Skip to content

Commit

Permalink
Resolving symbols declared in SuperInterfaces
Browse files Browse the repository at this point in the history
* Refactored TypeDeclaration.getAllAncestors and implemented getAncestors which provides only the direct SuperClasses/Interfaces.
* Implemented resolving symbols declared in SuperInterfaces.
* Added test for this case.
  • Loading branch information
mlangkabel committed Oct 2, 2016
1 parent 8eedafd commit 6151a5f
Show file tree
Hide file tree
Showing 13 changed files with 75 additions and 49 deletions.
Expand Up @@ -3,10 +3,13 @@
import com.github.javaparser.ast.body.BodyDeclaration; import com.github.javaparser.ast.body.BodyDeclaration;
import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import com.github.javaparser.ast.body.FieldDeclaration; import com.github.javaparser.ast.body.FieldDeclaration;
import com.github.javaparser.ast.type.ClassOrInterfaceType;

import me.tomassetti.symbolsolver.resolution.MethodResolutionLogic; import me.tomassetti.symbolsolver.resolution.MethodResolutionLogic;
import me.tomassetti.symbolsolver.model.declarations.MethodDeclaration; import me.tomassetti.symbolsolver.model.declarations.MethodDeclaration;
import me.tomassetti.symbolsolver.model.declarations.TypeDeclaration; import me.tomassetti.symbolsolver.model.declarations.TypeDeclaration;
import me.tomassetti.symbolsolver.model.declarations.ValueDeclaration; import me.tomassetti.symbolsolver.model.declarations.ValueDeclaration;
import me.tomassetti.symbolsolver.model.typesystem.ReferenceTypeUsage;
import me.tomassetti.symbolsolver.model.typesystem.TypeParameterUsage; import me.tomassetti.symbolsolver.model.typesystem.TypeParameterUsage;
import me.tomassetti.symbolsolver.model.typesystem.TypeUsage; import me.tomassetti.symbolsolver.model.typesystem.TypeUsage;
import me.tomassetti.symbolsolver.resolution.SymbolDeclarator; import me.tomassetti.symbolsolver.resolution.SymbolDeclarator;
Expand Down Expand Up @@ -50,13 +53,8 @@ public SymbolReference<? extends ValueDeclaration> solveSymbol(String name, Type
} }


// then among inherited fields // then among inherited fields
if (!wrappedNode.isInterface() && wrappedNode.getExtends() != null && !wrappedNode.getExtends().isEmpty()) { for (ReferenceTypeUsage ancestor : getDeclaration().getAncestors()) {
String superClassName = wrappedNode.getExtends().get(0).getName(); SymbolReference ref = ancestor.getTypeDeclaration().getContext().solveSymbol(name, typeSolver);
SymbolReference<TypeDeclaration> superClass = solveType(superClassName, typeSolver);
if (!superClass.isSolved()) {
throw new UnsolvedTypeException(this, superClassName);
}
SymbolReference ref = superClass.getCorrespondingDeclaration().getContext().solveSymbol(name, typeSolver);
if (ref.isSolved()) { if (ref.isSolved()) {
return ref; return ref;
} }
Expand All @@ -82,13 +80,8 @@ public Optional<Value> solveSymbolAsValue(String name, TypeSolver typeSolver) {
} }


// then among inherited fields // then among inherited fields
if (!wrappedNode.isInterface() && wrappedNode.getExtends() != null && !wrappedNode.getExtends().isEmpty()) { for (ReferenceTypeUsage ancestor : getDeclaration().getAncestors()) {
String superClassName = wrappedNode.getExtends().get(0).getName(); Optional<Value> ref = ancestor.getTypeDeclaration().getContext().solveSymbolAsValue(name, typeSolver);
SymbolReference<TypeDeclaration> superClass = solveType(superClassName, typeSolver);
if (!superClass.isSolved()) {
throw new UnsolvedTypeException(this, superClassName);
}
Optional<Value> ref = superClass.getCorrespondingDeclaration().getContext().solveSymbolAsValue(name, typeSolver);
if (ref.isPresent()) { if (ref.isPresent()) {
return ref; return ref;
} }
Expand Down
Expand Up @@ -341,23 +341,20 @@ public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSo
return new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver); return new JavaParserClassDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver);
} }


