From 8cf3836ed73b47e4e2a131ff27f71e01efc31db5 Mon Sep 17 00:00:00 2001 From: Martin Lippert Date: Thu, 10 Apr 2025 10:05:15 +0200 Subject: [PATCH] GH-1536: include signature information in query method index nodes --- .../data/DataRepositorySymbolProvider.java | 36 +++++++++++++++++-- .../boot/java/utils/SpringIndexerJava.java | 2 +- .../test/DataRepositoryIndexElementsTest.java | 27 ++++++++++---- .../DataRepositorySymbolProviderTest.java | 4 +-- ...CustomerRepositoryWithTwoParamsMethod.java | 11 ++++++ .../src/main/java/org/test/Status.java | 5 +++ 6 files changed, 74 insertions(+), 11 deletions(-) create mode 100644 headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-data-symbols/src/main/java/org/test/CustomerRepositoryWithTwoParamsMethod.java create mode 100644 headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-data-symbols/src/main/java/org/test/Status.java diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/DataRepositorySymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/DataRepositorySymbolProvider.java index 26373b8c7..d0032cd8e 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/DataRepositorySymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/data/DataRepositorySymbolProvider.java @@ -22,6 +22,7 @@ import org.eclipse.jdt.core.dom.Modifier; import org.eclipse.jdt.core.dom.NormalAnnotation; import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.jdt.core.dom.SingleMemberAnnotation; +import org.eclipse.jdt.core.dom.SingleVariableDeclaration; import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.Range; @@ -108,14 +109,15 @@ public class DataRepositorySymbolProvider implements SymbolProvider { if (nameNode != null) { String methodName = nameNode.getFullyQualifiedName(); - DocumentRegion nodeRegion = ASTUtils.nodeRegion(doc, method); + DocumentRegion nodeRegion = ASTUtils.nodeRegion(doc, nameNode); try { Range range = doc.toRange(nodeRegion); if (methodName != null) { String queryString = identifyQueryString(method, annotationHierarchies); - beanDefinition.addChild(new QueryMethodIndexElement(methodName, queryString, range)); + String methodSignature = identifyMethodSignature(method); + beanDefinition.addChild(new QueryMethodIndexElement(methodSignature, queryString, range)); } } catch (BadLocationException e) { @@ -125,6 +127,36 @@ public class DataRepositorySymbolProvider implements SymbolProvider { } } + private String identifyMethodSignature(MethodDeclaration method) { + StringBuilder result = new StringBuilder(); + + // method name + String name = method.getName().getFullyQualifiedName(); + result.append(name); + + // params + result.append("("); + + @SuppressWarnings("unchecked") + List parameters = method.parameters(); + String[] paramNames = new String[parameters.size()]; + + for (int i = 0; i < parameters.size(); i++) { + ITypeBinding type = parameters.get(i).getType().resolveBinding(); + paramNames[i] = type.getName(); + } + result.append(String.join(", ", paramNames)); + + result.append(") : "); + + // return type + ITypeBinding returnType = method.getReturnType2().resolveBinding(); + String returnTypeName = returnType.getName(); + result.append(returnTypeName); + + return result.toString(); + } + private List identifyQueryMethods(TypeDeclaration type, AnnotationHierarchies annotationHierarchies) { List result = new ArrayList<>(); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java index a81bfe9b5..6fb39f3cc 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJava.java @@ -92,7 +92,7 @@ public class SpringIndexerJava implements SpringIndexer { // whenever the implementation of the indexer changes in a way that the stored data in the cache is no longer valid, // we need to change the generation - this will result in a re-indexing due to no up-to-date cache data being found - private static final String GENERATION = "GEN-19"; + private static final String GENERATION = "GEN-20"; private static final String INDEX_FILES_TASK_ID = "index-java-source-files-task-"; private static final String SYMBOL_KEY = "symbols"; diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/test/DataRepositoryIndexElementsTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/test/DataRepositoryIndexElementsTest.java index 7e78bbd8e..1a5e5cba1 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/test/DataRepositoryIndexElementsTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/test/DataRepositoryIndexElementsTest.java @@ -84,7 +84,7 @@ public class DataRepositoryIndexElementsTest { assertEquals("org.test.CustomerRepository", repoBean[0].getType()); Bean[] matchingBeans = springIndex.getMatchingBeans("test-spring-data-symbols", "org.springframework.data.repository.CrudRepository"); - assertEquals(4, matchingBeans.length); + assertEquals(5, matchingBeans.length); ArrayUtils.contains(matchingBeans, repoBean[0]); } @@ -100,7 +100,22 @@ public class DataRepositoryIndexElementsTest { assertEquals(1, queryMethods.size()); QueryMethodIndexElement queryMethod = (QueryMethodIndexElement) queryMethods.get(0); - assertEquals("findByLastName", queryMethod.getMethodName()); + assertEquals("findByLastName(String) : List", queryMethod.getMethodName()); + } + + @Test + void testSimpleQueryMethodElementsWithTwoParams() throws Exception { + String docUri = directory.toPath().resolve("src/main/java/org/test/CustomerRepositoryWithTwoParamsMethod.java").toUri().toString(); + + DocumentElement document = springIndex.getDocument(docUri); + List children = document.getChildren(); + Bean repositoryElement = (Bean) children.get(0); + + List queryMethods = repositoryElement.getChildren(); + assertEquals(1, queryMethods.size()); + + QueryMethodIndexElement queryMethod = (QueryMethodIndexElement) queryMethods.get(0); + assertEquals("findByLastNameAndStatus(String, Status) : List", queryMethod.getMethodName()); } @Test @@ -115,7 +130,7 @@ public class DataRepositoryIndexElementsTest { assertEquals(1, queryMethods.size()); QueryMethodIndexElement queryMethod = (QueryMethodIndexElement) queryMethods.get(0); - assertEquals("findPetTypes", queryMethod.getMethodName()); + assertEquals("findPetTypes() : List", queryMethod.getMethodName()); assertEquals("SELECT ptype FROM PetType ptype ORDER BY ptype.name", queryMethod.getQueryString()); } @@ -140,11 +155,11 @@ public class DataRepositoryIndexElementsTest { assertEquals(2, queryMethods.size()); QueryMethodIndexElement queryMethod = (QueryMethodIndexElement) queryMethods.get(0); - assertEquals("findConcretePetTypes", queryMethod.getMethodName()); + assertEquals("findConcretePetTypes() : List", queryMethod.getMethodName()); assertEquals("CONCRETE REPO SELECT STATEMENT", queryMethod.getQueryString()); - + QueryMethodIndexElement parentQueryMethod = (QueryMethodIndexElement) queryMethods.get(1); - assertEquals("findParentPetTypes", parentQueryMethod.getMethodName()); + assertEquals("findParentPetTypes() : List", parentQueryMethod.getMethodName()); assertEquals("PARENT REPO INTERFACE QUERY STATEMENT", parentQueryMethod.getQueryString()); } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/test/DataRepositorySymbolProviderTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/test/DataRepositorySymbolProviderTest.java index acb780bf0..f630c0c83 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/test/DataRepositorySymbolProviderTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/data/test/DataRepositorySymbolProviderTest.java @@ -92,7 +92,7 @@ public class DataRepositorySymbolProviderTest { DocumentSymbol documentSymbol = symbols.get(0); List children = documentSymbol.getChildren(); DocumentSymbol childSymbol = children.get(0); - assertEquals("findByLastName", childSymbol.getName()); + assertEquals("findByLastName(String) : List", childSymbol.getName()); assertEquals(1, children.size()); } @@ -107,7 +107,7 @@ public class DataRepositorySymbolProviderTest { DocumentSymbol documentSymbol = symbols.get(0); List children = documentSymbol.getChildren(); DocumentSymbol queryMethodSymbol = children.get(0); - assertEquals("findPetTypes", queryMethodSymbol.getName()); + assertEquals("findPetTypes() : List", queryMethodSymbol.getName()); assertEquals(1, children.size()); List queryChildren = queryMethodSymbol.getChildren(); diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-data-symbols/src/main/java/org/test/CustomerRepositoryWithTwoParamsMethod.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-data-symbols/src/main/java/org/test/CustomerRepositoryWithTwoParamsMethod.java new file mode 100644 index 000000000..11605e654 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-data-symbols/src/main/java/org/test/CustomerRepositoryWithTwoParamsMethod.java @@ -0,0 +1,11 @@ +package org.test; + +import java.util.List; + +import org.springframework.data.repository.CrudRepository; + +public interface CustomerRepositoryWithTwoParamsMethod extends CrudRepository { + + List findByLastNameAndStatus(String lastName, Status status); + +} diff --git a/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-data-symbols/src/main/java/org/test/Status.java b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-data-symbols/src/main/java/org/test/Status.java new file mode 100644 index 000000000..2f02b5875 --- /dev/null +++ b/headless-services/spring-boot-language-server/src/test/resources/test-projects/test-spring-data-symbols/src/main/java/org/test/Status.java @@ -0,0 +1,5 @@ +package org.test; + +public class Status { + +}