Download
Getting Started
Members
Projects
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
More
Community
Marketplace
Events
Planet Eclipse
Newsletter
Videos
Participate
Report a Bug
Forums
Mailing Lists
Wiki
IRC
How to Contribute
Working Groups
Automotive
Internet of Things
LocationTech
Long-Term Support
PolarSys
Science
OpenMDM
Toggle navigation
Bugzilla – Attachment 5837 Details for
Bug 36049
[inline] Cannot inline method with multiple returns [refactoring]
Home
|
New
|
Browse
|
Search
|
[?]
|
Reports
|
Requests
|
Help
|
Log In
[x]
|
Terms of Use
|
Copyright Agent
[patch]
Updated patch
patch_org.eclipse.jdt.ui.txt (text/plain), 108.47 KB, created by
Dmitry Stalnov
on 2003-08-24 14:12:23 EDT
(
hide
)
Description:
Updated patch
Filename:
MIME Type:
Creator:
Dmitry Stalnov
Created:
2003-08-24 14:12:23 EDT
Size:
108.47 KB
patch
obsolete
>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 <code>true</code> if explicit cast is needed otherwise <code>false</code> > * @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 <code>true</code> 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()]); >+ } > }
You cannot view the attachment while viewing its details because your browser does not support IFRAMEs.
View the attachment on a separate page
.
View Attachment As Diff
View Attachment As Raw
Actions:
View
|
Diff
Attachments on
bug 36049
:
5813
|
5814
|
5837
|
6876
|
7066
|
7311
|
7891
|
7943
|
8737
|
8753