//return SymbolReference.unsolved(TypeDeclaration.class);
return getContext().getParent().solveType(name, typeSolver); return getContext().getParent().solveType(name, typeSolver);
} }


@Override @Override
public List<ReferenceTypeUsage> getAllAncestors() { public List<ReferenceTypeUsage> getAncestors() {
List<ReferenceTypeUsage> ancestors = new ArrayList<>(); List<ReferenceTypeUsage> ancestors = new ArrayList<>();
ReferenceTypeUsageImpl superclass = getSuperClass(); ReferenceTypeUsageImpl superclass = getSuperClass();
if (superclass != null) { if (superclass != null) {
ancestors.add(superclass); ancestors.add(superclass);
ancestors.addAll(superclass.getAllAncestors());
} }
if (wrappedNode.getImplements() != null) { if (wrappedNode.getImplements() != null) {
for (ClassOrInterfaceType implemented : wrappedNode.getImplements()) { for (ClassOrInterfaceType implemented : wrappedNode.getImplements()) {
ReferenceTypeUsageImpl ancestor = toTypeUsage(implemented, typeSolver); ReferenceTypeUsageImpl ancestor = toTypeUsage(implemented, typeSolver);
ancestors.add(ancestor); ancestors.add(ancestor);
ancestors.addAll(ancestor.getAllAncestors());
} }
} }
return ancestors; return ancestors;
Expand Down
Expand Up @@ -299,7 +299,7 @@ public SymbolReference<TypeDeclaration> solveType(String substring, TypeSolver t
} }


@Override @Override
public List<ReferenceTypeUsage> getAllAncestors() { public List<ReferenceTypeUsage> getAncestors() {
List<ReferenceTypeUsage> ancestors = new ArrayList<>(); List<ReferenceTypeUsage> ancestors = new ArrayList<>();
if (wrappedNode.getImplements() != null) { if (wrappedNode.getImplements() != null) {
for (ClassOrInterfaceType implementedType : wrappedNode.getImplements()) { for (ClassOrInterfaceType implementedType : wrappedNode.getImplements()) {
Expand All @@ -308,7 +308,6 @@ public List<ReferenceTypeUsage> getAllAncestors() {
throw new UnsolvedSymbolException(implementedType.getName()); throw new UnsolvedSymbolException(implementedType.getName());
} }
ancestors.add(new ReferenceTypeUsageImpl(implementedDeclRef.getCorrespondingDeclaration(), typeSolver)); ancestors.add(new ReferenceTypeUsageImpl(implementedDeclRef.getCorrespondingDeclaration(), typeSolver));
ancestors.addAll(implementedDeclRef.getCorrespondingDeclaration().getAllAncestors());
} }
} }
return ancestors; return ancestors;
Expand Down
Expand Up @@ -302,34 +302,32 @@ public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSo
return new JavaParserInterfaceDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver); return new JavaParserInterfaceDeclaration(this.wrappedNode, typeSolver).solveType(name.substring(prefix.length()), typeSolver);
} }


return SymbolReference.unsolved(TypeDeclaration.class); return getContext().getParent().solveType(name, typeSolver);
} }


@Override @Override
public List<ReferenceTypeUsage> getAllAncestors() { public List<ReferenceTypeUsage> getAncestors() {
List<ReferenceTypeUsage> ancestors = new ArrayList<>(); List<ReferenceTypeUsage> ancestors = new ArrayList<>();
if (wrappedNode.getExtends() != null) { if (wrappedNode.getExtends() != null) {
for (ClassOrInterfaceType extended : wrappedNode.getExtends()) { for (ClassOrInterfaceType extended : wrappedNode.getExtends()) {
SymbolReference<TypeDeclaration> superclass = solveType(extended.getName(), typeSolver); SymbolReference<TypeDeclaration> ancestor = solveType(extended.getName(), typeSolver);
if (!superclass.isSolved()) { if (!ancestor.isSolved()) {
throw new UnsolvedSymbolException(extended.getName()); throw new UnsolvedSymbolException(extended.getName());
} }
ancestors.add(new ReferenceTypeUsageImpl(superclass.getCorrespondingDeclaration(), typeSolver)); ancestors.add(new ReferenceTypeUsageImpl(ancestor.getCorrespondingDeclaration(), typeSolver));
ancestors.addAll(superclass.getCorrespondingDeclaration().getAllAncestors());
} }
} }
if (wrappedNode.getImplements() != null) { if (wrappedNode.getImplements() != null) {
for (ClassOrInterfaceType implemented : wrappedNode.getImplements()) { for (ClassOrInterfaceType implemented : wrappedNode.getImplements()) {
SymbolReference<TypeDeclaration> superclass = solveType(implemented.getName(), typeSolver); SymbolReference<TypeDeclaration> ancestor = solveType(implemented.getName(), typeSolver);
if (!superclass.isSolved()) { if (!ancestor.isSolved()) {
throw new UnsolvedSymbolException(implemented.getName()); throw new UnsolvedSymbolException(implemented.getName());
} }
ancestors.add(new ReferenceTypeUsageImpl(superclass.getCorrespondingDeclaration(), typeSolver)); ancestors.add(new ReferenceTypeUsageImpl(ancestor.getCorrespondingDeclaration(), typeSolver));
ancestors.addAll(superclass.getCorrespondingDeclaration().getAllAncestors());
} }
} }
return ancestors; return ancestors;
} }


