From 4121776e4fa1cef1cdc77116f5db613ef5e8d6b4 Mon Sep 17 00:00:00 2001 From: BoykoAlex Date: Thu, 10 Feb 2022 20:28:34 -0500 Subject: [PATCH] Everything compiles --- .../boot/java/beans/BeansSymbolProvider.java | 121 +++++------ .../java/beans/ComponentSymbolProvider.java | 39 ++-- .../data/DataRepositorySymbolProvider.java | 68 +++--- .../RequestMappingSymbolProvider.java | 133 ++++-------- .../WebfluxAcceptTypeFinder.java | 48 +++-- .../WebfluxContentTypeFinder.java | 50 +++-- .../requestmapping/WebfluxMethodFinder.java | 45 ++-- .../requestmapping/WebfluxPathFinder.java | 47 +++-- .../WebfluxRouterSymbolProvider.java | 197 +++++++++--------- .../java/requestmapping/WebfluxUtils.java | 60 ++---- .../vscode/boot/java/utils/FunctionUtils.java | 55 ++--- .../vscode/boot/java/utils/ORAstUtils.java | 37 +++- .../java/utils/SpringIndexerJavaContext.java | 8 +- .../utils/test/CompilationUnitCacheTest.java | 4 +- .../ValueSpelExpressionValidationTest.java | 3 +- 15 files changed, 428 insertions(+), 487 deletions(-) diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java index 4f518ad8c..17a6db6b9 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/BeansSymbolProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2019 Pivotal, Inc. + * Copyright (c) 2017, 2022 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,19 +13,20 @@ package org.springframework.ide.vscode.boot.java.beans; import java.util.Collection; import java.util.List; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.Annotation; -import org.eclipse.jdt.core.dom.IAnnotationBinding; -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.ParameterizedType; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.Type; -import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.SymbolKind; +import org.openrewrite.internal.lang.Nullable; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.J.Annotation; +import org.openrewrite.java.tree.J.ClassDeclaration; +import org.openrewrite.java.tree.J.Literal; +import org.openrewrite.java.tree.J.MethodDeclaration; +import org.openrewrite.java.tree.J.Modifier; +import org.openrewrite.java.tree.JavaType.FullyQualified; +import org.openrewrite.java.tree.JavaType.Method; +import org.openrewrite.java.tree.JavaType.Parameterized; +import org.openrewrite.java.tree.TypeUtils; import org.springframework.ide.vscode.boot.java.Annotations; import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider; import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation; @@ -33,6 +34,7 @@ import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation; import org.springframework.ide.vscode.boot.java.utils.ASTUtils; import org.springframework.ide.vscode.boot.java.utils.CachedSymbol; import org.springframework.ide.vscode.boot.java.utils.FunctionUtils; +import org.springframework.ide.vscode.boot.java.utils.ORAstUtils; import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.Log; @@ -40,6 +42,7 @@ import org.springframework.ide.vscode.commons.util.text.DocumentRegion; import org.springframework.ide.vscode.commons.util.text.TextDocument; import com.google.common.collect.ImmutableList; +import com.google.common.reflect.Parameter; import reactor.util.function.Tuple2; import reactor.util.function.Tuple3; @@ -54,7 +57,7 @@ public class BeansSymbolProvider extends AbstractSymbolProvider { private static final String[] NAME_ATTRIBUTES = {"value", "name"}; @Override - protected void addSymbolsPass1(Annotation node, ITypeBinding annotationType, Collection metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) { + protected void addSymbolsPass1(Annotation node, FullyQualified annotationType, Collection metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) { if (isMethodAbstract(node)) return; boolean isFunction = isFunctionBean(node); @@ -79,7 +82,7 @@ public class BeansSymbolProvider extends AbstractSymbolProvider { } @Override - protected void addSymbolsPass1(TypeDeclaration typeDeclaration, SpringIndexerJavaContext context, TextDocument doc) { + protected void addSymbolsPass1(ClassDeclaration typeDeclaration, SpringIndexerJavaContext context, TextDocument doc) { // this checks function beans that are defined as implementations of Function interfaces Tuple3 functionBean = FunctionUtils.getFunctionBean(typeDeclaration, doc); if (functionBean != null) { @@ -99,23 +102,23 @@ public class BeansSymbolProvider extends AbstractSymbolProvider { } protected Collection> getBeanNames(Annotation node, TextDocument doc) { - Collection beanNameNodes = getBeanNameLiterals(node); + Collection beanNameNodes = getBeanNameLiterals(node); if (beanNameNodes != null && !beanNameNodes.isEmpty()) { ImmutableList.Builder> namesAndRegions = ImmutableList.builder(); - for (StringLiteral nameNode : beanNameNodes) { - String name = ASTUtils.getLiteralValue(nameNode); - namesAndRegions.add(Tuples.of(name, ASTUtils.stringRegion(doc, nameNode))); + for (Literal nameNode : beanNameNodes) { + String name = ORAstUtils.getLiteralValue(nameNode); + namesAndRegions.add(Tuples.of(name, ORAstUtils.stringRegion(doc, nameNode))); } return namesAndRegions.build(); } else { - ASTNode parent = node.getParent(); + J parent = ORAstUtils.getParent(node); if (parent instanceof MethodDeclaration) { MethodDeclaration method = (MethodDeclaration) parent; return ImmutableList.of(Tuples.of( method.getName().toString(), - ASTUtils.nameRegion(doc, node) + ORAstUtils.nameRegion(doc, node) )); } return ImmutableList.of(); @@ -138,81 +141,71 @@ public class BeansSymbolProvider extends AbstractSymbolProvider { return symbolLabel.toString(); } - protected Collection getBeanNameLiterals(Annotation node) { - ImmutableList.Builder literals = ImmutableList.builder(); + protected Collection getBeanNameLiterals(Annotation node) { + ImmutableList.Builder literals = ImmutableList.builder(); for (String attrib : NAME_ATTRIBUTES) { - ASTUtils.getAttribute(node, attrib).ifPresent((valueExp) -> { - literals.addAll(ASTUtils.getExpressionValueAsListOfLiterals(valueExp)); + ORAstUtils.getAttribute(node, attrib).ifPresent((valueExp) -> { + literals.addAll(ORAstUtils.getExpressionValueAsListOfLiterals(valueExp)); }); } return literals.build(); } protected String getBeanType(Annotation node) { - ASTNode parent = node.getParent(); + J parent = ORAstUtils.getParent(node); if (parent instanceof MethodDeclaration) { - MethodDeclaration method = (MethodDeclaration) parent; - String returnType = method.getReturnType2().resolveBinding().getName(); - return returnType; + Method method = ((MethodDeclaration) parent).getMethodType(); + if (method != null) { + FullyQualified returnType = TypeUtils.asFullyQualified(method.getReturnType()); + if (returnType != null) { + return returnType.getFullyQualifiedName(); + } + } } return null; } private boolean isFunctionBean(Annotation node) { - ASTNode parent = node.getParent(); + J parent = ORAstUtils.getParent(node); if (parent instanceof MethodDeclaration) { - MethodDeclaration method = (MethodDeclaration) parent; - String returnType = null; - - if (method.getReturnType2().isParameterizedType()) { - ParameterizedType paramType = (ParameterizedType) method.getReturnType2(); - Type type = paramType.getType(); - ITypeBinding typeBinding = type.resolveBinding(); - returnType = typeBinding.getBinaryName(); + Method method = ((MethodDeclaration) parent).getMethodType(); + if (method != null) { + FullyQualified returnType = TypeUtils.asFullyQualified(method.getReturnType()); + if (returnType != null) { + String fqName = returnType.getFullyQualifiedName(); + + return FunctionUtils.FUNCTION_FUNCTION_TYPE.equals(fqName) || FunctionUtils.FUNCTION_CONSUMER_TYPE.equals(fqName) + || FunctionUtils.FUNCTION_SUPPLIER_TYPE.equals(fqName); + } } - else { - returnType = method.getReturnType2().resolveBinding().getQualifiedName(); - } - - return FunctionUtils.FUNCTION_FUNCTION_TYPE.equals(returnType) || FunctionUtils.FUNCTION_CONSUMER_TYPE.equals(returnType) - || FunctionUtils.FUNCTION_SUPPLIER_TYPE.equals(returnType); } return false; } private String getAnnotations(Annotation node) { StringBuilder result = new StringBuilder(); - - ASTNode parent = node.getParent(); + J parent = ORAstUtils.getParent(node); if (parent instanceof MethodDeclaration) { MethodDeclaration method = (MethodDeclaration) parent; - - List modifiers = method.modifiers(); - for (Object modifier : modifiers) { - if (modifier instanceof Annotation) { - Annotation annotation = (Annotation) modifier; - IAnnotationBinding annotationBinding = annotation.resolveAnnotationBinding(); - String type = annotationBinding.getAnnotationType().getBinaryName(); - - if (type != null && !Annotations.BEAN.equals(type)) { - result.append(' '); - result.append(annotation.toString()); - } + + for (Annotation a : method.getLeadingAnnotations()) { + FullyQualified type = TypeUtils.asFullyQualified(a.getType()); + if (type != null && !Annotations.BEAN.equals(type.getFullyQualifiedName())) { + result.append(' '); + result.append(a.printTrimmed()); } } + } - return result.toString(); } private boolean isMethodAbstract(Annotation node) { - if (node != null && node.getParent() != null && node.getParent() instanceof MethodDeclaration) { - MethodDeclaration method = (MethodDeclaration) node.getParent(); - List modifiers = method.modifiers(); - for (Object modifier : modifiers) { - if (modifier instanceof Modifier && ((Modifier) modifier).isAbstract()) { - return true; - } + if (node != null) { + J parent = ORAstUtils.getParent(node); + if (parent instanceof MethodDeclaration) { + MethodDeclaration method = (MethodDeclaration) parent; + return Modifier.hasModifier(method.getModifiers(), Modifier.Type.Abstract); } } return false; diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java index 14f2c3299..f0cbb17b5 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/beans/ComponentSymbolProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2019 Pivotal, Inc. + * Copyright (c) 2017, 2022 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,17 +13,19 @@ package org.springframework.ide.vscode.boot.java.beans; import java.util.Collection; import java.util.stream.Collectors; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.Annotation; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.SymbolKind; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.J.Annotation; +import org.openrewrite.java.tree.J.ClassDeclaration; +import org.openrewrite.java.tree.JavaType.FullyQualified; +import org.openrewrite.marker.Range; import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider; import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation; import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation; import org.springframework.ide.vscode.boot.java.utils.CachedSymbol; +import org.springframework.ide.vscode.boot.java.utils.ORAstUtils; import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.Log; @@ -36,7 +38,7 @@ import org.springframework.ide.vscode.commons.util.text.TextDocument; public class ComponentSymbolProvider extends AbstractSymbolProvider { @Override - protected void addSymbolsPass1(Annotation node, ITypeBinding annotationType, Collection metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) { + protected void addSymbolsPass1(Annotation node, FullyQualified annotationType, Collection metaAnnotations, SpringIndexerJavaContext context, TextDocument doc) { try { EnhancedSymbolInformation enhancedSymbol = createSymbol(node, annotationType, metaAnnotations, doc); context.getGeneratedSymbols().add(new CachedSymbol(context.getDocURI(), context.getLastModified(), enhancedSymbol)); @@ -46,17 +48,18 @@ public class ComponentSymbolProvider extends AbstractSymbolProvider { } } - protected EnhancedSymbolInformation createSymbol(Annotation node, ITypeBinding annotationType, Collection metaAnnotations, TextDocument doc) throws BadLocationException { - String annotationTypeName = annotationType.getName(); + protected EnhancedSymbolInformation createSymbol(Annotation node, FullyQualified annotationType, Collection metaAnnotations, TextDocument doc) throws BadLocationException { + String annotationTypeName = annotationType.getFullyQualifiedName(); Collection metaAnnotationNames = metaAnnotations.stream() - .map(ITypeBinding::getName) + .map(FullyQualified::getFullyQualifiedName) .collect(Collectors.toList()); String beanName = getBeanName(node); String beanType = getBeanType(node); + Range r = ORAstUtils.getRange(node); SymbolInformation symbol = new SymbolInformation( beanLabel("+", annotationTypeName, metaAnnotationNames, beanName, beanType), SymbolKind.Interface, - new Location(doc.getUri(), doc.toRange(node.getStartPosition(), node.getLength()))); + new Location(doc.getUri(), doc.toRange(r.getStart().getOffset(), r.length()))); SymbolAddOnInformation[] addon = new SymbolAddOnInformation[] {new BeansSymbolAddOnInformation(beanName)}; @@ -91,21 +94,21 @@ public class ComponentSymbolProvider extends AbstractSymbolProvider { } private String getBeanName(Annotation node) { - ASTNode parent = node.getParent(); - if (parent instanceof TypeDeclaration) { - TypeDeclaration type = (TypeDeclaration) parent; + J parent = ORAstUtils.getParent(node); + if (parent instanceof ClassDeclaration) { + ClassDeclaration type = (ClassDeclaration) parent; - String beanName = type.getName().toString(); + String beanName = type.getSimpleName(); return BeanUtils.getBeanNameFromType(beanName); } return null; } private String getBeanType(Annotation node) { - ASTNode parent = node.getParent(); - if (parent instanceof TypeDeclaration) { - TypeDeclaration type = (TypeDeclaration) parent; - String returnType = type.resolveBinding().getName(); + J parent = ORAstUtils.getParent(node); + if (parent instanceof ClassDeclaration) { + ClassDeclaration type = (ClassDeclaration) parent; + String returnType = type.getType().getFullyQualifiedName(); return returnType; } return null; 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 712eb6ae6..ea42b9fd0 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 @@ -10,11 +10,16 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.data; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.TypeDeclaration; +import java.util.List; + import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.SymbolInformation; import org.eclipse.lsp4j.SymbolKind; +import org.openrewrite.java.tree.J.ClassDeclaration; +import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.JavaType.FullyQualified; +import org.openrewrite.java.tree.JavaType.Parameterized; +import org.openrewrite.java.tree.TypeUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.boot.java.beans.BeanUtils; @@ -22,8 +27,8 @@ import org.springframework.ide.vscode.boot.java.beans.BeansSymbolAddOnInformatio import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider; import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation; import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation; -import org.springframework.ide.vscode.boot.java.utils.ASTUtils; import org.springframework.ide.vscode.boot.java.utils.CachedSymbol; +import org.springframework.ide.vscode.boot.java.utils.ORAstUtils; import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.text.DocumentRegion; @@ -40,7 +45,7 @@ public class DataRepositorySymbolProvider extends AbstractSymbolProvider { private static final Logger log = LoggerFactory.getLogger(DataRepositorySymbolProvider.class); @Override - protected void addSymbolsPass1(TypeDeclaration typeDeclaration, SpringIndexerJavaContext context, TextDocument doc) { + protected void addSymbolsPass1(ClassDeclaration typeDeclaration, SpringIndexerJavaContext context, TextDocument doc) { // this checks spring data repository beans that are defined as extensions of the repository interface Tuple4 repositoryBean = getRepositoryBean(typeDeclaration, doc); if (repositoryBean != null) { @@ -75,8 +80,8 @@ public class DataRepositorySymbolProvider extends AbstractSymbolProvider { return symbolLabel.toString(); } - private static Tuple4 getRepositoryBean(TypeDeclaration typeDeclaration, TextDocument doc) { - ITypeBinding resolvedType = typeDeclaration.resolveBinding(); + private static Tuple4 getRepositoryBean(ClassDeclaration typeDeclaration, TextDocument doc) { + FullyQualified resolvedType = typeDeclaration.getType(); if (resolvedType != null) { return getRepositoryBean(typeDeclaration, doc, resolvedType); @@ -86,53 +91,46 @@ public class DataRepositorySymbolProvider extends AbstractSymbolProvider { } } - private static Tuple4 getRepositoryBean(TypeDeclaration typeDeclaration, TextDocument doc, - ITypeBinding resolvedType) { - - ITypeBinding[] interfaces = resolvedType.getInterfaces(); - for (ITypeBinding resolvedInterface : interfaces) { - String simplifiedType = null; - if (resolvedInterface.isParameterizedType()) { - simplifiedType = resolvedInterface.getBinaryName(); - } - else { - simplifiedType = resolvedType.getQualifiedName(); - } - - if (Constants.REPOSITORY_TYPE.equals(simplifiedType)) { + private static Tuple4 getRepositoryBean(ClassDeclaration typeDeclaration, TextDocument doc, + FullyQualified resolvedType) { + + for (FullyQualified resolvedInterface : resolvedType.getInterfaces()) { + if (Constants.REPOSITORY_TYPE.equals(resolvedInterface.getFullyQualifiedName())) { String beanName = getBeanName(typeDeclaration); - String beanType = resolvedInterface.getName(); - + String beanType = resolvedInterface.toString(); + String domainType = null; - if (resolvedInterface.isParameterizedType()) { - ITypeBinding[] typeParameters = resolvedInterface.getTypeArguments(); - if (typeParameters != null && typeParameters.length > 0) { - domainType = typeParameters[0].getName(); + if (resolvedType instanceof Parameterized) { + List typeParams = ((Parameterized)resolvedType).getTypeParameters(); + if (typeParams != null && !typeParams.isEmpty()) { + FullyQualified typeParam = TypeUtils.asFullyQualified(typeParams.get(0)); + domainType = typeParam == null ? null : typeParam.getFullyQualifiedName(); } } - DocumentRegion region = ASTUtils.nodeRegion(doc, typeDeclaration.getName()); + DocumentRegion region = ORAstUtils.nodeRegion(doc, typeDeclaration.getName()); + return Tuples.of(beanName, beanType, domainType, region); - } - else { + } else { Tuple4 result = getRepositoryBean(typeDeclaration, doc, resolvedInterface); if (result != null) { return result; } } } - - ITypeBinding superclass = resolvedType.getSuperclass(); + + FullyQualified superclass = resolvedType.getSupertype(); if (superclass != null) { return getRepositoryBean(typeDeclaration, doc, superclass); - } - else { + } else { return null; } + + } - private static String getBeanName(TypeDeclaration typeDeclaration) { - String beanName = typeDeclaration.getName().toString(); + private static String getBeanName(ClassDeclaration typeDeclaration) { + String beanName = typeDeclaration.getSimpleName(); return BeanUtils.getBeanNameFromType(beanName); } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java index ac6239a99..5041400e8 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/RequestMappingSymbolProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2019 Pivotal, Inc. + * Copyright (c) 2017, 2022 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -12,23 +12,21 @@ package org.springframework.ide.vscode.boot.java.requestmapping; import java.util.Arrays; import java.util.Collection; -import java.util.Iterator; import java.util.List; import java.util.Objects; import java.util.stream.Stream; import org.eclipse.lsp4j.Location; -import org.openrewrite.internal.lang.Nullable; import org.openrewrite.java.tree.Expression; -import org.openrewrite.java.tree.TypeUtils; import org.openrewrite.java.tree.J.Annotation; import org.openrewrite.java.tree.J.Assignment; +import org.openrewrite.java.tree.J.ClassDeclaration; import org.openrewrite.java.tree.J.MethodDeclaration; import org.openrewrite.java.tree.JavaType.FullyQualified; +import org.openrewrite.java.tree.TypeUtils; import org.openrewrite.marker.Range; import org.springframework.ide.vscode.boot.java.Annotations; import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider; -import org.springframework.ide.vscode.boot.java.utils.ASTUtils; import org.springframework.ide.vscode.boot.java.utils.CachedSymbol; import org.springframework.ide.vscode.boot.java.utils.ORAstUtils; import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext; @@ -89,7 +87,6 @@ public class RequestMappingSymbolProvider extends AbstractSymbolProvider { private String[] getMethod(Annotation node, SpringIndexerJavaContext context) { String[] methods = null; - List args = node.getArguments(); // TODO: OR AST Annotation parameter @@ -97,34 +94,11 @@ public class RequestMappingSymbolProvider extends AbstractSymbolProvider { && (!(args.get(0) instanceof Assignment)) || "value".equals(((Assignment)args.get(0)).getVariable().printTrimmed()) ) ) { methods = getRequestMethod(node); - } else if () { - for (Expression arg : args) { - if (arg instanceof Assignment && "method".equals(((Assignment) arg).getVariable().printTrimmed())) { - - } - } + } else { + methods = getRequestMethodFromMultiArgs(node, context); } - if (node.isNormalAnnotation()) { - NormalAnnotation normNode = (NormalAnnotation) node; - List values = normNode.values(); - for (Iterator iterator = values.iterator(); iterator.hasNext();) { - Object object = iterator.next(); - if (object instanceof MemberValuePair) { - MemberValuePair pair = (MemberValuePair) object; - String valueName = pair.getName().getIdentifier(); - if (valueName != null && valueName.equals("method")) { - Expression expression = pair.getValue(); - methods = ASTUtils.getExpressionValueAsArray(expression, context::addDependency); - break; - } - } - } - } else if (node instanceof SingleMemberAnnotation) { - methods = getRequestMethod((SingleMemberAnnotation)node); - } - - if (methods == null && node.getParent() instanceof MethodDeclaration) { + if (methods == null && ORAstUtils.getParent(node) instanceof MethodDeclaration) { Annotation parentAnnotation = getParentAnnotation(node); if (parentAnnotation != null) { methods = getMethod(parentAnnotation, context); @@ -135,26 +109,25 @@ public class RequestMappingSymbolProvider extends AbstractSymbolProvider { } private String[] getPath(Annotation node, SpringIndexerJavaContext context) { - if (node.isNormalAnnotation()) { - NormalAnnotation normNode = (NormalAnnotation) node; - List values = normNode.values(); - for (Iterator iterator = values.iterator(); iterator.hasNext();) { - Object object = iterator.next(); - if (object instanceof MemberValuePair) { - MemberValuePair pair = (MemberValuePair) object; - String valueName = pair.getName().getIdentifier(); - if (valueName != null && (valueName.equals("value") || valueName.equals("path"))) { - Expression expression = pair.getValue(); - return ASTUtils.getExpressionValueAsArray(expression, context::addDependency); + + List args = node.getArguments(); + + if (args != null) { + if (args.size() == 1 && !(args.get(0) instanceof Assignment)) { + return ORAstUtils.getExpressionValueAsArray(args.get(0), context::addDependency); + } else { + for (Expression e : args) { + if (e instanceof Assignment) { + Assignment assign = (Assignment) e; + String varName = assign.getVariable().printTrimmed(); + if ("value".equals(varName) || "path".equals(varName)) { + return ORAstUtils.getExpressionValueAsArray(assign.getAssignment(), context::addDependency); + } } } } - } else if (node.isSingleMemberAnnotation()) { - SingleMemberAnnotation singleNode = (SingleMemberAnnotation) node; - Expression expression = singleNode.getValue(); - return ASTUtils.getExpressionValueAsArray(expression, context::addDependency); } - + return new String[] { "" }; } @@ -164,26 +137,14 @@ public class RequestMappingSymbolProvider extends AbstractSymbolProvider { } private Annotation getParentAnnotation(Annotation node) { - ASTNode parent = node.getParent() != null ? node.getParent().getParent() : null; - while (parent != null && !(parent instanceof TypeDeclaration)) { - parent = parent.getParent(); - } - - if (parent != null) { - TypeDeclaration type = (TypeDeclaration) parent; - List modifiers = type.modifiers(); - Iterator iterator = modifiers.iterator(); - while (iterator.hasNext()) { - Object modifier = iterator.next(); - if (modifier instanceof Annotation) { - Annotation annotation = (Annotation) modifier; - ITypeBinding resolvedType = annotation.resolveTypeBinding(); - String annotationType = resolvedType.getQualifiedName(); - if (annotationType != null && Annotations.SPRING_REQUEST_MAPPING.equals(annotationType)) { - return annotation; - } + ClassDeclaration classDecl = ORAstUtils.findNode(node, ClassDeclaration.class); + if (classDecl != null) { + for (Annotation a : classDecl.getLeadingAnnotations()) { + FullyQualified annotationType = TypeUtils.asFullyQualified(a.getType()); + if (annotationType != null && Annotations.SPRING_REQUEST_MAPPING.equals(annotationType.getFullyQualifiedName())) { + return a; } - } + } } return null; } @@ -210,40 +171,26 @@ public class RequestMappingSymbolProvider extends AbstractSymbolProvider { } private String[] getAcceptTypes(Annotation node, SpringIndexerJavaContext context) { - if (node.isNormalAnnotation()) { - NormalAnnotation normNode = (NormalAnnotation) node; - List values = normNode.values(); - for (Iterator iterator = values.iterator(); iterator.hasNext();) { - Object object = iterator.next(); - if (object instanceof MemberValuePair) { - MemberValuePair pair = (MemberValuePair) object; - String valueName = pair.getName().getIdentifier(); - if (valueName != null && valueName.equals("consumes")) { - Expression expression = pair.getValue(); - return ASTUtils.getExpressionValueAsArray(expression, context::addDependency); - } + for (Expression e : node.getArguments()) { + if (e instanceof Assignment) { + Assignment assign = (Assignment) e; + if ("consumes".equals(assign.getVariable().printTrimmed())) { + return ORAstUtils.getExpressionValueAsArray(assign.getAssignment(), context::addDependency); } } - } + } return new String[0]; } private String[] getContentTypes(Annotation node, SpringIndexerJavaContext context) { - if (node.isNormalAnnotation()) { - NormalAnnotation normNode = (NormalAnnotation) node; - List values = normNode.values(); - for (Iterator iterator = values.iterator(); iterator.hasNext();) { - Object object = iterator.next(); - if (object instanceof MemberValuePair) { - MemberValuePair pair = (MemberValuePair) object; - String valueName = pair.getName().getIdentifier(); - if (valueName != null && valueName.equals("produces")) { - Expression expression = pair.getValue(); - return ASTUtils.getExpressionValueAsArray(expression, context::addDependency); - } + for (Expression e : node.getArguments()) { + if (e instanceof Assignment) { + Assignment assign = (Assignment) e; + if ("produces".equals(assign.getVariable().printTrimmed())) { + return ORAstUtils.getExpressionValueAsArray(assign.getAssignment(), context::addDependency); } } - } + } return new String[0]; } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java index 2596183b5..ee281be88 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxAcceptTypeFinder.java @@ -13,18 +13,20 @@ package org.springframework.ide.vscode.boot.java.requestmapping; import java.util.ArrayList; import java.util.List; -import org.eclipse.jdt.core.dom.ASTVisitor; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.lsp4j.Range; +import org.openrewrite.ExecutionContext; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.tree.J.FieldAccess; +import org.openrewrite.java.tree.J.MethodInvocation; +import org.openrewrite.java.tree.JavaType.Method; +import org.springframework.ide.vscode.boot.java.utils.ORAstUtils; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.text.TextDocument; /** * @author Martin Lippert */ -public class WebfluxAcceptTypeFinder extends ASTVisitor { +public class WebfluxAcceptTypeFinder extends JavaIsoVisitor { private List acceptTypes; private TextDocument doc; @@ -39,26 +41,28 @@ public class WebfluxAcceptTypeFinder extends ASTVisitor { } @Override - public boolean visit(MethodInvocation node) { - IMethodBinding methodBinding = node.resolveMethodBinding(); - - try { - if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { - String name = methodBinding.getName(); - if (name != null && WebfluxUtils.REQUEST_PREDICATE_ACCEPT_TYPE_METHOD.equals(name)) { - SimpleName nameArgument = WebfluxUtils.extractSimpleNameArgument(node); - if (nameArgument != null && nameArgument.getFullyQualifiedName() != null) { - Range range = doc.toRange(nameArgument.getStartPosition(), nameArgument.getLength()); - acceptTypes.add(new WebfluxRouteElement(nameArgument.getFullyQualifiedName().toString(), range)); + public MethodInvocation visitMethodInvocation(MethodInvocation methodInvocation, ExecutionContext p) { + Method method = methodInvocation.getMethodType(); + if (method != null && WebfluxUtils.isRouteMethodInvocation(method) && method.getDeclaringType() != null) { + try { + if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(method.getDeclaringType().getFullyQualifiedName())) { + String name = method.getName(); + if (name != null && WebfluxUtils.REQUEST_PREDICATE_ACCEPT_TYPE_METHOD.equals(name)) { + FieldAccess nameArgument = WebfluxUtils.extractArgument(methodInvocation, FieldAccess.class); + if (nameArgument != null) { + org.openrewrite.marker.Range r = ORAstUtils.getRange(nameArgument); + Range range = doc.toRange(r.getStart().getOffset(), r.length()); + acceptTypes.add(new WebfluxRouteElement(nameArgument.getSimpleName(), range)); + } } } } + catch (BadLocationException e) { + // ignore + } + } - catch (BadLocationException e) { - // ignore - } - - return !WebfluxUtils.isRouteMethodInvocation(methodBinding); + return super.visitMethodInvocation(methodInvocation, p); } - + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java index 0cab68340..a0b23fe3a 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxContentTypeFinder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 Pivotal, Inc. + * Copyright (c) 2018, 2022 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,18 +13,20 @@ package org.springframework.ide.vscode.boot.java.requestmapping; import java.util.ArrayList; import java.util.List; -import org.eclipse.jdt.core.dom.ASTVisitor; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.SimpleName; import org.eclipse.lsp4j.Range; +import org.openrewrite.ExecutionContext; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.tree.J.FieldAccess; +import org.openrewrite.java.tree.J.MethodInvocation; +import org.openrewrite.java.tree.JavaType.Method; +import org.springframework.ide.vscode.boot.java.utils.ORAstUtils; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.text.TextDocument; /** * @author Martin Lippert */ -public class WebfluxContentTypeFinder extends ASTVisitor { +public class WebfluxContentTypeFinder extends JavaIsoVisitor { private List contentTypes; private TextDocument doc; @@ -39,26 +41,28 @@ public class WebfluxContentTypeFinder extends ASTVisitor { } @Override - public boolean visit(MethodInvocation node) { - IMethodBinding methodBinding = node.resolveMethodBinding(); - - try { - if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { - String name = methodBinding.getName(); - if (name != null && WebfluxUtils.REQUEST_PREDICATE_CONTENT_TYPE_METHOD.equals(name)) { - SimpleName nameArgument = WebfluxUtils.extractSimpleNameArgument(node); - if (nameArgument != null && nameArgument.getFullyQualifiedName() != null) { - Range range = doc.toRange(nameArgument.getStartPosition(), nameArgument.getLength()); - contentTypes.add(new WebfluxRouteElement(nameArgument.getFullyQualifiedName().toString(), range)); + public MethodInvocation visitMethodInvocation(MethodInvocation methodInvocation, ExecutionContext p) { + Method method = methodInvocation.getMethodType(); + if (method != null && WebfluxUtils.isRouteMethodInvocation(method)) { + try { + if (method.getDeclaringType() != null && WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(method.getDeclaringType().getFullyQualifiedName())) { + String name = method.getName(); + if (name != null && WebfluxUtils.REQUEST_PREDICATE_CONTENT_TYPE_METHOD.equals(name)) { + FieldAccess nameArgument = WebfluxUtils.extractArgument(methodInvocation, FieldAccess.class); + if (nameArgument != null && nameArgument.getTarget() != null) { + org.openrewrite.marker.Range r = ORAstUtils.getRange(nameArgument); + Range range = doc.toRange(r.getStart().getOffset(), r.length()); + contentTypes.add(new WebfluxRouteElement(nameArgument.getSimpleName(), range)); + } } } } + catch (BadLocationException e) { + // ignore + } + return methodInvocation; } - catch (BadLocationException e) { - // ignore - } - - return !WebfluxUtils.isRouteMethodInvocation(methodBinding); + return super.visitMethodInvocation(methodInvocation, p); } - + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java index 50c34628e..21c45889b 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxMethodFinder.java @@ -13,25 +13,27 @@ package org.springframework.ide.vscode.boot.java.requestmapping; import java.util.ArrayList; import java.util.List; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.ASTVisitor; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.QualifiedName; import org.eclipse.lsp4j.Range; +import org.openrewrite.ExecutionContext; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.J.FieldAccess; +import org.openrewrite.java.tree.J.MethodInvocation; +import org.openrewrite.java.tree.JavaType.Method; +import org.springframework.ide.vscode.boot.java.utils.ORAstUtils; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.text.TextDocument; /** * @author Martin Lippert */ -public class WebfluxMethodFinder extends ASTVisitor { +public class WebfluxMethodFinder extends JavaIsoVisitor { private List methods; - private ASTNode root; + private J root; private TextDocument doc; - public WebfluxMethodFinder(ASTNode root, TextDocument doc) { + public WebfluxMethodFinder(J root, TextDocument doc) { this.root = root; this.doc = doc; this.methods = new ArrayList<>(); @@ -42,23 +44,24 @@ public class WebfluxMethodFinder extends ASTVisitor { } @Override - public boolean visit(MethodInvocation node) { + public MethodInvocation visitMethodInvocation(MethodInvocation methodInvocation, ExecutionContext p) { boolean visitChildren = true; - if (node != this.root) { - IMethodBinding methodBinding = node.resolveMethodBinding(); - + if (methodInvocation != this.root) { + Method method = methodInvocation.getMethodType(); try { - if (WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { - String name = methodBinding.getName(); + if (method != null && method.getDeclaringType() != null && WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(method.getDeclaringType().getFullyQualifiedName())) { + String name = method.getName(); if (name != null && WebfluxUtils.REQUEST_PREDICATE_HTTPMETHOD_METHODS.contains(name)) { - Range range = doc.toRange(node.getStartPosition(), node.getLength()); + org.openrewrite.marker.Range r = ORAstUtils.getRange(methodInvocation); + Range range = doc.toRange(r.getStart().getOffset(), r.length()); methods.add(new WebfluxRouteElement(name, range)); } else if (name != null && WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(name)) { - QualifiedName qualifiedName = WebfluxUtils.extractQualifiedNameArgument(node); - if (qualifiedName.getName() != null) { - Range range = doc.toRange(qualifiedName.getStartPosition(), qualifiedName.getLength()); + FieldAccess qualifiedName = WebfluxUtils.extractArgument(methodInvocation, FieldAccess.class); + if (qualifiedName != null) { + org.openrewrite.marker.Range r = ORAstUtils.getRange(qualifiedName); + Range range = doc.toRange(r.getStart().getOffset(), r.length()); methods.add(new WebfluxRouteElement(qualifiedName.getName().toString(), range)); } } @@ -68,11 +71,11 @@ public class WebfluxMethodFinder extends ASTVisitor { // ignore } - if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) { + if (WebfluxUtils.isRouteMethodInvocation(method)) { visitChildren = false; } } - return visitChildren; + return visitChildren ? super.visitMethodInvocation(methodInvocation, p) : methodInvocation; } - + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java index 464d90064..c376a2b47 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxPathFinder.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 Pivotal, Inc. + * Copyright (c) 2018, 2022 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -13,25 +13,27 @@ package org.springframework.ide.vscode.boot.java.requestmapping; import java.util.ArrayList; import java.util.List; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.ASTVisitor; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.StringLiteral; import org.eclipse.lsp4j.Range; +import org.openrewrite.ExecutionContext; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.J.Literal; +import org.openrewrite.java.tree.J.MethodInvocation; +import org.openrewrite.java.tree.JavaType.Method; +import org.springframework.ide.vscode.boot.java.utils.ORAstUtils; import org.springframework.ide.vscode.commons.util.BadLocationException; import org.springframework.ide.vscode.commons.util.text.TextDocument; /** * @author Martin Lippert */ -public class WebfluxPathFinder extends ASTVisitor { +public class WebfluxPathFinder extends JavaIsoVisitor { private List path; - private ASTNode root; + private J root; private TextDocument doc; - public WebfluxPathFinder(ASTNode root, TextDocument doc) { + public WebfluxPathFinder(J root, TextDocument doc) { this.root = root; this.doc = doc; this.path = new ArrayList<>(); @@ -40,24 +42,25 @@ public class WebfluxPathFinder extends ASTVisitor { public List getPath() { return path; } - + @Override - public boolean visit(MethodInvocation node) { + public MethodInvocation visitMethodInvocation(MethodInvocation methodInvocation, ExecutionContext p) { boolean visitChildren = true; - if (node != this.root) { - IMethodBinding methodBinding = node.resolveMethodBinding(); + if (methodInvocation != this.root) { + Method method = methodInvocation.getMethodType(); try { - if (methodBinding != null && methodBinding.getDeclaringClass() != null - && WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { + if (method != null && method.getDeclaringType() != null + && WebfluxUtils.REQUEST_PREDICATES_TYPE.equals(method.getDeclaringType().getFullyQualifiedName())) { - String name = methodBinding.getName(); + String name = method.getName(); if (name != null && WebfluxUtils.REQUEST_PREDICATE_ALL_PATH_METHODS.contains(name)) { - StringLiteral stringLiteral = WebfluxUtils.extractStringLiteralArgument(node); + Literal stringLiteral = WebfluxUtils.extractArgument(methodInvocation, Literal.class); if (stringLiteral != null) { - Range range = doc.toRange(stringLiteral.getStartPosition(), stringLiteral.getLength()); - path.add(new WebfluxRouteElement(stringLiteral.getLiteralValue(), range)); + org.openrewrite.marker.Range r = ORAstUtils.getRange(stringLiteral); + Range range = doc.toRange(r.getStart().getOffset(), r.length()); + path.add(new WebfluxRouteElement(ORAstUtils.getLiteralValue(stringLiteral), range)); } } } @@ -66,12 +69,14 @@ public class WebfluxPathFinder extends ASTVisitor { // ignore } - if (WebfluxUtils.isRouteMethodInvocation(methodBinding)) { + if (WebfluxUtils.isRouteMethodInvocation(method)) { visitChildren = false; } } - return visitChildren; + + return visitChildren ? super.visitMethodInvocation(methodInvocation, p) : methodInvocation; } + } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java index 88f4f0c7d..ef0677989 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxRouterSymbolProvider.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018, 2019 Pivotal, Inc. + * Copyright (c) 2018, 2022 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -15,25 +15,28 @@ import java.util.Collection; import java.util.List; import java.util.function.Function; -import org.eclipse.jdt.core.dom.ASTNode; -import org.eclipse.jdt.core.dom.ASTVisitor; -import org.eclipse.jdt.core.dom.Block; -import org.eclipse.jdt.core.dom.ExpressionMethodReference; -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.MethodInvocation; -import org.eclipse.jdt.core.dom.QualifiedName; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.StringLiteral; -import org.eclipse.jdt.core.dom.Type; -import org.eclipse.jdt.core.dom.TypeDeclaration; import org.eclipse.lsp4j.Location; import org.eclipse.lsp4j.Range; +import org.openrewrite.ExecutionContext; +import org.openrewrite.InMemoryExecutionContext; +import org.openrewrite.java.JavaIsoVisitor; +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.J.Block; +import org.openrewrite.java.tree.J.ClassDeclaration; +import org.openrewrite.java.tree.J.FieldAccess; +import org.openrewrite.java.tree.J.Literal; +import org.openrewrite.java.tree.J.MethodDeclaration; +import org.openrewrite.java.tree.J.MethodInvocation; +import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.JavaType.FullyQualified; +import org.openrewrite.java.tree.JavaType.Method; +import org.openrewrite.java.tree.TypeUtils; import org.springframework.ide.vscode.boot.java.handlers.AbstractSymbolProvider; import org.springframework.ide.vscode.boot.java.handlers.EnhancedSymbolInformation; import org.springframework.ide.vscode.boot.java.handlers.SymbolAddOnInformation; import org.springframework.ide.vscode.boot.java.utils.CachedSymbol; +import org.springframework.ide.vscode.boot.java.utils.ORAstUtils; import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJava.SCAN_PASS; import org.springframework.ide.vscode.boot.java.utils.SpringIndexerJavaContext; import org.springframework.ide.vscode.commons.util.BadLocationException; @@ -46,15 +49,15 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { @Override public void addSymbols(MethodDeclaration methodDeclaration, SpringIndexerJavaContext context, TextDocument doc) { - Type returnType = methodDeclaration.getReturnType2(); + JavaType returnType = methodDeclaration.getMethodType().getReturnType(); if (returnType != null) { - ITypeBinding resolvedBinding = returnType.resolveBinding(); + FullyQualified fqType = TypeUtils.asFullyQualified(returnType); - if (resolvedBinding != null && WebfluxUtils.ROUTER_FUNCTION_TYPE.equals(resolvedBinding.getBinaryName())) { + if (fqType != null && WebfluxUtils.ROUTER_FUNCTION_TYPE.equals(fqType.getFullyQualifiedName())) { Block methodBody = methodDeclaration.getBody(); - if (methodBody != null && methodBody.statements() != null && methodBody.statements().size() > 0) { + if (methodBody != null && methodBody.getStatements() != null && methodBody.getStatements().size() > 0) { addSymbolsForRouterFunction(methodBody, context, doc); } else if (SCAN_PASS.ONE.equals(context.getPass())) { @@ -66,20 +69,15 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { } private void addSymbolsForRouterFunction(Block methodBody, SpringIndexerJavaContext context, TextDocument doc) { - methodBody.accept(new ASTVisitor() { - - @Override - public boolean visit(MethodInvocation node) { - IMethodBinding methodBinding = node.resolveMethodBinding(); - - if (methodBinding != null && WebfluxUtils.isRouteMethodInvocation(methodBinding)) { - extractMappingSymbol(node, doc, context); + new JavaIsoVisitor() { + public MethodInvocation visitMethodInvocation(MethodInvocation method, ExecutionContext p) { + Method m = method.getMethodType(); + if (m != null && WebfluxUtils.isRouteMethodInvocation(m)) { + extractMappingSymbol(method, doc, context); } - - return super.visit(node); + return super.visitMethodInvocation(method, p); } - - }); + }.visitNonNull(methodBody, new InMemoryExecutionContext()); } protected void extractMappingSymbol(MethodInvocation node, TextDocument doc, SpringIndexerJavaContext context) { @@ -88,8 +86,10 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { WebfluxRouteElement[] contentTypes = extractContentTypes(node, doc); WebfluxRouteElement[] acceptTypes = extractAcceptTypes(node, doc); - int methodNameStart = node.getName().getStartPosition(); - int invocationStart = node.getStartPosition(); + org.openrewrite.marker.Range methodInvocationRange = ORAstUtils.getRange(node); + org.openrewrite.marker.Range methodNameRange = ORAstUtils.getRange(node.getName()); + int methodNameStart = methodInvocationRange.getStart().getOffset(); + int invocationStart = methodNameRange.getStart().getOffset(); StringBuilder pathBuilder = new StringBuilder(); for (WebfluxRouteElement pathElement : pathElements) { @@ -101,7 +101,7 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { if (path.length() > 0) { try { - Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, node.getLength() - (methodNameStart - invocationStart))); + Location location = new Location(doc.getUri(), doc.toRange(methodNameStart, methodInvocationRange.length() - (methodNameStart - invocationStart))); WebfluxHandlerInformation handler = extractHandlerInformation(node, path, httpMethods, contentTypes, acceptTypes); WebfluxElementsInformation elements = extractElementsInformation(pathElements, httpMethods, contentTypes, acceptTypes); @@ -136,24 +136,25 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { private WebfluxRouteElement[] extractPath(MethodInvocation routerInvocation, TextDocument doc) { WebfluxPathFinder pathFinder = new WebfluxPathFinder(routerInvocation, doc); - List arguments = routerInvocation.arguments(); - for (Object argument : arguments) { - if (argument != null && argument instanceof ASTNode) { - ((ASTNode)argument).accept(pathFinder); + InMemoryExecutionContext ctx = new InMemoryExecutionContext(); + for (Expression argument : routerInvocation.getArguments()) { + if (argument != null) { + pathFinder.visitNonNull(argument, ctx); } } List path = pathFinder.getPath(); extractNestedValue(routerInvocation, path, (methodInvocation) -> { - IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); + Method method = methodInvocation.getMethodType(); try { - if (methodBinding != null && WebfluxUtils.REQUEST_PREDICATE_PATH_METHOD.equals(methodBinding.getName())) { - StringLiteral stringLiteral = WebfluxUtils.extractStringLiteralArgument(methodInvocation); + if (method != null && WebfluxUtils.REQUEST_PREDICATE_PATH_METHOD.equals(method.getName())) { + Literal stringLiteral = WebfluxUtils.extractArgument(methodInvocation, Literal.class); if (stringLiteral != null) { - Range range = doc.toRange(stringLiteral.getStartPosition(), stringLiteral.getLength()); - return new WebfluxRouteElement(stringLiteral.getLiteralValue(), range); + org.openrewrite.marker.Range r = ORAstUtils.getRange(stringLiteral); + Range range = doc.toRange(r.getStart().getOffset(), r.length()); + return new WebfluxRouteElement(ORAstUtils.getLiteralValue(stringLiteral), range); } } } @@ -168,23 +169,24 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { private WebfluxRouteElement[] extractMethods(MethodInvocation routerInvocation, TextDocument doc) { WebfluxMethodFinder methodFinder = new WebfluxMethodFinder(routerInvocation, doc); - List arguments = routerInvocation.arguments(); - for (Object argument : arguments) { - if (argument != null && argument instanceof ASTNode) { - ((ASTNode)argument).accept(methodFinder); + InMemoryExecutionContext ctx = new InMemoryExecutionContext(); + for (Expression argument : routerInvocation.getArguments()) { + if (argument != null) { + methodFinder.visitNonNull(argument, ctx); } } final List methods = methodFinder.getMethods(); extractNestedValue(routerInvocation, methods, (methodInvocation) -> { - IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); + Method method = methodInvocation.getMethodType(); try { - if (methodBinding != null && WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(methodBinding.getName())) { - QualifiedName qualifiedName = WebfluxUtils.extractQualifiedNameArgument(methodInvocation); - if (qualifiedName.getName() != null) { - Range range = doc.toRange(qualifiedName.getStartPosition(), qualifiedName.getLength()); + if (method != null && WebfluxUtils.REQUEST_PREDICATE_METHOD_METHOD.equals(method.getName())) { + FieldAccess qualifiedName = WebfluxUtils.extractArgument(methodInvocation, FieldAccess.class); + if (qualifiedName != null) { + org.openrewrite.marker.Range r = ORAstUtils.getRange(qualifiedName); + Range range = doc.toRange(r.getStart().getOffset(), r.length()); return new WebfluxRouteElement(qualifiedName.getName().toString(), range); } } @@ -201,24 +203,25 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { private WebfluxRouteElement[] extractAcceptTypes(MethodInvocation routerInvocation, TextDocument doc) { WebfluxAcceptTypeFinder typeFinder = new WebfluxAcceptTypeFinder(doc); - List arguments = routerInvocation.arguments(); - for (Object argument : arguments) { - if (argument != null && argument instanceof ASTNode) { - ((ASTNode)argument).accept(typeFinder); + InMemoryExecutionContext ctx = new InMemoryExecutionContext(); + for (Expression argument : routerInvocation.getArguments()) { + if (argument != null) { + typeFinder.visitNonNull(argument, ctx); } } final List acceptTypes = typeFinder.getAcceptTypes(); extractNestedValue(routerInvocation, acceptTypes, (methodInvocation) -> { - IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); + Method methodBinding = methodInvocation.getMethodType(); try { if (methodBinding != null && WebfluxUtils.REQUEST_PREDICATE_ACCEPT_TYPE_METHOD.equals(methodBinding.getName())) { - SimpleName nameArgument = WebfluxUtils.extractSimpleNameArgument(methodInvocation); - if (nameArgument != null && nameArgument.getFullyQualifiedName() != null) { - Range range = doc.toRange(nameArgument.getStartPosition(), nameArgument.getLength()); - return new WebfluxRouteElement(nameArgument.getFullyQualifiedName().toString(), range); + FieldAccess nameArgument = WebfluxUtils.extractArgument(methodInvocation, FieldAccess.class); + if (nameArgument != null) { + org.openrewrite.marker.Range r = ORAstUtils.getRange(nameArgument); + Range range = doc.toRange(r.getStart().getOffset(), r.length()); + return new WebfluxRouteElement(nameArgument.getSimpleName(), range); } } } @@ -234,24 +237,27 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { private WebfluxRouteElement[] extractContentTypes(MethodInvocation routerInvocation, TextDocument doc) { WebfluxContentTypeFinder contentTypeFinder = new WebfluxContentTypeFinder(doc); - List arguments = routerInvocation.arguments(); - for (Object argument : arguments) { - if (argument != null && argument instanceof ASTNode) { - ((ASTNode)argument).accept(contentTypeFinder); + InMemoryExecutionContext ctx = new InMemoryExecutionContext(); + for (Expression argument : routerInvocation.getArguments()) { + if (argument != null) { + contentTypeFinder.visitNonNull(argument, ctx); } } final List contentTypes = contentTypeFinder.getContentTypes(); extractNestedValue(routerInvocation, contentTypes, (methodInvocation) -> { - IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); + Method methodBinding = methodInvocation.getMethodType(); try { if (methodBinding != null && WebfluxUtils.REQUEST_PREDICATE_CONTENT_TYPE_METHOD.equals(methodBinding.getName())) { - SimpleName nameArgument = WebfluxUtils.extractSimpleNameArgument(methodInvocation); - if (nameArgument != null && nameArgument.getFullyQualifiedName() != null) { - Range range = doc.toRange(nameArgument.getStartPosition(), nameArgument.getLength()); - return new WebfluxRouteElement(nameArgument.getFullyQualifiedName().toString(), range); + // TODO: OR AST FieldAcess? So we need FQ name of something? See above a lot of similar places + + FieldAccess nameArgument = WebfluxUtils.extractArgument(methodInvocation, FieldAccess.class); + if (nameArgument != null) { + org.openrewrite.marker.Range r = ORAstUtils.getRange(nameArgument); + Range range = doc.toRange(r.getStart().getOffset(), r.length()); + return new WebfluxRouteElement(nameArgument.getSimpleName(), range); } } } @@ -265,22 +271,21 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { return (WebfluxRouteElement[]) contentTypes.toArray(new WebfluxRouteElement[contentTypes.size()]); } - private void extractNestedValue(ASTNode node, Collection values, Function extractor) { - if (node == null || node instanceof TypeDeclaration) { + private void extractNestedValue(J node, Collection values, Function extractor) { + if (node == null || node instanceof ClassDeclaration) { return; } if (node instanceof MethodInvocation) { MethodInvocation methodInvocation = (MethodInvocation) node; - IMethodBinding methodBinding = methodInvocation.resolveMethodBinding(); + Method method = methodInvocation.getMethodType(); - if (methodBinding != null && methodBinding.getDeclaringClass() != null - && WebfluxUtils.ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { + if (method != null && method.getDeclaringType() != null + && WebfluxUtils.ROUTER_FUNCTIONS_TYPE.equals(method.getDeclaringType().getFullyQualifiedName())) { - String name = methodBinding.getName(); + String name = method.getName(); if (WebfluxUtils.REQUEST_PREDICATE_NEST_METHOD.equals(name)) { - List arguments = methodInvocation.arguments(); - for (Object argument : arguments) { + for (Expression argument : methodInvocation.getArguments()) { if (argument instanceof MethodInvocation) { MethodInvocation nestedMethod = (MethodInvocation) argument; WebfluxRouteElement value = extractor.apply(nestedMethod); @@ -293,32 +298,30 @@ public class WebfluxRouterSymbolProvider extends AbstractSymbolProvider { } } - extractNestedValue(node.getParent(), values, extractor); + extractNestedValue(ORAstUtils.getParent(node), values, extractor); } private WebfluxHandlerInformation extractHandlerInformation(MethodInvocation node, String path, WebfluxRouteElement[] httpMethods, WebfluxRouteElement[] contentTypes, WebfluxRouteElement[] acceptTypes) { - List arguments = node.arguments(); - - if (arguments != null) { - for (Object argument : arguments) { - if (argument instanceof ExpressionMethodReference) { - ExpressionMethodReference methodReference = (ExpressionMethodReference) argument; - IMethodBinding methodBinding = methodReference.resolveMethodBinding(); - - if (methodBinding != null && methodBinding.getDeclaringClass() != null && methodBinding.getMethodDeclaration() != null) { - String handlerClass = methodBinding.getDeclaringClass().getBinaryName(); - if (handlerClass != null) handlerClass = handlerClass.trim(); - - String handlerMethod = methodBinding.getMethodDeclaration().toString(); - if (handlerMethod != null) handlerMethod = handlerMethod.trim(); - - return new WebfluxHandlerInformation(handlerClass, handlerMethod, path, getElementStrings(httpMethods), getElementStrings(contentTypes), getElementStrings(acceptTypes)); - } - } + for (Expression e : node.getArguments()) { + // TODO: OR AST Method references!!! + +// if (argument instanceof ExpressionMethodReference) { +// ExpressionMethodReference methodReference = (ExpressionMethodReference) argument; +// IMethodBinding methodBinding = methodReference.resolveMethodBinding(); +// +// if (methodBinding != null && methodBinding.getDeclaringClass() != null && methodBinding.getMethodDeclaration() != null) { +// String handlerClass = methodBinding.getDeclaringClass().getBinaryName(); +// if (handlerClass != null) handlerClass = handlerClass.trim(); +// +// String handlerMethod = methodBinding.getMethodDeclaration().toString(); +// if (handlerMethod != null) handlerMethod = handlerMethod.trim(); +// +// return new WebfluxHandlerInformation(handlerClass, handlerMethod, path, getElementStrings(httpMethods), getElementStrings(contentTypes), getElementStrings(acceptTypes)); +// } +// } } - } return null; } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java index af7a3c547..e1a62d2d0 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/requestmapping/WebfluxUtils.java @@ -16,11 +16,10 @@ import java.util.List; import java.util.Set; import java.util.function.Function; -import org.eclipse.jdt.core.dom.IMethodBinding; -import org.eclipse.jdt.core.dom.MethodInvocation; -import org.eclipse.jdt.core.dom.QualifiedName; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.StringLiteral; +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J.Literal; +import org.openrewrite.java.tree.J.MethodInvocation; +import org.openrewrite.java.tree.JavaType.Method; /** * @author Martin Lippert @@ -41,53 +40,30 @@ public class WebfluxUtils { public static final Set REQUEST_PREDICATE_ALL_PATH_METHODS = new HashSet<>(Arrays.asList(REQUEST_PREDICATE_PATH_METHOD, "GET", "POST", "DELETE", "PUT", "PATCH", "HEAD", "OPTIONS")); - public static StringLiteral extractStringLiteralArgument(MethodInvocation node) { - List arguments = node.arguments(); - if (arguments != null && arguments.size() > 0) { - Object object = arguments.get(0); - if (object instanceof StringLiteral) { - return (StringLiteral) object; + public static T extractArgument(MethodInvocation node, Class clazz) { + if (node.getArguments() != null) { + for (Expression e : node.getArguments()) { + if (clazz.isInstance(e)) { + return clazz.cast(e); + } } } return null; } - public static QualifiedName extractQualifiedNameArgument(MethodInvocation node) { - List arguments = node.arguments(); - if (arguments != null && arguments.size() > 0) { - Object object = arguments.get(0); - if (object instanceof QualifiedName) { - return (QualifiedName) object; - } - } - return null; - } - - public static SimpleName extractSimpleNameArgument(MethodInvocation node) { - List arguments = node.arguments(); - if (arguments != null && arguments.size() > 0) { - Object object = arguments.get(0); - if (object instanceof SimpleName) { - return (SimpleName) object; - } - } - return null; - } - - public static boolean isRouteMethodInvocation(IMethodBinding methodBinding) { - if (ROUTER_FUNCTIONS_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { - String name = methodBinding.getName(); - if ("route".equals(name)) { + public static boolean isRouteMethodInvocation(Method method) { + switch (method.getDeclaringType().getFullyQualifiedName()) { + case ROUTER_FUNCTIONS_TYPE: + if ("route".equals(method.getName())) { return true; } - } - else if (ROUTER_FUNCTION_TYPE.equals(methodBinding.getDeclaringClass().getBinaryName())) { - String name = methodBinding.getName(); - if ("andRoute".equals(name)) { + break; + case ROUTER_FUNCTION_TYPE: + if ("andRoute".equals(method.getName())) { return true; } + break; } - return false; } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/FunctionUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/FunctionUtils.java index 283b4da34..c494a9277 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/FunctionUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/FunctionUtils.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2018 Pivotal, Inc. + * Copyright (c) 2018, 2022 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -10,14 +10,14 @@ *******************************************************************************/ package org.springframework.ide.vscode.boot.java.utils; -import java.util.List; import java.util.function.Consumer; import java.util.function.Function; import java.util.function.Supplier; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.Modifier; -import org.eclipse.jdt.core.dom.TypeDeclaration; +import org.openrewrite.java.tree.J.ClassDeclaration; +import org.openrewrite.java.tree.J.Modifier; +import org.openrewrite.java.tree.JavaType.FullyQualified; +import org.openrewrite.java.tree.JavaType.FullyQualified.Kind; import org.springframework.ide.vscode.boot.java.beans.BeanUtils; import org.springframework.ide.vscode.commons.util.text.DocumentRegion; import org.springframework.ide.vscode.commons.util.text.TextDocument; @@ -34,10 +34,10 @@ public class FunctionUtils { public static final String FUNCTION_CONSUMER_TYPE = Consumer.class.getName(); public static final String FUNCTION_SUPPLIER_TYPE = Supplier.class.getName(); - public static Tuple3 getFunctionBean(TypeDeclaration typeDeclaration, TextDocument doc) { - ITypeBinding resolvedType = typeDeclaration.resolveBinding(); + public static Tuple3 getFunctionBean(ClassDeclaration typeDeclaration, TextDocument doc) { + FullyQualified resolvedType = typeDeclaration.getType(); - if (resolvedType != null && !resolvedType.isInterface() && !isAbstractClass(typeDeclaration, resolvedType)) { + if (resolvedType != null && resolvedType.getKind() == Kind.Class && !isAbstractClass(typeDeclaration)) { return getFunctionBean(typeDeclaration, doc, resolvedType); } else { @@ -45,24 +45,16 @@ public class FunctionUtils { } } - private static Tuple3 getFunctionBean(TypeDeclaration typeDeclaration, TextDocument doc, - ITypeBinding resolvedType) { - - ITypeBinding[] interfaces = resolvedType.getInterfaces(); - for (ITypeBinding resolvedInterface : interfaces) { - String simplifiedType = null; - if (resolvedInterface.isParameterizedType()) { - simplifiedType = resolvedInterface.getBinaryName(); - } - else { - simplifiedType = resolvedType.getQualifiedName(); - } + private static Tuple3 getFunctionBean(ClassDeclaration typeDeclaration, TextDocument doc, + FullyQualified resolvedType) { + for (FullyQualified resolvedInterface : resolvedType.getInterfaces()) { + String simplifiedType = resolvedInterface.getFullyQualifiedName(); if (FUNCTION_FUNCTION_TYPE.equals(simplifiedType) || FUNCTION_CONSUMER_TYPE.equals(simplifiedType) || FUNCTION_SUPPLIER_TYPE.equals(simplifiedType)) { String beanName = getBeanName(typeDeclaration); - String beanType = resolvedInterface.getName(); - DocumentRegion region = ASTUtils.nodeRegion(doc, typeDeclaration.getName()); + String beanType = resolvedInterface.toString(); + DocumentRegion region = ORAstUtils.nodeRegion(doc, typeDeclaration.getName()); return Tuples.of(beanName, beanType, region); } @@ -74,7 +66,7 @@ public class FunctionUtils { } } - ITypeBinding superclass = resolvedType.getSuperclass(); + FullyQualified superclass = resolvedType.getSupertype(); if (superclass != null) { return getFunctionBean(typeDeclaration, doc, superclass); } @@ -83,22 +75,13 @@ public class FunctionUtils { } } - protected static String getBeanName(TypeDeclaration typeDeclaration) { - String beanName = typeDeclaration.getName().toString(); + protected static String getBeanName(ClassDeclaration typeDeclaration) { + String beanName = typeDeclaration.getSimpleName(); return BeanUtils.getBeanNameFromType(beanName); } - protected static boolean isAbstractClass(TypeDeclaration typeDeclaration, ITypeBinding resolvedType) { - List modifiers = typeDeclaration.modifiers(); - for (Object object : modifiers) { - if (object instanceof Modifier) { - if (((Modifier) object).isAbstract()) { - return true; - } - } - } - - return false; + protected static boolean isAbstractClass(ClassDeclaration typeDeclaration) { + return Modifier.hasModifier(typeDeclaration.getModifiers(), Modifier.Type.Abstract); } } diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/ORAstUtils.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/ORAstUtils.java index dcad5138f..07fb1d306 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/ORAstUtils.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/ORAstUtils.java @@ -10,14 +10,6 @@ import java.util.concurrent.atomic.AtomicReference; import java.util.function.Consumer; import java.util.stream.Collectors; -import org.eclipse.jdt.core.dom.ArrayInitializer; -import org.eclipse.jdt.core.dom.IBinding; -import org.eclipse.jdt.core.dom.ITypeBinding; -import org.eclipse.jdt.core.dom.IVariableBinding; -import org.eclipse.jdt.core.dom.Name; -import org.eclipse.jdt.core.dom.QualifiedName; -import org.eclipse.jdt.core.dom.SimpleName; -import org.eclipse.jdt.core.dom.StringLiteral; import org.openrewrite.ExecutionContext; import org.openrewrite.InMemoryExecutionContext; import org.openrewrite.Parser; @@ -49,9 +41,12 @@ import org.openrewrite.marker.Range; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.ide.vscode.boot.java.Annotations; +import org.springframework.ide.vscode.commons.util.CollectorUtil; import org.springframework.ide.vscode.commons.util.text.DocumentRegion; import org.springframework.ide.vscode.commons.util.text.TextDocument; +import com.google.common.collect.ImmutableList; + public class ORAstUtils { private static final Logger log = LoggerFactory.getLogger(ORAstUtils.class); @@ -402,6 +397,21 @@ public class ORAstUtils { } return null; } + + public static List getExpressionValueAsListOfLiterals(Expression exp) { + if (exp instanceof NewArray) { + NewArray array = (NewArray) exp; + return array.getInitializer().stream() + .filter(Literal.class::isInstance) + .map(Literal.class::cast) + .collect(CollectorUtil.toImmutableList()); + } else if (exp instanceof Literal){ + return ImmutableList.of((Literal)exp); + } + return ImmutableList.of(); + } + + public static String getExpressionValueAsString(Expression exp, Consumer dependencies) { // TODO: OR AST need to check if there is way to extract constant values from variables @@ -417,6 +427,17 @@ public class ORAstUtils { return null; } } + + public static DocumentRegion stringRegion(TextDocument doc, Literal node) { + DocumentRegion nodeRegion = nodeRegion(doc, node); + if (nodeRegion.startsWith("\"")) { + nodeRegion = nodeRegion.subSequence(1); + } + if (nodeRegion.endsWith("\"")) { + nodeRegion = nodeRegion.subSequence(0, nodeRegion.getLength()-1); + } + return nodeRegion; + } public static List parse(JavaParser parser, Iterable sourceFiles) { List cus = parser.parse(sourceFiles, null, new InMemoryExecutionContext()); diff --git a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJavaContext.java b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJavaContext.java index 6ad76e03c..ca81e4c16 100644 --- a/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJavaContext.java +++ b/headless-services/spring-boot-language-server/src/main/java/org/springframework/ide/vscode/boot/java/utils/SpringIndexerJavaContext.java @@ -110,12 +110,12 @@ public class SpringIndexerJavaContext { return dependencies; } - public void addDependency(ITypeBinding dependsOn) { - if (dependsOn != null && dependsOn.isFromSource()) { - String type = dependsOn.getKey(); + public void addDependency(FullyQualified type) { + if (type != null && false/*dependsOn.isFromSource()*/ ) { // TODO: OR AST can't tell if type has a source + String fqName = type.getFullyQualifiedName(); if (type != null && !scannedTypes.contains(type)) { - dependencies.add(type); + dependencies.add(fqName); } } } diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java index 9a0b37c18..915295efc 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/utils/test/CompilationUnitCacheTest.java @@ -1,5 +1,5 @@ /******************************************************************************* - * Copyright (c) 2017, 2020 Pivotal, Inc. + * Copyright (c) 2017, 2022 Pivotal, Inc. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at @@ -21,9 +21,9 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import org.eclipse.jdt.core.dom.CompilationUnit; import org.junit.Test; import org.junit.runner.RunWith; +import org.openrewrite.java.tree.J.CompilationUnit; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; diff --git a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/value/test/ValueSpelExpressionValidationTest.java b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/value/test/ValueSpelExpressionValidationTest.java index 649a62e25..5a8e44ab4 100644 --- a/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/value/test/ValueSpelExpressionValidationTest.java +++ b/headless-services/spring-boot-language-server/src/test/java/org/springframework/ide/vscode/boot/java/value/test/ValueSpelExpressionValidationTest.java @@ -43,6 +43,7 @@ import org.springframework.ide.vscode.boot.java.handlers.BootJavaReconcileEngine import org.springframework.ide.vscode.boot.java.links.SourceLinkFactory; import org.springframework.ide.vscode.boot.java.links.SourceLinks; import org.springframework.ide.vscode.boot.java.utils.CompilationUnitCache; +import org.springframework.ide.vscode.boot.java.utils.ORCompilationUnitCache; import org.springframework.ide.vscode.boot.java.utils.SymbolCache; import org.springframework.ide.vscode.boot.java.utils.SymbolCacheVoid; import org.springframework.ide.vscode.boot.metadata.ValueProviderRegistry; @@ -71,7 +72,7 @@ public class ValueSpelExpressionValidationTest { @Autowired private BootLanguageServerHarness harness; @Autowired private IJavaProject testProject; @Autowired private JavaProjectFinder projectFinder; - @Autowired private CompilationUnitCache compilationUnitCache; + @Autowired private ORCompilationUnitCache compilationUnitCache; @Autowired private SimpleLanguageServer server; private File directory;