Wait for document symbols in sync fashion

This commit is contained in:
BoykoAlex
2021-05-12 23:21:55 -04:00
parent 5a4eea4d2b
commit 4f007de1bd
8 changed files with 185 additions and 28 deletions

View File

@@ -11,6 +11,7 @@
package org.springframework.ide.vscode.boot.app;
import java.io.File;
import java.util.Optional;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Qualifier;
@@ -54,7 +55,9 @@ import org.springframework.ide.vscode.boot.xml.SpringXMLCompletionEngine;
import org.springframework.ide.vscode.boot.yaml.completions.ApplicationYamlAssistContext;
import org.springframework.ide.vscode.boot.yaml.completions.SpringYamlCompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.LanguageServerRunner;
import org.springframework.ide.vscode.commons.languageserver.java.FutureProjectFinder;
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.util.DocumentEventListenerManager;
import org.springframework.ide.vscode.commons.languageserver.util.LspClient;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
@@ -225,4 +228,8 @@ public class BootLanguageServerBootApp {
new SampleProjectsProvider()
));
}
@Bean FutureProjectFinder futureProjectFinder(JavaProjectFinder projectFinder, Optional<ProjectObserver> projectObserver) {
return new FutureProjectFinder(projectFinder, projectObserver);
}
}

View File

