From a1373b7840da2f72c2f47aa3d38a7e46429c5291 Mon Sep 17 00:00:00 2001 From: Maarten Coene Date: Thu, 7 Mar 2019 16:47:42 +0100 Subject: [PATCH] Fix: issue with resolving overloaded methods with same number of parameters for javassist types --- .../JavassistClassDeclaration.java | 2 +- .../JavassistEnumDeclaration.java | 2 +- .../JavassistInterfaceDeclaration.java | 2 +- .../JavassistMethodDeclaration.java | 7 +-- .../JavassistTypeDeclarationAdapter.java | 2 +- .../javassistmodel/JavassistUtils.java | 31 +++++----- .../MethodsResolutionWithJavassistTest.java | 56 +++++++++++++++++++ .../resources/OverloadedMethodCall.java.txt | 12 ++++ ...olver_javaparsermodel_JavaParserFacade.txt | 2 +- ...eclarations_JavaParserClassDeclaration.txt | 10 ++-- 10 files changed, 97 insertions(+), 29 deletions(-) create mode 100644 javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionWithJavassistTest.java create mode 100644 javaparser-symbol-solver-testing/src/test/resources/OverloadedMethodCall.java.txt diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java index 2d1fcee9ca..9c6993a6e6 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistClassDeclaration.java @@ -123,7 +123,7 @@ public String getQualifiedName() { @Deprecated public Optional solveMethodAsUsage(String name, List argumentsTypes, Context invokationContext, List typeParameterValues) { - return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext); + return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, getTypeParameters(), typeParameterValues); } @Deprecated diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java index 4875848774..9acf93c277 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistEnumDeclaration.java @@ -202,7 +202,7 @@ public SymbolReference solveMethod(String name, List< public Optional solveMethodAsUsage(String name, List argumentsTypes, Context invokationContext, List typeParameterValues) { - return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext); + return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, getTypeParameters(), typeParameterValues); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java index 9692423d80..8417933bf0 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclaration.java @@ -99,7 +99,7 @@ public String getQualifiedName() { public Optional solveMethodAsUsage(String name, List argumentsTypes, Context invokationContext, List typeParameterValues) { - return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext); + return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, getTypeParameters(), typeParameterValues); } @Override diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java index da4e8983b0..a3c6f7ea01 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistMethodDeclaration.java @@ -34,10 +34,7 @@ import javassist.bytecode.SignatureAttribute; import java.lang.reflect.Modifier; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.Optional; +import java.util.*; import java.util.stream.Collectors; /** @@ -160,7 +157,7 @@ public boolean isAbstract() { public List getTypeParameters() { try { if (ctMethod.getGenericSignature() == null) { - return Collections.emptyList(); + return new ArrayList<>(); } SignatureAttribute.MethodSignature methodSignature = SignatureAttribute.toMethodSignature(ctMethod.getGenericSignature()); return Arrays.stream(methodSignature.getTypeParameters()).map((jasTp) -> new JavassistTypeParameter(jasTp, this, typeSolver)).collect(Collectors.toList()); diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java index 84a2771e14..2b3d22f738 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistTypeDeclarationAdapter.java @@ -70,7 +70,7 @@ private void collectDeclaredFields(CtClass ctClass, List getTypeParameters() { if (null == ctClass.getGenericSignature()) { - return Collections.emptyList(); + return new ArrayList<>(); } else { try { SignatureAttribute.ClassSignature classSignature = diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java index f753db76bc..0af0c3b6f7 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistUtils.java @@ -22,9 +22,9 @@ import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; import com.github.javaparser.resolution.declarations.ResolvedTypeParametrizable; import com.github.javaparser.resolution.types.*; -import com.github.javaparser.symbolsolver.core.resolution.Context; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; import com.github.javaparser.symbolsolver.model.typesystem.ReferenceTypeImpl; +import com.github.javaparser.symbolsolver.resolution.MethodResolutionLogic; import javassist.*; import javassist.bytecode.*; @@ -36,26 +36,29 @@ */ class JavassistUtils { - static Optional getMethodUsage(CtClass ctClass, String name, List argumentsTypes, TypeSolver typeSolver, Context invokationContext) { - // TODO avoid bridge and synthetic methods + static Optional getMethodUsage(CtClass ctClass, String name, List argumentsTypes, TypeSolver typeSolver, + List typeParameters, List typeParameterValues) { + List methods = new ArrayList<>(); for (CtMethod method : ctClass.getDeclaredMethods()) { - if (method.getName().equals(name)) { - // TODO check typeParametersValues + if (method.getName().equals(name) + && ((method.getMethodInfo().getAccessFlags() & AccessFlag.BRIDGE) == 0) + && ((method.getMethodInfo().getAccessFlags() & AccessFlag.SYNTHETIC) == 0)) { MethodUsage methodUsage = new MethodUsage(new JavassistMethodDeclaration(method, typeSolver)); - if (argumentsTypes.size() < methodUsage.getNoParams()) { - // this method cannot be a good candidate (except if variadic ?) - continue; + for (int i = 0; i < typeParameters.size() && i < typeParameterValues.size(); i++) { + ResolvedTypeParameterDeclaration tpToReplace = typeParameters.get(i); + ResolvedType newValue = typeParameterValues.get(i); + methodUsage = methodUsage.replaceTypeParameter(tpToReplace, newValue); } - return Optional.of(methodUsage); + methods.add(methodUsage); } } try { CtClass superClass = ctClass.getSuperclass(); if (superClass != null) { - Optional ref = JavassistUtils.getMethodUsage(superClass, name, argumentsTypes, typeSolver, invokationContext); + Optional ref = JavassistUtils.getMethodUsage(superClass, name, argumentsTypes, typeSolver, typeParameters, typeParameterValues); if (ref.isPresent()) { - return ref; + methods.add(ref.get()); } } } catch (NotFoundException e) { @@ -64,16 +67,16 @@ static Optional getMethodUsage(CtClass ctClass, String name, List ref = JavassistUtils.getMethodUsage(interfaze, name, argumentsTypes, typeSolver, invokationContext); + Optional ref = JavassistUtils.getMethodUsage(interfaze, name, argumentsTypes, typeSolver, typeParameters, typeParameterValues); if (ref.isPresent()) { - return ref; + methods.add(ref.get()); } } } catch (NotFoundException e) { throw new RuntimeException(e); } - return Optional.empty(); + return MethodResolutionLogic.findMostApplicableUsage(methods, name, argumentsTypes, typeSolver); } static ResolvedType signatureTypeToType(SignatureAttribute.Type signatureType, TypeSolver typeSolver, ResolvedTypeParametrizable typeParametrizable) { diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionWithJavassistTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionWithJavassistTest.java new file mode 100644 index 0000000000..641f59b6ba --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/MethodsResolutionWithJavassistTest.java @@ -0,0 +1,56 @@ +package com.github.javaparser.symbolsolver.resolution; + +import com.github.javaparser.ParserConfiguration; +import com.github.javaparser.StaticJavaParser; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; +import com.github.javaparser.ast.body.MethodDeclaration; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.resolution.MethodUsage; +import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparser.Navigator; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.javaparsermodel.contexts.CompilationUnitContext; +import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; +import com.github.javaparser.symbolsolver.resolution.typesolvers.JarTypeSolver; +import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; +import com.github.javaparser.utils.Log; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static org.junit.Assert.assertEquals; + +public class MethodsResolutionWithJavassistTest extends AbstractResolutionTest { + + @AfterEach + void resetConfiguration() { + StaticJavaParser.setConfiguration(new ParserConfiguration()); + Log.setAdapter(new Log.SilentAdapter()); + } + + @Test + public void testOverloadedMethods() throws Exception { + CompilationUnit cu = parseSample("OverloadedMethodCall"); + + CombinedTypeSolver typeSolver = new CombinedTypeSolver(); + typeSolver.add(new JarTypeSolver(adaptPath("src/test/resources/javaparser-core-3.0.0-alpha.2.jar"))); + typeSolver.add(new ReflectionTypeSolver()); + + Context context = new CompilationUnitContext(cu, typeSolver); + ClassOrInterfaceDeclaration classA = Navigator.demandClass(cu, "OverloadedMethodCall"); + MethodDeclaration method = Navigator.demandMethod(classA, "foo"); + + List calls = method.findAll(MethodCallExpr.class, n -> n.getNameAsString().equals("accept")); + assertEquals(2, calls.size()); + + // node.accept((GenericVisitor) null, null); + MethodUsage methodUsage1 = JavaParserFacade.get(typeSolver).solveMethodAsUsage(calls.get(0)); + assertEquals("com.github.javaparser.ast.visitor.GenericVisitor", methodUsage1.getParamType(0).describe()); + + // node.accept((VoidVisitor) null, null); + MethodUsage methodUsage2 = JavaParserFacade.get(typeSolver).solveMethodAsUsage(calls.get(1)); + assertEquals("com.github.javaparser.ast.visitor.VoidVisitor", methodUsage2.getParamType(0).describe()); + } +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethodCall.java.txt b/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethodCall.java.txt new file mode 100644 index 0000000000..094832c2d7 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/OverloadedMethodCall.java.txt @@ -0,0 +1,12 @@ +package test; + +import com.github.javaparser.ast.Node; +import com.github.javaparser.ast.visitor.GenericVisitor; +import com.github.javaparser.ast.visitor.VoidVisitor; + +public class OverloadedMethodCall { + public void foo(Node node) { + node.accept((GenericVisitor) null, null); + node.accept((VoidVisitor) null, null); + } +} \ No newline at end of file diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt index 915f610223..041284dfd2 100644 --- a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt +++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_JavaParserFacade.txt @@ -40,7 +40,7 @@ Line 161) SymbolReference.unsolved(ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class) Line 163) optAncestor.get() ==> java.util.Optional.get() Line 165) explicitConstructorInvocationStmt.isThis() ==> com.github.javaparser.ast.stmt.ExplicitConstructorInvocationStmt.isThis() - Line 166) JavaParserFacade.get(typeSolver).convert(classNode.getExtendedTypes(0), classNode) ==> UNSOLVED + Line 166) JavaParserFacade.get(typeSolver).convert(classNode.getExtendedTypes(0), classNode) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node) Line 166) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver) Line 166) classNode.getExtendedTypes(0) ==> com.github.javaparser.ast.nodeTypes.NodeWithExtends.getExtendedTypes(int) Line 167) classDecl.isReferenceType() ==> com.github.javaparser.symbolsolver.model.typesystem.Type.isReferenceType() diff --git a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt index af627c4e2a..6b42d18997 100644 --- a/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt +++ b/javaparser-symbol-solver-testing/src/test/test_sourcecode/javasymbolsolver_0_6_0/expected_output/java-symbol-solver-core/com_github_javaparser_symbolsolver_javaparsermodel_declarations_JavaParserClassDeclaration.txt @@ -89,8 +89,8 @@ Line 289) ancestors.add(ancestor) ==> java.util.List.add(E) Line 298) wrappedNode.getMembers() ==> com.github.javaparser.ast.body.TypeDeclaration.getMembers() Line 300) methods.add(new JavaParserMethodDeclaration((com.github.javaparser.ast.body.MethodDeclaration) member, typeSolver)) ==> java.util.Set.add(E) - Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)).collect(Collectors.toList()) ==> ERROR - Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)) ==> ERROR + Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector) + Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function) Line 308) this.wrappedNode.getTypeParameters().stream() ==> java.util.Collection.stream() Line 308) this.wrappedNode.getTypeParameters() ==> com.github.javaparser.ast.body.ClassOrInterfaceDeclaration.getTypeParameters() Line 310) Collectors.toList() ==> java.util.stream.Collectors.toList() @@ -127,12 +127,12 @@ Line 373) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments() Line 374) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType() Line 374) ref.getCorrespondingDeclaration() ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.getCorrespondingDeclaration() - Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))).collect(Collectors.toList()) ==> ERROR - Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) ==> ERROR + Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))).collect(Collectors.toList()) ==> java.util.stream.Stream.collect(java.util.stream.Collector) + Line 376) classOrInterfaceType.getTypeArguments().get().stream().map(ta -> new LazyType(v -> JavaParserFacade.get(typeSolver).convert(ta, ta))) ==> java.util.stream.Stream.map(java.util.function.Function) Line 376) classOrInterfaceType.getTypeArguments().get().stream() ==> java.util.Collection.stream() Line 376) classOrInterfaceType.getTypeArguments().get() ==> java.util.Optional.get() Line 376) classOrInterfaceType.getTypeArguments() ==> com.github.javaparser.ast.type.ClassOrInterfaceType.getTypeArguments() - Line 377) JavaParserFacade.get(typeSolver).convert(ta, ta) ==> ERROR + Line 377) JavaParserFacade.get(typeSolver).convert(ta, ta) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.convert(com.github.javaparser.ast.type.Type, com.github.javaparser.ast.Node) Line 377) JavaParserFacade.get(typeSolver) ==> com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade.get(com.github.javaparser.symbolsolver.model.resolution.TypeSolver) Line 378) Collectors.toList() ==> java.util.stream.Collectors.toList() Line 379) ref.getCorrespondingDeclaration().asReferenceType() ==> com.github.javaparser.symbolsolver.model.declarations.TypeDeclaration.asReferenceType()