GH-1068: initial version of running a single validation as part of the indexing machinery
This commit is contained in:
@@ -30,6 +30,8 @@ import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -137,7 +139,8 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd
|
||||
private static final int FORCED_EXIT_DELAY_IN_SECONDS = 3;
|
||||
|
||||
public final String EXTENSION_ID;
|
||||
private final String CODE_ACTION_COMMAND_ID;
|
||||
public final String CODE_ACTION_COMMAND_ID;
|
||||
|
||||
public final LazyCompletionResolver completionResolver = createCompletionResolver();
|
||||
|
||||
private SimpleTextDocumentService tds;
|
||||
@@ -706,7 +709,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd
|
||||
testListener.reconcileStarted(docId.getUri(), doc.getVersion());
|
||||
}
|
||||
|
||||
IProblemCollector problems = createProblemCollector(doc);
|
||||
IProblemCollector problems = createProblemCollector(new AtomicReference<TextDocument>(doc), null);
|
||||
|
||||
engine.reconcile(doc, problems);
|
||||
})
|
||||
@@ -749,9 +752,10 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd
|
||||
}
|
||||
}
|
||||
|
||||
public IProblemCollector createProblemCollector(TextDocument doc) {
|
||||
SimpleTextDocumentService documents = getTextDocumentService();
|
||||
TextDocumentIdentifier docId = doc.getId();
|
||||
public IProblemCollector createProblemCollector(AtomicReference<TextDocument> docRef, BiConsumer<String, Diagnostic> diagnosticsCollector) {
|
||||
|
||||
SimpleTextDocumentService documentsService = getTextDocumentService();
|
||||
|
||||
return new IProblemCollector() {
|
||||
|
||||
private LinkedHashSet<Diagnostic> diagnostics = new LinkedHashSet<>();
|
||||
@@ -759,8 +763,8 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd
|
||||
|
||||
@Override
|
||||
public void endCollecting() {
|
||||
documents.setQuickfixes(docId, quickfixes);
|
||||
documents.publishDiagnostics(docId, diagnostics);
|
||||
documentsService.setQuickfixes(docRef.get().getId(), quickfixes);
|
||||
documentsService.publishDiagnostics(docRef.get().getId(), diagnostics);
|
||||
log.debug("Reconcile done sent {} diagnostics", diagnostics.size());
|
||||
}
|
||||
|
||||
@@ -772,8 +776,8 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd
|
||||
@Override
|
||||
public void checkPointCollecting() {
|
||||
// publish what has been collected so far
|
||||
documents.setQuickfixes(docId, quickfixes);
|
||||
documents.publishDiagnostics(docId, diagnostics);
|
||||
documentsService.setQuickfixes(docRef.get().getId(), quickfixes);
|
||||
documentsService.publishDiagnostics(docRef.get().getId(), diagnostics);
|
||||
log.debug("Reconcile checkpoint sent {} diagnostics", diagnostics.size());
|
||||
}
|
||||
|
||||
@@ -787,7 +791,7 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd
|
||||
Diagnostic d = new Diagnostic();
|
||||
d.setCode(problem.getCode());
|
||||
d.setMessage(problem.getMessage());
|
||||
Range rng = doc.toRange(problem.getOffset(), problem.getLength());
|
||||
Range rng = docRef.get().toRange(problem.getOffset(), problem.getLength());
|
||||
d.setRange(rng);
|
||||
d.setSeverity(severity);
|
||||
d.setSource(getServer().EXTENSION_ID);
|
||||
@@ -810,9 +814,14 @@ public final class SimpleLanguageServer implements Sts4LanguageServer, SpringInd
|
||||
}).collect(Collectors.toList()));
|
||||
}
|
||||
diagnostics.add(d);
|
||||
|
||||
if (diagnosticsCollector != null) {
|
||||
diagnosticsCollector.accept(docRef.get().getId().getUri(), d);
|
||||
}
|
||||
|
||||
}
|
||||
} catch (BadLocationException e) {
|
||||
log.warn("Invalid reconcile problem ignored: " + doc.getUri() + " - problem position: " + problem.getOffset() + "/" + problem.getLength(), e);
|
||||
log.warn("Invalid reconcile problem ignored: " + docRef.get().getId().getUri() + " - problem position: " + problem.getOffset() + "/" + problem.getLength(), e);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -29,11 +29,15 @@ import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
@@ -50,6 +54,8 @@ import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyA
|
||||
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.AnnotationReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.reconcilers.BeanMethodNotPublicReconciler;
|
||||
import org.springframework.ide.vscode.boot.java.utils.DocumentDescriptor;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringFactoriesIndexer;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringIndexer;
|
||||
@@ -65,6 +71,7 @@ import org.springframework.ide.vscode.commons.languageserver.java.FutureProjectF
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver.Listener;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.ListenerList;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
|
||||
@@ -156,7 +163,9 @@ public class SpringSymbolIndex implements InitializingBean, SpringIndex {
|
||||
|
||||
SymbolHandler handler = new SymbolHandler() {
|
||||
@Override
|
||||
public void addSymbols(IJavaProject project, String docURI, EnhancedSymbolInformation[] enhancedSymbols, Bean[] beanDefinitions) {
|
||||
public void addSymbols(IJavaProject project, String docURI, EnhancedSymbolInformation[] enhancedSymbols, Bean[] beanDefinitions,
|
||||
List<Diagnostic> diagnostics) {
|
||||
|
||||
if (enhancedSymbols != null) {
|
||||
SpringSymbolIndex.this.addSymbolsByDoc(project, docURI, enhancedSymbols);
|
||||
}
|
||||
@@ -164,11 +173,16 @@ public class SpringSymbolIndex implements InitializingBean, SpringIndex {
|
||||
if (beanDefinitions != null) {
|
||||
springIndex.updateBeans(project.getElementName(), docURI, beanDefinitions);
|
||||
}
|
||||
|
||||
if (diagnostics != null) {
|
||||
server.getTextDocumentService().publishDiagnostics(new TextDocumentIdentifier(docURI), diagnostics);
|
||||
// TODO: need to use real TextDocumentIdentifier because of the document version
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addSymbols(IJavaProject project, EnhancedSymbolInformation[] enhancedSymbols,
|
||||
Bean[] beanDefinitions) {
|
||||
Bean[] beanDefinitions, Map<String, List<Diagnostic>> diagnosticsPerDoc) {
|
||||
|
||||
if (enhancedSymbols != null) {
|
||||
|
||||
@@ -208,12 +222,21 @@ public class SpringSymbolIndex implements InitializingBean, SpringIndex {
|
||||
}
|
||||
}
|
||||
|
||||
if (diagnosticsPerDoc != null) {
|
||||
for (String docURI : diagnosticsPerDoc.keySet()) {
|
||||
server.getTextDocumentService().publishDiagnostics(new TextDocumentIdentifier(docURI), diagnosticsPerDoc.get(docURI));
|
||||
// TODO: need to use real TextDocumentIdentifier because of the document version
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeSymbols(IJavaProject project, String docURI) {
|
||||
SpringSymbolIndex.this.removeSymbolsByDoc(project, docURI);
|
||||
springIndex.removeBeans(project.getElementName(), docURI);
|
||||
|
||||
// TODO remove diagnostics ?!? maybe, maybe not
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
@@ -221,7 +244,13 @@ public class SpringSymbolIndex implements InitializingBean, SpringIndex {
|
||||
Map<String, SpringIndexerXMLNamespaceHandler> namespaceHandler = new HashMap<>();
|
||||
namespaceHandler.put("http://www.springframework.org/schema/beans", new SpringIndexerXMLNamespaceHandlerBeans());
|
||||
springIndexerXML = new SpringIndexerXML(handler, namespaceHandler, this.cache, projectFinder());
|
||||
springIndexerJava = new SpringIndexerJava(handler, specificProviders, this.cache, projectFinder(), server.getProgressService());
|
||||
|
||||
List<AnnotationReconciler> reconcilers = new ArrayList<>();
|
||||
reconcilers.add(new BeanMethodNotPublicReconciler());
|
||||
|
||||
BiFunction<AtomicReference<TextDocument>, BiConsumer<String, Diagnostic>, IProblemCollector> problemCollectorFactory = (docRef, aggregator) -> server.createProblemCollector(docRef, aggregator);
|
||||
springIndexerJava = new SpringIndexerJava(handler, specificProviders, this.cache, projectFinder(), server.getProgressService(), reconcilers, problemCollectorFactory);
|
||||
|
||||
factoriesIndexer = new SpringFactoriesIndexer(handler, cache);
|
||||
|
||||
this.indexers = new SpringIndexer[] {springIndexerJava, factoriesIndexer};
|
||||
|
||||
@@ -18,6 +18,7 @@ import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -133,7 +134,7 @@ public class BootJavaReconcileEngine implements IReconcileEngine, IJavaProjectRe
|
||||
.map(docId -> new LazyTextDocument(docId.getUri(), LanguageId.JAVA)).collect(Collectors.toList());
|
||||
|
||||
Map<IDocument, IProblemCollector> problemCollectors = docs.stream()
|
||||
.collect(Collectors.toMap(d -> d, d -> server.createProblemCollector(d)));
|
||||
.collect(Collectors.toMap(doc -> doc, doc -> server.createProblemCollector(new AtomicReference<>(doc), null)));
|
||||
|
||||
problemCollectors.values().forEach(c -> c.beginCollecting());
|
||||
|
||||
|
||||
@@ -0,0 +1,82 @@
|
||||
/*******************************************************************************
|
||||
* Copyright (c) 2022, 2023 VMware, Inc.
|
||||
* All rights reserved. This program and the accompanying materials
|
||||
* are made available under the terms of the Eclipse Public License v1.0
|
||||
* which accompanies this distribution, and is available at
|
||||
* https://www.eclipse.org/legal/epl-v10.html
|
||||
*
|
||||
* Contributors:
|
||||
* VMware, Inc. - initial API and implementation
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.reconcilers;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.List;
|
||||
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.Modifier;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.Boot2JavaProblemType;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
|
||||
import org.springframework.ide.vscode.commons.java.Version;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblemImpl;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
|
||||
public class BeanMethodNotPublicReconciler implements AnnotationReconciler {
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(BeanMethodNotPublicReconciler.class);
|
||||
|
||||
@Override
|
||||
public void visit(IJavaProject project, IDocument doc, Annotation node, ITypeBinding typeBinding,
|
||||
IProblemCollector problemCollector) {
|
||||
|
||||
if (Annotations.BEAN.equals(typeBinding.getQualifiedName()) && node.getParent() instanceof MethodDeclaration) {
|
||||
MethodDeclaration m = (MethodDeclaration) node.getParent();
|
||||
Version version = SpringProjectUtil.getDependencyVersion(project, SpringProjectUtil.SPRING_BOOT);
|
||||
|
||||
if (version.getMajor() >= 2) {
|
||||
IMethodBinding methodBinding = m.resolveBinding();
|
||||
if (isNotOverridingPublicMethod(methodBinding)) {
|
||||
|
||||
ReconcileProblemImpl problem = ((List<?>)m.modifiers()).stream()
|
||||
.filter(Modifier.class::isInstance)
|
||||
.map(Modifier.class::cast)
|
||||
.filter(modifier -> modifier.isPublic())
|
||||
.findFirst()
|
||||
.map(modifier -> new ReconcileProblemImpl(
|
||||
Boot2JavaProblemType.JAVA_PUBLIC_BEAN_METHOD, "super special DIAGNOSTICS with public @Bean method",
|
||||
modifier.getStartPosition(), modifier.getLength()))
|
||||
.orElse(new ReconcileProblemImpl(
|
||||
Boot2JavaProblemType.JAVA_PUBLIC_BEAN_METHOD, "super special DIAGNOSTICS with public @Bean method",
|
||||
m.getName().getStartPosition(), m.getName().getLength()));
|
||||
|
||||
problemCollector.accept(problem);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static final boolean isOverriding(IMethodBinding binding) {
|
||||
try {
|
||||
Field f = binding.getClass().getDeclaredField("binding");
|
||||
f.setAccessible(true);
|
||||
org.eclipse.jdt.internal.compiler.lookup.MethodBinding value = (org.eclipse.jdt.internal.compiler.lookup.MethodBinding) f.get(binding);
|
||||
return value.isOverriding();
|
||||
} catch (Exception e) {
|
||||
log.error("", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static final boolean isNotOverridingPublicMethod(IMethodBinding methodBinding) {
|
||||
return !isOverriding(methodBinding) && (methodBinding.getModifiers() & Modifier.PUBLIC) != 0;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -10,12 +10,20 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.reconcilers;
|
||||
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.springframework.ide.vscode.boot.index.cache.AbstractIndexCacheable;
|
||||
|
||||
public class CachedDiagnostics extends AbstractIndexCacheable {
|
||||
|
||||
public CachedDiagnostics(String docURI) {
|
||||
private final Diagnostic diagnostic;
|
||||
|
||||
public CachedDiagnostics(String docURI, Diagnostic diagnostic) {
|
||||
super(docURI);
|
||||
this.diagnostic= diagnostic;
|
||||
}
|
||||
|
||||
public Diagnostic getDiagnostic() {
|
||||
return this.diagnostic;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -187,7 +187,7 @@ public class SpringFactoriesIndexer implements SpringIndexer {
|
||||
|
||||
if (symbols != null) {
|
||||
EnhancedSymbolInformation[] enhancedSymbols = Arrays.stream(symbols).map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
|
||||
symbolHandler.addSymbols(project, enhancedSymbols, null);
|
||||
symbolHandler.addSymbols(project, enhancedSymbols, null, null);
|
||||
}
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
@@ -257,7 +257,7 @@ public class SpringFactoriesIndexer implements SpringIndexer {
|
||||
this.cache.update(cacheKey, file, updatedDoc.getLastModified(), generatedSymbols, null, CachedSymbol.class);
|
||||
|
||||
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
|
||||
symbolHandler.addSymbols(project, docURI, symbols, null);
|
||||
symbolHandler.addSymbols(project, docURI, symbols, null, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -26,6 +26,8 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -45,6 +47,7 @@ import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.eclipse.lsp4j.WorkspaceSymbol;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -55,6 +58,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.AnnotationReconciler;
|
||||
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;
|
||||
@@ -62,6 +66,8 @@ import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.languageserver.PercentageProgressTask;
|
||||
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.languageserver.reconcile.ReconcileProblem;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
|
||||
import org.springframework.ide.vscode.commons.util.UriUtil;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
@@ -89,9 +95,9 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
private static final String BEANS_KEY = "beans";
|
||||
private static final String DIAGNOSTICS_KEY = "diagnostics";
|
||||
|
||||
|
||||
private final SymbolHandler symbolHandler;
|
||||
private final AnnotationHierarchyAwareLookup<SymbolProvider> symbolProviders;
|
||||
private final List<AnnotationReconciler> reconcilers;
|
||||
private final IndexCache cache;
|
||||
private final JavaProjectFinder projectFinder;
|
||||
private final ProgressService progressService;
|
||||
@@ -100,14 +106,19 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
private FileScanListener fileScanListener = null; //used by test code only
|
||||
|
||||
private final SpringIndexerJavaDependencyTracker dependencyTracker = new SpringIndexerJavaDependencyTracker();
|
||||
private final BiFunction<AtomicReference<TextDocument>, BiConsumer<String, Diagnostic>, IProblemCollector> problemCollectorCreator;
|
||||
|
||||
public SpringIndexerJava(SymbolHandler symbolHandler, AnnotationHierarchyAwareLookup<SymbolProvider> symbolProviders, IndexCache cache,
|
||||
JavaProjectFinder projectFimder, ProgressService progressService) {
|
||||
JavaProjectFinder projectFimder, ProgressService progressService, List<AnnotationReconciler> reconcilers,
|
||||
BiFunction<AtomicReference<TextDocument>, BiConsumer<String, Diagnostic>, IProblemCollector> problemCollectorCreator) {
|
||||
this.symbolHandler = symbolHandler;
|
||||
this.symbolProviders = symbolProviders;
|
||||
this.reconcilers = reconcilers;
|
||||
this.cache = cache;
|
||||
this.projectFinder = projectFimder;
|
||||
this.progressService = progressService;
|
||||
|
||||
this.problemCollectorCreator = problemCollectorCreator;
|
||||
}
|
||||
|
||||
public SpringIndexerJavaDependencyTracker getDependencyTracker() {
|
||||
@@ -259,8 +270,18 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
|
||||
AtomicReference<TextDocument> docRef = new AtomicReference<>();
|
||||
String file = UriUtil.toFileString(docURI);
|
||||
|
||||
BiConsumer<String, Diagnostic> diagnosticsAggregator = new BiConsumer<>() {
|
||||
@Override
|
||||
public void accept(String docURI, Diagnostic diagnostic) {
|
||||
generatedDiagnostics.add(new CachedDiagnostics(docURI, diagnostic));
|
||||
}
|
||||
};
|
||||
|
||||
IProblemCollector problemCollector = problemCollectorCreator.apply(docRef, diagnosticsAggregator);
|
||||
|
||||
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, file,
|
||||
lastModified, docRef, content, generatedSymbols, generatedBeans, generatedDiagnostics, SCAN_PASS.ONE, new ArrayList<>());
|
||||
lastModified, docRef, content, generatedSymbols, generatedBeans, problemCollector, SCAN_PASS.ONE, new ArrayList<>());
|
||||
|
||||
scanAST(context);
|
||||
|
||||
@@ -275,8 +296,9 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
|
||||
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
|
||||
Bean[] beans = generatedBeans.stream().filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
|
||||
List<Diagnostic> diagnostics = generatedDiagnostics.stream().filter(cachedDiagnostics -> cachedDiagnostics.getDiagnostic() != null).map(cachedDiagnostic -> cachedDiagnostic.getDiagnostic()).collect(Collectors.toList());
|
||||
|
||||
symbolHandler.addSymbols(project, docURI, symbols, beans);
|
||||
symbolHandler.addSymbols(project, docURI, symbols, beans, diagnostics);
|
||||
|
||||
Set<String> scannedFiles = new HashSet<>();
|
||||
scannedFiles.add(file);
|
||||
@@ -299,22 +321,33 @@ 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>();
|
||||
|
||||
IProblemCollector voidProblemCollector = new IProblemCollector() {
|
||||
@Override
|
||||
public void endCollecting() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void beginCollecting() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void accept(ReconcileProblem problem) {
|
||||
}
|
||||
};
|
||||
|
||||
AtomicReference<TextDocument> docRef = new AtomicReference<>();
|
||||
String file = UriUtil.toFileString(docURI);
|
||||
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, file,
|
||||
0, docRef, content, generatedSymbols, generatedBeans, generatedDiagnostics, SCAN_PASS.ONE, new ArrayList<>());
|
||||
0, docRef, content, generatedSymbols, generatedBeans, voidProblemCollector, SCAN_PASS.ONE, new ArrayList<>());
|
||||
|
||||
scanAST(context);
|
||||
|
||||
return generatedSymbols.stream().map(s -> s.getEnhancedSymbol()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
|
||||
}
|
||||
|
||||
private Set<String> scanFilesInternally(IJavaProject project, DocumentDescriptor[] docs) throws Exception {
|
||||
@@ -341,6 +374,13 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
List<CachedDiagnostics> generatedDiagnostics = new ArrayList<CachedDiagnostics>();
|
||||
|
||||
Multimap<String, String> dependencies = MultimapBuilder.hashKeys().hashSetValues().build();
|
||||
|
||||
BiConsumer<String, Diagnostic> diagnosticsAggregator = new BiConsumer<>() {
|
||||
@Override
|
||||
public void accept(String docURI, Diagnostic diagnostic) {
|
||||
generatedDiagnostics.add(new CachedDiagnostics(docURI, diagnostic));
|
||||
}
|
||||
};
|
||||
|
||||
FileASTRequestor requestor = new FileASTRequestor() {
|
||||
@Override
|
||||
@@ -353,8 +393,10 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
|
||||
AtomicReference<TextDocument> docRef = new AtomicReference<>();
|
||||
|
||||
IProblemCollector problemCollector = problemCollectorCreator.apply(docRef, diagnosticsAggregator);
|
||||
|
||||
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, sourceFilePath,
|
||||
lastModified, docRef, null, generatedSymbols, generatedBeans, generatedDiagnostics, SCAN_PASS.ONE, new ArrayList<>());
|
||||
lastModified, docRef, null, generatedSymbols, generatedBeans, problemCollector, SCAN_PASS.ONE, new ArrayList<>());
|
||||
|
||||
scanAST(context);
|
||||
|
||||
@@ -369,7 +411,8 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
|
||||
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
|
||||
Bean[] beans = generatedBeans.stream().filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
|
||||
symbolHandler.addSymbols(project, symbols, beans);
|
||||
Map<String, List<Diagnostic>> diagnosticsByDoc = generatedDiagnostics.stream().filter(cachedDiagnostic -> cachedDiagnostic.getDiagnostic() != null).collect(Collectors.groupingBy(CachedDiagnostics::getDocURI, Collectors.mapping(CachedDiagnostics::getDiagnostic, Collectors.toList())));
|
||||
symbolHandler.addSymbols(project, symbols, beans, diagnosticsByDoc);
|
||||
|
||||
IndexCacheKey symbolsCacheKey = getCacheKey(project, SYMBOL_KEY);
|
||||
IndexCacheKey beansCacheKey = getCacheKey(project, BEANS_KEY);
|
||||
@@ -433,12 +476,19 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
|
||||
log.info("scan java files, AST parse, pass 1 for files: {}", javaFiles.length);
|
||||
|
||||
String[] pass2Files = scanFiles(project, javaFiles, generatedSymbols, generatedBeans, generatedDiagnostics, SCAN_PASS.ONE);
|
||||
BiConsumer<String, Diagnostic> diagnosticsAggregator = new BiConsumer<>() {
|
||||
@Override
|
||||
public void accept(String docURI, Diagnostic diagnostic) {
|
||||
generatedDiagnostics.add(new CachedDiagnostics(docURI, diagnostic));
|
||||
}
|
||||
};
|
||||
|
||||
String[] pass2Files = scanFiles(project, javaFiles, generatedSymbols, generatedBeans, diagnosticsAggregator, 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, generatedDiagnostics, SCAN_PASS.TWO);
|
||||
scanFiles(project, pass2Files, generatedSymbols, generatedBeans, diagnosticsAggregator, SCAN_PASS.TWO);
|
||||
}
|
||||
|
||||
log.info("scan java files done, number of symbols created: " + generatedSymbols.size());
|
||||
@@ -465,12 +515,13 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
if (symbols != null && beans != null) {
|
||||
EnhancedSymbolInformation[] enhancedSymbols = Arrays.stream(symbols).map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
|
||||
Bean[] allBeans = Arrays.stream(beans).filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
|
||||
symbolHandler.addSymbols(project, enhancedSymbols, allBeans);
|
||||
Map<String, List<Diagnostic>> diagnosticsByDoc = Arrays.stream(diagnostics).filter(cachedDiagnostic -> cachedDiagnostic.getDiagnostic() != null).collect(Collectors.groupingBy(CachedDiagnostics::getDocURI, Collectors.mapping(CachedDiagnostics::getDiagnostic, Collectors.toList())));
|
||||
symbolHandler.addSymbols(project, enhancedSymbols, allBeans, diagnosticsByDoc);
|
||||
}
|
||||
}
|
||||
|
||||
private String[] scanFiles(IJavaProject project, String[] javaFiles, List<CachedSymbol> generatedSymbols, List<CachedBean> generatedBeans,
|
||||
List<CachedDiagnostics> generatedDiagnostics, SCAN_PASS pass) throws Exception {
|
||||
BiConsumer<String, Diagnostic> diagnosticsAggregator, SCAN_PASS pass) throws Exception {
|
||||
|
||||
PercentageProgressTask progressTask = this.progressService.createPercentageProgressTask(INDEX_FILES_TASK_ID + project.getElementName(),
|
||||
javaFiles.length, "Spring Tools: Indexing Java Sources for '" + project.getElementName() + "'");
|
||||
@@ -480,6 +531,7 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
List<String> nextPassFiles = new ArrayList<>();
|
||||
|
||||
FileASTRequestor requestor = new FileASTRequestor() {
|
||||
|
||||
@Override
|
||||
public void acceptAST(String sourceFilePath, CompilationUnit cu) {
|
||||
File file = new File(sourceFilePath);
|
||||
@@ -487,8 +539,10 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
long lastModified = file.lastModified();
|
||||
AtomicReference<TextDocument> docRef = new AtomicReference<>();
|
||||
|
||||
IProblemCollector problemCollector = problemCollectorCreator.apply(docRef, diagnosticsAggregator);
|
||||
|
||||
SpringIndexerJavaContext context = new SpringIndexerJavaContext(project, cu, docURI, sourceFilePath,
|
||||
lastModified, docRef, null, generatedSymbols, generatedBeans, generatedDiagnostics, pass, nextPassFiles);
|
||||
lastModified, docRef, null, generatedSymbols, generatedBeans, problemCollector, pass, nextPassFiles);
|
||||
|
||||
scanAST(context);
|
||||
progressTask.increment();
|
||||
@@ -594,6 +648,8 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
ITypeBinding typeBinding = node.resolveTypeBinding();
|
||||
|
||||
if (typeBinding != null) {
|
||||
|
||||
// symbol and index scanning
|
||||
Collection<SymbolProvider> providers = symbolProviders.get(typeBinding);
|
||||
Collection<ITypeBinding> metaAnnotations = AnnotationHierarchies.getMetaAnnotations(typeBinding, symbolProviders::containsKey);
|
||||
|
||||
@@ -609,6 +665,12 @@ public class SpringIndexerJava implements SpringIndexer {
|
||||
context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol));
|
||||
}
|
||||
}
|
||||
|
||||
// reconciling
|
||||
for (AnnotationReconciler reconciler : this.reconcilers) {
|
||||
reconciler.visit(context.getProject(), context.getDocRef().get(), node, typeBinding, context.getProblemCollector());
|
||||
}
|
||||
|
||||
}
|
||||
else {
|
||||
log.debug("type binding not around: " + context.getDocURI() + " - " + node.toString());
|
||||
|
||||
@@ -18,9 +18,9 @@ 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.languageserver.reconcile.IProblemCollector;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
/**
|
||||
@@ -37,13 +37,14 @@ public class SpringIndexerJavaContext {
|
||||
private final String content;
|
||||
private final List<CachedSymbol> generatedSymbols;
|
||||
private final List<CachedBean> beans;
|
||||
private final List<CachedDiagnostics> diagnostics;
|
||||
private final IProblemCollector getProblemCollector;
|
||||
private final SCAN_PASS pass;
|
||||
private final List<String> nextPassFiles;
|
||||
|
||||
private final Set<String> dependencies = new HashSet<>();
|
||||
private final Set<String> scannedTypes = new HashSet<>();
|
||||
|
||||
|
||||
public SpringIndexerJavaContext(
|
||||
IJavaProject project,
|
||||
CompilationUnit cu,
|
||||
@@ -54,7 +55,7 @@ public class SpringIndexerJavaContext {
|
||||
String content,
|
||||
List<CachedSymbol> generatedSymbols,
|
||||
List<CachedBean> beans,
|
||||
List<CachedDiagnostics> diagnostics,
|
||||
IProblemCollector problemCollector,
|
||||
SCAN_PASS pass,
|
||||
List<String> nextPassFiles
|
||||
) {
|
||||
@@ -67,8 +68,8 @@ public class SpringIndexerJavaContext {
|
||||
this.docRef = docRef;
|
||||
this.content = content;
|
||||
this.generatedSymbols = generatedSymbols;
|
||||
this.getProblemCollector = problemCollector;
|
||||
this.beans = beans;
|
||||
this.diagnostics = diagnostics;
|
||||
this.pass = pass;
|
||||
this.nextPassFiles = nextPassFiles;
|
||||
}
|
||||
@@ -109,10 +110,6 @@ public class SpringIndexerJavaContext {
|
||||
return beans;
|
||||
}
|
||||
|
||||
public List<CachedDiagnostics> getDiagnostics() {
|
||||
return diagnostics;
|
||||
}
|
||||
|
||||
public SCAN_PASS getPass() {
|
||||
return pass;
|
||||
}
|
||||
@@ -146,4 +143,9 @@ public class SpringIndexerJavaContext {
|
||||
dependencies.remove(type);
|
||||
}
|
||||
}
|
||||
|
||||
public IProblemCollector getProblemCollector() {
|
||||
return this.getProblemCollector;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ public class SpringIndexerXML implements SpringIndexer {
|
||||
if (symbols != null && beans != null) {
|
||||
EnhancedSymbolInformation[] enhancedSymbols = Arrays.stream(symbols).map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
|
||||
Bean[] allBeans = Arrays.stream(beans).filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
|
||||
symbolHandler.addSymbols(project, enhancedSymbols, allBeans);
|
||||
symbolHandler.addSymbols(project, enhancedSymbols, allBeans, null);
|
||||
}
|
||||
|
||||
long endTime = System.currentTimeMillis();
|
||||
@@ -175,7 +175,7 @@ public class SpringIndexerXML implements SpringIndexer {
|
||||
|
||||
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
|
||||
Bean[] beans = generatedBeans.stream().filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
|
||||
symbolHandler.addSymbols(project, docURI, symbols, beans);
|
||||
symbolHandler.addSymbols(project, docURI, symbols, beans, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -202,7 +202,7 @@ public class SpringIndexerXML implements SpringIndexer {
|
||||
|
||||
EnhancedSymbolInformation[] symbols = generatedSymbols.stream().map(cachedSymbol -> cachedSymbol.getEnhancedSymbol()).toArray(EnhancedSymbolInformation[]::new);
|
||||
Bean[] beans = generatedBeans.stream().filter(cachedBean -> cachedBean.getBean() != null).map(cachedBean -> cachedBean.getBean()).toArray(Bean[]::new);
|
||||
symbolHandler.addSymbols(project, docURI, symbols, beans);
|
||||
symbolHandler.addSymbols(project, docURI, symbols, beans, null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.eclipse.lsp4j.Diagnostic;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
|
||||
@@ -19,8 +23,8 @@ import org.springframework.ide.vscode.commons.protocol.spring.Bean;
|
||||
*/
|
||||
public interface SymbolHandler {
|
||||
|
||||
void addSymbols(IJavaProject project, String docURI, EnhancedSymbolInformation[] enhancedSymbols, Bean[] beanDefinitions);
|
||||
void addSymbols(IJavaProject project, EnhancedSymbolInformation[] enhancedSymbols, Bean[] beanDefinitions);
|
||||
void addSymbols(IJavaProject project, String docURI, EnhancedSymbolInformation[] enhancedSymbols, Bean[] beanDefinitions, List<Diagnostic> diagnostics);
|
||||
void addSymbols(IJavaProject project, EnhancedSymbolInformation[] enhancedSymbols, Bean[] beanDefinitions, Map<String, List<Diagnostic>> diagnosticsByDoc);
|
||||
|
||||
void removeSymbols(IJavaProject project, String docURI);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user