Index: core extension/org/eclipse/jdt/internal/corext/dom/ASTNodes.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.ui/core extension/org/eclipse/jdt/internal/corext/dom/ASTNodes.java,v
retrieving revision 1.43
diff -u -r1.43 ASTNodes.java
--- core extension/org/eclipse/jdt/internal/corext/dom/ASTNodes.java 20 Aug 2003 15:46:51 -0000 1.43
+++ core extension/org/eclipse/jdt/internal/corext/dom/ASTNodes.java 24 Aug 2003 16:18:06 -0000
@@ -18,7 +18,6 @@
import java.util.List;
import org.eclipse.core.runtime.CoreException;
-
import org.eclipse.jdt.core.ISourceRange;
import org.eclipse.jdt.core.ToolFactory;
import org.eclipse.jdt.core.compiler.IProblem;
@@ -27,43 +26,78 @@
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
+import org.eclipse.jdt.core.dom.ArrayAccess;
import org.eclipse.jdt.core.dom.ArrayCreation;
import org.eclipse.jdt.core.dom.ArrayInitializer;
import org.eclipse.jdt.core.dom.ArrayType;
+import org.eclipse.jdt.core.dom.AssertStatement;
import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
+import org.eclipse.jdt.core.dom.BooleanLiteral;
+import org.eclipse.jdt.core.dom.BreakStatement;
+import org.eclipse.jdt.core.dom.CastExpression;
+import org.eclipse.jdt.core.dom.CatchClause;
+import org.eclipse.jdt.core.dom.CharacterLiteral;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.CompilationUnit;
+import org.eclipse.jdt.core.dom.ConditionalExpression;
import org.eclipse.jdt.core.dom.ConstructorInvocation;
+import org.eclipse.jdt.core.dom.ContinueStatement;
+import org.eclipse.jdt.core.dom.DoStatement;
+import org.eclipse.jdt.core.dom.EmptyStatement;
import org.eclipse.jdt.core.dom.Expression;
+import org.eclipse.jdt.core.dom.ExpressionStatement;
+import org.eclipse.jdt.core.dom.FieldAccess;
import org.eclipse.jdt.core.dom.FieldDeclaration;
import org.eclipse.jdt.core.dom.ForStatement;
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 org.eclipse.jdt.core.dom.IfStatement;
+import org.eclipse.jdt.core.dom.ImportDeclaration;
import org.eclipse.jdt.core.dom.InfixExpression;
+import org.eclipse.jdt.core.dom.Initializer;
+import org.eclipse.jdt.core.dom.InstanceofExpression;
+import org.eclipse.jdt.core.dom.Javadoc;
+import org.eclipse.jdt.core.dom.LabeledStatement;
import org.eclipse.jdt.core.dom.Message;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.NullLiteral;
+import org.eclipse.jdt.core.dom.NumberLiteral;
+import org.eclipse.jdt.core.dom.PackageDeclaration;
+import org.eclipse.jdt.core.dom.ParenthesizedExpression;
+import org.eclipse.jdt.core.dom.PostfixExpression;
+import org.eclipse.jdt.core.dom.PrefixExpression;
import org.eclipse.jdt.core.dom.PrimitiveType;
import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.dom.SimpleType;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.Statement;
+import org.eclipse.jdt.core.dom.StringLiteral;
import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
+import org.eclipse.jdt.core.dom.SuperFieldAccess;
import org.eclipse.jdt.core.dom.SuperMethodInvocation;
+import org.eclipse.jdt.core.dom.SwitchCase;
import org.eclipse.jdt.core.dom.SwitchStatement;
+import org.eclipse.jdt.core.dom.SynchronizedStatement;
+import org.eclipse.jdt.core.dom.ThisExpression;
+import org.eclipse.jdt.core.dom.ThrowStatement;
import org.eclipse.jdt.core.dom.TryStatement;
import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.TypeDeclarationStatement;
+import org.eclipse.jdt.core.dom.TypeLiteral;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
-
+import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.internal.corext.Assert;
import org.eclipse.jdt.internal.corext.SourceRange;
import org.eclipse.jdt.internal.corext.textmanipulation.TextBuffer;
@@ -321,6 +355,11 @@
type == ASTNode.NUMBER_LITERAL || type == ASTNode.STRING_LITERAL || type == ASTNode.TYPE_LITERAL;
}
+ public static boolean isInvocation(Expression expression) {
+ int type= expression.getNodeType();
+ return type == ASTNode.METHOD_INVOCATION || type == ASTNode.SUPER_METHOD_INVOCATION;
+ }
+
public static String getTypeName(Type type) {
final StringBuffer buffer= new StringBuffer();
ASTVisitor visitor= new ASTVisitor() {
@@ -697,4 +736,638 @@
name.accept(visitor);
return result[0];
}
+
+ public static void acceptNodes(List nodes, ASTVisitor visitor) {
+ for (Iterator iter = nodes.iterator(); iter.hasNext();) {
+ ASTNode element = (ASTNode) iter.next();
+ element.accept(visitor);
+ }
+ }
+
+ private static class ChildSubstituteVisitor extends ASTVisitor {
+ private ASTNode fSource;
+ private ASTNode fReplacement;
+ public ChildSubstituteVisitor(ASTNode source, ASTNode replacement) {
+ fSource= source;
+ fReplacement= replacement;
+ }
+ public boolean visit(AnonymousClassDeclaration node) {
+ List bodies= node.bodyDeclarations();
+ int index= bodies.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ bodies.set(index, (BodyDeclaration)fReplacement);
+ }
+ else {
+ bodies.remove(index);
+ }
+ }
+ return false;
+ }
+ public boolean visit(ArrayAccess node) {
+ if(node.getArray() == fSource) {
+ node.setArray((Expression)fReplacement);
+ }
+ else if(node.getIndex() == fSource) {
+ node.setIndex((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(ArrayCreation node) {
+ if(node.getType() == fSource) {
+ node.setType((ArrayType)fReplacement);
+ }
+ else if(node.getInitializer() == fSource) {
+ node.setInitializer((ArrayInitializer)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(ArrayInitializer node) {
+ List expressions= node.expressions();
+ int index= expressions.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ expressions.set(index, (Expression)fReplacement);
+ }
+ else {
+ expressions.remove(index);
+ }
+ }
+ return false;
+ }
+ public boolean visit(ArrayType node) {
+ if(node.getComponentType() == fSource) {
+ node.setComponentType((Type)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(AssertStatement node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else if(node.getMessage() == fSource) {
+ node.setMessage((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(Assignment node) {
+ if(node.getLeftHandSide() == fSource) {
+ node.setLeftHandSide((Expression)fReplacement);
+ }
+ else if(node.getRightHandSide() == fSource) {
+ node.setRightHandSide((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(Block node) {
+ List statements= node.statements();
+ int index= statements.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ statements.set(index, (Statement)fReplacement);
+ }
+ else {
+ statements.remove(index);
+ }
+ }
+ return false;
+ }
+ public boolean visit(BooleanLiteral node) {
+ return false;
+ }
+ public boolean visit(BreakStatement node) {
+ if(node.getLabel() == fSource) {
+ node.setLabel((SimpleName)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(CastExpression node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else if(node.getType() == fSource) {
+ node.setType((Type)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(CatchClause node) {
+ if(node.getBody() == fSource) {
+ node.setBody((Block)fReplacement);
+ }
+ else if(node.getException() == fSource) {
+ node.setException((SingleVariableDeclaration)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(CharacterLiteral node) {
+ return false;
+ }
+ public boolean visit(ClassInstanceCreation node) {
+ if(node.getAnonymousClassDeclaration() == fSource) {
+ node.setAnonymousClassDeclaration((AnonymousClassDeclaration)fReplacement);
+ }
+ else if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else if(node.getName() == fSource) {
+ node.setName((Name)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(CompilationUnit node) {
+ return false;
+ }
+ public boolean visit(ConditionalExpression node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else if(node.getThenExpression() == fSource) {
+ node.setThenExpression((Expression)fReplacement);
+ }
+ else if(node.getElseExpression() == fSource) {
+ node.setElseExpression((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(ConstructorInvocation node) {
+ List arguments= node.arguments();
+ int index= arguments.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ arguments.set(index, (Expression)fReplacement);
+ }
+ else {
+ arguments.remove(index);
+ }
+ }
+ return false;
+ }
+ public boolean visit(ContinueStatement node) {
+ if(node.getLabel() == fSource) {
+ node.setLabel((SimpleName)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(DoStatement node) {
+ if(node.getBody() == fSource) {
+ node.setBody((Statement)fReplacement);
+ }
+ else if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(EmptyStatement node) {
+ return false;
+ }
+ public boolean visit(ExpressionStatement node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(FieldAccess node) {
+ if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ else if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(FieldDeclaration node) {
+ if(node.getType() == fSource) {
+ node.setType((Type)fReplacement);
+ }
+ else {
+ List fragments= node.fragments();
+ int index= fragments.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ fragments.set(index, (VariableDeclarationFragment)fReplacement);
+ }
+ else {
+ fragments.remove(index);
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(ForStatement node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else if(node.getBody() == fSource) {
+ node.setBody((Statement)fReplacement);
+ }
+ else {
+ List initializers= node.initializers();
+ int index= initializers.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ initializers.set(index, (Expression)fReplacement);
+ }
+ else {
+ initializers.remove(index);
+ }
+ }
+ else {
+ List updaters= node.updaters();
+ index= updaters.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ updaters.set(index, (Expression)fReplacement);
+ }
+ else {
+ updaters.remove(index);
+ }
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(IfStatement node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else if(node.getThenStatement() == fSource) {
+ node.setThenStatement((Statement)fReplacement);
+ }
+ else if(node.getElseStatement() == fSource) {
+ node.setElseStatement((Statement)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(ImportDeclaration node) {
+ if(node.getName() == fSource) {
+ node.setName((Name)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(InfixExpression node) {
+ if(node.getLeftOperand() == fSource) {
+ node.setLeftOperand((Expression)fReplacement);
+ }
+ else if(node.getRightOperand() == fSource) {
+ node.setRightOperand((Expression)fReplacement);
+ }
+ else if(node.hasExtendedOperands()) {
+ List extendedOperands= node.extendedOperands();
+ int index= extendedOperands.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ extendedOperands.set(index, (Expression)fReplacement);
+ }
+ else {
+ extendedOperands.remove(index);
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(Initializer node) {
+ if(node.getBody() == fSource) {
+ node.setBody((Block)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(Javadoc node) {
+ return false;
+ }
+ public boolean visit(LabeledStatement node) {
+ if(node.getLabel() == fSource) {
+ node.setLabel((SimpleName)fReplacement);
+ }
+ else if(node.getBody() == fSource) {
+ node.setBody((Block)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(MethodDeclaration node) {
+ if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ else if(node.getReturnType() == fSource) {
+ node.setReturnType((Type)fReplacement);
+ }
+ else if(node.getBody() == fSource) {
+ node.setBody((Block)fReplacement);
+ }
+ else {
+ List parameters= node.parameters();
+ int index= parameters.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ parameters.set(index, (SingleVariableDeclaration)fReplacement);
+ }
+ else {
+ parameters.remove(index);
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(MethodInvocation node) {
+ if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ else if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else {
+ List arguments= node.arguments();
+ int index= arguments.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ arguments.set(index, (Expression)fReplacement);
+ }
+ else {
+ arguments.remove(index);
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(NullLiteral node) {
+ return false;
+ }
+ public boolean visit(NumberLiteral node) {
+ return false;
+ }
+ public boolean visit(PackageDeclaration node) {
+ if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(ParenthesizedExpression node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(PostfixExpression node) {
+ if(node.getOperand() == fSource) {
+ node.setOperand((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(PrefixExpression node) {
+ if(node.getOperand() == fSource) {
+ node.setOperand((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(PrimitiveType node) {
+ return false;
+ }
+ public boolean visit(QualifiedName node) {
+ if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(ReturnStatement node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(SimpleName node) {
+ return false;
+ }
+ public boolean visit(SimpleType node) {
+ if(node.getName() == fSource) {
+ node.setName((Name)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(SingleVariableDeclaration node) {
+ if(node.getInitializer() == fSource) {
+ node.setInitializer((Expression)fReplacement);
+ }
+ else if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ else if(node.getType() == fSource) {
+ node.setType((Type)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(StringLiteral node) {
+ return false;
+ }
+ public boolean visit(SuperConstructorInvocation node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else {
+ List arguments= node.arguments();
+ int index= arguments.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ arguments.set(index, (Expression)fReplacement);
+ }
+ else {
+ arguments.remove(index);
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(SuperFieldAccess node) {
+ if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ else if(node.getQualifier() == fSource) {
+ node.setQualifier((Name)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(SuperMethodInvocation node) {
+ if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ else if(node.getQualifier() == fSource) {
+ node.setQualifier((Name)fReplacement);
+ }
+ else {
+ List arguments= node.arguments();
+ int index= arguments.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ arguments.set(index, (Expression)fReplacement);
+ }
+ else {
+ arguments.remove(index);
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(SwitchCase node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(SwitchStatement node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(SynchronizedStatement node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else if(node.getBody() == fSource) {
+ node.setBody((Block)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(ThisExpression node) {
+ return false;
+ }
+ public boolean visit(ThrowStatement node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(TryStatement node) {
+ if(node.getBody() == fSource) {
+ node.setBody((Block)fReplacement);
+ }
+ else if(node.getFinally() == fSource) {
+ node.setFinally((Block)fReplacement);
+ }
+ else {
+ List catchClauses= node.catchClauses();
+ int index= catchClauses.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ catchClauses.set(index, (CatchClause)fReplacement);
+ }
+ else {
+ catchClauses.remove(index);
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(TypeDeclaration node) {
+ if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ else if(node.getSuperclass() == fSource) {
+ node.setSuperclass((Name)fReplacement);
+ }
+ else {
+ List bodyDeclarations= node.bodyDeclarations();
+ int index= bodyDeclarations.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ bodyDeclarations.set(index, (BodyDeclaration)fReplacement);
+ }
+ else {
+ bodyDeclarations.remove(index);
+ }
+ }
+ else {
+ List superInterfaces= node.superInterfaces();
+ index= superInterfaces.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ superInterfaces.set(index, (Name)fReplacement);
+ }
+ else {
+ superInterfaces.remove(index);
+ }
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(TypeDeclarationStatement node) {
+ if(node.getTypeDeclaration() == fSource) {
+ node.setTypeDeclaration((TypeDeclaration)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(TypeLiteral node) {
+ if(node.getType() == fSource) {
+ node.setType((Type)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(VariableDeclarationExpression node) {
+ if(node.getType() == fSource) {
+ node.setType((Type)fReplacement);
+ }
+ else {
+ List fragments= node.fragments();
+ int index= fragments.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ fragments.set(index, (VariableDeclarationFragment)fReplacement);
+ }
+ else {
+ fragments.remove(index);
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(VariableDeclarationFragment node) {
+ if(node.getName() == fSource) {
+ node.setName((SimpleName)fReplacement);
+ }
+ else if(node.getInitializer() == fSource) {
+ node.setInitializer((Expression)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(VariableDeclarationStatement node) {
+ if(node.getType() == fSource) {
+ node.setType((Type)fReplacement);
+ }
+ else {
+ List fragments= node.fragments();
+ int index= fragments.indexOf(fSource);
+ if(index != -1) {
+ if(fReplacement != null) {
+ fragments.set(index, (VariableDeclarationFragment)fReplacement);
+ }
+ else {
+ fragments.remove(index);
+ }
+ }
+ }
+ return false;
+ }
+ public boolean visit(WhileStatement node) {
+ if(node.getExpression() == fSource) {
+ node.setExpression((Expression)fReplacement);
+ }
+ else if(node.getBody() == fSource) {
+ node.setBody((Statement)fReplacement);
+ }
+ return false;
+ }
+ public boolean visit(InstanceofExpression node) {
+ if(node.getLeftOperand() == fSource) {
+ node.setLeftOperand((Expression)fReplacement);
+ }
+ else if(node.getRightOperand() == fSource) {
+ node.setRightOperand((Type)fReplacement);
+ }
+ return false;
+ }
+ }
+
+ public static void substitute(ASTNode source, ASTNode replacement) {
+ ASTNode parent= source.getParent();
+ parent.accept(new ChildSubstituteVisitor(source, replacement));
+ }
}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/CallContext.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/CallContext.java,v
retrieving revision 1.7
diff -u -r1.7 CallContext.java
--- core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/CallContext.java 10 Mar 2003 21:56:47 -0000 1.7
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/CallContext.java 24 Aug 2003 16:18:08 -0000
@@ -10,22 +10,21 @@
*******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.code;
+import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.internal.corext.codemanipulation.ImportEdit;
import org.eclipse.jdt.internal.corext.dom.CodeScopeBuilder;
public class CallContext {
- public String[] arguments;
- public String receiver;
+ public ASTNode[] arguments;
+ public ASTNode receiver;
public boolean receiverIsStatic;
public CodeScopeBuilder.Scope scope;
- public int callMode;
public ImportEdit importer;
- public CallContext(CodeScopeBuilder.Scope s, int cm, ImportEdit i) {
+ public CallContext(CodeScopeBuilder.Scope s, ImportEdit i) {
super();
scope= s;
- callMode= cm;
importer= i;
}
}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/CallInliner.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/CallInliner.java,v
retrieving revision 1.30
diff -u -r1.30 CallInliner.java
--- core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/CallInliner.java 20 Aug 2003 15:46:51 -0000 1.30
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/CallInliner.java 24 Aug 2003 16:18:09 -0000
@@ -17,51 +17,55 @@
import java.util.Iterator;
import java.util.List;
-import org.eclipse.core.runtime.CoreException;
-
import org.eclipse.core.resources.IFile;
-
+import org.eclipse.core.runtime.CoreException;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
+import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
+import org.eclipse.jdt.core.dom.Assignment;
import org.eclipse.jdt.core.dom.Block;
import org.eclipse.jdt.core.dom.BodyDeclaration;
import org.eclipse.jdt.core.dom.CastExpression;
-import org.eclipse.jdt.core.dom.DoStatement;
+import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldAccess;
-import org.eclipse.jdt.core.dom.ForStatement;
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 org.eclipse.jdt.core.dom.IfStatement;
import org.eclipse.jdt.core.dom.Initializer;
import org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
import org.eclipse.jdt.core.dom.ParenthesizedExpression;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.SuperFieldAccess;
+import org.eclipse.jdt.core.dom.SuperMethodInvocation;
+import org.eclipse.jdt.core.dom.SwitchStatement;
import org.eclipse.jdt.core.dom.ThisExpression;
+import org.eclipse.jdt.core.dom.Type;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
-import org.eclipse.jdt.core.dom.WhileStatement;
-
import org.eclipse.jdt.internal.corext.Assert;
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings;
import org.eclipse.jdt.internal.corext.codemanipulation.ImportEdit;
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.ASTRewrite;
-import org.eclipse.jdt.internal.corext.dom.TypeBindingVisitor;
import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.dom.CodeScopeBuilder;
+import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor;
import org.eclipse.jdt.internal.corext.dom.LocalVariableIndex;
import org.eclipse.jdt.internal.corext.dom.Selection;
+import org.eclipse.jdt.internal.corext.dom.TypeBindingVisitor;
import org.eclipse.jdt.internal.corext.dom.TypeRules;
import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatus;
import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowContext;
@@ -85,14 +89,28 @@
private Expression fInvocation;
private ASTRewrite fRewriter;
- private List fStatements;
- private int fInsertionIndex;
- private boolean fNeedsStatement;
- private ASTNode fTargetNode;
private FlowContext fFlowContext;
private FlowInfo fFlowInfo;
private CodeScopeBuilder.Scope fInvocationScope;
-
+
+ /**
+ * Statements inserted before inlined one.
+ */
+ private List fStatementsBefore;
+ /**
+ * Statements inserted instead of inlined one.
+ */
+ private List fStatementReplacement;
+ /**
+ * Statements inserted after inlined one.
+ */
+ private List fStatementsAfter;
+ /**
+ * Expression inserted instead of method invocation.
+ */
+ private Expression fInvocationReplacement;
+ private boolean fRemoveInvocation;
+
private class InlineEvaluator extends HierarchicalASTVisitor {
private ParameterData fFormalArgument;
private boolean fResult;
@@ -206,10 +224,6 @@
return fImportEdit;
}
- public ASTNode getTargetNode() {
- return fTargetNode;
- }
-
public RefactoringStatus initialize(BodyDeclaration declaration) {
fBodyDeclaration= declaration;
RefactoringStatus result= new RefactoringStatus();
@@ -226,23 +240,14 @@
return result;
}
- public RefactoringStatus initialize(Expression invocation) {
- RefactoringStatus result= new RefactoringStatus();
+ public void initialize(Expression invocation) {
fInvocation= invocation;
fRewriter= new ASTRewrite(ASTNodes.getParent(fInvocation, ASTNode.BLOCK));
- ASTNode parent= fInvocation.getParent();
- int nodeType1= parent.getNodeType();
- if (nodeType1 == ASTNode.EXPRESSION_STATEMENT || nodeType1 == ASTNode.RETURN_STATEMENT) {
- fTargetNode= parent;
- } else {
- fTargetNode= fInvocation;
- }
- return result;
}
private void flowAnalysis() {
- fInvocationScope= fRootScope.findScope(fTargetNode.getStartPosition(), fTargetNode.getLength());
- fInvocationScope.setCursor(fTargetNode.getStartPosition());
+ fInvocationScope= fRootScope.findScope(fInvocation.getStartPosition(), fInvocation.getLength());
+ fInvocationScope.setCursor(fInvocation.getStartPosition());
fFlowContext= new FlowContext(0, fNumberOfLocals + 1);
fFlowContext.setConsiderAccessMode(true);
fFlowContext.setComputeMode(FlowContext.ARGUMENTS);
@@ -258,192 +263,483 @@
Assert.isTrue(false, "Should not happen"); //$NON-NLS-1$
}
}
-
+
+ public static class ReturnCollector extends ASTVisitor {
+ private List fResult= new ArrayList();
+ public ReturnCollector() {
+ }
+ public List getResult() {
+ return fResult;
+ }
+ public boolean visit(ReturnStatement node) {
+ fResult.add(node);
+ return false;
+ }
+ public boolean visit(AnonymousClassDeclaration node) {
+ return false;
+ }
+ public boolean visit(TypeDeclaration node) {
+ return false;
+ }
+ }
+
+ /**
+ * The singleton class is used to reset code positions of visited nodes.
+ *
+ * This is a good candidate for moving into ASTNodes class.
+ */
+ public static class PositionClearer extends GenericVisitor {
+ private static final PositionClearer instance= new PositionClearer();
+ private PositionClearer() {
+ }
+ public static PositionClearer getInstance() {
+ return instance;
+ }
+ protected boolean visitNode(ASTNode node) {
+ node.setSourceRange(-1, 0);
+ return true;
+ }
+ }
+
public TextEdit perform() throws CoreException {
flowAnalysis();
- int callType= fTargetNode.getNodeType();
- CallContext context= new CallContext(fInvocationScope, callType, fImportEdit);
+ CallContext context= new CallContext(fInvocationScope, fImportEdit);
List locals= new ArrayList(3);
-
- computeRealArguments(context, locals);
+ context.arguments= computeRealArguments(locals);
computeReceiver(context, locals);
-
- String[] blocks= fSourceProvider.getCodeBlocks(context);
- initializeInsertionPoint(fSourceProvider.getNumberOfStatements() + locals.size());
- addNewLocals(locals);
- replaceCall(callType, blocks);
+ List statements= fSourceProvider.getCodeStatements(context);
+ SourceProvider.replaceAST(fInvocation.getAST(), statements);
+ addNewLocals(statements, locals);
+
+ processReturnStatements(statements);
+ replaceCall();
MultiTextEdit result= new MultiTextEdit();
- fRewriter.rewriteNode(fBuffer, result, null);
+ fRewriter.rewriteNode(fBuffer, result);
fRewriter.removeModifications();
return result;
}
- private void computeRealArguments(CallContext context, List locals) {
+ /**
+ * Adds new locals to the top of statements list.
+ *
+ * @param statements list of statements
+ * @param locals list of new locals
+ */
+ private void addNewLocals(List statements, List locals) {
+ int index= 0;
+ for (Iterator it= locals.iterator(); it.hasNext(); ) {
+ statements.add(index++, it.next());
+ }
+ }
+
+ private static ITypeBinding resolveInvocationTypeBinding(ASTNode invocation) {
+ if(invocation instanceof MethodInvocation) {
+ return ((MethodInvocation)invocation).resolveTypeBinding();
+ }
+ else if(invocation instanceof SuperMethodInvocation) {
+ return ((SuperMethodInvocation)invocation).resolveTypeBinding();
+ }
+ return null;
+ }
+
+ private ASTNode[] computeRealArguments(List locals) {
+ AST ast= fInvocation.getAST();
List arguments= Invocations.getArguments(fInvocation);
- String[] realArguments= new String[arguments.size()];
+ ASTNode[] realArguments = new ASTNode[arguments.size()];
for (int i= 0; i < arguments.size(); i++) {
Expression expression= (Expression)arguments.get(i);
ParameterData parameter= fSourceProvider.getParameterData(i);
if (canInline(expression, parameter)) {
- realArguments[i] = getContent(expression);
+ realArguments[i]= ASTNode.copySubtree(expression.getAST(), expression);
// fixes bug #35905
if(expression instanceof CastExpression) {
- realArguments[i] = "(" + realArguments[i] + ")"; //$NON-NLS-1$ //$NON-NLS-2$
+ ParenthesizedExpression pe= ast.newParenthesizedExpression();
+ pe.setExpression((Expression)realArguments[i]);
+ realArguments[i]= pe;
}
} else {
String name= fInvocationScope.createName(parameter.getName(), true);
- realArguments[i]= name;
- locals.add(createLocalDeclaration(
- parameter.getTypeBinding(), name,
- (Expression)fRewriter.createCopy(expression)));
+ realArguments[i]= fInvocation.getAST().newSimpleName(name);
+ locals.add(createVariableDeclaration(
+ parameter.getType().resolveBinding(), name,
+ (Expression)ASTNode.copySubtree(expression.getAST(), expression)));
}
}
- context.arguments= realArguments;
+ return realArguments;
}
-
+
private void computeReceiver(CallContext context, List locals) {
Expression receiver= Invocations.getExpression(fInvocation);
if (receiver == null)
return;
- final boolean isName= receiver instanceof Name;
- if (isName)
- context.receiverIsStatic= ((Name)receiver).resolveBinding() instanceof ITypeBinding;
- if (ASTNodes.isLiteral(receiver) || isName) {
- context.receiver= fBuffer.getContent(receiver.getStartPosition(), receiver.getLength());
+ if (ASTNodes.isLiteral(receiver) || receiver instanceof Name) {
+ context.receiver= receiver;
return;
}
switch(fSourceProvider.getReceiversToBeUpdated()) {
case 0:
- // Make sure we evaluate the current receiver. Best is to assign to
- // local.
- locals.add(createLocalDeclaration(
+ // Make sure we evaluate the current receiver. Best is to assign to local.
+ locals.add(createVariableDeclaration(
receiver.resolveTypeBinding(),
fInvocationScope.createName("r", true), //$NON-NLS-1$
(Expression)fRewriter.createCopy(receiver)));
return;
case 1:
- context.receiver= fBuffer.getContent(receiver.getStartPosition(), receiver.getLength());
+ context.receiver= receiver;
return;
default:
String local= fInvocationScope.createName("r", true); //$NON-NLS-1$
- locals.add(createLocalDeclaration(
- receiver.resolveTypeBinding(),
- local,
- (Expression)fRewriter.createCopy(receiver)));
- context.receiver= local;
+ VariableDeclarationStatement receiverDeclaration=
+ createVariableDeclaration(
+ receiver.resolveTypeBinding(),
+ local,
+ (Expression)fRewriter.createCopy(receiver));
+ locals.add(receiverDeclaration);
+ context.receiver= fInvocation.getAST().newSimpleName(local);
return;
}
}
- private void addNewLocals(List locals) {
- for (Iterator iter= locals.iterator(); iter.hasNext();) {
- ASTNode element= (ASTNode)iter.next();
- fRewriter.markAsInserted(element);
- fStatements.add(fInsertionIndex++, element);
- }
- }
-
- private void replaceCall(int callType, String[] blocks) throws CoreException {
- // Inline empty body
- if (blocks.length == 0) {
- if (fNeedsStatement) {
- fRewriter.markAsReplaced(fTargetNode, fTargetNode.getAST().newEmptyStatement());
- } else {
- fRewriter.markAsRemoved(fTargetNode);
+ /**
+ * The method analyses return statements and fills fStatementsAfter,
+ * fStatementsBefore, fStatementReplacement and fInvocationReplacement
+ * member variables with statements that will be used during inlining.
+ *
+ * @param statements list of method statements to process
+ */
+ private void processReturnStatements(List statements) {
+
+ List returnStatements= null;
+ ReturnCollector returnCollector= new ReturnCollector();
+ ASTNodes.acceptNodes(statements, returnCollector);
+ returnStatements= returnCollector.getResult();
+
+ AST ast= fInvocation.getAST();
+ ASTNode invocationParent= fInvocation.getParent();
+ int invocationParentType= invocationParent.getNodeType();
+
+ if (!fSourceProvider.hasReturnValue()) {
+ // in case when inlined method returns void ...
+ for (Iterator iter= returnStatements.iterator(); iter.hasNext();) {
+ ReturnStatement rs= (ReturnStatement) iter.next();
+ ASTNode parent= rs.getParent();
+ // if parent of return statement is a control statements(if, for, do, while)
+ // then empty statement is required in place of the return
+ if (parent != null && isControlStatement(parent)) {
+ substitute(statements, rs, ast.newEmptyStatement());
+ } else {
+ // otheriwse it is safe to remove return statement completely
+ substitute(statements, rs, null);
+ }
}
- } else {
- ASTNode node= null;
- for (int i= 0; i < blocks.length - 1; i++) {
- node= fRewriter.createPlaceholder(blocks[i], ASTRewrite.STATEMENT);
- fRewriter.markAsInserted(node);
- fStatements.add(fInsertionIndex++, node);
- }
- String block= blocks[blocks.length - 1];
- // We can inline a call where the declaration is a function and the call itself
- // is a statement. In this case we have to create a temporary variable if the
- // returned expression must be evaluated.
- if (callType == ASTNode.EXPRESSION_STATEMENT && fSourceProvider.hasReturnValue()) {
- if (fSourceProvider.mustEvaluateReturnedExpression()) {
- if (fSourceProvider.returnValueNeedsLocalVariable()) {
- node= createLocalDeclaration(
- fSourceProvider.getReturnType(),
- fInvocationScope.createName(fSourceProvider.getMethodName(), true),
- (Expression)fRewriter.createPlaceholder(block, ASTRewrite.EXPRESSION));
+ if(invocationParentType == ASTNode.EXPRESSION_STATEMENT) {
+ fStatementReplacement= statements;
+ }
+ else {
+ fStatementsBefore= statements;
+ fRemoveInvocation= true;
+ }
+ } else if(invocationParentType == ASTNode.RETURN_STATEMENT) {
+ fStatementReplacement= statements;
+ } else if (invocationParentType == ASTNode.EXPRESSION_STATEMENT) {
+ for (Iterator iter= returnStatements.iterator(); iter.hasNext();) {
+ ReturnStatement rs= (ReturnStatement) iter.next();
+ Expression returnExpression= rs.getExpression();
+ // check if return expression must be evaluated
+ if (ASTNodes.isLiteral(returnExpression) || returnExpression instanceof Name) {
+ // completely remove return and its expression
+ substitute(statements, rs, null);
+ } else {
+ // check if return expression needs a local variable
+ if (ASTNodes.isInvocation(returnExpression) || returnExpression instanceof ClassInstanceCreation) {
+ // substitute parent expression with return expression
+ substitute(statements, rs,
+ ast.newExpressionStatement((Expression)ASTNode.copySubtree(ast, rs.getExpression())));
} else {
- node= fTargetNode.getAST().newExpressionStatement(
- (Expression)fRewriter.createPlaceholder(block, ASTRewrite.EXPRESSION));
+ // create a local variable to keep result of return expression
+ VariableDeclarationStatement node= createVariableDeclaration(
+ fSourceProvider.getReturnType().resolveBinding(),
+ fInvocationScope.createName(fSourceProvider.getMethodName(), true),
+ (Expression)ASTNode.copySubtree(ast, returnExpression));
+ substitute(statements, rs, node);
}
- } else {
- node= null;
}
- } else if (fTargetNode instanceof Expression) {
- node= fRewriter.createPlaceholder(block, ASTRewrite.EXPRESSION);
-
+ }
+ fStatementReplacement= statements;
+ } else if (invocationParent instanceof Expression) {
+ for (Iterator iter= returnStatements.iterator(); iter.hasNext();) {
+ ReturnStatement rs= (ReturnStatement) iter.next();
+ Expression returnExpression= rs.getExpression();
+ Expression node= (Expression)ASTNode.copySubtree(ast, returnExpression);
// fixes bug #24941
- if(needsExplicitCast()) {
- AST ast= node.getAST();
+ if (needsExplicitCast(rs)) {
CastExpression castExpression= ast.newCastExpression();
- ITypeBinding returnType= fSourceProvider.getReturnType();
- fImportEdit.addImport(returnType);
- castExpression.setType(ASTNodeFactory.newType(ast, returnType, false));
- castExpression.setExpression((Expression)node);
+ Type returnType= fSourceProvider.getReturnType();
+ fImportEdit.addImport(returnType.resolveBinding());
+ castExpression.setType((Type)ASTNode.copySubtree(ast, returnType));
+ castExpression.setExpression(node);
node= castExpression;
}
-
- if (needsParenthesis()) {
- ParenthesizedExpression pExp= fTargetNode.getAST().newParenthesizedExpression();
- pExp.setExpression((Expression)node);
- node= pExp;
+ if (needsParenthesis(rs)) {
+ ParenthesizedExpression pe= ast.newParenthesizedExpression();
+ pe.setExpression(node);
+ node= pe;
+ }
+ if (returnStatements.size() == 1) {
+ fInvocationReplacement= node;
+ fStatementsBefore= statements;
+ statements.remove(rs);
+ }
+ else {
+ substitute(statements, rs, ast.newExpressionStatement(node));
+ }
+ }
+ } else if(invocationParentType == ASTNode.VARIABLE_DECLARATION_FRAGMENT) {
+ if(returnStatements.size() > 1) {
+ // method invocation in variable declaration fragment can be used only as initializer
+ VariableDeclarationFragment fragment= (VariableDeclarationFragment)invocationParent;
+ fInvocationReplacement= createDefaultInitializer(invocationParent.getAST(),
+ resolveInvocationTypeBinding(fInvocation));
+ Expression variable= fragment.getName();
+ substituteReturnsWithAssignments(variable, returnStatements, statements);
+ fStatementsAfter= statements;
+ }
+ else { // returnStatements.size() == 1
+ ReturnStatement rs= (ReturnStatement) returnStatements.get(0);
+ Expression returnExpression= rs.getExpression();
+ fInvocationReplacement= (Expression)ASTNode.copySubtree(ast, returnExpression);
+ substitute(statements, rs, null);
+ fStatementsBefore= statements;
+ }
+ } else {
+ // case example:
+ // for(inlineMe(); i < 10; i++);
+ if(returnStatements.size() > 1) {
+ // if method has multiple returns then temporary variable will be created and all
+ // returns will be substituted with assignments to it.
+ VariableDeclarationStatement variableStatement= createVariableDeclaration(
+ fSourceProvider.getReturnType().resolveBinding(),
+ fInvocationScope.createName("temp", true), //$NON-NLS-1$
+ createDefaultInitializer(ast, fSourceProvider.getReturnType().resolveBinding()));
+ statements.add(0, variableStatement);
+ VariableDeclarationFragment fragment= (VariableDeclarationFragment)variableStatement.fragments().get(0);
+ Expression variable= fragment.getName();
+ substituteReturnsWithAssignments(variable, returnStatements, statements);
+ fStatementsBefore= statements;
+ fRemoveInvocation= true;
+ }
+ else { // returnStatements.size() == 1
+ ReturnStatement rs= (ReturnStatement) returnStatements.get(0);
+ Expression returnExpression= rs.getExpression();
+ // check if return expression must be evaluated
+ if (ASTNodes.isLiteral(returnExpression) || returnExpression instanceof Name) {
+ substitute(statements, rs, null);
+ fStatementsBefore= statements;
+ fRemoveInvocation= true;
+ }
+ else {
+ fInvocationReplacement= (Expression)ASTNode.copySubtree(ast, returnExpression);
+ substitute(statements, rs, null);
+ fStatementsBefore= statements;
}
- } else {
- node= fRewriter.createPlaceholder(block, ASTRewrite.STATEMENT);
}
-
- // Now replace the target node with the source node
- if (node != null) {
- if (fTargetNode == null) {
- fRewriter.markAsInserted(node);
- fStatements.add(fInsertionIndex++, node);
- } else {
- fRewriter.markAsReplaced(fTargetNode, node);
+ }
+ }
+
+ /**
+ * The helper method substitutes return statements with assignments
+ * expressions wrapped inside expression statements.
+ *
+ * @param variable AST node representing variable to assign to
+ * @param returnStatements list of return statements
+ * @param statements list of original statements
+ */
+ private void substituteReturnsWithAssignments(Expression variable, List returnStatements, List statements) {
+ AST ast= variable.getAST();
+ for (Iterator iter= returnStatements.iterator(); iter.hasNext();) {
+ ReturnStatement rs= (ReturnStatement) iter.next();
+ Expression returnExpression= rs.getExpression();
+ ASTNode parent= rs.getParent();
+ // every return is substituted with an assignement to the variable.
+ // prior to that method initializeTarget has replaced variable
+ // initializer with a default value (0 or null).
+ Assignment assignment= ast.newAssignment();
+ assignment.setLeftHandSide((Expression)ASTNode.copySubtree(ast, variable));
+ assignment.setRightHandSide((Expression)ASTNode.copySubtree(ast, returnExpression));
+ substitute(statements, rs, ast.newExpressionStatement(assignment));
+ }
+ }
+
+ /**
+ * @param ast
+ * @param variableBinding
+ * @return
+ */
+ private Expression createDefaultInitializer(AST ast, ITypeBinding typeBinding) {
+ if(typeBinding.isPrimitive()) {
+ if(typeBinding.getName().equals(PrimitiveType.BOOLEAN.toString())) {
+ return ast.newBooleanLiteral(false);
+ }
+ else {
+ return ast.newNumberLiteral();
+ }
+ }
+ return ast.newNullLiteral();
+ }
+
+ /**
+ * Helper method for substitution of one node with another in a list of statements.
+ *
+ * Special processing is required for top level nodes since their parents are null.
+ *
+ * @param statements list of original statements
+ * @param source source node, must exist in the hierarchy of statements
+ * @param replacement node replacing the source one
+ */
+ private static void substitute(List statements, ASTNode source, ASTNode replacement) {
+ if(source.getParent() == null) {
+ if(replacement == null) {
+ statements.remove(source);
+ }
+ else {
+ int index= statements.indexOf(source);
+ statements.set(index, replacement);
+ }
+ }
+ else {
+ ASTNodes.substitute(source, replacement);
+ }
+ }
+
+ /**
+ * The method does actual code modificiations.
+ *
+ * It uses only fStatementsBefore, fStatementsAfter, fStatementReplacement
+ * and fInvocationReplacement member variables prepared by other methods.
+ *
+ * The method adds empty statements and blocks where it is needed.
+ */
+ private void replaceCall() throws CoreException {
+
+ AST ast= fInvocation.getAST();
+ Statement invocationStatement= (Statement)ASTNodes.getParent(fInvocation, Statement.class);
+ Statement parentStatement= (Statement)invocationStatement.getParent();
+
+ int numberOfStatements= 0;
+ if (fStatementsBefore != null) {
+ numberOfStatements+= fStatementsBefore.size();
+ ASTNodes.acceptNodes(fStatementsBefore, PositionClearer.getInstance());
+ }
+ if (fStatementsAfter != null) {
+ numberOfStatements+= fStatementsAfter.size();
+ ASTNodes.acceptNodes(fStatementsAfter, PositionClearer.getInstance());
+ }
+ if (fStatementReplacement != null) {
+ numberOfStatements+= fStatementReplacement.size();
+ ASTNodes.acceptNodes(fStatementReplacement, PositionClearer.getInstance());
+ }
+ else {
+ numberOfStatements++;
+ }
+ if(fInvocationReplacement != null) {
+ fInvocationReplacement.accept(PositionClearer.getInstance());
+ }
+
+ List parentStatements= null;
+ if (parentStatement.getNodeType() == ASTNode.BLOCK) {
+ parentStatements= ((Block)parentStatement).statements();
+ }
+ else if (parentStatement.getNodeType() == ASTNode.SWITCH_STATEMENT) {
+ parentStatements= ((SwitchStatement)parentStatement).statements();
+ }
+ else if (numberOfStatements > 1) {
+ Block block= ast.newBlock();
+ List blockStatements= block.statements();
+ if (fStatementsBefore != null) {
+ blockStatements.addAll(fStatementsBefore);
+ }
+ if (fStatementReplacement != null) {
+ blockStatements.addAll(fStatementReplacement);
+ }
+ else if (fInvocationReplacement != null) {
+ // modifying original AST(not the copy!)
+ ASTNodes.substitute(fInvocation, fInvocationReplacement);
+ blockStatements.add(ASTNode.copySubtree(ast, invocationStatement));
+ // restoring original AST
+ ASTNodes.substitute(fInvocationReplacement, fInvocation);
+ }
+ if (fStatementsAfter!= null) {
+ blockStatements.addAll(fStatementsAfter);
+ }
+ fStatementReplacement= new ArrayList();
+ fStatementReplacement.add(block);
+ }
+ else if (numberOfStatements == 0) {
+ if (isControlStatement(parentStatement)/* && fInvocationReplacement == null*/) {
+ fStatementReplacement.add(ast.newEmptyStatement());
+ }
+ }
+ if(fStatementReplacement == null) {
+ if (fInvocationReplacement != null) {
+ // statement replacement has higher priority over invocation replacement
+ // so if fStatementReplacement is not null it will be used instead of
+ // fInvocationReplacement.
+ fRewriter.markAsReplaced(fInvocation, fInvocationReplacement);
+ }
+ else if(fRemoveInvocation) {
+ fRewriter.markAsRemoved(fInvocation);
+ }
+ }
+
+ if (parentStatements != null) {
+ int index= parentStatements.indexOf(invocationStatement);
+ if(fStatementsBefore != null) {
+ for (int i= 0; i < fStatementsBefore.size(); i++) {
+ parentStatements.add(index++, fStatementsBefore.get(i));
+ fRewriter.markAsInserted((ASTNode)fStatementsBefore.get(i), true);
}
- } else {
- if (fTargetNode != null) {
- fRewriter.markAsRemoved(fTargetNode);
+ }
+ if(fStatementReplacement != null) {
+ fRewriter.markAsReplaced(invocationStatement, parentStatements,
+ (ASTNode[])fStatementReplacement.toArray(new ASTNode[fStatementReplacement.size()]));
+ }
+ if(fStatementsAfter != null) {
+ index++;
+ for (int i= 0; i < fStatementsAfter.size(); i++) {
+ parentStatements.add(index++, fStatementsAfter.get(i));
+ fRewriter.markAsInserted((ASTNode)fStatementsAfter.get(i), true);
}
}
}
+ else if(fStatementReplacement != null) {
+ fRewriter.markAsReplaced(invocationStatement, (ASTNode)fStatementReplacement.get(0));
+ }
}
/**
* @return true
if explicit cast is needed otherwise false
* @throws JavaModelException
*/
- private boolean needsExplicitCast() {
+ private boolean needsExplicitCast(ReturnStatement rs) {
// if the return type of the method is the same as the type of the
// returned expression then we don't need an explicit cast.
- if (fSourceProvider.returnTypeMatchesReturnExpressions())
- return false;
- ASTNode parent= fTargetNode.getParent();
+ if (returnTypeMatchesReturnExpressions(rs))
+ return false;
+ ASTNode parent= fInvocation.getParent();
int nodeType= parent.getNodeType();
if (nodeType == ASTNode.METHOD_INVOCATION) {
MethodInvocation methodInvocation= (MethodInvocation)parent;
- if(methodInvocation.getExpression() == fTargetNode)
+ if(methodInvocation.getExpression() == fInvocation)
return false;
IMethodBinding method= methodInvocation.resolveMethodBinding();
ITypeBinding[] parameters= method.getParameterTypes();
int argumentIndex= methodInvocation.arguments().indexOf(fInvocation);
- List returnExprs= fSourceProvider.getReturnExpressions();
- // it is infered that only methods consisting of a single
- // return statement can be inlined as parameters in other
- // method invocations
- if (returnExprs.size() != 1)
- return false;
- parameters[argumentIndex]= ((Expression)returnExprs.get(0)).resolveTypeBinding();
-
+ parameters[argumentIndex]= (ITypeBinding)fSourceProvider.resolveTypeBinding(
+ rs.getExpression().getStartPosition());
+
ITypeBinding type= ASTNodes.getReceiverTypeBinding(methodInvocation);
TypeBindingVisitor visitor= new AmbiguousMethodAnalyzer(method, parameters);
if(!visitor.visit(type)) {
@@ -463,20 +759,33 @@
return false;
}
- private boolean needsParenthesis() {
- if (!fSourceProvider.needsReturnedExpressionParenthesis())
+ public boolean returnTypeMatchesReturnExpressions(ReturnStatement returnStatement) {
+ ITypeBinding returnType= fSourceProvider.getReturnType().resolveBinding();
+ Expression expression= returnStatement.getExpression();
+ if (expression != null) {
+ if (!Bindings.equals(returnType, expression.resolveTypeBinding()))
+ return false;
+ }
+ return true;
+ }
+
+ private boolean needsParenthesis(ReturnStatement rs) {
+ if (!ASTNodes.needsParentheses(rs.getExpression()))
return false;
- ASTNode parent= fTargetNode.getParent();
+ ASTNode parent= fInvocation.getParent();
int type= parent.getNodeType();
return type == ASTNode.METHOD_INVOCATION || (parent instanceof Expression && type != ASTNode.ASSIGNMENT);
}
-
- private VariableDeclarationStatement createLocalDeclaration(ITypeBinding type, String name, Expression initializer) {
- String typeName= fImportEdit.addImport(type);
- VariableDeclarationStatement decl= (VariableDeclarationStatement)ASTNodeFactory.newStatement(
- fInvocation.getAST(), typeName + " " + name + ";"); //$NON-NLS-1$ //$NON-NLS-2$
- ((VariableDeclarationFragment)decl.fragments().get(0)).setInitializer(initializer);
- return decl;
+
+ private VariableDeclarationStatement createVariableDeclaration(ITypeBinding typeBinding, String name, Expression initializer) {
+ AST ast= initializer.getAST();
+ String typeName= fImportEdit.addImport(typeBinding);
+ VariableDeclarationFragment fragment= ast.newVariableDeclarationFragment();
+ fragment.setName(ast.newSimpleName(name));
+ fragment.setInitializer(initializer);
+ VariableDeclarationStatement result= ast.newVariableDeclarationStatement(fragment);
+ result.setType(ASTNodeFactory.newType(ast, typeBinding.getName()));
+ return result;
}
private boolean canInline(Expression actualParameter, ParameterData formalParameter) {
@@ -484,69 +793,11 @@
actualParameter.accept(evaluator);
return evaluator.getResult();
}
-
- private void initializeInsertionPoint(int nos) {
- fStatements= null;
- fInsertionIndex= -1;
- fNeedsStatement= false;
- ASTNode parentStatement= ASTNodes.getParent(fInvocation, Statement.class);
- ASTNode container= parentStatement.getParent();
- int type= container.getNodeType();
- if (type == ASTNode.BLOCK) {
- fStatements= ((Block)container).statements();
- fInsertionIndex= fStatements.indexOf(parentStatement);
- } else if (isControlStatement(container)) {
- fNeedsStatement= true;
- if (nos > 1) {
- Block block= fInvocation.getAST().newBlock();
- fStatements= block.statements();
- fInsertionIndex= 0;
- Statement currentStatement= null;
- switch(type) {
- case ASTNode.FOR_STATEMENT:
- currentStatement= ((ForStatement)container).getBody();
- break;
- case ASTNode.WHILE_STATEMENT:
- currentStatement= ((WhileStatement)container).getBody();
- break;
- case ASTNode.DO_STATEMENT:
- currentStatement= ((DoStatement)container).getBody();
- break;
- case ASTNode.IF_STATEMENT:
- IfStatement node= (IfStatement)container;
- Statement thenPart= node.getThenStatement();
- if (fTargetNode == thenPart || ASTNodes.isParent(fTargetNode, thenPart)) {
- currentStatement= thenPart;
- } else {
- currentStatement= node.getElseStatement();
- }
- break;
- }
- Assert.isNotNull(currentStatement);
- // The method to be inlined is not the body of the control statement.
- if (currentStatement != fTargetNode) {
- ASTNode copy= fRewriter.createCopy(currentStatement);
- fStatements.add(copy);
- } else {
- // We can't replace a copy with something else. So we
- // have to insert all statements to be inlined.
- fTargetNode= null;
- }
- fRewriter.markAsReplaced(currentStatement, block);
- }
- }
- // We only insert one new statement or we delete the existing call.
- // So there is no need to have an insertion index.
- }
-
- private String getContent(ASTNode node) {
- return fBuffer.getContent(node.getStartPosition(), node.getLength());
- }
private static IFile getFile(ICompilationUnit cu) throws CoreException {
return (IFile)WorkingCopyUtil.getOriginal(cu).getResource();
}
-
+
private boolean isControlStatement(ASTNode node) {
int type= node.getNodeType();
return type == ASTNode.IF_STATEMENT || type == ASTNode.FOR_STATEMENT ||
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/InlineMethodRefactoring.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/InlineMethodRefactoring.java,v
retrieving revision 1.33
diff -u -r1.33 InlineMethodRefactoring.java
--- core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/InlineMethodRefactoring.java 20 Aug 2003 15:46:51 -0000 1.33
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/InlineMethodRefactoring.java 24 Aug 2003 16:18:09 -0000
@@ -207,10 +207,10 @@
Expression[] invocations= fTargetProvider.getInvocations(body, new SubProgressMonitor(pm, 1));
for (int i= 0; i < invocations.length; i++) {
Expression invocation= invocations[i];
- result.merge(inliner.initialize(invocation));
+ inliner.initialize(invocation);
if (result.hasFatalError())
break;
- RefactoringStatus targetStatus= invocationAnalyzer.perform(unit, invocation, inliner.getTargetNode(), fTargetProvider.getStatusSeverity());
+ RefactoringStatus targetStatus= invocationAnalyzer.perform(unit, invocation, fTargetProvider.getStatusSeverity());
result.merge(targetStatus);
if (result.hasFatalError())
break;
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/InvocationAnalyzer.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/InvocationAnalyzer.java,v
retrieving revision 1.5
diff -u -r1.5 InvocationAnalyzer.java
--- core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/InvocationAnalyzer.java 18 Jun 2003 15:24:47 -0000 1.5
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/InvocationAnalyzer.java 24 Aug 2003 16:18:10 -0000
@@ -10,14 +10,21 @@
*******************************************************************************/
package org.eclipse.jdt.internal.corext.refactoring.code;
+import java.util.Iterator;
+import java.util.List;
+
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.BodyDeclaration;
+import org.eclipse.jdt.core.dom.DoStatement;
import org.eclipse.jdt.core.dom.Expression;
import org.eclipse.jdt.core.dom.FieldDeclaration;
+import org.eclipse.jdt.core.dom.ForStatement;
import org.eclipse.jdt.core.dom.MethodInvocation;
+import org.eclipse.jdt.core.dom.Statement;
import org.eclipse.jdt.core.dom.VariableDeclaration;
import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
+import org.eclipse.jdt.core.dom.WhileStatement;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
@@ -41,12 +48,20 @@
fSourceProvider= sourceProvider;
}
- public RefactoringStatus perform(ICompilationUnit unit, ASTNode invocation, ASTNode targetNode, int severity) {
+ public RefactoringStatus perform(ICompilationUnit unit, ASTNode invocation, int severity) {
RefactoringStatus result= new RefactoringStatus();
fCUnit= unit;
fInvocation= invocation;
fSeverity= severity;
- fTargetNode= targetNode;
+
+ ASTNode parent= fInvocation.getParent();
+ int nodeType= parent.getNodeType();
+ if (nodeType == ASTNode.EXPRESSION_STATEMENT || nodeType == ASTNode.RETURN_STATEMENT) {
+ fTargetNode= parent;
+ } else {
+ fTargetNode= fInvocation;
+ }
+
checkIfUsedInDeclaration(result);
if (result.getSeverity() >= fSeverity)
return result;
@@ -73,28 +88,60 @@
JavaStatusContext.create(fSourceProvider.getCompilationUnit(), fSourceProvider.getDeclaration()),
RefactoringStatusCodes.INLINE_METHOD_EXECUTION_FLOW);
}
- } else if (nodeType == ASTNode.METHOD_INVOCATION) {
- ASTNode parent= fTargetNode.getParent();
- if (parent.getNodeType() == ASTNode.ASSIGNMENT || isSingleDeclaration(parent)) {
- // this is ok
- } else if (isMultiDeclarationFragment(parent)) {
- if (!fSourceProvider.isSimpleFunction()) {
- addEntry(result,
- RefactoringCoreMessages.getString("InvocationAnalyzer.multiDeclaration"), //$NON-NLS-1$
- RefactoringStatusCodes.INLINE_METHOD_INITIALIZER_IN_FRAGEMENT);
- }
- } else if (fSourceProvider.getNumberOfStatements() > 1 ) {
+ } else if (isUsedInLoop()) {
+ if (fSourceProvider.getNumberOfStatements() > 1 ) {
+ // TODO: The message is not correct for this situation
addEntry(result,
RefactoringCoreMessages.getString("CallInliner.simple_functions"), //$NON-NLS-1$
RefactoringStatusCodes.INLINE_METHOD_ONLY_SIMPLE_FUNCTIONS);
- } else if (!fSourceProvider.isSimpleFunction()) {
- addEntry(result,
- RefactoringCoreMessages.getString("CallInliner.execution_flow"), //$NON-NLS-1$
- fSeverity,
- JavaStatusContext.create(fSourceProvider.getCompilationUnit(), fSourceProvider.getDeclaration()),
- RefactoringStatusCodes.INLINE_METHOD_EXECUTION_FLOW);
}
+// } else if (nodeType == ASTNode.METHOD_INVOCATION) {
+// ASTNode parent= fTargetNode.getParent();
+// if (parent.getNodeType() == ASTNode.ASSIGNMENT || isSingleDeclaration(parent)) {
+// // this is ok
+// } else if (isMultiDeclarationFragment(parent)) {
+// if (!fSourceProvider.isSimpleFunction()) {
+// addEntry(result,
+// RefactoringCoreMessages.getString("InvocationAnalyzer.multiDeclaration"), //$NON-NLS-1$
+// RefactoringStatusCodes.INLINE_METHOD_INITIALIZER_IN_FRAGEMENT);
+// }
+// } else if (fSourceProvider.getNumberOfStatements() > 1 ) {
+// addEntry(result,
+// RefactoringCoreMessages.getString("CallInliner.simple_functions"), //$NON-NLS-1$
+// RefactoringStatusCodes.INLINE_METHOD_ONLY_SIMPLE_FUNCTIONS);
+// } else if (!fSourceProvider.isSimpleFunction()) {
+// addEntry(result,
+// RefactoringCoreMessages.getString("CallInliner.execution_flow"), //$NON-NLS-1$
+// fSeverity,
+// JavaStatusContext.create(fSourceProvider.getCompilationUnit(), fSourceProvider.getDeclaration()),
+// RefactoringStatusCodes.INLINE_METHOD_EXECUTION_FLOW);
+// }
}
+ }
+
+ /**
+ * @return true
is inlined invocation is used inside a one of loop statements.
+ */
+ private boolean isUsedInLoop() {
+ ASTNode parentStatement= ASTNodes.getParent(fTargetNode, Statement.class);
+ if (parentStatement instanceof WhileStatement) {
+ return true;
+ }
+ else if (parentStatement instanceof DoStatement) {
+ return true;
+ }
+ else if (parentStatement instanceof ForStatement) {
+ ForStatement forStatement= (ForStatement)parentStatement;
+ List initializers= forStatement.initializers();
+ for (Iterator iter= initializers.iterator(); iter.hasNext();) {
+ ASTNode initializer= (ASTNode) iter.next();
+ if(fTargetNode == initializer || ASTNodes.isParent(fTargetNode, initializer)) {
+ return false;
+ }
+ }
+ return true;
+ }
+ return false;
}
private void checkIfUsedInDeclaration(RefactoringStatus result) {
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ParameterData.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ParameterData.java,v
retrieving revision 1.5
diff -u -r1.5 ParameterData.java
--- core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ParameterData.java 27 May 2003 14:41:50 -0000 1.5
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/ParameterData.java 24 Aug 2003 16:18:10 -0000
@@ -16,6 +16,7 @@
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ITypeBinding;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
+import org.eclipse.jdt.core.dom.Type;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowInfo;
@@ -44,6 +45,10 @@
if (binding != null)
return binding.getName();
return ASTNodes.asString(fDeclaration.getType());
+ }
+
+ public Type getType() {
+ return fDeclaration.getType();
}
public ITypeBinding getTypeBinding() {
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SourceAnalyzer.java
===================================================================
RCS file: core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SourceAnalyzer.java
diff -N core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SourceAnalyzer.java
--- core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SourceAnalyzer.java 21 Jul 2003 10:18:13 -0000 1.17
+++ /dev/null 1 Jan 1970 00:00:00 -0000
@@ -1,330 +0,0 @@
-/*******************************************************************************
- * Copyright (c) 2000, 2003 IBM Corporation and others.
- * All rights reserved. This program and the accompanying materials
- * are made available under the terms of the Common Public License v1.0
- * which accompanies this distribution, and is available at
- * http://www.eclipse.org/legal/cpl-v10.html
- *
- * Contributors:
- * IBM Corporation - initial API and implementation
- *******************************************************************************/
-package org.eclipse.jdt.internal.corext.refactoring.code;
-
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.HashMap;
-import java.util.Iterator;
-import java.util.List;
-import java.util.Map;
-
-import org.eclipse.jdt.core.ICompilationUnit;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.compiler.IProblem;
-import org.eclipse.jdt.core.dom.ASTNode;
-import org.eclipse.jdt.core.dom.ASTVisitor;
-import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
-import org.eclipse.jdt.core.dom.Block;
-import org.eclipse.jdt.core.dom.ClassInstanceCreation;
-import org.eclipse.jdt.core.dom.Expression;
-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 org.eclipse.jdt.core.dom.MethodDeclaration;
-import org.eclipse.jdt.core.dom.MethodInvocation;
-import org.eclipse.jdt.core.dom.Name;
-import org.eclipse.jdt.core.dom.QualifiedName;
-import org.eclipse.jdt.core.dom.ReturnStatement;
-import org.eclipse.jdt.core.dom.SimpleName;
-import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
-import org.eclipse.jdt.core.dom.ThisExpression;
-import org.eclipse.jdt.core.dom.TypeDeclaration;
-import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
-
-import org.eclipse.jdt.internal.corext.dom.ASTNodes;
-import org.eclipse.jdt.internal.corext.dom.LocalVariableIndex;
-import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
-import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
-import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatus;
-import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowContext;
-import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowInfo;
-import org.eclipse.jdt.internal.corext.refactoring.code.flow.InOutFlowAnalyzer;
-
-class SourceAnalyzer {
-
- public static class NameData {
- private String fName;
- private List fReferences;
- public NameData(String n) {
- fName= n;
- fReferences= new ArrayList(2);
- }
- public String getName() {
- return fName;
- }
- public void addReference(SimpleName ref) {
- fReferences.add(ref);
- }
- public List references() {
- return fReferences;
- }
- }
-
- private class ActivationAnalyzer extends ASTVisitor {
- public RefactoringStatus status= new RefactoringStatus();
- private ASTNode fLastNode= getLastNode();
- private IMethodBinding fBinding= getBinding();
- public boolean visit(ReturnStatement node) {
- if (node != fLastNode) {
- fInterruptedExecutionFlow= true;
- }
- return true;
- }
- public boolean visit(TypeDeclaration node) {
- return false;
- }
- public boolean visit(AnonymousClassDeclaration node) {
- return false;
- }
- public boolean visit(MethodInvocation node) {
- if (fBinding != null && fBinding == node.getName().resolveBinding() && !status.hasFatalError()) {
- status.addFatalError(RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.recursive_call")); //$NON-NLS-1$
- return false;
- }
- return true;
- }
- public boolean visit(SimpleName node) {
- IBinding binding= node.resolveBinding();
- if (binding == null && !status.hasFatalError()) {
- status.addFatalError(
- RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.declaration_has_errors"), //$NON-NLS-1$
- JavaStatusContext.create(fCUnit, fDeclaration));
- return false;
- }
- return true;
- }
- public boolean visit(ThisExpression node) {
- if (node.getQualifier() != null) {
- status.addFatalError(
- RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.qualified_this_expressions"), //$NON-NLS-1$
- JavaStatusContext.create(fCUnit, node));
- return false;
- }
- return true;
- }
- private ASTNode getLastNode() {
- List statements= fDeclaration.getBody().statements();
- if (statements.size() == 0)
- return null;
- return (ASTNode)statements.get(statements.size() - 1);
- }
- private IMethodBinding getBinding() {
- return fDeclaration.resolveBinding();
- }
- }
-
- private class UpdateCollector extends ASTVisitor {
- private int fTypeCounter;
- public boolean visit(TypeDeclaration node) {
- if (fTypeCounter++ == 0) {
- addNameData(node.getName());
- }
- Name superclass= node.getSuperclass();
- if (superclass != null) {
- ITypeBinding superBinding= ASTNodes.getTypeBinding(superclass);
- if (superBinding != null)
- fTypes.add(superclass);
- }
- List interfaces= node.superInterfaces();
- for (Iterator iter= interfaces.iterator(); iter.hasNext();) {
- Name element= (Name)iter.next();
- ITypeBinding binding= ASTNodes.getTypeBinding(element);
- if (binding != null)
- fTypes.add(element);
- }
- return true;
- }
- public void endVisit(TypeDeclaration node) {
- fTypeCounter--;
- }
- public boolean visit(AnonymousClassDeclaration node) {
- fTypeCounter++;
- return true;
- }
- public void endVisit(AnonymousClassDeclaration node) {
- fTypeCounter--;
- }
- public boolean visit(MethodDeclaration node) {
- if (node.isConstructor()) {
- TypeDeclaration decl= (TypeDeclaration) ASTNodes.getParent(node, ASTNode.TYPE_DECLARATION);
- NameData name= (NameData)fNames.get(decl.getName().resolveBinding());
- if (name != null) {
- name.addReference(node.getName());
- }
- }
- return true;
- }
- public boolean visit(MethodInvocation node) {
- if (fTypeCounter == 0) {
- Expression receiver= node.getExpression();
- if (receiver == null)
- fImplicitReceivers.add(node);
- }
- return true;
- }
- public boolean visit(ClassInstanceCreation node) {
- if (fTypeCounter == 0) {
- Expression receiver= node.getExpression();
- if (receiver == null) {
- if (node.resolveTypeBinding().isLocal())
- fImplicitReceivers.add(node);
- }
- }
- return true;
- }
- public boolean visit(SingleVariableDeclaration node) {
- if (fTypeCounter == 0)
- addNameData(node.getName());
- return true;
- }
- public boolean visit(VariableDeclarationFragment node) {
- if (fTypeCounter == 0)
- addNameData(node.getName());
- return true;
- }
- public boolean visit(SimpleName node) {
- IBinding binding= node.resolveBinding();
- ParameterData data= (ParameterData)fParameters.get(binding);
- if (data != null)
- data.addReference(node);
-
- NameData name= (NameData)fNames.get(binding);
- if (name != null)
- name.addReference(node);
- if (binding instanceof ITypeBinding) {
- ITypeBinding tb= (ITypeBinding)binding;
- Name qName= node;
- QualifiedName parent;
- while ((parent= (QualifiedName)ASTNodes.getParent(qName, ASTNode.QUALIFIED_NAME)) != null &&
- parent.getQualifier() != qName) {
- qName= parent;
- }
- String typeName= null;
- if (tb.isArray())
- typeName= tb.getElementType().getQualifiedName();
- else
- typeName= tb.getQualifiedName();
- if (!ASTNodes.asString(qName).equals(typeName))
- fTypes.add(qName);
- }
- return true;
- }
- public boolean visit(ThisExpression node) {
- if (fTypeCounter == 0) {
- fImplicitReceivers.add(node);
- }
- return true;
- }
- private void addNameData(SimpleName name) {
- fNames.put(name.resolveBinding(), new NameData(name.getIdentifier()));
- }
- }
-
- private ICompilationUnit fCUnit;
- private MethodDeclaration fDeclaration;
- private Map fParameters;
- private Map fNames;
- private List fImplicitReceivers;
- private List fTypes;
- private boolean fInterruptedExecutionFlow;
-
- public SourceAnalyzer(ICompilationUnit unit, MethodDeclaration declaration) {
- super();
- fCUnit= unit;
- fDeclaration= declaration;
- List parameters= fDeclaration.parameters();
- fParameters= new HashMap(parameters.size() * 2);
- for (Iterator iter= parameters.iterator(); iter.hasNext();) {
- SingleVariableDeclaration element= (SingleVariableDeclaration) iter.next();
- fParameters.put(element.resolveBinding(), element.getProperty(ParameterData.PROPERTY));
- }
- fNames= new HashMap();
- fImplicitReceivers= new ArrayList(2);
- fTypes= new ArrayList(2);
- }
-
- public boolean isExecutionFlowInterrupted() {
- return fInterruptedExecutionFlow;
- }
-
- public RefactoringStatus checkActivation() throws JavaModelException {
- RefactoringStatus result= new RefactoringStatus();
- if (!fCUnit.isStructureKnown()) {
- result.addFatalError(
- RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.syntax_errors"), //$NON-NLS-1$
- JavaStatusContext.create(fCUnit));
- return result;
- }
- IProblem[] problems= ASTNodes.getProblems(fDeclaration, ASTNodes.NODE_ONLY, ASTNodes.ERROR);
- if (problems.length > 0) {
- result.addFatalError(
- RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.declaration_has_errors"), //$NON-NLS-1$
- JavaStatusContext.create(fCUnit, fDeclaration));
- return result;
- }
- if (fDeclaration.getBody() == null) {
- result.addFatalError(
- RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.abstract_methods"), //$NON-NLS-1$
- JavaStatusContext.create(fCUnit, fDeclaration));
- return result;
- }
- if (fDeclaration.isConstructor()) {
- result.addFatalError(
- RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.constructors"), //$NON-NLS-1$
- JavaStatusContext.create(fCUnit, fDeclaration));
- return result;
- }
- ActivationAnalyzer analyzer= new ActivationAnalyzer();
- fDeclaration.accept(analyzer);
- result.merge(analyzer.status);
- if (!result.hasFatalError()) {
-
- }
- return result;
- }
-
- public void analyzeParameters() {
- Block body= fDeclaration.getBody();
- body.accept(new UpdateCollector());
-
- int numberOfLocals= LocalVariableIndex.perform(fDeclaration);
- FlowContext context= new FlowContext(0, numberOfLocals + 1);
- context.setConsiderAccessMode(true);
- context.setComputeMode(FlowContext.MERGE);
- InOutFlowAnalyzer flowAnalyzer= new InOutFlowAnalyzer(context);
- FlowInfo info= flowAnalyzer.perform(getStatements());
-
- for (Iterator iter= fDeclaration.parameters().iterator(); iter.hasNext();) {
- SingleVariableDeclaration element= (SingleVariableDeclaration) iter.next();
- IVariableBinding binding= element.resolveBinding();
- ParameterData data= (ParameterData)element.getProperty(ParameterData.PROPERTY);
- data.setAccessMode(info.getAccessMode(context, binding));
- }
- }
-
- public Collection getUsedNames() {
- return fNames.values();
- }
-
- public List getImplicitReceivers() {
- return fImplicitReceivers;
- }
-
- public List getUsedTypes() {
- return fTypes;
- }
- private ASTNode[] getStatements() {
- List statements= fDeclaration.getBody().statements();
- return (ASTNode[]) statements.toArray(new ASTNode[statements.size()]);
- }
-}
Index: core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SourceProvider.java
===================================================================
RCS file: /home/eclipse/org.eclipse.jdt.ui/core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SourceProvider.java,v
retrieving revision 1.21
diff -u -r1.21 SourceProvider.java
--- core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SourceProvider.java 22 Aug 2003 12:00:25 -0000 1.21
+++ core refactoring/org/eclipse/jdt/internal/corext/refactoring/code/SourceProvider.java 24 Aug 2003 16:18:11 -0000
@@ -15,69 +15,303 @@
import java.util.ArrayList;
import java.util.Collection;
+import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
+import java.util.Map;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
-
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.compiler.IProblem;
+import org.eclipse.jdt.core.dom.AST;
import org.eclipse.jdt.core.dom.ASTNode;
import org.eclipse.jdt.core.dom.ASTVisitor;
+import org.eclipse.jdt.core.dom.AnonymousClassDeclaration;
import org.eclipse.jdt.core.dom.ClassInstanceCreation;
import org.eclipse.jdt.core.dom.Expression;
+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 org.eclipse.jdt.core.dom.MethodDeclaration;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.Modifier;
import org.eclipse.jdt.core.dom.Name;
+import org.eclipse.jdt.core.dom.PrimitiveType;
+import org.eclipse.jdt.core.dom.QualifiedName;
import org.eclipse.jdt.core.dom.ReturnStatement;
import org.eclipse.jdt.core.dom.SimpleName;
import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
-
+import org.eclipse.jdt.core.dom.ThisExpression;
+import org.eclipse.jdt.core.dom.Type;
+import org.eclipse.jdt.core.dom.TypeDeclaration;
+import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
import org.eclipse.jdt.internal.corext.codemanipulation.ImportEdit;
import org.eclipse.jdt.internal.corext.dom.ASTNodes;
import org.eclipse.jdt.internal.corext.dom.ASTRewrite;
-import org.eclipse.jdt.internal.corext.dom.Bindings;
import org.eclipse.jdt.internal.corext.dom.CodeScopeBuilder;
+import org.eclipse.jdt.internal.corext.dom.LocalVariableIndex;
+import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
+import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatus;
+import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowContext;
+import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowInfo;
+import org.eclipse.jdt.internal.corext.refactoring.code.flow.InOutFlowAnalyzer;
import org.eclipse.jdt.internal.corext.textmanipulation.MultiTextEdit;
-import org.eclipse.jdt.internal.corext.textmanipulation.RangeMarker;
import org.eclipse.jdt.internal.corext.textmanipulation.TextBuffer;
-import org.eclipse.jdt.internal.corext.textmanipulation.TextBufferEditor;
import org.eclipse.jdt.internal.corext.textmanipulation.TextEdit;
-import org.eclipse.jdt.internal.corext.textmanipulation.TextRange;
-import org.eclipse.jdt.internal.corext.textmanipulation.UndoMemento;
-import org.eclipse.jdt.internal.corext.util.CodeFormatterUtil;
-import org.eclipse.jdt.internal.corext.util.Strings;
public class SourceProvider {
+ private Map fNames;
+ private List fImplicitReceivers;
+ private List fTypes;
+ private Map fParameters;
private ICompilationUnit fCUnit;
private TextBuffer fBuffer;
+ private List fStatements;
private MethodDeclaration fDeclaration;
- private ASTRewrite fRewriter;
- private SourceAnalyzer fAnalyzer;
- private boolean fMustEvalReturnedExpression;
- private boolean fReturnValueNeedsLocalVariable;
- private List fReturnExpressions;
+ private boolean fInterruptedExecutionFlow;
+
+ private Map fBindings;
+ private Map fTypeBindings;
+ private Map fMethodBindings;
+
+ public static class NameData {
+ private String fName;
+ private List fReferences;
+ public NameData(String n) {
+ fName= n;
+ fReferences= new ArrayList(2);
+ }
+ public String getName() {
+ return fName;
+ }
+ public void addReference(SimpleName ref) {
+ fReferences.add(ref);
+ }
+ public List references() {
+ return fReferences;
+ }
+ }
+
+ private class ActivationAnalyzer extends ASTVisitor {
+ public RefactoringStatus status= new RefactoringStatus();
+ private ASTNode fLastNode= getLastNode();
+ private IMethodBinding fBinding= getBinding();
+ public boolean visit(ReturnStatement node) {
+ if (node != fLastNode) {
+ fInterruptedExecutionFlow= true;
+ }
+ return true;
+ }
+ public boolean visit(TypeDeclaration node) {
+ return false;
+ }
+ public boolean visit(AnonymousClassDeclaration node) {
+ return false;
+ }
+ public boolean visit(MethodInvocation node) {
+ if (fBinding != null && fBinding == resolveMethodBinding(node.getName()) && !status.hasFatalError()) {
+ status.addFatalError(RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.recursive_call")); //$NON-NLS-1$
+ return false;
+ }
+ return true;
+ }
+ public boolean visit(SimpleName node) {
+ IBinding binding= resolveBinding(node);
+ if (binding == null && !status.hasFatalError()) {
+ status.addFatalError(
+ RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.declaration_has_errors"), //$NON-NLS-1$
+ JavaStatusContext.create(fCUnit, fDeclaration));
+ return false;
+ }
+ return true;
+ }
+ public boolean visit(ThisExpression node) {
+ if (node.getQualifier() != null) {
+ status.addFatalError(
+ RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.qualified_this_expressions"), //$NON-NLS-1$
+ JavaStatusContext.create(fCUnit, node));
+ return false;
+ }
+ return true;
+ }
+ private ASTNode getLastNode() {
+ if (fStatements.size() == 0)
+ return null;
+ return (ASTNode)fStatements.get(fStatements.size() - 1);
+ }
+ private IMethodBinding getBinding() {
+ return fDeclaration.resolveBinding();
+ }
+ }
- private class ReturnAnalyzer extends ASTVisitor {
+ private class UpdateCollector extends ASTVisitor {
+ private int fTypeCounter;
+ public boolean visit(TypeDeclaration node) {
+ if (fTypeCounter++ == 0) {
+ addNameData(node.getName());
+ }
+ Name superclass= node.getSuperclass();
+ if (superclass != null) {
+ ITypeBinding superBinding= resolveTypeBinding(superclass);
+ if (superBinding != null)
+ fTypes.add(superclass);
+ }
+ List interfaces= node.superInterfaces();
+ for (Iterator iter= interfaces.iterator(); iter.hasNext();) {
+ Name element= (Name)iter.next();
+ ITypeBinding superBinding= resolveTypeBinding(superclass);
+ if (superBinding != null)
+ fTypes.add(superclass);
+ }
+ return true;
+ }
+ public void endVisit(TypeDeclaration node) {
+ fTypeCounter--;
+ }
+ public boolean visit(AnonymousClassDeclaration node) {
+ fTypeCounter++;
+ return true;
+ }
+ public void endVisit(AnonymousClassDeclaration node) {
+ fTypeCounter--;
+ }
+ public boolean visit(MethodDeclaration node) {
+ if (node.isConstructor()) {
+ TypeDeclaration decl= (TypeDeclaration) ASTNodes.getParent(node, ASTNode.TYPE_DECLARATION);
+ NameData name= (NameData)fNames.get(resolveTypeBinding(decl.getName()));
+ if (name != null) {
+ name.addReference(node.getName());
+ }
+ }
+ return true;
+ }
+ public boolean visit(MethodInvocation node) {
+ if (fTypeCounter == 0) {
+ Expression receiver= node.getExpression();
+ if (receiver == null)
+ fImplicitReceivers.add(node);
+ }
+ return true;
+ }
+ public boolean visit(ClassInstanceCreation node) {
+ if (fTypeCounter == 0) {
+ Expression receiver= node.getExpression();
+ if (receiver == null) {
+ IMethodBinding methodBinding= resolveMethodBinding(node);
+ ITypeBinding typeBinding= methodBinding.getDeclaringClass();
+ if (typeBinding.isLocal()) {
+ fImplicitReceivers.add(node);
+ }
+ }
+ }
+ return true;
+ }
+ public boolean visit(SingleVariableDeclaration node) {
+ if (fTypeCounter == 0)
+ addNameData(node.getName());
+ return true;
+ }
+ public boolean visit(VariableDeclarationFragment node) {
+ if (fTypeCounter == 0)
+ addNameData(node.getName());
+ return true;
+ }
+ public boolean visit(SimpleName node) {
+ IBinding binding= resolveBinding(node);
+ ParameterData data= (ParameterData)fParameters.get(binding);
+ if (data != null)
+ data.addReference(node);
+
+ NameData name= (NameData)fNames.get(binding);
+ if (name != null)
+ name.addReference(node);
+ if (binding instanceof ITypeBinding) {
+ ITypeBinding tb= (ITypeBinding)binding;
+ Name qName= node;
+ QualifiedName parent;
+ while ((parent= (QualifiedName)ASTNodes.getParent(qName, ASTNode.QUALIFIED_NAME)) != null &&
+ parent.getQualifier() != qName) {
+ qName= parent;
+ }
+ String typeName= null;
+ if (tb.isArray())
+ typeName= tb.getElementType().getQualifiedName();
+ else
+ typeName= tb.getQualifiedName();
+ if (!ASTNodes.asString(qName).equals(typeName))
+ fTypes.add(qName);
+ }
+ return true;
+ }
+ public boolean visit(ThisExpression node) {
+ if (fTypeCounter == 0) {
+ fImplicitReceivers.add(node);
+ }
+ return true;
+ }
+ private void addNameData(SimpleName name) {
+ IBinding binding= (IBinding)fBindings.get(new Integer(name.getStartPosition()));
+ fNames.put(binding, new NameData(name.getIdentifier()));
+ }
+ }
+
+ private class BindingCollector extends ASTVisitor {
+ public boolean visit(SimpleName node) {
+ fBindings.put(new Integer(node.getStartPosition()), node.resolveBinding());
+ fTypeBindings.put(new Integer(node.getStartPosition()), node.resolveTypeBinding());
+ return true;
+ }
+ public boolean visit(MethodInvocation node) {
+ fMethodBindings.put(new Integer(node.getStartPosition()), node.resolveMethodBinding());
+ return true;
+ }
+ public boolean visit(TypeDeclaration node) {
+ fTypeBindings.put(new Integer(node.getStartPosition()), node.resolveBinding());
+ return true;
+ }
+ public boolean visit(ClassInstanceCreation node) {
+ fTypeBindings.put(new Integer(node.getStartPosition()), node.resolveTypeBinding());
+ fMethodBindings.put(new Integer(node.getStartPosition()), node.resolveConstructorBinding());
+ return true;
+ }
public boolean visit(ReturnStatement node) {
Expression expression= node.getExpression();
- if (!(ASTNodes.isLiteral(expression) || expression instanceof Name)) {
- fMustEvalReturnedExpression= true;
- }
- if (Invocations.isInvocation(expression) || expression instanceof ClassInstanceCreation) {
- fReturnValueNeedsLocalVariable= false;
+ if(expression != null) {
+ fTypeBindings.put(new Integer(expression.getStartPosition()), expression.resolveTypeBinding());
}
- fReturnExpressions.add(expression);
- return false;
+ return true;
}
}
+ public IBinding resolveBinding(ASTNode node) {
+ return resolveBinding(node.getStartPosition());
+ }
+
+ public IBinding resolveBinding(int startPosition) {
+ return (IBinding)fBindings.get(new Integer(startPosition));
+ }
+
+ public ITypeBinding resolveTypeBinding(ASTNode node) {
+ return resolveTypeBinding(node.getStartPosition());
+ }
+
+ public ITypeBinding resolveTypeBinding(int startPosition) {
+ return (ITypeBinding)fTypeBindings.get(new Integer(startPosition));
+ }
+
+ public IMethodBinding resolveMethodBinding(ASTNode node) {
+ return resolveMethodBinding(node.getStartPosition());
+ }
+
+ public IMethodBinding resolveMethodBinding(int startPosition) {
+ return (IMethodBinding)fMethodBindings.get(new Integer(startPosition));
+ }
+
public SourceProvider(ICompilationUnit unit, MethodDeclaration declaration) {
super();
fCUnit= unit;
@@ -88,47 +322,90 @@
ParameterData data= new ParameterData(element);
element.setProperty(ParameterData.PROPERTY, data);
}
- fRewriter= new ASTRewrite(fDeclaration);
- fAnalyzer= new SourceAnalyzer(fCUnit, fDeclaration);
- fReturnValueNeedsLocalVariable= true;
- fReturnExpressions= new ArrayList();
+ fStatements= ASTNode.copySubtrees(fDeclaration.getAST(),
+ fDeclaration.getBody().statements());
+
+ fBindings= new HashMap();
+ fTypeBindings= new HashMap();
+ fMethodBindings= new HashMap();
+ fDeclaration.getBody().accept(new BindingCollector());
+ fParameters= new HashMap(parameters.size());
+ for (Iterator iter= parameters.iterator(); iter.hasNext();) {
+ SingleVariableDeclaration element= (SingleVariableDeclaration) iter.next();
+ fParameters.put(element.resolveBinding(), element.getProperty(ParameterData.PROPERTY));
+ }
+ fNames= new HashMap();
+ fImplicitReceivers= new ArrayList(2);
+ fTypes= new ArrayList(2);
}
-
+
public RefactoringStatus checkActivation(IProgressMonitor pm) throws JavaModelException {
- return fAnalyzer.checkActivation();
+ RefactoringStatus result= new RefactoringStatus();
+ if (!fCUnit.isStructureKnown()) {
+ result.addFatalError(
+ RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.syntax_errors"), //$NON-NLS-1$
+ JavaStatusContext.create(fCUnit));
+ return result;
+ }
+ IProblem[] problems= ASTNodes.getProblems(fDeclaration, ASTNodes.NODE_ONLY, ASTNodes.ERROR);
+ if (problems.length > 0) {
+ result.addFatalError(
+ RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.declaration_has_errors"), //$NON-NLS-1$
+ JavaStatusContext.create(fCUnit, fDeclaration));
+ return result;
+ }
+ if (fDeclaration.getBody() == null) {
+ result.addFatalError(
+ RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.abstract_methods"), //$NON-NLS-1$
+ JavaStatusContext.create(fCUnit, fDeclaration));
+ return result;
+ }
+ if (fDeclaration.isConstructor()) {
+ result.addFatalError(
+ RefactoringCoreMessages.getString("InlineMethodRefactoring.SourceAnalyzer.constructors"), //$NON-NLS-1$
+ JavaStatusContext.create(fCUnit, fDeclaration));
+ return result;
+ }
+ ActivationAnalyzer analyzer= new ActivationAnalyzer();
+ ASTNodes.acceptNodes(fStatements, analyzer);
+ result.merge(analyzer.status);
+ return result;
}
public void initialize() throws JavaModelException {
fBuffer= TextBuffer.create(fCUnit.getBuffer().getContents());
- fAnalyzer.analyzeParameters();
- if (hasReturnValue()) {
- ASTNode last= getLastStatement();
- if (last != null) {
- ReturnAnalyzer analyzer= new ReturnAnalyzer();
- last.accept(analyzer);
- }
- }
+
+ ASTNodes.acceptNodes(fStatements, new UpdateCollector());
+
+ int numberOfLocals= LocalVariableIndex.perform(fDeclaration);
+ FlowContext context= new FlowContext(0, numberOfLocals + 1);
+ context.setConsiderAccessMode(true);
+ context.setComputeMode(FlowContext.MERGE);
+ InOutFlowAnalyzer flowAnalyzer= new InOutFlowAnalyzer(context);
+ FlowInfo info= flowAnalyzer.perform(getStatements());
+
+ for (Iterator iter= fDeclaration.parameters().iterator(); iter.hasNext();) {
+ SingleVariableDeclaration element= (SingleVariableDeclaration) iter.next();
+ IVariableBinding binding= element.resolveBinding();
+ ParameterData data= (ParameterData)element.getProperty(ParameterData.PROPERTY);
+ data.setAccessMode(info.getAccessMode(context, binding));
+ }
}
public boolean isExecutionFlowInterrupted() {
- return fAnalyzer.isExecutionFlowInterrupted();
+ return fInterruptedExecutionFlow;
}
public boolean hasReturnValue() {
- IMethodBinding binding= fDeclaration.resolveBinding();
- return binding.getReturnType() != fDeclaration.getAST().resolveWellKnownType("void"); //$NON-NLS-1$
- }
-
- public boolean mustEvaluateReturnedExpression() {
- return fMustEvalReturnedExpression;
- }
-
- public boolean returnValueNeedsLocalVariable() {
- return fReturnValueNeedsLocalVariable;
+ Type returnType= fDeclaration.getReturnType();
+ if(!returnType.isPrimitiveType()) {
+ return true;
+ }
+ return ((PrimitiveType)returnType).getPrimitiveTypeCode() != PrimitiveType.VOID;
}
public int getNumberOfStatements() {
- return fDeclaration.getBody().statements().size();
+ return fStatements.size();
}
public boolean isSimpleFunction() {
@@ -146,22 +423,8 @@
return fDeclaration.getName().getIdentifier();
}
- public ITypeBinding getReturnType() {
- return fDeclaration.resolveBinding().getReturnType();
- }
-
- public List getReturnExpressions() {
- return fReturnExpressions;
- }
-
- public boolean returnTypeMatchesReturnExpressions() {
- ITypeBinding returnType= getReturnType();
- for (Iterator iter= fReturnExpressions.iterator(); iter.hasNext();) {
- Expression expression= (Expression)iter.next();
- if (!Bindings.equals(returnType, expression.resolveTypeBinding()))
- return false;
- }
- return true;
+ public Type getReturnType() {
+ return fDeclaration.getReturnType();
}
public ParameterData getParameterData(int index) {
@@ -172,229 +435,166 @@
public ICompilationUnit getCompilationUnit() {
return fCUnit;
}
-
- public boolean needsReturnedExpressionParenthesis() {
- ASTNode last= getLastStatement();
- if (last instanceof ReturnStatement) {
- return ASTNodes.needsParentheses(((ReturnStatement)last).getExpression());
- }
- return false;
- }
-
+
public int getReceiversToBeUpdated() {
- return fAnalyzer.getImplicitReceivers().size();
+ return fImplicitReceivers.size();
}
-
+
public TextEdit getDeleteEdit() {
ASTRewrite rewriter= new ASTRewrite(fDeclaration.getParent());
rewriter.markAsRemoved(fDeclaration);
MultiTextEdit result= new MultiTextEdit();
- rewriter.rewriteNode(fBuffer, result, null);
+ rewriter.rewriteNode(fBuffer, result);
rewriter.removeModifications();
return result;
}
-
- public String[] getCodeBlocks(CallContext context) throws CoreException {
- replaceParameterWithExpression(context.arguments);
- updateImplicitReceivers(context);
- makeNamesUnique(context.scope);
- updateTypes(context);
+
+ /**
+ * @param context call context of method invocation.
+ * @return list of statements composing inlined method body.
+ * @throws CoreException
+ */
+ public List getCodeStatements(CallContext context) throws CoreException {
- List ranges= null;
- if (hasReturnValue()) {
- if (context.callMode == ASTNode.RETURN_STATEMENT) {
- ranges= getStatementRanges();
- } else {
- ranges= getExpressionRanges();
- }
- } else {
- ASTNode last= getLastStatement();
- if (last != null && last.getNodeType() == ASTNode.RETURN_STATEMENT) {
- ranges= getReturnStatementRanges();
- } else {
- ranges= getStatementRanges();
- }
- }
+ context.receiver= replaceAST(fDeclaration.getAST(), context.receiver);
+ replaceAST(fDeclaration.getAST(), context.arguments);
- MultiTextEdit dummy= new MultiTextEdit();
- fRewriter.rewriteNode(fBuffer, dummy, null);
+ replaceParameterWithExpression(fStatements, context.arguments);
+ updateImplicitReceivers(context.importer, context.receiver);
+ makeNamesUnique(context.scope);
+ updateTypes(context.importer);
+
+ return fStatements;
+ }
- int size= ranges.size();
- RangeMarker[] markers= new RangeMarker[size];
- for (int i= 0; i < markers.length; i++) {
- markers[i]= new RangeMarker((TextRange)ranges.get(i));
- }
- int split= size <= 1 ? Integer.MAX_VALUE : ((TextRange)ranges.get(0)).getExclusiveEnd();
- TextEdit[] edits= dummy.removeAll();
- for (int i= 0; i < edits.length; i++) {
- TextEdit edit= edits[i];
- int pos= edit.getTextRange().getOffset() >= split ? 1 : 0;
- markers[pos].add(edit);
- }
- MultiTextEdit root= new MultiTextEdit();
- root.addAll(markers);
- TextBufferEditor editor= new TextBufferEditor(fBuffer);
- editor.add(root);
- UndoMemento undo= editor.performEdits(null);
- String[] result= getBlocks(markers);
- // It is faster to undo the changes than coping the buffer over and over again.
- TextBufferEditor undoEditor= new TextBufferEditor(fBuffer);
- undoEditor.add(undo);
- undoEditor.performEdits(null);
- fRewriter.removeModifications();
+ public static ASTNode replaceAST(AST ast, ASTNode node) {
+ ASTNode result= node;
+ if(node != null && node.getAST() != ast) {
+ result= ASTNode.copySubtree(ast, node);
+ }
return result;
}
- private void replaceParameterWithExpression(String[] expressions) {
+ public static void replaceAST(AST ast, ASTNode[] nodes) {
+ for (int i = 0; i < nodes.length; i++) {
+ nodes[i]= replaceAST(ast, nodes[i]);
+ }
+ }
+
+ public static void replaceAST(AST ast, List nodes) {
+ for (int i = 0; i < nodes.size(); i++) {
+ nodes.set(i, replaceAST(ast, (ASTNode)nodes.get(i)));
+ }
+ }
+
+ private class ParameterReferenceFinder extends ASTVisitor {
+ private HashMap parametersMap;
+ public ParameterReferenceFinder(HashMap parametersMap) {
+ this.parametersMap= parametersMap;
+ }
+ public boolean visit(SimpleName node) {
+ ArrayList list= (ArrayList)parametersMap.get(node.getIdentifier());
+ if (list != null) {
+ list.add(node);
+ }
+ return true;
+ }
+ }
+
+ private void replaceParameterWithExpression(List statements, ASTNode[] expressions) {
+ List parameters= fDeclaration.parameters();
+ List[] referenceList= new ArrayList[parameters.size()];
+ HashMap parametersMap= new HashMap(parameters.size());
+ for (int i= 0; i < parameters.size(); i++) {
+ SingleVariableDeclaration element= (SingleVariableDeclaration) parameters.get(i);
+ parametersMap.put(element.getName().getIdentifier(), referenceList[i]= new ArrayList());
+ }
+ ASTNodes.acceptNodes(fStatements, new ParameterReferenceFinder(parametersMap));
+
for (int i= 0; i < expressions.length; i++) {
- String expression= expressions[i];
- ParameterData parameter= getParameterData(i);
- List references= parameter.references();
+ ASTNode expression= expressions[i];
+ List references= referenceList[i];
for (Iterator iter= references.iterator(); iter.hasNext();) {
ASTNode element= (ASTNode) iter.next();
- ASTNode newNode= fRewriter.createPlaceholder(expression, ASTRewrite.getPlaceholderType(element));
- fRewriter.markAsReplaced(element, newNode);
+ if(expression.getParent() != null) {
+ expression= ASTNode.copySubtree(
+ expression.getAST(), expression);
+ }
+ ASTNodes.substitute(element, expression);
}
}
}
private void makeNamesUnique(CodeScopeBuilder.Scope scope) {
- Collection usedCalleeNames= fAnalyzer.getUsedNames();
+ Collection usedCalleeNames= fNames.values();
for (Iterator iter= usedCalleeNames.iterator(); iter.hasNext();) {
- SourceAnalyzer.NameData nd= (SourceAnalyzer.NameData) iter.next();
+ NameData nd= (NameData) iter.next();
if (scope.isInUse(nd.getName())) {
String newName= scope.createName(nd.getName(), true);
List references= nd.references();
for (Iterator refs= references.iterator(); refs.hasNext();) {
SimpleName element= (SimpleName) refs.next();
- ASTNode newNode= fRewriter.createPlaceholder(newName, ASTRewrite.EXPRESSION);
- fRewriter.markAsReplaced(element, newNode);
+ element.setIdentifier(newName);
}
}
}
}
- private void updateImplicitReceivers(CallContext context) {
- if (context.receiver == null)
- return;
- List implicitReceivers= fAnalyzer.getImplicitReceivers();
- for (Iterator iter= implicitReceivers.iterator(); iter.hasNext();) {
- ASTNode node= (ASTNode)iter.next();
- if (node instanceof MethodInvocation) {
- final MethodInvocation inv= (MethodInvocation)node;
- inv.setExpression(createReceiver(context, (IMethodBinding)inv.getName().resolveBinding()));
- } else if (node instanceof ClassInstanceCreation) {
- final ClassInstanceCreation inst= (ClassInstanceCreation)node;
- inst.setExpression(createReceiver(context, inst.resolveConstructorBinding()));
- } else if (node instanceof Expression) {
- fRewriter.markAsReplaced(node, fRewriter.createPlaceholder(context.receiver, ASTRewrite.EXPRESSION));
+ private void updateImplicitReceivers(ImportEdit importer, ASTNode receiver) {
+ if (receiver != null) {
+ AST ast= receiver.getAST();
+ for (Iterator iter= fImplicitReceivers.iterator(); iter.hasNext();) {
+ ASTNode node= (ASTNode)iter.next();
+ if(receiver.getParent() != null) {
+ receiver= ASTNode.copySubtree(receiver.getAST(), receiver);
+ }
+ int nodeType= node.getNodeType();
+ if (nodeType == ASTNode.METHOD_INVOCATION) {
+ MethodInvocation methodInvocation= (MethodInvocation)node;
+ IMethodBinding methodBinding= resolveMethodBinding(methodInvocation);
+ methodInvocation.setExpression(createReceiver(receiver, importer, methodBinding));
+ }
+ else if (nodeType == ASTNode.CLASS_INSTANCE_CREATION) {
+ ClassInstanceCreation methodInvocation= (ClassInstanceCreation)node;
+ IMethodBinding methodBinding= resolveMethodBinding(methodInvocation);
+ methodInvocation.setExpression(createReceiver(receiver, importer, methodBinding));
+ }
+ else {
+ ASTNodes.substitute(node, receiver);
+ }
}
}
}
-
- private void updateTypes(CallContext context) {
- ImportEdit importer= context.importer;
- for (Iterator iter= fAnalyzer.getUsedTypes().iterator(); iter.hasNext();) {
+
+ private Expression createReceiver(ASTNode receiver, ImportEdit importer, IMethodBinding methodBinding) {
+ if (Modifier.isStatic(methodBinding.getModifiers())) {
+ ITypeBinding typeBinding= methodBinding.getDeclaringClass();
+ importer.addImport(typeBinding);
+ return receiver.getAST().newSimpleName(typeBinding.getName());
+ }
+ else {
+ return (Expression)receiver;
+ }
+ }
+
+ private void updateTypes(ImportEdit importer) {
+ for (Iterator iter= fTypes.iterator(); iter.hasNext();) {
Name element= (Name)iter.next();
- ITypeBinding binding= ASTNodes.getTypeBinding(element);
+ ITypeBinding binding= resolveTypeBinding(element);
if (binding != null && !binding.isLocal()) {
String s= importer.addImport(binding);
if (!ASTNodes.asString(element).equals(s)) {
- fRewriter.markAsReplaced(element, fRewriter.createPlaceholder(s, ASTRewrite.EXPRESSION));
+ if(element instanceof SimpleName) {
+ SimpleName simpleName= (SimpleName)element;
+ simpleName.setIdentifier(s);
+ }
}
}
}
}
- private Expression createReceiver(CallContext context, IMethodBinding method) {
- String receiver= context.receiver;
- if (!context.receiverIsStatic && Modifier.isStatic(method.getModifiers())) {
- receiver= context.importer.addImport(fDeclaration.resolveBinding().getDeclaringClass());
- }
- Expression exp= (Expression)fRewriter.createPlaceholder(receiver, ASTRewrite.EXPRESSION);
- fRewriter.markAsInserted(exp);
- return exp;
- }
-
- private ASTNode getLastStatement() {
- List statements= fDeclaration.getBody().statements();
- if (statements.isEmpty())
- return null;
- return (ASTNode)statements.get(statements.size() - 1);
- }
-
- private List getReturnStatementRanges() {
- List result= new ArrayList(1);
+ private ASTNode[] getStatements() {
List statements= fDeclaration.getBody().statements();
- int size= statements.size();
- if (size <= 1)
- return result;
- result.add(createRange(statements, size - 2));
- return result;
- }
-
- private List getStatementRanges() {
- List result= new ArrayList(1);
- List statements= fDeclaration.getBody().statements();
- int size= statements.size();
- if (size == 0)
- return result;
- result.add(createRange(statements, size - 1));
- return result;
- }
-
- private List getExpressionRanges() {
- List result= new ArrayList(2);
- List statements= fDeclaration.getBody().statements();
- ReturnStatement rs= null;
- int size= statements.size();
- ASTNode node;
- switch (size) {
- case 0:
- return result;
- case 1:
- node= (ASTNode)statements.get(0);
- if (node.getNodeType() == ASTNode.RETURN_STATEMENT) {
- rs= (ReturnStatement)node;
- } else {
- result.add(TextRange.createFromStartAndLength(node.getStartPosition(), node.getLength()));
- }
- break;
- default: {
- node= (ASTNode)statements.get(size - 1);
- if (node.getNodeType() == ASTNode.RETURN_STATEMENT) {
- result.add(createRange(statements, size - 2));
- rs= (ReturnStatement)node;
- } else {
- result.add(createRange(statements, size - 1));
- }
- break;
- }
- }
- if (rs != null) {
- Expression exp= rs.getExpression();
- result.add(TextRange.createFromStartAndLength(exp.getStartPosition(), exp.getLength()));
- }
- return result;
- }
-
- private TextRange createRange(List statements, int end) {
- int start= ((ASTNode)statements.get(0)).getStartPosition();
- ASTNode last= (ASTNode)statements.get(end);
- int length = last.getStartPosition() - start + last.getLength();
- TextRange range= TextRange.createFromStartAndLength(start, length);
- return range;
- }
-
- private String[] getBlocks(RangeMarker[] markers) {
- String[] result= new String[markers.length];
- for (int i= 0; i < markers.length; i++) {
- TextRange range= markers[i].getTextRange();
- String content= fBuffer.getContent(range.getOffset(), range.getLength());
- String lines[]= Strings.convertIntoLines(content);
- Strings.trimIndentation(lines, CodeFormatterUtil.getTabWidth(), false);
- result[i]= Strings.concatenate(lines, fBuffer.getLineDelimiter());
- }
- return result;
- }
+ return (ASTNode[]) statements.toArray(new ASTNode[statements.size()]);
+ }
}