diff options
author | Roger Howell <MysterAitch@users.noreply.github.com> | 2020-08-14 16:10:11 +0000 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-08-14 16:10:11 +0000 |
commit | d4a71cf89e68a1d04c6a2ea4f5af83d450afee95 (patch) | |
tree | 969fd36ee9c048b92040232693ee635f16e24f61 | |
parent | 64ef518d6c10e9d570e9d3c1440a2df4f83ac468 (diff) | |
parent | 28612c837aa0f766e8f55c6b3a58789467c62e8f (diff) | |
download | platform_external_javaparser-d4a71cf89e68a1d04c6a2ea4f5af83d450afee95.tar.gz platform_external_javaparser-d4a71cf89e68a1d04c6a2ea4f5af83d450afee95.tar.bz2 platform_external_javaparser-d4a71cf89e68a1d04c6a2ea4f5af83d450afee95.zip |
Merge branch 'master' into symbolsolver-stackoverflow-fieldaccess
25 files changed, 619 insertions, 20 deletions
diff --git a/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java b/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java index 4e0456efa..5f64cdc10 100644 --- a/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java +++ b/javaparser-core/src/main/java/com/github/javaparser/resolution/MethodUsage.java @@ -181,9 +181,34 @@ public class MethodUsage implements ResolvedTypeParametrized { return typeParametersMap; } + /** + * The qualified signature of the method. It is composed by the qualified name of the declaring type + * followed by the signature of the method. + */ public String getQualifiedSignature() { - // TODO use the type parameters - return this.getDeclaration().getQualifiedSignature(); + return getDeclaration().declaringType().getQualifiedName() + "." + getSignature(); + } + + /** + * The signature of the method. + */ + public String getSignature() { + StringBuilder sb = new StringBuilder(); + sb.append(getName()); + sb.append("("); + for (int i = 0; i < getNoParams(); i++) { + if (i != 0) { + sb.append(", "); + } + ResolvedType type = getParamType(i); + if (type.isArray() && getDeclaration().getParam(i).isVariadic()) { + sb.append(type.asArrayType().getComponentType().describe()).append("..."); + } else { + sb.append(type.describe()); + } + } + sb.append(")"); + return sb.toString(); } public List<ResolvedType> exceptionTypes() { diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java index ba00112f7..20b8b4375 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/CompilationUnitContext.java @@ -44,6 +44,7 @@ import com.github.javaparser.symbolsolver.resolution.SymbolSolver; import java.util.LinkedList; import java.util.List; +import java.util.Optional; import java.util.stream.Collectors; /** @@ -93,9 +94,13 @@ public class CompilationUnitContext extends AbstractJavaParserContext<Compilatio if (importDecl.isAsterisk()) { String qName = importDecl.getNameAsString(); ResolvedTypeDeclaration importedType = typeSolver.solveType(qName); - SymbolReference<? extends ResolvedValueDeclaration> ref = new SymbolSolver(typeSolver).solveSymbolInType(importedType, name); - if (ref.isSolved()) { - return ref; + + // avoid infinite recursion + if (!isAncestorOf(importedType)) { + SymbolReference<? extends ResolvedValueDeclaration> ref = new SymbolSolver(typeSolver).solveSymbolInType(importedType, name); + if (ref.isSolved()) { + return ref; + } } } else { String whole = importDecl.getNameAsString(); @@ -274,10 +279,12 @@ public class CompilationUnitContext extends AbstractJavaParserContext<Compilatio } ResolvedTypeDeclaration ref = typeSolver.solveType(importString); - SymbolReference<ResolvedMethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true); - - if (method.isSolved()) { - return method; + // avoid infinite recursion + if (!isAncestorOf(ref)) { + SymbolReference<ResolvedMethodDeclaration> method = MethodResolutionLogic.solveMethodInType(ref, name, argumentsTypes, true); + if (method.isSolved()) { + return method; + } } } else { String qName = importDecl.getNameAsString(); @@ -338,4 +345,19 @@ public class CompilationUnitContext extends AbstractJavaParserContext<Compilatio return memberName; } + private boolean isAncestorOf(ResolvedTypeDeclaration descendant) { + if (descendant instanceof AssociableToAST) { + Optional<Node> astOpt = ((AssociableToAST<Node>) descendant).toAst(); + if (astOpt.isPresent()) { + return wrappedNode.isAncestorOf(astOpt.get()); + } else { + return false; + } + } else if (descendant instanceof JavaParserEnumDeclaration) { + return wrappedNode.isAncestorOf(((JavaParserEnumDeclaration) descendant).getWrappedNode()); + } else { + throw new UnsupportedOperationException(); + } + } + } diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java index 3a757b60c..c23cd2b01 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/ForStatementContext.java @@ -26,6 +26,7 @@ import com.github.javaparser.ast.body.VariableDeclarator; import com.github.javaparser.ast.expr.AssignExpr; import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.UnaryExpr; import com.github.javaparser.ast.expr.VariableDeclarationExpr; import com.github.javaparser.ast.nodeTypes.NodeWithStatements; import com.github.javaparser.ast.stmt.ForStmt; @@ -57,7 +58,7 @@ public class ForStatementContext extends AbstractJavaParserContext<ForStmt> { return SymbolReference.solved(JavaParserSymbolDeclaration.localVar(variableDeclarator, typeSolver)); } } - } else if (!(expression instanceof AssignExpr || expression instanceof MethodCallExpr)) { + } else if (!(expression instanceof AssignExpr || expression instanceof MethodCallExpr || expression instanceof UnaryExpr)) { throw new UnsupportedOperationException(expression.getClass().getCanonicalName()); } } 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 01ba856d4..d44d3b14e 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 @@ -48,6 +48,8 @@ import javassist.CtField; import javassist.CtMethod; import javassist.NotFoundException; import javassist.bytecode.AccessFlag; +import javassist.bytecode.BadBytecode; +import javassist.bytecode.SignatureAttribute; import javassist.bytecode.SyntheticAttribute; import java.lang.reflect.Modifier; @@ -176,11 +178,10 @@ public class JavassistInterfaceDeclaration extends AbstractTypeDeclaration @Override public List<ResolvedReferenceType> getAncestors(boolean acceptIncompleteList) { List<ResolvedReferenceType> ancestors = new ArrayList<>(); - try { - for (CtClass interfaze : ctClass.getInterfaces()) { + if (ctClass.getGenericSignature() == null) { + for (String superInterface : ctClass.getClassFile().getInterfaces()) { try { - ResolvedReferenceType superInterfaze = JavassistFactory.typeUsageFor(interfaze, typeSolver).asReferenceType(); - ancestors.add(superInterfaze); + ancestors.add(new ReferenceTypeImpl(typeSolver.solveType(JavassistUtils.internalNameToCanonicalName(superInterface)), typeSolver)); } catch (UnsolvedSymbolException e) { if (!acceptIncompleteList) { // we only throw an exception if we require a complete list; otherwise, we attempt to continue gracefully @@ -188,8 +189,22 @@ public class JavassistInterfaceDeclaration extends AbstractTypeDeclaration } } } - } catch (NotFoundException e) { - throw new RuntimeException(e); + } else { + try { + SignatureAttribute.ClassSignature classSignature = SignatureAttribute.toClassSignature(ctClass.getGenericSignature()); + for (SignatureAttribute.ClassType superInterface : classSignature.getInterfaces()) { + try { + ancestors.add(JavassistUtils.signatureTypeToType(superInterface, typeSolver, this).asReferenceType()); + } catch (UnsolvedSymbolException e) { + if (!acceptIncompleteList) { + // we only throw an exception if we require a complete list; otherwise, we attempt to continue gracefully + throw e; + } + } + } + } catch (BadBytecode e) { + throw new RuntimeException(e); + } } // Remove all {@code java.lang.Object}, then add precisely one. diff --git a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java index e2e3e9d8d..255db3c44 100644 --- a/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java +++ b/javaparser-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/logic/AbstractTypeDeclaration.java @@ -24,9 +24,13 @@ package com.github.javaparser.symbolsolver.logic; import com.github.javaparser.resolution.MethodUsage; import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.utils.Pair; import java.util.HashSet; +import java.util.List; import java.util.Set; /** @@ -43,13 +47,20 @@ public abstract class AbstractTypeDeclaration implements ResolvedReferenceTypeDe Set<String> methodsSignatures = new HashSet<>(); for (ResolvedMethodDeclaration methodDeclaration : getDeclaredMethods()) { - methods.add(new MethodUsage(methodDeclaration)); - methodsSignatures.add(methodDeclaration.getSignature()); + MethodUsage methodUsage = new MethodUsage(methodDeclaration); + methods.add(methodUsage); + methodsSignatures.add(methodUsage.getSignature()); } for (ResolvedReferenceType ancestor : getAllAncestors()) { + List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> typeParametersMap = ancestor.getTypeParametersMap(); for (MethodUsage mu : ancestor.getDeclaredMethods()) { - String signature = mu.getDeclaration().getSignature(); + // replace type parameters to be able to filter away overridden generified methods + MethodUsage methodUsage = mu; + for (Pair<ResolvedTypeParameterDeclaration, ResolvedType> p : typeParametersMap) { + methodUsage = methodUsage.replaceTypeParameter(p.a, p.b); + } + String signature = methodUsage.getSignature(); if (!methodsSignatures.contains(signature)) { methodsSignatures.add(signature); methods.add(mu); diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue2595Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue2595Test.java new file mode 100644 index 000000000..c83de02d6 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue2595Test.java @@ -0,0 +1,158 @@ +package com.github.javaparser.symbolsolver; + +import com.github.javaparser.JavaParser; +import com.github.javaparser.ParseResult; +import com.github.javaparser.ParseStart; +import com.github.javaparser.ParserConfiguration; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; +import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; +import org.junit.jupiter.api.Test; + +import java.util.List; + +import static com.github.javaparser.Providers.provider; +import static org.junit.jupiter.api.Assumptions.assumeFalse; +import static org.junit.jupiter.api.Assumptions.assumeTrue; + +public class Issue2595Test { + + + @Test + public void issue2595ImplicitTypeLambdaTest() { + String sourceCode = "" + + "import java.util.ArrayList;\n" + + "import java.util.List;\n" + + "import java.util.function.Function;\n" + + "\n" + + "public class Test {\n" + + "\n" + + " ClassMetric<Integer> fdp = c -> {\n" + + " List<String> classFieldNames = getAllClassFieldNames(c);\n" + + " return classFieldNames.size();\n" + + " };\n" + + "\n" + + "\n" + + " private List<String> getAllClassFieldNames(final String c) {\n" + + " return new ArrayList<>();\n" + + " }\n" + + "\n" + + "\n" + + " @FunctionalInterface\n" + + " public interface ClassMetric<T> extends Function<String, T> {\n" + + " @Override\n" + + " T apply(String c);\n" + + " }\n" + + "\n" + + "}\n"; + + parse(sourceCode); + } + + @Test + public void issue2595ExplicitTypeLambdaTest() { + String sourceCode = "import java.util.ArrayList;\n" + + "import java.util.List;\n" + + "import java.util.function.Function;\n" + + "\n" + + "public class TestIssue2595 {\n" + + " ClassMetric fdp = (String c) -> {\n" + + " List<String> classFieldNames = getAllClassFieldNames(c);\n" + + " return classFieldNames.size();\n" + + " };\n" + + " \n" + + "\n" + + " private List<String> getAllClassFieldNames(final String c) {\n" + + " return new ArrayList<>();\n" + + " }\n" + + "\n" + + " @FunctionalInterface\n" + + " public interface ClassMetric extends Function<String, Integer> {\n" + + " @Override\n" + + " Integer apply(String c);\n" + + " }\n" + + "}"; + + parse(sourceCode); + } + + @Test + public void issue2595NoParameterLambdaTest() { + String sourceCode = "import java.util.ArrayList;\n" + + "import java.util.List;\n" + + "\n" + + "public class TestIssue2595 {\n" + + " ClassMetric fdp = () -> {\n" + + " List<String> classFieldNames = getAllClassFieldNames();\n" + + " return classFieldNames.size();\n" + + " };\n" + + "\n" + + "\n" + + " private List<String> getAllClassFieldNames() {\n" + + " return new ArrayList<>();\n" + + " }\n" + + "\n" + + " @FunctionalInterface\n" + + " public interface ClassMetric {\n" + + " Integer apply();\n" + + " }\n" + + "}"; + + parse(sourceCode); + } + + @Test + public void issue2595AnonymousInnerClassTest() { + String sourceCode = "import java.util.ArrayList;\n" + + "import java.util.List;\n" + + "import java.util.function.Function;\n" + + "\n" + + "public class TestIssue2595 {\n" + + " ClassMetric fdp = new ClassMetric() {\n" + + " @Override\n" + + " public Integer apply(String c) {\n" + + " List<String> classFieldNames = getAllClassFieldNames(c);\n" + + " return classFieldNames.size();\n" + + " }\n" + + " };\n" + + "\n" + + " private List<String> getAllClassFieldNames(final String c) {\n" + + " return new ArrayList<>();\n" + + " }\n" + + "\n" + + " @FunctionalInterface\n" + + " public interface ClassMetric extends Function<String, Integer> {\n" + + " @Override\n" + + " Integer apply(String c);\n" + + " }\n" + + "}"; + + parse(sourceCode); + } + + private void parse(String sourceCode) { + TypeSolver typeSolver = new CombinedTypeSolver(new ReflectionTypeSolver()); + ParserConfiguration configuration = new ParserConfiguration().setSymbolResolver(new JavaSymbolSolver(typeSolver)); + JavaParser javaParser = new JavaParser(configuration); + + ParseResult<CompilationUnit> result = javaParser.parse(ParseStart.COMPILATION_UNIT, provider(sourceCode)); + assumeTrue(result.isSuccessful()); + assumeTrue(result.getResult().isPresent()); + + CompilationUnit cu = result.getResult().get(); +// System.out.println(cu); + + List<MethodCallExpr> methodCalls = cu.findAll(MethodCallExpr.class); + assumeFalse(methodCalls.isEmpty()); + for (int i = methodCalls.size() - 1; i >= 0; i--) { + MethodCallExpr methodCallExpr = methodCalls.get(i); + System.out.println(); + System.out.println("methodCallExpr = " + methodCallExpr); + System.out.println("methodCallExpr.resolve() = " + methodCallExpr.resolve()); + System.out.println("methodCallExpr.calculateResolvedType() = " + methodCallExpr.calculateResolvedType()); + } + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue2764Test.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue2764Test.java new file mode 100755 index 000000000..c2c4c44d1 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue2764Test.java @@ -0,0 +1,59 @@ +package com.github.javaparser.symbolsolver;
+
+import com.github.javaparser.JavaParser;
+import com.github.javaparser.ParseResult;
+import com.github.javaparser.ParseStart;
+import com.github.javaparser.ParserConfiguration;
+import com.github.javaparser.Providers;
+import com.github.javaparser.ast.CompilationUnit;
+import com.github.javaparser.ast.expr.NameExpr;
+import com.github.javaparser.ast.expr.UnaryExpr;
+import com.github.javaparser.ast.stmt.Statement;
+import com.github.javaparser.printer.PrettyPrinter;
+import com.github.javaparser.printer.PrettyPrinterConfiguration;
+import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration;
+import com.github.javaparser.symbolsolver.model.resolution.TypeSolver;
+import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver;
+
+import org.junit.jupiter.api.Test;
+
+import static com.github.javaparser.StaticJavaParser.parseStatement;
+import static com.github.javaparser.utils.Utils.EOL;
+import static com.github.javaparser.utils.Utils.normalizeEolInTextBlock;
+import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import org.junit.jupiter.api.BeforeEach;
+
+public class Issue2764Test {
+ private JavaParser javaParser;
+
+ @BeforeEach
+ void setUp() {
+ TypeSolver typeSolver = new ReflectionTypeSolver();
+ ParserConfiguration config = new ParserConfiguration();
+ config.setSymbolResolver(new JavaSymbolSolver(typeSolver));
+ javaParser = new JavaParser(config);
+ }
+
+ @Test
+ void resolveUnaryExpr() {
+ String code =
+ "class A {" +
+ " void a() {" +
+ " int e;" +
+ " for(e++;;){}" +
+ " }" +
+ "}";
+
+ ParseResult<CompilationUnit> parseResult = javaParser.parse(ParseStart.COMPILATION_UNIT, Providers.provider(code));
+ assertTrue(parseResult.isSuccessful());
+ assertTrue(parseResult.getResult().isPresent());
+
+ CompilationUnit cu = parseResult.getResult().get();
+ NameExpr name = (NameExpr) cu.findFirst(UnaryExpr.class).get().getExpression();
+ ResolvedValueDeclaration resolve = name.resolve();
+
+ assertTrue("int".contentEquals(resolve.getType().describe()));
+ }
+}
diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclarationTest.java index 72e92189a..1ed0f8ffa 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclarationTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javaparsermodel/declarations/JavaParserAnonymousClassDeclarationTest.java @@ -50,8 +50,10 @@ class JavaParserAnonymousClassDeclarationTest extends AbstractResolutionTest { MethodUsage methodUsage = JavaParserFacade.get(combinedTypeSolver).solveMethodAsUsage(methodCall); + assertThat(methodUsage.getDeclaration().getQualifiedSignature(), + is("AnonymousClassDeclarations.ParDo.of(AnonymousClassDeclarations.DoFn<I, O>)")); assertThat(methodUsage.getQualifiedSignature(), - is("AnonymousClassDeclarations.ParDo.of(AnonymousClassDeclarations.DoFn<I, O>)")); + is("AnonymousClassDeclarations.ParDo.of(AnonymousClassDeclarations.DoFn<java.lang.Integer, java.lang.Long>)")); } @Test diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java index c4d0dd6bc..8a96738de 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/javassistmodel/JavassistInterfaceDeclarationTest.java @@ -21,16 +21,21 @@ package com.github.javaparser.symbolsolver.javassistmodel; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; +import com.github.javaparser.resolution.types.ResolvedReferenceType; +import com.github.javaparser.resolution.types.ResolvedType; import com.github.javaparser.symbolsolver.AbstractSymbolResolutionTest; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; 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.Pair; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.io.IOException; import java.nio.file.Path; +import java.util.List; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -146,4 +151,23 @@ class JavassistInterfaceDeclarationTest extends AbstractSymbolResolutionTest { /// /// Test ancestors /// + + @Test + void testGetAncestorsWithGenericAncestors() { + JavassistInterfaceDeclaration compilationUnit = (JavassistInterfaceDeclaration) anotherTypeSolver.solveType("com.github.javaparser.test.GenericChildInterface"); + List<ResolvedReferenceType> ancestors = compilationUnit.getAncestors(); + assertEquals(2, ancestors.size()); + assertEquals("com.github.javaparser.test.GenericInterface<S>", ancestors.get(0).describe()); // Type should be 'S', from the GenericChildInterface + assertEquals("java.lang.Object", ancestors.get(1).describe()); + + // check the ancestor generic type is mapped to the type of the child + List<Pair<ResolvedTypeParameterDeclaration, ResolvedType>> typePamatersMap = ancestors.get(0).getTypeParametersMap(); + assertEquals(1, typePamatersMap.size()); + + ResolvedTypeParameterDeclaration genericTypeParameterDeclaration = typePamatersMap.get(0).a; + assertEquals("com.github.javaparser.test.GenericInterface.T", genericTypeParameterDeclaration.getQualifiedName()); + ResolvedType genericResolvedType = typePamatersMap.get(0).b; + assertEquals("com.github.javaparser.test.GenericChildInterface.S", genericResolvedType.asTypeParameter().getQualifiedName()); + } + } diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/FunctionInterfaceLogicTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/FunctionInterfaceLogicTest.java index 6df5a11b1..3ca4e22b9 100644 --- a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/FunctionInterfaceLogicTest.java +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/logic/FunctionInterfaceLogicTest.java @@ -53,4 +53,22 @@ class FunctionInterfaceLogicTest { assertEquals(true, FunctionalInterfaceLogic.getFunctionalMethod(consumer).isPresent()); assertEquals("accept", FunctionalInterfaceLogic.getFunctionalMethod(consumer).get().getName()); } + + @Test + void testGetFunctionalMethodWith2AbstractMethodsInHierarcy() { + TypeSolver typeSolver = new ReflectionTypeSolver(); + ResolvedType function = new ReferenceTypeImpl(new ReflectionInterfaceDeclaration(Foo.class, typeSolver), typeSolver); + assertEquals(true, FunctionalInterfaceLogic.getFunctionalMethod(function).isPresent()); + assertEquals("foo", FunctionalInterfaceLogic.getFunctionalMethod(function).get().getName()); + } + + public static interface Foo<S, T> extends Function<S, T> { + + T foo(S str); + + @Override + default T apply(S str) { + return foo(str); + } + } } diff --git a/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/CompilationUnitContextResolutionTest.java b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/CompilationUnitContextResolutionTest.java new file mode 100644 index 000000000..763976ab8 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/resolution/CompilationUnitContextResolutionTest.java @@ -0,0 +1,123 @@ +/* + * Copyright (C) 2015-2016 Federico Tomassetti + * Copyright (C) 2017-2020 The JavaParser Team. + * + * This file is part of JavaParser. + * + * JavaParser can be used either under the terms of + * a) the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * b) the terms of the Apache License + * + * You should have received a copy of both licenses in LICENCE.LGPL and + * LICENCE.APACHE. Please refer to those files for details. + * + * JavaParser is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + */ + +package com.github.javaparser.symbolsolver.resolution; + +import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.NameExpr; +import com.github.javaparser.ast.CompilationUnit; +import com.github.javaparser.StaticJavaParser; +import com.github.javaparser.symbolsolver.JavaSymbolSolver; +import com.github.javaparser.symbolsolver.javaparser.Navigator; +import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; +import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; +import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; +import java.io.IOException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * Tests resolution of MethodCallExpr with super classes + * + * @author Takeshi D. Itoh + */ +class CompilationUnitContextResolutionTest extends AbstractResolutionTest { + + @AfterEach + void unConfigureSymbolSolver() { + // unconfigure symbol solver so as not to potentially disturb tests in other classes + StaticJavaParser.getConfiguration().setSymbolResolver(null); + } + + // in each case, the name itself doesn't matter -- we just want to assert that StackOverflowError wouldn't occur. + + @Test + void solveMethodInReceiver() throws IOException { + StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new CombinedTypeSolver( + new ReflectionTypeSolver(), + new JavaParserTypeSolver(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/00_receiver"))))); + + CompilationUnit cu = StaticJavaParser.parse(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Main.java")); + MethodCallExpr mce = Navigator.findMethodCall(cu, "method").get(); + String actual = mce.resolve().getQualifiedName(); + assertEquals("main.Child.method", actual); + } + + @Test + void solveMethodInParent() throws IOException { + StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new CombinedTypeSolver( + new ReflectionTypeSolver(), + new JavaParserTypeSolver(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/01_parent"))))); + + CompilationUnit cu = StaticJavaParser.parse(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Main.java")); + MethodCallExpr mce = Navigator.findMethodCall(cu, "method").get(); + String actual = mce.resolve().getQualifiedName(); + assertEquals("main.Parent.method", actual); + } + + @Test + void solveMethodInNested() throws IOException { + StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new CombinedTypeSolver( + new ReflectionTypeSolver(), + new JavaParserTypeSolver(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/02_nested"))))); + + CompilationUnit cu = StaticJavaParser.parse(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Main.java")); + MethodCallExpr mce = Navigator.findMethodCall(cu, "method").get(); + String actual = mce.resolve().getQualifiedName(); + assertEquals("main.Child.method", actual); + } + + @Test + void solveSymbol() throws IOException { + StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new CombinedTypeSolver( + new ReflectionTypeSolver(), + new JavaParserTypeSolver(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/03_symbol"))))); + + CompilationUnit cu = StaticJavaParser.parse(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/03_symbol/main/Main.java")); + NameExpr ne = Navigator.findNameExpression(cu, "A").get(); + String actual = ne.resolve().getType().describe(); + assertEquals("main.Clazz.MyEnum", actual); + } + + @Test + void solveMyself() throws IOException { + StaticJavaParser.getConfiguration().setSymbolResolver(new JavaSymbolSolver(new CombinedTypeSolver( + new ReflectionTypeSolver(), + new JavaParserTypeSolver(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/04_reviewComment"))))); + + CompilationUnit cu = StaticJavaParser.parse(adaptPath("src/test/resources/CompilationUnitContextResolutionTest/04_reviewComment/main/Main.java")); + + MethodCallExpr mce = Navigator.findMethodCall(cu, "foo").get(); + String actual = mce.resolve().getQualifiedName(); + assertEquals("main.Main.NestedEnum.foo", actual); + + mce = Navigator.findMethodCall(cu, "bar").get(); + actual = mce.resolve().getQualifiedName(); + assertEquals("main.Main.NestedEnum.bar", actual); + + mce = Navigator.findMethodCall(cu, "baz").get(); + actual = mce.resolve().getQualifiedName(); + assertEquals("main.Main.NestedEnum.baz", actual); + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Child.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Child.java new file mode 100644 index 000000000..a14ded4e0 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Child.java @@ -0,0 +1,8 @@ +package main; + +public class Child extends Parent { + + void method() { + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Main.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Main.java new file mode 100644 index 000000000..e59574823 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Main.java @@ -0,0 +1,10 @@ +package main; + +public class Main { + + static void main() { + Child c; + c.method(); + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Parent.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Parent.java new file mode 100644 index 000000000..3857b76e0 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/00_receiver/main/Parent.java @@ -0,0 +1,12 @@ +package main; + +import static main.Parent.MyEnum.*; + +public class Parent { + + public enum MyEnum { + A("a"), + B("b"), + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Child.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Child.java new file mode 100644 index 000000000..5134b8b25 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Child.java @@ -0,0 +1,5 @@ +package main; + +public class Child extends Parent { + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/GrandParent.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/GrandParent.java new file mode 100644 index 000000000..d037b0add --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/GrandParent.java @@ -0,0 +1,12 @@ +package main; + +import static main.GrandParent.MyEnum.*; + +public class GrandParent { + + public enum MyEnum { + A("a"), + B("b"), + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Main.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Main.java new file mode 100644 index 000000000..e59574823 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Main.java @@ -0,0 +1,10 @@ +package main; + +public class Main { + + static void main() { + Child c; + c.method(); + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Parent.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Parent.java new file mode 100644 index 000000000..a0ed0ebb4 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/01_parent/main/Parent.java @@ -0,0 +1,8 @@ +package main; + +public class Parent { + + void method() { + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Child.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Child.java new file mode 100644 index 000000000..0b51ffb1c --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Child.java @@ -0,0 +1,8 @@ +package main; + +public class Child extends ParentNested { + + public void method() { + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Main.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Main.java new file mode 100644 index 000000000..cc5d06ae8 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Main.java @@ -0,0 +1,10 @@ +package main; + +public class Main { + + public static void main() { + Child c; + c.method(); + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Parent.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Parent.java new file mode 100644 index 000000000..e921d55f1 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/02_nested/main/Parent.java @@ -0,0 +1,15 @@ +package main; + +import static main.Parent.MyEnum.*; + +public class Parent { + + public class ParentNested { + } + + public enum MyEnum { + A("a"), + B("b"), + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/03_symbol/main/Clazz.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/03_symbol/main/Clazz.java new file mode 100644 index 000000000..5961136cf --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/03_symbol/main/Clazz.java @@ -0,0 +1,12 @@ +package main; + +import static main.Clazz.MyEnum.*; + +public class Clazz { + + public enum MyEnum { + A("a"), + B("b"), + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/03_symbol/main/Main.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/03_symbol/main/Main.java new file mode 100644 index 000000000..7d75b09e3 --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/03_symbol/main/Main.java @@ -0,0 +1,11 @@ +package main; + +import static main.Clazz.MyEnum.*; + +public class Main { + + public static void main() { + Object sym = A; + } + +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/04_reviewComment/main/Main.java b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/04_reviewComment/main/Main.java new file mode 100644 index 000000000..70afc0ede --- /dev/null +++ b/javaparser-symbol-solver-testing/src/test/resources/CompilationUnitContextResolutionTest/04_reviewComment/main/Main.java @@ -0,0 +1,20 @@ +package main; + +import static main.Main.NestedEnum.*; + +public class Main { + + public Main() { + foo(); + NestedEnum.bar(); + NestedEnum c; + c.baz(); + } + + public enum NestedEnum { + ; + public static void foo() {} + public static void bar() {} + public void baz() {} + } +} diff --git a/javaparser-symbol-solver-testing/src/test/resources/test-artifact-1.0.0.jar b/javaparser-symbol-solver-testing/src/test/resources/test-artifact-1.0.0.jar Binary files differindex 57b818de5..b4d1a6382 100644 --- a/javaparser-symbol-solver-testing/src/test/resources/test-artifact-1.0.0.jar +++ b/javaparser-symbol-solver-testing/src/test/resources/test-artifact-1.0.0.jar |