Skip to content

Commit

Permalink
Get functional interface descriptors from Javac instead of resolving …
Browse files Browse the repository at this point in the history
…them with a custom algorithm.

	Change on 2017/08/04 by kstanger <kstanger@google.com>

-------------
Created by MOE: https://github.com/google/moe
MOE_MIGRATED_REVID=164255550
  • Loading branch information
kstanger authored and tomball committed Aug 16, 2017
1 parent 39b0a8b commit dd9dbee
Show file tree
Hide file tree
Showing 4 changed files with 46 additions and 29 deletions.
19 changes: 19 additions & 0 deletions jre_emul/Tests/com/google/j2objc/java8/DefaultMethodsTest.java
Expand Up @@ -152,4 +152,23 @@ public void testGetMethodsReturnsDefaultMethod() {
assertTrue(methodNames.contains("f"));
assertTrue(methodNames.contains("notF"));
}

interface X {
int f();
int g();
}

interface Y extends X {
default int f() {
return 1;
}
}

public static int acceptY(Y y) {
return y.g();
}

public void testDefaultMethodOverrideToCreateFunctionalInterface() {
assertEquals(13, acceptY(() -> 13));
}
}
Expand Up @@ -14,6 +14,7 @@

package com.google.devtools.j2objc.ast;

import com.google.devtools.j2objc.types.ExecutablePair;
import java.util.ArrayList;
import java.util.List;
import javax.lang.model.element.TypeElement;
Expand All @@ -24,9 +25,10 @@
*/
public abstract class FunctionalExpression extends Expression {

private TypeMirror typeMirror;
private TypeElement typeElement;
private TypeMirror typeMirror = null;
private TypeElement typeElement = null;
private List<TypeMirror> targetTypes = new ArrayList<>();
private ExecutablePair descriptor = ExecutablePair.NULL;
protected ChildLink<Expression> lambdaOuterArg = ChildLink.create(Expression.class, this);
protected ChildList<Expression> lambdaCaptureArgs = ChildList.create(Expression.class, this);

Expand All @@ -38,6 +40,7 @@ public FunctionalExpression(FunctionalExpression other) {
typeMirror = other.getTypeMirror();
typeElement = other.getTypeElement();
targetTypes.addAll(other.getTargetTypes());
descriptor = other.getDescriptor();
lambdaOuterArg.copyFrom(other.getLambdaOuterArg());
lambdaCaptureArgs.copyFrom(other.getLambdaCaptureArgs());
}
Expand Down Expand Up @@ -70,6 +73,15 @@ public FunctionalExpression addTargetType(TypeMirror t) {
return this;
}

public ExecutablePair getDescriptor() {
return descriptor;
}

public FunctionalExpression setDescriptor(ExecutablePair e) {
descriptor = e;
return this;
}

public Expression getLambdaOuterArg() {
return lambdaOuterArg.get();
}
Expand Down
Expand Up @@ -125,6 +125,7 @@
import com.sun.tools.javac.code.Symbol.PackageSymbol;
import com.sun.tools.javac.code.Symbol.VarSymbol;
import com.sun.tools.javac.code.TypeTag;
import com.sun.tools.javac.code.Types;
import com.sun.tools.javac.tree.DocCommentTable;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCIdent;
Expand Down Expand Up @@ -152,6 +153,7 @@
public class TreeConverter {
private final JCTree.JCCompilationUnit unit;
private final JavacEnvironment env;
private final Types types;
private CompilationUnit newUnit;

public static CompilationUnit convertCompilationUnit(
Expand Down Expand Up @@ -189,6 +191,7 @@ public static CompilationUnit convertCompilationUnit(
private TreeConverter(JCTree.JCCompilationUnit javacUnit, JavacEnvironment javacEnv) {
unit = javacUnit;
env = javacEnv;
types = Types.instance(javacEnv.getContext());
}

private TreeNode convert(Object obj) {
Expand Down Expand Up @@ -780,7 +783,10 @@ private TreeNode convertFunctionalExpression(JCTree.JCFunctionalExpression node,
for (TypeMirror type : node.targets) {
newNode.addTargetType(type);
}
return newNode.setTypeMirror(node.type);
return newNode.setTypeMirror(node.type)
.setDescriptor(new ExecutablePair(
(ExecutableElement) types.findDescriptorSymbol(node.targets.head.tsym),
(ExecutableType) node.getDescriptorType(types)));
}

private TreeNode convertIdent(JCTree.JCIdent node) {
Expand Down
Expand Up @@ -54,7 +54,6 @@
import javax.lang.model.element.TypeElement;
import javax.lang.model.element.VariableElement;
import javax.lang.model.type.ArrayType;
import javax.lang.model.type.ExecutableType;
import javax.lang.model.type.TypeMirror;

/**
Expand All @@ -76,8 +75,7 @@ private class RewriteContext {
private final FunctionalExpression node;
private final TypeElement lambdaType;
private final TypeMirror typeMirror;
private ExecutableElement functionalInterface;
private ExecutableType functionalInterfaceType;
private final ExecutablePair descriptor;
private TypeDeclaration typeDecl;
private GeneratedExecutableElement implElement;
private MethodDeclaration implDecl;
Expand All @@ -87,42 +85,24 @@ private RewriteContext(FunctionalExpression node) {
this.node = node;
lambdaType = node.getTypeElement();
typeMirror = node.getTypeMirror();
resolveFunctionalInterface();
descriptor = node.getDescriptor();
createTypeDeclaration();
createImplementation();
createCreation();
removeCastExpression();
replaceNode();
}

public void resolveFunctionalInterface() {
typeUtil.visitTypeHierarchy(typeMirror, baseType -> {
TypeElement element = (TypeElement) baseType.asElement();
if (element.getKind().isClass()) {
return true;
}
for (ExecutableElement method : ElementUtil.getMethods(element)) {
if (!ElementUtil.isDefault(method) && !ElementUtil.isStatic(method)) {
functionalInterface = method;
functionalInterfaceType = typeUtil.asMemberOf(baseType, method);
return false;
}
}
return true;
});
assert functionalInterface != null : "Could not find functional interface for " + typeMirror;
}

private void createTypeDeclaration() {
typeDecl = new TypeDeclaration(lambdaType);
typeDecl.setSourceRange(node.getStartPosition(), node.getLength());
TreeUtil.getEnclosingTypeBodyDeclarations(node).add(typeDecl);
}

private void createImplementation() {
String selector = nameTable.getMethodSelector(functionalInterface);
String selector = nameTable.getMethodSelector(descriptor.element());
implElement = GeneratedExecutableElement.newMethodWithSelector(
selector, functionalInterface.getReturnType(), lambdaType);
selector, descriptor.element().getReturnType(), lambdaType);
implDecl = new MethodDeclaration(implElement);
typeDecl.addBodyDeclaration(implDecl);
}
Expand Down Expand Up @@ -171,7 +151,7 @@ private void setImplementationBody(TreeNode body) {

private Block asImplementationBlock(Expression expr) {
Block block = new Block();
if (TypeUtil.isVoid(functionalInterface.getReturnType())) {
if (TypeUtil.isVoid(descriptor.element().getReturnType())) {
block.addStatement(new ExpressionStatement(expr));
} else {
block.addStatement(new ReturnStatement(expr));
Expand All @@ -189,7 +169,7 @@ private void rewriteLambdaExpression(LambdaExpression node) {
}

private Iterator<VariableElement> createParameters() {
List<? extends TypeMirror> paramTypes = functionalInterfaceType.getParameterTypes();
List<? extends TypeMirror> paramTypes = descriptor.type().getParameterTypes();
List<VariableElement> params = new ArrayList<>(paramTypes.size());
int i = 0;
for (TypeMirror type : paramTypes) {
Expand Down

0 comments on commit dd9dbee

Please sign in to comment.