[PT-#150740880] File listener and project listeners mechanics

Refactor project finder into project manager

Update annotation index based on project changes

Missing comments
This commit is contained in:
BoykoAlex
2017-10-10 12:15:55 -04:00
parent 825db31d88
commit 423c6bcaef
40 changed files with 1177 additions and 359 deletions

View File

@@ -42,22 +42,15 @@ import org.springframework.ide.vscode.boot.java.value.ValueCompletionProcessor;
import org.springframework.ide.vscode.boot.java.value.ValueHoverProvider;
import org.springframework.ide.vscode.boot.java.value.ValuePropertyReferencesProvider;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.commons.gradle.GradleCore;
import org.springframework.ide.vscode.commons.gradle.GradleProjectFinderStrategy;
import org.springframework.ide.vscode.commons.languageserver.HighlightParams;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.java.DefaultJavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.util.ReferencesHandler;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleWorkspaceService;
import org.springframework.ide.vscode.commons.maven.JavaProjectWithClasspathFileFinderStrategy;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.MavenProjectFinderStrategy;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
import com.google.common.collect.ImmutableList;
@@ -71,19 +64,13 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
public static final String LANGUAGE_SERVER_PROCESS_PROPERTY = "spring-boot-language-server";
public static final JavaProjectFinder DEFAULT_PROJECT_FINDER = new DefaultJavaProjectFinder(new IJavaProjectFinderStrategy[] {
new MavenProjectFinderStrategy(MavenCore.getDefault()),
new GradleProjectFinderStrategy(GradleCore.getDefault()),
new JavaProjectWithClasspathFileFinderStrategy()
});
private final VscodeCompletionEngineAdapter completionEngine;
private final SpringIndexer indexer;
private final SpringLiveHoverWatchdog liveHoverWatchdog;
private final WordHighlighter testHightlighter = null; //new WordHighlighter("foo");
public BootJavaLanguageServer(JavaProjectFinder javaProjectFinder, SpringPropertyIndexProvider indexProvider) {
public BootJavaLanguageServer(JavaProjectManager javaProjectManager, SpringPropertyIndexProvider indexProvider) {
super("vscode-boot-java");
System.setProperty(LANGUAGE_SERVER_PROCESS_PROPERTY, LANGUAGE_SERVER_PROCESS_PROPERTY);
@@ -97,13 +84,13 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
validateWith(doc.getId(), reconcileEngine);
});
ICompletionEngine bootCompletionEngine = createCompletionEngine(javaProjectFinder, indexProvider);
ICompletionEngine bootCompletionEngine = createCompletionEngine(javaProjectManager, indexProvider);
completionEngine = createCompletionEngineAdapter(this, bootCompletionEngine);
completionEngine.setMaxCompletions(100);
documents.onCompletion(completionEngine::getCompletions);
documents.onCompletionResolve(completionEngine::resolveCompletion);
BootJavaHoverProvider hoverInfoProvider = createHoverHandler(javaProjectFinder);
BootJavaHoverProvider hoverInfoProvider = createHoverHandler(javaProjectManager);
documents.onHover(hoverInfoProvider);
liveHoverWatchdog = new SpringLiveHoverWatchdog(this, hoverInfoProvider);
@@ -117,10 +104,10 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
}
});
ReferencesHandler referencesHandler = createReferenceHandler(this, javaProjectFinder);
ReferencesHandler referencesHandler = createReferenceHandler(this, javaProjectManager);
documents.onReferences(referencesHandler);
indexer = createAnnotationIndexer(this, javaProjectFinder);
indexer = createAnnotationIndexer(this, javaProjectManager);
documents.onDidSave(params -> {
String docURI = params.getDocument().getId().getUri();
String content = params.getDocument().get();
@@ -130,7 +117,7 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
documents.onDocumentSymbol(new BootJavaDocumentSymbolHandler(indexer));
workspaceService.onWorkspaceSymbol(new BootJavaWorkspaceSymbolHandler(indexer));
BootJavaCodeLensEngine codeLensHandler = createCodeLensEngine(this, javaProjectFinder);
BootJavaCodeLensEngine codeLensHandler = createCodeLensEngine(this, javaProjectManager);
documents.onCodeLens(codeLensHandler::createCodeLenses);
documents.onCodeLensResolve(codeLensHandler::resolveCodeLens);
@@ -167,7 +154,7 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
return super.shutdown();
}
protected ICompletionEngine createCompletionEngine(JavaProjectFinder javaProjectFinder, SpringPropertyIndexProvider indexProvider) {
protected ICompletionEngine createCompletionEngine(JavaProjectManager javaProjectManager, SpringPropertyIndexProvider indexProvider) {
Map<String, CompletionProvider> providers = new HashMap<>();
providers.put(org.springframework.ide.vscode.boot.java.scope.Constants.SPRING_SCOPE, new ScopeCompletionProcessor());
providers.put(org.springframework.ide.vscode.boot.java.value.Constants.SPRING_VALUE, new ValueCompletionProcessor(indexProvider));
@@ -231,10 +218,10 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
" return ${entity};\n" +
"}"
));
return new BootJavaCompletionEngine(javaProjectFinder, providers, snippetManager);
return new BootJavaCompletionEngine(javaProjectManager, providers, snippetManager);
}
protected BootJavaHoverProvider createHoverHandler(JavaProjectFinder javaProjectFinder) {
protected BootJavaHoverProvider createHoverHandler(JavaProjectManager javaProjectFinder) {
HashMap<String, HoverProvider> providers = new HashMap<>();
providers.put(org.springframework.ide.vscode.boot.java.value.Constants.SPRING_VALUE, new ValueHoverProvider());
providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_REQUEST_MAPPING, new RequestMappingHoverProvider());
@@ -247,7 +234,7 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
return new BootJavaHoverProvider(this, javaProjectFinder, providers);
}
protected SpringIndexer createAnnotationIndexer(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
protected SpringIndexer createAnnotationIndexer(SimpleLanguageServer server, JavaProjectManager projectManager) {
HashMap<String, SymbolProvider> providers = new HashMap<>();
providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_REQUEST_MAPPING, new RequestMappingSymbolProvider());
providers.put(org.springframework.ide.vscode.boot.java.requestmapping.Constants.SPRING_GET_MAPPING, new RequestMappingSymbolProvider());
@@ -259,17 +246,17 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
providers.put(org.springframework.ide.vscode.boot.java.beans.Constants.SPRING_BEAN, new BeansSymbolProvider());
providers.put(org.springframework.ide.vscode.boot.java.beans.Constants.SPRING_COMPONENT, new ComponentSymbolProvider());
return new SpringIndexer(this, projectFinder, providers);
return new SpringIndexer(this, projectManager, providers);
}
protected ReferencesHandler createReferenceHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
protected ReferencesHandler createReferenceHandler(SimpleLanguageServer server, JavaProjectManager projectManager) {
Map<String, ReferenceProvider> providers = new HashMap<>();
providers.put(org.springframework.ide.vscode.boot.java.value.Constants.SPRING_VALUE, new ValuePropertyReferencesProvider(server));
return new BootJavaReferencesHandler(server, projectFinder, providers);
return new BootJavaReferencesHandler(server, projectManager, providers);
}
protected BootJavaCodeLensEngine createCodeLensEngine(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
protected BootJavaCodeLensEngine createCodeLensEngine(SimpleLanguageServer server, JavaProjectManager projectFinder) {
return new BootJavaCodeLensEngine(server, projectFinder);
}

View File

@@ -13,22 +13,33 @@ package org.springframework.ide.vscode.boot.java;
import java.io.IOException;
import org.springframework.ide.vscode.boot.metadata.DefaultSpringPropertyIndexProvider;
import org.springframework.ide.vscode.commons.gradle.GradleCore;
import org.springframework.ide.vscode.commons.gradle.GradleProjectManager;
import org.springframework.ide.vscode.commons.languageserver.LaunguageServerApp;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.CompositeJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.java.MavenProjectManager;
import org.springframework.ide.vscode.commons.maven.java.classpathfile.JavaProjectWithClasspathFileManager;
/**
* Starts up Language Server process
*
*
* @author Martin Lippert
*/
public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
LaunguageServerApp.start(() -> {
JavaProjectFinder javaProjectFinder = BootJavaLanguageServer.DEFAULT_PROJECT_FINDER;
DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder);
SimpleLanguageServer server = new BootJavaLanguageServer(javaProjectFinder, indexProvider);
CompositeJavaProjectManager javaProjectManager = new CompositeJavaProjectManager(new JavaProjectManager[] {
new MavenProjectManager(MavenCore.getDefault()),
new GradleProjectManager(GradleCore.getDefault()),
new JavaProjectWithClasspathFileManager()
});
DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectManager);
SimpleLanguageServer server = new BootJavaLanguageServer(javaProjectManager, indexProvider);
javaProjectManager.setFileObserver(server.getWorkspaceService());
return server;
});
}

