Lines 17-67
Link Here
|
17 |
import java.util.Iterator; |
17 |
import java.util.Iterator; |
18 |
import java.util.List; |
18 |
import java.util.List; |
19 |
|
19 |
|
20 |
import org.eclipse.core.runtime.CoreException; |
|
|
21 |
|
22 |
import org.eclipse.core.resources.IFile; |
20 |
import org.eclipse.core.resources.IFile; |
23 |
|
21 |
import org.eclipse.core.runtime.CoreException; |
24 |
import org.eclipse.jdt.core.ICompilationUnit; |
22 |
import org.eclipse.jdt.core.ICompilationUnit; |
25 |
import org.eclipse.jdt.core.dom.AST; |
23 |
import org.eclipse.jdt.core.dom.AST; |
26 |
import org.eclipse.jdt.core.dom.ASTNode; |
24 |
import org.eclipse.jdt.core.dom.ASTNode; |
|
|
25 |
import org.eclipse.jdt.core.dom.ASTVisitor; |
26 |
import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; |
27 |
import org.eclipse.jdt.core.dom.Assignment; |
27 |
import org.eclipse.jdt.core.dom.Block; |
28 |
import org.eclipse.jdt.core.dom.Block; |
28 |
import org.eclipse.jdt.core.dom.BodyDeclaration; |
29 |
import org.eclipse.jdt.core.dom.BodyDeclaration; |
29 |
import org.eclipse.jdt.core.dom.CastExpression; |
30 |
import org.eclipse.jdt.core.dom.CastExpression; |
30 |
import org.eclipse.jdt.core.dom.DoStatement; |
31 |
import org.eclipse.jdt.core.dom.ClassInstanceCreation; |
31 |
import org.eclipse.jdt.core.dom.Expression; |
32 |
import org.eclipse.jdt.core.dom.Expression; |
32 |
import org.eclipse.jdt.core.dom.FieldAccess; |
33 |
import org.eclipse.jdt.core.dom.FieldAccess; |
33 |
import org.eclipse.jdt.core.dom.ForStatement; |
|
|
34 |
import org.eclipse.jdt.core.dom.IBinding; |
34 |
import org.eclipse.jdt.core.dom.IBinding; |
35 |
import org.eclipse.jdt.core.dom.IMethodBinding; |
35 |
import org.eclipse.jdt.core.dom.IMethodBinding; |
36 |
import org.eclipse.jdt.core.dom.ITypeBinding; |
36 |
import org.eclipse.jdt.core.dom.ITypeBinding; |
37 |
import org.eclipse.jdt.core.dom.IVariableBinding; |
37 |
import org.eclipse.jdt.core.dom.IVariableBinding; |
38 |
import org.eclipse.jdt.core.dom.IfStatement; |
|
|
39 |
import org.eclipse.jdt.core.dom.Initializer; |
38 |
import org.eclipse.jdt.core.dom.Initializer; |
40 |
import org.eclipse.jdt.core.dom.MethodDeclaration; |
39 |
import org.eclipse.jdt.core.dom.MethodDeclaration; |
41 |
import org.eclipse.jdt.core.dom.MethodInvocation; |
40 |
import org.eclipse.jdt.core.dom.MethodInvocation; |
42 |
import org.eclipse.jdt.core.dom.Modifier; |
41 |
import org.eclipse.jdt.core.dom.Modifier; |
43 |
import org.eclipse.jdt.core.dom.Name; |
42 |
import org.eclipse.jdt.core.dom.Name; |
44 |
import org.eclipse.jdt.core.dom.ParenthesizedExpression; |
43 |
import org.eclipse.jdt.core.dom.ParenthesizedExpression; |
|
|
44 |
import org.eclipse.jdt.core.dom.PrimitiveType; |
45 |
import org.eclipse.jdt.core.dom.ReturnStatement; |
45 |
import org.eclipse.jdt.core.dom.SimpleName; |
46 |
import org.eclipse.jdt.core.dom.SimpleName; |
46 |
import org.eclipse.jdt.core.dom.Statement; |
47 |
import org.eclipse.jdt.core.dom.Statement; |
47 |
import org.eclipse.jdt.core.dom.SuperFieldAccess; |
48 |
import org.eclipse.jdt.core.dom.SuperFieldAccess; |
|
|
49 |
import org.eclipse.jdt.core.dom.SuperMethodInvocation; |
50 |
import org.eclipse.jdt.core.dom.SwitchStatement; |
48 |
import org.eclipse.jdt.core.dom.ThisExpression; |
51 |
import org.eclipse.jdt.core.dom.ThisExpression; |
|
|
52 |
import org.eclipse.jdt.core.dom.Type; |
53 |
import org.eclipse.jdt.core.dom.TypeDeclaration; |
49 |
import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
54 |
import org.eclipse.jdt.core.dom.VariableDeclarationFragment; |
50 |
import org.eclipse.jdt.core.dom.VariableDeclarationStatement; |
55 |
import org.eclipse.jdt.core.dom.VariableDeclarationStatement; |
51 |
import org.eclipse.jdt.core.dom.WhileStatement; |
|
|
52 |
|
53 |
import org.eclipse.jdt.internal.corext.Assert; |
56 |
import org.eclipse.jdt.internal.corext.Assert; |
54 |
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; |
57 |
import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; |
55 |
import org.eclipse.jdt.internal.corext.codemanipulation.ImportEdit; |
58 |
import org.eclipse.jdt.internal.corext.codemanipulation.ImportEdit; |
56 |
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; |
59 |
import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; |
57 |
import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
60 |
import org.eclipse.jdt.internal.corext.dom.ASTNodes; |
58 |
import org.eclipse.jdt.internal.corext.dom.ASTRewrite; |
61 |
import org.eclipse.jdt.internal.corext.dom.ASTRewrite; |
59 |
import org.eclipse.jdt.internal.corext.dom.TypeBindingVisitor; |
|
|
60 |
import org.eclipse.jdt.internal.corext.dom.Bindings; |
62 |
import org.eclipse.jdt.internal.corext.dom.Bindings; |
61 |
import org.eclipse.jdt.internal.corext.dom.CodeScopeBuilder; |
63 |
import org.eclipse.jdt.internal.corext.dom.CodeScopeBuilder; |
|
|
64 |
import org.eclipse.jdt.internal.corext.dom.GenericVisitor; |
62 |
import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor; |
65 |
import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor; |
63 |
import org.eclipse.jdt.internal.corext.dom.LocalVariableIndex; |
66 |
import org.eclipse.jdt.internal.corext.dom.LocalVariableIndex; |
64 |
import org.eclipse.jdt.internal.corext.dom.Selection; |
67 |
import org.eclipse.jdt.internal.corext.dom.Selection; |
|
|
68 |
import org.eclipse.jdt.internal.corext.dom.TypeBindingVisitor; |
65 |
import org.eclipse.jdt.internal.corext.dom.TypeRules; |
69 |
import org.eclipse.jdt.internal.corext.dom.TypeRules; |
66 |
import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatus; |
70 |
import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatus; |
67 |
import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowContext; |
71 |
import org.eclipse.jdt.internal.corext.refactoring.code.flow.FlowContext; |
Lines 85-98
Link Here
|
85 |
|
89 |
|
86 |
private Expression fInvocation; |
90 |
private Expression fInvocation; |
87 |
private ASTRewrite fRewriter; |
91 |
private ASTRewrite fRewriter; |
88 |
private List fStatements; |
|
|
89 |
private int fInsertionIndex; |
90 |
private boolean fNeedsStatement; |
91 |
private ASTNode fTargetNode; |
92 |
private FlowContext fFlowContext; |
92 |
private FlowContext fFlowContext; |
93 |
private FlowInfo fFlowInfo; |
93 |
private FlowInfo fFlowInfo; |
94 |
private CodeScopeBuilder.Scope fInvocationScope; |
94 |
private CodeScopeBuilder.Scope fInvocationScope; |
95 |
|
95 |
|
|
|
96 |
/** |
97 |
* Statements inserted before inlined one. |
98 |
*/ |
99 |
private List fStatementsBefore; |
100 |
/** |
101 |
* Statements inserted instead of inlined one. |
102 |
*/ |
103 |
private List fStatementReplacement; |
104 |
/** |
105 |
* Statements inserted after inlined one. |
106 |
*/ |
107 |
private List fStatementsAfter; |
108 |
/** |
109 |
* Expression inserted instead of method invocation. |
110 |
*/ |
111 |
private Expression fInvocationReplacement; |
112 |
private boolean fRemoveInvocation; |
113 |
|
96 |
private class InlineEvaluator extends HierarchicalASTVisitor { |
114 |
private class InlineEvaluator extends HierarchicalASTVisitor { |
97 |
private ParameterData fFormalArgument; |
115 |
private ParameterData fFormalArgument; |
98 |
private boolean fResult; |
116 |
private boolean fResult; |
Lines 206-215
Link Here
|
206 |
return fImportEdit; |
224 |
return fImportEdit; |
207 |
} |
225 |
} |
208 |
|
226 |
|
209 |
public ASTNode getTargetNode() { |
|
|
210 |
return fTargetNode; |
211 |
} |
212 |
|
213 |
public RefactoringStatus initialize(BodyDeclaration declaration) { |
227 |
public RefactoringStatus initialize(BodyDeclaration declaration) { |
214 |
fBodyDeclaration= declaration; |
228 |
fBodyDeclaration= declaration; |
215 |
RefactoringStatus result= new RefactoringStatus(); |
229 |
RefactoringStatus result= new RefactoringStatus(); |
Lines 226-248
Link Here
|
226 |
return result; |
240 |
return result; |
227 |
} |
241 |
} |
228 |
|
242 |
|
229 |
public RefactoringStatus initialize(Expression invocation) { |
243 |
public void initialize(Expression invocation) { |
230 |
RefactoringStatus result= new RefactoringStatus(); |
|
|
231 |
fInvocation= invocation; |
244 |
fInvocation= invocation; |
232 |
fRewriter= new ASTRewrite(ASTNodes.getParent(fInvocation, ASTNode.BLOCK)); |
245 |
fRewriter= new ASTRewrite(ASTNodes.getParent(fInvocation, ASTNode.BLOCK)); |
233 |
ASTNode parent= fInvocation.getParent(); |
|
|
234 |
int nodeType1= parent.getNodeType(); |
235 |
if (nodeType1 == ASTNode.EXPRESSION_STATEMENT || nodeType1 == ASTNode.RETURN_STATEMENT) { |
236 |
fTargetNode= parent; |
237 |
} else { |
238 |
fTargetNode= fInvocation; |
239 |
} |
240 |
return result; |
241 |
} |
246 |
} |
242 |
|
247 |
|
243 |
private void flowAnalysis() { |
248 |
private void flowAnalysis() { |
244 |
fInvocationScope= fRootScope.findScope(fTargetNode.getStartPosition(), fTargetNode.getLength()); |
249 |
fInvocationScope= fRootScope.findScope(fInvocation.getStartPosition(), fInvocation.getLength()); |
245 |
fInvocationScope.setCursor(fTargetNode.getStartPosition()); |
250 |
fInvocationScope.setCursor(fInvocation.getStartPosition()); |
246 |
fFlowContext= new FlowContext(0, fNumberOfLocals + 1); |
251 |
fFlowContext= new FlowContext(0, fNumberOfLocals + 1); |
247 |
fFlowContext.setConsiderAccessMode(true); |
252 |
fFlowContext.setConsiderAccessMode(true); |
248 |
fFlowContext.setComputeMode(FlowContext.ARGUMENTS); |
253 |
fFlowContext.setComputeMode(FlowContext.ARGUMENTS); |
Lines 258-449
Link Here
|
258 |
Assert.isTrue(false, "Should not happen"); //$NON-NLS-1$ |
263 |
Assert.isTrue(false, "Should not happen"); //$NON-NLS-1$ |
259 |
} |
264 |
} |
260 |
} |
265 |
} |
261 |
|
266 |
|
|
|
267 |
public static class ReturnCollector extends ASTVisitor { |
268 |
private List fResult= new ArrayList(); |
269 |
public ReturnCollector() { |
270 |
} |
271 |
public List getResult() { |
272 |
return fResult; |
273 |
} |
274 |
public boolean visit(ReturnStatement node) { |
275 |
fResult.add(node); |
276 |
return false; |
277 |
} |
278 |
public boolean visit(AnonymousClassDeclaration node) { |
279 |
return false; |
280 |
} |
281 |
public boolean visit(TypeDeclaration node) { |
282 |
return false; |
283 |
} |
284 |
} |
285 |
|
286 |
/** |
287 |
* The singleton class is used to reset code positions of visited nodes. |
288 |
* |
289 |
* This is a good candidate for moving into ASTNodes class. |
290 |
*/ |
291 |
public static class PositionClearer extends GenericVisitor { |
292 |
private static final PositionClearer instance= new PositionClearer(); |
293 |
private PositionClearer() { |
294 |
} |
295 |
public static PositionClearer getInstance() { |
296 |
return instance; |
297 |
} |
298 |
protected boolean visitNode(ASTNode node) { |
299 |
node.setSourceRange(-1, 0); |
300 |
return true; |
301 |
} |
302 |
} |
303 |
|
262 |
public TextEdit perform() throws CoreException { |
304 |
public TextEdit perform() throws CoreException { |
263 |
flowAnalysis(); |
305 |
flowAnalysis(); |
264 |
int callType= fTargetNode.getNodeType(); |
306 |
CallContext context= new CallContext(fInvocationScope, fImportEdit); |
265 |
CallContext context= new CallContext(fInvocationScope, callType, fImportEdit); |
|
|
266 |
|
307 |
|
267 |
List locals= new ArrayList(3); |
308 |
List locals= new ArrayList(3); |
268 |
|
309 |
context.arguments= computeRealArguments(locals); |
269 |
computeRealArguments(context, locals); |
|
|
270 |
computeReceiver(context, locals); |
310 |
computeReceiver(context, locals); |
271 |
|
|
|
272 |
String[] blocks= fSourceProvider.getCodeBlocks(context); |
273 |
initializeInsertionPoint(fSourceProvider.getNumberOfStatements() + locals.size()); |
274 |
|
311 |
|
275 |
addNewLocals(locals); |
312 |
List statements= fSourceProvider.getCodeStatements(context); |
276 |
replaceCall(callType, blocks); |
313 |
SourceProvider.replaceAST(fInvocation.getAST(), statements); |
|
|
314 |
addNewLocals(statements, locals); |
315 |
|
316 |
processReturnStatements(statements); |
317 |
replaceCall(); |
277 |
|
318 |
|
278 |
MultiTextEdit result= new MultiTextEdit(); |
319 |
MultiTextEdit result= new MultiTextEdit(); |
279 |
fRewriter.rewriteNode(fBuffer, result, null); |
320 |
fRewriter.rewriteNode(fBuffer, result); |
280 |
fRewriter.removeModifications(); |
321 |
fRewriter.removeModifications(); |
281 |
return result; |
322 |
return result; |
282 |
} |
323 |
} |
283 |
|
324 |
|
284 |
private void computeRealArguments(CallContext context, List locals) { |
325 |
/** |
|
|
326 |
* Adds new locals to the top of statements list. |
327 |
* |
328 |
* @param statements list of statements |
329 |
* @param locals list of new locals |
330 |
*/ |
331 |
private void addNewLocals(List statements, List locals) { |
332 |
int index= 0; |
333 |
for (Iterator it= locals.iterator(); it.hasNext(); ) { |
334 |
statements.add(index++, it.next()); |
335 |
} |
336 |
} |
337 |
|
338 |
private static ITypeBinding resolveInvocationTypeBinding(ASTNode invocation) { |
339 |
if(invocation instanceof MethodInvocation) { |
340 |
return ((MethodInvocation)invocation).resolveTypeBinding(); |
341 |
} |
342 |
else if(invocation instanceof SuperMethodInvocation) { |
343 |
return ((SuperMethodInvocation)invocation).resolveTypeBinding(); |
344 |
} |
345 |
return null; |
346 |
} |
347 |
|
348 |
private ASTNode[] computeRealArguments(List locals) { |
349 |
AST ast= fInvocation.getAST(); |
285 |
List arguments= Invocations.getArguments(fInvocation); |
350 |
List arguments= Invocations.getArguments(fInvocation); |
286 |
String[] realArguments= new String[arguments.size()]; |
351 |
ASTNode[] realArguments = new ASTNode[arguments.size()]; |
287 |
for (int i= 0; i < arguments.size(); i++) { |
352 |
for (int i= 0; i < arguments.size(); i++) { |
288 |
Expression expression= (Expression)arguments.get(i); |
353 |
Expression expression= (Expression)arguments.get(i); |
289 |
ParameterData parameter= fSourceProvider.getParameterData(i); |
354 |
ParameterData parameter= fSourceProvider.getParameterData(i); |
290 |
if (canInline(expression, parameter)) { |
355 |
if (canInline(expression, parameter)) { |
291 |
realArguments[i] = getContent(expression); |
356 |
realArguments[i]= ASTNode.copySubtree(expression.getAST(), expression); |
292 |
// fixes bug #35905 |
357 |
// fixes bug #35905 |
293 |
if(expression instanceof CastExpression) { |
358 |
if(expression instanceof CastExpression) { |
294 |
realArguments[i] = "(" + realArguments[i] + ")"; //$NON-NLS-1$ //$NON-NLS-2$ |
359 |
ParenthesizedExpression pe= ast.newParenthesizedExpression(); |
|
|
360 |
pe.setExpression((Expression)realArguments[i]); |
361 |
realArguments[i]= pe; |
295 |
} |
362 |
} |
296 |
} else { |
363 |
} else { |
297 |
String name= fInvocationScope.createName(parameter.getName(), true); |
364 |
String name= fInvocationScope.createName(parameter.getName(), true); |
298 |
realArguments[i]= name; |
365 |
realArguments[i]= fInvocation.getAST().newSimpleName(name); |
299 |
locals.add(createLocalDeclaration( |
366 |
locals.add(createVariableDeclaration( |
300 |
parameter.getTypeBinding(), name, |
367 |
parameter.getType().resolveBinding(), name, |
301 |
(Expression)fRewriter.createCopy(expression))); |
368 |
(Expression)ASTNode.copySubtree(expression.getAST(), expression))); |
302 |
} |
369 |
} |
303 |
} |
370 |
} |
304 |
context.arguments= realArguments; |
371 |
return realArguments; |
305 |
} |
372 |
} |
306 |
|
373 |
|
307 |
private void computeReceiver(CallContext context, List locals) { |
374 |
private void computeReceiver(CallContext context, List locals) { |
308 |
Expression receiver= Invocations.getExpression(fInvocation); |
375 |
Expression receiver= Invocations.getExpression(fInvocation); |
309 |
if (receiver == null) |
376 |
if (receiver == null) |
310 |
return; |
377 |
return; |
311 |
final boolean isName= receiver instanceof Name; |
378 |
if (ASTNodes.isLiteral(receiver) || receiver instanceof Name) { |
312 |
if (isName) |
379 |
context.receiver= receiver; |
313 |
context.receiverIsStatic= ((Name)receiver).resolveBinding() instanceof ITypeBinding; |
|
|
314 |
if (ASTNodes.isLiteral(receiver) || isName) { |
315 |
context.receiver= fBuffer.getContent(receiver.getStartPosition(), receiver.getLength()); |
316 |
return; |
380 |
return; |
317 |
} |
381 |
} |
318 |
switch(fSourceProvider.getReceiversToBeUpdated()) { |
382 |
switch(fSourceProvider.getReceiversToBeUpdated()) { |
319 |
case 0: |
383 |
case 0: |
320 |
// Make sure we evaluate the current receiver. Best is to assign to |
384 |
// Make sure we evaluate the current receiver. Best is to assign to local. |
321 |
// local. |
385 |
locals.add(createVariableDeclaration( |
322 |
locals.add(createLocalDeclaration( |
|
|
323 |
receiver.resolveTypeBinding(), |
386 |
receiver.resolveTypeBinding(), |
324 |
fInvocationScope.createName("r", true), //$NON-NLS-1$ |
387 |
fInvocationScope.createName("r", true), //$NON-NLS-1$ |
325 |
(Expression)fRewriter.createCopy(receiver))); |
388 |
(Expression)fRewriter.createCopy(receiver))); |
326 |
return; |
389 |
return; |
327 |
case 1: |
390 |
case 1: |
328 |
context.receiver= fBuffer.getContent(receiver.getStartPosition(), receiver.getLength()); |
391 |
context.receiver= receiver; |
329 |
return; |
392 |
return; |
330 |
default: |
393 |
default: |
331 |
String local= fInvocationScope.createName("r", true); //$NON-NLS-1$ |
394 |
String local= fInvocationScope.createName("r", true); //$NON-NLS-1$ |
332 |
locals.add(createLocalDeclaration( |
395 |
VariableDeclarationStatement receiverDeclaration= |
333 |
receiver.resolveTypeBinding(), |
396 |
createVariableDeclaration( |
334 |
local, |
397 |
receiver.resolveTypeBinding(), |
335 |
(Expression)fRewriter.createCopy(receiver))); |
398 |
local, |
336 |
context.receiver= local; |
399 |
(Expression)fRewriter.createCopy(receiver)); |
|
|
400 |
locals.add(receiverDeclaration); |
401 |
context.receiver= fInvocation.getAST().newSimpleName(local); |
337 |
return; |
402 |
return; |
338 |
} |
403 |
} |
339 |
} |
404 |
} |
340 |
|
405 |
|
341 |
private void addNewLocals(List locals) { |
406 |
/** |
342 |
for (Iterator iter= locals.iterator(); iter.hasNext();) { |
407 |
* The method analyses return statements and fills fStatementsAfter, |
343 |
ASTNode element= (ASTNode)iter.next(); |
408 |
* fStatementsBefore, fStatementReplacement and fInvocationReplacement |
344 |
fRewriter.markAsInserted(element); |
409 |
* member variables with statements that will be used during inlining. |
345 |
fStatements.add(fInsertionIndex++, element); |
410 |
* |
346 |
} |
411 |
* @param statements list of method statements to process |
347 |
} |
412 |
*/ |
348 |
|
413 |
private void processReturnStatements(List statements) { |
349 |
private void replaceCall(int callType, String[] blocks) throws CoreException { |
414 |
|
350 |
// Inline empty body |
415 |
List returnStatements= null; |
351 |
if (blocks.length == 0) { |
416 |
ReturnCollector returnCollector= new ReturnCollector(); |
352 |
if (fNeedsStatement) { |
417 |
ASTNodes.acceptNodes(statements, returnCollector); |
353 |
fRewriter.markAsReplaced(fTargetNode, fTargetNode.getAST().newEmptyStatement()); |
418 |
returnStatements= returnCollector.getResult(); |
354 |
} else { |
419 |
|
355 |
fRewriter.markAsRemoved(fTargetNode); |
420 |
AST ast= fInvocation.getAST(); |
|
|
421 |
ASTNode invocationParent= fInvocation.getParent(); |
422 |
int invocationParentType= invocationParent.getNodeType(); |
423 |
|
424 |
if (!fSourceProvider.hasReturnValue()) { |
425 |
// in case when inlined method returns void ... |
426 |
for (Iterator iter= returnStatements.iterator(); iter.hasNext();) { |
427 |
ReturnStatement rs= (ReturnStatement) iter.next(); |
428 |
ASTNode parent= rs.getParent(); |
429 |
// if parent of return statement is a control statements(if, for, do, while) |
430 |
// then empty statement is required in place of the return |
431 |
if (parent != null && isControlStatement(parent)) { |
432 |
substitute(statements, rs, ast.newEmptyStatement()); |
433 |
} else { |
434 |
// otheriwse it is safe to remove return statement completely |
435 |
substitute(statements, rs, null); |
436 |
} |
356 |
} |
437 |
} |
357 |
} else { |
438 |
if(invocationParentType == ASTNode.EXPRESSION_STATEMENT) { |
358 |
ASTNode node= null; |
439 |
fStatementReplacement= statements; |
359 |
for (int i= 0; i < blocks.length - 1; i++) { |
440 |
} |
360 |
node= fRewriter.createPlaceholder(blocks[i], ASTRewrite.STATEMENT); |
441 |
else { |
361 |
fRewriter.markAsInserted(node); |
442 |
fStatementsBefore= statements; |
362 |
fStatements.add(fInsertionIndex++, node); |
443 |
fRemoveInvocation= true; |
363 |
} |
444 |
} |
364 |
String block= blocks[blocks.length - 1]; |
445 |
} else if(invocationParentType == ASTNode.RETURN_STATEMENT) { |
365 |
// We can inline a call where the declaration is a function and the call itself |
446 |
fStatementReplacement= statements; |
366 |
// is a statement. In this case we have to create a temporary variable if the |
447 |
} else if (invocationParentType == ASTNode.EXPRESSION_STATEMENT) { |
367 |
// returned expression must be evaluated. |
448 |
for (Iterator iter= returnStatements.iterator(); iter.hasNext();) { |
368 |
if (callType == ASTNode.EXPRESSION_STATEMENT && fSourceProvider.hasReturnValue()) { |
449 |
ReturnStatement rs= (ReturnStatement) iter.next(); |
369 |
if (fSourceProvider.mustEvaluateReturnedExpression()) { |
450 |
Expression returnExpression= rs.getExpression(); |
370 |
if (fSourceProvider.returnValueNeedsLocalVariable()) { |
451 |
// check if return expression must be evaluated |
371 |
node= createLocalDeclaration( |
452 |
if (ASTNodes.isLiteral(returnExpression) || returnExpression instanceof Name) { |
372 |
fSourceProvider.getReturnType(), |
453 |
// completely remove return and its expression |
373 |
fInvocationScope.createName(fSourceProvider.getMethodName(), true), |
454 |
substitute(statements, rs, null); |
374 |
(Expression)fRewriter.createPlaceholder(block, ASTRewrite.EXPRESSION)); |
455 |
} else { |
|
|
456 |
// check if return expression needs a local variable |
457 |
if (ASTNodes.isInvocation(returnExpression) || returnExpression instanceof ClassInstanceCreation) { |
458 |
// substitute parent expression with return expression |
459 |
substitute(statements, rs, |
460 |
ast.newExpressionStatement((Expression)ASTNode.copySubtree(ast, rs.getExpression()))); |
375 |
} else { |
461 |
} else { |
376 |
node= fTargetNode.getAST().newExpressionStatement( |
462 |
// create a local variable to keep result of return expression |
377 |
(Expression)fRewriter.createPlaceholder(block, ASTRewrite.EXPRESSION)); |
463 |
VariableDeclarationStatement node= createVariableDeclaration( |
|
|
464 |
fSourceProvider.getReturnType().resolveBinding(), |
465 |
fInvocationScope.createName(fSourceProvider.getMethodName(), true), |
466 |
(Expression)ASTNode.copySubtree(ast, returnExpression)); |
467 |
substitute(statements, rs, node); |
378 |
} |
468 |
} |
379 |
} else { |
|
|
380 |
node= null; |
381 |
} |
469 |
} |
382 |
} else if (fTargetNode instanceof Expression) { |
470 |
} |
383 |
node= fRewriter.createPlaceholder(block, ASTRewrite.EXPRESSION); |
471 |
fStatementReplacement= statements; |
384 |
|
472 |
} else if (invocationParent instanceof Expression) { |
|
|
473 |
for (Iterator iter= returnStatements.iterator(); iter.hasNext();) { |
474 |
ReturnStatement rs= (ReturnStatement) iter.next(); |
475 |
Expression returnExpression= rs.getExpression(); |
476 |
Expression node= (Expression)ASTNode.copySubtree(ast, returnExpression); |
385 |
// fixes bug #24941 |
477 |
// fixes bug #24941 |
386 |
if(needsExplicitCast()) { |
478 |
if (needsExplicitCast(rs)) { |
387 |
AST ast= node.getAST(); |
|
|
388 |
CastExpression castExpression= ast.newCastExpression(); |
479 |
CastExpression castExpression= ast.newCastExpression(); |
389 |
ITypeBinding returnType= fSourceProvider.getReturnType(); |
480 |
Type returnType= fSourceProvider.getReturnType(); |
390 |
fImportEdit.addImport(returnType); |
481 |
fImportEdit.addImport(returnType.resolveBinding()); |
391 |
castExpression.setType(ASTNodeFactory.newType(ast, returnType, false)); |
482 |
castExpression.setType((Type)ASTNode.copySubtree(ast, returnType)); |
392 |
castExpression.setExpression((Expression)node); |
483 |
castExpression.setExpression(node); |
393 |
node= castExpression; |
484 |
node= castExpression; |
394 |
} |
485 |
} |
395 |
|
486 |
if (needsParenthesis(rs)) { |
396 |
if (needsParenthesis()) { |
487 |
ParenthesizedExpression pe= ast.newParenthesizedExpression(); |
397 |
ParenthesizedExpression pExp= fTargetNode.getAST().newParenthesizedExpression(); |
488 |
pe.setExpression(node); |
398 |
pExp.setExpression((Expression)node); |
489 |
node= pe; |
399 |
node= pExp; |
490 |
} |
|
|
491 |
if (returnStatements.size() == 1) { |
492 |
fInvocationReplacement= node; |
493 |
fStatementsBefore= statements; |
494 |
statements.remove(rs); |
495 |
} |
496 |
else { |
497 |
substitute(statements, rs, ast.newExpressionStatement(node)); |
498 |
} |
499 |
} |
500 |
} else if(invocationParentType == ASTNode.VARIABLE_DECLARATION_FRAGMENT) { |
501 |
if(returnStatements.size() > 1) { |
502 |
// method invocation in variable declaration fragment can be used only as initializer |
503 |
VariableDeclarationFragment fragment= (VariableDeclarationFragment)invocationParent; |
504 |
fInvocationReplacement= createDefaultInitializer(invocationParent.getAST(), |
505 |
resolveInvocationTypeBinding(fInvocation)); |
506 |
Expression variable= fragment.getName(); |
507 |
substituteReturnsWithAssignments(variable, returnStatements, statements); |
508 |
fStatementsAfter= statements; |
509 |
} |
510 |
else { // returnStatements.size() == 1 |
511 |
ReturnStatement rs= (ReturnStatement) returnStatements.get(0); |
512 |
Expression returnExpression= rs.getExpression(); |
513 |
fInvocationReplacement= (Expression)ASTNode.copySubtree(ast, returnExpression); |
514 |
substitute(statements, rs, null); |
515 |
fStatementsBefore= statements; |
516 |
} |
517 |
} else { |
518 |
// case example: |
519 |
// for(inlineMe(); i < 10; i++); |
520 |
if(returnStatements.size() > 1) { |
521 |
// if method has multiple returns then temporary variable will be created and all |
522 |
// returns will be substituted with assignments to it. |
523 |
VariableDeclarationStatement variableStatement= createVariableDeclaration( |
524 |
fSourceProvider.getReturnType().resolveBinding(), |
525 |
fInvocationScope.createName("temp", true), //$NON-NLS-1$ |
526 |
createDefaultInitializer(ast, fSourceProvider.getReturnType().resolveBinding())); |
527 |
statements.add(0, variableStatement); |
528 |
VariableDeclarationFragment fragment= (VariableDeclarationFragment)variableStatement.fragments().get(0); |
529 |
Expression variable= fragment.getName(); |
530 |
substituteReturnsWithAssignments(variable, returnStatements, statements); |
531 |
fStatementsBefore= statements; |
532 |
fRemoveInvocation= true; |
533 |
} |
534 |
else { // returnStatements.size() == 1 |
535 |
ReturnStatement rs= (ReturnStatement) returnStatements.get(0); |
536 |
Expression returnExpression= rs.getExpression(); |
537 |
// check if return expression must be evaluated |
538 |
if (ASTNodes.isLiteral(returnExpression) || returnExpression instanceof Name) { |
539 |
substitute(statements, rs, null); |
540 |
fStatementsBefore= statements; |
541 |
fRemoveInvocation= true; |
542 |
} |
543 |
else { |
544 |
fInvocationReplacement= (Expression)ASTNode.copySubtree(ast, returnExpression); |
545 |
substitute(statements, rs, null); |
546 |
fStatementsBefore= statements; |
400 |
} |
547 |
} |
401 |
} else { |
|
|
402 |
node= fRewriter.createPlaceholder(block, ASTRewrite.STATEMENT); |
403 |
} |
548 |
} |
404 |
|
549 |
} |
405 |
// Now replace the target node with the source node |
550 |
} |
406 |
if (node != null) { |
551 |
|
407 |
if (fTargetNode == null) { |
552 |
/** |
408 |
fRewriter.markAsInserted(node); |
553 |
* The helper method substitutes return statements with assignments |
409 |
fStatements.add(fInsertionIndex++, node); |
554 |
* expressions wrapped inside expression statements. |
410 |
} else { |
555 |
* |
411 |
fRewriter.markAsReplaced(fTargetNode, node); |
556 |
* @param variable AST node representing variable to assign to |
|
|
557 |
* @param returnStatements list of return statements |
558 |
* @param statements list of original statements |
559 |
*/ |
560 |
private void substituteReturnsWithAssignments(Expression variable, List returnStatements, List statements) { |
561 |
AST ast= variable.getAST(); |
562 |
for (Iterator iter= returnStatements.iterator(); iter.hasNext();) { |
563 |
ReturnStatement rs= (ReturnStatement) iter.next(); |
564 |
Expression returnExpression= rs.getExpression(); |
565 |
ASTNode parent= rs.getParent(); |
566 |
// every return is substituted with an assignement to the variable. |
567 |
// prior to that method initializeTarget has replaced variable |
568 |
// initializer with a default value (0 or null). |
569 |
Assignment assignment= ast.newAssignment(); |
570 |
assignment.setLeftHandSide((Expression)ASTNode.copySubtree(ast, variable)); |
571 |
assignment.setRightHandSide((Expression)ASTNode.copySubtree(ast, returnExpression)); |
572 |
substitute(statements, rs, ast.newExpressionStatement(assignment)); |
573 |
} |
574 |
} |
575 |
|
576 |
/** |
577 |
* @param ast |
578 |
* @param variableBinding |
579 |
* @return |
580 |
*/ |
581 |
private Expression createDefaultInitializer(AST ast, ITypeBinding typeBinding) { |
582 |
if(typeBinding.isPrimitive()) { |
583 |
if(typeBinding.getName().equals(PrimitiveType.BOOLEAN.toString())) { |
584 |
return ast.newBooleanLiteral(false); |
585 |
} |
586 |
else { |
587 |
return ast.newNumberLiteral(); |
588 |
} |
589 |
} |
590 |
return ast.newNullLiteral(); |
591 |
} |
592 |
|
593 |
/** |
594 |
* Helper method for substitution of one node with another in a list of statements. |
595 |
* |
596 |
* Special processing is required for top level nodes since their parents are null. |
597 |
* |
598 |
* @param statements list of original statements |
599 |
* @param source source node, must exist in the hierarchy of statements |
600 |
* @param replacement node replacing the source one |
601 |
*/ |
602 |
private static void substitute(List statements, ASTNode source, ASTNode replacement) { |
603 |
if(source.getParent() == null) { |
604 |
if(replacement == null) { |
605 |
statements.remove(source); |
606 |
} |
607 |
else { |
608 |
int index= statements.indexOf(source); |
609 |
statements.set(index, replacement); |
610 |
} |
611 |
} |
612 |
else { |
613 |
ASTNodes.substitute(source, replacement); |
614 |
} |
615 |
} |
616 |
|
617 |
/** |
618 |
* The method does actual code modificiations. |
619 |
* |
620 |
* It uses only fStatementsBefore, fStatementsAfter, fStatementReplacement |
621 |
* and fInvocationReplacement member variables prepared by other methods. |
622 |
* |
623 |
* The method adds empty statements and blocks where it is needed. |
624 |
*/ |
625 |
private void replaceCall() throws CoreException { |
626 |
|
627 |
AST ast= fInvocation.getAST(); |
628 |
Statement invocationStatement= (Statement)ASTNodes.getParent(fInvocation, Statement.class); |
629 |
Statement parentStatement= (Statement)invocationStatement.getParent(); |
630 |
|
631 |
int numberOfStatements= 0; |
632 |
if (fStatementsBefore != null) { |
633 |
numberOfStatements+= fStatementsBefore.size(); |
634 |
ASTNodes.acceptNodes(fStatementsBefore, PositionClearer.getInstance()); |
635 |
} |
636 |
if (fStatementsAfter != null) { |
637 |
numberOfStatements+= fStatementsAfter.size(); |
638 |
ASTNodes.acceptNodes(fStatementsAfter, PositionClearer.getInstance()); |
639 |
} |
640 |
if (fStatementReplacement != null) { |
641 |
numberOfStatements+= fStatementReplacement.size(); |
642 |
ASTNodes.acceptNodes(fStatementReplacement, PositionClearer.getInstance()); |
643 |
} |
644 |
else { |
645 |
numberOfStatements++; |
646 |
} |
647 |
if(fInvocationReplacement != null) { |
648 |
fInvocationReplacement.accept(PositionClearer.getInstance()); |
649 |
} |
650 |
|
651 |
List parentStatements= null; |
652 |
if (parentStatement.getNodeType() == ASTNode.BLOCK) { |
653 |
parentStatements= ((Block)parentStatement).statements(); |
654 |
} |
655 |
else if (parentStatement.getNodeType() == ASTNode.SWITCH_STATEMENT) { |
656 |
parentStatements= ((SwitchStatement)parentStatement).statements(); |
657 |
} |
658 |
else if (numberOfStatements > 1) { |
659 |
Block block= ast.newBlock(); |
660 |
List blockStatements= block.statements(); |
661 |
if (fStatementsBefore != null) { |
662 |
blockStatements.addAll(fStatementsBefore); |
663 |
} |
664 |
if (fStatementReplacement != null) { |
665 |
blockStatements.addAll(fStatementReplacement); |
666 |
} |
667 |
else if (fInvocationReplacement != null) { |
668 |
// modifying original AST(not the copy!) |
669 |
ASTNodes.substitute(fInvocation, fInvocationReplacement); |
670 |
blockStatements.add(ASTNode.copySubtree(ast, invocationStatement)); |
671 |
// restoring original AST |
672 |
ASTNodes.substitute(fInvocationReplacement, fInvocation); |
673 |
} |
674 |
if (fStatementsAfter!= null) { |
675 |
blockStatements.addAll(fStatementsAfter); |
676 |
} |
677 |
fStatementReplacement= new ArrayList(); |
678 |
fStatementReplacement.add(block); |
679 |
} |
680 |
else if (numberOfStatements == 0) { |
681 |
if (isControlStatement(parentStatement)/* && fInvocationReplacement == null*/) { |
682 |
fStatementReplacement.add(ast.newEmptyStatement()); |
683 |
} |
684 |
} |
685 |
if(fStatementReplacement == null) { |
686 |
if (fInvocationReplacement != null) { |
687 |
// statement replacement has higher priority over invocation replacement |
688 |
// so if fStatementReplacement is not null it will be used instead of |
689 |
// fInvocationReplacement. |
690 |
fRewriter.markAsReplaced(fInvocation, fInvocationReplacement); |
691 |
} |
692 |
else if(fRemoveInvocation) { |
693 |
fRewriter.markAsRemoved(fInvocation); |
694 |
} |
695 |
} |
696 |
|
697 |
if (parentStatements != null) { |
698 |
int index= parentStatements.indexOf(invocationStatement); |
699 |
if(fStatementsBefore != null) { |
700 |
for (int i= 0; i < fStatementsBefore.size(); i++) { |
701 |
parentStatements.add(index++, fStatementsBefore.get(i)); |
702 |
fRewriter.markAsInserted((ASTNode)fStatementsBefore.get(i), true); |
412 |
} |
703 |
} |
413 |
} else { |
704 |
} |
414 |
if (fTargetNode != null) { |
705 |
if(fStatementReplacement != null) { |
415 |
fRewriter.markAsRemoved(fTargetNode); |
706 |
fRewriter.markAsReplaced(invocationStatement, parentStatements, |
|
|
707 |
(ASTNode[])fStatementReplacement.toArray(new ASTNode[fStatementReplacement.size()])); |
708 |
} |
709 |
if(fStatementsAfter != null) { |
710 |
index++; |
711 |
for (int i= 0; i < fStatementsAfter.size(); i++) { |
712 |
parentStatements.add(index++, fStatementsAfter.get(i)); |
713 |
fRewriter.markAsInserted((ASTNode)fStatementsAfter.get(i), true); |
416 |
} |
714 |
} |
417 |
} |
715 |
} |
418 |
} |
716 |
} |
|
|
717 |
else if(fStatementReplacement != null) { |
718 |
fRewriter.markAsReplaced(invocationStatement, (ASTNode)fStatementReplacement.get(0)); |
719 |
} |
419 |
} |
720 |
} |
420 |
|
721 |
|
421 |
/** |
722 |
/** |
422 |
* @return <code>true</code> if explicit cast is needed otherwise <code>false</code> |
723 |
* @return <code>true</code> if explicit cast is needed otherwise <code>false</code> |
423 |
* @throws JavaModelException |
724 |
* @throws JavaModelException |
424 |
*/ |
725 |
*/ |
425 |
private boolean needsExplicitCast() { |
726 |
private boolean needsExplicitCast(ReturnStatement rs) { |
426 |
// if the return type of the method is the same as the type of the |
727 |
// if the return type of the method is the same as the type of the |
427 |
// returned expression then we don't need an explicit cast. |
728 |
// returned expression then we don't need an explicit cast. |
428 |
if (fSourceProvider.returnTypeMatchesReturnExpressions()) |
729 |
if (returnTypeMatchesReturnExpressions(rs)) |
429 |
return false; |
730 |
return false; |
430 |
ASTNode parent= fTargetNode.getParent(); |
731 |
ASTNode parent= fInvocation.getParent(); |
431 |
int nodeType= parent.getNodeType(); |
732 |
int nodeType= parent.getNodeType(); |
432 |
if (nodeType == ASTNode.METHOD_INVOCATION) { |
733 |
if (nodeType == ASTNode.METHOD_INVOCATION) { |
433 |
MethodInvocation methodInvocation= (MethodInvocation)parent; |
734 |
MethodInvocation methodInvocation= (MethodInvocation)parent; |
434 |
if(methodInvocation.getExpression() == fTargetNode) |
735 |
if(methodInvocation.getExpression() == fInvocation) |
435 |
return false; |
736 |
return false; |
436 |
IMethodBinding method= methodInvocation.resolveMethodBinding(); |
737 |
IMethodBinding method= methodInvocation.resolveMethodBinding(); |
437 |
ITypeBinding[] parameters= method.getParameterTypes(); |
738 |
ITypeBinding[] parameters= method.getParameterTypes(); |
438 |
int argumentIndex= methodInvocation.arguments().indexOf(fInvocation); |
739 |
int argumentIndex= methodInvocation.arguments().indexOf(fInvocation); |
439 |
List returnExprs= fSourceProvider.getReturnExpressions(); |
740 |
parameters[argumentIndex]= (ITypeBinding)fSourceProvider.resolveTypeBinding( |
440 |
// it is infered that only methods consisting of a single |
741 |
rs.getExpression().getStartPosition()); |
441 |
// return statement can be inlined as parameters in other |
742 |
|
442 |
// method invocations |
|
|
443 |
if (returnExprs.size() != 1) |
444 |
return false; |
445 |
parameters[argumentIndex]= ((Expression)returnExprs.get(0)).resolveTypeBinding(); |
446 |
|
447 |
ITypeBinding type= ASTNodes.getReceiverTypeBinding(methodInvocation); |
743 |
ITypeBinding type= ASTNodes.getReceiverTypeBinding(methodInvocation); |
448 |
TypeBindingVisitor visitor= new AmbiguousMethodAnalyzer(method, parameters); |
744 |
TypeBindingVisitor visitor= new AmbiguousMethodAnalyzer(method, parameters); |
449 |
if(!visitor.visit(type)) { |
745 |
if(!visitor.visit(type)) { |
Lines 463-482
Link Here
|
463 |
return false; |
759 |
return false; |
464 |
} |
760 |
} |
465 |
|
761 |
|
466 |
private boolean needsParenthesis() { |
762 |
public boolean returnTypeMatchesReturnExpressions(ReturnStatement returnStatement) { |
467 |
if (!fSourceProvider.needsReturnedExpressionParenthesis()) |
763 |
ITypeBinding returnType= fSourceProvider.getReturnType().resolveBinding(); |
|
|
764 |
Expression expression= returnStatement.getExpression(); |
765 |
if (expression != null) { |
766 |
if (!Bindings.equals(returnType, expression.resolveTypeBinding())) |
767 |
return false; |
768 |
} |
769 |
return true; |
770 |
} |
771 |
|
772 |
private boolean needsParenthesis(ReturnStatement rs) { |
773 |
if (!ASTNodes.needsParentheses(rs.getExpression())) |
468 |
return false; |
774 |
return false; |
469 |
ASTNode parent= fTargetNode.getParent(); |
775 |
ASTNode parent= fInvocation.getParent(); |
470 |
int type= parent.getNodeType(); |
776 |
int type= parent.getNodeType(); |
471 |
return type == ASTNode.METHOD_INVOCATION || (parent instanceof Expression && type != ASTNode.ASSIGNMENT); |
777 |
return type == ASTNode.METHOD_INVOCATION || (parent instanceof Expression && type != ASTNode.ASSIGNMENT); |
472 |
} |
778 |
} |
473 |
|
779 |
|
474 |
private VariableDeclarationStatement createLocalDeclaration(ITypeBinding type, String name, Expression initializer) { |
780 |
private VariableDeclarationStatement createVariableDeclaration(ITypeBinding typeBinding, String name, Expression initializer) { |
475 |
String typeName= fImportEdit.addImport(type); |
781 |
AST ast= initializer.getAST(); |
476 |
VariableDeclarationStatement decl= (VariableDeclarationStatement)ASTNodeFactory.newStatement( |
782 |
String typeName= fImportEdit.addImport(typeBinding); |
477 |
fInvocation.getAST(), typeName + " " + name + ";"); //$NON-NLS-1$ //$NON-NLS-2$ |
783 |
VariableDeclarationFragment fragment= ast.newVariableDeclarationFragment(); |
478 |
((VariableDeclarationFragment)decl.fragments().get(0)).setInitializer(initializer); |
784 |
fragment.setName(ast.newSimpleName(name)); |
479 |
return decl; |
785 |
fragment.setInitializer(initializer); |
|
|
786 |
VariableDeclarationStatement result= ast.newVariableDeclarationStatement(fragment); |
787 |
result.setType(ASTNodeFactory.newType(ast, typeBinding.getName())); |
788 |
return result; |
480 |
} |
789 |
} |
481 |
|
790 |
|
482 |
private boolean canInline(Expression actualParameter, ParameterData formalParameter) { |
791 |
private boolean canInline(Expression actualParameter, ParameterData formalParameter) { |
Lines 484-552
Link Here
|
484 |
actualParameter.accept(evaluator); |
793 |
actualParameter.accept(evaluator); |
485 |
return evaluator.getResult(); |
794 |
return evaluator.getResult(); |
486 |
} |
795 |
} |
487 |
|
|
|
488 |
private void initializeInsertionPoint(int nos) { |
489 |
fStatements= null; |
490 |
fInsertionIndex= -1; |
491 |
fNeedsStatement= false; |
492 |
ASTNode parentStatement= ASTNodes.getParent(fInvocation, Statement.class); |
493 |
ASTNode container= parentStatement.getParent(); |
494 |
int type= container.getNodeType(); |
495 |
if (type == ASTNode.BLOCK) { |
496 |
fStatements= ((Block)container).statements(); |
497 |
fInsertionIndex= fStatements.indexOf(parentStatement); |
498 |
} else if (isControlStatement(container)) { |
499 |
fNeedsStatement= true; |
500 |
if (nos > 1) { |
501 |
Block block= fInvocation.getAST().newBlock(); |
502 |
fStatements= block.statements(); |
503 |
fInsertionIndex= 0; |
504 |
Statement currentStatement= null; |
505 |
switch(type) { |
506 |
case ASTNode.FOR_STATEMENT: |
507 |
currentStatement= ((ForStatement)container).getBody(); |
508 |
break; |
509 |
case ASTNode.WHILE_STATEMENT: |
510 |
currentStatement= ((WhileStatement)container).getBody(); |
511 |
break; |
512 |
case ASTNode.DO_STATEMENT: |
513 |
currentStatement= ((DoStatement)container).getBody(); |
514 |
break; |
515 |
case ASTNode.IF_STATEMENT: |
516 |
IfStatement node= (IfStatement)container; |
517 |
Statement thenPart= node.getThenStatement(); |
518 |
if (fTargetNode == thenPart || ASTNodes.isParent(fTargetNode, thenPart)) { |
519 |
currentStatement= thenPart; |
520 |
} else { |
521 |
currentStatement= node.getElseStatement(); |
522 |
} |
523 |
break; |
524 |
} |
525 |
Assert.isNotNull(currentStatement); |
526 |
// The method to be inlined is not the body of the control statement. |
527 |
if (currentStatement != fTargetNode) { |
528 |
ASTNode copy= fRewriter.createCopy(currentStatement); |
529 |
fStatements.add(copy); |
530 |
} else { |
531 |
// We can't replace a copy with something else. So we |
532 |
// have to insert all statements to be inlined. |
533 |
fTargetNode= null; |
534 |
} |
535 |
fRewriter.markAsReplaced(currentStatement, block); |
536 |
} |
537 |
} |
538 |
// We only insert one new statement or we delete the existing call. |
539 |
// So there is no need to have an insertion index. |
540 |
} |
541 |
|
542 |
private String getContent(ASTNode node) { |
543 |
return fBuffer.getContent(node.getStartPosition(), node.getLength()); |
544 |
} |
545 |
|
796 |
|
546 |
private static IFile getFile(ICompilationUnit cu) throws CoreException { |
797 |
private static IFile getFile(ICompilationUnit cu) throws CoreException { |
547 |
return (IFile)WorkingCopyUtil.getOriginal(cu).getResource(); |
798 |
return (IFile)WorkingCopyUtil.getOriginal(cu).getResource(); |
548 |
} |
799 |
} |
549 |
|
800 |
|
550 |
private boolean isControlStatement(ASTNode node) { |
801 |
private boolean isControlStatement(ASTNode node) { |
551 |
int type= node.getNodeType(); |
802 |
int type= node.getNodeType(); |
552 |
return type == ASTNode.IF_STATEMENT || type == ASTNode.FOR_STATEMENT || |
803 |
return type == ASTNode.IF_STATEMENT || type == ASTNode.FOR_STATEMENT || |