Skip to content

Commit

Permalink
Convert certain QualifiedName nodes to FieldAccess at tree conversion…
Browse files Browse the repository at this point in the history
… time, thus avoiding the conversion during later mutations.

	Change on 2015/06/29 by kstanger <kstanger@google.com>
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=97153120
  • Loading branch information
kstanger committed Jul 3, 2015
1 parent 9005c9e commit 11f804e
Show file tree
Hide file tree
Showing 6 changed files with 23 additions and 92 deletions.
Expand Up @@ -348,29 +348,6 @@ public static void insertBefore(Statement node, Statement toInsert) {
asStatementList(node).add(0, toInsert);
}

/**
* Replaces (in place) a QualifiedName node with an equivalent FieldAccess
* node. This is helpful when a mutation needs to replace the qualifier with
* a node that has Expression type but not Name type.
* CAUTION: It is strongly recommended that this method be used within a
* "visit", and not a "endVisit" because it will rewrite all QualifiedNode
* ancestors.
*/
public static FieldAccess convertToFieldAccess(QualifiedName node) {
TreeNode parent = node.getParent();
if (parent instanceof QualifiedName) {
FieldAccess newParent = convertToFieldAccess((QualifiedName) parent);
Expression expr = newParent.getExpression();
assert expr instanceof QualifiedName;
node = (QualifiedName) expr;
}
IVariableBinding variableBinding = getVariableBinding(node);
assert variableBinding != null : "node must be a variable";
FieldAccess newNode = new FieldAccess(variableBinding, remove(node.getQualifier()));
node.replaceWith(newNode);
return newNode;
}

