refactored spring indexer to use executor service and react to project events instead of scanning workspace roots every time
This commit is contained in:
@@ -73,6 +73,11 @@ public class GradleJavaProject extends AbstractJavaProject {
|
||||
boolean update() throws Exception {
|
||||
return classpath.update();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocationUri() {
|
||||
return projectDir.toURI().toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ public interface IJavaProject extends IJavaElement {
|
||||
final static String PROJECT_CACHE_FOLDER = ".sts4-cache";
|
||||
|
||||
IClasspath getClasspath();
|
||||
String getLocationUri();
|
||||
|
||||
@Override
|
||||
default String getElementName() {
|
||||
@@ -32,5 +33,6 @@ public interface IJavaProject extends IJavaElement {
|
||||
default boolean exists() {
|
||||
return getClasspath().exists();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -80,4 +80,9 @@ public class MavenJavaProject extends AbstractJavaProject {
|
||||
return "MavenJavaProject("+classpath.getName()+")";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocationUri() {
|
||||
return pom.getParentFile().toURI().toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -193,7 +193,7 @@ public class BootJavaLanguageServerComponents implements LanguageServerComponent
|
||||
}
|
||||
|
||||
private void initialize(InitializeParams params) {
|
||||
this.indexer.initialize(server.getWorkspaceRoots());
|
||||
// this.indexer.initialize(server.getWorkspaceRoots());
|
||||
}
|
||||
|
||||
private void initialized() {
|
||||
|
||||
@@ -19,22 +19,21 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.BlockingQueue;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.core.dom.AST;
|
||||
@@ -53,7 +52,6 @@ import org.eclipse.lsp4j.Location;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
import org.eclipse.lsp4j.SymbolKind;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.eclipse.lsp4j.WorkspaceFolder;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.ide.vscode.boot.BootLanguageServerParams;
|
||||
@@ -69,13 +67,14 @@ import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserve
|
||||
import org.springframework.ide.vscode.commons.languageserver.java.ProjectObserver.Listener;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleWorkspaceService;
|
||||
import org.springframework.ide.vscode.commons.util.ExceptionUtil;
|
||||
import org.springframework.ide.vscode.commons.util.Futures;
|
||||
import org.springframework.ide.vscode.commons.util.StringUtil;
|
||||
import org.springframework.ide.vscode.commons.util.UriUtil;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
@@ -92,34 +91,40 @@ public class SpringIndexer {
|
||||
private final ConcurrentMap<String, List<SymbolInformation>> symbolsByDoc;
|
||||
private final ConcurrentMap<String, List<SymbolAddOnInformation>> addonInformationByDoc;
|
||||
|
||||
private final Thread updateWorker;
|
||||
private final BlockingQueue<WorkerItem> updateQueue;
|
||||
private final ConcurrentMap<String, List<SymbolInformation>> symbolsByProject;
|
||||
private final ConcurrentMap<String, List<SymbolAddOnInformation>> addonInformationByProject;
|
||||
|
||||
private final ExecutorService updateQueue;
|
||||
|
||||
private static final Logger log = LoggerFactory.getLogger(SpringIndexer.class);
|
||||
|
||||
private final Listener projectListener = new Listener() {
|
||||
|
||||
@Override
|
||||
public void created(IJavaProject project) {
|
||||
log.debug("project created event: {}", project.getElementName());
|
||||
refresh();
|
||||
initializeProject(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void changed(IJavaProject project) {
|
||||
log.debug("project changed event: {}", project.getElementName());
|
||||
refresh();
|
||||
initializeProject(project);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void deleted(IJavaProject project) {
|
||||
log.debug("project deleted event: {}", project.getElementName());
|
||||
refresh();
|
||||
deleteProject(project);
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
private volatile InitializeItem lastInitializeItem;
|
||||
private SimpleWorkspaceService getWorkspaceService() {
|
||||
return server.getServer().getWorkspaceService();
|
||||
}
|
||||
|
||||
private ProjectObserver getProjectObserver() {
|
||||
return params.projectObserver;
|
||||
}
|
||||
|
||||
public SpringIndexer(SimpleLanguageServer server, BootLanguageServerParams params, AnnotationHierarchyAwareLookup<SymbolProvider> specificProviders) {
|
||||
log.debug("Creating {}", this);
|
||||
@@ -130,32 +135,15 @@ public class SpringIndexer {
|
||||
|
||||
this.symbols = Collections.synchronizedList(new ArrayList<>());
|
||||
this.symbolsByDoc = new ConcurrentHashMap<>();
|
||||
this.symbolsByProject = new ConcurrentHashMap<>();
|
||||
this.addonInformation = Collections.synchronizedList(new ArrayList<>());
|
||||
this.addonInformationByDoc = new ConcurrentHashMap<>();
|
||||
this.addonInformationByProject = new ConcurrentHashMap<>();
|
||||
|
||||
this.updateQueue = new LinkedBlockingQueue<>();
|
||||
this.updateWorker = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (true) {
|
||||
WorkerItem workerItem = updateQueue.take();
|
||||
log.debug("dequeued {}", workerItem);
|
||||
workerItem.run();
|
||||
}
|
||||
}
|
||||
catch (InterruptedException e) {
|
||||
// ignore
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}, "Spring Annotation Index Update Worker");
|
||||
server.onInitialized(updateWorker::start);
|
||||
this.updateQueue = Executors.newSingleThreadExecutor();
|
||||
|
||||
getWorkspaceService().onDidChangeWorkspaceFolders(evt -> {
|
||||
log.debug("workspace roots have changed event arrived - added: " + evt.getEvent().getAdded() + " - removed: " + evt.getEvent().getRemoved());
|
||||
refresh();
|
||||
});
|
||||
|
||||
if (getProjectObserver() != null) {
|
||||
@@ -163,10 +151,6 @@ public class SpringIndexer {
|
||||
}
|
||||
}
|
||||
|
||||
private ProjectObserver getProjectObserver() {
|
||||
return params.projectObserver;
|
||||
}
|
||||
|
||||
public void serverInitialized() {
|
||||
List<String> globPattern = Arrays.asList("**/*.java");
|
||||
getWorkspaceService().getFileObserver().onFileDeleted(globPattern, (file) -> {
|
||||
@@ -177,72 +161,11 @@ public class SpringIndexer {
|
||||
});
|
||||
}
|
||||
|
||||
private SimpleWorkspaceService getWorkspaceService() {
|
||||
return server.getServer().getWorkspaceService();
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> initialize(Collection<WorkspaceFolder> workspaceRoots) {
|
||||
InitializeItem toCancel = null;
|
||||
try {
|
||||
synchronized(this) {
|
||||
toCancel = lastInitializeItem;
|
||||
//Careful do not cancel until created and setup new item. Otherwise it creates a
|
||||
//race condition in the test harness which needs to be able to ensure initialization
|
||||
//is completed.
|
||||
lastInitializeItem = new InitializeItem(workspaceRoots.toArray(new WorkspaceFolder[workspaceRoots.size()]));
|
||||
updateQueue.put(lastInitializeItem);
|
||||
return lastInitializeItem.getFuture();
|
||||
}
|
||||
} catch (Throwable e) {
|
||||
log.error("", e);
|
||||
return Futures.error(e);
|
||||
} finally {
|
||||
try {
|
||||
if (toCancel!=null && !toCancel.getFuture().isDone()) {
|
||||
toCancel.getFuture().cancel(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
//ignore
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isInitializing() {
|
||||
return lastInitializeItem != null && !lastInitializeItem.getFuture().isDone();
|
||||
}
|
||||
|
||||
public void waitForInitializeTask() {
|
||||
InitializeItem lastInitializeItem = this.lastInitializeItem;
|
||||
while (lastInitializeItem != null) {
|
||||
if (!lastInitializeItem.getFuture().isDone()) {
|
||||
try {
|
||||
log.debug("Wating for {}", lastInitializeItem);
|
||||
lastInitializeItem.getFuture().get();
|
||||
} catch (Exception e) {
|
||||
log.debug("Waiting for {} aborted", lastInitializeItem);
|
||||
log.debug(ExceptionUtil.getMessage(e));
|
||||
}
|
||||
lastInitializeItem = this.lastInitializeItem;
|
||||
} else {
|
||||
log.debug("No need to wait for {}", lastInitializeItem);
|
||||
lastInitializeItem = this.lastInitializeItem==lastInitializeItem ? null : this.lastInitializeItem;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void refresh() {
|
||||
synchronized (this) {
|
||||
Collection<WorkspaceFolder> roots = server.getWorkspaceRoots();
|
||||
log.debug("refresh spring indexer for roots: {}", roots.toString());
|
||||
initialize(roots);
|
||||
}
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
try {
|
||||
synchronized(this) {
|
||||
if (updateWorker != null && updateWorker.isAlive()) {
|
||||
updateWorker.interrupt();
|
||||
if (updateQueue != null && !updateQueue.isShutdown()) {
|
||||
updateQueue.shutdownNow();
|
||||
}
|
||||
|
||||
if (getProjectObserver() != null) {
|
||||
@@ -254,17 +177,36 @@ public class SpringIndexer {
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> initializeProject(IJavaProject project) {
|
||||
try {
|
||||
InitializeProject initializeItem = new InitializeProject(project);
|
||||
return CompletableFuture.runAsync(initializeItem, this.updateQueue);
|
||||
} catch (Throwable e) {
|
||||
log.error("", e);
|
||||
return Futures.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> deleteProject(IJavaProject project) {
|
||||
try {
|
||||
DeleteProject initializeItem = new DeleteProject(project);
|
||||
return CompletableFuture.runAsync(initializeItem, this.updateQueue);
|
||||
} catch (Throwable e) {
|
||||
log.error("", e);
|
||||
return Futures.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> updateDocument(String docURI, String content) {
|
||||
synchronized(this) {
|
||||
if (docURI.endsWith(".java") && lastInitializeItem != null) {
|
||||
if (docURI.endsWith(".java")) {
|
||||
try {
|
||||
Optional<IJavaProject> maybeProject = projectFinder.find(new TextDocumentIdentifier(docURI));
|
||||
if (maybeProject.isPresent()) {
|
||||
String[] classpathEntries = getClasspathEntries(maybeProject.get());
|
||||
|
||||
UpdateItem updateItem = new UpdateItem(docURI, content, classpathEntries);
|
||||
updateQueue.put(updateItem);
|
||||
return updateItem.getFuture();
|
||||
|
||||
UpdateItem updateItem = new UpdateItem(maybeProject.get(), docURI, content, classpathEntries);
|
||||
return CompletableFuture.runAsync(updateItem, this.updateQueue);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -279,29 +221,32 @@ public class SpringIndexer {
|
||||
public CompletableFuture<Void> deleteDocument(String deletedDocURI) {
|
||||
synchronized(this) {
|
||||
try {
|
||||
DeleteItem deleteItem = new DeleteItem(deletedDocURI);
|
||||
updateQueue.put(deleteItem);
|
||||
return deleteItem.getFuture();
|
||||
Optional<IJavaProject> maybeProject = projectFinder.find(new TextDocumentIdentifier(deletedDocURI));
|
||||
if (maybeProject.isPresent()) {
|
||||
DeleteItem deleteItem = new DeleteItem(maybeProject.get(), deletedDocURI);
|
||||
return CompletableFuture.runAsync(deleteItem, this.updateQueue);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
log.error("", e);
|
||||
return Futures.error(e);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public CompletableFuture<Void> createDocument(String docURI) {
|
||||
synchronized(this) {
|
||||
if (docURI.endsWith(".java") && lastInitializeItem != null) {
|
||||
if (docURI.endsWith(".java")) {
|
||||
try {
|
||||
Optional<IJavaProject> maybeProject = projectFinder.find(new TextDocumentIdentifier(docURI));
|
||||
if (maybeProject.isPresent()) {
|
||||
String[] classpathEntries = getClasspathEntries(maybeProject.get());
|
||||
|
||||
String content = FileUtils.readFileToString(new File(new URI(docURI)));
|
||||
UpdateItem updateItem = new UpdateItem(docURI, content, classpathEntries);
|
||||
updateQueue.put(updateItem);
|
||||
return updateItem.getFuture();
|
||||
UpdateItem updateItem = new UpdateItem(maybeProject.get(), docURI, content, classpathEntries);
|
||||
return CompletableFuture.runAsync(updateItem, this.updateQueue);
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
@@ -314,8 +259,6 @@ public class SpringIndexer {
|
||||
}
|
||||
|
||||
public List<SymbolInformation> getAllSymbols(String query) {
|
||||
waitForInitializeTask();
|
||||
|
||||
if (query != null && query.length() > 0) {
|
||||
return searchMatchingSymbols(this.symbols, query);
|
||||
} else {
|
||||
@@ -324,13 +267,10 @@ public class SpringIndexer {
|
||||
}
|
||||
|
||||
public List<? extends SymbolInformation> getSymbols(String docURI) {
|
||||
waitForInitializeTask();
|
||||
return this.symbolsByDoc.get(docURI);
|
||||
}
|
||||
|
||||
public List<SymbolAddOnInformation> getAllAdditionalInformation(Predicate<SymbolAddOnInformation> filter) {
|
||||
waitForInitializeTask();
|
||||
|
||||
if (filter != null) {
|
||||
return addonInformation.stream().filter(filter).collect(Collectors.toList());
|
||||
}
|
||||
@@ -340,46 +280,29 @@ public class SpringIndexer {
|
||||
}
|
||||
|
||||
public List<? extends SymbolAddOnInformation> getAdditonalInformation(String docURI) {
|
||||
waitForInitializeTask();
|
||||
List<SymbolAddOnInformation> info = this.addonInformationByDoc.get(docURI);
|
||||
return info == null ? ImmutableList.of() : info;
|
||||
}
|
||||
|
||||
private List<SymbolInformation> searchMatchingSymbols(List<SymbolInformation> allsymbols, String query) {
|
||||
waitForInitializeTask();
|
||||
return allsymbols.stream()
|
||||
.filter(symbol -> StringUtil.containsCharactersCaseInsensitive(symbol.getName(), query))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private void scanFiles(WorkspaceFolder directory) {
|
||||
try {
|
||||
Map<Optional<IJavaProject>, List<String>> projects = Files.walk(Paths.get(new URI(directory.getUri())))
|
||||
.filter(path -> path.getFileName().toString().endsWith(".java"))
|
||||
.filter(Files::isRegularFile)
|
||||
.map(path -> path.toAbsolutePath().toString())
|
||||
.collect(Collectors.groupingBy((javaFile) -> projectFinder.find(new TextDocumentIdentifier(new File(javaFile).toURI().toString()))));
|
||||
|
||||
projects.forEach((maybeProject, files) -> maybeProject.ifPresent(project -> scanProject(project, files.toArray(new String[0]))));
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void scanProject(IJavaProject project, String[] files) {
|
||||
try {
|
||||
ASTParser parser = ASTParser.newParser(AST.JLS10);
|
||||
String[] classpathEntries = getClasspathEntries(project);
|
||||
|
||||
scanFiles(parser, files, classpathEntries);
|
||||
scanFiles(project, parser, files, classpathEntries);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void scanFile(String docURI, String content, String[] classpathEntries) throws Exception {
|
||||
private void scanFile(IJavaProject project, String docURI, String content, String[] classpathEntries) throws Exception {
|
||||
ASTParser parser = ASTParser.newParser(AST.JLS10);
|
||||
Map<String, String> options = JavaCore.getOptions();
|
||||
JavaCore.setComplianceOptions(JavaCore.VERSION_10, options);
|
||||
@@ -400,22 +323,12 @@ public class SpringIndexer {
|
||||
CompilationUnit cu = (CompilationUnit) parser.createAST(null);
|
||||
|
||||
if (cu != null) {
|
||||
List<SymbolInformation> oldSymbols = symbolsByDoc.remove(docURI);
|
||||
if (oldSymbols != null) {
|
||||
symbols.removeAll(oldSymbols);
|
||||
}
|
||||
|
||||
List<SymbolAddOnInformation> oldAddOnInformation = addonInformationByDoc.remove(docURI);
|
||||
if (oldAddOnInformation != null) {
|
||||
addonInformation.removeAll(oldAddOnInformation);
|
||||
}
|
||||
|
||||
AtomicReference<TextDocument> docRef = new AtomicReference<>();
|
||||
scanAST(cu, docURI, docRef, content);
|
||||
scanAST(project, cu, docURI, docRef, content);
|
||||
}
|
||||
}
|
||||
|
||||
private void scanFiles(ASTParser parser, String[] javaFiles, String[] classpathEntries) throws Exception {
|
||||
private void scanFiles(IJavaProject project, ASTParser parser, String[] javaFiles, String[] classpathEntries) throws Exception {
|
||||
|
||||
Map<String, String> options = JavaCore.getOptions();
|
||||
JavaCore.setComplianceOptions(JavaCore.VERSION_10, options);
|
||||
@@ -434,20 +347,20 @@ public class SpringIndexer {
|
||||
public void acceptAST(String sourceFilePath, CompilationUnit cu) {
|
||||
String docURI = UriUtil.toUri(new File(sourceFilePath)).toString();
|
||||
AtomicReference<TextDocument> docRef = new AtomicReference<>();
|
||||
scanAST(cu, docURI, docRef, null);
|
||||
scanAST(project, cu, docURI, docRef, null);
|
||||
}
|
||||
};
|
||||
|
||||
parser.createASTs(javaFiles, null, new String[0], requestor, null);
|
||||
}
|
||||
|
||||
private void scanAST(final CompilationUnit cu, final String docURI, AtomicReference<TextDocument> docRef, final String content) {
|
||||
private void scanAST(final IJavaProject project, final CompilationUnit cu, final String docURI, AtomicReference<TextDocument> docRef, final String content) {
|
||||
cu.accept(new ASTVisitor() {
|
||||
|
||||
@Override
|
||||
public boolean visit(TypeDeclaration node) {
|
||||
try {
|
||||
extractSymbolInformation(node, docURI, docRef, content);
|
||||
extractSymbolInformation(project, node, docURI, docRef, content);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -458,7 +371,7 @@ public class SpringIndexer {
|
||||
@Override
|
||||
public boolean visit(MethodDeclaration node) {
|
||||
try {
|
||||
extractSymbolInformation(node, docURI, docRef, content);
|
||||
extractSymbolInformation(project, node, docURI, docRef, content);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -469,7 +382,7 @@ public class SpringIndexer {
|
||||
@Override
|
||||
public boolean visit(SingleMemberAnnotation node) {
|
||||
try {
|
||||
extractSymbolInformation(node, docURI, docRef, content);
|
||||
extractSymbolInformation(project, node, docURI, docRef, content);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -481,7 +394,7 @@ public class SpringIndexer {
|
||||
@Override
|
||||
public boolean visit(NormalAnnotation node) {
|
||||
try {
|
||||
extractSymbolInformation(node, docURI, docRef, content);
|
||||
extractSymbolInformation(project, node, docURI, docRef, content);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -493,7 +406,7 @@ public class SpringIndexer {
|
||||
@Override
|
||||
public boolean visit(MarkerAnnotation node) {
|
||||
try {
|
||||
extractSymbolInformation(node, docURI, docRef, content);
|
||||
extractSymbolInformation(project, node, docURI, docRef, content);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
@@ -504,7 +417,7 @@ public class SpringIndexer {
|
||||
});
|
||||
}
|
||||
|
||||
private void extractSymbolInformation(TypeDeclaration typeDeclaration, String docURI, AtomicReference<TextDocument> docRef, String content) throws Exception {
|
||||
private void extractSymbolInformation(IJavaProject project, TypeDeclaration typeDeclaration, String docURI, AtomicReference<TextDocument> docRef, String content) throws Exception {
|
||||
Collection<SymbolProvider> providers = symbolProviders.getAll();
|
||||
if (!providers.isEmpty()) {
|
||||
TextDocument doc = getTempTextDocument(docURI, docRef, content);
|
||||
@@ -512,20 +425,14 @@ public class SpringIndexer {
|
||||
Collection<EnhancedSymbolInformation> sbls = provider.getSymbols(typeDeclaration, doc);
|
||||
if (sbls != null) {
|
||||
sbls.forEach(enhancedSymbol -> {
|
||||
symbols.add(enhancedSymbol.getSymbol());
|
||||
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(enhancedSymbol.getSymbol());
|
||||
|
||||
if (enhancedSymbol.getAdditionalInformation() != null) {
|
||||
addonInformation.addAll(Arrays.asList(enhancedSymbol.getAdditionalInformation()));
|
||||
addonInformationByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolAddOnInformation>()).addAll(Arrays.asList(enhancedSymbol.getAdditionalInformation()));
|
||||
}
|
||||
addSymbol(project, docURI, enhancedSymbol);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSymbolInformation(MethodDeclaration methodDeclaration, String docURI, AtomicReference<TextDocument> docRef, String content) throws Exception {
|
||||
private void extractSymbolInformation(IJavaProject project, MethodDeclaration methodDeclaration, String docURI, AtomicReference<TextDocument> docRef, String content) throws Exception {
|
||||
Collection<SymbolProvider> providers = symbolProviders.getAll();
|
||||
if (!providers.isEmpty()) {
|
||||
TextDocument doc = getTempTextDocument(docURI, docRef, content);
|
||||
@@ -533,20 +440,14 @@ public class SpringIndexer {
|
||||
Collection<EnhancedSymbolInformation> sbls = provider.getSymbols(methodDeclaration, doc);
|
||||
if (sbls != null) {
|
||||
sbls.forEach(enhancedSymbol -> {
|
||||
symbols.add(enhancedSymbol.getSymbol());
|
||||
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(enhancedSymbol.getSymbol());
|
||||
|
||||
if (enhancedSymbol.getAdditionalInformation() != null) {
|
||||
addonInformation.addAll(Arrays.asList(enhancedSymbol.getAdditionalInformation()));
|
||||
addonInformationByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolAddOnInformation>()).addAll(Arrays.asList(enhancedSymbol.getAdditionalInformation()));
|
||||
}
|
||||
addSymbol(project, docURI, enhancedSymbol);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void extractSymbolInformation(Annotation node, String docURI, AtomicReference<TextDocument> docRef, String content) throws Exception {
|
||||
private void extractSymbolInformation(IJavaProject project, Annotation node, String docURI, AtomicReference<TextDocument> docRef, String content) throws Exception {
|
||||
ITypeBinding typeBinding = node.resolveTypeBinding();
|
||||
|
||||
if (typeBinding != null) {
|
||||
@@ -558,21 +459,14 @@ public class SpringIndexer {
|
||||
Collection<EnhancedSymbolInformation> sbls = provider.getSymbols(node, typeBinding, metaAnnotations, doc);
|
||||
if (sbls != null) {
|
||||
sbls.forEach(enhancedSymbol -> {
|
||||
symbols.add(enhancedSymbol.getSymbol());
|
||||
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(enhancedSymbol.getSymbol());
|
||||
|
||||
if (enhancedSymbol.getAdditionalInformation() != null) {
|
||||
addonInformation.addAll(Arrays.asList(enhancedSymbol.getAdditionalInformation()));
|
||||
addonInformationByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolAddOnInformation>()).addAll(Arrays.asList(enhancedSymbol.getAdditionalInformation()));
|
||||
}
|
||||
addSymbol(project, docURI, enhancedSymbol);
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
SymbolInformation symbol = provideDefaultSymbol(node, docURI, docRef, content);
|
||||
if (symbol != null) {
|
||||
symbols.add(symbol);
|
||||
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(symbol);
|
||||
addSymbol(project, docURI, new EnhancedSymbolInformation(symbol, null));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -625,136 +519,176 @@ public class SpringIndexer {
|
||||
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
* inner class to capture items for the update worker
|
||||
*/
|
||||
private interface WorkerItem {
|
||||
|
||||
public void run();
|
||||
public CompletableFuture<Void> getFuture();
|
||||
|
||||
}
|
||||
|
||||
private static AtomicInteger initItemId = new AtomicInteger(0);
|
||||
|
||||
private class InitializeItem implements WorkerItem {
|
||||
private class InitializeProject implements Runnable {
|
||||
|
||||
private int id = initItemId.incrementAndGet();
|
||||
|
||||
private final WorkspaceFolder[] workspaceRoots;
|
||||
private final CompletableFuture<Void> future;
|
||||
private final IJavaProject project;
|
||||
|
||||
public InitializeItem(WorkspaceFolder[] workspaceRoots) {
|
||||
this.workspaceRoots = workspaceRoots;
|
||||
this.future = new CompletableFuture<Void>();
|
||||
public InitializeProject(IJavaProject project) {
|
||||
this.project = project;
|
||||
log.debug("{} created ", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> getFuture() {
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log.debug("{} starting...", this);
|
||||
try {
|
||||
if (!future.isCancelled()) {
|
||||
// log.debug("initialze spring indexer task started for roots: " + Arrays.toString(workspaceRoots));
|
||||
symbols.clear();
|
||||
symbolsByDoc.clear();
|
||||
removeSymbolsByProject(project);
|
||||
|
||||
addonInformation.clear();
|
||||
addonInformationByDoc.clear();
|
||||
String projectUri = project.getLocationUri();
|
||||
List<String> files = Files.walk(Paths.get(new URI(projectUri)))
|
||||
.filter(path -> path.getFileName().toString().endsWith(".java"))
|
||||
.filter(Files::isRegularFile)
|
||||
.map(path -> path.toAbsolutePath().toString())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (WorkspaceFolder root : workspaceRoots) {
|
||||
SpringIndexer.this.scanFiles(root);
|
||||
}
|
||||
SpringIndexer.this.scanProject(project, (String[]) files.toArray(new String[files.size()]));
|
||||
|
||||
// log.debug("initialze spring indexer task completed for roots: " + Arrays.toString(workspaceRoots));
|
||||
|
||||
future.complete(null);
|
||||
log.debug("{} completed", this);
|
||||
}
|
||||
else {
|
||||
log.debug("{} skipped because it was canceled", this);
|
||||
}
|
||||
log.debug("{} completed", this);
|
||||
} catch (Throwable e) {
|
||||
log.error("{} threw exception", this, e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "InitItem("+id+")";
|
||||
}
|
||||
}
|
||||
|
||||
private class UpdateItem implements WorkerItem {
|
||||
private class DeleteProject implements Runnable {
|
||||
|
||||
private final IJavaProject project;
|
||||
|
||||
public DeleteProject(IJavaProject project) {
|
||||
this.project = project;
|
||||
log.debug("{} created ", this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
log.debug("{} starting...", this);
|
||||
try {
|
||||
removeSymbolsByProject(project);
|
||||
log.debug("{} completed", this);
|
||||
} catch (Throwable e) {
|
||||
log.error("{} threw exception", this, e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private class UpdateItem implements Runnable {
|
||||
|
||||
private final String docURI;
|
||||
private final String content;
|
||||
private final String[] classpathEntries;
|
||||
private final IJavaProject project;
|
||||
|
||||
private final CompletableFuture<Void> future;
|
||||
|
||||
public UpdateItem(String docURI, String content, String[] classpathEntries) {
|
||||
public UpdateItem(IJavaProject project, String docURI, String content, String[] classpathEntries) {
|
||||
this.project = project;
|
||||
this.docURI = docURI;
|
||||
this.content = content;
|
||||
this.classpathEntries = classpathEntries;
|
||||
this.future = new CompletableFuture<Void>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> getFuture() {
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
SpringIndexer.this.scanFile(docURI, content, classpathEntries);
|
||||
removeSymbolsByDoc(project, docURI);
|
||||
SpringIndexer.this.scanFile(project, docURI, content, classpathEntries);
|
||||
} catch (Exception e) {
|
||||
log.error("{}", e);
|
||||
}
|
||||
future.complete(null);
|
||||
}
|
||||
}
|
||||
|
||||
private class DeleteItem implements WorkerItem {
|
||||
private class DeleteItem implements Runnable {
|
||||
|
||||
private final String docURI;
|
||||
private final CompletableFuture<Void> future;
|
||||
private IJavaProject project;
|
||||
|
||||
public DeleteItem(String docURI) {
|
||||
public DeleteItem(IJavaProject project, String docURI) {
|
||||
this.project = project;
|
||||
this.docURI = docURI;
|
||||
this.future = new CompletableFuture<Void>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Void> getFuture() {
|
||||
return future;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
|
||||
List<SymbolInformation> oldSymbols = symbolsByDoc.remove(docURI);
|
||||
if (oldSymbols != null) {
|
||||
symbols.removeAll(oldSymbols);
|
||||
}
|
||||
|
||||
List<SymbolAddOnInformation> oldAddInInformation = addonInformationByDoc.remove(docURI);
|
||||
if (oldAddInInformation != null) {
|
||||
addonInformation.removeAll(oldAddInInformation);
|
||||
}
|
||||
|
||||
removeSymbolsByDoc(project, docURI);
|
||||
} catch (Exception e) {
|
||||
log.error("{}", e);
|
||||
}
|
||||
future.complete(null);
|
||||
}
|
||||
}
|
||||
|
||||
private void addSymbol(IJavaProject project, String docURI, EnhancedSymbolInformation enhancedSymbol) {
|
||||
symbols.add(enhancedSymbol.getSymbol());
|
||||
symbolsByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolInformation>()).add(enhancedSymbol.getSymbol());
|
||||
symbolsByProject.computeIfAbsent(project.getElementName(), s -> new ArrayList<SymbolInformation>()).add(enhancedSymbol.getSymbol());
|
||||
|
||||
if (enhancedSymbol.getAdditionalInformation() != null) {
|
||||
addonInformation.addAll(Arrays.asList(enhancedSymbol.getAdditionalInformation()));
|
||||
addonInformationByDoc.computeIfAbsent(docURI, s -> new ArrayList<SymbolAddOnInformation>()).addAll(Arrays.asList(enhancedSymbol.getAdditionalInformation()));
|
||||
addonInformationByProject.computeIfAbsent(project.getElementName(), s -> new ArrayList<SymbolAddOnInformation>()).addAll(Arrays.asList(enhancedSymbol.getAdditionalInformation()));
|
||||
}
|
||||
}
|
||||
|
||||
private void removeSymbolsByDoc(IJavaProject project, String docURI) {
|
||||
List<SymbolInformation> oldSymbols = symbolsByDoc.remove(docURI);
|
||||
if (oldSymbols != null) {
|
||||
symbols.removeAll(oldSymbols);
|
||||
|
||||
List<SymbolInformation> projectSymbols = symbolsByProject.get(project.getElementName());
|
||||
if (projectSymbols != null) {
|
||||
projectSymbols.removeAll(oldSymbols);
|
||||
}
|
||||
}
|
||||
|
||||
List<SymbolAddOnInformation> oldAddInInformation = addonInformationByDoc.remove(docURI);
|
||||
if (oldAddInInformation != null) {
|
||||
addonInformation.removeAll(oldAddInInformation);
|
||||
|
||||
List<SymbolAddOnInformation> projectAddOns = addonInformationByProject.get(project.getElementName());
|
||||
if (projectAddOns != null) {
|
||||
projectAddOns.removeAll(oldAddInInformation);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void removeSymbolsByProject(IJavaProject project) {
|
||||
List<SymbolInformation> oldSymbols = symbolsByProject.remove(project.getElementName());
|
||||
if (oldSymbols != null) {
|
||||
symbols.removeAll(oldSymbols);
|
||||
|
||||
Set<String> keySet = symbolsByDoc.keySet();
|
||||
Iterator<String> docIter = keySet.iterator();
|
||||
while (docIter.hasNext()) {
|
||||
String docURI = docIter.next();
|
||||
List<SymbolInformation> docSymbols = symbolsByDoc.get(docURI);
|
||||
docSymbols.removeAll(oldSymbols);
|
||||
|
||||
if (docSymbols.isEmpty()) {
|
||||
docIter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
List<SymbolAddOnInformation> oldAddInInformation = addonInformationByProject.remove(project.getElementName());
|
||||
if (oldAddInInformation != null) {
|
||||
addonInformation.removeAll(oldAddInInformation);
|
||||
|
||||
Set<String> keySet = addonInformationByDoc.keySet();
|
||||
Iterator<String> docIter = keySet.iterator();
|
||||
while (docIter.hasNext()) {
|
||||
String docURI = docIter.next();
|
||||
List<SymbolAddOnInformation> docAddons = addonInformationByDoc.get(docURI);
|
||||
docAddons.removeAll(oldAddInInformation);
|
||||
|
||||
if (docAddons.isEmpty()) {
|
||||
docIter.remove();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -219,6 +219,7 @@ public class JdtLsProjectCache implements JavaProjectsService {
|
||||
return classpath;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLocationUri() {
|
||||
return classpath.projectUri;
|
||||
}
|
||||
|
||||
@@ -11,15 +11,19 @@
|
||||
package org.springframework.ide.vscode.boot.java.beans.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyAwareLookup;
|
||||
import org.springframework.ide.vscode.boot.java.beans.BeansSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.beans.ComponentSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.beans.test.SpringIndexerHarness.TestSymbolInfo;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringIndexer;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.project.harness.BootJavaLanguageServerHarness;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
|
||||
@@ -30,6 +34,8 @@ public class SpringIndexerBeansTest {
|
||||
|
||||
private AnnotationHierarchyAwareLookup<SymbolProvider> symbolProviders;
|
||||
private BootJavaLanguageServerHarness harness;
|
||||
private File directory;
|
||||
private SpringIndexer indexer;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
@@ -38,105 +44,81 @@ public class SpringIndexerBeansTest {
|
||||
symbolProviders.put(Annotations.COMPONENT, new ComponentSymbolProvider());
|
||||
|
||||
harness = BootJavaLanguageServerHarness.builder().build();
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()));
|
||||
harness.intialize(null);
|
||||
|
||||
indexer = harness.getServerWrapper().getComponents().getSpringIndexer();
|
||||
directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
|
||||
String projectDir = directory.toURI().toString();
|
||||
IJavaProject project = harness.getServerWrapper().getComponents().getProjectFinder().find(new TextDocumentIdentifier(projectDir)).get();
|
||||
|
||||
CompletableFuture<Void> initProject = indexer.initializeProject(project);
|
||||
initProject.get(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanSimpleConfigurationClass() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/SimpleConfiguration.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("@Configuration", "@+ 'simpleConfiguration' (@Configuration <: @Component) SimpleConfiguration"),
|
||||
symbol("@Bean", "@+ 'simpleBean' (@Bean) BeanClass")
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("@Configuration", "@+ 'simpleConfiguration' (@Configuration <: @Component) SimpleConfiguration"),
|
||||
SpringIndexerHarness.symbol("@Bean", "@+ 'simpleBean' (@Bean) BeanClass")
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void testScanSpecialConfigurationClass() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/SpecialConfiguration.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("@Configuration", "@+ 'specialConfiguration' (@Configuration <: @Component) SpecialConfiguration"),
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("@Configuration", "@+ 'specialConfiguration' (@Configuration <: @Component) SpecialConfiguration"),
|
||||
|
||||
// @Bean("implicitNamedBean")
|
||||
symbol("implicitNamedBean", "@+ 'implicitNamedBean' (@Bean) BeanClass"),
|
||||
SpringIndexerHarness.symbol("implicitNamedBean", "@+ 'implicitNamedBean' (@Bean) BeanClass"),
|
||||
|
||||
// @Bean(value="valueBean")
|
||||
symbol("valueBean", "@+ 'valueBean' (@Bean) BeanClass"),
|
||||
SpringIndexerHarness.symbol("valueBean", "@+ 'valueBean' (@Bean) BeanClass"),
|
||||
|
||||
// @Bean(value= {"valueBean1", "valueBean2"})
|
||||
symbol("valueBean1", "@+ 'valueBean1' (@Bean) BeanClass"),
|
||||
symbol("valueBean2", "@+ 'valueBean2' (@Bean) BeanClass"),
|
||||
SpringIndexerHarness.symbol("valueBean1", "@+ 'valueBean1' (@Bean) BeanClass"),
|
||||
SpringIndexerHarness.symbol("valueBean2", "@+ 'valueBean2' (@Bean) BeanClass"),
|
||||
|
||||
// @Bean(name="namedBean")
|
||||
symbol("namedBean", "@+ 'namedBean' (@Bean) BeanClass"),
|
||||
SpringIndexerHarness.symbol("namedBean", "@+ 'namedBean' (@Bean) BeanClass"),
|
||||
|
||||
// @Bean(name= {"namedBean1", "namedBean2"})
|
||||
symbol("namedBean1", "@+ 'namedBean1' (@Bean) BeanClass"),
|
||||
symbol("namedBean2", "@+ 'namedBean2' (@Bean) BeanClass")
|
||||
SpringIndexerHarness.symbol("namedBean1", "@+ 'namedBean1' (@Bean) BeanClass"),
|
||||
SpringIndexerHarness.symbol("namedBean2", "@+ 'namedBean2' (@Bean) BeanClass")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanAbstractBeanConfiguration() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/AbstractBeanConfiguration.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("@Configuration", "@+ 'abstractBeanConfiguration' (@Configuration <: @Component) AbstractBeanConfiguration")
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("@Configuration", "@+ 'abstractBeanConfiguration' (@Configuration <: @Component) AbstractBeanConfiguration")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanSimpleComponentClass() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/SimpleComponent.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("@Component", "@+ 'simpleComponent' (@Component) SimpleComponent")
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("@Component", "@+ 'simpleComponent' (@Component) SimpleComponent")
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void testScanSimpleControllerClass() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
@Test
|
||||
public void testScanSimpleControllerClass() throws Exception {
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/SimpleController.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("@Controller", "@+ 'simpleController' (@Controller <: @Component) SimpleController")
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("@Controller", "@+ 'simpleController' (@Controller <: @Component) SimpleController")
|
||||
);
|
||||
}
|
||||
|
||||
@Test public void testScanRestControllerClass() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
@Test
|
||||
public void testScanRestControllerClass() throws Exception {
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/SimpleRestController.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("@RestController", "@+ 'simpleRestController' (@RestController <: @Controller, @Component) SimpleRestController")
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("@RestController", "@+ 'simpleRestController' (@RestController <: @Controller, @Component) SimpleRestController")
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////
|
||||
// harness code
|
||||
|
||||
private SpringIndexerHarness createIndexerHarness() {
|
||||
return new SpringIndexerHarness(harness.getServer(), harness.getServerParams(), symbolProviders);
|
||||
}
|
||||
|
||||
private TestSymbolInfo symbol(String coveredText, String label) {
|
||||
return new TestSymbolInfo(coveredText, label);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,15 +11,19 @@
|
||||
package org.springframework.ide.vscode.boot.java.beans.test;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyAwareLookup;
|
||||
import org.springframework.ide.vscode.boot.java.beans.BeansSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.beans.ComponentSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.beans.test.SpringIndexerHarness.TestSymbolInfo;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringIndexer;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.project.harness.BootJavaLanguageServerHarness;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
|
||||
@@ -30,6 +34,8 @@ public class SpringIndexerFunctionBeansTest {
|
||||
|
||||
private AnnotationHierarchyAwareLookup<SymbolProvider> symbolProviders;
|
||||
private BootJavaLanguageServerHarness harness;
|
||||
private SpringIndexer indexer;
|
||||
private File directory;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
@@ -38,97 +44,67 @@ public class SpringIndexerFunctionBeansTest {
|
||||
symbolProviders.put(Annotations.COMPONENT, new ComponentSymbolProvider());
|
||||
|
||||
harness = BootJavaLanguageServerHarness.builder().build();
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI()));
|
||||
harness.intialize(null);
|
||||
|
||||
indexer = harness.getServerWrapper().getComponents().getSpringIndexer();
|
||||
directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
|
||||
String projectDir = directory.toURI().toString();
|
||||
IJavaProject project = harness.getServerWrapper().getComponents().getProjectFinder().find(new TextDocumentIdentifier(projectDir)).get();
|
||||
|
||||
CompletableFuture<Void> initProject = indexer.initializeProject(project);
|
||||
initProject.get(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanSimpleFunctionBean() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/FunctionClass.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("@Configuration", "@+ 'functionClass' (@Configuration <: @Component) FunctionClass"),
|
||||
symbol("@Bean", "@> 'uppercase' (@Bean) Function<String,String>")
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("@Configuration", "@+ 'functionClass' (@Configuration <: @Component) FunctionClass"),
|
||||
SpringIndexerHarness.symbol("@Bean", "@> 'uppercase' (@Bean) Function<String,String>")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanSimpleFunctionClass() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/ScannedFunctionClass.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("ScannedFunctionClass", "@> 'scannedFunctionClass' Function<String,String>")
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("ScannedFunctionClass", "@> 'scannedFunctionClass' Function<String,String>")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanSpecializedFunctionClass() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/FunctionFromSpecializedClass.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("FunctionFromSpecializedClass", "@> 'functionFromSpecializedClass' Function<String,String>")
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("FunctionFromSpecializedClass", "@> 'functionFromSpecializedClass' Function<String,String>")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanSpecializedFunctionInterface() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/FunctionFromSpecializedInterface.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri,
|
||||
symbol("FunctionFromSpecializedInterface", "@> 'functionFromSpecializedInterface' Function<String,String>")
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri,
|
||||
SpringIndexerHarness.symbol("FunctionFromSpecializedInterface", "@> 'functionFromSpecializedInterface' Function<String,String>")
|
||||
);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSymbolForAbstractClasses() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/SpecializedFunctionClass.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri);
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testNoSymbolForSubInterfaces() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/SpecializedFunctionInterface.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri);
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanInconsistentInterfaceHierarchy() throws Exception {
|
||||
SpringIndexerHarness indexer = createIndexerHarness();
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
|
||||
indexer.initialize(indexer.wsFolder(directory));
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/LoopedFunctionClass.java").toUri().toString();
|
||||
indexer.assertDocumentSymbols(docUri);
|
||||
}
|
||||
|
||||
////////////////////////////////
|
||||
// harness code
|
||||
|
||||
private TestSymbolInfo symbol(String coveredText, String label) {
|
||||
return new TestSymbolInfo(coveredText, label);
|
||||
}
|
||||
|
||||
private SpringIndexerHarness createIndexerHarness() {
|
||||
return new SpringIndexerHarness(harness.getServer(), harness.getServerParams(), symbolProviders);
|
||||
SpringIndexerHarness.assertDocumentSymbols(indexer, docUri);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -12,11 +12,9 @@ package org.springframework.ide.vscode.boot.java.beans.test;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@@ -24,12 +22,7 @@ import java.util.List;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
import org.eclipse.lsp4j.WorkspaceFolder;
|
||||
import org.springframework.ide.vscode.boot.BootLanguageServerParams;
|
||||
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyAwareLookup;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringIndexer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.util.text.LanguageId;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.Editor;
|
||||
@@ -104,18 +97,16 @@ public class SpringIndexerHarness {
|
||||
|
||||
};
|
||||
|
||||
private SpringIndexer indexer;
|
||||
|
||||
public SpringIndexerHarness(SimpleLanguageServer server, BootLanguageServerParams params, AnnotationHierarchyAwareLookup<SymbolProvider> symbolProviders) {
|
||||
this.indexer = new SpringIndexer(server, params, symbolProviders);
|
||||
public static TestSymbolInfo symbol(String coveredText, String label) {
|
||||
return new TestSymbolInfo(coveredText, label);
|
||||
}
|
||||
|
||||
public void assertDocumentSymbols(String documentUri, TestSymbolInfo... expectedSymbols) throws Exception {
|
||||
List<TestSymbolInfo> actualSymbols = getSymbolsInFile(documentUri);
|
||||
public static void assertDocumentSymbols(SpringIndexer indexer, String documentUri, TestSymbolInfo... expectedSymbols) throws Exception {
|
||||
List<TestSymbolInfo> actualSymbols = getSymbolsInFile(indexer, documentUri);
|
||||
assertEquals(symbolsString(Arrays.asList(expectedSymbols)), symbolsString(actualSymbols));
|
||||
}
|
||||
|
||||
private String symbolsString(List<TestSymbolInfo> symbols) {
|
||||
private static String symbolsString(List<TestSymbolInfo> symbols) {
|
||||
StringBuilder buf = new StringBuilder();
|
||||
for (TestSymbolInfo s : symbols) {
|
||||
buf.append(s+"\n");
|
||||
@@ -123,7 +114,7 @@ public class SpringIndexerHarness {
|
||||
return buf.toString();
|
||||
}
|
||||
|
||||
public List<TestSymbolInfo> getSymbolsInFile(String docURI) throws Exception {
|
||||
public static List<TestSymbolInfo> getSymbolsInFile(SpringIndexer indexer, String docURI) throws Exception {
|
||||
List<? extends SymbolInformation> symbols = indexer.getSymbols(docURI);
|
||||
if (symbols!=null) {
|
||||
symbols = new ArrayList<>(symbols);
|
||||
@@ -140,17 +131,4 @@ public class SpringIndexerHarness {
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
public Collection<WorkspaceFolder> wsFolder(File directory) {
|
||||
if (directory != null) {
|
||||
WorkspaceFolder folder = new WorkspaceFolder();
|
||||
folder.setName(directory.getName());
|
||||
folder.setUri(directory.toURI().toString());
|
||||
return ImmutableList.of(folder);
|
||||
}
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
public void initialize(Collection<WorkspaceFolder> wsRoots) {
|
||||
indexer.initialize(wsRoots);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -57,6 +57,10 @@ public class CompilationUnitCacheTest {
|
||||
public IClasspath getClasspath() {
|
||||
return new DelegatingCachedClasspath<>(() -> null, null);
|
||||
}
|
||||
@Override
|
||||
public String getLocationUri() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
harness.intialize(null);
|
||||
|
||||
@@ -99,6 +103,10 @@ public class CompilationUnitCacheTest {
|
||||
public IClasspath getClasspath() {
|
||||
return new DelegatingCachedClasspath<>(() -> null, null);
|
||||
}
|
||||
@Override
|
||||
public String getLocationUri() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
harness.intialize(null);
|
||||
|
||||
@@ -130,6 +138,10 @@ public class CompilationUnitCacheTest {
|
||||
public IClasspath getClasspath() {
|
||||
return new DelegatingCachedClasspath<>(() -> null, null);
|
||||
}
|
||||
@Override
|
||||
public String getLocationUri() {
|
||||
return null;
|
||||
}
|
||||
});
|
||||
harness.intialize(null);
|
||||
|
||||
|
||||
@@ -17,26 +17,19 @@ import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.File;
|
||||
import java.net.URI;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.eclipse.lsp4j.SymbolInformation;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServerComponents;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringIndexer;
|
||||
import org.springframework.ide.vscode.commons.languageserver.composable.ComposableLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.maven.MavenCore;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.util.Assert;
|
||||
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
|
||||
import org.springframework.ide.vscode.project.harness.BootJavaLanguageServerHarness;
|
||||
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
|
||||
@@ -45,28 +38,30 @@ import org.springframework.ide.vscode.project.harness.ProjectsHarness;
|
||||
*/
|
||||
public class SpringIndexerTest {
|
||||
|
||||
private Map<String, SymbolProvider> symbolProviders;
|
||||
private LanguageServerHarness<ComposableLanguageServer<BootJavaLanguageServerComponents>> harness;
|
||||
|
||||
private SpringIndexer indexer() {
|
||||
return harness.getServerWrapper().getComponents().getSpringIndexer();
|
||||
}
|
||||
|
||||
private BootJavaLanguageServerHarness harness;
|
||||
private File directory;
|
||||
private SpringIndexer indexer;
|
||||
private String projectDir;
|
||||
private IJavaProject project;
|
||||
|
||||
@Before
|
||||
public void setup() throws Exception {
|
||||
symbolProviders = new HashMap<>();
|
||||
symbolProviders.put(Annotations.SPRING_REQUEST_MAPPING, new RequestMappingSymbolProvider());
|
||||
harness = BootJavaLanguageServerHarness.builder().build();
|
||||
|
||||
harness.intialize(null);
|
||||
indexer = harness.getServerWrapper().getComponents().getSpringIndexer();
|
||||
|
||||
directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
projectDir = directory.toURI().toString();
|
||||
project = harness.getServerWrapper().getComponents().getProjectFinder().find(new TextDocumentIdentifier(projectDir)).get();
|
||||
|
||||
CompletableFuture<Void> initProject = indexer.initializeProject(project);
|
||||
initProject.get(5, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanningAllAnnotationsSimpleProjectUpfront() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
|
||||
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
|
||||
List<? extends SymbolInformation> allSymbols = indexer().getAllSymbols("");
|
||||
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("");
|
||||
|
||||
assertEquals(6, allSymbols.size());
|
||||
|
||||
@@ -85,36 +80,28 @@ public class SpringIndexerTest {
|
||||
|
||||
@Test
|
||||
public void testRetrievingSymbolsPerDocument() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
|
||||
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/MainClass.java").toUri().toString();
|
||||
List<? extends SymbolInformation> symbols = indexer().getSymbols(docUri);
|
||||
List<? extends SymbolInformation> symbols = indexer.getSymbols(docUri);
|
||||
assertEquals(3, symbols.size());
|
||||
assertTrue(containsSymbol(symbols, "@+ 'mainClass' (@SpringBootApplication <: @SpringBootConfiguration, @Configuration, @Component) MainClass", docUri, 6, 0, 6, 22));
|
||||
assertTrue(containsSymbol(symbols, "@/embedded-foo-mapping", docUri, 17, 1, 17, 41));
|
||||
assertTrue(containsSymbol(symbols, "@/foo-root-mapping/embedded-foo-mapping-with-root", docUri, 27, 1, 27, 51));
|
||||
|
||||
docUri = directory.toPath().resolve("src/main/java/org/test/SimpleMappingClass.java").toUri().toString();
|
||||
symbols = indexer().getSymbols(docUri);
|
||||
symbols = indexer.getSymbols(docUri);
|
||||
assertEquals(2, symbols.size());
|
||||
assertTrue(containsSymbol(symbols, "@/mapping1", docUri, 6, 1, 6, 28));
|
||||
assertTrue(containsSymbol(symbols, "@/mapping2", docUri, 11, 1, 11, 28));
|
||||
|
||||
docUri = directory.toPath().resolve("src/main/java/org/test/sub/MappingClassSubpackage.java").toUri().toString();
|
||||
symbols = indexer().getSymbols(docUri);
|
||||
symbols = indexer.getSymbols(docUri);
|
||||
assertEquals(1, symbols.size());
|
||||
assertTrue(containsSymbol(symbols, "@/classlevel/mapping-subpackage", docUri, 7, 1, 7, 38));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testScanningAllAnnotationsMultiModuleProjectUpfront() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/").toURI()));
|
||||
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing").toURI());
|
||||
|
||||
List<? extends SymbolInformation> allSymbols = indexer().getAllSymbols("");
|
||||
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("");
|
||||
|
||||
assertEquals(6, allSymbols.size());
|
||||
|
||||
@@ -133,27 +120,23 @@ public class SpringIndexerTest {
|
||||
|
||||
@Test
|
||||
public void testUpdateChangedDocument() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
|
||||
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
|
||||
// update document and update index
|
||||
String changedDocURI = directory.toPath().resolve("src/main/java/org/test/SimpleMappingClass.java").toUri().toString();
|
||||
|
||||
assertTrue(containsSymbol(indexer().getSymbols(changedDocURI), "@/mapping1", changedDocURI));
|
||||
assertTrue(containsSymbol(indexer.getSymbols(changedDocURI), "@/mapping1", changedDocURI));
|
||||
|
||||
String newContent = FileUtils.readFileToString(new File(new URI(changedDocURI))).replace("mapping1", "mapping1-CHANGED");
|
||||
CompletableFuture<Void> updateFuture = indexer().updateDocument(changedDocURI, newContent);
|
||||
CompletableFuture<Void> updateFuture = indexer.updateDocument(changedDocURI, newContent);
|
||||
updateFuture.get(5, TimeUnit.SECONDS);
|
||||
|
||||
// check for updated index per document
|
||||
List<? extends SymbolInformation> symbols = indexer().getSymbols(changedDocURI);
|
||||
List<? extends SymbolInformation> symbols = indexer.getSymbols(changedDocURI);
|
||||
assertEquals(2, symbols.size());
|
||||
assertTrue(containsSymbol(symbols, "@/mapping1-CHANGED", changedDocURI, 6, 1, 6, 36));
|
||||
assertTrue(containsSymbol(symbols, "@/mapping2", changedDocURI, 11, 1, 11, 28));
|
||||
|
||||
// check for updated index in all symbols
|
||||
List<? extends SymbolInformation> allSymbols = indexer().getAllSymbols("");
|
||||
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("");
|
||||
assertEquals(6, allSymbols.size());
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/MainClass.java").toUri().toString();
|
||||
@@ -169,20 +152,15 @@ public class SpringIndexerTest {
|
||||
assertTrue(containsSymbol(allSymbols, "@/classlevel/mapping-subpackage", docUri, 7, 1, 7, 38));
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testNewDocumentCreated() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
|
||||
String createdDocURI = directory.toPath().resolve("src/main/java/org/test/CreatedClass.java").toUri().toString();
|
||||
|
||||
// check for document to not be created yet
|
||||
List<? extends SymbolInformation> symbols = indexer().getSymbols(createdDocURI);
|
||||
List<? extends SymbolInformation> symbols = indexer.getSymbols(createdDocURI);
|
||||
assertNull(symbols);
|
||||
|
||||
List<? extends SymbolInformation> allSymbols = indexer().getAllSymbols("");
|
||||
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("");
|
||||
assertEquals(6, allSymbols.size());
|
||||
|
||||
try {
|
||||
@@ -206,17 +184,17 @@ public class SpringIndexerTest {
|
||||
"}\n" +
|
||||
"";
|
||||
FileUtils.write(new File(new URI(createdDocURI)), content);
|
||||
CompletableFuture<Void> createFuture = indexer().createDocument(createdDocURI);
|
||||
CompletableFuture<Void> createFuture = indexer.createDocument(createdDocURI);
|
||||
createFuture.get(5, TimeUnit.SECONDS);
|
||||
|
||||
// check for updated index per document
|
||||
symbols = indexer().getSymbols(createdDocURI);
|
||||
symbols = indexer.getSymbols(createdDocURI);
|
||||
assertEquals(2, symbols.size());
|
||||
assertTrue(containsSymbol(symbols, "@/created-mapping1", createdDocURI, 6, 1, 6, 36));
|
||||
assertTrue(containsSymbol(symbols, "@/created-mapping2", createdDocURI, 11, 1, 11, 36));
|
||||
|
||||
// check for updated index in all symbols
|
||||
allSymbols = indexer().getAllSymbols("");
|
||||
allSymbols = indexer.getAllSymbols("");
|
||||
assertEquals(8, allSymbols.size());
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/MainClass.java").toUri().toString();
|
||||
@@ -241,21 +219,18 @@ public class SpringIndexerTest {
|
||||
|
||||
@Test
|
||||
public void testRemoveSymbolsFromDeletedDocument() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
|
||||
// update document and update index
|
||||
String deletedDocURI = directory.toPath().resolve("src/main/java/org/test/SimpleMappingClass.java").toUri().toString();
|
||||
|
||||
assertFalse(indexer().getSymbols(deletedDocURI).isEmpty()); //We have symbols before deletion?
|
||||
CompletableFuture<Void> deleteFuture = indexer().deleteDocument(deletedDocURI);
|
||||
assertFalse(indexer.getSymbols(deletedDocURI).isEmpty()); //We have symbols before deletion?
|
||||
CompletableFuture<Void> deleteFuture = indexer.deleteDocument(deletedDocURI);
|
||||
deleteFuture.get(5, TimeUnit.HOURS);
|
||||
|
||||
// check for updated index per document
|
||||
Assert.noElements(indexer().getSymbols(deletedDocURI));
|
||||
Assert.noElements(indexer.getSymbols(deletedDocURI));
|
||||
|
||||
// check for updated index in all symbols
|
||||
List<? extends SymbolInformation> allSymbols = indexer().getAllSymbols("");
|
||||
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("");
|
||||
assertEquals(4, allSymbols.size());
|
||||
|
||||
String docUri = directory.toPath().resolve("src/main/java/org/test/MainClass.java").toUri().toString();
|
||||
@@ -269,11 +244,7 @@ public class SpringIndexerTest {
|
||||
|
||||
@Test
|
||||
public void testFilterSymbolsUsingQueryString() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
|
||||
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
|
||||
List<? extends SymbolInformation> allSymbols = indexer().getAllSymbols("mapp");
|
||||
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("mapp");
|
||||
|
||||
assertEquals(6, allSymbols.size());
|
||||
|
||||
@@ -291,11 +262,7 @@ public class SpringIndexerTest {
|
||||
|
||||
@Test
|
||||
public void testFilterSymbolsUsingQueryStringSplittedResult() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
|
||||
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
|
||||
List<? extends SymbolInformation> allSymbols = indexer().getAllSymbols("@/foo-root-mapping");
|
||||
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("@/foo-root-mapping");
|
||||
|
||||
assertEquals(1, allSymbols.size());
|
||||
|
||||
@@ -306,11 +273,7 @@ public class SpringIndexerTest {
|
||||
|
||||
@Test
|
||||
public void testFilterSymbolsUsingQueryStringFullSymbolString() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
|
||||
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
|
||||
List<? extends SymbolInformation> allSymbols = indexer().getAllSymbols("@/foo-root-mapping/embedded-foo-mapping-with-root");
|
||||
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("@/foo-root-mapping/embedded-foo-mapping-with-root");
|
||||
|
||||
assertEquals(1, allSymbols.size());
|
||||
|
||||
@@ -350,33 +313,16 @@ public class SpringIndexerTest {
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRefreshOnProjectChange() throws Exception {
|
||||
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
|
||||
|
||||
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
|
||||
|
||||
List<? extends SymbolInformation> allSymbols = indexer().getAllSymbols("");
|
||||
public void testDeleteProject() throws Exception {
|
||||
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("");
|
||||
assertEquals(6, allSymbols.size());
|
||||
|
||||
// Delete some symbols
|
||||
String deletedDocURI = directory.toPath().resolve("src/main/java/org/test/SimpleMappingClass.java").toUri().toString();
|
||||
CompletableFuture<Void> deleteFuture = indexer().deleteDocument(deletedDocURI);
|
||||
deleteFuture.get(5, TimeUnit.SECONDS);
|
||||
// check for updated index in all symbols
|
||||
allSymbols = indexer().getAllSymbols("");
|
||||
assertEquals(4, allSymbols.size());
|
||||
CompletableFuture<Void> deleteProject = indexer.deleteProject(project);
|
||||
deleteProject.get(5, TimeUnit.SECONDS);
|
||||
|
||||
|
||||
File pomFile = directory.toPath().resolve(MavenCore.POM_XML).toFile();
|
||||
assertFalse(indexer().isInitializing());
|
||||
harness.changeFile(pomFile.toURI().toString());
|
||||
|
||||
// Everything is expected to be re-indexed hence "fake" deleted document should be indexed now
|
||||
allSymbols = indexer().getAllSymbols("");
|
||||
assertFalse(indexer().isInitializing());
|
||||
assertEquals(6, allSymbols.size());
|
||||
assertEquals(0, allSymbols.size());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@ const JAVA_LANGUAGE_ID = "java";
|
||||
/** Called when extension is activated */
|
||||
export function activate(context: VSCode.ExtensionContext) {
|
||||
let options : commons.ActivatorOptions = {
|
||||
DEBUG: false,
|
||||
CONNECT_TO_LS: false,
|
||||
DEBUG: true,
|
||||
CONNECT_TO_LS: true,
|
||||
extensionId: 'vscode-spring-boot',
|
||||
preferJdk: true,
|
||||
checkjvm: (context: VSCode.ExtensionContext, jvm: commons.JVM) => {
|
||||
|
||||
Reference in New Issue
Block a user