Skip to content

Commit

Permalink
wip
Browse files Browse the repository at this point in the history
  • Loading branch information
ftomassetti committed Jul 31, 2015
1 parent 2f49331 commit 8b8cc6c
Show file tree
Hide file tree
Showing 14 changed files with 155 additions and 37 deletions.
43 changes: 42 additions & 1 deletion src/main/java/me/tomassetti/symbolsolver/JavaParserFacade.java
@@ -1,11 +1,17 @@
package me.tomassetti.symbolsolver; package me.tomassetti.symbolsolver;


import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.expr.Expression; import com.github.javaparser.ast.expr.Expression;
import com.github.javaparser.ast.expr.MethodCallExpr; import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.expr.NameExpr; import com.github.javaparser.ast.expr.NameExpr;
import javassist.compiler.ast.Expr;
import me.tomassetti.symbolsolver.model.*; import me.tomassetti.symbolsolver.model.*;
import me.tomassetti.symbolsolver.model.MethodDeclaration; import me.tomassetti.symbolsolver.model.MethodDeclaration;
import me.tomassetti.symbolsolver.model.javaparser.JavaParserFactory;
import me.tomassetti.symbolsolver.model.javaparser.UnsolvedSymbolException;
import me.tomassetti.symbolsolver.model.javaparser.contexts.MethodCallExprContext;

import java.util.ArrayList;
import java.util.List;


/** /**
* Class to be used by final users to solve symbols for JavaParser ASTs. * Class to be used by final users to solve symbols for JavaParser ASTs.
Expand Down Expand Up @@ -39,4 +45,39 @@ public SymbolReference<MethodDeclaration> solve(MethodCallExpr methodCallExpr) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }


/**
* Should return more like a TypeApplication: a TypeDeclaration and possible parameters or array modifiers.
* @return
*/
public TypeUsage getType(Node node) {
if (node instanceof NameExpr) {
NameExpr nameExpr = (NameExpr) node;
SymbolReference<SymbolDeclaration> ref = new SymbolSolver(typeSolver).solveSymbol(nameExpr.getName(), nameExpr);
if (!ref.isSolved()) {
throw new UnsolvedSymbolException(JavaParserFactory.getContext(nameExpr), nameExpr.getName());
}
return new TypeUsageOfTypeDeclaration(ref.getCorrespondingDeclaration().getType());
} else if (node instanceof MethodCallExpr) {
// first solve the method
SymbolReference<MethodDeclaration> ref = new JavaParserFacade(typeSolver).solveMethod((MethodCallExpr)node);
if (!ref.isSolved()) {
throw new UnsolvedSymbolException(JavaParserFactory.getContext(node), ((MethodCallExpr)node).getName());
}
return new TypeUsageOfTypeDeclaration(ref.getCorrespondingDeclaration().getReturnType());
// the type is the return type of the method
} else {
throw new UnsupportedOperationException(node.getClass().getCanonicalName());
}
}

private SymbolReference<MethodDeclaration> solveMethod(MethodCallExpr methodCallExpr) {
List<TypeUsage> params = new ArrayList<>();
if (methodCallExpr.getArgs() != null) {
for (Expression param : methodCallExpr.getArgs()) {
params.add(getType(param));
}
}
return new MethodCallExprContext(methodCallExpr).solveMethod(methodCallExpr.getName(), params, typeSolver);
}

} }
4 changes: 1 addition & 3 deletions src/main/java/me/tomassetti/symbolsolver/model/Context.java
@@ -1,7 +1,5 @@
package me.tomassetti.symbolsolver.model; package me.tomassetti.symbolsolver.model;


import com.github.javaparser.ast.type.Type;

import java.util.List; import java.util.List;


/** /**
Expand All @@ -10,7 +8,7 @@
public interface Context { public interface Context {
public SymbolReference solveSymbol(String name, TypeSolver typeSolver); public SymbolReference solveSymbol(String name, TypeSolver typeSolver);
public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver); public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSolver);
public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeReference> parameterTypes, TypeSolver typeSolver); public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver);
public Context getParent(); public Context getParent();
public boolean isRoot(); public boolean isRoot();
} }
Expand Up @@ -5,4 +5,6 @@
*/ */
public interface MethodDeclaration extends SymbolDeclaration { public interface MethodDeclaration extends SymbolDeclaration {
TypeDeclaration getType(); TypeDeclaration getType();

TypeDeclaration getReturnType();
} }
@@ -1,9 +1,6 @@
package me.tomassetti.symbolsolver.model; package me.tomassetti.symbolsolver.model;


