Skip to content

Commit

Permalink
issue80: better handling of Lambdas and FunctionInterface
Browse files Browse the repository at this point in the history
  • Loading branch information
ftomassetti committed Oct 9, 2016
1 parent fdf266d commit 47a5cc8
Show file tree
Hide file tree
Showing 57 changed files with 286 additions and 200 deletions.
Expand Up @@ -237,7 +237,7 @@ private TypeUsage getTypeConcrete(Node node, boolean solveLambdas) {
int pos = JavaParserSymbolDeclaration.getParamPos(node); int pos = JavaParserSymbolDeclaration.getParamPos(node);
SymbolReference<MethodDeclaration> refMethod = JavaParserFacade.get(typeSolver).solve(callExpr); SymbolReference<MethodDeclaration> refMethod = JavaParserFacade.get(typeSolver).solve(callExpr);
if (!refMethod.isSolved()) { if (!refMethod.isSolved()) {
throw new UnsolvedSymbolException(callExpr.getName()); throw new UnsolvedSymbolException(node.getParentNode().toString(), callExpr.getName());
} }
logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName()); logger.finest("getType on lambda expr " + refMethod.getCorrespondingDeclaration().getName());
//logger.finest("Method param " + refMethod.getCorrespondingDeclaration().getParam(pos)); //logger.finest("Method param " + refMethod.getCorrespondingDeclaration().getParam(pos));
Expand Down Expand Up @@ -536,8 +536,7 @@ public TypeDeclaration getTypeDeclaration(ClassOrInterfaceDeclaration classOrInt
public TypeUsage getTypeOfThisIn(Node node) { public TypeUsage getTypeOfThisIn(Node node) {
// TODO consider static methods // TODO consider static methods
if (node instanceof ClassOrInterfaceDeclaration) { if (node instanceof ClassOrInterfaceDeclaration) {
JavaParserClassDeclaration classDeclaration = new JavaParserClassDeclaration((ClassOrInterfaceDeclaration) node, typeSolver); return new ReferenceTypeUsageImpl(getTypeDeclaration((ClassOrInterfaceDeclaration) node), typeSolver);
return new ReferenceTypeUsageImpl(classDeclaration, typeSolver);
} else if (node instanceof EnumDeclaration) { } else if (node instanceof EnumDeclaration) {
JavaParserEnumDeclaration enumDeclaration = new JavaParserEnumDeclaration((EnumDeclaration) node, typeSolver); JavaParserEnumDeclaration enumDeclaration = new JavaParserEnumDeclaration((EnumDeclaration) node, typeSolver);
return new ReferenceTypeUsageImpl(enumDeclaration, typeSolver); return new ReferenceTypeUsageImpl(enumDeclaration, typeSolver);
Expand Down
Expand Up @@ -129,6 +129,11 @@ public ClassDeclaration asClass() {
return this; return this;
} }


@Override
public boolean hasDirectlyAnnotation(String canonicalName) {
throw new UnsupportedOperationException();
}

@Override @Override
public boolean isInterface() { public boolean isInterface() {
return wrappedNode.isInterface(); return wrappedNode.isInterface();
Expand Down
Expand Up @@ -88,6 +88,11 @@ public boolean isType() {
return true; return true;
} }


@Override
public boolean hasDirectlyAnnotation(String canonicalName) {
throw new UnsupportedOperationException();
}

@Override @Override
public boolean canBeAssignedTo(TypeDeclaration other) { public boolean canBeAssignedTo(TypeDeclaration other) {
// Enums cannot be extended // Enums cannot be extended
Expand Down
Expand Up @@ -89,6 +89,11 @@ public InterfaceDeclaration asInterface() {
return this; return this;
} }


@Override
public boolean hasDirectlyAnnotation(String canonicalName) {
throw new UnsupportedOperationException();
}

public boolean isInterface() { public boolean isInterface() {
return true; return true;
} }
Expand Down
Expand Up @@ -155,6 +155,11 @@ public boolean isTypeVariable() {
return true; return true;
} }


@Override
public boolean hasDirectlyAnnotation(String canonicalName) {
throw new UnsupportedOperationException();
}

@Override @Override
public List<TypeParameter> getTypeParameters() { public List<TypeParameter> getTypeParameters() {
return Collections.emptyList(); return Collections.emptyList();
Expand All @@ -174,4 +179,9 @@ public com.github.javaparser.ast.TypeParameter getWrappedNode()
{ {
return wrappedNode; return wrappedNode;
} }

@Override
public String toString() {
return "JPTypeParameter(" + wrappedNode.getName() +", bounds=" + wrappedNode.getTypeBound()+ ")";
}
} }
Expand Up @@ -139,6 +139,11 @@ public boolean isType() {
return true; return true;
} }


@Override
public boolean hasDirectlyAnnotation(String canonicalName) {
throw new UnsupportedOperationException();
}

@Override @Override
public boolean isClass() { public boolean isClass() {
return false; return false;
Expand Down
Expand Up @@ -42,6 +42,11 @@ public ClassDeclaration asClass() {
return this; return this;
} }


@Override
public boolean hasDirectlyAnnotation(String canonicalName) {
throw new UnsupportedOperationException();
}

@Override @Override
public Set<MethodDeclaration> getDeclaredMethods() { public Set<MethodDeclaration> getDeclaredMethods() {
return Arrays.stream(ctClass.getDeclaredMethods()) return Arrays.stream(ctClass.getDeclaredMethods())
Expand Down
Expand Up @@ -240,6 +240,23 @@ public Set<MethodDeclaration> getDeclaredMethods() {
.collect(Collectors.toSet()); .collect(Collectors.toSet());
} }


@Override
public boolean hasDirectlyAnnotation(String canonicalName) {
try {
for (Object annotationRaw : ctClass.getAnnotations()) {
if (annotationRaw.getClass().getCanonicalName().equals(canonicalName)) {
return true;
}
if (Arrays.stream(annotationRaw.getClass().getInterfaces()).anyMatch(it -> it.getCanonicalName().equals(canonicalName))) {
return true;
}
}
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
}
return false;
}

@Override @Override
public String getName() { public String getName() {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
Expand Down
@@ -1,18 +1,16 @@
package me.tomassetti.symbolsolver.model.typesystem; package me.tomassetti.symbolsolver.model.typesystem;


import me.tomassetti.symbolsolver.javaparsermodel.LambdaArgumentTypeUsagePlaceholder;
import me.tomassetti.symbolsolver.javaparsermodel.declarations.JavaParserTypeVariableDeclaration;
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.invokations.MethodUsage; import me.tomassetti.symbolsolver.model.invokations.MethodUsage;
import me.tomassetti.symbolsolver.model.resolution.TypeParameter; import me.tomassetti.symbolsolver.model.resolution.TypeParameter;
import me.tomassetti.symbolsolver.model.resolution.TypeSolver; import me.tomassetti.symbolsolver.model.resolution.TypeSolver;
import me.tomassetti.symbolsolver.javaparsermodel.LambdaArgumentTypeUsagePlaceholder;
import me.tomassetti.symbolsolver.javaparsermodel.declarations.JavaParserTypeVariableDeclaration;


import java.util.HashSet; import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.function.Function;
import java.util.function.Predicate;


// TODO Remove references to typeSolver: it is needed to instantiate other instances of ReferenceTypeUsage // TODO Remove references to typeSolver: it is needed to instantiate other instances of ReferenceTypeUsage
// and to get the Object type declaration // and to get the Object type declaration
Expand Down Expand Up @@ -62,7 +60,7 @@ public boolean isAssignableBy(TypeUsage other) {
} }
} }
if (other instanceof LambdaArgumentTypeUsagePlaceholder) { if (other instanceof LambdaArgumentTypeUsagePlaceholder) {
return this.getQualifiedName().equals(Predicate.class.getCanonicalName()) || this.getQualifiedName().equals(Function.class.getCanonicalName()); return this.getTypeDeclaration().hasAnnotation(FunctionalInterface.class.getCanonicalName());
} else if (other instanceof ReferenceTypeUsageImpl) { } else if (other instanceof ReferenceTypeUsageImpl) {
ReferenceTypeUsageImpl otherRef = (ReferenceTypeUsageImpl) other; ReferenceTypeUsageImpl otherRef = (ReferenceTypeUsageImpl) other;
if (compareConsideringTypeParameters(otherRef)) { if (compareConsideringTypeParameters(otherRef)) {
Expand Down
Expand Up @@ -277,6 +277,11 @@ public ClassDeclaration asClass() {
return this; return this;
} }


@Override
public boolean hasDirectlyAnnotation(String canonicalName) {
throw new UnsupportedOperationException();
}

/*@Override /*@Override
public boolean canBeAssignedTo(TypeDeclaration other, TypeSolver typeSolver) { public boolean canBeAssignedTo(TypeDeclaration other, TypeSolver typeSolver) {
if (getQualifiedName().equals(other.getQualifiedName())) { if (getQualifiedName().equals(other.getQualifiedName())) {
Expand Down
Expand Up @@ -18,6 +18,7 @@
import me.tomassetti.symbolsolver.javaparsermodel.LambdaArgumentTypeUsagePlaceholder; import me.tomassetti.symbolsolver.javaparsermodel.LambdaArgumentTypeUsagePlaceholder;
import me.tomassetti.symbolsolver.javaparsermodel.UnsolvedSymbolException; import me.tomassetti.symbolsolver.javaparsermodel.UnsolvedSymbolException;


import java.lang.annotation.Annotation;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.lang.reflect.Method; import java.lang.reflect.Method;
import java.lang.reflect.TypeVariable; import java.lang.reflect.TypeVariable;
Expand Down Expand Up @@ -303,6 +304,16 @@ public InterfaceDeclaration asInterface() {
return this; return this;
} }


@Override
public boolean hasDirectlyAnnotation(String canonicalName) {
for (Annotation a : clazz.getDeclaredAnnotations()) {
if (a.annotationType().getCanonicalName().equals(canonicalName)) {
return true;
}
}
return false;
}

@Override @Override
public List<TypeParameter> getTypeParameters() { public List<TypeParameter> getTypeParameters() {
List<TypeParameter> params = new ArrayList<>(); List<TypeParameter> params = new ArrayList<>();
Expand Down
@@ -0,0 +1,23 @@
package me.tomassetti.symbolsolver;

import java.io.File;

public abstract class AbstractTest {

protected static File adaptPath(File path) {
if (path.exists()) {
return path;
} else {
File underJavaParserCore = new File("java-symbol-solver-core/" + path.getPath());
if (underJavaParserCore.exists()) {
return underJavaParserCore;
} else {
throw new IllegalArgumentException();
}
}
}

protected static String adaptPath(String path) {
return adaptPath(new File(path)).getPath();
}
}
Expand Up @@ -8,15 +8,15 @@
import me.tomassetti.symbolsolver.javaparsermodel.JavaParserFacade; import me.tomassetti.symbolsolver.javaparsermodel.JavaParserFacade;
import me.tomassetti.symbolsolver.model.declarations.Declaration; import me.tomassetti.symbolsolver.model.declarations.Declaration;
import me.tomassetti.symbolsolver.model.declarations.TypeDeclaration; import me.tomassetti.symbolsolver.model.declarations.TypeDeclaration;
import me.tomassetti.symbolsolver.resolution.AbstractTest; import me.tomassetti.symbolsolver.resolution.AbstractResolutionTest;
import me.tomassetti.symbolsolver.resolution.typesolvers.JreTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.JreTypeSolver;
import org.junit.Test; import org.junit.Test;


import java.util.stream.Collectors; import java.util.stream.Collectors;


import static org.junit.Assert.*; import static org.junit.Assert.*;


public class FindingAllFields extends AbstractTest { public class FindingAllFields extends AbstractResolutionTest {


@Test @Test
public void findAllInheritedFields() throws ParseException { public void findAllInheritedFields() throws ParseException {
Expand Down
Expand Up @@ -9,13 +9,13 @@
import me.tomassetti.symbolsolver.javaparsermodel.JavaParserFacade; import me.tomassetti.symbolsolver.javaparsermodel.JavaParserFacade;
import me.tomassetti.symbolsolver.model.resolution.TypeSolver; import me.tomassetti.symbolsolver.model.resolution.TypeSolver;
import me.tomassetti.symbolsolver.model.typesystem.TypeUsage; import me.tomassetti.symbolsolver.model.typesystem.TypeUsage;
import me.tomassetti.symbolsolver.resolution.AbstractTest; import me.tomassetti.symbolsolver.resolution.AbstractResolutionTest;
import me.tomassetti.symbolsolver.resolution.typesolvers.JreTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.JreTypeSolver;
import org.junit.Test; import org.junit.Test;


import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;


public class Issue18 extends AbstractTest { public class Issue18 extends AbstractResolutionTest {


@Test @Test
public void typeDeclarationSuperClassImplicitlyIncludeObject() throws ParseException { public void typeDeclarationSuperClassImplicitlyIncludeObject() throws ParseException {
Expand Down
@@ -1,6 +1,7 @@
package me.tomassetti.symbolsolver.javaparsermodel.declarations; package me.tomassetti.symbolsolver.javaparsermodel.declarations;


import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import me.tomassetti.symbolsolver.AbstractTest;
import me.tomassetti.symbolsolver.model.resolution.TypeSolver; import me.tomassetti.symbolsolver.model.resolution.TypeSolver;
import me.tomassetti.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import me.tomassetti.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
Expand All @@ -13,17 +14,17 @@


import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;


public class JavaParserClassDeclarationTest { public class JavaParserClassDeclarationTest extends AbstractTest {


private TypeSolver typeSolver; private TypeSolver typeSolver;


@Before @Before
public void setup() { public void setup() {
File src = new File("src/test/resources/javaparser_src/proper_source"); File src = adaptPath(new File("src/test/resources/javaparser_src/proper_source"));
CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(); CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
combinedTypeSolver.add(new JreTypeSolver()); combinedTypeSolver.add(new JreTypeSolver());
combinedTypeSolver.add(new JavaParserTypeSolver(src)); combinedTypeSolver.add(new JavaParserTypeSolver(src));
combinedTypeSolver.add(new JavaParserTypeSolver(new File("src/test/resources/javaparser_src/generated"))); combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(new File("src/test/resources/javaparser_src/generated"))));
typeSolver = combinedTypeSolver; typeSolver = combinedTypeSolver;
} }


Expand Down
@@ -1,6 +1,7 @@
package me.tomassetti.symbolsolver.javassistmodel; package me.tomassetti.symbolsolver.javassistmodel;


import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import me.tomassetti.symbolsolver.AbstractTest;
import me.tomassetti.symbolsolver.model.resolution.TypeSolver; import me.tomassetti.symbolsolver.model.resolution.TypeSolver;
import me.tomassetti.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import me.tomassetti.symbolsolver.resolution.typesolvers.JarTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.JarTypeSolver;
Expand All @@ -13,13 +14,13 @@


import static org.junit.Assert.*; import static org.junit.Assert.*;


public class JavassistClassDeclarationTest { public class JavassistClassDeclarationTest extends AbstractTest {


private TypeSolver typeSolver; private TypeSolver typeSolver;


@Before @Before
public void setup() throws IOException { public void setup() throws IOException {
String pathToJar = "src/test/resources/javaparser-core-2.1.0.jar"; String pathToJar = adaptPath("src/test/resources/javaparser-core-2.1.0.jar");
typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new JreTypeSolver()); typeSolver = new CombinedTypeSolver(new JarTypeSolver(pathToJar), new JreTypeSolver());
} }


Expand Down
Expand Up @@ -3,13 +3,14 @@
import com.github.javaparser.JavaParser; import com.github.javaparser.JavaParser;
import com.github.javaparser.ParseException; import com.github.javaparser.ParseException;
import com.github.javaparser.ast.CompilationUnit; import com.github.javaparser.ast.CompilationUnit;
import me.tomassetti.symbolsolver.AbstractTest;


import java.io.InputStream; import java.io.InputStream;


/** /**
* @author Federico Tomassetti * @author Federico Tomassetti
*/ */
public abstract class AbstractTest { public abstract class AbstractResolutionTest extends AbstractTest {


protected CompilationUnit parseSample(String sampleName) throws ParseException { protected CompilationUnit parseSample(String sampleName) throws ParseException {
InputStream is = this.getClass().getClassLoader().getResourceAsStream(sampleName + ".java.txt"); InputStream is = this.getClass().getClassLoader().getResourceAsStream(sampleName + ".java.txt");
Expand Down
@@ -1,6 +1,7 @@
package me.tomassetti.symbolsolver.resolution; package me.tomassetti.symbolsolver.resolution;


import com.github.javaparser.ParseException; import com.github.javaparser.ParseException;
import me.tomassetti.symbolsolver.AbstractTest;
import me.tomassetti.symbolsolver.SourceFileInfoExtractor; import me.tomassetti.symbolsolver.SourceFileInfoExtractor;
import me.tomassetti.symbolsolver.javaparsermodel.JavaParserFacade; import me.tomassetti.symbolsolver.javaparsermodel.JavaParserFacade;
import me.tomassetti.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
Expand All @@ -15,15 +16,15 @@


import static org.junit.Assert.*; import static org.junit.Assert.*;


public class AnalyseJavaParserTest { public class AnalyseJavaParserTest extends AbstractTest {


private static final File src = new File("src/test/resources/javaparser_src/proper_source"); private static final File src = adaptPath(new File("src/test/resources/javaparser_src/proper_source"));


private SourceFileInfoExtractor getSourceFileInfoExtractor() { private SourceFileInfoExtractor getSourceFileInfoExtractor() {
CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(); CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
combinedTypeSolver.add(new JreTypeSolver()); combinedTypeSolver.add(new JreTypeSolver());
combinedTypeSolver.add(new JavaParserTypeSolver(src)); combinedTypeSolver.add(new JavaParserTypeSolver(src));
combinedTypeSolver.add(new JavaParserTypeSolver(new File("src/test/resources/javaparser_src/generated"))); combinedTypeSolver.add(new JavaParserTypeSolver(adaptPath(new File("src/test/resources/javaparser_src/generated"))));
SourceFileInfoExtractor sourceFileInfoExtractor = new SourceFileInfoExtractor(); SourceFileInfoExtractor sourceFileInfoExtractor = new SourceFileInfoExtractor();
sourceFileInfoExtractor.setTypeSolver(combinedTypeSolver); sourceFileInfoExtractor.setTypeSolver(combinedTypeSolver);
sourceFileInfoExtractor.setPrintFileName(false); sourceFileInfoExtractor.setPrintFileName(false);
Expand Down Expand Up @@ -51,7 +52,7 @@ private void parse(String fileName) throws IOException, ParseException {
String output = outErrStream.toString(); String output = outErrStream.toString();


String path = "src/test/resources/javaparser_expected_output/" + fileName.replaceAll("/", "_")+ ".txt"; String path = "src/test/resources/javaparser_expected_output/" + fileName.replaceAll("/", "_")+ ".txt";
File dstFile = new File(path); File dstFile = adaptPath(new File(path));


if (DEBUG && (sourceFileInfoExtractor.getKo() != 0 || sourceFileInfoExtractor.getUnsupported() != 0)){ if (DEBUG && (sourceFileInfoExtractor.getKo() != 0 || sourceFileInfoExtractor.getUnsupported() != 0)){
System.err.println(output); System.err.println(output);
Expand Down
@@ -1,7 +1,7 @@
package me.tomassetti.symbolsolver.resolution; package me.tomassetti.symbolsolver.resolution;


import com.github.javaparser.ParseException; import com.github.javaparser.ParseException;
import me.tomassetti.symbolsolver.SourceFileInfoExtractor; import me.tomassetti.symbolsolver.*;
import me.tomassetti.symbolsolver.javaparsermodel.JavaParserFacade; import me.tomassetti.symbolsolver.javaparsermodel.JavaParserFacade;
import me.tomassetti.symbolsolver.resolution.typesolvers.CombinedTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.CombinedTypeSolver;
import me.tomassetti.symbolsolver.resolution.typesolvers.JavaParserTypeSolver; import me.tomassetti.symbolsolver.resolution.typesolvers.JavaParserTypeSolver;
Expand All @@ -19,23 +19,10 @@
/** /**
* We analize a more recent version of JavaParser, after the project moved to Java 8. * We analize a more recent version of JavaParser, after the project moved to Java 8.
*/ */
public class AnalyseNewJavaParserTest { public class AnalyseNewJavaParserTest extends AbstractResolutionTest {


private static final File src = adaptPath(new File("src/test/resources/javaparser_new_src/javaparser-core")); private static final File src = adaptPath(new File("src/test/resources/javaparser_new_src/javaparser-core"));


private static File adaptPath(File path) {
if (path.exists()) {
return path;
} else {
File underJavaParserCore = new File("java-symbol-solver-core/" + path.getPath());
if (underJavaParserCore.exists()) {
return underJavaParserCore;
} else {
throw new IllegalArgumentException();
}
}
}

private static SourceFileInfoExtractor getSourceFileInfoExtractor() { private static SourceFileInfoExtractor getSourceFileInfoExtractor() {
CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver(); CombinedTypeSolver combinedTypeSolver = new CombinedTypeSolver();
combinedTypeSolver.add(new JreTypeSolver()); combinedTypeSolver.add(new JreTypeSolver());
Expand Down

0 comments on commit 47a5cc8

Please sign in to comment.