PT #164318678: Live hovers for beans with non-standard ids

This commit is contained in:
BoykoAlex
2019-05-16 14:24:10 -04:00
parent 0290842dfb
commit 13a1ba088b
4 changed files with 169 additions and 26 deletions

View File

@@ -53,9 +53,15 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider
public AbstractInjectedIntoHoverProvider(SourceLinks sourceLinks) {
this.sourceLinks = sourceLinks;
}
@FunctionalInterface
protected interface DefinedBeanProvider {
LiveBean definedBean(SpringBootApp app);
}
@Override
public Collection<CodeLens> getLiveHintCodeLenses(IJavaProject project, Annotation annotation, TextDocument doc, SpringBootApp[] runningApps) {
public Collection<CodeLens> getLiveHintCodeLenses(IJavaProject project, Annotation annotation, TextDocument doc,
SpringBootApp[] runningApps) {
// Highlight if any running app contains an instance of this component
try {
if (runningApps.length > 0) {
@@ -64,8 +70,8 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider
if (Stream.of(runningApps).anyMatch(app -> LiveHoverUtils.hasRelevantBeans(app, definedBean))) {
Optional<Range> nameRange = ASTUtils.nameRange(doc, annotation);
if (nameRange.isPresent()) {
List<CodeLens> codeLenses = assembleCodeLenses(project, runningApps, definedBean, doc, nameRange.get(), annotation);
return codeLenses.isEmpty() ? ImmutableList.of(new CodeLens(nameRange.get())) : codeLenses;
List<CodeLens> codeLenses = assembleCodeLenses(project, runningApps, app -> definedBean, doc, nameRange.get(), annotation);
return codeLenses;
}
}
}
@@ -83,7 +89,7 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider
LiveBean definedBean = getDefinedBean(annotation);
if (definedBean != null) {
Hover hover = assembleHover(project, runningApps, definedBean, annotation, true, true);
Hover hover = assembleHover(project, runningApps, app -> definedBean, annotation, true, true);
if (hover != null) {
Optional<Range> nameRange = ASTUtils.nameRange(doc, annotation);
if (nameRange.isPresent()) {
@@ -96,10 +102,18 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider
return null;
}
protected List<CodeLens> assembleCodeLenses(IJavaProject project, SpringBootApp[] runningApps, LiveBean definedBean,
protected List<CodeLens> assembleCodeLenses(IJavaProject project, SpringBootApp[] runningApps, DefinedBeanProvider definedBeanProvider,
TextDocument doc, Range range, ASTNode node) {
boolean beanFound = false;
for (SpringBootApp app : runningApps) {
LiveBean definedBean = definedBeanProvider.definedBean(app);
if (definedBean == null) {
continue;
}
beanFound = true;
List<LiveBean> relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean);
if (!relevantBeans.isEmpty()) {
@@ -120,8 +134,9 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider
List<CodeLens> codeLenses = builder.build();
return codeLenses.isEmpty() ? ImmutableList.of(new CodeLens(range)) : codeLenses;
}
}
return ImmutableList.of();
return beanFound ? ImmutableList.of(new CodeLens(range)) : null;
}
protected List<CodeLens> assembleCodeLenseForAutowired(List<LiveBean> wiredBeans, IJavaProject project, SpringBootApp app, TextDocument doc, Range nameRange, ASTNode astNode) {
@@ -134,13 +149,19 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider
return Collections.emptyList();
}
protected Hover assembleHover(IJavaProject project, SpringBootApp[] runningApps, LiveBean definedBean, ASTNode astNode, boolean injected, boolean wired) {
protected Hover assembleHover(IJavaProject project, SpringBootApp[] runningApps, DefinedBeanProvider definedBeanProvider, ASTNode astNode, boolean injected, boolean wired) {
StringBuilder hover = new StringBuilder();
for (SpringBootApp app : runningApps) {
List<LiveBean> relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean);
LiveBean definedBean = definedBeanProvider.definedBean(app);
if (definedBean == null) {
continue;
}
List<LiveBean> relevantBeans = LiveHoverUtils.findRelevantBeans(app, definedBean);
if (!relevantBeans.isEmpty()) {
if (hover.length() > 0) {
hover.append(" \n \n");
@@ -180,7 +201,7 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider
}
}
protected List<LiveBean> getRelevantInjectedIntoBeans(IJavaProject project, SpringBootApp app, LiveBean definedBean, List<LiveBean> relevantBeans) {
LiveBeansModel beans = app.getBeans();
if (relevantBeans != null) {

View File

@@ -127,7 +127,7 @@ public class BeanInjectedIntoHoverProvider extends AbstractInjectedIntoHoverProv
if (beanAnnotation != null) {
LiveBean definedBean = getDefinedBean(beanAnnotation);
if (definedBean != null) {
Hover hover = assembleHover(project, runningApps, definedBean, parameter, false, true);
Hover hover = assembleHover(project, runningApps, app -> definedBean, parameter, false, true);
if (hover != null) {
hover.setRange(range);
}

View File

@@ -15,7 +15,6 @@ import java.util.Collections;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Stream;
import org.eclipse.jdt.core.Flags;
import org.eclipse.jdt.core.dom.ASTNode;
@@ -35,6 +34,7 @@ import org.springframework.ide.vscode.boot.java.links.SourceLinks;
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.boot.app.cli.livebean.LiveBean;
import org.springframework.ide.vscode.commons.boot.app.cli.livebean.LiveBeansModel;
import org.springframework.ide.vscode.commons.java.IJavaProject;
import org.springframework.ide.vscode.commons.util.BadLocationException;
import org.springframework.ide.vscode.commons.util.StringUtil;
@@ -102,18 +102,18 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP
}
@Override
public Collection<CodeLens> getLiveHintCodeLenses(IJavaProject project, TypeDeclaration typeDeclaration, TextDocument doc,
SpringBootApp[] runningApps) {
public Collection<CodeLens> getLiveHintCodeLenses(IJavaProject project, TypeDeclaration typeDeclaration,
TextDocument doc, SpringBootApp[] runningApps) {
if (runningApps.length > 0 && !isComponentAnnotatedType(typeDeclaration)) {
try {
LiveBean definedBean = getDefinedBeanForType(typeDeclaration, null);
if (definedBean != null) {
if (Stream.of(runningApps).anyMatch(app -> LiveHoverUtils.hasRelevantBeans(app, definedBean))) {
Optional<Range> nameRange = Optional.of(ASTUtils.nodeRegion(doc, typeDeclaration.getName()).asRange());
if (nameRange.isPresent()) {
List<CodeLens> codeLenses = assembleCodeLenses(project, runningApps, definedBean, doc, nameRange.get(), typeDeclaration);
return codeLenses.isEmpty() ? ImmutableList.of(new CodeLens(nameRange.get())) : codeLenses;
}
ITypeBinding beanType = typeDeclaration.resolveBinding();
if (beanType != null) {
String id = getBeanId(null, beanType, Flags.isStatic(typeDeclaration.getModifiers()));
Optional<Range> nameRange = Optional.of(ASTUtils.nodeRegion(doc, typeDeclaration.getName()).asRange());
if (nameRange.isPresent()) {
List<CodeLens> codeLenses = assembleCodeLenses(project, runningApps, app -> definedBean(app, getBeanType(beanType), id), doc,
nameRange.get(), typeDeclaration);
return codeLenses.isEmpty() ? ImmutableList.of(new CodeLens(nameRange.get())) : codeLenses;
}
}
} catch (Exception e) {
@@ -122,16 +122,34 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP
}
return ImmutableList.of();
}
private LiveBean definedBean(SpringBootApp app, String beanType, String possibleId) {
LiveBeansModel beans = app.getBeans();
if (beans != null) {
if (beans.getBeansOfName(possibleId).isEmpty()) {
// try bean type if there is only one bean of such type
List<LiveBean> liveBeanCandidates = beans.getBeansOfType(beanType);
if (liveBeanCandidates.size() == 1) {
return liveBeanCandidates.get(0);
}
} else {
// Just construct defined bean ourselves
return LiveBean.builder().id(possibleId).type(beanType).build();
}
}
return null;
}
@Override
public Hover provideHover(ASTNode node, TypeDeclaration typeDeclaration, ITypeBinding type, int offset,
TextDocument doc, IJavaProject project, SpringBootApp[] runningApps) {
if (runningApps.length > 0 && !isComponentAnnotatedType(typeDeclaration)) {
LiveBean definedBean = getDefinedBeanForType(typeDeclaration, null);
if (definedBean != null) {
Hover hover = assembleHover(project, runningApps, definedBean, typeDeclaration, true, true);
ITypeBinding beanType = typeDeclaration.resolveBinding();
if (beanType != null) {
String id = getBeanId(null, beanType, Flags.isStatic(typeDeclaration.getModifiers()));
Hover hover = assembleHover(project, runningApps, app -> definedBean(app, getBeanType(beanType), id), typeDeclaration, true, true);
if (hover != null) {
SimpleName name = typeDeclaration.getName();
try {

View File

@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 2018 Pivotal, Inc.
* Copyright (c) 2018, 2019 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
@@ -141,6 +141,110 @@ public class BeansByTypeHoverProviderTest {
"Process [PID=111, name=`the-app`]"
);
}
@Test
public void beanWithNonStandardId() throws Exception {
LiveBeansModel beans = LiveBeansModel.builder()
.add(LiveBean.builder()
.id("random")
.type("com.example.ScannedRandomClass")
.build()
)
.add(LiveBean.builder()
.id("randomOtherBean")
.type("randomOtherBeanType")
.dependencies("random")
.build()
)
.add(LiveBean.builder()
.id("irrelevantBean")
.type("com.example.IrrelevantBean")
.dependencies("myController")
.build()
)
.build();
mockAppProvider.builder()
.isSpringBootApp(true)
.processId("111")
.processName("the-app")
.beans(beans)
.build();
Editor editor = harness.newEditor(LanguageId.JAVA,
"package com.example;\n" +
"\n" +
"import java.io.Serializable;\n" +
"\n" +
"public class ScannedRandomClass implements Serializable {\n" +
"\n" +
" public String apply(String t) {\n" +
" return t.toUpperCase();\n" +
" }\n" +
"\n" +
"}\n" +
""
);
editor.assertHighlights("ScannedRandomClass");
editor.assertTrimmedHover("ScannedRandomClass",
"**&#8594; `randomOtherBeanType`**\n" +
"- Bean: `randomOtherBean` \n" +
" Type: `randomOtherBeanType`\n" +
" \n" +
"Bean id: `random` \n" +
"Process [PID=111, name=`the-app`]"
);
}
@Test
public void beansWithNonStandardIdMoreThanOneOfSameType() throws Exception {
LiveBeansModel beans = LiveBeansModel.builder()
.add(LiveBean.builder()
.id("random")
.type("com.example.ScannedRandomClass")
.build()
)
.add(LiveBean.builder()
.id("anotherRandom")
.type("com.example.ScannedRandomClass")
.build()
)
.add(LiveBean.builder()
.id("randomOtherBean")
.type("randomOtherBeanType")
.dependencies("random")
.build()
)
.add(LiveBean.builder()
.id("irrelevantBean")
.type("com.example.IrrelevantBean")
.dependencies("anotherRandom")
.build()
)
.build();
mockAppProvider.builder()
.isSpringBootApp(true)
.processId("111")
.processName("the-app")
.beans(beans)
.build();
Editor editor = harness.newEditor(LanguageId.JAVA,
"package com.example;\n" +
"\n" +
"import java.io.Serializable;\n" +
"\n" +
"public class ScannedRandomClass implements Serializable {\n" +
"\n" +
" public String apply(String t) {\n" +
" return t.toUpperCase();\n" +
" }\n" +
"\n" +
"}\n" +
""
);
editor.assertHighlights();
editor.assertNoHover("ScannedRandomClass");
}
@Test
public void scannedAndInjectedFunction() throws Exception {