import com.github.javaparser.ast.Node; import com.github.javaparser.ast.Node;
import com.github.javaparser.ast.body.Parameter;
import com.github.javaparser.ast.body.TypeDeclaration;
import com.github.javaparser.ast.expr.MethodCallExpr;
import com.github.javaparser.ast.type.ClassOrInterfaceType; import com.github.javaparser.ast.type.ClassOrInterfaceType;
import com.github.javaparser.ast.type.ReferenceType; import com.github.javaparser.ast.type.ReferenceType;
import com.github.javaparser.ast.type.Type; import com.github.javaparser.ast.type.Type;
Expand Down Expand Up @@ -41,11 +38,11 @@ public SymbolReference<me.tomassetti.symbolsolver.model.TypeDeclaration> solveTy
return solveType(name, JavaParserFactory.getContext(node)); return solveType(name, JavaParserFactory.getContext(node));
} }


public SymbolReference<MethodDeclaration> solveMethod(String methodName, List<TypeReference> params, Context context) { public SymbolReference<MethodDeclaration> solveMethod(String methodName, List<TypeUsage> params, Context context) {
return context.solveMethod(methodName, params, typeSolver); return context.solveMethod(methodName, params, typeSolver);
} }


public SymbolReference<MethodDeclaration> solveMethod(String methodName, List<TypeReference> params, Node node) { public SymbolReference<MethodDeclaration> solveMethod(String methodName, List<TypeUsage> params, Node node) {
return solveMethod(methodName, params, JavaParserFactory.getContext(node)); return solveMethod(methodName, params, JavaParserFactory.getContext(node));
} }


Expand All @@ -61,7 +58,7 @@ public me.tomassetti.symbolsolver.model.TypeDeclaration solveType(Type type) {
throw new UnsolvedSymbolException(JavaParserFactory.getContext(type), classType.getName()); throw new UnsolvedSymbolException(JavaParserFactory.getContext(type), classType.getName());
} }
if (!(ref.getCorrespondingDeclaration().isType())) { if (!(ref.getCorrespondingDeclaration().isType())) {
throw new IllegalStateException(); throw new IllegalStateException(ref.getCorrespondingDeclaration().toString());
} }
return ref.getCorrespondingDeclaration().asTypeDeclaration(); return ref.getCorrespondingDeclaration().asTypeDeclaration();
} else { } else {
Expand Down
@@ -1,9 +1,13 @@
package me.tomassetti.symbolsolver.model; package me.tomassetti.symbolsolver.model;


import java.util.List;

/** /**
* Created by federico on 31/07/15. * Created by federico on 31/07/15.
*/ */
public interface TypeDeclaration extends SymbolDeclaration { public interface TypeDeclaration extends SymbolDeclaration {
String getQualifiedName(); String getQualifiedName();
Context getContext(); Context getContext();

SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes);
} }
@@ -1,5 +1,7 @@
package me.tomassetti.symbolsolver.model; package me.tomassetti.symbolsolver.model;


import java.util.List;

/** /**
* Reference to a type. A TypeRef could be a primitive type or a reference type (enum, class, interface). * Reference to a type. A TypeRef could be a primitive type or a reference type (enum, class, interface).
* In the later case it could take type parameters (other TypeRefs). It could also be a TypeVariable, like in: * In the later case it could take type parameters (other TypeRefs). It could also be a TypeVariable, like in:
Expand All @@ -8,7 +10,7 @@
* *
* where B is a TypeVariable. It could also be Wildcard Type, possibly with constraints. * where B is a TypeVariable. It could also be Wildcard Type, possibly with constraints.
*/ */
public interface TypeReference { public interface TypeUsage {


boolean isArray(); boolean isArray();
boolean isPrimitive(); boolean isPrimitive();
Expand All @@ -21,12 +23,13 @@ public interface TypeReference {


String getTypeName(); String getTypeName();


TypeReference getBaseType(); TypeUsage getBaseType();


/* Represent the position of the reference, it is used when solving symbols /* Represent the position of the reference, it is used when solving symbols
* because a reference to a class A could be related to different classes depending on the position * because a reference to a class A could be related to different classes depending on the position
* of the reference * of the reference
*/ */
Context getContext(); Context getContext();


SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes);
} }
@@ -0,0 +1,50 @@
package me.tomassetti.symbolsolver.model;