@Override @Override
public List<TypeParameter> getTypeParameters() { public List<TypeParameter> getTypeParameters() {
Expand Down
Expand Up @@ -146,7 +146,7 @@ public SymbolReference<TypeDeclaration> solveType(String substring, TypeSolver t
} }


@Override @Override
public List<ReferenceTypeUsage> getAllAncestors() { public List<ReferenceTypeUsage> getAncestors() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }


Expand Down
Expand Up @@ -105,7 +105,7 @@ public SymbolReference<TypeDeclaration> solveType(String substring, TypeSolver t
} }


@Override @Override
public List<ReferenceTypeUsage> getAllAncestors() { public List<ReferenceTypeUsage> getAncestors() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }


Expand Down
Expand Up @@ -210,13 +210,12 @@ public SymbolReference<TypeDeclaration> solveType(String substring, TypeSolver t
} }


@Override @Override
public List<ReferenceTypeUsage> getAllAncestors() { public List<ReferenceTypeUsage> getAncestors() {
List<ReferenceTypeUsage> ancestors = new LinkedList<>(); List<ReferenceTypeUsage> ancestors = new LinkedList<>();
if (getSuperClass() != null) { if (getSuperClass() != null) {
ancestors.add(getSuperClass()); ancestors.add(getSuperClass());
ancestors.addAll(getSuperClass().getAllAncestors());
} }
ancestors.addAll(getAllInterfaces().stream().map(i -> new ReferenceTypeUsageImpl(i, typeSolver)).collect(Collectors.<ReferenceTypeUsageImpl>toList())); ancestors.addAll(getInterfaces().stream().map(i -> new ReferenceTypeUsageImpl(i, typeSolver)).collect(Collectors.<ReferenceTypeUsageImpl>toList()));
return ancestors; return ancestors;
} }


Expand Down
Expand Up @@ -217,13 +217,12 @@ public SymbolReference<TypeDeclaration> solveType(String substring, TypeSolver t
} }


