Skip to content

Commit

Permalink
Adds lambdas and method references to the reference graph.
Browse files Browse the repository at this point in the history
	Change on 2017/01/03 by kstanger <kstanger@google.com>

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=143473670
  • Loading branch information
kstanger authored and tomball committed Jan 6, 2017
1 parent 9b09d04 commit 729921f
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 9 deletions.
Expand Up @@ -52,6 +52,10 @@ public static Edge newOuterClassEdge(TypeNode origin, TypeNode target) {
return new Edge(origin, target, null, "(outer class " + target.getName() + ")");
}

public static Edge newReceiverClassEdge(TypeNode origin, TypeNode target) {
return new Edge(origin, target, null, "(receiver class " + target.getName() + ")");
}

public static Edge newCaptureEdge(TypeNode origin, TypeNode target, String varName) {
return new Edge(origin, target, null,
"(capture " + varName + " with type " + target.getName() + ")");
Expand Down
Expand Up @@ -20,8 +20,15 @@
import com.google.common.collect.Sets;
import com.google.devtools.j2objc.ast.ClassInstanceCreation;
import com.google.devtools.j2objc.ast.CompilationUnit;
import com.google.devtools.j2objc.ast.CreationReference;
import com.google.devtools.j2objc.ast.ExpressionMethodReference;
import com.google.devtools.j2objc.ast.LambdaExpression;
import com.google.devtools.j2objc.ast.MethodInvocation;
import com.google.devtools.j2objc.ast.MethodReference;
import com.google.devtools.j2objc.ast.SuperMethodReference;
import com.google.devtools.j2objc.ast.TreeNode;
import com.google.devtools.j2objc.ast.TypeDeclaration;
import com.google.devtools.j2objc.ast.TypeMethodReference;
import com.google.devtools.j2objc.ast.UnitTreeVisitor;
import com.google.devtools.j2objc.util.CaptureInfo;
import com.google.devtools.j2objc.util.ElementUtil;
Expand Down Expand Up @@ -295,26 +302,68 @@ private void followCaptureFields(TypeElement type, TypeNode typeNode) {
}
}

private void handleTypeDeclaration(TypeDeclaration node) {
TypeElement typeElem = node.getTypeElement();
private String getTypeDeclarationName(TreeNode node, TypeElement typeElem) {
if (node instanceof MethodReference) {
return "methodref:" + node.getLineNumber();
} else if (ElementUtil.isLambda(typeElem)) {
return "lambda:" + node.getLineNumber();
} else if (ElementUtil.isAnonymous(typeElem)) {
return "anonymous:" + node.getLineNumber();
} else {
return NameUtil.getName(typeElem.asType());
}
}

private void handleTypeDeclaration(TreeNode node, TypeElement typeElem) {
TypeMirror type = typeElem.asType();
String name = ElementUtil.isAnonymous(typeElem)
? "anonymous:" + node.getLineNumber() : NameUtil.getName(type);
TypeNode typeNode = createNode(type, nameUtil.getSignature(type), name);
TypeNode typeNode = createNode(
type, nameUtil.getSignature(type), getTypeDeclarationName(node, typeElem));
if (captureInfo.needsOuterReference(typeElem)) {
hasOuterRef.add(typeNode);
}
VariableElement receiverField = captureInfo.getReceiverField(typeElem);
if (receiverField != null) {
TypeNode receiverNode = getOrCreateNode(receiverField.asType());
if (receiverNode != null) {
addEdge(Edge.newReceiverClassEdge(typeNode, receiverNode));
}
}
if (ElementUtil.isAnonymous(typeElem)) {
followCaptureFields(typeElem, typeNode);
}
}

@Override
public boolean visit(TypeDeclaration node) {
handleTypeDeclaration(node);
handleTypeDeclaration(node, node.getTypeElement());
return true;
}

@Override
public void endVisit(LambdaExpression node) {
handleTypeDeclaration(node, node.getTypeElement());
}

@Override
public void endVisit(CreationReference node) {
handleTypeDeclaration(node, node.getTypeElement());
}

@Override
public void endVisit(ExpressionMethodReference node) {
handleTypeDeclaration(node, node.getTypeElement());
}

@Override
public void endVisit(SuperMethodReference node) {
handleTypeDeclaration(node, node.getTypeElement());
}

@Override
public void endVisit(TypeMethodReference node) {
handleTypeDeclaration(node, node.getTypeElement());
}

@Override
public boolean visit(ClassInstanceCreation node) {
visitType(node.getTypeMirror());
Expand Down
Expand Up @@ -375,9 +375,14 @@ public void testSimpleLambdaWithCycle() throws Exception {
addSourceFile("I.java", "interface I { int foo(); }");
addSourceFile("A.java", "class A { int j = 1; I i = () -> j; }");
findCycles();
// TODO(kstanger): Right now this makes sure that cycle_finder doesn't crash on lambdas, but it
// should be finding a cycle here.
assertNoCycles();
assertCycle("LA.$Lambda$1;", "LA;");
}

public void testMethodReferenceCycle() throws Exception {
addSourceFile("I.java", "interface I { int foo(); }");
addSourceFile("A.java", "class A { int bar() { return 1; } I i = this::bar; }");
findCycles();
assertCycle("LA.$Lambda$1;", "LA;");
}

private void assertContains(String substr, String str) {
Expand Down

0 comments on commit 729921f

Please sign in to comment.