import java.util.List;

/**
* Created by federico on 31/07/15.
*/
public class TypeUsageOfTypeDeclaration implements TypeUsage {

private TypeDeclaration typeDeclaration;

public TypeUsageOfTypeDeclaration(TypeDeclaration typeDeclaration) {
this.typeDeclaration = typeDeclaration;
}

@Override
public boolean isArray() {
return false;
}

@Override
public boolean isPrimitive() {
return false;
}

@Override
public boolean isReferenceType() {
return true;
}

@Override
public String getTypeName() {
return typeDeclaration.getName();
}

@Override
public TypeUsage getBaseType() {
throw new UnsupportedOperationException();
}

@Override
public Context getContext() {
throw new UnsupportedOperationException();
}

@Override
public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes) {
return typeDeclaration.solveMethod(name, parameterTypes);
}
}
Expand Up @@ -61,7 +61,7 @@ public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSo
} }


@Override @Override
public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeReference> parameterTypes, TypeSolver typeSolver) { public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver) {
for (BodyDeclaration member : this.wrappedNode.getMembers()) { for (BodyDeclaration member : this.wrappedNode.getMembers()) {
if (member instanceof com.github.javaparser.ast.body.MethodDeclaration) { if (member instanceof com.github.javaparser.ast.body.MethodDeclaration) {
com.github.javaparser.ast.body.MethodDeclaration method = (com.github.javaparser.ast.body.MethodDeclaration)member; com.github.javaparser.ast.body.MethodDeclaration method = (com.github.javaparser.ast.body.MethodDeclaration)member;
Expand Down
Expand Up @@ -83,7 +83,7 @@ private static boolean isQualifiedName(String name) {
} }


@Override @Override
public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeReference> parameterTypes, TypeSolver typeSolver) { public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
} }
Expand Up @@ -4,7 +4,6 @@
import me.tomassetti.symbolsolver.JavaParserFacade; import me.tomassetti.symbolsolver.JavaParserFacade;
import me.tomassetti.symbolsolver.model.*; import me.tomassetti.symbolsolver.model.*;
import me.tomassetti.symbolsolver.model.javaparser.JavaParserFactory; import me.tomassetti.symbolsolver.model.javaparser.JavaParserFactory;
import me.tomassetti.symbolsolver.model.javaparser.UnsolvedSymbolException;


import java.util.List; import java.util.List;


Expand All @@ -28,17 +27,10 @@ public SymbolReference<TypeDeclaration> solveType(String name, TypeSolver typeSo
} }


@Override @Override
public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeReference> parameterTypes, TypeSolver typeSolver) { public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver) {
if (wrappedNode.getScope() != null) { if (wrappedNode.getScope() != null) {
// TODO resolve the scope and get a context from there TypeUsage typeOfScope = new JavaParserFacade(typeSolver).getType(wrappedNode.getScope());
SymbolReference<SymbolDeclaration> declScope = new JavaParserFacade(typeSolver).solve(wrappedNode.getScope()); return typeOfScope.solveMethod(name, parameterTypes);
if (declScope.isSolved()) {
TypeDeclaration typeOfDeclScope = declScope.getCorrespondingDeclaration().getType();
return typeOfDeclScope.getContext().solveMethod(name, parameterTypes, typeSolver);
} else {
// TODO this should be improved to indicate that is the scope that has not been solved
throw new UnsolvedSymbolException(this, name);
}
} else { } else {
return JavaParserFactory.getContext(wrappedNode.getParentNode()).solveSymbol(name, typeSolver); return JavaParserFactory.getContext(wrappedNode.getParentNode()).solveSymbol(name, typeSolver);
} }
Expand Down
Expand Up @@ -4,7 +4,6 @@
import com.github.javaparser.ast.body.MethodDeclaration; import com.github.javaparser.ast.body.MethodDeclaration;
import me.tomassetti.symbolsolver.model.*; import me.tomassetti.symbolsolver.model.*;
import me.tomassetti.symbolsolver.model.javaparser.JavaParserFactory; import me.tomassetti.symbolsolver.model.javaparser.JavaParserFactory;
import me.tomassetti.symbolsolver.model.javaparser.contexts.AbstractJavaParserContext;


import java.util.List; import java.util.List;


Expand Down Expand Up @@ -38,7 +37,7 @@ public SymbolReference<me.tomassetti.symbolsolver.model.TypeDeclaration> solveTy
} }


