GH-1381: support Go To Definition for ConditionalOnMissingBean, focus in name attribute, and support value arrays
This commit is contained in:
@@ -19,6 +19,8 @@ import org.eclipse.jdt.core.dom.ASTNode;
|
||||
import org.eclipse.jdt.core.dom.Annotation;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
import org.eclipse.jdt.core.dom.IAnnotationBinding;
|
||||
import org.eclipse.jdt.core.dom.ITypeBinding;
|
||||
import org.eclipse.jdt.core.dom.MemberValuePair;
|
||||
import org.eclipse.jdt.core.dom.StringLiteral;
|
||||
import org.eclipse.lsp4j.LocationLink;
|
||||
import org.eclipse.lsp4j.TextDocumentIdentifier;
|
||||
@@ -51,19 +53,62 @@ public class ConditionalOnBeanDefinitionProvider implements IJavaDefinitionProvi
|
||||
if (parent != null && parent instanceof Annotation) {
|
||||
Annotation a = (Annotation) parent;
|
||||
IAnnotationBinding binding = a.resolveAnnotationBinding();
|
||||
if (binding != null && binding.getAnnotationType() != null && Annotations.CONDITIONAL_ON_BEAN.equals(binding.getAnnotationType().getQualifiedName())) {
|
||||
String beanName = valueNode.getLiteralValue();
|
||||
|
||||
if (beanName != null && beanName.length() > 0) {
|
||||
return findBeansWithName(project, beanName);
|
||||
}
|
||||
if (binding != null) {
|
||||
ITypeBinding annotationType = binding.getAnnotationType();
|
||||
if (annotationType != null) {
|
||||
String annotationTypeQualifiedName = annotationType.getQualifiedName();
|
||||
|
||||
if (Annotations.CONDITIONAL_ON_BEAN.equals(annotationTypeQualifiedName)
|
||||
|| Annotations.CONDITIONAL_ON_MISSING_BEAN.equals(annotationTypeQualifiedName)) {
|
||||
|
||||
return getDefinitions(project, valueNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<LocationLink> findBeansWithName(IJavaProject project, String beanName) {
|
||||
private List<LocationLink> getDefinitions(IJavaProject project, StringLiteral valueNode) {
|
||||
String value = valueNode.getLiteralValue();
|
||||
|
||||
if (value != null && value.length() > 0) {
|
||||
return getDefinitionsForValue(project, valueNode, value);
|
||||
}
|
||||
else {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
}
|
||||
|
||||
private List<LocationLink> getDefinitionsForValue(IJavaProject project, StringLiteral valueNode, String value) {
|
||||
ASTNode parent = valueNode.getParent();
|
||||
if (parent != null && !(parent instanceof MemberValuePair)) {
|
||||
parent = parent.getParent();
|
||||
}
|
||||
|
||||
if (parent != null && parent instanceof MemberValuePair) {
|
||||
MemberValuePair pair = (MemberValuePair) parent;
|
||||
String name = pair.getName().toString();
|
||||
|
||||
if ("name".equals(name)) {
|
||||
return findBeansWithName(project, value);
|
||||
}
|
||||
else if ("type".equals(name) ||"ignoredType".equals(name)) {
|
||||
return findBeanTypesWithName(project, value);
|
||||
}
|
||||
}
|
||||
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<LocationLink> findBeanTypesWithName(IJavaProject project, String value) {
|
||||
// TODO
|
||||
return Collections.emptyList();
|
||||
}
|
||||
|
||||
private List<LocationLink> findBeansWithName(IJavaProject project, String beanName) {
|
||||
Bean[] beans = this.springIndex.getBeansWithName(project.getElementName(), beanName);
|
||||
|
||||
return Arrays.stream(beans)
|
||||
|
||||
@@ -79,24 +79,109 @@ public class ConditionalOnBeanDefinitionProviderTest {
|
||||
|
||||
@Configuration
|
||||
public class TestConditionalOnBeanCompletion {
|
||||
@ConditionalOnBean(name="bean1")
|
||||
@ConditionalOnBean(name = "bean1")
|
||||
@Bean
|
||||
public void method() {
|
||||
}
|
||||
}""", tempJavaDocUri);
|
||||
|
||||
String expectedDefinitionUri = directory.toPath().resolve("src/main/java/org/test/MainClass.java").toUri().toString();
|
||||
|
||||
Bean[] beans = springIndex.getBeansWithName(project.getElementName(), "bean1");
|
||||
assertEquals(1, beans.length);
|
||||
|
||||
LocationLink expectedLocation = new LocationLink(expectedDefinitionUri,
|
||||
LocationLink expectedLocation = new LocationLink(beans[0].getLocation().getUri(),
|
||||
beans[0].getLocation().getRange(), beans[0].getLocation().getRange(),
|
||||
null);
|
||||
|
||||
editor.assertLinkTargets("bean1", List.of(expectedLocation));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionalOnMissingBeanWithNameRefersToBeanDefinitionLink() throws Exception {
|
||||
String tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TempClass.java").toUri().toString();
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA, """
|
||||
package org.test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TestConditionalOnBeanCompletion {
|
||||
@ConditionalOnMissingBean(name = "bean1")
|
||||
@Bean
|
||||
public void method() {
|
||||
}
|
||||
}""", tempJavaDocUri);
|
||||
|
||||
Bean[] beans = springIndex.getBeansWithName(project.getElementName(), "bean1");
|
||||
assertEquals(1, beans.length);
|
||||
|
||||
LocationLink expectedLocation = new LocationLink(beans[0].getLocation().getUri(),
|
||||
beans[0].getLocation().getRange(), beans[0].getLocation().getRange(),
|
||||
null);
|
||||
|
||||
editor.assertLinkTargets("bean1", List.of(expectedLocation));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionalOnBeanWithNameArrayRefersToBeanDefinitionLink() throws Exception {
|
||||
String tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TempClass.java").toUri().toString();
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA, """
|
||||
package org.test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TestConditionalOnBeanCompletion {
|
||||
@ConditionalOnBean(name = {"bean1", "bean2"})
|
||||
@Bean
|
||||
public void method() {
|
||||
}
|
||||
}""", tempJavaDocUri);
|
||||
|
||||
Bean[] beans = springIndex.getBeansWithName(project.getElementName(), "bean2");
|
||||
assertEquals(1, beans.length);
|
||||
|
||||
LocationLink expectedLocation = new LocationLink(beans[0].getLocation().getUri(),
|
||||
beans[0].getLocation().getRange(), beans[0].getLocation().getRange(),
|
||||
null);
|
||||
|
||||
editor.assertLinkTargets("bean2", List.of(expectedLocation));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionalOnMissingBeanWithNameArrayRefersToBeanDefinitionLink() throws Exception {
|
||||
String tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TempClass.java").toUri().toString();
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA, """
|
||||
package org.test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TestConditionalOnBeanCompletion {
|
||||
@ConditionalOnMissingBean(name = {"bean1", "bean2"})
|
||||
@Bean
|
||||
public void method() {
|
||||
}
|
||||
}""", tempJavaDocUri);
|
||||
|
||||
Bean[] beans = springIndex.getBeansWithName(project.getElementName(), "bean2");
|
||||
assertEquals(1, beans.length);
|
||||
|
||||
LocationLink expectedLocation = new LocationLink(beans[0].getLocation().getUri(),
|
||||
beans[0].getLocation().getRange(), beans[0].getLocation().getRange(),
|
||||
null);
|
||||
|
||||
editor.assertLinkTargets("bean2", List.of(expectedLocation));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionalOnBeanRefersToRandomBeanWithoutDefinitionLink() throws Exception {
|
||||
String tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TempClass.java").toUri().toString();
|
||||
@@ -110,7 +195,7 @@ public class ConditionalOnBeanDefinitionProviderTest {
|
||||
|
||||
@Configuration
|
||||
public class TestConditionalOnBeanCompletion {
|
||||
@ConditionalOnBean(name="bean5")
|
||||
@ConditionalOnBean(name = "bean5")
|
||||
@Bean
|
||||
public void method() {
|
||||
}
|
||||
@@ -119,4 +204,70 @@ public class ConditionalOnBeanDefinitionProviderTest {
|
||||
editor.assertNoLinkTargets("bean5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionalOnMissingBeanRefersToRandomBeanWithoutDefinitionLink() throws Exception {
|
||||
String tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TempClass.java").toUri().toString();
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA, """
|
||||
package org.test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TestConditionalOnBeanCompletion {
|
||||
@ConditionalOnMissingBean(name = "bean5")
|
||||
@Bean
|
||||
public void method() {
|
||||
}
|
||||
}""", tempJavaDocUri);
|
||||
|
||||
editor.assertNoLinkTargets("bean5");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionalOnBeanUsesTypeInsteadOfBeanNameSoNoDefinitionLink() throws Exception {
|
||||
String tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TempClass.java").toUri().toString();
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA, """
|
||||
package org.test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TestConditionalOnBeanCompletion {
|
||||
@ConditionalOnBean(type = "bean1")
|
||||
@Bean
|
||||
public void method() {
|
||||
}
|
||||
}""", tempJavaDocUri);
|
||||
|
||||
editor.assertNoLinkTargets("bean1");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testConditionalOnMissingBeanUsesTypeInsteadOfBeanNameSoNoDefinitionLink() throws Exception {
|
||||
String tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TempClass.java").toUri().toString();
|
||||
|
||||
Editor editor = harness.newEditor(LanguageId.JAVA, """
|
||||
package org.test;
|
||||
|
||||
import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
|
||||
@Configuration
|
||||
public class TestConditionalOnBeanCompletion {
|
||||
@ConditionalOnMissingBean(type = "bean1")
|
||||
@Bean
|
||||
public void method() {
|
||||
}
|
||||
}""", tempJavaDocUri);
|
||||
|
||||
editor.assertNoLinkTargets("bean1");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user