Skip to content

Commit

Permalink
GH-1491: minor refactorings and preparing case for query methods from…
Browse files Browse the repository at this point in the history
… type hierarchy
  • Loading branch information
martinlippert committed Mar 5, 2025
1 parent d2b8cdb commit e586ebd
Show file tree
Hide file tree
Showing 3 changed files with 70 additions and 9 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,17 +10,21 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.data;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;

import org.eclipse.jdt.core.dom.Annotation;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.MethodDeclaration;
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.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.lsp4j.Location;
import org.eclipse.lsp4j.Range;
Expand Down Expand Up @@ -99,22 +103,22 @@ public void addSymbols(TypeDeclaration typeDeclaration, SpringIndexerJavaContext
}

private void indexQueryMethods(Bean beanDefinition, TypeDeclaration typeDeclaration, SpringIndexerJavaContext context, TextDocument doc) {
MethodDeclaration[] methods = typeDeclaration.getMethods();
if (methods == null) return;
AnnotationHierarchies annotationHierarchies = AnnotationHierarchies.get(typeDeclaration);

List<MethodDeclaration> methods = identifyQueryMethods(typeDeclaration, annotationHierarchies);

for (MethodDeclaration method : methods) {
int modifiers = method.getModifiers();
SimpleName nameNode = method.getName();

if (nameNode != null && (modifiers & Modifier.DEFAULT) == 0) {
if (nameNode != null) {
String methodName = nameNode.getFullyQualifiedName();
DocumentRegion nodeRegion = ASTUtils.nodeRegion(doc, method);

try {
Range range = doc.toRange(nodeRegion);

if (methodName != null) {
String queryString = identifyQueryString(method);
String queryString = identifyQueryString(method, annotationHierarchies);
beanDefinition.addChild(new QueryMethodIndexElement(methodName, queryString, range));
}

Expand All @@ -125,8 +129,24 @@ private void indexQueryMethods(Bean beanDefinition, TypeDeclaration typeDeclarat
}
}

private String identifyQueryString(MethodDeclaration method) {
AnnotationHierarchies annotationHierarchies = AnnotationHierarchies.get(method);
private List<MethodDeclaration> identifyQueryMethods(TypeDeclaration type, AnnotationHierarchies annotationHierarchies) {
List<MethodDeclaration> result = new ArrayList<>();

MethodDeclaration[] methods = type.getMethods();
if (methods == null) return result;

for (MethodDeclaration method : methods) {
int modifiers = method.getModifiers();

if ((modifiers & Modifier.DEFAULT) == 0) {
result.add(method);
}
}

return result;
}

private String identifyQueryString(MethodDeclaration method, AnnotationHierarchies annotationHierarchies) {

EmbeddedQueryExpression queryExpression = null;

Expand All @@ -150,7 +170,7 @@ else if (annotation instanceof NormalAnnotation) {

return null;
}

protected String beanLabel(boolean isFunctionBean, String beanName, String beanType, String markerString) {
StringBuilder symbolLabel = new StringBuilder();
symbolLabel.append("@+");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
*******************************************************************************/
package org.springframework.ide.vscode.boot.java.data.test;

import static org.junit.Assert.assertNull;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.io.File;
Expand All @@ -20,6 +21,7 @@
import org.apache.commons.lang3.ArrayUtils;
import org.eclipse.lsp4j.TextDocumentIdentifier;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.ExtendWith;
import org.springframework.beans.factory.annotation.Autowired;
Expand Down Expand Up @@ -82,7 +84,7 @@ void testSimpleRepositoryElements() throws Exception {
assertEquals("org.test.CustomerRepository", repoBean[0].getType());

Bean[] matchingBeans = springIndex.getMatchingBeans("test-spring-data-symbols", "org.springframework.data.repository.CrudRepository");
assertEquals(3, matchingBeans.length);
assertEquals(4, matchingBeans.length);
ArrayUtils.contains(matchingBeans, repoBean[0]);
}

Expand Down Expand Up @@ -115,7 +117,35 @@ void testQueryMethodElementWithQueryString() throws Exception {
QueryMethodIndexElement queryMethod = (QueryMethodIndexElement) queryMethods.get(0);
assertEquals("findPetTypes", queryMethod.getMethodName());
assertEquals("SELECT ptype FROM PetType ptype ORDER BY ptype.name", queryMethod.getQueryString());
}

@Test
void testNoRepositoryBeanAnnotationResultsInNoBeanIndexElement() throws Exception {
String docUri = directory.toPath().resolve("src/main/java/org/test/CustomerRepositoryParentInterface.java").toUri().toString();

DocumentElement document = springIndex.getDocument(docUri);
assertNull(document); // nothing in the doc, therefore not even the doc node is around
}

@Test
@Disabled // query methods from superclasses or interfaces not yet implemented, maybe requires a different way to think about this (separate index elements instead of one element with all query methods)
void testQueryMethodsFromParentInterfaces() throws Exception {
String docUri = directory.toPath().resolve("src/main/java/org/test/CustomerRepositoryWithParentInterfaces.java").toUri().toString();

DocumentElement document = springIndex.getDocument(docUri);
List<SpringIndexElement> children = document.getChildren();
Bean repositoryElement = (Bean) children.get(0);

List<SpringIndexElement> queryMethods = repositoryElement.getChildren();
assertEquals(2, queryMethods.size());

QueryMethodIndexElement queryMethod = (QueryMethodIndexElement) queryMethods.get(0);
assertEquals("findConcretePetTypes", queryMethod.getMethodName());
assertEquals("CONCRETE REPO SELECT STATEMENT", queryMethod.getQueryString());

QueryMethodIndexElement parentQueryMethod = (QueryMethodIndexElement) queryMethods.get(1);
assertEquals("findParentPetTypes", parentQueryMethod.getMethodName());
assertEquals("PARENT REPO INTERFACE QUERY STATEMENT", parentQueryMethod.getQueryString());
}

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package org.test;

import java.util.List;

import org.springframework.data.jpa.repository.Query;

public interface CustomerRepositoryWithParentInterfaces extends CustomerRepositoryParentInterface {

@Query("CONCRETE REPO SELECT STATEMENT")
List<Object> findConcretePetTypes();
}

0 comments on commit e586ebd

Please sign in to comment.