@Override @Override
public SymbolReference<me.tomassetti.symbolsolver.model.MethodDeclaration> solveMethod(String name, List<TypeReference> parameterTypes, TypeSolver typeSolver) { public SymbolReference<me.tomassetti.symbolsolver.model.MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver) {
if (wrappedNode.getName().equals(name)) { if (wrappedNode.getName().equals(name)) {
// TODO understand if signature is compatible // TODO understand if signature is compatible
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
Expand Down
Expand Up @@ -6,7 +6,6 @@
import me.tomassetti.symbolsolver.model.MethodDeclaration; import me.tomassetti.symbolsolver.model.MethodDeclaration;
import me.tomassetti.symbolsolver.model.TypeDeclaration; import me.tomassetti.symbolsolver.model.TypeDeclaration;
import me.tomassetti.symbolsolver.model.javaparser.JavaParserFactory; import me.tomassetti.symbolsolver.model.javaparser.JavaParserFactory;
import me.tomassetti.symbolsolver.model.javaparser.contexts.AbstractJavaParserContext;


import java.util.List; import java.util.List;


Expand Down Expand Up @@ -48,7 +47,7 @@ public SymbolReference solveSymbol(String name, TypeSolver typeSolver) {
} }


@Override @Override
public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeReference> parameterTypes, TypeSolver typeSolver) { public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes, TypeSolver typeSolver) {
return getParent().solveMethod(name, parameterTypes, typeSolver); return getParent().solveMethod(name, parameterTypes, typeSolver);
} }


Expand Down
@@ -1,11 +1,11 @@
package me.tomassetti.symbolsolver.model.javaparser.declarations; package me.tomassetti.symbolsolver.model.javaparser.declarations;


import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration; import com.github.javaparser.ast.body.ClassOrInterfaceDeclaration;
import me.tomassetti.symbolsolver.model.ClassDeclaration; import me.tomassetti.symbolsolver.model.*;
import me.tomassetti.symbolsolver.model.Context;
import me.tomassetti.symbolsolver.model.TypeDeclaration;
import me.tomassetti.symbolsolver.model.javaparser.JavaParserFactory; import me.tomassetti.symbolsolver.model.javaparser.JavaParserFactory;


import java.util.List;

/** /**
* Created by federico on 30/07/15. * Created by federico on 30/07/15.
*/ */
Expand All @@ -22,6 +22,11 @@ public Context getContext() {
return JavaParserFactory.getContext(wrappedNode); return JavaParserFactory.getContext(wrappedNode);
} }


@Override
public SymbolReference<MethodDeclaration> solveMethod(String name, List<TypeUsage> parameterTypes) {
throw new UnsupportedOperationException();
}