@@ -28,6 +28,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -54,6 +55,7 @@ import org.springframework.ide.vscode.boot.java.utils.SymbolHandler;
import org.springframework.ide.vscode.boot.java.utils.SymbolIndexConfig;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.java.SpringProjectUtil;
import org.springframework.ide.vscode.commons.languageserver.java.FutureProjectFinder;
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;
@@ -78,6 +80,7 @@ public class SpringSymbolIndex implements InitializingBean {
@Autowired BootLanguageServerParams params;
@Autowired AnnotationHierarchyAwareLookup<SymbolProvider> specificProviders;
@Autowired SymbolCache cache;
@Autowired FutureProjectFinder futureProjectFinder;
private static final String QUERY_PARAM_LOCATION_PREFIX = "locationPrefix:";
private static final int MAX_NUMBER_OF_SYMBOLS_IN_RESPONSE = 50;
@@ -120,7 +123,10 @@ public class SpringSymbolIndex implements InitializingBean {
private String watchXMLDeleteRegistration;
private String watchXMLCreatedRegistration;
private String watchXMLChangedRegistration;
// Futures resolved when project is initialized/indexed
private Map<URI, CompletableFuture<Void>> initializedProjects = new HashMap<>();
private SimpleWorkspaceService getWorkspaceService() {
return server.getServer().getWorkspaceService();
@@ -273,8 +279,16 @@ public class SpringSymbolIndex implements InitializingBean {
log.error("{}", e);
}
}
public CompletableFuture<Void> initializeProject(IJavaProject project) {
CompletableFuture<Void> cf = _initializeProject(project);
cf.thenAccept( f -> {
projectInitializedFuture(project).complete(null);
});
return cf;
}
private CompletableFuture<Void> _initializeProject(IJavaProject project) {
try {
if (SpringProjectUtil.isBootProject(project) || SpringProjectUtil.isSpringProject(project)) {
if (project.getElementName() == null) {
@@ -291,7 +305,7 @@ public class SpringSymbolIndex implements InitializingBean {
InitializeProject initializeItem = new InitializeProject(project, this.indexers[i]);
futures[i] = CompletableFuture.runAsync(initializeItem, this.updateQueue);
}
return CompletableFuture.allOf(futures);
}
} else {
@@ -520,21 +534,35 @@ public class SpringSymbolIndex implements InitializingBean {
.filter(filter)
.map(enhanced -> enhanced.getSymbol());
}
public List<? extends SymbolInformation> getSymbols(String docURI) {
List<EnhancedSymbolInformation> docSymbols = this.symbolsByDoc.get(docURI);
if (docSymbols != null) {
synchronized(docSymbols) {
ImmutableList.Builder<SymbolInformation> builder = ImmutableList.builder();
for (EnhancedSymbolInformation enhanced : docSymbols) {
builder.add(enhanced.getSymbol());
}
return builder.build();
}
synchronized private CompletableFuture<Void> projectInitializedFuture(IJavaProject project) {
if (project == null) {
return CompletableFuture.completedFuture(null);
} else {
URI uri = project.getLocationUri();
return initializedProjects.computeIfAbsent(uri, u -> new CompletableFuture<Void>());
}
else {
}
public List<? extends SymbolInformation> getSymbols(String docURI) {
try {
CompletableFuture<Void> projectInitialized = futureProjectFinder.findFuture(URI.create(docURI)).thenCompose(project -> projectInitializedFuture(project));
projectInitialized.get(60, TimeUnit.SECONDS);
List<EnhancedSymbolInformation> docSymbols = this.symbolsByDoc.get(docURI);
if (docSymbols != null) {
synchronized (docSymbols) {
ImmutableList.Builder<SymbolInformation> builder = ImmutableList.builder();
for (EnhancedSymbolInformation enhanced : docSymbols) {
builder.add(enhanced.getSymbol());
}
return builder.build();
}
}
} catch (Exception e) {
log.warn("", e);
return Collections.emptyList();
}
return Collections.emptyList();
}
public List<SymbolAddOnInformation> getAllAdditionalInformation(Predicate<SymbolAddOnInformation> filter) {

View File

@@ -20,20 +20,30 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp;
import org.springframework.ide.vscode.boot.bootiful.SourceLinksTestConf;
import org.springframework.ide.vscode.boot.java.links.SourceLinks;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.languageserver.starter.LanguageServerAutoConf;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author Alex Boyko
*/
@RunWith(SpringRunner.class)
@BootLanguageServerTest
@Import(SourceLinksTestConf.class)
//@BootLanguageServerTest
@OverrideAutoConfiguration(enabled=false)
@Import({LanguageServerAutoConf.class, SourceLinksTestConf.class})
@SpringBootTest(classes={
BootLanguageServerBootApp.class
})
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
public class AdvancedSourceLinksTest {
private ProjectsHarness projects = ProjectsHarness.INSTANCE;

View File

@@ -25,24 +25,34 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp;
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.bootiful.XmlBeansTestConf;
import org.springframework.ide.vscode.boot.java.beans.BeansSymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation;
import org.springframework.ide.vscode.boot.java.utils.SymbolIndexConfig;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.languageserver.starter.LanguageServerAutoConf;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.junit4.SpringRunner;
/**
* @author Martin Lippert
*/
@RunWith(SpringRunner.class)
@BootLanguageServerTest
@Import(XmlBeansTestConf.class)
//@BootLanguageServerTest
@OverrideAutoConfiguration(enabled=false)
@Import({LanguageServerAutoConf.class, XmlBeansTestConf.class})
@SpringBootTest(classes={
BootLanguageServerBootApp.class
})
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
public class SpringIndexerXMLProjectTest {
@Autowired private BootLanguageServerHarness harness;

View File

@@ -27,17 +27,22 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp;
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.bootiful.XmlBeansTestConf;
import org.springframework.ide.vscode.boot.test.DefinitionLinkAsserts;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.commons.util.UriUtil;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.languageserver.starter.LanguageServerAutoConf;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.junit4.SpringRunner;
import com.google.gson.Gson;
@@ -46,8 +51,13 @@ import com.google.gson.Gson;
* @author Alex Boyko
*/
@RunWith(SpringRunner.class)
@BootLanguageServerTest
@Import(XmlBeansTestConf.class)
//@BootLanguageServerTest
@OverrideAutoConfiguration(enabled=false)
@Import({LanguageServerAutoConf.class, XmlBeansTestConf.class})
@SpringBootTest(classes={
BootLanguageServerBootApp.class
})
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
public class XmlBeansHyperlinkTest {
@Autowired private BootLanguageServerHarness harness;

View File

@@ -31,8 +31,10 @@ import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.OverrideAutoConfiguration;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.context.annotation.Import;
import org.springframework.ide.vscode.boot.bootiful.BootLanguageServerTest;
import org.springframework.ide.vscode.boot.app.BootLanguageServerBootApp;
import org.springframework.ide.vscode.boot.bootiful.XmlBeansTestConf;
import org.springframework.ide.vscode.boot.xml.SpringXMLReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
@@ -42,8 +44,11 @@ import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguage
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import org.springframework.ide.vscode.languageserver.starter.LanguageServerAutoConf;
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.annotation.DirtiesContext.ClassMode;
import org.springframework.test.context.junit4.SpringRunner;
import com.google.gson.Gson;
@@ -52,8 +57,13 @@ import com.google.gson.Gson;
* @author Martin Lippert
*/
@RunWith(SpringRunner.class)
@BootLanguageServerTest
@Import(XmlBeansTestConf.class)
//@BootLanguageServerTest
@OverrideAutoConfiguration(enabled=false)
@Import({LanguageServerAutoConf.class, XmlBeansTestConf.class})
@SpringBootTest(classes={
BootLanguageServerBootApp.class
})
@DirtiesContext(classMode=ClassMode.AFTER_EACH_TEST_METHOD)
public class XMLSpelExpressionValidationTest {
@Autowired private BootLanguageServerHarness harness;