View File

@@ -19,7 +19,7 @@ import org.eclipse.lsp4j.CodeLensParams;
import org.eclipse.lsp4j.Command;
import org.eclipse.lsp4j.Position;
import org.eclipse.lsp4j.Range;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -30,9 +30,9 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class BootJavaCodeLensEngine {
private final SimpleLanguageServer server;
private final JavaProjectFinder projectFinder;
private final JavaProjectManager projectFinder;
public BootJavaCodeLensEngine(SimpleLanguageServer server, JavaProjectFinder projectFinder) {
public BootJavaCodeLensEngine(SimpleLanguageServer server, JavaProjectManager projectFinder) {
this.server = server;
this.projectFinder = projectFinder;
}

View File

@@ -30,7 +30,7 @@ import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.util.text.IDocument;
/**
@@ -38,12 +38,12 @@ import org.springframework.ide.vscode.commons.util.text.IDocument;
*/
public class BootJavaCompletionEngine implements ICompletionEngine {
private JavaProjectFinder projectFinder;
private JavaProjectManager projectManager;
private Map<String, CompletionProvider> completionProviders;
private JavaSnippetManager snippets;
public BootJavaCompletionEngine(JavaProjectFinder projectFinder, Map<String, CompletionProvider> specificProviders, JavaSnippetManager snippets) {
this.projectFinder = projectFinder;
public BootJavaCompletionEngine(JavaProjectManager projectManager, Map<String, CompletionProvider> specificProviders, JavaSnippetManager snippets) {
this.projectManager = projectManager;
this.completionProviders = specificProviders;
this.snippets = snippets;
}
@@ -108,7 +108,7 @@ public class BootJavaCompletionEngine implements ICompletionEngine {
}
private String[] getClasspathEntries(IDocument doc) throws Exception {
IJavaProject project = this.projectFinder.find(doc);
IJavaProject project = this.projectManager.find(doc);
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries();
return classpathEntries

View File

@@ -36,7 +36,7 @@ import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
@@ -49,11 +49,11 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
*/
public class BootJavaHoverProvider implements HoverHandler {
private JavaProjectFinder projectFinder;
private JavaProjectManager projectFinder;
private SimpleLanguageServer server;
private Map<String, HoverProvider> hoverProviders;
public BootJavaHoverProvider(SimpleLanguageServer server, JavaProjectFinder projectFinder, Map<String, HoverProvider> specificProviders) {
public BootJavaHoverProvider(SimpleLanguageServer server, JavaProjectManager projectFinder, Map<String, HoverProvider> specificProviders) {
this.server = server;
this.projectFinder = projectFinder;
this.hoverProviders = specificProviders;

View File

@@ -28,7 +28,7 @@ import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.ReferenceParams;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.util.ReferencesHandler;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
@@ -40,13 +40,13 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
*/
public class BootJavaReferencesHandler implements ReferencesHandler {
private JavaProjectFinder projectFinder;
private JavaProjectManager projectManager;
private SimpleLanguageServer server;
private Map<String, ReferenceProvider> referenceProviders;
public BootJavaReferencesHandler(SimpleLanguageServer server, JavaProjectFinder projectFinder, Map<String, ReferenceProvider> specificProviders) {
public BootJavaReferencesHandler(SimpleLanguageServer server, JavaProjectManager projectManager, Map<String, ReferenceProvider> specificProviders) {
this.server = server;
this.projectFinder = projectFinder;
this.projectManager = projectManager;
this.referenceProviders = specificProviders;
}
@@ -124,7 +124,7 @@ public class BootJavaReferencesHandler implements ReferencesHandler {
}
private String[] getClasspathEntries(IDocument doc) throws Exception {
IJavaProject project = this.projectFinder.find(doc);
IJavaProject project = this.projectManager.find(doc);
IClasspath classpath = project.getClasspath();
Stream<Path> classpathEntries = classpath.getClasspathEntries();
return classpathEntries

View File

@@ -25,6 +25,7 @@ import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -46,7 +47,8 @@ import org.eclipse.lsp4j.SymbolKind;
import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager.Listener;
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;
@@ -57,7 +59,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
public class SpringIndexer {
private SimpleLanguageServer server;
private JavaProjectFinder projectFinder;
private JavaProjectManager projectManager;
private Map<String, SymbolProvider> symbolProviders;
private List<SymbolInformation> symbols;
@@ -65,38 +67,47 @@ public class SpringIndexer {
private CompletableFuture<Void> initializeTask;
private final Thread updateWorker;
private final BlockingQueue<UpdateItem> updateQueue;
private Thread updateWorker;
private BlockingQueue<UpdateItem> updateQueue;
public SpringIndexer(SimpleLanguageServer server, JavaProjectFinder projectFinder, Map<String, SymbolProvider> specificProviders) {
private AtomicBoolean initializing = new AtomicBoolean(false);
private final Listener projectListener = new Listener() {
@Override
public void created(IJavaProject project) {
refresh();
}
@Override
public void changed(IJavaProject project) {
refresh();
}
@Override
public void deleted(IJavaProject project) {
refresh();
}
};
public SpringIndexer(SimpleLanguageServer server, JavaProjectManager projectManager, Map<String, SymbolProvider> specificProviders) {
this.server = server;
this.projectFinder = projectFinder;
this.projectManager = projectManager;
this.symbolProviders = specificProviders;
this.symbols = Collections.synchronizedList(new ArrayList<>());
this.symbolsByDoc = new ConcurrentHashMap<>();
this.updateQueue = new LinkedBlockingQueue<>();
this.updateWorker = new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
UpdateItem updateItem = updateQueue.take();
scanFile(updateItem.getDocURI(), updateItem.getContent(), updateItem.getClasspathEntries());
updateItem.getFuture().complete(null);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}, "Spring Annotation Index Update Worker");
}
public CompletableFuture<Void> initialize(final Path workspaceRoot) {
synchronized(this) {
if (this.initializeTask == null) {
initializing.set(true);
if (projectManager != null) {
projectManager.addListener(projectListener);
}
this.initializeTask = CompletableFuture.runAsync(new Runnable() {
@Override
public void run() {
@@ -104,7 +115,25 @@ public class SpringIndexer {
scanFiles(workspaceRoot.toFile());
System.out.println("initial scan done...!!!");
SpringIndexer.this.updateQueue = new LinkedBlockingQueue<>();
SpringIndexer.this.updateWorker = new Thread(new Runnable() {
@Override
public void run() {
try {
while (true) {
UpdateItem updateItem = updateQueue.take();
scanFile(updateItem.getDocURI(), updateItem.getContent(), updateItem.getClasspathEntries());
updateItem.getFuture().complete(null);
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}, "Spring Annotation Index Update Worker");
updateWorker.start();
initializing.set(false);
}
});
}
@@ -113,15 +142,33 @@ public class SpringIndexer {
}
}
public boolean isInitializing() {
return initializing.get();
}
private void refresh() {
synchronized (this) {
shutdown();
initializeTask = null;
symbols.clear();
symbolsByDoc.clear();
initialize(server.getWorkspaceRoot());
}
}
public void shutdown() {
try {
if (this.initializeTask != null) {
initializeTask.cancel(true);
}
if (updateWorker.isAlive()) {
if (updateWorker != null && updateWorker.isAlive()) {
updateWorker.interrupt();
}
if (projectManager != null) {
projectManager.removeListener(projectListener);
}
}
catch (Exception e) {
e.printStackTrace();
@@ -133,7 +180,7 @@ public class SpringIndexer {
try {
initializeTask.get();
IJavaProject project = projectFinder.find(new File(new URI(docURI)));
IJavaProject project = projectManager.find(new File(new URI(docURI)));
if (project != null) {
String[] classpathEntries = getClasspathEntries(project);
@@ -216,7 +263,7 @@ public class SpringIndexer {
.filter(path -> path.getFileName().toString().endsWith(".java"))
.filter(Files::isRegularFile)
.map(path -> path.toAbsolutePath().toString())
.collect(Collectors.groupingBy((javaFile) -> projectFinder.find(new File(javaFile))));
.collect(Collectors.groupingBy((javaFile) -> projectManager.find(new File(javaFile))));
System.out.println("scan directory done!!!");

View File

@@ -14,7 +14,7 @@ package org.springframework.ide.vscode.boot.metadata;
import org.springframework.boot.configurationmetadata.ConfigurationMetadataProperty;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@@ -22,19 +22,19 @@ public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexPr
private static final FuzzyMap<ConfigurationMetadataProperty> EMPTY_INDEX = new SpringPropertyIndex(null);
private JavaProjectFinder javaProjectFinder;
private JavaProjectManager javaProjectManager;
private SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager();
private ProgressService progressService = (id, msg) -> {
/* ignore */ };
public DefaultSpringPropertyIndexProvider(JavaProjectFinder javaProjectFinder) {
this.javaProjectFinder = javaProjectFinder;
public DefaultSpringPropertyIndexProvider(JavaProjectManager javaProjectManager) {
this.javaProjectManager = javaProjectManager;
}
@Override
public FuzzyMap<ConfigurationMetadataProperty> getIndex(IDocument doc) {
IJavaProject jp = javaProjectFinder.find(doc);
IJavaProject jp = javaProjectManager.find(doc);
if (jp != null) {
return indexManager.get(jp, progressService);
}

View File

@@ -24,7 +24,8 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.AbstractJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
@@ -37,7 +38,7 @@ import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
*/
public class ScopeCompletionTest {
protected final JavaProjectFinder javaProjectFinder = new JavaProjectFinder() {
protected final JavaProjectManager javaProjectFinder = new AbstractJavaProjectManager() {
@Override
public boolean isProjectRoot(File file) {
return false;

View File

@@ -25,7 +25,8 @@ import org.junit.Test;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
import org.springframework.ide.vscode.boot.java.value.ValueCompletionProcessor;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.AbstractJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.LanguageId;
import org.springframework.ide.vscode.languageserver.testharness.Editor;
@@ -38,7 +39,7 @@ import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
*/
public class ValueCompletionTest {
protected final JavaProjectFinder javaProjectFinder = new JavaProjectFinder() {
protected final JavaProjectManager javaProjectFinder = new AbstractJavaProjectManager() {
@Override
public boolean isProjectRoot(File file) {
return false;

View File

@@ -28,11 +28,10 @@ import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.boot.java.requestmapping.Constants;
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.java.DefaultJavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.CompositeJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.MavenProjectFinderStrategy;
import org.springframework.ide.vscode.commons.maven.java.MavenProjectManager;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
@@ -43,7 +42,7 @@ import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
public class RequestMappingSymbolProviderTest {
private Map<String, SymbolProvider> symbolProviders;
private JavaProjectFinder projectFinder;
private JavaProjectManager projectManager;
private LanguageServerHarness<BootJavaLanguageServer> harness;
private PropertyIndexHarness indexHarness;
@@ -52,13 +51,13 @@ public class RequestMappingSymbolProviderTest {
symbolProviders = new HashMap<>();
symbolProviders.put(Constants.SPRING_REQUEST_MAPPING, new RequestMappingSymbolProvider());
projectFinder = new DefaultJavaProjectFinder(new IJavaProjectFinderStrategy[] {new MavenProjectFinderStrategy(MavenCore.getDefault())});
projectManager = new CompositeJavaProjectManager(new JavaProjectManager[] {new MavenProjectManager(MavenCore.getDefault())});
indexHarness = new PropertyIndexHarness();
harness = new LanguageServerHarness<BootJavaLanguageServer>(new Callable<BootJavaLanguageServer>() {
@Override
public BootJavaLanguageServer call() throws Exception {
BootJavaLanguageServer server = new BootJavaLanguageServer(projectFinder, indexHarness.getIndexProvider());
BootJavaLanguageServer server = new BootJavaLanguageServer(projectManager, indexHarness.getIndexProvider());
return server;
}
}) {
@@ -73,7 +72,7 @@ public class RequestMappingSymbolProviderTest {
public void testSimpleRequestMappingSymbol() throws Exception {
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()));
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI());
indexer.initialize(directory.toPath());
@@ -87,7 +86,7 @@ public class RequestMappingSymbolProviderTest {
public void testParentRequestMappingSymbol() throws Exception {
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI()));
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-request-mapping-symbols/").toURI());
indexer.initialize(directory.toPath());

View File

@@ -29,11 +29,10 @@ import org.springframework.ide.vscode.boot.java.beans.ComponentSymbolProvider;
import org.springframework.ide.vscode.boot.java.beans.Constants;
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.java.DefaultJavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.CompositeJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.MavenProjectFinderStrategy;
import org.springframework.ide.vscode.commons.maven.java.MavenProjectManager;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
@@ -44,7 +43,7 @@ import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
public class SpringIndexerBeansTest {
private Map<String, SymbolProvider> symbolProviders;
private JavaProjectFinder projectFinder;
private JavaProjectManager projectManager;
private LanguageServerHarness<BootJavaLanguageServer> harness;
private PropertyIndexHarness indexHarness;
@@ -54,13 +53,13 @@ public class SpringIndexerBeansTest {
symbolProviders.put(Constants.SPRING_BEAN, new BeansSymbolProvider());
symbolProviders.put(Constants.SPRING_COMPONENT, new ComponentSymbolProvider());
projectFinder = new DefaultJavaProjectFinder(new IJavaProjectFinderStrategy[] {new MavenProjectFinderStrategy(MavenCore.getDefault())});
projectManager = new CompositeJavaProjectManager(new JavaProjectManager[] {new MavenProjectManager(MavenCore.getDefault())});
indexHarness = new PropertyIndexHarness();
harness = new LanguageServerHarness<BootJavaLanguageServer>(new Callable<BootJavaLanguageServer>() {
@Override
public BootJavaLanguageServer call() throws Exception {
BootJavaLanguageServer server = new BootJavaLanguageServer(projectFinder, indexHarness.getIndexProvider());
BootJavaLanguageServer server = new BootJavaLanguageServer(projectManager, indexHarness.getIndexProvider());
return server;
}
}) {
@@ -74,7 +73,7 @@ public class SpringIndexerBeansTest {
@Test
public void testScanSimpleConfigurationClass() throws Exception {
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
indexer.initialize(directory.toPath());
@@ -86,7 +85,7 @@ public class SpringIndexerBeansTest {
@Test
public void testScanSimpleFunctionBean() throws Exception {
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
indexer.initialize(directory.toPath());
@@ -98,7 +97,7 @@ public class SpringIndexerBeansTest {
@Test
public void testScanSimpleComponentClass() throws Exception {
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-beans/").toURI());
indexer.initialize(directory.toPath());

View File

@@ -11,6 +11,7 @@
package org.springframework.ide.vscode.boot.java.utils.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
import java.io.File;
@@ -32,11 +33,11 @@ import org.springframework.ide.vscode.boot.java.handlers.SymbolProvider;
import org.springframework.ide.vscode.boot.java.requestmapping.Constants;
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.java.DefaultJavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.CompositeJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.MavenProjectFinderStrategy;
import org.springframework.ide.vscode.commons.maven.java.MavenProjectManager;
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
import org.springframework.ide.vscode.project.harness.ProjectsHarness;
import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
@@ -47,22 +48,25 @@ import org.springframework.ide.vscode.project.harness.PropertyIndexHarness;
public class SpringIndexerTest {
private Map<String, SymbolProvider> symbolProviders;
private JavaProjectFinder projectFinder;
private JavaProjectManager projectManager;
private LanguageServerHarness<BootJavaLanguageServer> harness;
private PropertyIndexHarness indexHarness;
private BasicFileObserver fileObserver;
@Before
public void setup() throws Exception {
symbolProviders = new HashMap<>();
symbolProviders.put(Constants.SPRING_REQUEST_MAPPING, new RequestMappingSymbolProvider());
projectFinder = new DefaultJavaProjectFinder(new IJavaProjectFinderStrategy[] {new MavenProjectFinderStrategy(MavenCore.getDefault())});
projectManager = new CompositeJavaProjectManager(new JavaProjectManager[] {new MavenProjectManager(MavenCore.getDefault())});
fileObserver = new BasicFileObserver();
projectManager.setFileObserver(fileObserver);
indexHarness = new PropertyIndexHarness();
harness = new LanguageServerHarness<BootJavaLanguageServer>(new Callable<BootJavaLanguageServer>() {
@Override
public BootJavaLanguageServer call() throws Exception {
BootJavaLanguageServer server = new BootJavaLanguageServer(projectFinder, indexHarness.getIndexProvider());
BootJavaLanguageServer server = new BootJavaLanguageServer(projectManager, indexHarness.getIndexProvider());
return server;
}
}) {
@@ -77,7 +81,7 @@ public class SpringIndexerTest {
public void testScanningAllAnnotationsSimpleProjectUpfront() throws Exception {
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
indexer.initialize(directory.toPath());
@@ -101,7 +105,7 @@ public class SpringIndexerTest {
public void testRetrievingSymbolsPerDocument() throws Exception {
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
indexer.initialize(directory.toPath());
@@ -128,7 +132,7 @@ public class SpringIndexerTest {
public void testScanningAllAnnotationsMultiModuleProjectUpfront() throws Exception {
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/").toURI()));
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/").toURI());
indexer.initialize(directory.toPath());
@@ -153,7 +157,7 @@ public class SpringIndexerTest {
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
// create initial index content
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
indexer.initialize(directory.toPath());
@@ -190,7 +194,7 @@ public class SpringIndexerTest {
public void testFilterSymbolsUsingQueryString() throws Exception {
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
indexer.initialize(directory.toPath());
@@ -212,7 +216,7 @@ public class SpringIndexerTest {
public void testFilterSymbolsUsingQueryStringSplittedResult() throws Exception {
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
indexer.initialize(directory.toPath());
@@ -230,7 +234,7 @@ public class SpringIndexerTest {
public void testFilterSymbolsUsingQueryStringFullSymbolString() throws Exception {
harness.intialize(new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI()));
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectFinder, symbolProviders);
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
indexer.initialize(directory.toPath());
@@ -260,4 +264,27 @@ 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()));
SpringIndexer indexer = new SpringIndexer(harness.getServer(), projectManager, symbolProviders);
File directory = new File(ProjectsHarness.class.getResource("/test-projects/test-annotation-indexing-parent/test-annotation-indexing/").toURI());
indexer.initialize(directory.toPath()).get();
List<? extends SymbolInformation> allSymbols = indexer.getAllSymbols("");
assertEquals(8, allSymbols.size());
File pomFile = directory.toPath().resolve(MavenCore.POM_XML).toFile();
assertFalse(indexer.isInitializing());
fileObserver.notifyFileChanged(pomFile.toURI().toString());
// Refresh in progress
assertTrue(indexer.isInitializing());
allSymbols = indexer.getAllSymbols("");
assertFalse(indexer.isInitializing());
assertEquals(8, allSymbols.size());
}
}

View File

@@ -20,22 +20,15 @@ import org.springframework.ide.vscode.boot.properties.hover.PropertiesHoverInfoP
import org.springframework.ide.vscode.boot.properties.reconcile.SpringPropertiesReconcileEngine;
import org.springframework.ide.vscode.boot.yaml.completions.ApplicationYamlAssistContext;
import org.springframework.ide.vscode.boot.yaml.reconcile.ApplicationYamlReconcileEngine;
import org.springframework.ide.vscode.commons.gradle.GradleCore;
import org.springframework.ide.vscode.commons.gradle.GradleProjectFinderStrategy;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.VscodeCompletionEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfoProvider;
import org.springframework.ide.vscode.commons.languageserver.hover.VscodeHoverEngineAdapter;
import org.springframework.ide.vscode.commons.languageserver.hover.VscodeHoverEngineAdapter.HoverType;
import org.springframework.ide.vscode.commons.languageserver.java.DefaultJavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.reconcile.IReconcileEngine;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleTextDocumentService;
import org.springframework.ide.vscode.commons.maven.JavaProjectWithClasspathFileFinderStrategy;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.MavenProjectFinderStrategy;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.TextDocument;
@@ -60,12 +53,6 @@ import com.google.common.collect.ImmutableList;
*/
public class BootPropertiesLanguageServer extends SimpleLanguageServer {
public static final JavaProjectFinder DEFAULT_PROJECT_FINDER = new DefaultJavaProjectFinder(new IJavaProjectFinderStrategy[] {
new MavenProjectFinderStrategy(MavenCore.getDefault()),
new GradleProjectFinderStrategy(GradleCore.getDefault()),
new JavaProjectWithClasspathFileFinderStrategy()
});
private static final String YML = ".yml";
private static final String PROPERTIES = ".properties";
@@ -73,7 +60,7 @@ public class BootPropertiesLanguageServer extends SimpleLanguageServer {
public boolean includeDeindentedProposals() { return false; };
};
// Shared:
private final JavaProjectFinder javaProjectFinder;
private final JavaProjectManager javaProjectManager;
private final SpringPropertyIndexProvider indexProvider;
private final TypeUtilProvider typeUtilProvider;
private final VscodeCompletionEngineAdapter completionEngine;
@@ -88,12 +75,12 @@ public class BootPropertiesLanguageServer extends SimpleLanguageServer {
private final YamlStructureProvider yamlStructureProvider= YamlStructureProvider.DEFAULT;
private YamlAssistContextProvider yamlAssistContextProvider;
public BootPropertiesLanguageServer(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectFinder javaProjectFinder) {
public BootPropertiesLanguageServer(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectManager javaProjectManager) {
super("vscode-boot-properties");
this.indexProvider = indexProvider;
this.typeUtilProvider = typeUtilProvider;
this.javaProjectFinder = javaProjectFinder;
this.completionFactory = new PropertyCompletionFactory(javaProjectFinder);
this.javaProjectManager = javaProjectManager;
this.completionFactory = new PropertyCompletionFactory(javaProjectManager);
this.yamlAssistContextProvider = new YamlAssistContextProvider() {
@Override
public YamlAssistContext getGlobalAssistContext(YamlDocument ydoc) {
@@ -123,7 +110,7 @@ public class BootPropertiesLanguageServer extends SimpleLanguageServer {
}
private ICompletionEngine getCompletionEngine() {
ICompletionEngine propertiesCompletions = new SpringPropertiesCompletionEngine(indexProvider, typeUtilProvider, javaProjectFinder);
ICompletionEngine propertiesCompletions = new SpringPropertiesCompletionEngine(indexProvider, typeUtilProvider, javaProjectManager);
ICompletionEngine yamlCompletions = new YamlCompletionEngine(yamlStructureProvider, yamlAssistContextProvider, COMPLETION_OPTIONS);
return (IDocument document, int offset) -> {
String uri = document.getUri();
@@ -139,7 +126,7 @@ public class BootPropertiesLanguageServer extends SimpleLanguageServer {
}
protected HoverInfoProvider getHoverProvider() {
HoverInfoProvider propertiesHovers = new PropertiesHoverInfoProvider(indexProvider, typeUtilProvider, javaProjectFinder);
HoverInfoProvider propertiesHovers = new PropertiesHoverInfoProvider(indexProvider, typeUtilProvider, javaProjectManager);
HoverInfoProvider ymlHovers = new YamlHoverInfoProvider(parser, yamlStructureProvider, yamlAssistContextProvider);
return (IDocument document, int offset) -> {

View File

@@ -15,9 +15,15 @@ import java.io.IOException;
import org.springframework.ide.vscode.boot.metadata.DefaultSpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtil;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.commons.gradle.GradleCore;
import org.springframework.ide.vscode.commons.gradle.GradleProjectManager;
import org.springframework.ide.vscode.commons.languageserver.LaunguageServerApp;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.CompositeJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.maven.java.MavenProjectManager;
import org.springframework.ide.vscode.commons.maven.java.classpathfile.JavaProjectWithClasspathFileManager;
import org.springframework.ide.vscode.commons.util.text.IDocument;
/**
@@ -31,10 +37,15 @@ public class Main {
public static void main(String[] args) throws IOException, InterruptedException {
LaunguageServerApp.start(() -> {
JavaProjectFinder javaProjectFinder = BootPropertiesLanguageServer.DEFAULT_PROJECT_FINDER;
DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectFinder);
TypeUtilProvider typeUtilProvider = (IDocument doc) -> new TypeUtil(javaProjectFinder.find(doc));
SimpleLanguageServer server = new BootPropertiesLanguageServer(indexProvider, typeUtilProvider, javaProjectFinder);
CompositeJavaProjectManager javaProjectManager = new CompositeJavaProjectManager(new JavaProjectManager[] {
new MavenProjectManager(MavenCore.getDefault()),
new GradleProjectManager(GradleCore.getDefault()),
new JavaProjectWithClasspathFileManager()
});
DefaultSpringPropertyIndexProvider indexProvider = new DefaultSpringPropertyIndexProvider(javaProjectManager);
TypeUtilProvider typeUtilProvider = (IDocument doc) -> new TypeUtil(javaProjectManager.find(doc));
SimpleLanguageServer server = new BootPropertiesLanguageServer(indexProvider, typeUtilProvider, javaProjectManager);
javaProjectManager.setFileObserver(server.getWorkspaceService());
indexProvider.setProgressService(server.getProgressService());
return server;
});

View File

@@ -19,7 +19,7 @@ import org.springframework.ide.vscode.boot.metadata.types.TypedProperty;
import org.springframework.ide.vscode.commons.languageserver.completion.DocumentEdits;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.completion.ScoreableProposal;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.util.FuzzyMap.Match;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@@ -113,9 +113,9 @@ public class PropertyCompletionFactory {
return proposal;
}
private JavaProjectFinder documentContextFinder;
private JavaProjectManager documentContextFinder;
public PropertyCompletionFactory(JavaProjectFinder documentContextFinder) {
public PropertyCompletionFactory(JavaProjectManager documentContextFinder) {
this.documentContextFinder = documentContextFinder;
}

View File

@@ -13,7 +13,7 @@ package org.springframework.ide.vscode.boot.metadata;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.ProgressService;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.util.FuzzyMap;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@@ -21,18 +21,18 @@ public class DefaultSpringPropertyIndexProvider implements SpringPropertyIndexPr
private static final FuzzyMap<PropertyInfo> EMPTY_INDEX = new SpringPropertyIndex(null, null);
private JavaProjectFinder javaProjectFinder;
private JavaProjectManager javaProjectManager;
private SpringPropertiesIndexManager indexManager = new SpringPropertiesIndexManager(ValueProviderRegistry.getDefault());
private ProgressService progressService = (id, msg) -> { /*ignore*/ };
public DefaultSpringPropertyIndexProvider(JavaProjectFinder javaProjectFinder) {
this.javaProjectFinder = javaProjectFinder;
public DefaultSpringPropertyIndexProvider(JavaProjectManager javaProjectManager) {
this.javaProjectManager = javaProjectManager;
}
@Override
public FuzzyMap<PropertyInfo> getIndex(IDocument doc) {
IJavaProject jp = javaProjectFinder.find(doc);
IJavaProject jp = javaProjectManager.find(doc);
if (jp!=null) {
return indexManager.get(jp, progressService);
}

View File

@@ -18,7 +18,7 @@ import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionEngine;
import org.springframework.ide.vscode.commons.languageserver.completion.ICompletionProposal;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.text.IDocument;;
@@ -37,10 +37,10 @@ public class SpringPropertiesCompletionEngine implements ICompletionEngine {
* Constructor used in 'production'. Wires up stuff properly for running inside a normal
* Eclipse runtime.
*/
public SpringPropertiesCompletionEngine(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectFinder projectFinder) {
public SpringPropertiesCompletionEngine(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectManager projectManager) {
this.indexProvider = indexProvider;
this.typeUtilProvider = typeUtilProvider;
this.completionFactory = new PropertyCompletionFactory(projectFinder);
this.completionFactory = new PropertyCompletionFactory(projectManager);
}
/**

View File

@@ -14,7 +14,7 @@ package org.springframework.ide.vscode.boot.properties.hover;
import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.commons.languageserver.hover.HoverInfoProvider;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.util.Renderable;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.text.IRegion;
@@ -25,9 +25,9 @@ public class PropertiesHoverInfoProvider implements HoverInfoProvider {
private SpringPropertyIndexProvider indexProvider;
private TypeUtilProvider typeUtilProvider;
private JavaProjectFinder projectFinder;
private JavaProjectManager projectFinder;
public PropertiesHoverInfoProvider(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectFinder projectFinder) {
public PropertiesHoverInfoProvider(SpringPropertyIndexProvider indexProvider, TypeUtilProvider typeUtilProvider, JavaProjectManager projectFinder) {
this.indexProvider = indexProvider;
this.typeUtilProvider = typeUtilProvider;
this.projectFinder = projectFinder;

View File

@@ -28,7 +28,8 @@ import org.springframework.ide.vscode.boot.metadata.SpringPropertyIndexProvider;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtil;
import org.springframework.ide.vscode.boot.metadata.types.TypeUtilProvider;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.AbstractJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.commons.util.text.IDocument;
@@ -45,7 +46,7 @@ public abstract class AbstractPropsEditorTest {
private ProjectsHarness projects = ProjectsHarness.INSTANCE;
protected PropertyIndexHarness md;
protected final JavaProjectFinder javaProjectFinder = new JavaProjectFinder() {
protected final JavaProjectManager javaProjectFinder = new AbstractJavaProjectManager() {
@Override
public boolean isProjectRoot(File file) {
return false;

View File

@@ -22,7 +22,8 @@ import org.eclipse.lsp4j.TextDocumentSyncKind;
import org.junit.Test;
import org.springframework.ide.vscode.boot.BootPropertiesLanguageServer;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
import org.springframework.ide.vscode.commons.languageserver.java.AbstractJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.languageserver.testharness.LanguageServerHarness;
@@ -40,7 +41,7 @@ public class BootPropertiesLanguageServerTest {
}
private LanguageServerHarness newHarness() throws Exception {
JavaProjectFinder nullJavaProjectFinder = new JavaProjectFinder() {
JavaProjectManager nullJavaProjectFinder = new AbstractJavaProjectManager() {
@Override
public boolean isProjectRoot(File file) {
return false;

View File

@@ -13,6 +13,7 @@ package org.springframework.ide.vscode.commons.gradle;
import java.io.File;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.Log;
/**
* Implementation of Gradle Java project
@@ -32,5 +33,13 @@ public class GradleJavaProject implements IJavaProject {
public GradleProjectClasspath getClasspath() {
return classpath;
}
void update(GradleCore gradle, File projectDir) {
try {
this.classpath = new GradleProjectClasspath(gradle, projectDir);
} catch (GradleException e) {
Log.log(e);
}
}
}

View File

@@ -1,57 +0,0 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.gradle;
import java.io.File;
import java.util.concurrent.ExecutionException;
import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy;
import org.springframework.ide.vscode.commons.util.FileUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
/**
* Tests whether document belongs to a Gradle project
*
* @author Alex Boyko
*
*/
public class GradleProjectFinderStrategy implements IJavaProjectFinderStrategy {
private Cache<File, GradleJavaProject> cache = CacheBuilder.newBuilder().build();
private GradleCore gradle;
public GradleProjectFinderStrategy(GradleCore gradle) {
this.gradle = gradle;
}
@Override
public GradleJavaProject find(File file) throws ExecutionException {
File gradlebuild = FileUtils.findFile(file, GradleCore.GRADLE_BUILD_FILE);
if (gradlebuild != null) {
return cache.get(gradlebuild.getParentFile(), () -> {
System.out.println("create gradle project: " + file.getAbsolutePath());
GradleJavaProject project = new GradleJavaProject(gradle, gradlebuild.getParentFile());
System.out.println("gradle project created");
return project;
});
}
return null;
}
@Override
public boolean isProjectRoot(File file) {
return FileUtils.findFile(file, GradleCore.GRADLE_BUILD_FILE, false) != null;
}
}

View File

@@ -0,0 +1,115 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.gradle;
import java.io.File;
import java.net.URI;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import org.springframework.ide.vscode.commons.languageserver.java.AbstractJavaProjectManager;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.FileObserver.FileListener;
import org.springframework.ide.vscode.commons.util.FileUtils;
import org.springframework.ide.vscode.commons.util.Log;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
/**
* Tests whether document belongs to a Gradle project
*
* @author Alex Boyko
*
*/
public class GradleProjectManager extends AbstractJavaProjectManager {
private Cache<File, GradleJavaProject> cache = CacheBuilder.newBuilder().build();
private GradleCore gradle;
public GradleProjectManager(GradleCore gradle) {
this.gradle = gradle;
}
@Override
public GradleJavaProject find(File file) {
File gradlebuild = FileUtils.findFile(file, GradleCore.GRADLE_BUILD_FILE);
if (gradlebuild != null) {
try {
return cache.get(gradlebuild.getParentFile(), () -> {
System.out.println("create gradle project: " + file.getAbsolutePath());
GradleJavaProject project = new GradleJavaProject(gradle, gradlebuild.getParentFile());
System.out.println("gradle project created");
return project;
});
} catch (ExecutionException e) {
Log.log(e);
return null;
}
}
return null;
}
@Override
public boolean isProjectRoot(File file) {
return FileUtils.findFile(file, GradleCore.GRADLE_BUILD_FILE, false) != null;
}
@Override
public void setFileObserver(FileObserver fileObserver) {
super.setFileObserver(fileObserver);
cache.invalidateAll();
}
@Override
protected FileListener createFileListener() {
return new FileListener() {
private File getProjectFolderFromUri(String uri) {
return Paths.get(URI.create(uri)).toFile().getParentFile();
}
@Override
public void deleted(String uri) {
File gradleProjectFolder = getProjectFolderFromUri(uri);
GradleJavaProject project = cache.getIfPresent(gradleProjectFolder);
if (project != null) {
cache.invalidate(gradleProjectFolder);
notifyProjectDeleted(project);
}
}
@Override
public void created(String uri) {
// Ignore created projects - cache should take care of newly created ones
}
@Override
public void changed(String uri) {
File gradleProjectFolder = getProjectFolderFromUri(uri);
GradleJavaProject project = cache.getIfPresent(gradleProjectFolder);
if (project != null) {
project.update(gradle, gradleProjectFolder);
notifyProjectChanged(project);
}
}
@Override
public boolean accept(String uri) {
return GradleCore.GRADLE_BUILD_FILE.equals(Paths.get(URI.create(uri)).getFileName().toString());
}
};
}
}

View File

@@ -12,8 +12,10 @@ package org.springframework.ide.vscode.commons.gradle;
import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.List;
@@ -21,6 +23,9 @@ import java.util.Set;
import java.util.stream.Collectors;
import org.junit.Test;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager.Listener;
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
/**
* Tests covering Gradle project data
@@ -54,5 +59,40 @@ public class GradleProjectTest {
List<String> resources = project.getClasspath().getClasspathResources().collect(Collectors.toList());
assertArrayEquals(new String[] {"test-resource-1.txt"}, resources.toArray(new String[resources.size()]));
}
@Test
public void testGradleFileChanges() throws Exception {
Path testProjectPath = Paths.get(GradleProjectTest.class.getResource("/empty-gradle-project").toURI());
File gradleFile = testProjectPath.resolve(GradleCore.GRADLE_BUILD_FILE).toFile();
GradleProjectManager manager = new GradleProjectManager(GradleCore.getDefault());
BasicFileObserver fileObserver = new BasicFileObserver();
manager.setFileObserver(fileObserver);
IJavaProject[] projectChanged = new IJavaProject[] { null };
IJavaProject[] projectDeleted = new IJavaProject[] { null };
manager.addListener(new Listener() {
@Override
public void created(IJavaProject project) {}
@Override
public void changed(IJavaProject project) {
projectChanged[0] = project;
}
@Override
public void deleted(IJavaProject project) {
projectDeleted[0] = project;
}
});
// Get the project from cache
GradleJavaProject cachedProject = manager.find(gradleFile);
assertNotNull(cachedProject);
fileObserver.notifyFileChanged(gradleFile.toURI().toString());
assertEquals(cachedProject, projectChanged[0]);
fileObserver.notifyFileDeleted(gradleFile.toURI().toString());
assertEquals(cachedProject, projectDeleted[0]);
}
}

View File

@@ -0,0 +1,109 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.java;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.FileObserver.FileListener;
import org.springframework.ide.vscode.commons.util.text.IDocument;
import org.springframework.ide.vscode.commons.util.ListenerList;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.StringUtil;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
/**
* Base implementation of {@link JavaProjectManager}
*
* @author Alex Boyko
*
*/
public abstract class AbstractJavaProjectManager implements JavaProjectManager {
private ListenerList<Listener> listeners;
private FileObserver fileObserver;
private Supplier<FileListener> fileListener;
public AbstractJavaProjectManager() {
this.fileListener = Suppliers.memoize(() -> createFileListener());
this.listeners = new ListenerList<>();
}
protected FileListener createFileListener() {
return null;
}
@Override
public IJavaProject find(IDocument doc) {
try {
String uriStr = doc.getUri();
if (StringUtil.hasText(uriStr)) {
URI uri = new URI(uriStr);
// TODO: This only work with File uri. Should it work with others
// too?
if (uri.getScheme().equalsIgnoreCase("file")) {
File file = new File(uri).getAbsoluteFile();
return find(file);
}
}
}
catch (URISyntaxException e) {
Log.log(e);
}
return null;
}
@Override
public void setFileObserver(FileObserver fileObserver) {
FileListener listener= fileListener.get();
if (this.fileObserver != null && listener != null) {
this.fileObserver.removeListener(listener);
}
this.fileObserver = fileObserver;
if (this.fileObserver != null && listener != null) {
this.fileObserver.addListener(listener);
}
}
final protected FileObserver getFileObserver() {
return this.fileObserver;
}
@Override
public void addListener(Listener listener) {
listeners.add(listener);
}
@Override
public void removeListener(Listener listener) {
listeners.remove(listener);
}
final protected void notifyProjectCreated(IJavaProject project) {
listeners.forEach(l -> l.created(project));
}
final protected void notifyProjectChanged(IJavaProject project) {
listeners.forEach(l -> l.changed(project));
}
final protected void notifyProjectDeleted(IJavaProject project) {
listeners.forEach(l -> l.deleted(project));
}
}

View File

@@ -1,32 +1,40 @@
/*******************************************************************************
* Copyright (c) 2016, 2017 Pivotal, Inc.
* Copyright (c) 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.java;
import java.io.File;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.Arrays;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.Log;
import org.springframework.ide.vscode.commons.util.StringUtil;
import org.springframework.ide.vscode.commons.util.text.IDocument;
public class DefaultJavaProjectFinder implements JavaProjectFinder {
private final IJavaProjectFinderStrategy[] strategies;
/**
* Composite project manager that acts a single project manager but consissts of many project managers
*
* @author Alex Boyko
*
*/
public class CompositeJavaProjectManager implements JavaProjectManager {
public DefaultJavaProjectFinder(IJavaProjectFinderStrategy[] strategies) {
this.strategies = strategies;
private final JavaProjectManager[] projectManagers;
public CompositeJavaProjectManager(JavaProjectManager[] projectManagers) {
this.projectManagers = projectManagers;
}
@Override
public IJavaProject find(IDocument doc) {
try {
@@ -46,10 +54,10 @@ public class DefaultJavaProjectFinder implements JavaProjectFinder {
}
return null;
}
@Override
public IJavaProject find(File file) {
for (IJavaProjectFinderStrategy strategy : strategies) {
for (JavaProjectManager strategy : projectManagers) {
try {
IJavaProject project = strategy.find(file);
if (project != null) {
@@ -64,7 +72,7 @@ public class DefaultJavaProjectFinder implements JavaProjectFinder {
@Override
public boolean isProjectRoot(File file) {
for (IJavaProjectFinderStrategy strategy : strategies) {
for (JavaProjectManager strategy : projectManagers) {
try {
if (strategy.isProjectRoot(file)) {
return true;
@@ -75,5 +83,19 @@ public class DefaultJavaProjectFinder implements JavaProjectFinder {
}
return false;
}
public void setFileObserver(FileObserver fileObserver) {
Arrays.stream(projectManagers).forEach(pm -> pm.setFileObserver(fileObserver));
}
@Override
public void addListener(Listener listener) {
Arrays.stream(projectManagers).forEach(pm -> pm.addListener(listener));
}
@Override
public void removeListener(Listener listener) {
Arrays.stream(projectManagers).forEach(pm -> pm.removeListener(listener));
}
}

View File

@@ -1,27 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016, 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.languageserver.java;
import java.io.File;
import org.springframework.ide.vscode.commons.java.IJavaProject;
/**
* Strategy foe finding Java project for a document
*
* @author Alex Boyko
*/
public interface IJavaProjectFinderStrategy {
IJavaProject find(File file) throws Exception;
boolean isProjectRoot(File file);
}

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2016-2017 Pivotal, Inc.
* Copyright (c) 2016, 2017 Pivotal, 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
@@ -13,12 +13,29 @@ package org.springframework.ide.vscode.commons.languageserver.java;
import java.io.File;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.text.IDocument;
public interface JavaProjectFinder {
/**
* Java project manager. Able to find a java project for a file or document and
* provide project change listening mechanism
*
* @author Alex Boyko
*/
public interface JavaProjectManager {
interface Listener {
void created(IJavaProject project);
void changed(IJavaProject project);
void deleted(IJavaProject project);
}
void setFileObserver(FileObserver fileObserver);
IJavaProject find(IDocument doc);
IJavaProject find(File file);
boolean isProjectRoot(File file);
void addListener(Listener listener);
void removeListener( Listener listener);
}

View File

@@ -0,0 +1,181 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.java.test;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import java.io.File;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import org.junit.Test;
import org.springframework.ide.vscode.commons.java.IClasspath;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.AbstractJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.CompositeJavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager.Listener;
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
import org.springframework.ide.vscode.commons.util.FileObserver.FileListener;
import org.springframework.ide.vscode.commons.util.FileUtils;
import org.springframework.ide.vscode.commons.util.Log;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
/**
* Tests for {@link CompositeJavaProjectManager}
*
* @author Alex Boyko
*
*/
public class CompositeJavaProjectManagerTest {
private AbstractJavaProjectManager createProjectManagerForFile(String fileName) {
return new AbstractJavaProjectManager() {
private Cache<File, IJavaProject> cache = CacheBuilder.newBuilder().build();
@Override
public boolean isProjectRoot(File file) {
return FileUtils.findFile(file, fileName, false) != null;
}
@Override
public IJavaProject find(File file) {
if (fileName.equals(file.toPath().getFileName().toString())) {
try {
return cache.get(file, () -> {
return new IJavaProject() {
@Override
public IClasspath getClasspath() {
return null;
}
};
});
} catch (ExecutionException e) {
Log.log(e);
return null;
}
}
return null;
}
@Override
protected FileListener createFileListener() {
return new FileListener() {
private File getFileFromUri(String uri) {
return Paths.get(URI.create(uri)).toFile();
}
@Override
public void deleted(String uri) {
File file = getFileFromUri(uri);
IJavaProject project = cache.getIfPresent(file);
if (project != null) {
cache.invalidate(file);
notifyProjectDeleted(project);
}
}
@Override
public void created(String uri) {
}
@Override
public void changed(String uri) {
File file = getFileFromUri(uri);
IJavaProject project = cache.getIfPresent(file);
if (project != null) {
notifyProjectChanged(project);
}
}
@Override
public boolean accept(String uri) {
return fileName.equals(Paths.get(URI.create(uri)).getFileName().toString());
}
};
}
};
}
@Test
public void testListeners() throws Exception {
AbstractJavaProjectManager manager1 = createProjectManagerForFile("test-1");
AbstractJavaProjectManager manager2 = createProjectManagerForFile("test-2");
CompositeJavaProjectManager compositeManager = new CompositeJavaProjectManager(new JavaProjectManager[] {
manager1,
manager2
});
BasicFileObserver fileObserver = new BasicFileObserver();
compositeManager.setFileObserver(fileObserver);
Path containerPath = Paths.get(CompositeJavaProjectManagerTest.class.getResource("/").toURI());
File projectFile1 = containerPath.resolve("test-1").toFile();
IJavaProject p1 = compositeManager.find(projectFile1);
assertNotNull(p1);
File projectFile2 = containerPath.resolve("test-2").toFile();
IJavaProject p2 = compositeManager.find(projectFile2);
assertNotNull(p2);
IJavaProject[] projectChanged = new IJavaProject[] { null };
IJavaProject[] projectDeleted = new IJavaProject[] { null };
compositeManager.addListener(new Listener() {
@Override
public void created(IJavaProject project) {
}
@Override
public void changed(IJavaProject project) {
projectChanged[0] = project;
}
@Override
public void deleted(IJavaProject project) {
projectDeleted[0] = project;
}
});
fileObserver.notifyFileChanged(projectFile1.toURI().toString());
assertEquals(p1, projectChanged[0]);
assertNull(projectDeleted[0]);
projectChanged[0] = projectDeleted[0] = null;
fileObserver.notifyFileDeleted(projectFile1.toURI().toString());
assertNull(projectChanged[0]);
assertEquals(p1, projectDeleted[0]);
projectChanged[0] = projectDeleted[0] = null;
fileObserver.notifyFileChanged(projectFile2.toURI().toString());
assertEquals(p2, projectChanged[0]);
assertNull(projectDeleted[0]);
projectChanged[0] = projectDeleted[0] = null;
fileObserver.notifyFileDeleted(projectFile2.toURI().toString());
assertNull(projectChanged[0]);
assertEquals(p2, projectDeleted[0]);
projectChanged[0] = projectDeleted[0] = null;
}
}

View File

@@ -21,18 +21,21 @@ import org.eclipse.lsp4j.SymbolInformation;
import org.eclipse.lsp4j.WorkspaceSymbolParams;
import org.eclipse.lsp4j.services.WorkspaceService;
import org.springframework.ide.vscode.commons.util.Assert;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.Log;
import com.google.common.collect.ImmutableList;
import reactor.core.publisher.Mono;
public class SimpleWorkspaceService implements WorkspaceService {
public class SimpleWorkspaceService implements WorkspaceService, FileObserver {
private SimpleLanguageServer server;
private ListenerList<Settings> configurationListeners = new ListenerList<>();
private ExecuteCommandHandler executeCommandHandler;
private WorkspaceSymbolHandler workspaceSymbolHandler;
private org.springframework.ide.vscode.commons.util.ListenerList<FileListener> fileListeners = new org.springframework.ide.vscode.commons.util.ListenerList<>();
public SimpleWorkspaceService(SimpleLanguageServer server) {
this.server = server;
@@ -59,6 +62,32 @@ public class SimpleWorkspaceService implements WorkspaceService {
@Override
public void didChangeWatchedFiles(DidChangeWatchedFilesParams params) {
params.getChanges().forEach(event -> fileListeners.forEach(listener -> {
try {
String uri = event.getUri();
if (uri != null) {
if (listener.accept(event.getUri())) {
switch (event.getType()) {
case Created:
listener.created(uri);
break;
case Changed:
listener.changed(uri);
break;
case Deleted:
listener.deleted(uri);
break;
default:
Log.log("Uknown file change type '" + event.getType() + "' for file: " + uri);
break;
}
}
}
} catch (Throwable t) {
Log.log(t);
}
}));
}
@Override
@@ -87,4 +116,14 @@ public class SimpleWorkspaceService implements WorkspaceService {
return this.workspaceSymbolHandler != null;
}
@Override
public void addListener(FileListener listener) {
fileListeners.add(listener);
}
@Override
public void removeListener(FileListener listener) {
fileListeners.remove(listener);
}
}

View File

@@ -1,43 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016, 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.maven;
import java.io.File;
import java.util.concurrent.ExecutionException;
import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy;
import org.springframework.ide.vscode.commons.maven.java.classpathfile.JavaProjectWithClasspathFile;
import org.springframework.ide.vscode.commons.util.FileUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
public class JavaProjectWithClasspathFileFinderStrategy implements IJavaProjectFinderStrategy {
public Cache<File, JavaProjectWithClasspathFile> cache = CacheBuilder.newBuilder().build();
@Override
public JavaProjectWithClasspathFile find(File file) throws ExecutionException {
File cpFile = FileUtils.findFile(file, MavenCore.CLASSPATH_TXT);
if (cpFile != null) {
return cache.get(cpFile, () -> {
return new JavaProjectWithClasspathFile(cpFile);
});
}
return null;
}
@Override
public boolean isProjectRoot(File file) {
return FileUtils.findFile(file, MavenCore.CLASSPATH_TXT, false) != null;
}
}

View File

@@ -1,57 +0,0 @@
/*******************************************************************************
* Copyright (c) 2016, 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.maven;
import java.io.File;
import java.util.concurrent.ExecutionException;
import org.springframework.ide.vscode.commons.languageserver.java.IJavaProjectFinderStrategy;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.commons.util.FileUtils;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
/**
* Finds Maven Project based
*
* @author Alex Boyko
*/
public class MavenProjectFinderStrategy implements IJavaProjectFinderStrategy {
private Cache<File, MavenJavaProject> cache = CacheBuilder.newBuilder().build();
private MavenCore maven;
public MavenProjectFinderStrategy(MavenCore maven) {
this.maven = maven;
}
@Override
public MavenJavaProject find(File file) throws ExecutionException {
File pomFile = FileUtils.findFile(file, MavenCore.POM_XML);
if (pomFile != null) {
return cache.get(pomFile, () -> {
System.out.println("create maven project: " + file.getAbsolutePath());
MavenJavaProject project = new MavenJavaProject(maven, pomFile);
System.out.println("maven project created");
return project;
});
}
return null;
}
@Override
public boolean isProjectRoot(File file) {
return FileUtils.findFile(file, MavenCore.POM_XML, false) != null;
}
}

View File

@@ -33,5 +33,9 @@ public class MavenJavaProject implements IJavaProject {
public MavenProjectClasspath getClasspath() {
return classpath;
}
void update(MavenCore maven, File pom) {
this.classpath = new MavenProjectClasspath(maven, pom);
}
}

View File

@@ -0,0 +1,115 @@
/*******************************************************************************
* Copyright (c) 2016, 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.maven.java;
import java.io.File;
import java.net.URI;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import org.springframework.ide.vscode.commons.languageserver.java.AbstractJavaProjectManager;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.FileObserver.FileListener;
import org.springframework.ide.vscode.commons.util.FileUtils;
import org.springframework.ide.vscode.commons.util.Log;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
/**
* Finds Maven Project based
*
* @author Alex Boyko
*/
public class MavenProjectManager extends AbstractJavaProjectManager {
private Cache<File, MavenJavaProject> cache = CacheBuilder.newBuilder().build();
private MavenCore maven;
public MavenProjectManager(MavenCore maven) {
this.maven = maven;
}
@Override
public MavenJavaProject find(File file) {
File pomFile = FileUtils.findFile(file, MavenCore.POM_XML);
if (pomFile != null) {
try {
return cache.get(pomFile, () -> {
System.out.println("create maven project: " + file.getAbsolutePath());
MavenJavaProject project = new MavenJavaProject(maven, pomFile);
System.out.println("maven project created");
return project;
});
} catch (ExecutionException e) {
Log.log(e);
return null;
}
}
return null;
}
@Override
public boolean isProjectRoot(File file) {
return FileUtils.findFile(file, MavenCore.POM_XML, false) != null;
}
@Override
public void setFileObserver(FileObserver fileObserver) {
super.setFileObserver(fileObserver);
cache.invalidateAll();
}
@Override
protected FileListener createFileListener() {
return new FileListener() {
private File getFileFromUri(String uri) {
return Paths.get(URI.create(uri)).toFile();
}
@Override
public void deleted(String uri) {
File pomFile = getFileFromUri(uri);
MavenJavaProject project = cache.getIfPresent(pomFile);
if (project != null) {
// Only invalidate and fire event if projects was cached.
cache.invalidate(pomFile);
notifyProjectDeleted(project);
}
}
@Override
public void created(String uri) {
// Ignore created projects - cache should take care of newly created ones
}
@Override
public void changed(String uri) {
File pomFile = getFileFromUri(uri);
MavenJavaProject project = cache.getIfPresent(pomFile);
if (project != null) {
// Only update and fire event if project cached
project.update(maven, pomFile);
notifyProjectChanged(project);
}
}
@Override
public boolean accept(String uri) {
return MavenCore.POM_XML.equals(Paths.get(URI.create(uri)).getFileName().toString());
}
};
}
}

View File

@@ -66,5 +66,10 @@ public class JavaProjectWithClasspathFile implements IJavaProject {
return false;
return true;
}
void update(File cpFile) {
this.cpFile = cpFile;
this.classpath = new FileClasspath(Paths.get(cpFile.toURI()));
}
}

View File

@@ -0,0 +1,103 @@
/*******************************************************************************
* Copyright (c) 2016, 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.maven.java.classpathfile;
import java.io.File;
import java.net.URI;
import java.nio.file.Paths;
import java.util.concurrent.ExecutionException;
import org.springframework.ide.vscode.commons.languageserver.java.AbstractJavaProjectManager;
import org.springframework.ide.vscode.commons.maven.MavenCore;
import org.springframework.ide.vscode.commons.util.FileObserver;
import org.springframework.ide.vscode.commons.util.FileObserver.FileListener;
import org.springframework.ide.vscode.commons.util.FileUtils;
import org.springframework.ide.vscode.commons.util.Log;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
public class JavaProjectWithClasspathFileManager extends AbstractJavaProjectManager {
private Cache<File, JavaProjectWithClasspathFile> cache = CacheBuilder.newBuilder().build();
@Override
public JavaProjectWithClasspathFile find(File file) {
File cpFile = FileUtils.findFile(file, MavenCore.CLASSPATH_TXT);
if (cpFile != null) {
try {
return cache.get(cpFile, () -> {
return new JavaProjectWithClasspathFile(cpFile);
});
} catch (ExecutionException e) {
Log.log(e);
return null;
}
}
return null;
}
@Override
public boolean isProjectRoot(File file) {
return FileUtils.findFile(file, MavenCore.CLASSPATH_TXT, false) != null;
}
@Override
public void setFileObserver(FileObserver fileObserver) {
super.setFileObserver(fileObserver);
cache.invalidateAll();
}
@Override
protected FileListener createFileListener() {
return new FileListener() {
@Override
public boolean accept(String uri) {
return MavenCore.CLASSPATH_TXT.equals(Paths.get(URI.create(uri)).getFileName().toString());
}
private File getFileFromUri(String uri) {
return Paths.get(URI.create(uri)).toFile();
}
@Override
public void deleted(String uri) {
File cpFile = getFileFromUri(uri);
JavaProjectWithClasspathFile project = cache.getIfPresent(cpFile);
if (project != null) {
// Only invalidate and fire event if projects was cached.
cache.invalidate(cpFile);
notifyProjectDeleted(project);
}
}
@Override
public void created(String uri) {
// Ignore created projects - cache should take care of newly created ones
}
@Override
public void changed(String uri) {
File cpFile = getFileFromUri(uri);
JavaProjectWithClasspathFile project = cache.getIfPresent(cpFile);
if (project != null) {
// Only update and fire event if project cached
project.update(cpFile);
notifyProjectChanged(project);
}
}
};
}
}

View File

@@ -0,0 +1,70 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.maven;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
import org.junit.Test;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectManager.Listener;
import org.springframework.ide.vscode.commons.maven.java.MavenJavaProject;
import org.springframework.ide.vscode.commons.maven.java.MavenProjectManager;
import org.springframework.ide.vscode.commons.util.BasicFileObserver;
/**
* Tests for {@link MavenProjectManager}
*
* @author Alex Boyko
*
*/
public class MavenProjectManagerTest {
@Test
public void testPomFileChanges() throws Exception {
Path testProjectPath = Paths.get(DependencyTreeTest.class.getResource("/empty-boot-project-with-classpath-file").toURI());
File pomFile = testProjectPath.resolve(MavenCore.POM_XML).toFile();
MavenProjectManager manager = new MavenProjectManager(MavenCore.getDefault());
BasicFileObserver fileObserver = new BasicFileObserver();
manager.setFileObserver(fileObserver);
IJavaProject[] projectChanged = new IJavaProject[] { null };
IJavaProject[] projectDeleted = new IJavaProject[] { null };
manager.addListener(new Listener() {
@Override
public void created(IJavaProject project) {}
@Override
public void changed(IJavaProject project) {
projectChanged[0] = project;
}
@Override
public void deleted(IJavaProject project) {
projectDeleted[0] = project;
}
});
// Get the project from cache
MavenJavaProject cachedProject = manager.find(pomFile);
assertNotNull(cachedProject);
fileObserver.notifyFileChanged(pomFile.toURI().toString());
assertEquals(cachedProject, projectChanged[0]);
fileObserver.notifyFileDeleted(pomFile.toURI().toString());
assertEquals(cachedProject, projectDeleted[0]);
}
}

View File

@@ -0,0 +1,69 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.util;
/**
* Basic implementation of File Observer interface
*
* @author Alex Boyko
*
*/
public class BasicFileObserver implements FileObserver {
private ListenerList<FileListener> listeners = new ListenerList<>();
@Override
public void addListener(FileListener listener) {
listeners.add(listener);
}
@Override
public void removeListener(FileListener listener) {
listeners.remove(listener);
}
public void notifyFileChanged(String uri) {
listeners.forEach(l -> {
try {
if (l.accept(uri)) {
l.changed(uri);
}
} catch (Throwable t) {
Log.log(t);
}
});
}
public void notifyFileCreated(String uri) {
listeners.forEach(l -> {
try {
if (l.accept(uri)) {
l.created(uri);
}
} catch (Throwable t) {
Log.log(t);
}
});
}
public void notifyFileDeleted(String uri) {
listeners.forEach(l -> {
try {
if (l.accept(uri)) {
l.deleted(uri);
}
} catch (Throwable t) {
Log.log(t);
}
});
}
}

View File

@@ -0,0 +1,32 @@
/*******************************************************************************
* Copyright (c) 2017 Pivotal, 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
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Pivotal, Inc. - initial API and implementation
*******************************************************************************/
package org.springframework.ide.vscode.commons.util;
/**
* Object able to add/remove {@link FileListener} objects and fire events via these listeners
*
* @author Alex Boyko
*
*/
public interface FileObserver {
public interface FileListener {
boolean accept(String uri);
void changed(String uri);
void deleted(String uri);
void created(String uri);
}
void addListener(FileListener listener);
void removeListener(FileListener listener);
}