PT #151428541: first steps to gather live hover hint data from running apps
This commit is contained in:
@@ -12,9 +12,11 @@ package org.springframework.ide.vscode.boot.java;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.lsp4j.CompletionItemKind;
|
||||
import org.eclipse.lsp4j.InitializedParams;
|
||||
import org.eclipse.lsp4j.InitializeParams;
|
||||
import org.eclipse.lsp4j.InitializeResult;
|
||||
import org.springframework.ide.vscode.boot.java.beans.BeansSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.beans.ComponentSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.BootJavaCodeLensEngine;
|
||||
@@ -32,9 +34,10 @@ import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingHov
|
||||
import org.springframework.ide.vscode.boot.java.requestmapping.RequestMappingSymbolProvider;
|
||||
import org.springframework.ide.vscode.boot.java.scope.ScopeCompletionProcessor;
|
||||
import org.springframework.ide.vscode.boot.java.snippets.JavaSnippet;
|
||||
import org.springframework.ide.vscode.boot.java.snippets.JavaSnippetManager;
|
||||
import org.springframework.ide.vscode.boot.java.snippets.JavaSnippetContext;
|
||||
import org.springframework.ide.vscode.boot.java.snippets.JavaSnippetManager;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringIndexer;
|
||||
import org.springframework.ide.vscode.boot.java.utils.SpringLiveHoverWatchdog;
|
||||
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;
|
||||
@@ -47,7 +50,6 @@ import org.springframework.ide.vscode.commons.languageserver.java.DefaultJavaPro
|
||||
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.reconcile.IReconcileEngine;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.HoverHandler;
|
||||
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;
|
||||
@@ -66,6 +68,8 @@ import com.google.common.collect.ImmutableList;
|
||||
*/
|
||||
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()),
|
||||
@@ -74,9 +78,13 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
|
||||
|
||||
private final VscodeCompletionEngineAdapter completionEngine;
|
||||
private final SpringIndexer indexer;
|
||||
private final SpringLiveHoverWatchdog liveHoverWatchdog;
|
||||
|
||||
public BootJavaLanguageServer(JavaProjectFinder javaProjectFinder, SpringPropertyIndexProvider indexProvider) {
|
||||
super("vscode-boot-java");
|
||||
|
||||
System.setProperty(LANGUAGE_SERVER_PROCESS_PROPERTY, LANGUAGE_SERVER_PROCESS_PROPERTY);
|
||||
|
||||
SimpleWorkspaceService workspaceService = getWorkspaceService();
|
||||
SimpleTextDocumentService documents = getTextDocumentService();
|
||||
|
||||
@@ -92,9 +100,16 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
|
||||
documents.onCompletion(completionEngine::getCompletions);
|
||||
documents.onCompletionResolve(completionEngine::resolveCompletion);
|
||||
|
||||
HoverHandler hoverInfoProvider = createHoverHandler(javaProjectFinder);
|
||||
BootJavaHoverProvider hoverInfoProvider = createHoverHandler(javaProjectFinder);
|
||||
documents.onHover(hoverInfoProvider);
|
||||
|
||||
liveHoverWatchdog = new SpringLiveHoverWatchdog(this, hoverInfoProvider);
|
||||
documents.onDidChangeContent(params -> {
|
||||
TextDocument doc = params.getDocument();
|
||||
liveHoverWatchdog.watchDocument(doc.getUri());
|
||||
liveHoverWatchdog.update(doc.getUri());
|
||||
});
|
||||
|
||||
ReferencesHandler referencesHandler = createReferenceHandler(this, javaProjectFinder);
|
||||
documents.onReferences(referencesHandler);
|
||||
|
||||
@@ -112,9 +127,28 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialized(InitializedParams params) {
|
||||
super.initialized(params);
|
||||
public CompletableFuture<InitializeResult> initialize(InitializeParams params) {
|
||||
CompletableFuture<InitializeResult> result = super.initialize(params);
|
||||
|
||||
this.indexer.initialize(this.getWorkspaceRoot());
|
||||
this.liveHoverWatchdog.start();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void initialized() {
|
||||
// TODO: due to a missing message from lsp4e this "initialized" is not called in the LSP4E case
|
||||
// if this gets fixed, the code should move here (from "initialize" above)
|
||||
|
||||
// this.indexer.initialize(this.getWorkspaceRoot());
|
||||
// this.liveHoverWatchdog.start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Object> shutdown() {
|
||||
liveHoverWatchdog.shutdown();
|
||||
return super.shutdown();
|
||||
}
|
||||
|
||||
protected ICompletionEngine createCompletionEngine(JavaProjectFinder javaProjectFinder, SpringPropertyIndexProvider indexProvider) {
|
||||
@@ -184,7 +218,7 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
|
||||
return new BootJavaCompletionEngine(javaProjectFinder, providers, snippetManager);
|
||||
}
|
||||
|
||||
protected HoverHandler createHoverHandler(JavaProjectFinder javaProjectFinder) {
|
||||
protected BootJavaHoverProvider createHoverHandler(JavaProjectFinder 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());
|
||||
|
||||
@@ -11,6 +11,8 @@
|
||||
package org.springframework.ide.vscode.boot.java.handlers;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
import java.util.stream.Stream;
|
||||
@@ -19,18 +21,26 @@ import org.eclipse.jdt.core.JavaCore;
|
||||
import org.eclipse.jdt.core.dom.AST;
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.ASTParser;
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MarkerAnnotation;
|
||||
import org.eclipse.jdt.core.dom.NodeFinder;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
import org.eclipse.jdt.core.dom.SingleMemberAnnotation;
|
||||
import org.eclipse.lsp4j.Hover;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.TextDocumentPositionParams;
|
||||
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.util.HoverHandler;
|
||||
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.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.text.IDocument;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
@@ -68,7 +78,89 @@ public class BootJavaHoverProvider implements HoverHandler {
|
||||
return SimpleTextDocumentService.NO_HOVER;
|
||||
}
|
||||
|
||||
public Range[] getLiveHoverHints(final TextDocument document, final SpringBootApp[] runningBootApps) {
|
||||
List<Range> result = new ArrayList<>();
|
||||
try {
|
||||
IJavaProject project = getProject(document);
|
||||
CompilationUnit cu = parse(document, project);
|
||||
|
||||
cu.accept(new ASTVisitor() {
|
||||
@Override
|
||||
public boolean visit(SingleMemberAnnotation node) {
|
||||
try {
|
||||
extractLiveHints(node, document, runningBootApps, result);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(NormalAnnotation node) {
|
||||
try {
|
||||
extractLiveHints(node, document, runningBootApps, result);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return super.visit(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(MarkerAnnotation node) {
|
||||
try {
|
||||
extractLiveHints(node, document, runningBootApps, result);
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return super.visit(node);
|
||||
}
|
||||
});
|
||||
}
|
||||
catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return result.toArray(new Range[result.size()]);
|
||||
}
|
||||
|
||||
protected void extractLiveHints(Annotation annotation, TextDocument document, SpringBootApp[] runningApps, List<Range> result) {
|
||||
ITypeBinding type = annotation.resolveTypeBinding();
|
||||
if (type != null) {
|
||||
String qualifiedName = type.getQualifiedName();
|
||||
if (qualifiedName != null) {
|
||||
HoverProvider provider = this.hoverProviders.get(qualifiedName);
|
||||
if (provider != null) {
|
||||
Range range = provider.getLiveHoverHint(annotation, document, runningApps);
|
||||
if (range != null) {
|
||||
result.add(range);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private CompletableFuture<Hover> provideHover(TextDocument document, int offset) throws Exception {
|
||||
IJavaProject project = getProject(document);
|
||||
CompilationUnit cu = parse(document, project);
|
||||
|
||||
ASTNode node = NodeFinder.perform(cu, offset, 0);
|
||||
|
||||
if (node != null) {
|
||||
System.out.println("AST node found: " + node.getClass().getName());
|
||||
return provideHoverForAnnotation(node, offset, document, project);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private CompilationUnit parse(TextDocument document, IJavaProject project)
|
||||
throws Exception, BadLocationException {
|
||||
ASTParser parser = ASTParser.newParser(AST.JLS8);
|
||||
Map<String, String> options = JavaCore.getOptions();
|
||||
JavaCore.setComplianceOptions(JavaCore.VERSION_1_8, options);
|
||||
@@ -78,7 +170,7 @@ public class BootJavaHoverProvider implements HoverHandler {
|
||||
parser.setBindingsRecovery(true);
|
||||
parser.setResolveBindings(true);
|
||||
|
||||
String[] classpathEntries = getClasspathEntries(document);
|
||||
String[] classpathEntries = getClasspathEntries(project);
|
||||
String[] sourceEntries = new String[] {};
|
||||
parser.setEnvironment(classpathEntries, sourceEntries, null, true);
|
||||
|
||||
@@ -88,17 +180,10 @@ public class BootJavaHoverProvider implements HoverHandler {
|
||||
parser.setSource(document.get(0, document.getLength()).toCharArray());
|
||||
|
||||
CompilationUnit cu = (CompilationUnit) parser.createAST(null);
|
||||
ASTNode node = NodeFinder.perform(cu, offset, 0);
|
||||
|
||||
if (node != null) {
|
||||
System.out.println("AST node found: " + node.getClass().getName());
|
||||
return provideHoverForAnnotation(node, offset, document);
|
||||
}
|
||||
|
||||
return null;
|
||||
return cu;
|
||||
}
|
||||
|
||||
private CompletableFuture<Hover> provideHoverForAnnotation(ASTNode node, int offset, TextDocument doc) {
|
||||
private CompletableFuture<Hover> provideHoverForAnnotation(ASTNode node, int offset, TextDocument doc, IJavaProject project) {
|
||||
Annotation annotation = null;
|
||||
|
||||
while (node != null && !(node instanceof Annotation)) {
|
||||
@@ -113,7 +198,8 @@ public class BootJavaHoverProvider implements HoverHandler {
|
||||
if (qualifiedName != null) {
|
||||
HoverProvider provider = this.hoverProviders.get(qualifiedName);
|
||||
if (provider != null) {
|
||||
return provider.provideHover(node, annotation, type, offset, doc);
|
||||
SpringBootApp[] runningApps = getRunningSpringApps(project);
|
||||
return provider.provideHover(node, annotation, type, offset, doc, runningApps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -122,8 +208,11 @@ public class BootJavaHoverProvider implements HoverHandler {
|
||||
return null;
|
||||
}
|
||||
|
||||
private String[] getClasspathEntries(IDocument doc) throws Exception {
|
||||
IJavaProject project = this.projectFinder.find(doc);
|
||||
private IJavaProject getProject(IDocument doc) throws Exception {
|
||||
return this.projectFinder.find(doc);
|
||||
}
|
||||
|
||||
private String[] getClasspathEntries(IJavaProject project) throws Exception {
|
||||
IClasspath classpath = project.getClasspath();
|
||||
Stream<Path> classpathEntries = classpath.getClasspathEntries();
|
||||
return classpathEntries
|
||||
@@ -131,4 +220,15 @@ public class BootJavaHoverProvider implements HoverHandler {
|
||||
.map(path -> path.toAbsolutePath().toString()).toArray(String[]::new);
|
||||
}
|
||||
|
||||
private SpringBootApp[] getRunningSpringApps(IJavaProject project) {
|
||||
try {
|
||||
return SpringBootApp.getAllRunningSpringApps().values().stream()
|
||||
.filter((app) -> !app.containsSystemProperty(BootJavaLanguageServer.LANGUAGE_SERVER_PROCESS_PROPERTY))
|
||||
.toArray(SpringBootApp[]::new);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return new SpringBootApp[0];
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,6 +16,8 @@ import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.lsp4j.Hover;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
/**
|
||||
@@ -23,7 +25,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
*/
|
||||
public interface HoverProvider {
|
||||
|
||||
CompletableFuture<Hover> provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset,
|
||||
TextDocument doc);
|
||||
CompletableFuture<Hover> provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset, TextDocument doc, SpringBootApp[] runningApps);
|
||||
Range getLiveHoverHint(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps);
|
||||
|
||||
}
|
||||
|
||||
@@ -13,7 +13,6 @@ package org.springframework.ide.vscode.boot.java.requestmapping;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
@@ -31,6 +30,7 @@ import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.json.JSONObject;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.HoverProvider;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.util.BadLocationException;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
/**
|
||||
@@ -40,14 +40,32 @@ public class RequestMappingHoverProvider implements HoverProvider {
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Hover> provideHover(ASTNode node, Annotation annotation,
|
||||
ITypeBinding type, int offset, TextDocument doc) {
|
||||
return provideHover(annotation, doc);
|
||||
ITypeBinding type, int offset, TextDocument doc, SpringBootApp[] runningApps) {
|
||||
return provideHover(annotation, doc, runningApps);
|
||||
}
|
||||
|
||||
private CompletableFuture<Hover> provideHover(Annotation annotation, TextDocument doc) {
|
||||
@Override
|
||||
public Range getLiveHoverHint(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) {
|
||||
try {
|
||||
if (runningApps.length > 0) {
|
||||
// TODO: this check is too simple, we need to do a lot more here
|
||||
// -> check if the running app has a matching request mapping for this annotation
|
||||
|
||||
Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
|
||||
return hoverRange;
|
||||
}
|
||||
}
|
||||
catch (BadLocationException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private CompletableFuture<Hover> provideHover(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) {
|
||||
|
||||
try {
|
||||
JSONObject[] mappings = getRequestMappingsFromProcesses();
|
||||
JSONObject[] mappings = getRequestMappingsFromProcesses(runningApps);
|
||||
|
||||
List<Either<String, MarkedString>> hoverContent = new ArrayList<>();
|
||||
|
||||
@@ -55,7 +73,6 @@ public class RequestMappingHoverProvider implements HoverProvider {
|
||||
addHoverContent(mappings[i], hoverContent, annotation);
|
||||
}
|
||||
|
||||
|
||||
Range hoverRange = doc.toRange(annotation.getStartPosition(), annotation.getLength());
|
||||
Hover hover = new Hover();
|
||||
|
||||
@@ -109,21 +126,16 @@ public class RequestMappingHoverProvider implements HoverProvider {
|
||||
return mappingPath != null ? key.contains(mappingPath) : false;
|
||||
}
|
||||
|
||||
public JSONObject[] getRequestMappingsFromProcesses() {
|
||||
public JSONObject[] getRequestMappingsFromProcesses(SpringBootApp[] runningApps) {
|
||||
List<JSONObject> result = new ArrayList<>();
|
||||
|
||||
try {
|
||||
Map<String, SpringBootApp> apps = SpringBootApp.getAllRunningJavaApps();
|
||||
Iterator<SpringBootApp> appsIter = apps.values().iterator();
|
||||
while (appsIter.hasNext()) {
|
||||
SpringBootApp app = appsIter.next();
|
||||
if (app.isSpringBootApp()) {
|
||||
String mappings = app.getRequestMappings();
|
||||
if (mappings != null) {
|
||||
JSONObject requestMappings = new JSONObject(mappings);
|
||||
if (requestMappings != null) {
|
||||
result.add(requestMappings);
|
||||
}
|
||||
for (SpringBootApp app : runningApps) {
|
||||
String mappings = app.getRequestMappings();
|
||||
if (mappings != null) {
|
||||
JSONObject requestMappings = new JSONObject(mappings);
|
||||
if (requestMappings != null) {
|
||||
result.add(requestMappings);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,117 @@
|
||||
/*******************************************************************************
|
||||
* 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.boot.java.utils;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.Timer;
|
||||
import java.util.TimerTask;
|
||||
import java.util.concurrent.ConcurrentSkipListSet;
|
||||
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.BootJavaHoverProvider;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
import org.springframework.ide.vscode.commons.languageserver.util.SimpleLanguageServer;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
/**
|
||||
* @author Martin Lippert
|
||||
*/
|
||||
public class SpringLiveHoverWatchdog {
|
||||
|
||||
private static final int POLLING_INTERVAL_MILLISECONDS = 5000;
|
||||
|
||||
private final Set<String> watchedDocs;
|
||||
private final SimpleLanguageServer server;
|
||||
private final BootJavaHoverProvider hoverProvider;
|
||||
|
||||
private final Timer timer;
|
||||
|
||||
public SpringLiveHoverWatchdog(SimpleLanguageServer server, BootJavaHoverProvider hoverProvider) {
|
||||
this.server = server;
|
||||
this.hoverProvider = hoverProvider;
|
||||
this.watchedDocs = new ConcurrentSkipListSet<>();
|
||||
|
||||
this.timer = new Timer();
|
||||
}
|
||||
|
||||
public void start() {
|
||||
TimerTask task = new TimerTask() {
|
||||
@Override
|
||||
public void run() {
|
||||
update();
|
||||
}
|
||||
};
|
||||
|
||||
timer.scheduleAtFixedRate(task, 0, POLLING_INTERVAL_MILLISECONDS);
|
||||
}
|
||||
|
||||
public void shutdown() {
|
||||
timer.cancel();
|
||||
}
|
||||
|
||||
public void watchDocument(String docURI) {
|
||||
this.watchedDocs.add(docURI);
|
||||
}
|
||||
|
||||
public void unwatchDocument(String docURI) {
|
||||
this.watchedDocs.remove(docURI);
|
||||
cleanupLiveHints(docURI);
|
||||
|
||||
if (watchedDocs.size() == 0) {
|
||||
cleanupResources();
|
||||
}
|
||||
}
|
||||
|
||||
public void update(String docURI) {
|
||||
try {
|
||||
SpringBootApp[] runningBootApps = SpringBootApp.getAllRunningSpringApps().values().stream()
|
||||
.filter((app) -> !app.containsSystemProperty(BootJavaLanguageServer.LANGUAGE_SERVER_PROCESS_PROPERTY))
|
||||
.toArray(SpringBootApp[]::new);
|
||||
|
||||
TextDocument doc = this.server.getTextDocumentService().get(docURI);
|
||||
if (doc != null) {
|
||||
Range[] ranges = this.hoverProvider.getLiveHoverHints(doc, runningBootApps);
|
||||
publishLiveHints(ranges);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
protected void update() {
|
||||
if (this.watchedDocs.size() > 0) {
|
||||
for (String docURI : watchedDocs) {
|
||||
update(docURI);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void publishLiveHints(Range[] ranges) {
|
||||
for (Range range : ranges) {
|
||||
int startLine = range.getStart().getLine();
|
||||
int startChar = range.getStart().getCharacter();
|
||||
int endLine = range.getEnd().getLine();
|
||||
int endChar = range.getEnd().getCharacter();
|
||||
|
||||
System.out.println("live hover information at: " + startLine + ":" + startChar + " - " + endLine + ":" + endChar);
|
||||
}
|
||||
}
|
||||
|
||||
private void cleanupLiveHints(String docURI) {
|
||||
// TODO: send client a message to cleanup live hover diagnostics data
|
||||
}
|
||||
|
||||
private void cleanupResources() {
|
||||
// TODO: close and cleanup open JMX connections and cached data
|
||||
}
|
||||
|
||||
}
|
||||
@@ -13,7 +13,6 @@ package org.springframework.ide.vscode.boot.java.value;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CompletableFuture;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
@@ -35,27 +34,22 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
*/
|
||||
public class ValueHoverProvider implements HoverProvider {
|
||||
|
||||
public static void register(Map<String, HoverProvider> hoverProviders) {
|
||||
ValueHoverProvider provider = new ValueHoverProvider();
|
||||
hoverProviders.put(Constants.SPRING_VALUE, provider);
|
||||
}
|
||||
|
||||
@Override
|
||||
public CompletableFuture<Hover> provideHover(ASTNode node, Annotation annotation, ITypeBinding type, int offset,
|
||||
TextDocument doc) {
|
||||
TextDocument doc, SpringBootApp[] runningApps) {
|
||||
|
||||
try {
|
||||
// case: @Value("prefix<*>")
|
||||
if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
|
||||
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
|
||||
return provideHover(node.toString(), offset - node.getStartPosition(), node.getStartPosition(), doc);
|
||||
return provideHover(node.toString(), offset - node.getStartPosition(), node.getStartPosition(), doc, runningApps);
|
||||
}
|
||||
}
|
||||
// case: @Value(value="prefix<*>")
|
||||
else if (node instanceof StringLiteral && node.getParent() instanceof MemberValuePair
|
||||
&& "value".equals(((MemberValuePair)node.getParent()).getName().toString())) {
|
||||
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
|
||||
return provideHover(node.toString(), offset - node.getStartPosition(), node.getStartPosition(), doc);
|
||||
return provideHover(node.toString(), offset - node.getStartPosition(), node.getStartPosition(), doc, runningApps);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -66,7 +60,12 @@ public class ValueHoverProvider implements HoverProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
private CompletableFuture<Hover> provideHover(String value, int offset, int nodeStartOffset, TextDocument doc) {
|
||||
@Override
|
||||
public Range getLiveHoverHint(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) {
|
||||
return null;
|
||||
}
|
||||
|
||||
private CompletableFuture<Hover> provideHover(String value, int offset, int nodeStartOffset, TextDocument doc, SpringBootApp[] runningApps) {
|
||||
|
||||
try {
|
||||
LocalRange range = getPropertyRange(value, offset);
|
||||
@@ -74,7 +73,7 @@ public class ValueHoverProvider implements HoverProvider {
|
||||
String propertyKey = value.substring(range.getStart(), range.getEnd());
|
||||
|
||||
if (propertyKey != null) {
|
||||
JSONObject[] allProperties = getPropertiesFromProcesses();
|
||||
JSONObject[] allProperties = getPropertiesFromProcesses(runningApps);
|
||||
|
||||
List<Either<String, MarkedString>> hoverContent = new ArrayList<>();
|
||||
|
||||
@@ -114,21 +113,16 @@ public class ValueHoverProvider implements HoverProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
public JSONObject[] getPropertiesFromProcesses() {
|
||||
public JSONObject[] getPropertiesFromProcesses(SpringBootApp[] runningApps) {
|
||||
List<JSONObject> result = new ArrayList<>();
|
||||
|
||||
try {
|
||||
Map<String, SpringBootApp> apps = SpringBootApp.getAllRunningJavaApps();
|
||||
Iterator<SpringBootApp> appsIter = apps.values().iterator();
|
||||
while (appsIter.hasNext()) {
|
||||
SpringBootApp app = appsIter.next();
|
||||
if (app.isSpringBootApp()) {
|
||||
String environment = app.getEnvironment();
|
||||
if (environment != null) {
|
||||
JSONObject env = new JSONObject(environment);
|
||||
if (env != null) {
|
||||
result.add(env);
|
||||
}
|
||||
for (SpringBootApp app : runningApps) {
|
||||
String environment = app.getEnvironment();
|
||||
if (environment != null) {
|
||||
JSONObject env = new JSONObject(environment);
|
||||
if (env != null) {
|
||||
result.add(env);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user