PT #164318678: Live hovers for beans with non-standard ids
This commit is contained in:
@@ -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) {
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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",
|
||||
"**→ `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 {
|
||||
|
||||
Reference in New Issue
Block a user