Skip to content

Commit

Permalink
Fix issue #300
Browse files Browse the repository at this point in the history
  • Loading branch information
mcesar committed Dec 10, 2017
1 parent c6db610 commit 1db4cd7
Show file tree
Hide file tree
Showing 6 changed files with 156 additions and 43 deletions.
Expand Up @@ -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;
Expand Down Expand Up @@ -270,6 +271,10 @@ public SymbolReference<ResolvedAnnotationDeclaration> solve(AnnotationExpr annot
}
}

public SymbolReference<ResolvedFieldDeclaration> solve(FieldAccessExpr fieldAccessExpr) {
return ((FieldAccessContext) JavaParserFactory.getContext(fieldAccessExpr, typeSolver)).solveField(fieldAccessExpr.getName().getId(), typeSolver);
}

public ResolvedType getType(Node node) {
return getType(node, true);
}
Expand Down
Expand Up @@ -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;
Expand Down Expand Up @@ -138,4 +148,49 @@ protected Optional<Value> solveWithAsValue(SymbolDeclarator symbolDeclarator, St
.findFirst();
}

protected Collection<ResolvedReferenceTypeDeclaration> findTypeDeclarations(Optional<Expression> optScope, TypeSolver typeSolver) {
if (optScope.isPresent()) {
Expression scope = optScope.get();

// consider static methods
if (scope instanceof NameExpr) {
NameExpr scopeAsName = (NameExpr) scope;
SymbolReference<ResolvedTypeDeclaration> 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<ResolvedReferenceTypeDeclaration> 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());
}
}

}
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -91,4 +94,15 @@ public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
return getParent().solveSymbolAsValue(name, typeSolver);
}
}

public SymbolReference<ResolvedFieldDeclaration> solveField(String name, TypeSolver typeSolver) {
Collection<ResolvedReferenceTypeDeclaration> 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);
}
}
Expand Up @@ -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;
Expand Down Expand Up @@ -148,51 +149,14 @@ public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {

@Override
public SymbolReference<ResolvedMethodDeclaration> solveMethod(String name, List<ResolvedType> 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<ResolvedTypeDeclaration> 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<ResolvedReferenceTypeDeclaration> rrtds = findTypeDeclarations(wrappedNode.getScope(), typeSolver);
for (ResolvedReferenceTypeDeclaration rrtd : rrtds) {
SymbolReference<ResolvedMethodDeclaration> 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<ResolvedMethodDeclaration> 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);
}

///
Expand Down
@@ -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<? extends ResolvedValueDeclaration> ref = javaParserFacade.solve(fieldAccess);
assertEquals(ResolvedPrimitiveType.INT, ref.getCorrespondingDeclaration().getType().asPrimitive());
}
}

@@ -0,0 +1,12 @@
public class Issue300 {

class A {
int i;
}

class B {
B() {
new A().i = 0;
}
}
}

0 comments on commit 1db4cd7

Please sign in to comment.