From 1db4cd7914d4f36224a4a8944e546650d5fc5a4d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20C=C3=A9sar=20de=20Oliveira?= Date: Sun, 10 Dec 2017 12:32:41 -0200 Subject: [PATCH] Fix issue #300 --- .../javaparsermodel/JavaParserFacade.java | 5 ++ .../contexts/AbstractJavaParserContext.java | 55 ++++++++++++++++ .../contexts/FieldAccessContext.java | 14 +++++ .../contexts/MethodCallExprContext.java | 50 +++------------ .../javaparser/symbolsolver/Issue300.java | 63 +++++++++++++++++++ .../src/test/resources/issue300/Issue300.java | 12 ++++ 6 files changed, 156 insertions(+), 43 deletions(-) create mode 100644 java-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300.java create mode 100644 java-symbol-solver-testing/src/test/resources/issue300/Issue300.java diff --git a/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java b/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java index 26d5d1e4c5..39e0d29eab 100644 --- a/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java +++ b/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/JavaParserFacade.java @@ -28,6 +28,7 @@ import com.github.javaparser.resolution.declarations.*; import com.github.javaparser.resolution.types.*; import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.contexts.FieldAccessContext; import com.github.javaparser.symbolsolver.javaparsermodel.declarations.*; import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; @@ -270,6 +271,10 @@ public SymbolReference solve(AnnotationExpr annot } } + public SymbolReference solve(FieldAccessExpr fieldAccessExpr) { + return ((FieldAccessContext) JavaParserFactory.getContext(fieldAccessExpr, typeSolver)).solveField(fieldAccessExpr.getName().getId(), typeSolver); + } + public ResolvedType getType(Node node) { return getType(node, true); } diff --git a/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java b/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java index 3ee59a9a08..e2f348ce1f 100644 --- a/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java +++ b/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/AbstractJavaParserContext.java @@ -20,15 +20,25 @@ import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.FieldAccessExpr; import com.github.javaparser.ast.expr.MethodCallExpr; +import com.github.javaparser.ast.expr.NameExpr; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedTypeParameterDeclaration; import com.github.javaparser.resolution.types.ResolvedType; import com.github.javaparser.symbolsolver.core.resolution.Context; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFactory; import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; import com.github.javaparser.symbolsolver.model.resolution.Value; +import com.github.javaparser.symbolsolver.reflectionmodel.ReflectionClassDeclaration; import com.github.javaparser.symbolsolver.resolution.SymbolDeclarator; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; import java.util.Optional; import static com.github.javaparser.symbolsolver.javaparser.Navigator.getParentNode; @@ -138,4 +148,49 @@ protected Optional solveWithAsValue(SymbolDeclarator symbolDeclarator, St .findFirst(); } + protected Collection findTypeDeclarations(Optional optScope, TypeSolver typeSolver) { + if (optScope.isPresent()) { + Expression scope = optScope.get(); + + // consider static methods + if (scope instanceof NameExpr) { + NameExpr scopeAsName = (NameExpr) scope; + SymbolReference symbolReference = this.solveType(scopeAsName.getName().getId(), typeSolver); + if (symbolReference.isSolved() && symbolReference.getCorrespondingDeclaration().isType()) { + return Arrays.asList(symbolReference.getCorrespondingDeclaration().asReferenceType()); + } + } + + ResolvedType typeOfScope = null; + try { + typeOfScope = JavaParserFacade.get(typeSolver).getType(scope); + } catch (Exception e) { + throw new RuntimeException(String.format("Issue calculating the type of the scope of " + this), e); + } + if (typeOfScope.isWildcard()) { + if (typeOfScope.asWildcard().isExtends() || typeOfScope.asWildcard().isSuper()) { + return Arrays.asList(typeOfScope.asWildcard().getBoundedType().asReferenceType().getTypeDeclaration()); + } else { + return Arrays.asList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); + } + } else if (typeOfScope.isArray()) { + // method call on array are Object methods + return Arrays.asList(new ReflectionClassDeclaration(Object.class, typeSolver).asReferenceType()); + } else if (typeOfScope.isTypeVariable()) { + Collection result = new ArrayList<>(); + for (ResolvedTypeParameterDeclaration.Bound bound : typeOfScope.asTypeParameter().getBounds()) { + result.add(bound.getType().asReferenceType().getTypeDeclaration()); + } + return result; + } else if (typeOfScope.isConstraint()){ + return Arrays.asList(typeOfScope.asConstraintType().getBound().asReferenceType().getTypeDeclaration()); + } else { + return Arrays.asList(typeOfScope.asReferenceType().getTypeDeclaration()); + } + } else { + ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode); + return Arrays.asList(typeOfScope.asReferenceType().getTypeDeclaration()); + } + } + } diff --git a/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java b/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java index dfae053021..860fe6bc4e 100644 --- a/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java +++ b/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/FieldAccessContext.java @@ -20,8 +20,10 @@ import com.github.javaparser.ast.expr.FieldAccessExpr; import com.github.javaparser.ast.expr.ThisExpr; import com.github.javaparser.resolution.declarations.ResolvedMethodDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedReferenceTypeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedTypeDeclaration; import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration; import com.github.javaparser.resolution.types.ResolvedPrimitiveType; import com.github.javaparser.resolution.types.ResolvedType; import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; @@ -31,6 +33,7 @@ import com.github.javaparser.symbolsolver.model.resolution.Value; import com.github.javaparser.symbolsolver.resolution.SymbolSolver; +import java.util.Collection; import java.util.List; import java.util.Optional; @@ -91,4 +94,15 @@ public Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { return getParent().solveSymbolAsValue(name, typeSolver); } } + + public SymbolReference solveField(String name, TypeSolver typeSolver) { + Collection rrtds = findTypeDeclarations(Optional.of(wrappedNode.getScope()), typeSolver); + for (ResolvedReferenceTypeDeclaration rrtd : rrtds) { + try { + return SymbolReference.solved(rrtd.getField(wrappedNode.getName().getId())); + } catch (Throwable t) { + } + } + return SymbolReference.unsolved(ResolvedFieldDeclaration.class); + } } diff --git a/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java b/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java index 0e0a4717f3..ca9f07c42a 100644 --- a/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java +++ b/java-symbol-solver-core/src/main/java/com/github/javaparser/symbolsolver/javaparsermodel/contexts/MethodCallExprContext.java @@ -34,6 +34,7 @@ import com.github.javaparser.utils.Pair; import java.util.ArrayList; +import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; @@ -148,51 +149,14 @@ public Optional solveSymbolAsValue(String name, TypeSolver typeSolver) { @Override public SymbolReference solveMethod(String name, List argumentsTypes, boolean staticOnly, TypeSolver typeSolver) { - if (wrappedNode.getScope().isPresent()) { - Expression scope = wrappedNode.getScope().get(); - - // consider static methods - if (scope instanceof NameExpr) { - NameExpr scopeAsName = (NameExpr) scope; - SymbolReference symbolReference = this.solveType(scopeAsName.getName().getId(), typeSolver); - if (symbolReference.isSolved() && symbolReference.getCorrespondingDeclaration().isType()) { - ResolvedTypeDeclaration typeDeclaration = symbolReference.getCorrespondingDeclaration().asType(); - return MethodResolutionLogic.solveMethodInType(typeDeclaration, name, argumentsTypes, false, typeSolver); - } - } - - ResolvedType typeOfScope = null; - try { - typeOfScope = JavaParserFacade.get(typeSolver).getType(scope); - } catch (Exception e) { - throw new RuntimeException(String.format("Issue calculating the type of the scope of " + this), e); + Collection rrtds = findTypeDeclarations(wrappedNode.getScope(), typeSolver); + for (ResolvedReferenceTypeDeclaration rrtd : rrtds) { + SymbolReference res = MethodResolutionLogic.solveMethodInType(rrtd, name, argumentsTypes, false, typeSolver); + if (res.isSolved()) { + return res; } - if (typeOfScope.isWildcard()) { - if (typeOfScope.asWildcard().isExtends() || typeOfScope.asWildcard().isSuper()) { - return MethodResolutionLogic.solveMethodInType(typeOfScope.asWildcard().getBoundedType().asReferenceType().getTypeDeclaration(), name, argumentsTypes, false, typeSolver); - } else { - return MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver); - } - } else if (typeOfScope.isArray()) { - // method call on array are Object methods - return MethodResolutionLogic.solveMethodInType(new ReflectionClassDeclaration(Object.class, typeSolver), name, argumentsTypes, false, typeSolver); - } else if (typeOfScope.isTypeVariable()) { - for (ResolvedTypeParameterDeclaration.Bound bound : typeOfScope.asTypeParameter().getBounds()) { - SymbolReference res = MethodResolutionLogic.solveMethodInType(bound.getType().asReferenceType().getTypeDeclaration(), name, argumentsTypes, false, typeSolver); - if (res.isSolved()) { - return res; - } - } - return SymbolReference.unsolved(ResolvedMethodDeclaration.class); - } else if (typeOfScope.isConstraint()){ - return MethodResolutionLogic.solveMethodInType(typeOfScope.asConstraintType().getBound().asReferenceType().getTypeDeclaration(), name, argumentsTypes, typeSolver); - } else { - return MethodResolutionLogic.solveMethodInType(typeOfScope.asReferenceType().getTypeDeclaration(), name, argumentsTypes, false, typeSolver); - } - } else { - ResolvedType typeOfScope = JavaParserFacade.get(typeSolver).getTypeOfThisIn(wrappedNode); - return MethodResolutionLogic.solveMethodInType(typeOfScope.asReferenceType().getTypeDeclaration(), name, argumentsTypes, false, typeSolver); } + return SymbolReference.unsolved(ResolvedMethodDeclaration.class); } /// diff --git a/java-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300.java b/java-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300.java new file mode 100644 index 0000000000..da19b8d5af --- /dev/null +++ b/java-symbol-solver-testing/src/test/java/com/github/javaparser/symbolsolver/Issue300.java @@ -0,0 +1,63 @@ +/* + * Copyright 2016 Federico Tomassetti + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.github.javaparser.symbolsolver; + +import com.github.javaparser.JavaParser; +import com.github.javaparser.ParseException; +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.Expression; +import com.github.javaparser.ast.expr.FieldAccessExpr; +import com.github.javaparser.ast.stmt.ExpressionStmt; +import com.github.javaparser.resolution.declarations.ResolvedValueDeclaration; +import com.github.javaparser.resolution.types.ResolvedType; +import com.github.javaparser.resolution.types.ResolvedPrimitiveType; +import com.github.javaparser.symbolsolver.javaparser.Navigator; +import com.github.javaparser.symbolsolver.javaparsermodel.JavaParserFacade; +import com.github.javaparser.symbolsolver.model.resolution.SymbolReference; +import com.github.javaparser.symbolsolver.model.resolution.TypeSolver; +import com.github.javaparser.symbolsolver.resolution.typesolvers.CombinedTypeSolver; +import com.github.javaparser.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; +import com.github.javaparser.symbolsolver.resolution.AbstractResolutionTest; +import com.github.javaparser.symbolsolver.resolution.typesolvers.ReflectionTypeSolver; +import org.junit.Test; +import java.io.File; +import java.io.FileNotFoundException; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +public class Issue300 extends AbstractResolutionTest { + + @Test + public void fieldAccessIssue() throws ParseException, FileNotFoundException { + String pathToSourceFile = adaptPath("src/test/resources/issue300/Issue300.java"); + CompilationUnit cu = JavaParser.parse(new File(pathToSourceFile)); + + final FieldAccessExpr fieldAccess = Navigator.findNodeOfGivenClass(cu, FieldAccessExpr.class); + assertNotNull(fieldAccess); + + TypeSolver typeSolver = new CombinedTypeSolver( + new ReflectionTypeSolver(), + new JavaParserTypeSolver(adaptPath(new File("src/test/resources/issue300")))); + final JavaParserFacade javaParserFacade = JavaParserFacade.get(typeSolver); + final SymbolReference ref = javaParserFacade.solve(fieldAccess); + assertEquals(ResolvedPrimitiveType.INT, ref.getCorrespondingDeclaration().getType().asPrimitive()); + } +} + diff --git a/java-symbol-solver-testing/src/test/resources/issue300/Issue300.java b/java-symbol-solver-testing/src/test/resources/issue300/Issue300.java new file mode 100644 index 0000000000..ae39712c8c --- /dev/null +++ b/java-symbol-solver-testing/src/test/resources/issue300/Issue300.java @@ -0,0 +1,12 @@ +public class Issue300 { + + class A { + int i; + } + + class B { + B() { + new A().i = 0; + } + } +}