GH-1068: foundation to generate and cache diagnostics in symbol machinery

This commit is contained in:
Martin Lippert
2023-07-13 10:12:21 +02:00
parent 0478a21e0c
commit 151ad12d25
2 changed files with 47 additions and 11 deletions

View File

@@ -55,6 +55,7 @@ import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyA
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.boot.java.reconcilers.CachedDiagnostics;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IClasspathUtil;
import org.springframework.ide.vscode.commons.java.IJavaProject;
@@ -83,6 +84,7 @@ public class SpringIndexerJava implements SpringIndexer {
private static final String SYMBOL_KEY = "symbols";
private static final String BEANS_KEY = "beans";
private static final String DIAGNOSTICS_KEY = "diagnostics";
private final SymbolHandler symbolHandler;
private final AnnotationHierarchyAwareLookup<SymbolProvider> symbolProviders;
@@ -132,19 +134,24 @@ public class SpringIndexerJava implements SpringIndexer {
public void removeProject(IJavaProject project) throws Exception {
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
IndexCacheKey diagnosticsCacheKey = getCacheKey(project, DIAGNOSTICS_KEY);
this.cache.remove(symbolsCacheKey);
this.cache.remove(beansCacheKey);
this.cache.remove(diagnosticsCacheKey);
}
@Override
public void updateFile(IJavaProject project, DocumentDescriptor updatedDoc, String content) throws Exception {
IndexCacheKey symbolCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
IndexCacheKey diagnosticsCacheKey = getCacheKey(project, DIAGNOSTICS_KEY);
if (updatedDoc != null && shouldProcessDocument(project, updatedDoc.getDocURI())) {
if (isCacheOutdated(symbolCacheKey, updatedDoc.getDocURI(), updatedDoc.getLastModified())
|| isCacheOutdated(beansCacheKey, updatedDoc.getDocURI(), updatedDoc.getLastModified())) {
|| isCacheOutdated(beansCacheKey, updatedDoc.getDocURI(), updatedDoc.getLastModified())
|| isCacheOutdated(diagnosticsCacheKey, updatedDoc.getDocURI(), updatedDoc.getLastModified())) {
this.symbolHandler.removeSymbols(project, updatedDoc.getDocURI());
scanFile(project, updatedDoc, content);
}
@@ -168,21 +175,27 @@ public class SpringIndexerJava implements SpringIndexer {
public void removeFiles(IJavaProject project, String[] docURIs) throws Exception {
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
IndexCacheKey diagnosticsCacheKey = getCacheKey(project, DIAGNOSTICS_KEY);
for (String docURI : docURIs) {
String file = new File(new URI(docURI)).getAbsolutePath();
this.cache.removeFile(symbolsCacheKey, file, CachedSymbol.class);
this.cache.removeFile(beansCacheKey, file, CachedSymbol.class);
this.cache.removeFile(beansCacheKey, file, CachedBean.class);
this.cache.removeFile(diagnosticsCacheKey, file, CachedDiagnostics.class);
}
}
private DocumentDescriptor[] filterDocuments(IJavaProject project, DocumentDescriptor[] updatedDocs) {
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
IndexCacheKey diagnosticsCacheKey = getCacheKey(project, DIAGNOSTICS_KEY);
return Arrays.stream(updatedDocs).filter(doc -> shouldProcessDocument(project, doc.getDocURI()))
.filter(doc -> isCacheOutdated(symbolsCacheKey, doc.getDocURI(), doc.getLastModified())
|| isCacheOutdated(beansCacheKey, doc.getDocURI(), doc.getLastModified())).toArray(DocumentDescriptor[]::new);
|| isCacheOutdated(beansCacheKey, doc.getDocURI(), doc.getLastModified())
|| isCacheOutdated(diagnosticsCacheKey, doc.getDocURI(), doc.getLastModified()))
.toArray(DocumentDescriptor[]::new);
}
private boolean shouldProcessDocument(IJavaProject project, String docURI) {
@@ -235,19 +248,22 @@ public class SpringIndexerJava implements SpringIndexer {
if (cu != null) {
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
List<CachedDiagnostics> generatedDiagnostics = new ArrayList<CachedDiagnostics>();
AtomicReference<TextDocument> docRef = new AtomicReference<>();
String file = UriUtil.toFileString(docURI);
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, file,
lastModified, docRef, content, generatedSymbols, generatedBeans, SCAN_PASS.ONE, new ArrayList<>());
lastModified, docRef, content, generatedSymbols, generatedBeans, generatedDiagnostics, SCAN_PASS.ONE, new ArrayList<>());
scanAST(context);
IndexCacheKey symbolCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
IndexCacheKey diagnosticsCacheKey = getCacheKey(project, DIAGNOSTICS_KEY);
this.cache.update(symbolCacheKey, file, lastModified, generatedSymbols, context.getDependencies(), CachedSymbol.class);
this.cache.update(beansCacheKey, file, lastModified, generatedBeans, context.getDependencies(), CachedBean.class);
this.cache.update(diagnosticsCacheKey, file, lastModified, generatedDiagnostics, context.getDependencies(), CachedDiagnostics.class);
// dependencyTracker.dump();
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
@@ -276,11 +292,12 @@ public class SpringIndexerJava implements SpringIndexer {
if (cu != null) {
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
List<CachedDiagnostics> generatedDiagnostics = new ArrayList<CachedDiagnostics>();
AtomicReference<TextDocument> docRef = new AtomicReference<>();
String file = UriUtil.toFileString(docURI);
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, file,
0, docRef, content, generatedSymbols, generatedBeans, SCAN_PASS.ONE, new ArrayList<>());
0, docRef, content, generatedSymbols, generatedBeans, generatedDiagnostics, SCAN_PASS.ONE, new ArrayList<>());
scanAST(context);
@@ -314,6 +331,7 @@ public class SpringIndexerJava implements SpringIndexer {
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
List<CachedDiagnostics> generatedDiagnostics = new ArrayList<CachedDiagnostics>();
Multimap<String, String> dependencies = MultimapBuilder.hashKeys().hashSetValues().build();
@@ -329,7 +347,7 @@ public class SpringIndexerJava implements SpringIndexer {
AtomicReference<TextDocument> docRef = new AtomicReference<>();
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, sourceFilePath,
lastModified, docRef, null, generatedSymbols, generatedBeans, SCAN_PASS.ONE, new ArrayList<>());
lastModified, docRef, null, generatedSymbols, generatedBeans, generatedDiagnostics, SCAN_PASS.ONE, new ArrayList<>());
scanAST(context);
@@ -348,9 +366,11 @@ public class SpringIndexerJava implements SpringIndexer {
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
IndexCacheKey diagnosticsCacheKey = getCacheKey(project, DIAGNOSTICS_KEY);
this.cache.update(symbolsCacheKey, javaFiles, lastModified, generatedSymbols, dependencies, CachedSymbol.class);
this.cache.update(beansCacheKey, javaFiles, lastModified, generatedBeans, dependencies, CachedBean.class);
this.cache.update(diagnosticsCacheKey, javaFiles, lastModified, generatedDiagnostics, dependencies, CachedDiagnostics.class);
return scannedTypes;
}
@@ -389,39 +409,46 @@ public class SpringIndexerJava implements SpringIndexer {
private void scanFiles(IJavaProject project, String[] javaFiles) throws Exception {
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
IndexCacheKey diagnosticsCacheKey = getCacheKey(project, DIAGNOSTICS_KEY);
Pair<CachedSymbol[], Multimap<String, String>> cachedSymbols = this.cache.retrieve(symbolsCacheKey, javaFiles, CachedSymbol.class);
Pair<CachedBean[], Multimap<String, String>> cachedBeans = this.cache.retrieve(beansCacheKey, javaFiles, CachedBean.class);
Pair<CachedDiagnostics[], Multimap<String, String>> cachedDiagnostics = this.cache.retrieve(diagnosticsCacheKey, javaFiles, CachedDiagnostics.class);
CachedSymbol[] symbols;
CachedBean[] beans;
CachedDiagnostics[] diagnostics;
if (cachedSymbols == null || cachedBeans == null) {
List<CachedSymbol> generatedSymbols = new ArrayList<CachedSymbol>();
List<CachedBean> generatedBeans = new ArrayList<CachedBean>();
List<CachedDiagnostics> generatedDiagnostics = new ArrayList<CachedDiagnostics>();
log.info("scan java files, AST parse, pass 1 for files: {}", javaFiles.length);
String[] pass2Files = scanFiles(project, javaFiles, generatedSymbols, generatedBeans, SCAN_PASS.ONE);
String[] pass2Files = scanFiles(project, javaFiles, generatedSymbols, generatedBeans, generatedDiagnostics, SCAN_PASS.ONE);
if (pass2Files.length > 0) {
log.info("scan java files, AST parse, pass 2 for files: {}", javaFiles.length);
scanFiles(project, pass2Files, generatedSymbols, generatedBeans, SCAN_PASS.TWO);
scanFiles(project, pass2Files, generatedSymbols, generatedBeans, generatedDiagnostics, SCAN_PASS.TWO);
}
log.info("scan java files done, number of symbols created: " + generatedSymbols.size());
this.cache.store(symbolsCacheKey, javaFiles, generatedSymbols, dependencyTracker.getAllDependencies(), CachedSymbol.class);
this.cache.store(beansCacheKey, javaFiles, generatedBeans, dependencyTracker.getAllDependencies(), CachedBean.class);
this.cache.store(diagnosticsCacheKey, javaFiles, generatedDiagnostics, dependencyTracker.getAllDependencies(), CachedDiagnostics.class);
// dependencyTracker.dump();
symbols = (CachedSymbol[]) generatedSymbols.toArray(new CachedSymbol[generatedSymbols.size()]);
beans = (CachedBean[]) generatedBeans.toArray(new CachedBean[generatedBeans.size()]);
diagnostics = (CachedDiagnostics[]) generatedDiagnostics.toArray(new CachedDiagnostics[generatedDiagnostics.size()]);
}
else {
symbols = cachedSymbols.getLeft();
beans = cachedBeans.getLeft();
diagnostics = cachedDiagnostics.getLeft();
log.info("scan java files used cached data: {} - no. of cached symbols retrieved: {}", project.getElementName(), symbols.length);
this.dependencyTracker.restore(cachedSymbols.getRight());
@@ -435,8 +462,9 @@ public class SpringIndexerJava implements SpringIndexer {
}
}
private String[] scanFiles(IJavaProject project, String[] javaFiles, List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans, SCAN_PASS pass)
throws Exception {
private String[] scanFiles(IJavaProject project, String[] javaFiles, List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans,
List<CachedDiagnostics> generatedDiagnostics, SCAN_PASS pass) throws Exception {
ASTParser parser = createParser(project, SCAN_PASS.ONE.equals(pass));
List<String> nextPassFiles = new ArrayList<>();
@@ -449,7 +477,7 @@ public class SpringIndexerJava implements SpringIndexer {
AtomicReference<TextDocument> docRef = new AtomicReference<>();
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, sourceFilePath,
lastModified, docRef, null, generatedSymbols, generatedBeans, pass, nextPassFiles);
lastModified, docRef, null, generatedSymbols, generatedBeans, generatedDiagnostics, pass, nextPassFiles);
scanAST(context);
}

View File

@@ -18,6 +18,7 @@ import java.util.concurrent.atomic.AtomicReference;
import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.springframework.ide.vscode.boot.java.beans.CachedBean;
import org.springframework.ide.vscode.boot.java.reconcilers.CachedDiagnostics;
import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJava.SCAN_PASS;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -36,6 +37,7 @@ public class SpringIndexerJavaContext {
private final String content;
private final List<CachedSymbol> generatedSymbols;
private final List<CachedBean> beans;
private final List<CachedDiagnostics> diagnostics;
private final SCAN_PASS pass;
private final List<String> nextPassFiles;
@@ -52,6 +54,7 @@ public class SpringIndexerJavaContext {
String content,
List<CachedSymbol> generatedSymbols,
List<CachedBean> beans,
List<CachedDiagnostics> diagnostics,
SCAN_PASS pass,
List<String> nextPassFiles
) {
@@ -65,6 +68,7 @@ public class SpringIndexerJavaContext {
this.content = content;
this.generatedSymbols = generatedSymbols;
this.beans = beans;
this.diagnostics = diagnostics;
this.pass = pass;
this.nextPassFiles = nextPassFiles;
}
@@ -104,6 +108,10 @@ public class SpringIndexerJavaContext {
public List<CachedBean> getBeans() {
return beans;
}
public List<CachedDiagnostics> getDiagnostics() {
return diagnostics;
}
public SCAN_PASS getPass() {
return pass;