Improve @Autowired for hover inside of @Component class.
This commit is contained in:
@@ -22,7 +22,9 @@ import org.eclipse.jdt.core.dom.TypeDeclaration;
|
||||
import org.eclipse.lsp4j.Hover;
|
||||
import org.eclipse.lsp4j.Range;
|
||||
import org.eclipse.lsp4j.jsonrpc.messages.Either;
|
||||
import org.springframework.ide.vscode.boot.java.Annotations;
|
||||
import org.springframework.ide.vscode.boot.java.handlers.HoverProvider;
|
||||
import org.springframework.ide.vscode.boot.java.livehover.ComponentInjectionsHoverProvider;
|
||||
import org.springframework.ide.vscode.boot.java.livehover.LiveHoverUtils;
|
||||
import org.springframework.ide.vscode.boot.java.utils.ASTUtils;
|
||||
import org.springframework.ide.vscode.commons.boot.app.cli.SpringBootApp;
|
||||
@@ -106,7 +108,6 @@ public class AutowiredHoverProvider implements HoverProvider {
|
||||
}
|
||||
}
|
||||
if (hasInterestingApp && hasAutowiring) {
|
||||
System.out.println(hover);
|
||||
return CompletableFuture
|
||||
.completedFuture(new Hover(ImmutableList.of(Either.forLeft(hover.toString()))));
|
||||
}
|
||||
@@ -115,25 +116,31 @@ public class AutowiredHoverProvider implements HoverProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
private LiveBean getDefinedBean(Annotation annotation) {
|
||||
TypeDeclaration declaringType = ASTUtils.findDeclaringType(annotation);
|
||||
private LiveBean getDefinedBean(Annotation autowiredAnnotation) {
|
||||
TypeDeclaration declaringType = ASTUtils.findDeclaringType(autowiredAnnotation);
|
||||
if (declaringType != null) {
|
||||
ITypeBinding beanType = declaringType.resolveBinding();
|
||||
if (beanType != null) {
|
||||
String id = getBeanId(declaringType, beanType);
|
||||
if (StringUtil.hasText(id)) {
|
||||
return LiveBean.builder().id(id).type(beanType.getQualifiedName()).build();
|
||||
for (Annotation annotation : ASTUtils.getAnnotations(declaringType)) {
|
||||
String annotationType = ASTUtils.getAnnotationType(annotation);
|
||||
switch (annotationType) {
|
||||
case Annotations.COMPONENT:
|
||||
return ComponentInjectionsHoverProvider.getDefinedBeanForComponent(annotation);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getBeanId(TypeDeclaration declaringType, ITypeBinding beanType) {
|
||||
// TODO: take specific bean declarations into account like @Component at declaring type
|
||||
String typeName = beanType.getName();
|
||||
if (StringUtil.hasText(typeName)) {
|
||||
return Character.toLowerCase(typeName.charAt(0)) + typeName.substring(1);
|
||||
//TODO: handler below is an attempt to do something that may work in many cases, but is probably
|
||||
// missing logics for special cases where annotation attributes on the declaring type matter.
|
||||
ITypeBinding beanType = declaringType.resolveBinding();
|
||||
if (beanType!=null) {
|
||||
String beanTypeName = beanType.getName();
|
||||
if (StringUtil.hasText(beanTypeName)) {
|
||||
return LiveBean.builder()
|
||||
.id(Character.toLowerCase(beanTypeName.charAt(0)) + beanTypeName.substring(1))
|
||||
.type(beanTypeName)
|
||||
.build();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -87,7 +87,6 @@ public abstract class AbstractInjectedIntoHoverProvider implements HoverProvider
|
||||
}
|
||||
}
|
||||
if (hasInterestingApp) {
|
||||
System.out.println(hover);
|
||||
return CompletableFuture
|
||||
.completedFuture(new Hover(ImmutableList.of(Either.forLeft(hover.toString()))));
|
||||
}
|
||||
|
||||
@@ -68,6 +68,11 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP
|
||||
|
||||
@Override
|
||||
protected LiveBean getDefinedBean(Annotation annotation) {
|
||||
return getDefinedBeanForComponent(annotation);
|
||||
}
|
||||
|
||||
public static LiveBean getDefinedBeanForComponent(Annotation annotation) {
|
||||
//Move to ASTUtils?
|
||||
TypeDeclaration declaringType = ASTUtils.getAnnotatedType(annotation);
|
||||
if (declaringType != null) {
|
||||
ITypeBinding beanType = declaringType.resolveBinding();
|
||||
@@ -81,7 +86,7 @@ public class ComponentInjectionsHoverProvider extends AbstractInjectedIntoHoverP
|
||||
return null;
|
||||
}
|
||||
|
||||
private String getBeanId(Annotation annotation, ITypeBinding beanType) {
|
||||
private static String getBeanId(Annotation annotation, ITypeBinding beanType) {
|
||||
return ASTUtils.getAttribute(annotation, "value").flatMap(ASTUtils::getFirstString)
|
||||
.orElseGet(() -> {
|
||||
String typeName = beanType.getName();
|
||||
|
||||
@@ -11,14 +11,17 @@
|
||||
package org.springframework.ide.vscode.boot.java.utils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.ArrayInitializer;
|
||||
import org.eclipse.jdt.core.dom.Expression;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MemberValuePair;
|
||||
import org.eclipse.jdt.core.dom.MethodDeclaration;
|
||||
import org.eclipse.jdt.core.dom.NormalAnnotation;
|
||||
@@ -32,6 +35,8 @@ import org.springframework.ide.vscode.commons.languageserver.util.DocumentRegion
|
||||
import org.springframework.ide.vscode.commons.util.Log;
|
||||
import org.springframework.ide.vscode.commons.util.text.TextDocument;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
|
||||
public class ASTUtils {
|
||||
|
||||
public static DocumentRegion nameRegion(TextDocument doc, Annotation annotation) {
|
||||
@@ -161,8 +166,7 @@ public class ASTUtils {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public
|
||||
static String[] getExpressionValueAsArray(Expression exp) {
|
||||
public static String[] getExpressionValueAsArray(Expression exp) {
|
||||
if (exp instanceof ArrayInitializer) {
|
||||
ArrayInitializer array = (ArrayInitializer) exp;
|
||||
return ((List<Expression>) array.expressions()).stream().map(e -> getExpressionValueAsString(e))
|
||||
@@ -176,4 +180,28 @@ public class ASTUtils {
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
public static Collection<Annotation> getAnnotations(TypeDeclaration declaringType) {
|
||||
Object modifiersObj = declaringType.getStructuralProperty(TypeDeclaration.MODIFIERS2_PROPERTY);
|
||||
if (modifiersObj instanceof List) {
|
||||
ImmutableList.Builder<Annotation> annotations = ImmutableList.builder();
|
||||
for (Object node : (List<?>)modifiersObj) {
|
||||
if (node instanceof Annotation) {
|
||||
annotations.add((Annotation) node);
|
||||
}
|
||||
}
|
||||
return annotations.build();
|
||||
}
|
||||
return ImmutableList.of();
|
||||
}
|
||||
|
||||
|
||||
public static String getAnnotationType(Annotation annotation) {
|
||||
ITypeBinding binding = annotation.resolveTypeBinding();
|
||||
if (binding!=null) {
|
||||
return binding.getQualifiedName();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -241,4 +241,67 @@ public class AutowiredHoverProviderTest {
|
||||
editor.assertNoHover("@Autowired");
|
||||
}
|
||||
|
||||
@Test public void bug_152553935() throws Exception {
|
||||
//https://www.pivotaltracker.com/story/show/152553935
|
||||
LiveBeansModel beans = LiveBeansModel.builder()
|
||||
.add(LiveBean.builder()
|
||||
.id("defaultFoo")
|
||||
.type("com.example.FooImplementation")
|
||||
.dependencies("defaultFoo")
|
||||
.dependencies("otherBean")
|
||||
.build()
|
||||
)
|
||||
.add(LiveBean.builder()
|
||||
.id("otherBean")
|
||||
.type("com.example.DependencyA")
|
||||
.build()
|
||||
)
|
||||
.build();
|
||||
mockAppProvider.builder()
|
||||
.isSpringBootApp(true)
|
||||
.processId("111")
|
||||
.processName("the-app")
|
||||
.beans(beans)
|
||||
.build();
|
||||
|
||||
|
||||
Editor editor = harness.newEditor(
|
||||
"package com.example;\n" +
|
||||
"\n" +
|
||||
"import org.springframework.beans.factory.annotation.Autowired;\n" +
|
||||
"import org.springframework.scheduling.TaskScheduler;\n" +
|
||||
"import org.springframework.stereotype.Component;\n" +
|
||||
"\n" +
|
||||
"@Component(\"defaultFoo\")\n" +
|
||||
"public class FooImplementation implements Foo {\n" +
|
||||
" \n" +
|
||||
" private TaskScheduler scheduler;\n" +
|
||||
" \n" +
|
||||
" @Autowired Foo self;\n" +
|
||||
" \n" +
|
||||
" @Override\n" +
|
||||
" public void doSomeFoo() {\n" +
|
||||
" scheduler.scheduleWithFixedDelay(() -> {\n" +
|
||||
" System.out.println(\"Doo Done done!\");\n" +
|
||||
" }, 1000);\n" +
|
||||
" System.out.println(\"Foo do do do do!\");\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
" @Autowired\n" +
|
||||
" public void setScheduler(TaskScheduler scheduler) {\n" +
|
||||
" this.scheduler = scheduler;\n" +
|
||||
" }\n" +
|
||||
"\n" +
|
||||
"}"
|
||||
);
|
||||
editor.assertHighlights("@Component", "@Autowired", "@Autowired");
|
||||
for (int i = 1; i <= 2; i++) {
|
||||
editor.assertHoverContains("@Autowired", 1,
|
||||
"Bean [id: defaultFoo, type: `com.example.FooImplementation`] got autowired with:\n" +
|
||||
"\n" +
|
||||
"- Bean: otherBean \n" +
|
||||
" Type: `com.example.DependencyA`");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user