Skip to content

Commit 0f854a9

Browse files
committed
adjusted handling of named annotation to not take beans without named annotatin into account
1 parent e1b831e commit 0f854a9

File tree

6 files changed

+99
-75
lines changed

6 files changed

+99
-75
lines changed

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/NamedCompletionProvider.java

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -39,9 +39,7 @@ public List<AnnotationAttributeProposal> getCompletionCandidates(IJavaProject pr
3939

4040
Bean[] beans = this.springIndex.getBeansOfProject(project.getElementName());
4141

42-
return Stream.concat(
43-
findAllNamedValues(beans),
44-
Arrays.stream(beans).map(bean -> bean.getName()))
42+
return findAllNamedValues(beans)
4543
.distinct()
4644
.map(beanName -> new AnnotationAttributeProposal(beanName))
4745
.collect(Collectors.toList());

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/NamedDefinitionProvider.java

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,12 +14,14 @@
1414
import java.util.Collections;
1515
import java.util.List;
1616
import java.util.stream.Collectors;
17+
import java.util.stream.Stream;
1718

1819
import org.eclipse.jdt.core.dom.ASTNode;
1920
import org.eclipse.jdt.core.dom.Annotation;
2021
import org.eclipse.jdt.core.dom.CompilationUnit;
2122
import org.eclipse.jdt.core.dom.IAnnotationBinding;
2223
import org.eclipse.jdt.core.dom.StringLiteral;
24+
import org.eclipse.lsp4j.Location;
2325
import org.eclipse.lsp4j.LocationLink;
2426
import org.eclipse.lsp4j.TextDocumentIdentifier;
2527
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
@@ -64,12 +66,18 @@ public List<LocationLink> getDefinitions(CancelChecker cancelToken, IJavaProject
6466
}
6567

6668
private List<LocationLink> findBeansWithName(IJavaProject project, String beanName) {
67-
Bean[] beans = this.springIndex.getBeansWithName(project.getElementName(), beanName);
69+
Bean[] beans = this.springIndex.getBeansOfProject(project.getElementName());
6870

69-
return Arrays.stream(beans)
70-
.map(bean -> {
71-
return new LocationLink(bean.getLocation().getUri(), bean.getLocation().getRange(), bean.getLocation().getRange());
72-
})
71+
Stream<Location> namedLocationFromBeans = Arrays.stream(beans)
72+
// annotations from beans themselves
73+
.flatMap(bean -> Arrays.stream(bean.getAnnotations()))
74+
.filter(annotation -> Annotations.NAMED_ANNOTATIONS.contains(annotation.getAnnotationType()))
75+
.filter(annotation -> annotation.getAttributes() != null && annotation.getAttributes().containsKey("value") && annotation.getAttributes().get("value").length == 1)
76+
.filter(annotation -> annotation.getAttributes().get("value")[0].getName().equals(beanName))
77+
.map(annotation -> annotation.getAttributes().get("value")[0].getLocation());
78+
79+
return namedLocationFromBeans
80+
.map(location -> new LocationLink(location.getUri(), location.getRange(), location.getRange()))
7381
.collect(Collectors.toList());
7482
}
7583

headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/NamedReferencesProvider.java

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -71,11 +71,6 @@ else if (node instanceof StringLiteral && node.getParent() instanceof MemberValu
7171
private List<? extends Location> provideReferences(IJavaProject project, String value) {
7272
Bean[] beans = this.springIndex.getBeansOfProject(project.getElementName());
7373

74-
// beans with name
75-
Stream<Location> beanLocations = Arrays.stream(beans)
76-
.filter(bean -> bean.getName().equals(value))
77-
.map(bean -> bean.getLocation());
78-
7974
Stream<Location> namedLocationFromBeans = Arrays.stream(beans)
8075
// annotations from beans themselves
8176
.flatMap(bean -> Arrays.stream(bean.getAnnotations()))
@@ -95,7 +90,7 @@ private List<? extends Location> provideReferences(IJavaProject project, String
9590
.filter(annotation -> annotation.getAttributes().get("value")[0].getName().equals(value))
9691
.map(annotation -> annotation.getAttributes().get("value")[0].getLocation());
9792

98-
return Stream.concat(beanLocations, Stream.concat(namedLocationFromBeans, namedLocationsFromInjectionPoints)).toList();
93+
return Stream.concat(namedLocationFromBeans, namedLocationsFromInjectionPoints).toList();
9994
}
10095

10196
}

headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/NamedCompletionProviderTest.java

Lines changed: 16 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -95,53 +95,53 @@ public void restoreIndexState() {
9595
}
9696

9797
@Test
98-
public void testQualifierCompletionWithoutQuotesWithoutPrefix() throws Exception {
99-
assertCompletions("@Named(<*>)", new String[] {"named1", "named2", "bean1", "bean2"}, 0, "@Named(\"named1\"<*>)");
98+
public void testNamedCompletionWithoutQuotesWithoutPrefix() throws Exception {
99+
assertCompletions("@Named(<*>)", new String[] {"named1", "named2"}, 0, "@Named(\"named1\"<*>)");
100100
}
101101

102102
@Test
103-
public void testQualifierCompletionWithoutQuotesWithPrefix() throws Exception {
104-
assertCompletions("@Named(be<*>)", 2, "@Named(\"bean1\"<*>)");
103+
public void testNamedCompletionWithoutQuotesWithPrefix() throws Exception {
104+
assertCompletions("@Named(be<*>)", 0, null);
105105
}
106106

107107
@Test
108-
public void testQualifierCompletionWithoutQuotesWithPrefixFromExistingQualifier() throws Exception {
108+
public void testNamedCompletionWithoutQuotesWithPrefixFromExistingQualifier() throws Exception {
109109
assertCompletions("@Named(na<*>)", new String[] {"named1", "named2"}, 0, "@Named(\"named1\"<*>)");
110110
}
111111

112112
@Test
113-
public void testQualifierCompletionWithoutQuotesWithAttributeName() throws Exception {
114-
assertCompletions("@Named(value=<*>)", 4, "@Named(value=\"named1\"<*>)");
113+
public void testNamedCompletionWithoutQuotesWithAttributeName() throws Exception {
114+
assertCompletions("@Named(value=<*>)", 2, "@Named(value=\"named1\"<*>)");
115115
}
116116

117117
@Test
118-
public void testQualifierCompletionInsideOfQuotesWithoutPrefix() throws Exception {
119-
assertCompletions("@Named(\"<*>\")", 4, "@Named(\"named1<*>\")");
118+
public void testNamedCompletionInsideOfQuotesWithoutPrefix() throws Exception {
119+
assertCompletions("@Named(\"<*>\")", 2, "@Named(\"named1<*>\")");
120120
}
121121

122122
@Test
123-
public void testQualifierCompletionInsideOfQuotesWithPrefix() throws Exception {
124-
assertCompletions("@Named(\"be<*>\")", 2, "@Named(\"bean1<*>\")");
123+
public void testNAmedCompletionInsideOfQuotesWithPrefix() throws Exception {
124+
assertCompletions("@Named(\"na<*>\")", 2, "@Named(\"named1<*>\")");
125125
}
126126

127127
@Test
128-
public void testQualifierCompletionInsideOfQuotesWithPrefixButWithoutMatches() throws Exception {
128+
public void testNamedCompletionInsideOfQuotesWithPrefixButWithoutMatches() throws Exception {
129129
assertCompletions("@Named(\"XXX<*>\")", 0, null);
130130
}
131131

132132
@Test
133-
public void testQualifierCompletionOutsideOfAnnotation1() throws Exception {
133+
public void testNamedCompletionOutsideOfAnnotation1() throws Exception {
134134
assertCompletions("@Named(\"XXX\")<*>", 0, null);
135135
}
136136

137137
@Test
138-
public void testQualifierCompletionOutsideOfAnnotation2() throws Exception {
138+
public void testNamedCompletionOutsideOfAnnotation2() throws Exception {
139139
assertCompletions("@Named<*>(\"XXX\")", 0, null);
140140
}
141141

142142
@Test
143-
public void testQualifierCompletionInsideOfQuotesWithPrefixAndReplacedPostfix() throws Exception {
144-
assertCompletions("@Named(\"be<*>xxx\")", 2, "@Named(\"bean1<*>\")");
143+
public void testNamedCompletionInsideOfQuotesWithPrefixAndReplacedPostfix() throws Exception {
144+
assertCompletions("@Named(\"na<*>xxx\")", 2, "@Named(\"named1<*>\")");
145145
}
146146

147147
private void assertCompletions(String completionLine, int noOfExpectedCompletions, String expectedCompletedLine) throws Exception {

headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/NamedDefinitionProviderTest.java

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,9 @@
1010
*******************************************************************************/
1111
package org.springframework.ide.vscode.boot.java.beans.test;
1212

13-
import static org.junit.Assert.assertEquals;
14-
1513
import java.io.File;
1614
import java.util.List;
15+
import java.util.Map;
1716
import java.util.concurrent.CompletableFuture;
1817
import java.util.concurrent.TimeUnit;
1918

@@ -33,6 +32,7 @@
3332
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
3433
import org.springframework.ide.vscode.commons.java.IJavaProject;
3534
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
35+
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationAttributeValue;
3636
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata;
3737
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
3838
import org.springframework.ide.vscode.commons.util.text.LanguageId;
@@ -62,6 +62,8 @@ public class NamedDefinitionProviderTest {
6262
private String tempJavaDocUri1;
6363
private String tempJavaDocUri2;
6464
private String tempJavaDocUri;
65+
private Location locationNamedAnnotation1;
66+
private Location locationNamedAnnotation2;
6567

6668
@BeforeEach
6769
public void setup() throws Exception {
@@ -79,8 +81,14 @@ public void setup() throws Exception {
7981
tempJavaDocUri1 = directory.toPath().resolve("src/main/java/org/test/TempClass1.java").toUri().toString();
8082
tempJavaDocUri2 = directory.toPath().resolve("src/main/java/org/test/TempClass2.java").toUri().toString();
8183

82-
bean1 = new Bean("bean1", "type1", new Location(tempJavaDocUri1, new Range(new Position(1,1), new Position(1, 20))), null, null, new AnnotationMetadata[] {});
83-
bean2 = new Bean("bean2", "type2", new Location(tempJavaDocUri2, new Range(new Position(1,1), new Position(1, 20))), null, null, new AnnotationMetadata[] {});
84+
locationNamedAnnotation1 = new Location(tempJavaDocUri1, new Range(new Position(1, 10), new Position(1, 20)));
85+
locationNamedAnnotation2 = new Location(tempJavaDocUri2, new Range(new Position(2, 10), new Position(2, 20)));
86+
87+
AnnotationMetadata annotationBean1 = new AnnotationMetadata("jakarta.inject.Named", false, null, Map.of("value", new AnnotationAttributeValue[] {new AnnotationAttributeValue("named1", locationNamedAnnotation1)}));
88+
AnnotationMetadata annotationBean2 = new AnnotationMetadata("jakarta.inject.Named", false, null, Map.of("value", new AnnotationAttributeValue[] {new AnnotationAttributeValue("named2", locationNamedAnnotation2)}));
89+
90+
bean1 = new Bean("bean1", "type1", new Location(tempJavaDocUri1, new Range(new Position(1,1), new Position(1, 20))), null, null, new AnnotationMetadata[] {annotationBean1});
91+
bean2 = new Bean("bean2", "type2", new Location(tempJavaDocUri2, new Range(new Position(1,1), new Position(1, 20))), null, null, new AnnotationMetadata[] {annotationBean2});
8492

8593
springIndex.updateBeans(project.getElementName(), new Bean[] {bean1, bean2});
8694
}
@@ -92,18 +100,15 @@ public void testNamedClassRefersToBeanDefinitionLink() throws Exception {
92100
93101
import jakarta.inject.Named;
94102
95-
@Named("bean1")
103+
@Named("named1")
96104
public class TestDependsOnClass {
97105
}""", tempJavaDocUri);
98106

99-
Bean[] beans = springIndex.getBeansWithName(project.getElementName(), "bean1");
100-
assertEquals(1, beans.length);
101-
102-
LocationLink expectedLocation = new LocationLink(tempJavaDocUri1,
103-
beans[0].getLocation().getRange(), beans[0].getLocation().getRange(),
107+
LocationLink expectedLocation = new LocationLink(locationNamedAnnotation1.getUri(),
108+
locationNamedAnnotation1.getRange(), locationNamedAnnotation1.getRange(),
104109
null);
105110

106-
editor.assertLinkTargets("bean1", List.of(expectedLocation));
111+
editor.assertLinkTargets("named1", List.of(expectedLocation));
107112
}
108113

109114
@Test
@@ -117,19 +122,16 @@ public void testNamedDependencyRefersToBeanDefinitionLink() throws Exception {
117122
@Component
118123
public class TestDependsOnClass {
119124
120-
public void setDependency(@Named("bean1") Object bean) {
125+
public void setDependency(@Named("named1") Object bean) {
121126
}
122127
123128
}""", tempJavaDocUri);
124129

125-
Bean[] beans = springIndex.getBeansWithName(project.getElementName(), "bean1");
126-
assertEquals(1, beans.length);
127-
128-
LocationLink expectedLocation = new LocationLink(tempJavaDocUri1,
129-
beans[0].getLocation().getRange(), beans[0].getLocation().getRange(),
130+
LocationLink expectedLocation = new LocationLink(locationNamedAnnotation1.getUri(),
131+
locationNamedAnnotation1.getRange(), locationNamedAnnotation1.getRange(),
130132
null);
131133

132-
editor.assertLinkTargets("bean1", List.of(expectedLocation));
134+
editor.assertLinkTargets("named1", List.of(expectedLocation));
133135
}
134136

135137
@Test
@@ -143,12 +145,12 @@ public void testNamedDependencyRefersToNonExistingBeanDefinitionLink() throws Ex
143145
@Component
144146
public class TestDependsOnClass {
145147
146-
public void setDependency(@Named("XXX") Object bean1) {
148+
public void setDependency(@Named("bean1") Object bean1) {
147149
}
148150
149151
}""", tempJavaDocUri1);
150152

151-
editor.assertNoLinkTargets("XXX");
153+
editor.assertNoLinkTargets("bean1");
152154
}
153155

154156
}

headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/beans/test/NamedReferencesProviderTest.java

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,15 @@
1111
package org.springframework.ide.vscode.boot.java.beans.test;
1212

1313
import static org.junit.Assert.assertEquals;
14+
import static org.junit.Assert.assertNull;
1415
import static org.junit.Assert.assertTrue;
1516

1617
import java.io.File;
1718
import java.util.List;
19+
import java.util.Map;
1820
import java.util.concurrent.CompletableFuture;
1921
import java.util.concurrent.TimeUnit;
2022

21-
import org.apache.commons.lang3.ArrayUtils;
2223
import org.eclipse.lsp4j.Location;
2324
import org.eclipse.lsp4j.Position;
2425
import org.eclipse.lsp4j.Range;
@@ -34,8 +35,10 @@
3435
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
3536
import org.springframework.ide.vscode.commons.java.IJavaProject;
3637
import org.springframework.ide.vscode.commons.languageserver.java.JavaProjectFinder;
38+
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationAttributeValue;
3739
import org.springframework.ide.vscode.commons.protocol.spring.AnnotationMetadata;
3840
import org.springframework.ide.vscode.commons.protocol.spring.Bean;
41+
import org.springframework.ide.vscode.commons.protocol.spring.InjectionPoint;
3942
import org.springframework.ide.vscode.commons.util.text.LanguageId;
4043
import org.springframework.ide.vscode.languageserver.testharness.Editor;
4144
import org.springframework.ide.vscode.project.harness.BootLanguageServerHarness;
@@ -61,6 +64,11 @@ public class NamedReferencesProviderTest {
6164

6265
private String tempJavaDocUri1;
6366
private String tempJavaDocUri;
67+
private String tempJavaDocUri2;
68+
private Location locationNamedAnnotation1;
69+
private Location locationNamedAnnotation2;
70+
private Bean bean2;
71+
private Location point1NamedAnnotationLocation;
6472

6573
@BeforeEach
6674
public void setup() throws Exception {
@@ -74,63 +82,76 @@ public void setup() throws Exception {
7482
CompletableFuture<Void> initProject = indexer.waitOperation();
7583
initProject.get(5, TimeUnit.SECONDS);
7684

77-
tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TestDependsOnClass.java").toUri().toString();
85+
tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TestDependsOnClass.java").toUri().toString();
7886
tempJavaDocUri1 = directory.toPath().resolve("src/main/java/org/test/TempClass1.java").toUri().toString();
87+
tempJavaDocUri2 = directory.toPath().resolve("src/main/java/org/test/TempClass2.java").toUri().toString();
7988

80-
bean1 = new Bean("bean1", "type1", new Location(tempJavaDocUri1, new Range(new Position(1,1), new Position(1, 20))), null, null, new AnnotationMetadata[] {});
89+
locationNamedAnnotation1 = new Location(tempJavaDocUri1, new Range(new Position(1, 10), new Position(1, 20)));
90+
locationNamedAnnotation2 = new Location(tempJavaDocUri2, new Range(new Position(2, 10), new Position(2, 20)));
8191

82-
Bean[] beans = ArrayUtils.add(springIndex.getBeansOfProject(project.getElementName()), bean1);
83-
springIndex.updateBeans(project.getElementName(), beans);
92+
AnnotationMetadata annotationBean1 = new AnnotationMetadata("jakarta.inject.Named", false, null, Map.of("value", new AnnotationAttributeValue[] {new AnnotationAttributeValue("named1", locationNamedAnnotation1)}));
93+
AnnotationMetadata annotationBean2 = new AnnotationMetadata("jakarta.inject.Named", false, null, Map.of("value", new AnnotationAttributeValue[] {new AnnotationAttributeValue("named2", locationNamedAnnotation2)}));
94+
95+
point1NamedAnnotationLocation = new Location(tempJavaDocUri1, new Range(new Position(20, 10), new Position(20, 20)));
96+
AnnotationMetadata point1Metadata = new AnnotationMetadata("jakarta.inject.Named", false, null, Map.of("value", new AnnotationAttributeValue[] {new AnnotationAttributeValue("namedAtPoint1", point1NamedAnnotationLocation)}));
97+
98+
InjectionPoint point1 = new InjectionPoint("point1", "type1", null, new AnnotationMetadata[] {point1Metadata});
99+
100+
bean1 = new Bean("bean1", "type1", new Location(tempJavaDocUri1, new Range(new Position(1,1), new Position(1, 20))), new InjectionPoint[] {point1}, null, new AnnotationMetadata[] {annotationBean1});
101+
bean2 = new Bean("bean2", "type2", new Location(tempJavaDocUri2, new Range(new Position(1,1), new Position(1, 20))), null, null, new AnnotationMetadata[] {annotationBean2});
102+
103+
springIndex.updateBeans(project.getElementName(), new Bean[] {bean1, bean2});
84104
}
85105

86106
@Test
87-
public void testNamedRefersToBean() throws Exception {
107+
public void testNamedRefersToNamedBean() throws Exception {
88108
Editor editor = harness.newEditor(LanguageId.JAVA, """
89109
package org.test;
90110
91111
import jakarta.inject.Named;
92112
93-
@Named("be<*>an1")
113+
@Named("na<*>med1")
94114
public class TestDependsOnClass {
95115
}""", tempJavaDocUri);
96116

97-
Bean[] beans = springIndex.getBeansWithName(project.getElementName(), "bean1");
98-
assertEquals(1, beans.length);
99-
100-
Location expectedLocation = new Location(tempJavaDocUri1,
101-
beans[0].getLocation().getRange());
102-
103117
List<? extends Location> references = editor.getReferences();
104118
assertEquals(1, references.size());
105119

106120
Location foundLocation = references.get(0);
107-
assertEquals(expectedLocation, foundLocation);
121+
assertEquals(locationNamedAnnotation1, foundLocation);
108122
}
109123

110124
@Test
111-
public void testNamedRefersToOtherNamedValues() throws Exception {
125+
public void testNamedNotRefersToPureSpringBean() throws Exception {
112126
Editor editor = harness.newEditor(LanguageId.JAVA, """
113127
package org.test;
114128
115129
import jakarta.inject.Named;
116130
117-
@Named("specificFin<*>der")
131+
@Named("be<*>an1")
118132
public class TestDependsOnClass {
119133
}""", tempJavaDocUri);
120134

121-
String expectedDefinitionUri1 = directory.toPath().resolve("src/main/java/org/test/jakarta/SimpleMovieLister.java").toUri().toString();
122-
Location expectedLocation1 = new Location(expectedDefinitionUri1,
123-
new Range(new Position(27, 45), new Position(27, 61)));
135+
List<? extends Location> references = editor.getReferences();
136+
assertNull(references);
137+
}
124138

125-
String expectedDefinitionUri2 = directory.toPath().resolve("src/main/java/org/test/javax/SimpleMovieLister.java").toUri().toString();
126-
Location expectedLocation2 = new Location(expectedDefinitionUri2,
127-
new Range(new Position(27, 45), new Position(27, 61)));
139+
@Test
140+
public void testNamedRefersToNamedInjectionPoints() throws Exception {
141+
Editor editor = harness.newEditor(LanguageId.JAVA, """
142+
package org.test;
143+
144+
import jakarta.inject.Named;
128145
146+
@Named("namedAt<*>Point1")
147+
public class TestDependsOnClass {
148+
}""", tempJavaDocUri);
149+
129150
List<? extends Location> references = editor.getReferences();
130-
assertEquals(2, references.size());
151+
assertEquals(1, references.size());
131152

132-
assertTrue(references.contains(expectedLocation1));
133-
assertTrue(references.contains(expectedLocation2));
153+
Location foundLocation = references.get(0);
154+
assertEquals(point1NamedAnnotationLocation, foundLocation);
134155
}
135156

136157
}

0 commit comments

Comments
 (0)