Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(281)

Unified Diff: editor/util/plugins/com.google.dart.java2dart/src/com/google/dart/java2dart/processor/PropertySemanticProcessor.java

Issue 109853003: New analyzer snapshot. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fixes for review comments. Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: editor/util/plugins/com.google.dart.java2dart/src/com/google/dart/java2dart/processor/PropertySemanticProcessor.java
diff --git a/editor/util/plugins/com.google.dart.java2dart/src/com/google/dart/java2dart/processor/PropertySemanticProcessor.java b/editor/util/plugins/com.google.dart.java2dart/src/com/google/dart/java2dart/processor/PropertySemanticProcessor.java
index 2be66ec006a830000a7f58fa7086f8be824755d5..02eabc8e41f989e3529040d998d2636dd321720e 100644
--- a/editor/util/plugins/com.google.dart.java2dart/src/com/google/dart/java2dart/processor/PropertySemanticProcessor.java
+++ b/editor/util/plugins/com.google.dart.java2dart/src/com/google/dart/java2dart/processor/PropertySemanticProcessor.java
@@ -14,13 +14,17 @@
package com.google.dart.java2dart.processor;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.dart.engine.ast.AssignmentExpression;
+import com.google.dart.engine.ast.Block;
import com.google.dart.engine.ast.BlockFunctionBody;
import com.google.dart.engine.ast.ClassDeclaration;
import com.google.dart.engine.ast.ClassMember;
import com.google.dart.engine.ast.CompilationUnit;
+import com.google.dart.engine.ast.ConstructorDeclaration;
import com.google.dart.engine.ast.Expression;
import com.google.dart.engine.ast.ExpressionFunctionBody;
import com.google.dart.engine.ast.ExpressionStatement;
@@ -28,13 +32,17 @@ import com.google.dart.engine.ast.FieldDeclaration;
import com.google.dart.engine.ast.FormalParameter;
import com.google.dart.engine.ast.MethodDeclaration;
import com.google.dart.engine.ast.MethodInvocation;
+import com.google.dart.engine.ast.NodeList;
import com.google.dart.engine.ast.PropertyAccess;
+import com.google.dart.engine.ast.RedirectingConstructorInvocation;
import com.google.dart.engine.ast.SimpleFormalParameter;
import com.google.dart.engine.ast.SimpleIdentifier;
import com.google.dart.engine.ast.Statement;
+import com.google.dart.engine.ast.SuperConstructorInvocation;
import com.google.dart.engine.ast.ThisExpression;
import com.google.dart.engine.ast.TypeName;
import com.google.dart.engine.ast.VariableDeclaration;
+import com.google.dart.engine.ast.VariableDeclarationList;
import com.google.dart.engine.ast.visitor.RecursiveASTVisitor;
import com.google.dart.engine.scanner.Keyword;
import com.google.dart.engine.scanner.TokenType;
@@ -42,18 +50,20 @@ import com.google.dart.java2dart.Context;
import com.google.dart.java2dart.util.Bindings;
import static com.google.dart.java2dart.util.ASTFactory.assignmentExpression;
+import static com.google.dart.java2dart.util.ASTFactory.emptyFunctionBody;
+import static com.google.dart.java2dart.util.ASTFactory.fieldFormalParameter;
import static com.google.dart.java2dart.util.ASTFactory.propertyAccess;
import static com.google.dart.java2dart.util.TokenFactory.token;
import org.apache.commons.lang3.StringUtils;
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;
+import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
+import java.util.concurrent.atomic.AtomicBoolean;
/**
* {@link SemanticProcessor} for converting <code>getX()</code> or <code>setX(x)</code> into getter
@@ -61,17 +71,34 @@ import java.util.Set;
*/
public class PropertySemanticProcessor extends SemanticProcessor {
private static class FieldPropertyInfo {
+ final ClassDeclaration clazz;
final String name;
MethodDeclaration getter;
MethodDeclaration setter;
- String getterField;
- String setterField;
+ VariableDeclaration getterField;
+ VariableDeclaration setterField;
+ VariableDeclaration field;
+ SimpleIdentifier fieldName;
+ List<SimpleIdentifier> fieldAssignmentReferences;
- public FieldPropertyInfo(String name) {
+ public FieldPropertyInfo(ClassDeclaration clazz, String name) {
+ this.clazz = clazz;
this.name = name;
}
}
+ public static final String KEY_ORIGINAL_PARAMETER = "original-formal-parameter";
+
+ private static int getNumConstructors(ClassDeclaration classDeclaration) {
+ int numConstructors = 0;
+ for (ClassMember member : classDeclaration.getMembers()) {
+ if (member instanceof ConstructorDeclaration) {
+ numConstructors++;
+ }
+ }
+ return numConstructors;
+ }
+
private static boolean hasPrefix(String name, String prefix) {
// should start with prefix
if (!name.startsWith(prefix)) {
@@ -87,16 +114,148 @@ public class PropertySemanticProcessor extends SemanticProcessor {
return Character.isUpperCase(nextChar);
}
+ private static boolean isValidFieldProperty(FieldPropertyInfo property) {
+ // we need getter
+ VariableDeclaration getField = property.getterField;
+ if (property.getter == null || getField == null) {
+ return false;
+ }
+ // setter should be valid
+ VariableDeclaration setField = property.setterField;
+ if (property.setter != null && setField == null) {
+ return false;
+ }
+ // if there are both getter and setter, their fields should be the same
+ if (getField != null && setField != null && getField != setField) {
+ return false;
+ }
+ property.field = getField;
+ property.fieldName = property.field.getName();
+ // OK
+ return true;
+ }
+
private static boolean isValidSetterType(TypeName type) {
return type.getName().getName().equals("void");
}
+ /**
+ * Checks if {@link CompilationUnit} declares field with name "onlyBasicGettersSetters", removes
+ * it and return {@code true}.
+ */
+ private static boolean onlyBasicGettersSetters(CompilationUnit unit) {
+ final AtomicBoolean result = new AtomicBoolean();
+ unit.accept(new RecursiveASTVisitor<Void>() {
+ @Override
+ public Void visitVariableDeclaration(VariableDeclaration node) {
+ if (node.getName().getName().equals("_onlyBasicGettersSetters")) {
+ FieldDeclaration fieldDeclaration = (FieldDeclaration) node.getParent().getParent();
+ ClassDeclaration clazz = (ClassDeclaration) fieldDeclaration.getParent();
+ clazz.getMembers().remove(fieldDeclaration);
+ result.set(true);
+ }
+ return null;
+ }
+ });
+ return result.get();
+ }
+
+ /**
+ * Removes the given {@link ClassMember} from its parent {@link ClassDeclaration}.
+ */
+ private static void removeClassMember(ClassMember member) {
+ ClassDeclaration clazz = (ClassDeclaration) member.getParent();
+ List<ClassMember> members = clazz.getMembers();
+ members.remove(member);
+ }
+
public PropertySemanticProcessor(Context context) {
super(context);
}
+ public void convertToField(FieldPropertyInfo property) {
+ MethodDeclaration getter = property.getter;
+ MethodDeclaration setter = property.setter;
+ VariableDeclaration field = property.field;
+ SimpleIdentifier fieldName = property.fieldName;
+ int numConstructors = getNumConstructors(property.clazz);
+ // analyze field assignments
+ boolean canBeFinal;
+ {
+ getAssignmentReferencesInConstructors(property);
+ // analyze constructor assignments
+ List<SimpleIdentifier> references = property.fieldAssignmentReferences;
+ canBeFinal = references != null && references.size() == numConstructors;
+ // if there are no setter and we cannot make the field final, then keep getter/setter
+ if (setter == null && !canBeFinal) {
+ return;
+ }
+ // convert to "this.property" in constructors
+ if (references != null) {
+ convertToFieldFormalInitializers(property, references);
+ }
+ }
+ // update field
+ {
+ context.renameIdentifier(fieldName, property.name);
+ // mark "final" if no writes
+ boolean readOnly = isReadOnlyField(fieldName);
+ if (readOnly) {
+ ((VariableDeclarationList) field.getParent()).setKeyword(token(Keyword.FINAL));
+ if (canBeFinal && numConstructors != 0) {
+ field.setInitializer(null);
+ }
+ }
+ }
+ // remove getter, update field
+ if (getter != null) {
+ removeClassMember(getter);
+ }
+ // remove setter
+ if (setter != null) {
+ removeClassMember(setter);
+ }
+ // now these are field references
+ {
+ IBinding fieldBinding = context.getNodeBinding(fieldName);
+ replaceMethodReferencesWithFieldBindings(getter, fieldBinding);
+ replaceMethodReferencesWithFieldBindings(setter, fieldBinding);
+ }
+ }
+
+ public void convertToFields(CompilationUnit unit) {
+ final Set<IBinding> overriddenMethods = getOverriddenMethods(unit);
+ unit.accept(new RecursiveASTVisitor<Void>() {
+ @Override
+ public Void visitClassDeclaration(ClassDeclaration node) {
+ List<FieldPropertyInfo> properties = getFieldProperties(node);
+ removeOverriddenProperties(overriddenMethods, properties);
+ for (FieldPropertyInfo property : properties) {
+ if (!isValidFieldProperty(property)) {
+ continue;
+ }
+ convertToField(property);
+ }
+ return null;
+ }
+ });
+ }
+
@Override
- public void process(final CompilationUnit unit) {
+ public void process(CompilationUnit unit) {
+ convertGettersSetters(unit);
+ if (onlyBasicGettersSetters(unit)) {
+ return;
+ }
+ convertToFields(unit);
+ }
+
+ /**
+ * Converts every <code>getX()</code> into <code>get x</code> and <code>setX(v)</code> into
+ * <code>set x(v)</code> with corresponding replacement of {@link MethodInvocation} into
+ * {@link PropertyAccess} in references.
+ */
+ private void convertGettersSetters(CompilationUnit unit) {
unit.accept(new RecursiveASTVisitor<Void>() {
@Override
public Void visitFieldDeclaration(FieldDeclaration node) {
@@ -182,197 +341,321 @@ public class PropertySemanticProcessor extends SemanticProcessor {
return super.visitMethodDeclaration(node);
}
});
- // remember all overridden and overriding methods
- final Set<IMethodBinding> ignoredMethods = Sets.newHashSet();
- unit.accept(new RecursiveASTVisitor<Void>() {
- @Override
- public Void visitMethodDeclaration(MethodDeclaration node) {
- IMethodBinding binding = (IMethodBinding) context.getNodeBinding(node);
- if (binding != null) {
- IMethodBinding superBinding = Bindings.findOverriddenMethod(binding, true);
- if (superBinding != null) {
- ignoredMethods.add(binding);
- ignoredMethods.add(superBinding);
+ }
+
+ private void convertToFieldFormalInitializers(FieldPropertyInfo property,
+ List<SimpleIdentifier> references) {
+ for (SimpleIdentifier reference : references) {
+ // prepare constructor
+ ConstructorDeclaration constructor = reference.getAncestor(ConstructorDeclaration.class);
+ // convert "formal parameter" into "field initializing formal parameter"
+ List<FormalParameter> parameters = constructor.getParameters().getParameters();
+ for (FormalParameter parameter : parameters) {
+ if (parameter instanceof SimpleFormalParameter) {
+ SimpleFormalParameter simpleParameter = (SimpleFormalParameter) parameter;
+ SimpleIdentifier parameterName = simpleParameter.getIdentifier();
+ if (parameterName.getName().equals(property.name)) {
+ FormalParameter ffp = fieldFormalParameter(null, null, parameterName);
+ ffp.setProperty(KEY_ORIGINAL_PARAMETER, parameter);
+ replaceNode(simpleParameter, ffp);
+ break;
}
}
- return null;
}
- });
- // try to convert properties into fields
- unit.accept(new RecursiveASTVisitor<Void>() {
- private final Map<String, FieldPropertyInfo> properties = Maps.newHashMap();
+ // remove assignment statement
+ Statement statement = (Statement) reference.getParent().getParent().getParent();
+ List<Statement> statements = removeBlockStatement(statement);
+ if (statements.isEmpty()) {
+ constructor.setBody(emptyFunctionBody());
+ }
+ }
+ }
- @Override
- public Void visitClassDeclaration(ClassDeclaration node) {
- properties.clear();
- super.visitClassDeclaration(node);
- // simplify field properties
- for (FieldPropertyInfo property : properties.values()) {
- MethodDeclaration getter = property.getter;
- MethodDeclaration setter = property.setter;
- // no getter or not field
- if (getter == null || property.getterField == null) {
- continue;
- }
- // setter is not field
- if (setter != null && !StringUtils.equals(property.getterField, property.setterField)) {
- continue;
- }
- // remove getter, update field
- if (getter != null) {
- ClassDeclaration clazz = (ClassDeclaration) getter.getParent();
- List<ClassMember> members = clazz.getMembers();
- members.remove(getter);
- for (ClassMember member : members) {
- if (member instanceof FieldDeclaration) {
- FieldDeclaration fieldDeclaration = (FieldDeclaration) member;
- List<VariableDeclaration> variables = fieldDeclaration.getFields().getVariables();
- for (VariableDeclaration field : variables) {
- SimpleIdentifier fieldName = field.getName();
- if (fieldName.getName().equals(property.getterField)) {
- context.renameIdentifier(fieldName, property.name);
- // mark "final" is no writes
- {
- boolean readOnly = true;
- List<SimpleIdentifier> references = context.getReferences(fieldName);
- for (SimpleIdentifier reference : references) {
- readOnly &= !reference.inSetterContext();
- }
- if (readOnly) {
- fieldDeclaration.getFields().setKeyword(token(Keyword.FINAL));
- }
- }
- // now these are field references
- {
- IBinding fieldBinding = context.getNodeBinding(fieldName);
- replaceMethodReferencesWithFieldBindings(getter, fieldBinding);
- replaceMethodReferencesWithFieldBindings(setter, fieldBinding);
- }
- // done
- break;
- }
- }
- }
- }
- }
- // remove setter
- if (setter != null) {
- ClassDeclaration clazz = (ClassDeclaration) setter.getParent();
- List<ClassMember> members = clazz.getMembers();
- members.remove(setter);
- }
+ /**
+ * If the given {@link SimpleIdentifier} is the field reference and:
+ * <ul>
+ * <li>The field is assigned only in constructors.</li>
+ * <li>The field is assigned only once in each constructor.</li>
+ * <li>The assignment looks like <code>this.name = name;</code> statement.</li>
+ * </ul>
+ * Then returns all references of the field in these simple assignments. Otherwise returns
+ * {@code null}.
+ */
+ private void getAssignmentReferencesInConstructors(FieldPropertyInfo property) {
+ Set<ConstructorDeclaration> constructorsWithAssignments = Sets.newHashSet();
+ List<SimpleIdentifier> assignReferences = Lists.newArrayList();
+ List<SimpleIdentifier> references = context.getReferences(property.fieldName);
+ for (SimpleIdentifier reference : references) {
+ // not in setter context
+ if (!reference.inSetterContext()) {
+ continue;
+ }
+ // should be in constructor
+ ConstructorDeclaration constructor = reference.getAncestor(ConstructorDeclaration.class);
+ if (constructor == null) {
+ if (reference.getAncestor(MethodDeclaration.class) == property.setter) {
+ continue;
}
- // done
- return null;
+ return;
+ }
+ // may be more than one assignment
+ if (constructorsWithAssignments.contains(constructor)) {
+ return;
+ }
+ constructorsWithAssignments.add(constructor);
+ // should be "this.name"
+ if (!(reference.getParent() instanceof PropertyAccess)) {
+ return;
+ }
+ PropertyAccess propertyAccess = (PropertyAccess) reference.getParent();
+ if (!(propertyAccess.getTarget() instanceof ThisExpression)) {
+ return;
+ }
+ // should be assignment
+ if (!(propertyAccess.getParent() instanceof AssignmentExpression)) {
+ return;
+ }
+ AssignmentExpression assignment = (AssignmentExpression) propertyAccess.getParent();
+ // should be "this.name = _name"
+ if (assignment.getRightHandSide() instanceof SimpleIdentifier) {
+ SimpleIdentifier right = (SimpleIdentifier) assignment.getRightHandSide();
+ if (isReferencedInSuperConstructorInvocation(right)) {
+ continue;
+ }
+ String rightName = right.getName();
+ String leftName = reference.getName();
+ if (!leftName.equals("_" + rightName)) {
+ return;
+ }
+ } else {
+ return;
+ }
+ // should be simple, just in statement
+ if (!(assignment.getParent() instanceof ExpressionStatement)) {
+ return;
}
+ // should be just "="
+ if (assignment.getOperator().getType() != TokenType.EQ) {
+ return;
+ }
+ // OK, valid assignment reference
+ assignReferences.add(reference);
+ }
+ // OK, no other assignments found
+ property.fieldAssignmentReferences = assignReferences;
+ }
+ private List<FieldPropertyInfo> getFieldProperties(final ClassDeclaration classDeclaration) {
+ final Map<String, FieldPropertyInfo> properties = Maps.newHashMap();
+ classDeclaration.accept(new RecursiveASTVisitor<Void>() {
@Override
public Void visitMethodDeclaration(MethodDeclaration node) {
- IMethodBinding binding = (IMethodBinding) context.getNodeBinding(node);
- // don't remove method if it overrides
- if (binding == null) {
- return null;
- }
- if (ignoredMethods.contains(binding)) {
+ // we need getter or setter
+ if (!node.isGetter() && !node.isSetter()) {
return null;
}
- ITypeBinding declaringClass = binding.getDeclaringClass();
+ // prepare property
+ String propertyName = node.getName().getName();
+ FieldPropertyInfo property = getProperty(propertyName);
// getter
if (node.isGetter()) {
- String name = node.getName().getName();
- FieldPropertyInfo property = getProperty(name);
- property.getter = node;
- if (node.getBody() instanceof ExpressionFunctionBody) {
- ExpressionFunctionBody body = (ExpressionFunctionBody) node.getBody();
- Expression expression = body.getExpression();
- if (expression instanceof SimpleIdentifier) {
- SimpleIdentifier identifier = (SimpleIdentifier) expression;
- // may be not a local field
- IBinding identifierBinding = context.getNodeBinding(identifier);
- if (identifierBinding instanceof IVariableBinding) {
- IVariableBinding fieldBinding = (IVariableBinding) identifierBinding;
- if (fieldBinding.getDeclaringClass() != declaringClass) {
- return null;
- }
- } else {
- return null;
- }
- // OK, remember the field
- property.getterField = identifier.getName();
- }
- }
+ processGetter(property, node);
}
// setter
if (node.isSetter()) {
- String name = node.getName().getName();
- FieldPropertyInfo property = getProperty(name);
- property.setter = node;
- // block body
- if (!(node.getBody() instanceof BlockFunctionBody)) {
- return null;
- }
- // single statement
- BlockFunctionBody body = (BlockFunctionBody) node.getBody();
- List<Statement> statements = body.getBlock().getStatements();
- if (statements.size() != 1) {
- return null;
- }
- Statement statement = statements.get(0);
- // prepare expression
- if (!(statement instanceof ExpressionStatement)) {
- return null;
- }
- Expression expression = ((ExpressionStatement) statement).getExpression();
- // should be assignment
- if (!(expression instanceof AssignmentExpression)) {
- return null;
- }
- AssignmentExpression assignment = (AssignmentExpression) expression;
- // simple assignment
- if (assignment.getOperator().getType() != TokenType.EQ) {
- return null;
- }
- // RHS should be just parameter name
- Expression rhs = assignment.getRightHandSide();
- if (!(rhs instanceof SimpleIdentifier)) {
- return null;
- }
- SimpleIdentifier rhsName = (SimpleIdentifier) rhs;
- String parameterName = ((SimpleFormalParameter) node.getParameters().getParameters().get(
- 0)).getIdentifier().getName();
- if (!rhsName.getName().equals(parameterName)) {
- return null;
- }
- // LHS
- Expression lhs = assignment.getLeftHandSide();
- if (lhs instanceof PropertyAccess) {
- PropertyAccess access = (PropertyAccess) lhs;
- if (access.getTarget() instanceof ThisExpression) {
- property.setterField = access.getPropertyName().getName();
- }
- }
+ processSetter(property, node);
}
+ // done
return null;
}
private FieldPropertyInfo getProperty(String name) {
FieldPropertyInfo property = properties.get(name);
if (property == null) {
- property = new FieldPropertyInfo(name);
+ property = new FieldPropertyInfo(classDeclaration, name);
properties.put(name, property);
}
return property;
}
- private void replaceMethodReferencesWithFieldBindings(MethodDeclaration method,
- IBinding fieldBinding) {
- if (method == null) {
+ private boolean isFieldWithPropertyName(String fieldName, String propertyName) {
+ String prefix = "_" + propertyName;
+ if (!fieldName.startsWith(prefix)) {
+ return false;
+ }
+ String rest = fieldName.substring(prefix.length());
+ if (!StringUtils.isNumericSpace(rest)) {
+ return false;
+ }
+ return true;
+ }
+
+ private void processGetter(FieldPropertyInfo property, MethodDeclaration node) {
+ property.getter = node;
+ if (node.getBody() instanceof ExpressionFunctionBody) {
+ ExpressionFunctionBody body = (ExpressionFunctionBody) node.getBody();
+ Expression expression = body.getExpression();
+ if (expression instanceof SimpleIdentifier) {
+ SimpleIdentifier identifier = (SimpleIdentifier) expression;
+ String fieldName = identifier.getName();
+ // may be not a local field
+ VariableDeclaration field = classDeclaration.getField(fieldName);
+ if (field == null) {
+ return;
+ }
+ // maybe field doesn't have the same name as the property
+ if (!isFieldWithPropertyName(fieldName, property.name)) {
+ return;
+ }
+ // OK, remember the field
+ property.getterField = field;
+ }
+ }
+ }
+
+ private void processSetter(FieldPropertyInfo property, MethodDeclaration node) {
+ property.setter = node;
+ // block body
+ if (!(node.getBody() instanceof BlockFunctionBody)) {
+ return;
+ }
+ // single statement
+ BlockFunctionBody body = (BlockFunctionBody) node.getBody();
+ List<Statement> statements = body.getBlock().getStatements();
+ if (statements.size() != 1) {
+ return;
+ }
+ Statement statement = statements.get(0);
+ // prepare expression
+ if (!(statement instanceof ExpressionStatement)) {
+ return;
+ }
+ Expression expression = ((ExpressionStatement) statement).getExpression();
+ // should be assignment
+ if (!(expression instanceof AssignmentExpression)) {
+ return;
+ }
+ AssignmentExpression assignment = (AssignmentExpression) expression;
+ // simple assignment
+ if (assignment.getOperator().getType() != TokenType.EQ) {
+ return;
+ }
+ // RHS should be just parameter name
+ Expression rhs = assignment.getRightHandSide();
+ if (!(rhs instanceof SimpleIdentifier)) {
+ return;
+ }
+ SimpleIdentifier rhsName = (SimpleIdentifier) rhs;
+ List<FormalParameter> parameters = node.getParameters().getParameters();
+ String parameterName = ((SimpleFormalParameter) parameters.get(0)).getIdentifier().getName();
+ if (!rhsName.getName().equals(parameterName)) {
return;
}
- for (SimpleIdentifier reference : context.getReferences(method.getName())) {
- context.putReference(reference, fieldBinding, null);
+ // LHS
+ Expression lhs = assignment.getLeftHandSide();
+ if (lhs instanceof PropertyAccess) {
+ PropertyAccess access = (PropertyAccess) lhs;
+ if (access.getTarget() instanceof ThisExpression) {
+ String fieldName = access.getPropertyName().getName();
+ // may be not a local field
+ VariableDeclaration field = classDeclaration.getField(fieldName);
+ if (field == null) {
+ return;
+ }
+ // may be field has not the same name as the property
+ if (!isFieldWithPropertyName(fieldName, property.name)) {
+ return;
+ }
+ // OK, remember the field
+ property.setterField = field;
+ }
}
}
});
+ return Lists.newArrayList(properties.values());
+ }
+
+ private Set<IBinding> getOverriddenMethods(CompilationUnit unit) {
+ final Set<IBinding> overriddenMethods = Sets.newHashSet();
+ unit.accept(new RecursiveASTVisitor<Void>() {
+ @Override
+ public Void visitMethodDeclaration(MethodDeclaration node) {
+ IMethodBinding binding = (IMethodBinding) context.getNodeBinding(node);
+ if (binding != null) {
+ IMethodBinding superBinding = Bindings.findOverriddenMethod(binding, true);
+ if (superBinding != null) {
+ overriddenMethods.add(superBinding);
+ }
+ }
+ return null;
+ }
+ });
+ return overriddenMethods;
+ }
+
+ private boolean isOverridden(Set<IBinding> overriddenMethods, MethodDeclaration method) {
+ if (method == null) {
+ return false;
+ }
+ IBinding binding = context.getNodeBinding(method);
+ return overriddenMethods.contains(binding);
+ }
+
+ private boolean isReadOnlyField(SimpleIdentifier fieldName) {
+ List<SimpleIdentifier> references = context.getReferences(fieldName);
+ for (SimpleIdentifier reference : references) {
+ if (reference.inSetterContext()) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * @return {@code true} if the given parameter is referenced
+ * {@link RedirectingConstructorInvocation} or {@link SuperConstructorInvocation}.
+ */
+ private boolean isReferencedInSuperConstructorInvocation(SimpleIdentifier parameter) {
+ List<SimpleIdentifier> references = context.getReferences(parameter);
+ for (SimpleIdentifier reference : references) {
+ if (reference.getAncestor(SuperConstructorInvocation.class) != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ /**
+ * Removes given {@link Statement} from its {@link Block}.
+ */
+ private NodeList<Statement> removeBlockStatement(Statement statement) {
+ NodeList<Statement> statements = ((Block) statement.getParent()).getStatements();
+ statements.remove(statement);
+ context.clearNodes(statement);
+ return statements;
+ }
+
+ private void removeOverriddenProperties(Set<IBinding> overriddenMethods,
+ List<FieldPropertyInfo> properties) {
+ for (Iterator<FieldPropertyInfo> I = properties.iterator(); I.hasNext();) {
+ FieldPropertyInfo property = I.next();
+ if (isOverridden(overriddenMethods, property.getter)
+ || isOverridden(overriddenMethods, property.setter)) {
+ I.remove();
+ }
+ }
+ }
+
+ private void replaceMethodReferencesWithFieldBindings(MethodDeclaration method,
+ IBinding fieldBinding) {
+ if (method == null) {
+ return;
+ }
+ SimpleIdentifier name = method.getName();
+ List<SimpleIdentifier> references = context.getReferences(name);
+ references = ImmutableList.copyOf(references);
+ for (SimpleIdentifier reference : references) {
+ context.putReference(reference, fieldBinding, null);
+ }
}
}

Powered by Google App Engine
This is Rietveld 408576698