@Override @Override
public String getName() { public String getName() {
return wrappedNode.getName(); return wrappedNode.getName();
Expand Down
38 changes: 33 additions & 5 deletions src/test/java/me/tomassetti/symbolsolver/model/ContextTest.java
Expand Up @@ -186,16 +186,13 @@ public void resolveReferenceToMethod() throws ParseException {
expect(compilationUnit.isType()).andReturn(true); expect(compilationUnit.isType()).andReturn(true);
expect(compilationUnit.asTypeDeclaration()).andReturn(compilationUnit); expect(compilationUnit.asTypeDeclaration()).andReturn(compilationUnit);
expect(compilationUnit.getContext()).andReturn(compilationUnitCtx); expect(compilationUnit.getContext()).andReturn(compilationUnitCtx);
expect(compilationUnit.solveMethod("getTypes", Collections.emptyList())).andReturn(SymbolReference.solved(getTypes));
expect(getTypes.getType()).andReturn(compilationUnit); expect(getTypes.getType()).andReturn(compilationUnit);
TypeSolver typeSolver = createMock(TypeSolver.class); TypeSolver typeSolver = createMock(TypeSolver.class);
expect(typeSolver.tryToSolveType("com.github.javaparser.ast.CompilationUnit")).andReturn(SymbolReference.solved(compilationUnit)); expect(typeSolver.tryToSolveType("com.github.javaparser.ast.CompilationUnit")).andReturn(SymbolReference.solved(compilationUnit));
expect(compilationUnitCtx.solveMethod("getTypes", Collections.emptyList(), typeSolver)).andReturn(SymbolReference.solved(getTypes)); //expect(compilationUnitCtx.solveMethod("getTypes", Collections.emptyList(), typeSolver)).andReturn(SymbolReference.solved(getTypes));
SymbolSolver symbolSolver = new SymbolSolver(typeSolver); SymbolSolver symbolSolver = new SymbolSolver(typeSolver);
replay(typeSolver, compilationUnit, compilationUnitCtx, getTypes); replay(typeSolver, compilationUnit, compilationUnitCtx, getTypes);
Node ctx = callToGetTypes;
System.out.println("CTX "+ctx+" "+ctx.getClass());
ctx = ctx.getParentNode();
System.out.println("SCOPE "+callToGetTypes.getScope()+" "+callToGetTypes.getScope().getClass());
SymbolReference<me.tomassetti.symbolsolver.model.MethodDeclaration> ref = symbolSolver.solveMethod("getTypes", Collections.emptyList(), callToGetTypes); SymbolReference<me.tomassetti.symbolsolver.model.MethodDeclaration> ref = symbolSolver.solveMethod("getTypes", Collections.emptyList(), callToGetTypes);


assertEquals(true, ref.isSolved()); assertEquals(true, ref.isSolved());
Expand All @@ -205,4 +202,35 @@ public void resolveReferenceToMethod() throws ParseException {
verify(typeSolver); verify(typeSolver);
} }


/*@Test
public void resolveCascadeOfReferencesToMethod() throws ParseException {
CompilationUnit cu = parseSample("Navigator");
ClassOrInterfaceDeclaration referencesToField = Navigator.demandClass(cu, "Navigator");
MethodDeclaration method = Navigator.demandMethod(referencesToField, "findType");
MethodCallExpr callToStream = Navigator.findMethodCall(method, "stream");
AVOID MOCKING SO MUCH
ClassDeclaration compilationUnit = createMock(ClassDeclaration.class);
//expect(compilationUnit.getName()).andReturn("CompilationUnit");
//expect(compilationUnit.getQualifiedName()).andReturn("com.github.javaparser.ast.CompilationUnit");
expect(compilationUnit.isType()).andReturn(true);
expect(compilationUnit.asTypeDeclaration()).andReturn(compilationUnit);
//expect(compilationUnit.getContext()).andReturn(compilationUnitCtx);
//expect(getTypes.getType()).andReturn(compilationUnit);
TypeSolver typeSolver = createMock(TypeSolver.class);
expect(typeSolver.tryToSolveType("com.github.javaparser.ast.CompilationUnit")).andReturn(SymbolReference.solved(compilationUnit));
//expect(compilationUnitCtx.solveMethod("getTypes", Collections.emptyList(), typeSolver)).andReturn(SymbolReference.solved(getTypes));
SymbolSolver symbolSolver = new SymbolSolver(typeSolver);
replay(typeSolver, compilationUnit);
//replay(typeSolver, compilationUnit, compilationUnitCtx, getTypes);
SymbolReference<me.tomassetti.symbolsolver.model.MethodDeclaration> ref = symbolSolver.solveMethod("stream", Collections.emptyList(), callToStream);
assertEquals(true, ref.isSolved());
assertEquals("stream", ref.getCorrespondingDeclaration().getName());
assertEquals("java.util.Collection", ref.getCorrespondingDeclaration().getType().getQualifiedName());
verify(typeSolver);
}*/

} }

0 comments on commit 8b8cc6c

Please sign in to comment.