Skip to content

Commit

Permalink
GH-1463: support for concatenated strings for more reference providers
Browse files Browse the repository at this point in the history
  • Loading branch information
martinlippert committed Feb 10, 2025
1 parent 4d767eb commit f96b32b
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 30 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -323,8 +323,8 @@ protected ReferencesHandler createReferenceHandler(SimpleLanguageServer server,
specificProviders.put(Annotations.VALUE, new ValuePropertyReferencesProvider(projectFinder, index));
specificProviders.put(Annotations.CONDITIONAL_ON_PROPERTY, new ValuePropertyReferencesProvider(projectFinder, index));
specificProviders.put(Annotations.QUALIFIER, new QualifierReferencesProvider(index));
specificProviders.put(Annotations.NAMED_JAKARTA, new NamedReferencesProvider(index, symbolIndex));
specificProviders.put(Annotations.NAMED_JAVAX, new NamedReferencesProvider(index, symbolIndex));
specificProviders.put(Annotations.NAMED_JAKARTA, new NamedReferencesProvider(index));
specificProviders.put(Annotations.NAMED_JAVAX, new NamedReferencesProvider(index));
specificProviders.put(Annotations.PROFILE, new ProfileReferencesProvider(index));

List<ReferenceProvider> unspecificProviders = new ArrayList<>();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,12 +16,13 @@

import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.Annotation;
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.StringLiteral;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.springframework.ide.vscode.boot.app.SpringSymbolIndex;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.handlers.ReferenceProvider;
Expand All @@ -35,12 +36,12 @@
*/
public class NamedReferencesProvider implements ReferenceProvider {

private static final Logger log = LoggerFactory.getLogger(NamedReferencesProvider.class);

private final SpringMetamodelIndex springIndex;
private final SpringSymbolIndex symbolIndex;

public NamedReferencesProvider(SpringMetamodelIndex springIndex, SpringSymbolIndex symbolIndex) {
public NamedReferencesProvider(SpringMetamodelIndex springIndex) {
this.springIndex = springIndex;
this.symbolIndex = symbolIndex;
}

@Override
Expand All @@ -49,22 +50,22 @@ public List<? extends Location> provideReferences(CancelChecker cancelToken, IJa
cancelToken.checkCanceled();

try {
while (node != null && !(node.getParent() instanceof Annotation) && !(node.getParent() instanceof MemberValuePair)) {
node = node.getParent();
}

// case: @Value("prefix<*>")
if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
return provideReferences(project, ASTUtils.getLiteralValue((StringLiteral) node));
}
if (node instanceof Expression expression && node.getParent() instanceof Annotation) {
return provideReferences(project, ASTUtils.getExpressionValueAsString(expression, v -> {}));
}
// case: @Value(value="prefix<*>")
else if (node instanceof StringLiteral && node.getParent() instanceof MemberValuePair
else if (node instanceof Expression expression && node.getParent() instanceof MemberValuePair
&& "value".equals(((MemberValuePair)node.getParent()).getName().toString())) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
return provideReferences(project, ASTUtils.getLiteralValue((StringLiteral) node));
}
return provideReferences(project, ASTUtils.getExpressionValueAsString(expression, v -> {}));
}
}
catch (Exception e) {
e.printStackTrace();
log.error("error finding references for named annotatio value", e);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,13 @@
import org.eclipse.jdt.core.dom.ASTNode;
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.StringLiteral;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.jsonrpc.CancelChecker;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.ide.vscode.boot.index.SpringMetamodelIndex;
import org.springframework.ide.vscode.boot.java.Annotations;
import org.springframework.ide.vscode.boot.java.handlers.ReferenceProvider;
Expand All @@ -35,6 +37,8 @@
*/
public class ProfileReferencesProvider implements ReferenceProvider {

private static final Logger log = LoggerFactory.getLogger(ProfileReferencesProvider.class);

private final SpringMetamodelIndex springIndex;

public ProfileReferencesProvider(SpringMetamodelIndex springIndex) {
Expand All @@ -47,28 +51,29 @@ public List<? extends Location> provideReferences(CancelChecker cancelToken, IJa
cancelToken.checkCanceled();

try {
while (node != null
&& !(node.getParent() instanceof Annotation)
&& !(node.getParent() instanceof MemberValuePair)
&& !(node.getParent() instanceof ArrayInitializer)) {
node = node.getParent();
}

// case: @Value("prefix<*>")
if (node instanceof StringLiteral && node.getParent() instanceof Annotation) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
return provideReferences(project, ASTUtils.getLiteralValue((StringLiteral) node));
}
if (node instanceof Expression expression && node.getParent() instanceof Annotation) {
return provideReferences(project, ASTUtils.getExpressionValueAsString(expression, v -> {}));
}
// case: @Value(value="prefix<*>")
else if (node instanceof StringLiteral && node.getParent() instanceof MemberValuePair
else if (node instanceof Expression expression && node.getParent() instanceof MemberValuePair
&& "value".equals(((MemberValuePair)node.getParent()).getName().toString())) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
return provideReferences(project, ASTUtils.getLiteralValue((StringLiteral) node));
}
return provideReferences(project, ASTUtils.getExpressionValueAsString(expression, v -> {}));
}
// case: @Qualifier({"prefix<*>"})
else if (node instanceof StringLiteral && node.getParent() instanceof ArrayInitializer) {
if (node.toString().startsWith("\"") && node.toString().endsWith("\"")) {
return provideReferences(project, ASTUtils.getLiteralValue((StringLiteral) node));
}
else if (node instanceof Expression expression && node.getParent() instanceof ArrayInitializer) {
return provideReferences(project, ASTUtils.getExpressionValueAsString(expression, v -> {}));
}
}
catch (Exception e) {
e.printStackTrace();
log.error("error finding references for profile", e);
}

return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -120,6 +120,24 @@ public class TestDependsOnClass {
assertEquals(locationNamedAnnotation1, foundLocation);
}

@Test
public void testNamedRefersToNamedBeanWithConcatenatedString() throws Exception {
Editor editor = harness.newEditor(LanguageId.JAVA, """
package org.test;
import jakarta.inject.Named;
@Named("na" + "m<*>ed1")
public class TestDependsOnClass {
}""", tempJavaDocUri);

List<? extends Location> references = editor.getReferences();
assertEquals(1, references.size());

Location foundLocation = references.get(0);
assertEquals(locationNamedAnnotation1, foundLocation);
}

@Test
public void testNamedNotRefersToPureSpringBean() throws Exception {
Editor editor = harness.newEditor(LanguageId.JAVA, """
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,37 @@ public class TestDependsOnClass {
assertTrue(references.contains(expectedLocation2));
}

@Test
public void testProfileRefersToOtherProfilesWithConcatenatedString() 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.stereotype.Component;
import org.springframework.context.annotation.Profile;
@Component
@Profile("pro" + "f<*>ile1")
public class TestDependsOnClass {
}""", tempJavaDocUri);

List<? extends Location> references = editor.getReferences();
assertEquals(2, references.size());

String expectedDefinitionUri1 = directory.toPath().resolve("src/main/java/org/test/profiles/ProfilesClass1.java").toUri().toString();
Location expectedLocation1 = new Location(expectedDefinitionUri1,
new Range(new Position(6, 9), new Position(6, 19)));

assertTrue(references.contains(expectedLocation1));

String expectedDefinitionUri2 = directory.toPath().resolve("src/main/java/org/test/profiles/ProfilesClassWithArray.java").toUri().toString();
Location expectedLocation2 = new Location(expectedDefinitionUri2,
new Range(new Position(6, 18), new Position(6, 28)));

assertTrue(references.contains(expectedLocation2));
}

@Test
public void testProfileWithinArrayRefersToOtherProfiles() throws Exception {
String tempJavaDocUri = directory.toPath().resolve("src/main/java/org/test/TempClass.java").toUri().toString();
Expand Down

0 comments on commit f96b32b

Please sign in to comment.