Make live hovers AnnotationHierarchyAware

This commit is contained in:
Kris De Volder
2017-11-21 11:30:55 -08:00
parent 7136162000
commit 6783ffdbe8
5 changed files with 62 additions and 56 deletions

View File

@@ -250,7 +250,7 @@ public class BootJavaLanguageServer extends SimpleLanguageServer {
protected BootJavaHoverProvider createHoverHandler(JavaProjectFinder javaProjectFinder,
RunningAppProvider runningAppProvider) {
HashMap<String, HoverProvider> providers = new HashMap<>();
AnnotationHierarchyAwareLookup<HoverProvider> providers = new AnnotationHierarchyAwareLookup<>();
providers.put(org.springframework.ide.vscode.boot.java.value.Constants.SPRING_VALUE, new ValueHoverProvider());

View File

@@ -12,6 +12,7 @@ package org.springframework.ide.vscode.boot.java.handlers;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@@ -32,6 +33,7 @@ import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.eclipse.lsp4j.TextDocumentPositionParams;
import org.eclipse.lsp4j.jsonrpc.messages.Either;
import org.springframework.ide.vscode.boot.java.BootJavaLanguageServer;
import org.springframework.ide.vscode.boot.java.annotations.AnnotationHierarchyAwareLookup;
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
import org.springframework.ide.vscode.commons.java.IClasspath;
@@ -53,10 +55,10 @@ public class BootJavaHoverProvider implements HoverHandler {
private JavaProjectFinder projectFinder;
private BootJavaLanguageServer server;
private Map<String, HoverProvider> hoverProviders;
private AnnotationHierarchyAwareLookup<HoverProvider> hoverProviders;
private RunningAppProvider runningAppProvider;
public BootJavaHoverProvider(BootJavaLanguageServer server, JavaProjectFinder projectFinder, Map<String, HoverProvider> specificProviders, RunningAppProvider runningAppProvider) {
public BootJavaHoverProvider(BootJavaLanguageServer server, JavaProjectFinder projectFinder, AnnotationHierarchyAwareLookup<HoverProvider> specificProviders, RunningAppProvider runningAppProvider) {
this.server = server;
this.projectFinder = projectFinder;
this.hoverProviders = specificProviders;
@@ -84,7 +86,7 @@ public class BootJavaHoverProvider implements HoverHandler {
public Range[] getLiveHoverHints(final TextDocument document, final SpringBootApp[] runningBootApps) {
return server.getCompilationUnitCache().withCompilationUnit(document, cu -> {
List<Range> result = new ArrayList<>();
Collection<Range> result = new HashSet<>();
try {
if (cu != null) {
cu.accept(new ASTVisitor() {
@@ -129,26 +131,22 @@ public class BootJavaHoverProvider implements HoverHandler {
});
}
protected void extractLiveHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps, List<Range> result) {
protected void extractLiveHints(Annotation annotation, TextDocument doc, SpringBootApp[] runningApps, Collection<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) {
if (runningApps.length>0) {
getProject(doc).ifPresent(project -> {
if (hasActuatorDependency(project)) {
Collection<Range> hints = provider.getLiveHoverHints(annotation, doc, runningApps);
if (hints!=null) {
result.addAll(hints);
}
} else {
//Do nothing... we don't want a highlight for the 'no actuator warning'
//ASTUtils.nameRange(doc, annotation).ifPresent(result::add);
if (runningApps.length>0) {
for (HoverProvider provider : this.hoverProviders.get(type)) {
getProject(doc).ifPresent(project -> {
if (hasActuatorDependency(project)) {
Collection<Range> hints = provider.getLiveHoverHints(annotation, doc, runningApps);
if (hints!=null) {
result.addAll(hints);
}
});
}
} else {
//Do nothing... we don't want a highlight for the 'no actuator warning'
//ASTUtils.nameRange(doc, annotation).ifPresent(result::add);
}
});
}
}
}
@@ -179,20 +177,20 @@ public class BootJavaHoverProvider implements HoverHandler {
annotation = (Annotation) node;
ITypeBinding type = annotation.resolveTypeBinding();
if (type != null) {
String qualifiedName = type.getQualifiedName();
if (qualifiedName != null) {
HoverProvider provider = this.hoverProviders.get(qualifiedName);
if (provider != null) {
SpringBootApp[] runningApps = getRunningSpringApps(project);
if (runningApps.length>0) {
if (hasActuatorDependency(project)) {
return provider.provideHover(node, annotation, type, offset, doc, project, runningApps);
} else {
DocumentRegion region = ASTUtils.nameRegion(doc, annotation);
if (region.containsOffset(offset)) {
return actuatorWarning(project);
}
}
SpringBootApp[] runningApps = getRunningSpringApps(project);
if (runningApps.length>0) {
for (HoverProvider provider : this.hoverProviders.get(type)) {
Hover hover = provider.provideHover(node, annotation, type, offset, doc, project, runningApps);
if (hover!=null) {
//TODO: compose multiple hovers somehow instead of just returning the first one?
return hover;
}
}
//Only reaching here if we didn't get a hover.
if (!hasActuatorDependency(project)) {
DocumentRegion region = ASTUtils.nameRegion(doc, annotation);
if (region.containsOffset(offset)) {
return actuatorWarning(project);
}
}
}

View File

@@ -52,23 +52,29 @@ public class ActiveProfilesProvider implements HoverProvider {
if (runningApps.length>0) {
StringBuilder markdown = new StringBuilder();
markdown.append("**Active Profiles**\n\n");
boolean hasInterestingApp = false;
for (SpringBootApp app : runningApps) {
List<String> profiles = app.getActiveProfiles();
if (profiles==null) {
markdown.append(niceAppName(app)+" : _Unknown_\n\n");
} else if (profiles.isEmpty()) {
markdown.append(niceAppName(app)+" : _None_\n\n");
} else {
markdown.append(niceAppName(app)+" :\n");
for (String profile : profiles) {
markdown.append("- "+profile+"\n");
hasInterestingApp = true;
if (profiles.isEmpty()) {
markdown.append(niceAppName(app)+" : _None_\n\n");
} else {
markdown.append(niceAppName(app)+" :\n");
for (String profile : profiles) {
markdown.append("- "+profile+"\n");
}
markdown.append("\n");
}
markdown.append("\n");
}
}
return new Hover(
ImmutableList.of(Either.forLeft(markdown.toString()))
);
if (hasInterestingApp) {
return new Hover(
ImmutableList.of(Either.forLeft(markdown.toString()))
);
}
}
return null;
}

View File

@@ -300,7 +300,7 @@ public class AutowiredHoverProviderTest {
);
editor.assertHighlights("@Component", "@Autowired", "@Autowired");
for (int i = 1; i <= 2; i++) {
editor.assertHoverContains("@Autowired", 1,
editor.assertHoverContains("@Autowired", i,
"Bean [id: defaultFoo, type: `com.example.FooImplementation`] got autowired with:\n" +
"\n" +
"- Bean: otherBean \n" +
@@ -351,15 +351,16 @@ public class AutowiredHoverProviderTest {
" \n" +
"}"
);
editor.assertHighlights(/* not yet: "@Controller",*/ "@Autowired");
for (int i = 1; i <= 2; i++) {
editor.assertHoverContains("@Autowired", 1,
"Bean [id: myController, type: `com.example.MyController`] got autowired with:\n" +
"\n" +
"- Bean: restTemplate \n" +
" Type: `org.springframework.web.client.RestTemplate`");
}
editor.assertHighlights("@Controller", "@Autowired");
editor.assertHoverContains("@Autowired",
"Bean [id: myController, type: `com.example.MyController`] got autowired with:\n" +
"\n" +
"- Bean: restTemplate \n" +
" Type: `org.springframework.web.client.RestTemplate`"
);
editor.assertHoverContains("@Controller",
"**Injection report for Bean [id: myController, type: `com.example.MyController`]**"
);
}
}

View File

@@ -78,6 +78,7 @@ public class ActiveProfilesHoverTest {
public void testActiveProfileHover_Unknown() throws Exception {
//Sometimes its not possible to determine active profiles for an app (e.g. no actuator dependency).
//Make sure we show something sensible
harness.useProject(projects.mavenProject("no-actuator-boot-15-web-app"));
mockAppProvider.builder()
.isSpringBootApp(true)
@@ -98,8 +99,8 @@ public class ActiveProfilesHoverTest {
"\n" +
"}"
);
editor.assertHoverContains("@Profile", "Process [PID=22022, name=`foo.bar.RunningApp`] : _Unknown_");
editor.assertHighlights("@Profile");
editor.assertHoverContains("@Profile", "Consider adding `spring-boot-actuator` as a dependency");
editor.assertHighlights(/*NONE*/);
}
@Test