Skip to content

Commit

Permalink
Fix: issue with resolving overloaded methods with same number of para…
Browse files Browse the repository at this point in the history
…meters for javassist types
  • Loading branch information
maartenc committed Mar 7, 2019
1 parent cfde589 commit a1373b7
Show file tree
Hide file tree
Showing 10 changed files with 97 additions and 29 deletions.
Expand Up @@ -123,7 +123,7 @@ public String getQualifiedName() {
@Deprecated
public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes,
Context invokationContext, List<ResolvedType> typeParameterValues) {
return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext);
return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, getTypeParameters(), typeParameterValues);
}

@Deprecated
Expand Down
Expand Up @@ -202,7 +202,7 @@ public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<

public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes,
Context invokationContext, List<ResolvedType> typeParameterValues) {
return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext);
return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, getTypeParameters(), typeParameterValues);
}

@Override
Expand Down
Expand Up @@ -99,7 +99,7 @@ public String getQualifiedName() {
public Optional<MethodUsage> solveMethodAsUsage(String name, List<ResolvedType> argumentsTypes,
Context invokationContext, List<ResolvedType> typeParameterValues) {

return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, invokationContext);
return JavassistUtils.getMethodUsage(ctClass, name, argumentsTypes, typeSolver, getTypeParameters(), typeParameterValues);
}

@Override
Expand Down
Expand Up @@ -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;

/**
Expand Down Expand Up @@ -160,7 +157,7 @@ public boolean isAbstract() {
public List<ResolvedTypeParameterDeclaration> 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());
Expand Down
Expand Up @@ -70,7 +70,7 @@ private void collectDeclaredFields(CtClass ctClass, List<ResolvedFieldDeclaratio

public List<ResolvedTypeParameterDeclaration> getTypeParameters() {
if (null == ctClass.getGenericSignature()) {
return Collections.emptyList();
return new ArrayList<>();
} else {
try {
SignatureAttribute.ClassSignature classSignature =
Expand Down
Expand Up @@ -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.*;

Expand All @@ -36,26 +36,29 @@
*/
class JavassistUtils {

static Optional<MethodUsage> getMethodUsage(CtClass ctClass, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver, Context invokationContext) {
// TODO avoid bridge and synthetic methods
static Optional<MethodUsage> getMethodUsage(CtClass ctClass, String name, List<ResolvedType> argumentsTypes, TypeSolver typeSolver,
List<ResolvedTypeParameterDeclaration> typeParameters, List<ResolvedType> typeParameterValues) {
List<MethodUsage> 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<MethodUsage> ref = JavassistUtils.getMethodUsage(superClass, name, argumentsTypes, typeSolver, invokationContext);
Optional<MethodUsage> ref = JavassistUtils.getMethodUsage(superClass, name, argumentsTypes, typeSolver, typeParameters, typeParameterValues);
if (ref.isPresent()) {
return ref;
methods.add(ref.get());
}
}
} catch (NotFoundException e) {
Expand All @@ -64,16 +67,16 @@ static Optional<MethodUsage> getMethodUsage(CtClass ctClass, String name, List<R

try {
for (CtClass interfaze : ctClass.getInterfaces()) {
Optional<MethodUsage> ref = JavassistUtils.getMethodUsage(interfaze, name, argumentsTypes, typeSolver, invokationContext);
Optional<MethodUsage> 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) {
Expand Down
@@ -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<MethodCallExpr> 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<R, A>", 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<A>", methodUsage2.getParamType(0).describe());
}
}
@@ -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);
}
}
Expand Up @@ -40,7 +40,7 @@
Line 161) SymbolReference.unsolved(ConstructorDeclaration.class) ==> com.github.javaparser.symbolsolver.model.resolution.SymbolReference.unsolved(java.lang.Class<S2>)
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()
Expand Down
Expand Up @@ -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<? super T, A, R>)
Line 308) this.wrappedNode.getTypeParameters().stream().map((tp) -> new JavaParserTypeParameter(tp, typeSolver)) ==> java.util.stream.Stream.map(java.util.function.Function<? super T, ? extends R>)
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()
Expand Down Expand Up @@ -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<? super T, A, R>)
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<? super T, ? extends R>)
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()
Expand Down

0 comments on commit a1373b7

Please sign in to comment.