public static Expression newLiteral(Object value, Types typeEnv) {
if (value instanceof Boolean) {
return new BooleanLiteral((Boolean) value, typeEnv);
Expand Down
Expand Up @@ -24,7 +24,6 @@
import com.google.devtools.j2objc.ast.MethodDeclaration;
import com.google.devtools.j2objc.ast.MethodInvocation;
import com.google.devtools.j2objc.ast.ParenthesizedExpression;
import com.google.devtools.j2objc.ast.QualifiedName;
import com.google.devtools.j2objc.ast.ReturnStatement;
import com.google.devtools.j2objc.ast.SimpleName;
import com.google.devtools.j2objc.ast.SuperMethodInvocation;
Expand Down Expand Up @@ -302,18 +301,6 @@ public void endVisit(MethodInvocation node) {
}
}

@Override
public boolean visit(QualifiedName node) {
if (needsCast(node.getQualifier(), true)) {
// The qualifier child has type Name and can't be replaced with a
// CastExpression, so we must convert to a FieldAccess.
FieldAccess newNode = TreeUtil.convertToFieldAccess(node);
newNode.accept(this);
return false;
}
return true;
}

@Override
public void endVisit(ReturnStatement node) {
Expression expr = node.getExpression();
Expand Down
Expand Up @@ -38,7 +38,6 @@
import com.google.devtools.j2objc.ast.MethodInvocation;
import com.google.devtools.j2objc.ast.NullLiteral;
import com.google.devtools.j2objc.ast.ParenthesizedExpression;
import com.google.devtools.j2objc.ast.QualifiedName;
import com.google.devtools.j2objc.ast.Statement;
import com.google.devtools.j2objc.ast.SwitchCase;
import com.google.devtools.j2objc.ast.SwitchStatement;
Expand Down Expand Up @@ -191,29 +190,6 @@ public void endVisit(FieldAccess node) {
}
}

@Override
public boolean visit(QualifiedName node) {
if (!needsNilCheck(node.getQualifier())) {
return true;
}

// Instance references to static fields don't need to be nil-checked.
// This is true in Java (surprisingly), where instance.FIELD returns
// FIELD even when instance is null.
IVariableBinding var = TreeUtil.getVariableBinding(node);
IVariableBinding qualifierVar = TreeUtil.getVariableBinding(node.getQualifier());
if (var != null && qualifierVar != null && BindingUtil.isStatic(var)
&& !BindingUtil.isStatic(qualifierVar)) {
return true;
}

// We can't substitute the qualifier with a nil_chk because it must have a
// Name type, so we have to convert to a FieldAccess node.
FieldAccess newNode = TreeUtil.convertToFieldAccess(node);
newNode.accept(this);
return false;
}

@Override
public void endVisit(MethodInvocation node) {
IMethodBinding binding = node.getMethodBinding();
Expand Down
Expand Up @@ -320,14 +320,19 @@ public void endVisit(AnnotationTypeDeclaration node) {
}

@Override
public boolean visit(SimpleName node) {
TreeNode parent = node.getParent();
if (parent instanceof FieldAccess
|| (parent instanceof QualifiedName && node == ((QualifiedName) parent).getName())) {
// Already a qualified node.
return false;
}
public boolean visit(FieldAccess node) {
node.getExpression().accept(this);
return false;
}

@Override
public boolean visit(QualifiedName node) {
node.getQualifier().accept(this);
return false;
}

@Override
public boolean visit(SimpleName node) {
IVariableBinding var = TreeUtil.getVariableBinding(node);
if (var != null) {
if (var.isField() && !Modifier.isStatic(var.getModifiers())) {
Expand Down
Expand Up @@ -39,7 +39,6 @@
import com.google.devtools.j2objc.ast.LabeledStatement;
import com.google.devtools.j2objc.ast.LambdaExpression;
import com.google.devtools.j2objc.ast.MethodDeclaration;
import com.google.devtools.j2objc.ast.Name;
import com.google.devtools.j2objc.ast.ParenthesizedExpression;
import com.google.devtools.j2objc.ast.QualifiedName;
import com.google.devtools.j2objc.ast.ReturnStatement;
Expand All @@ -60,7 +59,6 @@
import com.google.j2objc.annotations.AutoreleasePool;
import com.google.j2objc.annotations.RetainedLocalRef;

import org.eclipse.jdt.core.dom.IBinding;
import org.eclipse.jdt.core.dom.IMethodBinding;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.IVariableBinding;
Expand Down Expand Up @@ -407,22 +405,14 @@ public void endVisit(FieldDeclaration node) {

@Override
public boolean visit(QualifiedName node) {
// Check for ScopedLocalRefs.
IBinding var = node.getBinding();
if (var instanceof IVariableBinding) {
IVariableBinding localRef = localRefs.get(node.getQualifier().getBinding());
if (localRef != null) {
IVariableBinding localRefFieldBinding = typeEnv.getLocalRefType().getDeclaredFields()[0];
Name newQualifier = node.getQualifier().copy();
newQualifier.setBinding(localRef);
FieldAccess localRefAccess = new FieldAccess(localRefFieldBinding, newQualifier);
CastExpression newCast = new CastExpression(
node.getQualifier().getTypeBinding(), localRefAccess);
ParenthesizedExpression newParens = ParenthesizedExpression.parenthesize(newCast);
FieldAccess access = new FieldAccess((IVariableBinding) var, newParens);
node.replaceWith(access);
return false;
}
IVariableBinding var = TreeUtil.getVariableBinding(node);
Expression qualifier = node.getQualifier();
if (var != null && var.isField() && TreeUtil.getVariableBinding(qualifier) != null) {
// FieldAccess nodes are more easily mutated than QualifiedName.
FieldAccess fieldAccess = new FieldAccess(var, TreeUtil.remove(qualifier));
node.replaceWith(fieldAccess);
fieldAccess.accept(this);
return false;
}
return true;
}
Expand Down
Expand Up @@ -105,6 +105,9 @@ private void handleFieldAccess(Expression node, Expression maybeFieldAccess) {
expr.accept(this);
} else {
fieldAccess.replaceWith(TreeUtil.remove(name));
if (fieldAccess == node) {
name.accept(this);
}
}
}

Expand All @@ -127,13 +130,6 @@ public boolean visit(QualifiedName node) {
private boolean visitName(Name node) {
IVariableBinding var = TreeUtil.getVariableBinding(node);
if (var != null && useAccessor(node, var)) {
TreeNode parent = node.getParent();
if (parent instanceof QualifiedName && node == ((QualifiedName) parent).getQualifier()) {
// QualifiedName nodes can only have qualifier children of type Name, so
// we must convert QualifiedName parents to FieldAccess nodes.
FieldAccess newParent = TreeUtil.convertToFieldAccess((QualifiedName) parent);
node = (Name) newParent.getExpression();
}
node.replaceWith(newGetterInvocation(var, false));
return false;
}
Expand Down

0 comments on commit 11f804e

Please sign in to comment.