Merge branch 'main' of https://github.com/spring-projects/spring-tools into main
This commit is contained in:
@@ -11,4 +11,12 @@
|
||||
package org.springframework.ide.vscode.boot.java.data;
|
||||
|
||||
public record DataRepositoryAotMetadata (String name, String type, String module, DataRepositoryAotMetadataMethod[] methods) {
|
||||
|
||||
public boolean isJPA() {
|
||||
return module != null && module.toLowerCase().equals("jpa");
|
||||
}
|
||||
|
||||
public boolean isMongoDb() {
|
||||
return module != null && module.toLowerCase().equals("mongodb");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import org.apache.commons.text.StringEscapeUtils;
|
||||
@@ -80,18 +81,30 @@ public class DataRepositoryAotMetadataCodeLensProvider implements CodeLensProvid
|
||||
return true;
|
||||
}
|
||||
|
||||
static Optional<String> getDataQuery(DataRepositoryAotMetadataService repositoryMetadataService, IJavaProject project, IMethodBinding methodBinding) {
|
||||
// static Optional<String> getDataQuery(DataRepositoryAotMetadataService repositoryMetadataService, IJavaProject project, IMethodBinding methodBinding) {
|
||||
// final String repositoryClass = methodBinding.getDeclaringClass().getBinaryName().trim();
|
||||
// final IMethodBinding method = methodBinding.getMethodDeclaration();
|
||||
//
|
||||
// DataRepositoryAotMetadata metadata = repositoryMetadataService.getRepositoryMetadata(project, repositoryClass);
|
||||
//
|
||||
// if (metadata != null) {
|
||||
// return Optional.ofNullable(repositoryMetadataService.getQueryStatement(metadata, method));
|
||||
// }
|
||||
//
|
||||
// return Optional.empty();
|
||||
//
|
||||
// }
|
||||
|
||||
static Optional<DataRepositoryAotMetadata> getMetadata(DataRepositoryAotMetadataService dataRepositoryAotMetadataService, IJavaProject project, IMethodBinding methodBinding) {
|
||||
final String repositoryClass = methodBinding.getDeclaringClass().getBinaryName().trim();
|
||||
|
||||
return Optional.ofNullable(dataRepositoryAotMetadataService.getRepositoryMetadata(project, repositoryClass));
|
||||
}
|
||||
|
||||
static Optional<DataRepositoryAotMetadataMethod> getMethodMetadata(DataRepositoryAotMetadataService dataRepositoryAotMetadataService, DataRepositoryAotMetadata metadata, IMethodBinding methodBinding) {
|
||||
final IMethodBinding method = methodBinding.getMethodDeclaration();
|
||||
|
||||
DataRepositoryAotMetadata metadata = repositoryMetadataService.getRepositoryMetadata(project, repositoryClass);
|
||||
|
||||
if (metadata != null) {
|
||||
return Optional.ofNullable(repositoryMetadataService.getQueryStatement(metadata, method));
|
||||
}
|
||||
|
||||
return Optional.empty();
|
||||
|
||||
return Optional.ofNullable(dataRepositoryAotMetadataService.findMethod(metadata, method));
|
||||
}
|
||||
|
||||
protected void provideCodeLens(CancelChecker cancelToken, MethodDeclaration node, TextDocument document, List<CodeLens> resultAccumulator) {
|
||||
@@ -106,13 +119,14 @@ public class DataRepositoryAotMetadataCodeLensProvider implements CodeLensProvid
|
||||
|
||||
if (isValidMethodBinding(methodBinding)) {
|
||||
cancelToken.checkCanceled();
|
||||
getDataQuery(repositoryMetadataService, project, methodBinding)
|
||||
.map(queryStatement -> createCodeLenses(node, document, queryStatement))
|
||||
|
||||
getMetadata(repositoryMetadataService, project, methodBinding)
|
||||
.map(metadata -> createCodeLenses(node, document, metadata))
|
||||
.ifPresent(cls -> cls.forEach(resultAccumulator::add));
|
||||
}
|
||||
}
|
||||
|
||||
private List<CodeLens> createCodeLenses(MethodDeclaration node, TextDocument document, String queryStatement) {
|
||||
private List<CodeLens> createCodeLenses(MethodDeclaration node, TextDocument document, DataRepositoryAotMetadata metadata) {
|
||||
List<CodeLens> codeLenses = new ArrayList<>(2);
|
||||
|
||||
try {
|
||||
@@ -122,13 +136,16 @@ public class DataRepositoryAotMetadataCodeLensProvider implements CodeLensProvid
|
||||
Range range = new Range(startPos, endPos);
|
||||
AnnotationHierarchies hierarchyAnnot = AnnotationHierarchies.get(node);
|
||||
|
||||
if (mb != null && hierarchyAnnot != null) {
|
||||
Optional<DataRepositoryAotMetadataMethod> methodMetadata = getMethodMetadata(repositoryMetadataService, metadata, mb);
|
||||
|
||||
if (mb != null && hierarchyAnnot != null && methodMetadata.isPresent()) {
|
||||
|
||||
boolean isQueryAnnotated = hierarchyAnnot.isAnnotatedWith(mb, Annotations.DATA_JPA_QUERY)
|
||||
|| hierarchyAnnot.isAnnotatedWith(mb, Annotations.DATA_MONGODB_QUERY);
|
||||
|
||||
|
||||
if (!isQueryAnnotated) {
|
||||
codeLenses.add(new CodeLens(range, refactorings.createFixCommand(COVERT_TO_QUERY_LABEL, createFixDescriptor(mb, document.getUri(), queryStatement)), null));
|
||||
codeLenses.add(new CodeLens(range, refactorings.createFixCommand(COVERT_TO_QUERY_LABEL, createFixDescriptor(mb, document.getUri(), metadata, methodMetadata.get())), null));
|
||||
}
|
||||
|
||||
Command impl = new Command("Implementation", GenAotQueryMethodImplProvider.CMD_NAVIGATE_TO_IMPL, List.of(new GenAotQueryMethodImplProvider.GoToImplParams(
|
||||
@@ -142,7 +159,7 @@ public class DataRepositoryAotMetadataCodeLensProvider implements CodeLensProvid
|
||||
|
||||
if (!isQueryAnnotated) {
|
||||
Command queryTitle = new Command();
|
||||
queryTitle.setTitle(queryStatement);
|
||||
queryTitle.setTitle(methodMetadata.get().getQueryStatement(metadata));
|
||||
codeLenses.add(new CodeLens(range, queryTitle, null));
|
||||
}
|
||||
}
|
||||
@@ -152,15 +169,31 @@ public class DataRepositoryAotMetadataCodeLensProvider implements CodeLensProvid
|
||||
return codeLenses;
|
||||
}
|
||||
|
||||
static FixDescriptor createFixDescriptor(IMethodBinding mb, String docUri, String queryStatement) {
|
||||
static FixDescriptor createFixDescriptor(IMethodBinding mb, String docUri, DataRepositoryAotMetadata metadata, DataRepositoryAotMetadataMethod methodMetadata) {
|
||||
return new FixDescriptor(AddAnnotationOverMethod.class.getName(), List.of(docUri), "Turn into `@Query`")
|
||||
|
||||
.withRecipeScope(RecipeScope.FILE)
|
||||
.withParameters(Map.of("annotationType", Annotations.DATA_JPA_QUERY, "method",
|
||||
"%s %s(%s)".formatted(mb.getDeclaringClass().getQualifiedName(), mb.getName(),
|
||||
Arrays.stream(mb.getParameterTypes()).map(pt -> pt.getQualifiedName())
|
||||
.collect(Collectors.joining(", "))),
|
||||
"attributes", List.of(new AddAnnotationOverMethod.Attribute("value",
|
||||
"\"%s\"".formatted(StringEscapeUtils.escapeJava(queryStatement))))));
|
||||
|
||||
.withParameters(Map.of(
|
||||
"annotationType", metadata.isJPA() ? Annotations.DATA_JPA_QUERY : Annotations.DATA_MONGODB_QUERY,
|
||||
"method", "%s %s(%s)".formatted(mb.getDeclaringClass().getQualifiedName(), mb.getName(),
|
||||
Arrays.stream(mb.getParameterTypes())
|
||||
.map(pt -> pt.getQualifiedName())
|
||||
.collect(Collectors.joining(", "))),
|
||||
"attributes", createAttributeList(methodMetadata.getAttributesMap(metadata))));
|
||||
}
|
||||
|
||||
private static List<AddAnnotationOverMethod.Attribute> createAttributeList(Map<String, String> attributes) {
|
||||
List<AddAnnotationOverMethod.Attribute> result = new ArrayList<>();
|
||||
|
||||
Set<String> keys = attributes.keySet();
|
||||
for (String key : keys) {
|
||||
result.add(new AddAnnotationOverMethod.Attribute(key, "\"%s\"".formatted(StringEscapeUtils.escapeJava(attributes.get(key)))));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -10,5 +10,99 @@
|
||||
*******************************************************************************/
|
||||
package org.springframework.ide.vscode.boot.java.data;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
public record DataRepositoryAotMetadataMethod(String name, String signature, DataRepositoryAotMetadataQuery query) {
|
||||
|
||||
public String getQueryStatement(DataRepositoryAotMetadata repository) {
|
||||
if (repository != null && repository.isJPA()) {
|
||||
return getJpaQueryStatement();
|
||||
}
|
||||
else if (repository != null && repository.isMongoDb()) {
|
||||
return getMongoDbQueryStatement();
|
||||
}
|
||||
else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private String getJpaQueryStatement() {
|
||||
return query() != null ? query.query(): null;
|
||||
}
|
||||
|
||||
private String getMongoDbQueryStatement() {
|
||||
List<String> parts = new ArrayList<>();
|
||||
|
||||
if (query == null) return null;
|
||||
|
||||
if (query().filter() != null) {
|
||||
if (!StringUtils.hasText(query().sort())
|
||||
&& !StringUtils.hasText(query().fields())
|
||||
&& !StringUtils.hasText(query().projection())
|
||||
&& !StringUtils.hasText(query().pipeline())) {
|
||||
|
||||
parts.add(query().filter());
|
||||
}
|
||||
else {
|
||||
parts.add("filter = \"" + query().filter() + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
if (query().fields() != null) {
|
||||
parts.add("fields = \"" + query().fields() + "\"");
|
||||
}
|
||||
|
||||
if (query().sort() != null) {
|
||||
parts.add("sort = \"" + query().sort() + "\"");
|
||||
}
|
||||
|
||||
if (query().projection() != null) {
|
||||
parts.add("projection = \"" + query().projection() + "\"");
|
||||
}
|
||||
|
||||
if (query().pipeline() != null) {
|
||||
parts.add("pipeline = \"" + query().pipeline() + "\"");
|
||||
}
|
||||
|
||||
return String.join(", ", parts);
|
||||
}
|
||||
|
||||
public Map<String, String> getAttributesMap(DataRepositoryAotMetadata metadata) {
|
||||
if (metadata != null && metadata.isJPA()) {
|
||||
return Map.of("value", getJpaQueryStatement());
|
||||
}
|
||||
else if (metadata != null && metadata.isMongoDb()) {
|
||||
if (query != null) {
|
||||
return createMongoDbQueryAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
return Map.of();
|
||||
}
|
||||
|
||||
private Map<String, String> createMongoDbQueryAttributes() {
|
||||
Map<String, String> result = new HashMap<>();
|
||||
|
||||
if (query.filter() != null) {
|
||||
result.put("value", query.filter());
|
||||
}
|
||||
|
||||
if (query().fields() != null) {
|
||||
result.put("fields", query().fields());
|
||||
}
|
||||
|
||||
if (query().sort() != null) {
|
||||
result.put("sort", query().sort());
|
||||
}
|
||||
|
||||
// TODO; what about projection and pipeline ?
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -13,8 +13,6 @@ package org.springframework.ide.vscode.boot.java.data;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.core.dom.IMethodBinding;
|
||||
@@ -25,7 +23,6 @@ import org.springframework.ide.vscode.commons.java.IClasspathUtil;
|
||||
import org.springframework.ide.vscode.commons.java.IJavaProject;
|
||||
import org.springframework.ide.vscode.commons.java.parser.JLRMethodParser;
|
||||
import org.springframework.ide.vscode.commons.java.parser.JLRMethodParser.JLRMethod;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
|
||||
@@ -71,58 +68,9 @@ public class DataRepositoryAotMetadataService {
|
||||
|
||||
public String getQueryStatement(DataRepositoryAotMetadata metadata, IMethodBinding method) {
|
||||
DataRepositoryAotMetadataMethod methodMetadata = findMethod(metadata, method);
|
||||
|
||||
if (methodMetadata != null) {
|
||||
if (metadata.module() != null && metadata.module().toUpperCase().equals("JPA")) {
|
||||
return getJpaQueryStatement(methodMetadata);
|
||||
}
|
||||
else if (metadata.module() != null && metadata.module().toUpperCase().equals("MONGODB")) {
|
||||
return getMongoDbQueryStatement(methodMetadata);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
return methodMetadata.getQueryStatement(metadata);
|
||||
}
|
||||
|
||||
private String getMongoDbQueryStatement(DataRepositoryAotMetadataMethod methodMetadata) {
|
||||
List<String> parts = new ArrayList<>();
|
||||
|
||||
if (methodMetadata.query().filter() != null) {
|
||||
if (!StringUtils.hasText(methodMetadata.query().sort())
|
||||
&& !StringUtils.hasText(methodMetadata.query().fields())
|
||||
&& !StringUtils.hasText(methodMetadata.query().projection())
|
||||
&& !StringUtils.hasText(methodMetadata.query().pipeline())) {
|
||||
|
||||
parts.add(methodMetadata.query().filter());
|
||||
}
|
||||
else {
|
||||
parts.add("filter = \"" + methodMetadata.query().filter() + "\"");
|
||||
}
|
||||
}
|
||||
|
||||
if (methodMetadata.query().fields() != null) {
|
||||
parts.add("fields = \"" + methodMetadata.query().fields() + "\"");
|
||||
}
|
||||
|
||||
if (methodMetadata.query().sort() != null) {
|
||||
parts.add("sort = \"" + methodMetadata.query().sort() + "\"");
|
||||
}
|
||||
|
||||
if (methodMetadata.query().projection() != null) {
|
||||
parts.add("projection = \"" + methodMetadata.query().projection() + "\"");
|
||||
}
|
||||
|
||||
if (methodMetadata.query().pipeline() != null) {
|
||||
parts.add("pipeline = \"" + methodMetadata.query().pipeline() + "\"");
|
||||
}
|
||||
|
||||
return String.join(", ", parts);
|
||||
}
|
||||
|
||||
private String getJpaQueryStatement(DataRepositoryAotMetadataMethod methodMetadata) {
|
||||
return methodMetadata.query().query();
|
||||
}
|
||||
|
||||
|
||||
public DataRepositoryAotMetadataMethod findMethod(DataRepositoryAotMetadata metadata, IMethodBinding method) {
|
||||
String name = method.getName();
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
package org.springframework.ide.vscode.boot.java.data;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Optional;
|
||||
|
||||
import org.eclipse.jdt.core.dom.ASTVisitor;
|
||||
import org.eclipse.jdt.core.dom.CompilationUnit;
|
||||
@@ -56,15 +57,26 @@ public class QueryMethodCodeActionProvider implements JdtAstCodeActionProvider {
|
||||
@Override
|
||||
public boolean visit(MethodDeclaration node) {
|
||||
cancelToken.checkCanceled();
|
||||
|
||||
if (node.getStartPosition() <= region.getStart() && node.getStartPosition() + node.getLength() >= region.getEnd()) {
|
||||
int start = node.getStartPosition();
|
||||
int end = node.getName().getStartPosition() + node.getName().getLength();
|
||||
|
||||
if (start <= region.getStart() && end >= region.getEnd()) {
|
||||
|
||||
IMethodBinding binding = node.resolveBinding();
|
||||
AnnotationHierarchies hierarchyAnnot = AnnotationHierarchies.get(node);
|
||||
if (hierarchyAnnot != null && !hierarchyAnnot.isAnnotatedWith(binding, Annotations.DATA_JPA_QUERY)) {
|
||||
DataRepositoryAotMetadataCodeLensProvider.getDataQuery(repositoryMetadataService, project, binding)
|
||||
.map(query -> createCodeAction(binding, docURI, query)).ifPresent(collector::accept);
|
||||
if (hierarchyAnnot != null
|
||||
&& !hierarchyAnnot.isAnnotatedWith(binding, Annotations.DATA_JPA_QUERY)
|
||||
&& !hierarchyAnnot.isAnnotatedWith(binding, Annotations.DATA_MONGODB_QUERY)) {
|
||||
|
||||
Optional<DataRepositoryAotMetadata> metadata = DataRepositoryAotMetadataCodeLensProvider.getMetadata(repositoryMetadataService, project, binding);
|
||||
if (metadata.isPresent()) {
|
||||
Optional<DataRepositoryAotMetadataMethod> methodMetadata = DataRepositoryAotMetadataCodeLensProvider.getMethodMetadata(repositoryMetadataService, metadata.get(), binding);
|
||||
methodMetadata
|
||||
.map(method -> createCodeAction(binding, docURI, metadata.get(), method))
|
||||
.ifPresent(collector::accept);
|
||||
}
|
||||
}
|
||||
}
|
||||
return super.visit(node);
|
||||
@@ -75,9 +87,9 @@ public class QueryMethodCodeActionProvider implements JdtAstCodeActionProvider {
|
||||
};
|
||||
}
|
||||
|
||||
private CodeAction createCodeAction(IMethodBinding mb, URI docUri, String query) {
|
||||
private CodeAction createCodeAction(IMethodBinding mb, URI docUri, DataRepositoryAotMetadata metadata, DataRepositoryAotMetadataMethod method) {
|
||||
CodeAction ca = new CodeAction();
|
||||
ca.setCommand(refactorings.createFixCommand(TITLE, DataRepositoryAotMetadataCodeLensProvider.createFixDescriptor(mb, docUri.toASCIIString(), query)));
|
||||
ca.setCommand(refactorings.createFixCommand(TITLE, DataRepositoryAotMetadataCodeLensProvider.createFixDescriptor(mb, docUri.toASCIIString(), metadata, method)));
|
||||
ca.setTitle(TITLE);
|
||||
ca.setKind(CodeActionKind.Refactor);
|
||||
return ca;
|
||||
|
||||
Reference in New Issue
Block a user