@Override @Override
public List<ReferenceTypeUsage> getAllAncestors() { public List<ReferenceTypeUsage> getAncestors() {
List<ReferenceTypeUsage> ancestors = new ArrayList<>(); List<ReferenceTypeUsage> ancestors = new ArrayList<>();
try { try {
for (CtClass interfaze : ctClass.getInterfaces()) { for (CtClass interfaze : ctClass.getInterfaces()) {
ReferenceTypeUsage superInterfaze = JavassistFactory.typeUsageFor(interfaze, typeSolver()).asReferenceTypeUsage(); ReferenceTypeUsage superInterfaze = JavassistFactory.typeUsageFor(interfaze, typeSolver()).asReferenceTypeUsage();
ancestors.add(superInterfaze); ancestors.add(superInterfaze);
ancestors.addAll(superInterfaze.getAllAncestors());
} }
} catch (NotFoundException e) { } catch (NotFoundException e) {
throw new RuntimeException(e); throw new RuntimeException(e);
Expand Down
Expand Up @@ -63,16 +63,16 @@ protected TypeSolver typeSolver() {
} }


@Override @Override
public List<ReferenceTypeUsage> getAllAncestors() { public List<ReferenceTypeUsage> getAncestors() {
List<ReferenceTypeUsage> ancestors = new LinkedList<>(); List<ReferenceTypeUsage> ancestors = new LinkedList<>();
if (getSuperClass() != null) { if (getSuperClass() != null) {
ReferenceTypeUsageImpl superClass = getSuperClass(); ReferenceTypeUsageImpl superClass = getSuperClass();
ancestors.add(superClass); ancestors.add(superClass);
ancestors.addAll(getSuperClass().getAllAncestors()); } else {
ReferenceTypeUsageImpl object = new ReferenceTypeUsageImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver); ReferenceTypeUsageImpl object = new ReferenceTypeUsageImpl(new ReflectionClassDeclaration(Object.class, typeSolver), typeSolver);
ancestors.add(object); ancestors.add(object);
} }
ancestors.addAll(getAllInterfaces().stream().map((i) -> new ReferenceTypeUsageImpl(i, typeSolver)).collect(Collectors.<ReferenceTypeUsageImpl>toList())); ancestors.addAll(getInterfaces().stream().map((i) -> new ReferenceTypeUsageImpl(i, typeSolver)).collect(Collectors.<ReferenceTypeUsageImpl>toList()));
for (int i = 0; i < ancestors.size(); i++) { for (int i = 0; i < ancestors.size(); i++) {
ReferenceTypeUsage ancestor = ancestors.get(i); ReferenceTypeUsage ancestor = ancestors.get(i);
if (ancestor.hasName() && ancestor.getQualifiedName().equals(Object.class.getCanonicalName())) { if (ancestor.hasName() && ancestor.getQualifiedName().equals(Object.class.getCanonicalName())) {
Expand Down
Expand Up @@ -245,17 +245,15 @@ public SymbolReference<TypeDeclaration> solveType(String substring, TypeSolver t
} }


@Override @Override
public List<ReferenceTypeUsage> getAllAncestors() { public List<ReferenceTypeUsage> getAncestors() {
List<ReferenceTypeUsage> ancestors = new LinkedList<>(); List<ReferenceTypeUsage> ancestors = new LinkedList<>();
if (clazz.getSuperclass() != null) { if (clazz.getSuperclass() != null) {
ReferenceTypeUsageImpl superclass = new ReferenceTypeUsageImpl(new ReflectionInterfaceDeclaration(clazz.getSuperclass(), typeSolver), typeSolver); ReferenceTypeUsageImpl superclass = new ReferenceTypeUsageImpl(new ReflectionInterfaceDeclaration(clazz.getSuperclass(), typeSolver), typeSolver);
ancestors.add(superclass); ancestors.add(superclass);
ancestors.addAll(superclass.getAllAncestors());
} }
for (Class<?> interfaze : clazz.getInterfaces()) { for (Class<?> interfaze : clazz.getInterfaces()) {
ReferenceTypeUsageImpl interfazeDecl = new ReferenceTypeUsageImpl(new ReflectionInterfaceDeclaration(interfaze, typeSolver), typeSolver); ReferenceTypeUsageImpl interfazeDecl = new ReferenceTypeUsageImpl(new ReflectionInterfaceDeclaration(interfaze, typeSolver), typeSolver);
ancestors.add(interfazeDecl); ancestors.add(interfazeDecl);
ancestors.addAll(interfazeDecl.getAllAncestors());
} }
for (int i = 0; i < ancestors.size(); i++) { for (int i = 0; i < ancestors.size(); i++) {
if (ancestors.get(i).getQualifiedName().equals(Object.class.getCanonicalName())) { if (ancestors.get(i).getQualifiedName().equals(Object.class.getCanonicalName())) {
Expand Down
Expand Up @@ -106,7 +106,7 @@ public void solveSymbolReferringToDeclaredStaticField() throws ParseException {
} }


@Test @Test
public void solveSymbolReferringToInehritedInstanceField() throws ParseException { public void solveSymbolReferringToInheritedInstanceField() throws ParseException {
CompilationUnit cu = parseSample("ClassWithSymbols"); CompilationUnit cu = parseSample("ClassWithSymbols");
ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A"); ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver); Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
Expand All @@ -115,6 +115,17 @@ public void solveSymbolReferringToInehritedInstanceField() throws ParseException
assertEquals(true, ref.isSolved()); assertEquals(true, ref.isSolved());
assertEquals("boolean", ref.getCorrespondingDeclaration().getType().describe()); assertEquals("boolean", ref.getCorrespondingDeclaration().getType().describe());
} }

@Test
public void solveSymbolReferringToInterfaceInheritedInstanceField() throws ParseException {
CompilationUnit cu = parseSample("ClassWithSymbols");
ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);

SymbolReference<? extends ValueDeclaration> ref = context.solveSymbol("o", new DummyTypeSolver());
assertEquals(true, ref.isSolved());
assertEquals("int", ref.getCorrespondingDeclaration().getType().describe());
}


@Test @Test
public void solveSymbolReferringToInheritedStaticField() throws ParseException { public void solveSymbolReferringToInheritedStaticField() throws ParseException {
Expand Down Expand Up @@ -160,7 +171,7 @@ public void solveSymbolAsValueReferringToDeclaredStaticField() throws ParseExcep
} }


@Test @Test
public void solveSymbolAsValueReferringToInehritedInstanceField() throws ParseException { public void solveSymbolAsValueReferringToInheritedInstanceField() throws ParseException {
CompilationUnit cu = parseSample("ClassWithSymbols"); CompilationUnit cu = parseSample("ClassWithSymbols");
ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A"); ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver); Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);
Expand All @@ -169,6 +180,17 @@ public void solveSymbolAsValueReferringToInehritedInstanceField() throws ParseEx
assertEquals(true, ref.isPresent()); assertEquals(true, ref.isPresent());
assertEquals("boolean", ref.get().getUsage().describe()); assertEquals("boolean", ref.get().getUsage().describe());
} }

@Test
public void solveSymbolAsValueReferringToInterfaceInheritedInstanceField() throws ParseException {
CompilationUnit cu = parseSample("ClassWithSymbols");
ClassOrInterfaceDeclaration classOrInterfaceDeclaration = Navigator.demandClass(cu, "A");
Context context = new ClassOrInterfaceDeclarationContext(classOrInterfaceDeclaration, typeSolver);

Optional<Value> ref = context.solveSymbolAsValue("o", new DummyTypeSolver());
assertEquals(true, ref.isPresent());
assertEquals("int", ref.get().getUsage().describe());
}


@Test @Test
public void solveSymbolAsValueReferringToInheritedStaticField() throws ParseException { public void solveSymbolAsValueReferringToInheritedStaticField() throws ParseException {
Expand Down
@@ -1,10 +1,17 @@
class Super { class Super {
protected boolean k; protected boolean k;
private static char m; private static char m;
}

interface SuperSuperInterface {
public int o;
}


interface SuperInterface extends SuperSuperInterface {
public int p;
} }


class A extends Super { class A extends Super implements SuperInterface {


private int i; private int i;
private static long j; private static long j;
Expand All @@ -25,4 +32,8 @@ class A extends Super {
return m; return m;
} }


public void foo5(){
return o;
}

} }
Expand Up @@ -7,6 +7,7 @@
import me.tomassetti.symbolsolver.model.typesystem.ReferenceTypeUsage; import me.tomassetti.symbolsolver.model.typesystem.ReferenceTypeUsage;
import me.tomassetti.symbolsolver.model.typesystem.TypeUsage; import me.tomassetti.symbolsolver.model.typesystem.TypeUsage;


import java.util.ArrayList;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
Expand Down Expand Up @@ -66,7 +67,16 @@ default boolean canBeAssignedTo(TypeDeclaration other) {
*/ */
SymbolReference<TypeDeclaration> solveType(String substring, TypeSolver typeSolver); SymbolReference<TypeDeclaration> solveType(String substring, TypeSolver typeSolver);


List<ReferenceTypeUsage> getAllAncestors(); List<ReferenceTypeUsage> getAncestors();

default List<ReferenceTypeUsage> getAllAncestors() {
List<ReferenceTypeUsage> ancestors = new ArrayList<>();
for (ReferenceTypeUsage ancestor : getAncestors()) {
ancestors.add(ancestor);
ancestors.addAll(ancestor.getAllAncestors());
}
return ancestors;
}


Set<MethodDeclaration> getDeclaredMethods(); Set<MethodDeclaration> getDeclaredMethods();


Expand Down

0 comments on commit 6151a5f

Please sign in to comment.