KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > ui > text > correction > AdvancedQuickAssistProcessor


1 /*******************************************************************************
2  * Copyright (c) 2000, 2006 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  * Konstantin Scheglov (scheglov_ke@nlmk.ru) - initial API and implementation
10  * (reports 71244 & 74746: New Quick Assist's [quick assist])
11  *******************************************************************************/

12 package org.eclipse.jdt.internal.ui.text.correction;
13
14 import java.util.ArrayList JavaDoc;
15 import java.util.Collection JavaDoc;
16 import java.util.HashSet JavaDoc;
17 import java.util.Hashtable JavaDoc;
18 import java.util.Iterator JavaDoc;
19 import java.util.List JavaDoc;
20 import java.util.Map JavaDoc;
21
22 import org.eclipse.core.runtime.CoreException;
23
24 import org.eclipse.swt.graphics.Image;
25
26 import org.eclipse.jdt.core.ICompilationUnit;
27 import org.eclipse.jdt.core.dom.AST;
28 import org.eclipse.jdt.core.dom.ASTNode;
29 import org.eclipse.jdt.core.dom.Assignment;
30 import org.eclipse.jdt.core.dom.Block;
31 import org.eclipse.jdt.core.dom.BooleanLiteral;
32 import org.eclipse.jdt.core.dom.BreakStatement;
33 import org.eclipse.jdt.core.dom.CastExpression;
34 import org.eclipse.jdt.core.dom.ChildListPropertyDescriptor;
35 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
36 import org.eclipse.jdt.core.dom.ConditionalExpression;
37 import org.eclipse.jdt.core.dom.ConstructorInvocation;
38 import org.eclipse.jdt.core.dom.ContinueStatement;
39 import org.eclipse.jdt.core.dom.DoStatement;
40 import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
41 import org.eclipse.jdt.core.dom.Expression;
42 import org.eclipse.jdt.core.dom.ExpressionStatement;
43 import org.eclipse.jdt.core.dom.ForStatement;
44 import org.eclipse.jdt.core.dom.IBinding;
45 import org.eclipse.jdt.core.dom.ITypeBinding;
46 import org.eclipse.jdt.core.dom.IVariableBinding;
47 import org.eclipse.jdt.core.dom.IfStatement;
48 import org.eclipse.jdt.core.dom.InfixExpression;
49 import org.eclipse.jdt.core.dom.InstanceofExpression;
50 import org.eclipse.jdt.core.dom.MethodDeclaration;
51 import org.eclipse.jdt.core.dom.MethodInvocation;
52 import org.eclipse.jdt.core.dom.Name;
53 import org.eclipse.jdt.core.dom.ParenthesizedExpression;
54 import org.eclipse.jdt.core.dom.PostfixExpression;
55 import org.eclipse.jdt.core.dom.PrefixExpression;
56 import org.eclipse.jdt.core.dom.PrimitiveType;
57 import org.eclipse.jdt.core.dom.QualifiedName;
58 import org.eclipse.jdt.core.dom.ReturnStatement;
59 import org.eclipse.jdt.core.dom.SimpleName;
60 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
61 import org.eclipse.jdt.core.dom.Statement;
62 import org.eclipse.jdt.core.dom.StringLiteral;
63 import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor;
64 import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
65 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
66 import org.eclipse.jdt.core.dom.SwitchCase;
67 import org.eclipse.jdt.core.dom.SwitchStatement;
68 import org.eclipse.jdt.core.dom.Type;
69 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
70 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
71 import org.eclipse.jdt.core.dom.WhileStatement;
72 import org.eclipse.jdt.core.dom.InfixExpression.Operator;
73 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
74 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
75 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
76
77 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
78 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
79 import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
80 import org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder;
81 import org.eclipse.jdt.internal.corext.fix.CleanUpConstants;
82 import org.eclipse.jdt.internal.corext.fix.ExpressionsFix;
83 import org.eclipse.jdt.internal.corext.fix.IFix;
84 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
85 import org.eclipse.jdt.internal.corext.util.Messages;
86
87 import org.eclipse.jdt.ui.CodeStyleConfiguration;
88 import org.eclipse.jdt.ui.text.java.IInvocationContext;
89 import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
90 import org.eclipse.jdt.ui.text.java.IProblemLocation;
91 import org.eclipse.jdt.ui.text.java.IQuickAssistProcessor;
92
93 import org.eclipse.jdt.internal.ui.JavaPluginImages;
94 import org.eclipse.jdt.internal.ui.fix.ExpressionsCleanUp;
95
96 /**
97  */

98 public class AdvancedQuickAssistProcessor implements IQuickAssistProcessor {
99     public AdvancedQuickAssistProcessor() {
100         super();
101     }
102     /* (non-Javadoc)
103      * @see org.eclipse.jdt.internal.ui.text.correction.IAssistProcessor#hasAssists(org.eclipse.jdt.internal.ui.text.correction.IAssistContext)
104      */

105     public boolean hasAssists(IInvocationContext context) throws CoreException {
106         ASTNode coveringNode = context.getCoveringNode();
107         if (coveringNode != null) {
108             ArrayList JavaDoc coveredNodes= getFullyCoveredNodes(context, coveringNode);
109             return getInverseIfProposals(context, coveringNode, null)
110                     || getIfReturnIntoIfElseAtEndOfVoidMethodProposals(context, coveringNode, null)
111                     || getInverseIfContinueIntoIfThenInLoopsProposals(context, coveringNode, null)
112                     || getInverseIfIntoContinueInLoopsProposals(context, coveringNode, null)
113                     || getInverseConditionProposals(context, coveringNode, coveredNodes, null)
114                     || getRemoveExtraParenthesisProposals(context, coveringNode, coveredNodes, null)
115                     || getAddParanoidalParenthesisProposals(context, coveringNode, coveredNodes, null)
116                     || getJoinAndIfStatementsProposals(context, coveringNode, null)
117                     || getSplitAndConditionProposals(context, coveringNode, null)
118                     || getJoinOrIfStatementsProposals(context, coveringNode, coveredNodes, null)
119                     || getSplitOrConditionProposals(context, coveringNode, null)
120                     || getInverseConditionalExpressionProposals(context, coveringNode, null)
121                     || getExchangeInnerAndOuterIfConditionsProposals(context, coveringNode, null)
122                     || getExchangeOperandsProposals(context, coveringNode, null)
123                     || getCastAndAssignIfStatementProposals(context, coveringNode, null)
124                     || getPickOutStringProposals(context, coveringNode, null)
125                     || getReplaceIfElseWithConditionalProposals(context, coveringNode, null)
126                     || getReplaceConditionalWithIfElseProposals(context, coveringNode, null)
127                     || getInverseLocalVariableProposals(context, coveringNode, null)
128                     || getPushNegationDownProposals(context, coveringNode, null)
129                     || getPullNegationUpProposals(context, coveringNode, coveredNodes, null)
130                     || getJoinIfListInIfElseIfProposals(context, coveringNode, coveredNodes, null)
131                     || getConvertSwitchToIfProposals(context, coveringNode, null);
132         }
133         return false;
134     }
135     /* (non-Javadoc)
136      * @see org.eclipse.jdt.internal.ui.text.correction.IAssistProcessor#getAssists(org.eclipse.jdt.internal.ui.text.correction.IAssistContext, org.eclipse.jdt.internal.ui.text.correction.IProblemLocation[])
137      */

138     public IJavaCompletionProposal[] getAssists(IInvocationContext context, IProblemLocation[] locations)
139             throws CoreException {
140         ASTNode coveringNode = context.getCoveringNode();
141         if (coveringNode != null) {
142             ArrayList JavaDoc coveredNodes = getFullyCoveredNodes(context, coveringNode);
143             ArrayList JavaDoc resultingCollections = new ArrayList JavaDoc();
144             if (noErrorsAtLocation(locations)) {
145                 getInverseIfProposals(context, coveringNode, resultingCollections);
146                 getIfReturnIntoIfElseAtEndOfVoidMethodProposals(context, coveringNode, resultingCollections);
147                 getInverseIfContinueIntoIfThenInLoopsProposals(context, coveringNode, resultingCollections);
148                 getInverseIfIntoContinueInLoopsProposals(context, coveringNode, resultingCollections);
149                 getInverseConditionProposals(context, coveringNode, coveredNodes, resultingCollections);
150                 getRemoveExtraParenthesisProposals(context, coveringNode, coveredNodes, resultingCollections);
151                 getAddParanoidalParenthesisProposals(context, coveringNode, coveredNodes, resultingCollections);
152                 getJoinAndIfStatementsProposals(context, coveringNode, resultingCollections);
153                 getSplitAndConditionProposals(context, coveringNode, resultingCollections);
154                 getJoinOrIfStatementsProposals(context, coveringNode, coveredNodes, resultingCollections);
155                 getSplitOrConditionProposals(context, coveringNode, resultingCollections);
156                 getInverseConditionalExpressionProposals(context, coveringNode, resultingCollections);
157                 getExchangeInnerAndOuterIfConditionsProposals(context, coveringNode, resultingCollections);
158                 getExchangeOperandsProposals(context, coveringNode, resultingCollections);
159                 getCastAndAssignIfStatementProposals(context, coveringNode, resultingCollections);
160                 getPickOutStringProposals(context, coveringNode, resultingCollections);
161                 getReplaceIfElseWithConditionalProposals(context, coveringNode, resultingCollections);
162                 getReplaceConditionalWithIfElseProposals(context, coveringNode, resultingCollections);
163                 getInverseLocalVariableProposals(context, coveringNode, resultingCollections);
164                 getPushNegationDownProposals(context, coveringNode, resultingCollections);
165                 getPullNegationUpProposals(context, coveringNode, coveredNodes, resultingCollections);
166                 getJoinIfListInIfElseIfProposals(context, coveringNode, coveredNodes, resultingCollections);
167                 getConvertSwitchToIfProposals(context, coveringNode, resultingCollections);
168             }
169             return (IJavaCompletionProposal[]) resultingCollections.toArray(new IJavaCompletionProposal[resultingCollections.size()]);
170         }
171         return null;
172     }
173     private static boolean noErrorsAtLocation(IProblemLocation[] locations) {
174         if (locations != null) {
175             for (int i = 0; i < locations.length; i++) {
176                 if (locations[i].isError()) {
177                     return false;
178                 }
179             }
180         }
181         return true;
182     }
183     private static boolean getIfReturnIntoIfElseAtEndOfVoidMethodProposals(IInvocationContext context, ASTNode covering,
184             Collection JavaDoc resultingCollections) {
185         Statement coveringStatement = ASTResolving.findParentStatement(covering);
186         if (!(coveringStatement instanceof IfStatement)) {
187             return false;
188         }
189         IfStatement ifStatement = (IfStatement) coveringStatement;
190         if (ifStatement.getElseStatement() != null) {
191             return false;
192         }
193         // 'then' block should have 'return' as last statement
194
Statement thenStatement = ifStatement.getThenStatement();
195         if (!(thenStatement instanceof Block)) {
196             return false;
197         }
198         Block thenBlock = (Block) thenStatement;
199         List JavaDoc thenStatements = thenBlock.statements();
200         if (thenStatements.isEmpty() || !(thenStatements.get(thenStatements.size() - 1) instanceof ReturnStatement)) {
201             return false;
202         }
203         // method should return 'void'
204
MethodDeclaration coveringMetod = ASTResolving.findParentMethodDeclaration(covering);
205         if (coveringMetod == null) {
206             return false;
207         }
208         Type returnType = coveringMetod.getReturnType2();
209         if (!(returnType instanceof PrimitiveType)
210                 || ((PrimitiveType) returnType).getPrimitiveTypeCode() != PrimitiveType.VOID)
211             return false;
212         //
213
List JavaDoc statements = coveringMetod.getBody().statements();
214         int ifIndex = statements.indexOf(ifStatement);
215         if (ifIndex == -1) {
216             return false;
217         }
218         // we could produce quick assist
219
if (resultingCollections == null) {
220             return true;
221         }
222         //
223
AST ast = coveringStatement.getAST();
224         ASTRewrite rewrite = ASTRewrite.create(ast);
225         // remove last 'return' in 'then' block
226
ListRewrite listRewriter = rewrite.getListRewrite(thenBlock,
227             (ChildListPropertyDescriptor) ifStatement.getLocationInParent());
228         listRewriter.remove((ASTNode) thenStatements.get(thenStatements.size() - 1), null);
229         // prepare original nodes
230
Expression conditionPlaceholder = (Expression) rewrite.createMoveTarget(ifStatement.getExpression());
231         Statement thenPlaceholder = (Statement) rewrite.createMoveTarget(ifStatement.getThenStatement());
232         // prepare 'else' block
233
Block elseBlock = ast.newBlock();
234         for (int i = ifIndex + 1; i < statements.size(); i++) {
235             Statement statement = (Statement) statements.get(i);
236             elseBlock.statements().add(rewrite.createMoveTarget(statement));
237         }
238         // prepare new 'if' statement
239
IfStatement newIf = ast.newIfStatement();
240         newIf.setExpression(conditionPlaceholder);
241         newIf.setThenStatement(thenPlaceholder);
242         newIf.setElseStatement(elseBlock);
243         rewrite.replace(ifStatement, newIf, null);
244         // add correction proposal
245
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_convertToIfElse_description;
246         Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
247         ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(),
248                 rewrite, 1, image);
249         resultingCollections.add(proposal);
250         return true;
251     }
252     private static boolean getInverseIfProposals(IInvocationContext context, ASTNode covering, Collection JavaDoc resultingCollections) {
253         Statement coveringStatement = ASTResolving.findParentStatement(covering);
254         if (!(coveringStatement instanceof IfStatement)) {
255             return false;
256         }
257         IfStatement ifStatement = (IfStatement) coveringStatement;
258         if (ifStatement.getElseStatement() == null) {
259             return false;
260         }
261         // we could produce quick assist
262
if (resultingCollections == null) {
263             return true;
264         }
265         //
266
AST ast = coveringStatement.getAST();
267         ASTRewrite rewrite = ASTRewrite.create(ast);
268         Statement thenStatement= ifStatement.getThenStatement();
269         Statement elseStatement= ifStatement.getElseStatement();
270         
271         // prepare original nodes
272
Expression inversedExpression = getInversedBooleanExpression(rewrite, ifStatement.getExpression());
273         
274         Statement newElseStatement = (Statement) rewrite.createMoveTarget(thenStatement);
275         Statement newThenStatement = (Statement) rewrite.createMoveTarget(elseStatement);
276         // set new nodes
277
rewrite.set(ifStatement, IfStatement.EXPRESSION_PROPERTY, inversedExpression, null);
278         
279         if (elseStatement instanceof IfStatement) {// bug 79507 && bug 74580
280
Block elseBlock = ast.newBlock();
281             elseBlock.statements().add(newThenStatement);
282             newThenStatement= elseBlock;
283         }
284         rewrite.set(ifStatement, IfStatement.THEN_STATEMENT_PROPERTY, newThenStatement, null);
285         rewrite.set(ifStatement, IfStatement.ELSE_STATEMENT_PROPERTY, newElseStatement, null);
286         // add correction proposal
287
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_inverseIf_description;
288         Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
289         ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(),
290                 rewrite, 1, image);
291         resultingCollections.add(proposal);
292         return true;
293     }
294     private static boolean getInverseIfContinueIntoIfThenInLoopsProposals(IInvocationContext context, ASTNode covering,
295             Collection JavaDoc resultingCollections) {
296         Statement coveringStatement = ASTResolving.findParentStatement(covering);
297         if (!(coveringStatement instanceof IfStatement)) {
298             return false;
299         }
300         IfStatement ifStatement = (IfStatement) coveringStatement;
301         if (ifStatement.getElseStatement() != null) {
302             return false;
303         }
304         // check that 'then' is 'continue'
305
if (!(ifStatement.getThenStatement() instanceof ContinueStatement)) {
306             return false;
307         }
308         // check that 'if' statement is statement in block that is body of loop
309
Block loopBlock = null;
310         if ((ifStatement.getParent() instanceof Block) && (ifStatement.getParent().getParent() instanceof ForStatement)) {
311             loopBlock = (Block) ifStatement.getParent();
312         } else if ((ifStatement.getParent() instanceof Block)
313                 && (ifStatement.getParent().getParent() instanceof WhileStatement)) {
314             loopBlock = (Block) ifStatement.getParent();
315         } else {
316             return false;
317         }
318         if (resultingCollections == null) {
319             return true;
320         }
321         //
322
AST ast = coveringStatement.getAST();
323         ASTRewrite rewrite = ASTRewrite.create(ast);
324         // create inverted 'if' statement
325
Expression inversedExpression = getInversedBooleanExpression(rewrite, ifStatement.getExpression());
326         IfStatement newIf = ast.newIfStatement();
327         newIf.setExpression(inversedExpression);
328         // prepare 'then' for new 'if'
329
Block thenBlock = ast.newBlock();
330         int ifIndex = loopBlock.statements().indexOf(ifStatement);
331         for (int i = ifIndex + 1; i < loopBlock.statements().size(); i++) {
332             Statement statement = (Statement) loopBlock.statements().get(i);
333             thenBlock.statements().add(rewrite.createMoveTarget(statement));
334         }
335         newIf.setThenStatement(thenBlock);
336         // replace 'if' statement in loop
337
rewrite.replace(ifStatement, newIf, null);
338         // add correction proposal
339
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_inverseIfContinue_description;
340         Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
341         ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(),
342                 rewrite, 1, image);
343         resultingCollections.add(proposal);
344         return true;
345     }
346     private static boolean getInverseIfIntoContinueInLoopsProposals(IInvocationContext context, ASTNode covering, Collection JavaDoc resultingCollections) {
347         Statement coveringStatement = ASTResolving.findParentStatement(covering);
348         if (!(coveringStatement instanceof IfStatement)) {
349             return false;
350         }
351         IfStatement ifStatement = (IfStatement) coveringStatement;
352         if (ifStatement.getElseStatement() != null) {
353             return false;
354         }
355         // prepare outer control structure and block that contains 'if' statement
356
ASTNode ifParent = ifStatement.getParent();
357         Block ifParentBlock = null;
358         ASTNode ifParentStructure = ifParent;
359         if (ifParentStructure instanceof Block) {
360             ifParentBlock = (Block) ifParent;
361             ifParentStructure = ifParentStructure.getParent();
362         }
363         // check that control structure is loop and 'if' statement if last statement
364
if (!(ifParentStructure instanceof ForStatement) && !(ifParentStructure instanceof WhileStatement)) {
365             return false;
366         }
367         if ((ifParentBlock != null) && (ifParentBlock.statements().indexOf(ifStatement) != ifParentBlock.statements().size() - 1)) {
368             return false;
369         }
370         // we could produce quick assist
371
if (resultingCollections == null) {
372             return true;
373         }
374         //
375
AST ast = coveringStatement.getAST();
376         ASTRewrite rewrite = ASTRewrite.create(ast);
377         // create inverted 'if' statement
378
Expression inversedExpression = getInversedBooleanExpression(rewrite, ifStatement.getExpression());
379         IfStatement newIf = ast.newIfStatement();
380         newIf.setExpression(inversedExpression);
381         newIf.setThenStatement(ast.newContinueStatement());
382         //
383
if (ifParentBlock == null) {
384             // if there is no block, create it
385
ifParentBlock = ast.newBlock();
386             ifParentBlock.statements().add(newIf);
387             for (Iterator JavaDoc iter = getUnwrappedStatements(ifStatement.getThenStatement()).iterator(); iter.hasNext();) {
388                 Statement statement = (Statement) iter.next();
389                 ifParentBlock.statements().add(rewrite.createMoveTarget(statement));
390             }
391             // replace 'if' statement as body with new block
392
if (ifParentStructure instanceof ForStatement) {
393                 rewrite.set(ifParentStructure, ForStatement.BODY_PROPERTY, ifParentBlock, null);
394             } else if (ifParentStructure instanceof WhileStatement) {
395                 rewrite.set(ifParentStructure, WhileStatement.BODY_PROPERTY, ifParentBlock, null);
396             }
397         } else {
398             // if there was block, replace
399
ListRewrite listRewriter = rewrite.getListRewrite(ifParentBlock,
400                 (ChildListPropertyDescriptor) ifStatement.getLocationInParent());
401             listRewriter.replace(ifStatement, newIf, null);
402             // add statements from 'then' to the end of block
403
for (Iterator JavaDoc iter = getUnwrappedStatements(ifStatement.getThenStatement()).iterator(); iter.hasNext();) {
404                 Statement statement = (Statement) iter.next();
405                 listRewriter.insertLast(rewrite.createMoveTarget(statement), null);
406             }
407         }
408         // add correction proposal
409
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_inverseIfToContinue_description;
410         Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
411         ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(),
412                 rewrite, 1, image);
413         resultingCollections.add(proposal);
414         return true;
415     }
416     private static ArrayList JavaDoc getUnwrappedStatements(Statement body) {
417         ArrayList JavaDoc statements = new ArrayList JavaDoc();
418         if (body instanceof Block) {
419             for (Iterator JavaDoc iter = ((Block) body).statements().iterator(); iter.hasNext();) {
420                 Statement statement = (Statement) iter.next();
421                 statements.add(statement);
422             }
423         } else {
424             statements.add(body);
425         }
426         return statements;
427     }
428     private static boolean getInverseConditionProposals(IInvocationContext context, ASTNode covering, ArrayList JavaDoc coveredNodes, Collection JavaDoc resultingCollections) {
429         if (coveredNodes.isEmpty()) {
430             return false;
431         }
432         //
433
final AST ast = covering.getAST();
434         final ASTRewrite rewrite = ASTRewrite.create(ast);
435         // check sub-expressions in fully covered nodes
436
boolean hasChanges = false;
437         for (Iterator JavaDoc iter = coveredNodes.iterator(); iter.hasNext();) {
438             ASTNode covered = (ASTNode) iter.next();
439             Expression coveredExpression= getBooleanExpression(covered);
440             if (coveredExpression != null) {
441                 Expression inversedExpression = getInversedBooleanExpression(rewrite, coveredExpression);
442                 rewrite.replace(coveredExpression, inversedExpression, null);
443                 hasChanges = true;
444             }
445         }
446         //
447
if (!hasChanges) {
448             return false;
449         }
450         if (resultingCollections == null) {
451             return true;
452         }
453         // add correction proposal
454
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_inverseConditions_description;
455         Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
456         ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(),
457                 rewrite, 1, image);
458         resultingCollections.add(proposal);
459         return true;
460     }
461     private static Expression getInversedBooleanExpression(ASTRewrite rewrite, Expression expression) {
462         return getInversedBooleanExpression(rewrite, expression, null);
463     }
464     private interface SimpleNameRenameProvider {
465         SimpleName getRenamed(SimpleName name);
466     }
467     private static Expression getRenamedNameCopy(SimpleNameRenameProvider provider,
468             ASTRewrite rewrite,
469             Expression expression) {
470         if (provider != null) {
471             if (expression instanceof SimpleName) {
472                 SimpleName name= (SimpleName) expression;
473                 SimpleName newName= provider.getRenamed(name);
474                 if (newName != null) {
475                     return newName;
476                 }
477             }
478         }
479         return (Expression) rewrite.createCopyTarget(expression);
480     }
481     private static Expression getInversedBooleanExpression(ASTRewrite rewrite, Expression expression, SimpleNameRenameProvider provider) {
482         if (!isBoolean(expression)) {
483             return (Expression) rewrite.createCopyTarget(expression);
484         }
485         AST ast= rewrite.getAST();
486         //
487
if (expression instanceof BooleanLiteral) {
488             return ast.newBooleanLiteral(!((BooleanLiteral) expression).booleanValue());
489         }
490         if (expression instanceof InfixExpression) {
491             InfixExpression infixExpression= (InfixExpression) expression;
492             InfixExpression.Operator operator= infixExpression.getOperator();
493             if (operator == InfixExpression.Operator.LESS) {
494                 return getInversedInfixBooleanExpression(rewrite, infixExpression, InfixExpression.Operator.GREATER_EQUALS, provider);
495             }
496             if (operator == InfixExpression.Operator.GREATER) {
497                 return getInversedInfixBooleanExpression(rewrite, infixExpression, InfixExpression.Operator.LESS_EQUALS, provider);
498             }
499             if (operator == InfixExpression.Operator.LESS_EQUALS) {
500                 return getInversedInfixBooleanExpression(rewrite, infixExpression, InfixExpression.Operator.GREATER, provider);
501             }
502             if (operator == InfixExpression.Operator.GREATER_EQUALS) {
503                 return getInversedInfixBooleanExpression(rewrite, infixExpression, InfixExpression.Operator.LESS, provider);
504             }
505             if (operator == InfixExpression.Operator.EQUALS) {
506                 return getInversedInfixBooleanExpression(rewrite, infixExpression, InfixExpression.Operator.NOT_EQUALS, provider);
507             }
508             if (operator == InfixExpression.Operator.NOT_EQUALS) {
509                 return getInversedInfixBooleanExpression(rewrite, infixExpression, InfixExpression.Operator.EQUALS, provider);
510             }
511             if (operator == InfixExpression.Operator.CONDITIONAL_AND) {
512                 return getInversedAndOrExpression(rewrite, infixExpression, InfixExpression.Operator.CONDITIONAL_OR, provider);
513             }
514             if (operator == InfixExpression.Operator.CONDITIONAL_OR) {
515                 return getInversedAndOrExpression(rewrite, infixExpression, InfixExpression.Operator.CONDITIONAL_AND, provider);
516             }
517             if (operator == InfixExpression.Operator.AND) {
518                 return getInversedAndOrExpression(rewrite, infixExpression, InfixExpression.Operator.OR, provider);
519             }
520             if (operator == InfixExpression.Operator.OR) {
521                 return getInversedAndOrExpression(rewrite, infixExpression, InfixExpression.Operator.AND, provider);
522             }
523         }
524         if (expression instanceof PrefixExpression) {
525             PrefixExpression prefixExpression= (PrefixExpression) expression;
526             if (prefixExpression.getOperator() == PrefixExpression.Operator.NOT) {
527                 return getRenamedNameCopy(provider, rewrite, prefixExpression.getOperand());
528             }
529         }
530         if (expression instanceof InstanceofExpression) {
531             PrefixExpression prefixExpression= ast.newPrefixExpression();
532             prefixExpression.setOperator(PrefixExpression.Operator.NOT);
533             ParenthesizedExpression parenthesizedExpression= ast.newParenthesizedExpression();
534             parenthesizedExpression.setExpression((Expression) rewrite.createCopyTarget(expression));
535             prefixExpression.setOperand(parenthesizedExpression);
536             return prefixExpression;
537         }
538         if (expression instanceof ParenthesizedExpression) {
539             ParenthesizedExpression parenthesizedExpression= (ParenthesizedExpression) expression;
540             Expression innerExpression= parenthesizedExpression.getExpression();
541             while (innerExpression instanceof ParenthesizedExpression) {
542                 innerExpression= ((ParenthesizedExpression) innerExpression).getExpression();
543             }
544             if (innerExpression instanceof InstanceofExpression) {
545                 return getInversedBooleanExpression(rewrite, innerExpression, provider);
546             }
547             parenthesizedExpression= ast.newParenthesizedExpression();
548             parenthesizedExpression.setExpression(getInversedBooleanExpression(rewrite, innerExpression, provider));
549             return parenthesizedExpression;
550         }
551         //
552
PrefixExpression prefixExpression= ast.newPrefixExpression();
553         prefixExpression.setOperator(PrefixExpression.Operator.NOT);
554         prefixExpression.setOperand(getRenamedNameCopy(provider, rewrite, expression));
555         return prefixExpression;
556     }
557     private static boolean isBoolean(Expression expression) {
558         return expression.resolveTypeBinding() == expression.getAST().resolveWellKnownType("boolean"); //$NON-NLS-1$
559
}
560     private static Expression getInversedInfixBooleanExpression(ASTRewrite rewrite, InfixExpression expression, InfixExpression.Operator newOperator, SimpleNameRenameProvider provider) {
561         InfixExpression newExpression = rewrite.getAST().newInfixExpression();
562         newExpression.setOperator(newOperator);
563         newExpression.setLeftOperand(getInversedBooleanExpression(rewrite, expression.getLeftOperand(), provider));
564         newExpression.setRightOperand(getInversedBooleanExpression(rewrite, expression.getRightOperand(), provider));
565         return newExpression;
566     }
567     
568     private static Expression parenthesizeIfRequired(Expression operand, int newOperatorPrecedence) {
569         if (newOperatorPrecedence < getExpressionPrecedence(operand)) {
570             return getParenthesizedExpression(operand.getAST(), operand);
571         }
572         return operand;
573     }
574     
575     private static Expression getInversedAndOrExpression(ASTRewrite rewrite, InfixExpression infixExpression, Operator newOperator, SimpleNameRenameProvider provider) {
576         InfixExpression newExpression = rewrite.getAST().newInfixExpression();
577         newExpression.setOperator(newOperator);
578         
579         int newOperatorPrecedence = getInfixOperatorPrecedence(newOperator);
580         //
581
Expression leftOperand = getInversedBooleanExpression(rewrite, infixExpression.getLeftOperand(), provider);
582         newExpression.setLeftOperand(parenthesizeIfRequired(leftOperand, newOperatorPrecedence));
583         
584         Expression rightOperand = getInversedBooleanExpression(rewrite, infixExpression.getRightOperand(), provider);
585         newExpression.setRightOperand(parenthesizeIfRequired(rightOperand, newOperatorPrecedence));
586         
587         List JavaDoc extraOperands= infixExpression.extendedOperands();
588         List JavaDoc newExtraOperands= newExpression.extendedOperands();
589         for (int i= 0; i < extraOperands.size(); i++) {
590             Expression extraOperand = getInversedBooleanExpression(rewrite, (Expression) extraOperands.get(i), provider);
591             newExtraOperands.add(parenthesizeIfRequired(extraOperand, newOperatorPrecedence));
592         }
593         return newExpression;
594     }
595     private static boolean getRemoveExtraParenthesisProposals(IInvocationContext context, ASTNode covering, ArrayList JavaDoc coveredNodes,
596             Collection JavaDoc resultingCollections) {
597         ArrayList JavaDoc nodes;
598         if ((context.getSelectionLength() == 0) && (covering instanceof ParenthesizedExpression)) {
599             nodes = new ArrayList JavaDoc();
600             nodes.add(covering);
601         } else {
602             nodes= coveredNodes;
603         }
604         if (nodes.isEmpty())
605             return false;
606         
607         IFix fix= ExpressionsFix.createRemoveUnnecessaryParenthesisFix(context.getASTRoot(), (ASTNode[])nodes.toArray(new ASTNode[nodes.size()]));
608         if (fix == null)
609             return false;
610         
611         if (resultingCollections == null)
612             return true;
613         
614         Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_REMOVE);
615         Map JavaDoc options= new Hashtable JavaDoc();
616         options.put(CleanUpConstants.EXPRESSIONS_USE_PARENTHESES, CleanUpConstants.TRUE);
617         options.put(CleanUpConstants.EXPRESSIONS_USE_PARENTHESES_NEVER, CleanUpConstants.TRUE);
618         FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new ExpressionsCleanUp(options), 1, image, context);
619         resultingCollections.add(proposal);
620         return true;
621     }
622     private static int getExpressionPrecedence(Expression expression) {
623         if (expression instanceof PostfixExpression) {
624             return 0;
625         }
626         if (expression instanceof PrefixExpression) {
627             return 1;
628         }
629         if ((expression instanceof ClassInstanceCreation) || (expression instanceof CastExpression)) {
630             return 2;
631         }
632         if (expression instanceof InfixExpression) {
633             InfixExpression infixExpression = (InfixExpression) expression;
634             InfixExpression.Operator operator = infixExpression.getOperator();
635             return getInfixOperatorPrecedence(operator);
636         }
637         if (expression instanceof InstanceofExpression) {
638             return 6;
639         }
640         if (expression instanceof ConditionalExpression) {
641             return 13;
642         }
643         if (expression instanceof Assignment) {
644             return 14;
645         }
646         if (expression instanceof MethodInvocation) {
647             return 2;
648         }
649         return -1;
650     }
651     private static int getInfixOperatorPrecedence(InfixExpression.Operator operator) {
652         if ((operator == InfixExpression.Operator.TIMES) || (operator == InfixExpression.Operator.DIVIDE)
653                 || (operator == InfixExpression.Operator.REMAINDER)) {
654             return 3;
655         }
656         if ((operator == InfixExpression.Operator.PLUS) || (operator == InfixExpression.Operator.MINUS)) {
657             return 4;
658         }
659         if ((operator == InfixExpression.Operator.LEFT_SHIFT)
660                 || (operator == InfixExpression.Operator.RIGHT_SHIFT_SIGNED)
661                 || (operator == InfixExpression.Operator.RIGHT_SHIFT_UNSIGNED)) {
662             return 5;
663         }
664         if ((operator == InfixExpression.Operator.LESS) || (operator == InfixExpression.Operator.GREATER)
665                 || (operator == InfixExpression.Operator.LESS_EQUALS)
666                 || (operator == InfixExpression.Operator.GREATER_EQUALS)) {
667             return 6;
668         }
669         if ((operator == InfixExpression.Operator.EQUALS) || (operator == InfixExpression.Operator.NOT_EQUALS)) {
670             return 7;
671         }
672         if (operator == InfixExpression.Operator.AND) {
673             return 8;
674         }
675         if (operator == InfixExpression.Operator.XOR) {
676             return 9;
677         }
678         if (operator == InfixExpression.Operator.OR) {
679             return 10;
680         }
681         if (operator == InfixExpression.Operator.CONDITIONAL_AND) {
682             return 11;
683         }
684         if (operator == InfixExpression.Operator.CONDITIONAL_OR) {
685             return 12;
686         }
687         return -1;
688     }
689     
690     private static boolean getAddParanoidalParenthesisProposals(IInvocationContext context, ASTNode covering, ArrayList JavaDoc coveredNodes,
691             Collection JavaDoc resultingCollections) throws CoreException {
692         
693         IFix fix= ExpressionsFix.createAddParanoidalParenthesisFix(context.getASTRoot(), (ASTNode[])coveredNodes.toArray(new ASTNode[coveredNodes.size()]));
694         if (fix == null)
695             return false;
696         
697         if (resultingCollections == null)
698             return true;
699
700         // add correction proposal
701
Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
702         Map JavaDoc options= new Hashtable JavaDoc();
703         options.put(CleanUpConstants.EXPRESSIONS_USE_PARENTHESES, CleanUpConstants.TRUE);
704         options.put(CleanUpConstants.EXPRESSIONS_USE_PARENTHESES_ALWAYS, CleanUpConstants.TRUE);
705         FixCorrectionProposal proposal= new FixCorrectionProposal(fix, new ExpressionsCleanUp(options), 1, image, context);
706         resultingCollections.add(proposal);
707         return true;
708     }
709     
710     private static ArrayList JavaDoc getFullyCoveredNodes(IInvocationContext context, ASTNode coveringNode) {
711         final ArrayList JavaDoc coveredNodes = new ArrayList JavaDoc();
712         final int selectionBegin = context.getSelectionOffset();
713         final int selectionEnd = selectionBegin + context.getSelectionLength();
714         coveringNode.accept(new GenericVisitor() {
715             protected boolean visitNode(ASTNode node) {
716                 int nodeStart= node.getStartPosition();
717                 int nodeEnd= nodeStart + node.getLength();
718                 // if node does not intersects with selection, don't visit children
719
if (nodeEnd < selectionBegin || selectionEnd < nodeStart) {
720                     return false;
721                 }
722                 // if node is fully covered, we don't need to visit children
723
if (isCovered(node)) {
724                     ASTNode parent = node.getParent();
725                     if ((parent == null) || !isCovered(parent)) {
726                         coveredNodes.add(node);
727                         return false;
728                     }
729                 }
730                 // if node only partly intersects with selection, we try to find fully covered children
731
return true;
732             }
733             private boolean isCovered(ASTNode node) {
734                 int begin = node.getStartPosition();
735                 int end = begin + node.getLength();
736                 return (begin >= selectionBegin) && (end <= selectionEnd);
737             }
738         });
739         return coveredNodes;
740     }
741     private static boolean getJoinAndIfStatementsProposals(IInvocationContext context, ASTNode node,
742             Collection JavaDoc resultingCollections) {
743         Operator andOperator = InfixExpression.Operator.CONDITIONAL_AND;
744         boolean result = false;
745         //
746
Statement statement = ASTResolving.findParentStatement(node);
747         if (!(statement instanceof IfStatement)) {
748             return false;
749         }
750         IfStatement ifStatement = (IfStatement) statement;
751         if (ifStatement.getElseStatement() != null) {
752             return false;
753         }
754         // case when current IfStatement is sole child of another IfStatement
755
{
756             IfStatement outerIf = null;
757             if (ifStatement.getParent() instanceof IfStatement) {
758                 outerIf = (IfStatement) ifStatement.getParent();
759             } else if (ifStatement.getParent() instanceof Block) {
760                 Block block = (Block) ifStatement.getParent();
761                 if ((block.getParent() instanceof IfStatement) && (block.statements().size() == 1)) {
762                     outerIf = (IfStatement) block.getParent();
763                 }
764             }
765             if ((outerIf != null) && (outerIf.getElseStatement() == null)) {
766                 if (resultingCollections == null) {
767                     return true;
768                 }
769                 //
770
AST ast = statement.getAST();
771                 ASTRewrite rewrite = ASTRewrite.create(ast);
772                 // prepare condition parts, add parenthesis if needed
773
Expression outerCondition = getParenthesizedForAndIfNeeded(ast, rewrite, outerIf.getExpression());
774                 Expression innerCondition = getParenthesizedForAndIfNeeded(ast, rewrite, ifStatement.getExpression());
775                 // create compound condition
776
InfixExpression condition = ast.newInfixExpression();
777                 condition.setOperator(andOperator);
778                 condition.setLeftOperand(outerCondition);
779                 condition.setRightOperand(innerCondition);
780                 // create new IfStatement
781
IfStatement newIf = ast.newIfStatement();
782                 newIf.setExpression(condition);
783                 Statement bodyPlaceholder = (Statement) rewrite.createCopyTarget(ifStatement.getThenStatement());
784                 newIf.setThenStatement(bodyPlaceholder);
785                 rewrite.replace(outerIf, newIf, null);
786                 // add correction proposal
787
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_joinWithOuter_description;
788                 Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
789                 ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label,
790                         context.getCompilationUnit(), rewrite, 1, image);
791                 resultingCollections.add(proposal);
792                 result = true;
793             }
794         }
795         // case when current IfStatement has another IfStatement as sole child
796
{
797             IfStatement innerIf = null;
798             if (ifStatement.getThenStatement() instanceof IfStatement) {
799                 innerIf = (IfStatement) ifStatement.getThenStatement();
800             } else if (ifStatement.getThenStatement() instanceof Block) {
801                 Block block = (Block) ifStatement.getThenStatement();
802                 if ((block.statements().size() == 1) && (block.statements().get(0) instanceof IfStatement)) {
803                     innerIf = (IfStatement) block.statements().get(0);
804                 }
805             }
806             if ((innerIf != null) && (innerIf.getElseStatement() == null)) {
807                 if (resultingCollections == null) {
808                     return true;
809                 }
810                 //
811
AST ast = statement.getAST();
812                 ASTRewrite rewrite = ASTRewrite.create(ast);
813                 // prepare condition parts, add parenthesis if needed
814
Expression outerCondition = getParenthesizedForAndIfNeeded(ast, rewrite, ifStatement.getExpression());
815                 Expression innerCondition = getParenthesizedForAndIfNeeded(ast, rewrite, innerIf.getExpression());
816                 // create compound condition
817
InfixExpression condition = ast.newInfixExpression();
818                 condition.setOperator(andOperator);
819                 condition.setLeftOperand(outerCondition);
820                 condition.setRightOperand(innerCondition);
821                 // create new IfStatement
822
IfStatement newIf = ast.newIfStatement();
823                 newIf.setExpression(condition);
824                 Statement bodyPlaceholder = (Statement) rewrite.createCopyTarget(innerIf.getThenStatement());
825                 newIf.setThenStatement(bodyPlaceholder);
826                 rewrite.replace(ifStatement, newIf, null);
827                 // add correction proposal
828
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_joinWithInner_description;
829                 Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
830                 ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label,
831                         context.getCompilationUnit(), rewrite, 1, image);
832                 resultingCollections.add(proposal);
833                 result = true;
834             }
835         }
836         return result;
837     }
838     private static Expression getParenthesizedForAndIfNeeded(AST ast, ASTRewrite rewrite, Expression expression) {
839         boolean addParentheses = false;
840         int nodeType = expression.getNodeType();
841         if (nodeType == ASTNode.INFIX_EXPRESSION) {
842             InfixExpression infixExpression = (InfixExpression) expression;
843             addParentheses = infixExpression.getOperator() == InfixExpression.Operator.CONDITIONAL_OR;
844         } else {
845             addParentheses = nodeType == ASTNode.CONDITIONAL_EXPRESSION || nodeType == ASTNode.ASSIGNMENT
846                     || nodeType == ASTNode.INSTANCEOF_EXPRESSION;
847         }
848         expression = (Expression) rewrite.createCopyTarget(expression);
849         if (addParentheses) {
850             return getParenthesizedExpression(ast, expression);
851         }
852         return expression;
853     }
854     private static Expression getParenthesizedExpression(AST ast, Expression expression) {
855         ParenthesizedExpression parenthesizedExpression = ast.newParenthesizedExpression();
856         parenthesizedExpression.setExpression(expression);
857         return parenthesizedExpression;
858     }
859     private static boolean getSplitAndConditionProposals(IInvocationContext context, ASTNode node,
860             Collection JavaDoc resultingCollections) {
861         Operator andOperator = InfixExpression.Operator.CONDITIONAL_AND;
862         // check that user invokes quick assist on infix expression
863
if (!(node instanceof InfixExpression)) {
864             return false;
865         }
866         InfixExpression infixExpression = (InfixExpression) node;
867         if (infixExpression.getOperator() != andOperator) {
868             return false;
869         }
870         int offset= isOperatorSelected(infixExpression, context.getSelectionOffset(), context.getSelectionLength());
871         if (offset == -1) {
872             return false;
873         }
874
875         // check that infix expression belongs to IfStatement
876
Statement statement = ASTResolving.findParentStatement(node);
877         if (!(statement instanceof IfStatement)) {
878             return false;
879         }
880         IfStatement ifStatement = (IfStatement) statement;
881         if (ifStatement.getElseStatement() != null) {
882             return false;
883         }
884         // check that infix expression is part of first level && condition of IfStatement
885
InfixExpression topInfixExpression = infixExpression;
886         while ((topInfixExpression.getParent() instanceof InfixExpression)
887                 && ((InfixExpression) topInfixExpression.getParent()).getOperator() == andOperator) {
888             topInfixExpression = (InfixExpression) topInfixExpression.getParent();
889         }
890         if (ifStatement.getExpression() != topInfixExpression) {
891             return false;
892         }
893         //
894
if (resultingCollections == null) {
895             return true;
896         }
897         AST ast = ifStatement.getAST();
898         ASTRewrite rewrite = ASTRewrite.create(ast);
899         
900         // prepare left and right conditions
901
Expression[] newOperands= { null, null };
902         breakInfixOperationAtOperation(rewrite, topInfixExpression, andOperator, offset, true, newOperands);
903
904         Expression leftCondition= newOperands[0];
905         Expression rightCondition= newOperands[1];
906         
907         // replace condition in inner IfStatement
908
rewrite.set(ifStatement, IfStatement.EXPRESSION_PROPERTY, rightCondition, null);
909         // prepare outer IfStatement
910
IfStatement outerIfStatement = ast.newIfStatement();
911         outerIfStatement.setExpression(leftCondition);
912         Block outerBlock = ast.newBlock();
913         outerIfStatement.setThenStatement(outerBlock);
914         ASTNode ifPlaceholder = rewrite.createMoveTarget(ifStatement);
915         outerBlock.statements().add(ifPlaceholder);
916         // replace ifStatement
917
rewrite.replace(ifStatement, outerIfStatement, null);
918         // add correction proposal
919
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_splitAndCondition_description;
920         Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
921         ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(),
922                 rewrite, 1, image);
923         resultingCollections.add(proposal);
924         return true;
925     }
926     private static boolean isSelectingOperator(ASTNode n1, ASTNode n2, int offset, int length) {
927         // between the nodes
928
if (offset + length <= n2.getStartPosition() && offset >= ASTNodes.getExclusiveEnd(n1)) {
929             return true;
930         }
931         // or exactly select the node (but not with infix expressions)
932
if (n1.getStartPosition() == offset && ASTNodes.getExclusiveEnd(n2) == offset + length) {
933             if (n1 instanceof InfixExpression || n2 instanceof InfixExpression) {
934                 return false;
935             }
936             return true;
937         }
938         return false;
939     }
940     
941     private static int isOperatorSelected(InfixExpression infixExpression, int offset, int length) {
942         ASTNode left= infixExpression.getLeftOperand();
943         ASTNode right= infixExpression.getRightOperand();
944         
945         if (isSelectingOperator(left, right, offset, length)) {
946             return ASTNodes.getExclusiveEnd(left);
947         }
948         List JavaDoc extended= infixExpression.extendedOperands();
949         for (int i= 0; i < extended.size(); i++) {
950             left= right;
951             right= (ASTNode) extended.get(i);
952             if (isSelectingOperator(left, right, offset, length)) {
953                 return ASTNodes.getExclusiveEnd(left);
954             }
955         }
956         return -1;
957     }
958     
959     private static boolean getJoinOrIfStatementsProposals(IInvocationContext context, ASTNode covering, ArrayList JavaDoc coveredNodes,
960             Collection JavaDoc resultingCollections) {
961         Operator orOperator = InfixExpression.Operator.CONDITIONAL_OR;
962         if (coveredNodes.size() < 2)
963             return false;
964         // check that all covered nodes are IfStatement's with same 'then' statement and without 'else'
965
String JavaDoc commonThenSource = null;
966         for (Iterator JavaDoc iter = coveredNodes.iterator(); iter.hasNext();) {
967             ASTNode node = (ASTNode) iter.next();
968             if (!(node instanceof IfStatement))
969                 return false;
970             //
971
IfStatement ifStatement = (IfStatement) node;
972             if (ifStatement.getElseStatement() != null)
973                 return false;
974             //
975
Statement thenStatement = ifStatement.getThenStatement();
976             try {
977                 String JavaDoc thenSource = context.getCompilationUnit().getBuffer().getText(thenStatement.getStartPosition(),
978                     thenStatement.getLength());
979                 if (commonThenSource == null) {
980                     commonThenSource = thenSource;
981                 } else {
982                     if (!commonThenSource.equals(thenSource))
983                         return false;
984                 }
985             } catch (Throwable JavaDoc e) {
986                 return false;
987             }
988         }
989         if (resultingCollections == null) {
990             return true;
991         }
992         //
993
final AST ast = covering.getAST();
994         final ASTRewrite rewrite = ASTRewrite.create(ast);
995         // prepare OR'ed condition
996
InfixExpression condition = null;
997         boolean hasRightOperand = false;
998         Statement thenStatement = null;
999         for (Iterator JavaDoc iter = coveredNodes.iterator(); iter.hasNext();) {
1000            IfStatement ifStatement = (IfStatement) iter.next();
1001            if (thenStatement == null)
1002                thenStatement = (Statement) rewrite.createCopyTarget(ifStatement.getThenStatement());
1003            Expression ifCondition = getParenthesizedForOrIfNeeded(ast, rewrite, ifStatement.getExpression());
1004            if (condition == null) {
1005                condition = ast.newInfixExpression();
1006                condition.setOperator(orOperator);
1007                condition.setLeftOperand(ifCondition);
1008            } else if (!hasRightOperand) {
1009                condition.setRightOperand(ifCondition);
1010                hasRightOperand = true;
1011            } else {
1012                InfixExpression newCondition = ast.newInfixExpression();
1013                newCondition.setOperator(orOperator);
1014                newCondition.setLeftOperand(condition);
1015                newCondition.setRightOperand(ifCondition);
1016                condition = newCondition;
1017            }
1018        }
1019        // prepare new IfStatement with OR'ed condition
1020
IfStatement newIf = ast.newIfStatement();
1021        newIf.setExpression(condition);
1022        newIf.setThenStatement(thenStatement);
1023        //
1024
ListRewrite listRewriter = null;
1025        for (Iterator JavaDoc iter = coveredNodes.iterator(); iter.hasNext();) {
1026            IfStatement ifStatement = (IfStatement) iter.next();
1027            if (listRewriter == null) {
1028                Block sourceBlock = (Block) ifStatement.getParent();
1029                //int insertIndex = sourceBlock.statements().indexOf(ifStatement);
1030
listRewriter = rewrite.getListRewrite(sourceBlock,
1031                    (ChildListPropertyDescriptor) ifStatement.getLocationInParent());
1032            }
1033            if (newIf != null) {
1034                listRewriter.replace(ifStatement, newIf, null);
1035                newIf = null;
1036            } else {
1037                listRewriter.remove(ifStatement, null);
1038            }
1039        }
1040        // add correction proposal
1041
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_joinWithOr_description;
1042        Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1043        ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(),
1044                rewrite, 1, image);
1045        resultingCollections.add(proposal);
1046        return true;
1047    }
1048    private static Expression getParenthesizedForOrIfNeeded(AST ast, ASTRewrite rewrite, Expression expression) {
1049        boolean addParentheses = false;
1050        int nodeType = expression.getNodeType();
1051        addParentheses = nodeType == ASTNode.CONDITIONAL_EXPRESSION || nodeType == ASTNode.ASSIGNMENT
1052                || nodeType == ASTNode.INSTANCEOF_EXPRESSION;
1053        expression = (Expression) rewrite.createCopyTarget(expression);
1054        if (addParentheses) {
1055            return getParenthesizedExpression(ast, expression);
1056        }
1057        return expression;
1058    }
1059    private static boolean getSplitOrConditionProposals(IInvocationContext context, ASTNode node,
1060            Collection JavaDoc resultingCollections) {
1061        Operator orOperator = InfixExpression.Operator.CONDITIONAL_OR;
1062        // check that user invokes quick assist on infix expression
1063
if (!(node instanceof InfixExpression)) {
1064            return false;
1065        }
1066        InfixExpression infixExpression = (InfixExpression) node;
1067        if (infixExpression.getOperator() != orOperator) {
1068            return false;
1069        }
1070        int offset= isOperatorSelected(infixExpression, context.getSelectionOffset(), context.getSelectionLength());
1071        if (offset == -1) {
1072            return false;
1073        }
1074        // check that infix expression belongs to IfStatement
1075
Statement statement = ASTResolving.findParentStatement(node);
1076        if (!(statement instanceof IfStatement)) {
1077            return false;
1078        }
1079        IfStatement ifStatement = (IfStatement) statement;
1080        if (ifStatement.getElseStatement() != null) {
1081            return false;
1082        }
1083        // check that infix expression is part of first level || condition of IfStatement
1084
InfixExpression topInfixExpression = infixExpression;
1085        while ((topInfixExpression.getParent() instanceof InfixExpression)
1086                && ((InfixExpression) topInfixExpression.getParent()).getOperator() == orOperator) {
1087            topInfixExpression = (InfixExpression) topInfixExpression.getParent();
1088        }
1089        if (ifStatement.getExpression() != topInfixExpression) {
1090            return false;
1091        }
1092        //
1093
if (resultingCollections == null) {
1094            return true;
1095        }
1096        AST ast = ifStatement.getAST();
1097        ASTRewrite rewrite = ASTRewrite.create(ast);
1098
1099        // prepare left and right conditions
1100
Expression[] newOperands= { null, null };
1101        breakInfixOperationAtOperation(rewrite, topInfixExpression, orOperator, offset, true, newOperands);
1102        
1103        Expression leftCondition= newOperands[0];
1104        Expression rightCondition= newOperands[1];
1105        
1106        // prepare first statement
1107
IfStatement firstIf = ast.newIfStatement();
1108        firstIf.setExpression(leftCondition);
1109        firstIf.setThenStatement((Statement) rewrite.createCopyTarget(ifStatement.getThenStatement()));
1110        // prepare second statement
1111
IfStatement secondIf = ast.newIfStatement();
1112        secondIf.setExpression(rightCondition);
1113        secondIf.setThenStatement((Statement) rewrite.createCopyTarget(ifStatement.getThenStatement()));
1114        // add first and second IfStatement's
1115
Block sourceBlock = (Block) ifStatement.getParent();
1116        int insertIndex = sourceBlock.statements().indexOf(ifStatement);
1117        ListRewrite listRewriter = rewrite.getListRewrite(sourceBlock,
1118            (ChildListPropertyDescriptor) statement.getLocationInParent());
1119        listRewriter.replace(ifStatement, firstIf, null);
1120        listRewriter.insertAt(secondIf, insertIndex + 1, null);
1121        // add correction proposal
1122
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_splitOrCondition_description;
1123        Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1124        ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(),
1125                rewrite, 1, image);
1126        resultingCollections.add(proposal);
1127        return true;
1128    }
1129    private static boolean getInverseConditionalExpressionProposals(IInvocationContext context, ASTNode covering,
1130            Collection JavaDoc resultingCollections) {
1131        // try to find conditional expression as parent
1132
while (covering instanceof Expression) {
1133            if (covering instanceof ConditionalExpression)
1134                break;
1135            covering = covering.getParent();
1136        }
1137        if (!(covering instanceof ConditionalExpression)) {
1138            return false;
1139        }
1140        ConditionalExpression expression = (ConditionalExpression) covering;
1141        // we could produce quick assist
1142
if (resultingCollections == null) {
1143            return true;
1144        }
1145        //
1146
AST ast = covering.getAST();
1147        ASTRewrite rewrite = ASTRewrite.create(ast);
1148        // prepare new conditional expression
1149
ConditionalExpression newExpression = ast.newConditionalExpression();
1150        newExpression.setExpression(getInversedBooleanExpression(rewrite, expression.getExpression()));
1151        newExpression.setThenExpression((Expression) rewrite.createCopyTarget(expression.getElseExpression()));
1152        newExpression.setElseExpression((Expression) rewrite.createCopyTarget(expression.getThenExpression()));
1153        // replace old expression with new
1154
rewrite.replace(expression, newExpression, null);
1155        // add correction proposal
1156
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_inverseConditionalExpression_description;
1157        Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1158        ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(),
1159                rewrite, 1, image);
1160        resultingCollections.add(proposal);
1161        return true;
1162    }
1163    private static boolean getExchangeInnerAndOuterIfConditionsProposals(IInvocationContext context, ASTNode node,
1164            Collection JavaDoc resultingCollections) {
1165        boolean result = false;
1166        //
1167
Statement statement = ASTResolving.findParentStatement(node);
1168        if (!(statement instanceof IfStatement)) {
1169            return false;
1170        }
1171        IfStatement ifStatement = (IfStatement) statement;
1172        if (ifStatement.getElseStatement() != null) {
1173            return false;
1174        }
1175        // case when current IfStatement is sole child of another IfStatement
1176
{
1177            IfStatement outerIf = null;
1178            if (ifStatement.getParent() instanceof IfStatement) {
1179                outerIf = (IfStatement) ifStatement.getParent();
1180            } else if (ifStatement.getParent() instanceof Block) {
1181                Block block = (Block) ifStatement.getParent();
1182                if ((block.getParent() instanceof IfStatement) && (block.statements().size() == 1)) {
1183                    outerIf = (IfStatement) block.getParent();
1184                }
1185            }
1186            if ((outerIf != null) && (outerIf.getElseStatement() == null)) {
1187                if (resultingCollections == null) {
1188                    return true;
1189                }
1190                //
1191
AST ast = statement.getAST();
1192                ASTRewrite rewrite = ASTRewrite.create(ast);
1193                // prepare conditions
1194
Expression outerCondition = (Expression) rewrite.createCopyTarget(outerIf.getExpression());
1195                Expression innerCondition = (Expression) rewrite.createCopyTarget(ifStatement.getExpression());
1196                // exchange conditions
1197
rewrite.replace(outerIf.getExpression(), innerCondition, null);
1198                rewrite.replace(ifStatement.getExpression(), outerCondition, null);
1199                // add correction proposal
1200
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_exchangeInnerAndOuterIfConditions_description;
1201                Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1202                ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label,
1203                        context.getCompilationUnit(), rewrite, 1, image);
1204                resultingCollections.add(proposal);
1205                result = true;
1206            }
1207        }
1208        // case when current IfStatement has another IfStatement as sole child
1209
{
1210            IfStatement innerIf = null;
1211            if (ifStatement.getThenStatement() instanceof IfStatement) {
1212                innerIf = (IfStatement) ifStatement.getThenStatement();
1213            } else if (ifStatement.getThenStatement() instanceof Block) {
1214                Block block = (Block) ifStatement.getThenStatement();
1215                if ((block.statements().size() == 1) && (block.statements().get(0) instanceof IfStatement)) {
1216                    innerIf = (IfStatement) block.statements().get(0);
1217                }
1218            }
1219            if ((innerIf != null) && (innerIf.getElseStatement() == null)) {
1220                if (resultingCollections == null) {
1221                    return true;
1222                }
1223                //
1224
AST ast = statement.getAST();
1225                ASTRewrite rewrite = ASTRewrite.create(ast);
1226                // prepare conditions
1227
Expression innerCondition = (Expression) rewrite.createCopyTarget(innerIf.getExpression());
1228                Expression outerCondition = (Expression) rewrite.createCopyTarget(ifStatement.getExpression());
1229                // exchange conditions
1230
rewrite.replace(innerIf.getExpression(), outerCondition, null);
1231                rewrite.replace(ifStatement.getExpression(), innerCondition, null);
1232                // add correction proposal
1233
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_exchangeInnerAndOuterIfConditions_description;
1234                Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1235                ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label,
1236                        context.getCompilationUnit(), rewrite, 1, image);
1237                resultingCollections.add(proposal);
1238                result = true;
1239            }
1240        }
1241        return result;
1242    }
1243    private static boolean getExchangeOperandsProposals(IInvocationContext context, ASTNode node,
1244            Collection JavaDoc resultingCollections) {
1245        // check that user invokes quick assist on infix expression
1246
if (!(node instanceof InfixExpression)) {
1247            return false;
1248        }
1249        InfixExpression infixExpression = (InfixExpression) node;
1250        Operator operator = infixExpression.getOperator();
1251        if ((operator != InfixExpression.Operator.CONDITIONAL_AND) && (operator != InfixExpression.Operator.AND)
1252                && (operator != InfixExpression.Operator.CONDITIONAL_OR) && (operator != InfixExpression.Operator.OR)
1253                && (operator != InfixExpression.Operator.EQUALS) && (operator != InfixExpression.Operator.PLUS)
1254                && (operator != InfixExpression.Operator.TIMES) && (operator != InfixExpression.Operator.XOR)) {
1255            return false;
1256        }
1257        
1258        int offset= isOperatorSelected(infixExpression, context.getSelectionOffset(), context.getSelectionLength());
1259        if (offset == -1) {
1260            return false;
1261        }
1262        
1263        // we could produce quick assist
1264
if (resultingCollections == null) {
1265            return true;
1266        }
1267        AST ast = infixExpression.getAST();
1268        ASTRewrite rewrite = ASTRewrite.create(ast);
1269        // prepare left and right expressions
1270
Expression leftExpression = null;
1271        Expression rightExpression = null;
1272        InfixExpression currentExpression = infixExpression;
1273        leftExpression= combineOperands(rewrite, leftExpression, infixExpression.getLeftOperand(), true, operator);
1274        if (infixExpression.getRightOperand().getStartPosition() <= context.getSelectionOffset()) {
1275            leftExpression= combineOperands(rewrite, leftExpression, infixExpression.getRightOperand(), true, operator);
1276        } else {
1277            rightExpression= combineOperands(rewrite, rightExpression, infixExpression.getRightOperand(), true, operator);
1278        }
1279        for (Iterator JavaDoc iter= currentExpression.extendedOperands().iterator(); iter.hasNext();) {
1280            Expression extendedOperand= (Expression) iter.next();
1281            if (extendedOperand.getStartPosition() <= context.getSelectionOffset()) {
1282                leftExpression= combineOperands(rewrite, leftExpression, extendedOperand, true, operator);
1283            } else {
1284                rightExpression= combineOperands(rewrite, rightExpression, extendedOperand, true, operator);
1285            }
1286        }
1287        // create new infix expression
1288
InfixExpression newInfix = ast.newInfixExpression();
1289        newInfix.setOperator(operator);
1290        newInfix.setLeftOperand(rightExpression);
1291        newInfix.setRightOperand(leftExpression);
1292        rewrite.replace(infixExpression, newInfix, null);
1293        // add correction proposal
1294
String JavaDoc label = CorrectionMessages.AdvancedQuickAssistProcessor_exchangeOperands_description;
1295        Image image = JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1296        ASTRewriteCorrectionProposal proposal = new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 1, image);
1297        resultingCollections.add(proposal);
1298        return true;
1299    }
1300    
1301    /**
1302     * Breaks an infix operation with possible extended operators at the given operator and returns the new left and right operands.
1303     * a & b & c -> [[a' & b' ] & c' ] (c' == copy of c)
1304     * @param rewrite
1305     * @param expression
1306     * @param operator
1307     * @param operatorOffset
1308     */

1309    private static void breakInfixOperationAtOperation(ASTRewrite rewrite, Expression expression, Operator operator, int operatorOffset, boolean removeParenthesis, Expression[] res) {
1310        if (expression.getStartPosition() + expression.getLength() <= operatorOffset) {
1311            // add to the left
1312
res[0]= combineOperands(rewrite, res[0], expression, removeParenthesis, operator);
1313            return;
1314        }
1315        if (operatorOffset <= expression.getStartPosition()) {
1316            // add to the right
1317
res[1]= combineOperands(rewrite, res[1], expression, removeParenthesis, operator);
1318            return;
1319        }
1320        if (!(expression instanceof InfixExpression)) {
1321            throw new IllegalArgumentException JavaDoc("Cannot break up non-infix expression"); //$NON-NLS-1$
1322
}
1323        InfixExpression infixExpression= (InfixExpression) expression;
1324        if (infixExpression.getOperator() != operator) {
1325            throw new IllegalArgumentException JavaDoc("Incompatible operator"); //$NON-NLS-1$
1326
}
1327        breakInfixOperationAtOperation(rewrite, infixExpression.getLeftOperand(), operator, operatorOffset, removeParenthesis, res);
1328        breakInfixOperationAtOperation(rewrite, infixExpression.getRightOperand(), operator, operatorOffset, removeParenthesis, res);
1329        
1330        List JavaDoc extended= infixExpression.extendedOperands();
1331        for (int i= 0; i < extended.size(); i++) {
1332            breakInfixOperationAtOperation(rewrite, (Expression) extended.get(i), operator, operatorOffset, removeParenthesis, res);
1333        }
1334    }
1335    
1336    private static Expression combineOperands(ASTRewrite rewrite, Expression existing, Expression nodeToAdd, boolean removeParenthesis, Operator operator) {
1337        if (existing == null && removeParenthesis) {
1338            while (nodeToAdd instanceof ParenthesizedExpression) {
1339                nodeToAdd= ((ParenthesizedExpression) nodeToAdd).getExpression();
1340            }
1341        }
1342        Expression newRight= (Expression) rewrite.createMoveTarget(nodeToAdd);
1343        if (existing == null) {
1344            return newRight;
1345        }
1346        AST ast= rewrite.getAST();
1347        InfixExpression infix= ast.newInfixExpression();
1348        infix.setOperator(operator);
1349        infix.setLeftOperand(existing);
1350        infix.setRightOperand(newRight);
1351        return infix;
1352    }
1353
1354    private static boolean getCastAndAssignIfStatementProposals(IInvocationContext context, ASTNode node, Collection JavaDoc resultingCollections) {
1355        if (!(node instanceof InstanceofExpression)) {
1356            return false;
1357        }
1358        InstanceofExpression expression= (InstanceofExpression) node;
1359        // test that we are the expression of a 'while' or 'if'
1360
while (node.getParent() instanceof Expression) {
1361            node= node.getParent();
1362        }
1363        StructuralPropertyDescriptor locationInParent= node.getLocationInParent();
1364
1365        boolean negated= isNegated(expression);
1366        
1367        Statement body= null;
1368        ASTNode insertionPosition= null;
1369        if (negated) {
1370            insertionPosition= node.getParent();
1371            if (locationInParent == IfStatement.EXPRESSION_PROPERTY) {
1372                body= ((IfStatement) node.getParent()).getElseStatement();
1373                if (body != null) {
1374                    negated= false;
1375                }
1376            }
1377            if (body == null && insertionPosition.getParent() instanceof Block) {
1378                body= (Statement)insertionPosition.getParent();
1379            }
1380        } else {
1381            if (locationInParent == IfStatement.EXPRESSION_PROPERTY) {
1382                body= ((IfStatement) node.getParent()).getThenStatement();
1383            } else if (locationInParent == WhileStatement.EXPRESSION_PROPERTY) {
1384                body= ((WhileStatement) node.getParent()).getBody();
1385            }
1386        }
1387        if (body == null) {
1388            return false;
1389        }
1390
1391        Type originalType= expression.getRightOperand();
1392        if (originalType.resolveBinding() == null) {
1393            return false;
1394        }
1395
1396        // we could produce quick assist
1397
if (resultingCollections == null) {
1398            return true;
1399        }
1400
1401        final String JavaDoc KEY_NAME= "name"; //$NON-NLS-1$
1402
final String JavaDoc KEY_TYPE= "type"; //$NON-NLS-1$
1403
//
1404
AST ast= expression.getAST();
1405        ASTRewrite rewrite= ASTRewrite.create(ast);
1406        ICompilationUnit cu= context.getCompilationUnit();
1407        // prepare correction proposal
1408
String JavaDoc label= CorrectionMessages.AdvancedQuickAssistProcessor_castAndAssign;
1409        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_LOCAL);
1410        LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, cu, rewrite, 7, image);
1411        // prepare possible variable names
1412
String JavaDoc[] varNames= suggestLocalVariableNames(cu, originalType.resolveBinding());
1413        for (int i= 0; i < varNames.length; i++) {
1414            proposal.addLinkedPositionProposal(KEY_NAME, varNames[i], null);
1415        }
1416        CastExpression castExpression= ast.newCastExpression();
1417        castExpression.setExpression((Expression) rewrite.createCopyTarget(expression.getLeftOperand()));
1418        castExpression.setType((Type) ASTNode.copySubtree(ast, originalType));
1419        // prepare new variable declaration
1420
VariableDeclarationFragment vdf= ast.newVariableDeclarationFragment();
1421        vdf.setName(ast.newSimpleName(varNames[0]));
1422        vdf.setInitializer(castExpression);
1423        // prepare new variable declaration statement
1424
VariableDeclarationStatement vds= ast.newVariableDeclarationStatement(vdf);
1425        vds.setType((Type) ASTNode.copySubtree(ast, originalType));
1426        
1427        // add new variable declaration statement
1428
if (negated) {
1429            ListRewrite listRewriter= rewrite.getListRewrite(body, Block.STATEMENTS_PROPERTY);
1430            listRewriter.insertAfter(vds, insertionPosition, null);
1431        } else {
1432            if (body instanceof Block) {
1433                ListRewrite listRewriter= rewrite.getListRewrite(body, Block.STATEMENTS_PROPERTY);
1434                listRewriter.insertAt(vds, 0, null);
1435            } else {
1436                Block newBlock= ast.newBlock();
1437                List JavaDoc statements= newBlock.statements();
1438                statements.add(vds);
1439                statements.add(rewrite.createMoveTarget(body));
1440                rewrite.replace(body, newBlock, null);
1441            }
1442        }
1443
1444        // setup linked positions
1445
proposal.addLinkedPosition(rewrite.track(vdf.getName()), true, KEY_NAME);
1446        proposal.addLinkedPosition(rewrite.track(vds.getType()), false, KEY_TYPE);
1447        proposal.addLinkedPosition(rewrite.track(castExpression.getType()), false, KEY_TYPE);
1448        proposal.setEndPosition(rewrite.track(vds)); // set cursor after expression statement
1449
// add correction proposal
1450
resultingCollections.add(proposal);
1451        return true;
1452    }
1453
1454    private static boolean isNegated(Expression expression) {
1455        if (!(expression.getParent() instanceof ParenthesizedExpression))
1456            return false;
1457        
1458        ParenthesizedExpression parenthesis= (ParenthesizedExpression)expression.getParent();
1459        if (!(parenthesis.getParent() instanceof PrefixExpression))
1460            return false;
1461        
1462        PrefixExpression prefix= (PrefixExpression)parenthesis.getParent();
1463        if (!(prefix.getOperator() == PrefixExpression.Operator.NOT))
1464            return false;
1465        
1466        return true;
1467    }
1468    private static String JavaDoc[] suggestLocalVariableNames(ICompilationUnit cu, ITypeBinding binding) {
1469        return StubUtility.getVariableNameSuggestions(StubUtility.LOCAL, cu.getJavaProject(), binding, null, null);
1470    }
1471
1472    private static boolean getPickOutStringProposals(IInvocationContext context, ASTNode node, Collection JavaDoc resultingCollections) {
1473        // we work with String's
1474
if (!(node instanceof StringLiteral)) {
1475            return false;
1476        }
1477        // user should select part of String
1478
int selectionPos= context.getSelectionOffset();
1479        int selectionLen= context.getSelectionLength();
1480        if (selectionLen == 0) {
1481            return false;
1482        }
1483        int valueStart= node.getStartPosition() + 1;
1484        int valueEnd= node.getStartPosition() + node.getLength() - 1;
1485
1486        // selection must be inside node and the quotes and not contain the full value
1487
if ((selectionPos < valueStart) || (selectionPos + selectionLen > valueEnd) || (valueEnd - valueStart == selectionLen)) {
1488            return false;
1489        }
1490
1491        // prepare string parts positions
1492
StringLiteral stringLiteral= (StringLiteral) node;
1493        String JavaDoc stringValue= stringLiteral.getEscapedValue();
1494
1495        int firstPos= selectionPos - node.getStartPosition();
1496        int secondPos= firstPos + selectionLen;
1497
1498
1499        // prepare new string literals
1500

1501        AST ast= node.getAST();
1502        StringLiteral leftLiteral= ast.newStringLiteral();
1503        StringLiteral centerLiteral= ast.newStringLiteral();
1504        StringLiteral rightLiteral= ast.newStringLiteral();
1505        try {
1506            leftLiteral.setEscapedValue('"' + stringValue.substring(1, firstPos) + '"');
1507            centerLiteral.setEscapedValue('"' + stringValue.substring(firstPos, secondPos) + '"');
1508            rightLiteral.setEscapedValue('"' + stringValue.substring(secondPos, stringValue.length() - 1) + '"');
1509        } catch (IllegalArgumentException JavaDoc e) {
1510            return false;
1511        }
1512        if (resultingCollections == null) {
1513            return true;
1514        }
1515
1516        ASTRewrite rewrite= ASTRewrite.create(ast);
1517
1518        // prepare new expression instead of StringLiteral
1519
InfixExpression expression= ast.newInfixExpression();
1520        expression.setOperator(InfixExpression.Operator.PLUS);
1521        if (firstPos != 1 ) {
1522            expression.setLeftOperand(leftLiteral);
1523        }
1524
1525
1526        if (firstPos == 1) {
1527            expression.setLeftOperand(centerLiteral);
1528        } else {
1529            expression.setRightOperand(centerLiteral);
1530        }
1531
1532        if (secondPos < stringValue.length() - 1) {
1533            if (firstPos == 1) {
1534                expression.setRightOperand(rightLiteral);
1535            } else {
1536                expression.extendedOperands().add(rightLiteral);
1537            }
1538        }
1539        // use new expression instead of old StirngLiteral
1540
rewrite.replace(stringLiteral, expression, null);
1541        // add correction proposal
1542
String JavaDoc label= CorrectionMessages.AdvancedQuickAssistProcessor_pickSelectedString;
1543        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1544        LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label, context.getCompilationUnit(), rewrite, 1, image);
1545        proposal.addLinkedPosition(rewrite.track(centerLiteral), true, "CENTER_STRING"); //$NON-NLS-1$
1546
resultingCollections.add(proposal);
1547        return true;
1548    }
1549
1550    private static Statement getSingleStatement(Statement statement) {
1551        if (statement instanceof Block) {
1552            List JavaDoc blockStatements= ((Block) statement).statements();
1553            if (blockStatements.size() != 1) {
1554                return null;
1555            }
1556            return (Statement) blockStatements.get(0);
1557        }
1558        return statement;
1559    }
1560
1561    private static boolean getReplaceIfElseWithConditionalProposals(IInvocationContext context, ASTNode node, Collection JavaDoc resultingCollections) {
1562        if (!(node instanceof IfStatement)) {
1563            return false;
1564        }
1565        IfStatement ifStatement= (IfStatement) node;
1566        Statement thenStatement= getSingleStatement(ifStatement.getThenStatement());
1567        Statement elseStatement= getSingleStatement(ifStatement.getElseStatement());
1568        if (thenStatement == null || elseStatement == null) {
1569            return false;
1570        }
1571        Expression assigned= null;
1572        Expression thenExpression= null;
1573        Expression elseExpression= null;
1574        
1575        ITypeBinding exprBinding= null;
1576        if (thenStatement instanceof ReturnStatement && elseStatement instanceof ReturnStatement) {
1577            thenExpression= ((ReturnStatement) thenStatement).getExpression();
1578            elseExpression= ((ReturnStatement) elseStatement).getExpression();
1579            MethodDeclaration declaration= ASTResolving.findParentMethodDeclaration(node);
1580            if (declaration == null || declaration.isConstructor()) {
1581                return false;
1582            }
1583            exprBinding= declaration.getReturnType2().resolveBinding();
1584        } else if (thenStatement instanceof ExpressionStatement && elseStatement instanceof ExpressionStatement) {
1585            Expression inner1= ((ExpressionStatement) thenStatement).getExpression();
1586            Expression inner2= ((ExpressionStatement) elseStatement).getExpression();
1587            if (inner1 instanceof Assignment && inner2 instanceof Assignment) {
1588                Assignment assign1= (Assignment) inner1;
1589                Assignment assign2= (Assignment) inner2;
1590                Expression left1= assign1.getLeftHandSide();
1591                Expression left2= assign2.getLeftHandSide();
1592                if (left1 instanceof Name && left2 instanceof Name && assign1.getOperator() == assign2.getOperator()) {
1593                    IBinding bind1= ((Name) left1).resolveBinding();
1594                    IBinding bind2= ((Name) left2).resolveBinding();
1595                    if (bind1 == bind2 && bind1 instanceof IVariableBinding) {
1596                        assigned= left1;
1597                        exprBinding= ((IVariableBinding) bind1).getType();
1598                        thenExpression= assign1.getRightHandSide();
1599                        elseExpression= assign2.getRightHandSide();
1600                    }
1601                }
1602            }
1603        }
1604        if (thenExpression == null || elseExpression == null) {
1605            return false;
1606        }
1607
1608        // we could produce quick assist
1609
if (resultingCollections == null) {
1610            return true;
1611        }
1612        //
1613
AST ast= node.getAST();
1614        ASTRewrite rewrite= ASTRewrite.create(ast);
1615        
1616        String JavaDoc label= CorrectionMessages.AdvancedQuickAssistProcessor_replaceIfWithConditional;
1617        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1618        ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 1, image);
1619
1620        
1621        // prepare conditional expression
1622
ConditionalExpression conditionalExpression = ast.newConditionalExpression();
1623        Expression conditionCopy= (Expression) rewrite.createCopyTarget(ifStatement.getExpression());
1624        conditionalExpression.setExpression(conditionCopy);
1625        Expression thenCopy= (Expression) rewrite.createCopyTarget(thenExpression);
1626        Expression elseCopy= (Expression) rewrite.createCopyTarget(elseExpression);
1627
1628        
1629        if (!JavaModelUtil.is50OrHigher(context.getCompilationUnit().getJavaProject())) {
1630            ITypeBinding thenBinding= thenExpression.resolveTypeBinding();
1631            ITypeBinding elseBinding= elseExpression.resolveTypeBinding();
1632            if (thenBinding != null && elseBinding != null && exprBinding != null && !elseBinding.isAssignmentCompatible(thenBinding)) {
1633                CastExpression castException= ast.newCastExpression();
1634                proposal.createImportRewrite(context.getASTRoot());
1635                castException.setType(proposal.getImportRewrite().addImport(exprBinding, ast));
1636                castException.setExpression(elseCopy);
1637                elseCopy= castException;
1638            }
1639        }
1640        conditionalExpression.setThenExpression(thenCopy);
1641        conditionalExpression.setElseExpression(elseCopy);
1642        
1643        // replace 'if' statement with conditional expression
1644
if (assigned == null) {
1645            ReturnStatement returnStatement = ast.newReturnStatement();
1646            returnStatement.setExpression(conditionalExpression);
1647            rewrite.replace(ifStatement, returnStatement, null);
1648        } else {
1649            Assignment assignment= ast.newAssignment();
1650            assignment.setLeftHandSide((Expression) rewrite.createCopyTarget(assigned));
1651            assignment.setRightHandSide(conditionalExpression);
1652            assignment.setOperator(((Assignment) assigned.getParent()).getOperator());
1653            
1654            ExpressionStatement expressionStatement = ast.newExpressionStatement(assignment);
1655            rewrite.replace(ifStatement, expressionStatement, null);
1656        }
1657
1658        // add correction proposal
1659
resultingCollections.add(proposal);
1660        return true;
1661    }
1662
1663    private static ReturnStatement createReturnExpression(ASTRewrite rewrite, Expression expression) {
1664        AST ast= rewrite.getAST();
1665        ReturnStatement thenReturn = ast.newReturnStatement();
1666        thenReturn.setExpression((Expression) rewrite.createCopyTarget(expression));
1667        return thenReturn;
1668    }
1669
1670    private static Statement createAssignmentStatement(ASTRewrite rewrite, Assignment.Operator assignmentOperator, Expression origAssignee, Expression origAssigned) {
1671        AST ast= rewrite.getAST();
1672        Assignment elseAssignment= ast.newAssignment();
1673        elseAssignment.setOperator(assignmentOperator);
1674        elseAssignment.setLeftHandSide((Expression) rewrite.createCopyTarget(origAssignee));
1675        elseAssignment.setRightHandSide((Expression) rewrite.createCopyTarget(origAssigned));
1676        ExpressionStatement statement = ast.newExpressionStatement(elseAssignment);
1677        return statement;
1678    }
1679
1680    private static boolean getReplaceConditionalWithIfElseProposals(IInvocationContext context, ASTNode covering, Collection JavaDoc resultingCollections) {
1681        // check that parent statement is assignment
1682
while (!(covering instanceof ConditionalExpression) && covering instanceof Expression) {
1683            covering= covering.getParent();
1684        }
1685        if (!(covering instanceof ConditionalExpression)) {
1686            return false;
1687        }
1688
1689        StructuralPropertyDescriptor locationInParent= covering.getLocationInParent();
1690        if (locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY) {
1691            if (covering.getParent().getLocationInParent() != ExpressionStatement.EXPRESSION_PROPERTY) {
1692                return false;
1693            }
1694        } else if (locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY) {
1695            ASTNode statement= covering.getParent().getParent();
1696            if (!(statement instanceof VariableDeclarationStatement) || statement.getLocationInParent() != Block.STATEMENTS_PROPERTY) {
1697                return false;
1698            }
1699        } else if (locationInParent != ReturnStatement.EXPRESSION_PROPERTY) {
1700            return false;
1701        }
1702
1703        ConditionalExpression conditional= (ConditionalExpression) covering;
1704        // we could produce quick assist
1705
if (resultingCollections == null) {
1706            return true;
1707        }
1708        //
1709
AST ast= covering.getAST();
1710        ASTRewrite rewrite= ASTRewrite.create(ast);
1711        // prepare new 'if' statement
1712
Expression expression= conditional.getExpression();
1713        while (expression instanceof ParenthesizedExpression) {
1714            expression= ((ParenthesizedExpression) expression).getExpression();
1715        }
1716        IfStatement ifStatement= ast.newIfStatement();
1717        ifStatement.setExpression((Expression) rewrite.createCopyTarget(expression));
1718        if (locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY) {
1719            Assignment assignment= (Assignment) covering.getParent();
1720            Expression assignee= assignment.getLeftHandSide();
1721            Assignment.Operator op= assignment.getOperator();
1722            
1723            ifStatement.setThenStatement(createAssignmentStatement(rewrite, op, assignee, conditional.getThenExpression()));
1724            ifStatement.setElseStatement(createAssignmentStatement(rewrite, op, assignee, conditional.getElseExpression()));
1725
1726            // replace return conditional expression with if/then/else/return
1727
rewrite.replace(covering.getParent().getParent(), ifStatement, null);
1728
1729        } else if (locationInParent == ReturnStatement.EXPRESSION_PROPERTY) {
1730            ifStatement.setThenStatement(createReturnExpression(rewrite, conditional.getThenExpression()));
1731            ifStatement.setElseStatement(createReturnExpression(rewrite, conditional.getElseExpression()));
1732            //
1733
// replace return conditional expression with if/then/else/return
1734
rewrite.replace(conditional.getParent(), ifStatement, null);
1735        } else if (locationInParent == VariableDeclarationFragment.INITIALIZER_PROPERTY) {
1736            VariableDeclarationFragment frag= (VariableDeclarationFragment) covering.getParent();
1737            Assignment.Operator op= Assignment.Operator.ASSIGN;
1738            
1739            Expression assignee= frag.getName();
1740            ifStatement.setThenStatement(createAssignmentStatement(rewrite, op, assignee, conditional.getThenExpression()));
1741            ifStatement.setElseStatement(createAssignmentStatement(rewrite, op, assignee, conditional.getElseExpression()));
1742
1743            rewrite.set(frag, VariableDeclarationFragment.INITIALIZER_PROPERTY, null, null); // clear initializer
1744

1745            ASTNode statement= frag.getParent();
1746            rewrite.getListRewrite(statement.getParent(), Block.STATEMENTS_PROPERTY).insertAfter(ifStatement, statement, null);
1747        }
1748
1749        // add correction proposal
1750
String JavaDoc label= CorrectionMessages.AdvancedQuickAssistProcessor_replaceConditionalWithIf;
1751        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1752        ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 1, image);
1753        resultingCollections.add(proposal);
1754        return true;
1755    }
1756    private static boolean getInverseLocalVariableProposals(IInvocationContext context,
1757            ASTNode covering,
1758            Collection JavaDoc resultingCollections) {
1759        final AST ast= covering.getAST();
1760        // cursor should be placed on variable name
1761
if (!(covering instanceof SimpleName)) {
1762            return false;
1763        }
1764        SimpleName coveringName= (SimpleName) covering;
1765        if (!coveringName.isDeclaration()) {
1766            return false;
1767        }
1768        // prepare bindings
1769
final IBinding variableBinding= coveringName.resolveBinding();
1770        if (!(variableBinding instanceof IVariableBinding)) {
1771            return false;
1772        }
1773        IVariableBinding binding= (IVariableBinding) variableBinding;
1774        if (binding.isField()) {
1775            return false;
1776        }
1777        // we operate only on boolean variable
1778
if (!isBoolean(coveringName)) {
1779            return false;
1780        }
1781        // we could produce quick assist
1782
if (resultingCollections == null) {
1783            return true;
1784        }
1785        // find linked nodes
1786
final MethodDeclaration method= ASTResolving.findParentMethodDeclaration(covering);
1787        SimpleName[] linkedNodes= LinkedNodeFinder.findByBinding(method, variableBinding);
1788        //
1789
final ASTRewrite rewrite= ASTRewrite.create(ast);
1790        // create proposal
1791
String JavaDoc label= CorrectionMessages.AdvancedQuickAssistProcessor_inverseBooleanVariable;
1792        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1793        final String JavaDoc KEY_NAME= "name"; //$NON-NLS-1$
1794
final LinkedCorrectionProposal proposal= new LinkedCorrectionProposal(label,
1795            context.getCompilationUnit(),
1796            rewrite,
1797            1,
1798            image);
1799        // prepare new variable identifier
1800
final String JavaDoc oldIdentifier= coveringName.getIdentifier();
1801        final String JavaDoc notString = Messages.format(CorrectionMessages.AdvancedQuickAssistProcessor_negatedVariableName, ""); //$NON-NLS-1$
1802
final String JavaDoc newIdentifier;
1803        if (oldIdentifier.startsWith(notString)) {
1804            int notLength= notString.length();
1805            if (oldIdentifier.length() > notLength) {
1806                newIdentifier= Character.toLowerCase(oldIdentifier.charAt(notLength)) + oldIdentifier.substring(notLength + 1);
1807            } else {
1808                newIdentifier= oldIdentifier;
1809            }
1810        } else {
1811            newIdentifier= Messages.format(CorrectionMessages.AdvancedQuickAssistProcessor_negatedVariableName, Character.toUpperCase(oldIdentifier.charAt(0)) + oldIdentifier.substring(1));
1812        }
1813        //
1814
proposal.addLinkedPositionProposal(KEY_NAME, newIdentifier, null);
1815        proposal.addLinkedPositionProposal(KEY_NAME, oldIdentifier, null);
1816        // iterate over linked nodes and replace variable references with negated reference
1817
final HashSet JavaDoc renamedNames= new HashSet JavaDoc();
1818        for (int i= 0; i < linkedNodes.length; i++) {
1819            SimpleName name= linkedNodes[i];
1820            if (renamedNames.contains(name)) {
1821                continue;
1822            }
1823            // prepare new name with new identifier
1824
SimpleName newName= ast.newSimpleName(newIdentifier);
1825            proposal.addLinkedPosition(rewrite.track(newName), name == coveringName, KEY_NAME);
1826            //
1827
StructuralPropertyDescriptor location= name.getLocationInParent();
1828            if (location == SingleVariableDeclaration.NAME_PROPERTY) {
1829                // set new name
1830
rewrite.replace(name, newName, null);
1831            } else if (location == Assignment.LEFT_HAND_SIDE_PROPERTY) {
1832                Assignment assignment= (Assignment) name.getParent();
1833                Expression expression= assignment.getRightHandSide();
1834                int exStart= expression.getStartPosition();
1835                int exEnd= exStart + expression.getLength();
1836                // collect all names that are used in assignments
1837
HashSet JavaDoc overlapNames= new HashSet JavaDoc();
1838                for (int j= 0; j < linkedNodes.length; j++) {
1839                    SimpleName name2= linkedNodes[j];
1840                    if (name2 == null) {
1841                        continue;
1842                    }
1843                    int name2Start= name2.getStartPosition();
1844                    if (exStart <= name2Start && name2Start < exEnd) {
1845                        overlapNames.add(name2);
1846                    }
1847                }
1848                // prepare inverted expression
1849
SimpleNameRenameProvider provider= new SimpleNameRenameProvider() {
1850                    public SimpleName getRenamed(SimpleName simpleName) {
1851                        if (simpleName.resolveBinding() == variableBinding) {
1852                            renamedNames.add(simpleName);
1853                            return ast.newSimpleName(newIdentifier);
1854                        }
1855                        return null;
1856                    }
1857                };
1858                Expression inversedExpression= getInversedBooleanExpression(rewrite, expression, provider);
1859                // if any name was not renamed during expression inverting, we can not already rename it, so fail to create assist
1860
for (Iterator JavaDoc iter= overlapNames.iterator(); iter.hasNext();) {
1861                    Object JavaDoc o= iter.next();
1862                    if (!renamedNames.contains(o)) {
1863                        return false;
1864                    }
1865                }
1866                // check operator and replace if needed
1867
Assignment.Operator operator= assignment.getOperator();
1868                if (operator == Assignment.Operator.BIT_AND_ASSIGN) {
1869                    Assignment newAssignment= ast.newAssignment();
1870                    newAssignment.setLeftHandSide(newName);
1871                    newAssignment.setRightHandSide(inversedExpression);
1872                    newAssignment.setOperator(Assignment.Operator.BIT_OR_ASSIGN);
1873                    rewrite.replace(assignment, newAssignment, null);
1874                } else if (operator == Assignment.Operator.BIT_OR_ASSIGN) {
1875                    Assignment newAssignment= ast.newAssignment();
1876                    newAssignment.setLeftHandSide(newName);
1877                    newAssignment.setRightHandSide(inversedExpression);
1878                    newAssignment.setOperator(Assignment.Operator.BIT_AND_ASSIGN);
1879                    rewrite.replace(assignment, newAssignment, null);
1880                } else {
1881                    rewrite.replace(expression, inversedExpression, null);
1882                    // set new name
1883
rewrite.replace(name, newName, null);
1884                }
1885            } else if (location == VariableDeclarationFragment.NAME_PROPERTY) {
1886                // replace initializer for variable
1887
VariableDeclarationFragment vdf= (VariableDeclarationFragment) name.getParent();
1888                Expression expression= vdf.getInitializer();
1889                if (expression != null) {
1890                    rewrite.replace(expression, getInversedBooleanExpression(rewrite, expression), null);
1891                }
1892                // set new name
1893
rewrite.replace(name, newName, null);
1894            } else if ((name.getParent() instanceof PrefixExpression)
1895                && (((PrefixExpression) name.getParent()).getOperator() == PrefixExpression.Operator.NOT)) {
1896                rewrite.replace(name.getParent(), newName, null);
1897            } else {
1898                PrefixExpression expression= ast.newPrefixExpression();
1899                expression.setOperator(PrefixExpression.Operator.NOT);
1900                expression.setOperand(newName);
1901                rewrite.replace(name, expression, null);
1902            }
1903        }
1904        // add correction proposal
1905
resultingCollections.add(proposal);
1906        return true;
1907    }
1908    private static boolean getPushNegationDownProposals(IInvocationContext context,
1909            ASTNode covering,
1910            Collection JavaDoc resultingCollections) {
1911        PrefixExpression negationExpression= null;
1912        ParenthesizedExpression parenthesizedExpression= null;
1913        // check for case when cursor is on '!' before parentheses
1914
if (covering instanceof PrefixExpression) {
1915            PrefixExpression prefixExpression= (PrefixExpression) covering;
1916            if ((prefixExpression.getOperator() == PrefixExpression.Operator.NOT)
1917                && (prefixExpression.getOperand() instanceof ParenthesizedExpression)) {
1918                negationExpression= prefixExpression;
1919                parenthesizedExpression= (ParenthesizedExpression) prefixExpression.getOperand();
1920            }
1921        }
1922        // check for case when cursor is on parenthesized expression that is negated
1923
if ((covering instanceof ParenthesizedExpression)
1924            && (covering.getParent() instanceof PrefixExpression)
1925            && (((PrefixExpression) covering.getParent()).getOperator() == PrefixExpression.Operator.NOT)) {
1926            negationExpression= (PrefixExpression) covering.getParent();
1927            parenthesizedExpression= (ParenthesizedExpression) covering;
1928        }
1929        //
1930
if (negationExpression == null) {
1931            return false;
1932        }
1933        // we could produce quick assist
1934
if (resultingCollections == null) {
1935            return true;
1936        }
1937        //
1938
final AST ast= covering.getAST();
1939        final ASTRewrite rewrite= ASTRewrite.create(ast);
1940        // prepared inverted expression
1941
Expression inversedExpression= getInversedBooleanExpression(rewrite, parenthesizedExpression.getExpression());
1942        // check, may be we should keep parentheses
1943
boolean keepParentheses= false;
1944        if (negationExpression.getParent() instanceof Expression) {
1945            int parentPrecedence= getExpressionPrecedence((Expression) negationExpression.getParent());
1946            int inversedExpressionPrecedence= getExpressionPrecedence(inversedExpression);
1947            keepParentheses= parentPrecedence < inversedExpressionPrecedence;
1948        }
1949        // replace negated expression with inverted one
1950
if (keepParentheses) {
1951            ParenthesizedExpression pe= ast.newParenthesizedExpression();
1952            pe.setExpression(inversedExpression);
1953            rewrite.replace(negationExpression, pe, null);
1954        } else {
1955            rewrite.replace(negationExpression, inversedExpression, null);
1956        }
1957        // add correction proposal
1958
String JavaDoc label= CorrectionMessages.AdvancedQuickAssistProcessor_pushNegationDown;
1959        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
1960        ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 1, image);
1961        resultingCollections.add(proposal);
1962        return true;
1963    }
1964    
1965    private static Expression getBooleanExpression(ASTNode node) {
1966        if (!(node instanceof Expression)) {
1967            return null;
1968        }
1969
1970        // check if the node is a location where it can be negated
1971
StructuralPropertyDescriptor locationInParent= node.getLocationInParent();
1972        if (locationInParent == QualifiedName.NAME_PROPERTY) {
1973            node= node.getParent();
1974            locationInParent= node.getLocationInParent();
1975        }
1976        while (locationInParent == ParenthesizedExpression.EXPRESSION_PROPERTY) {
1977            node= node.getParent();
1978            locationInParent= node.getLocationInParent();
1979        }
1980        Expression expression= (Expression) node;
1981        if (!isBoolean(expression)) {
1982            return null;
1983        }
1984        if (expression.getParent() instanceof InfixExpression) {
1985            return expression;
1986        }
1987        if (locationInParent == Assignment.RIGHT_HAND_SIDE_PROPERTY
1988                || locationInParent == IfStatement.EXPRESSION_PROPERTY
1989                || locationInParent == WhileStatement.EXPRESSION_PROPERTY
1990                || locationInParent == DoStatement.EXPRESSION_PROPERTY
1991                || locationInParent == ReturnStatement.EXPRESSION_PROPERTY
1992                || locationInParent == ForStatement.EXPRESSION_PROPERTY
1993                || locationInParent == MethodInvocation.ARGUMENTS_PROPERTY
1994                || locationInParent == ConstructorInvocation.ARGUMENTS_PROPERTY
1995                || locationInParent == SuperMethodInvocation.ARGUMENTS_PROPERTY
1996                || locationInParent == EnumConstantDeclaration.ARGUMENTS_PROPERTY
1997                || locationInParent == SuperConstructorInvocation.ARGUMENTS_PROPERTY
1998                || locationInParent == ClassInstanceCreation.ARGUMENTS_PROPERTY
1999                || locationInParent == ConditionalExpression.EXPRESSION_PROPERTY
2000                || locationInParent == PrefixExpression.OPERAND_PROPERTY) {
2001            return expression;
2002        }
2003        return null;
2004    }
2005    
2006    
2007    
2008    private static boolean getPullNegationUpProposals(IInvocationContext context, ASTNode covering, ArrayList JavaDoc coveredNodes, Collection JavaDoc resultingCollections) {
2009        if (coveredNodes.size() != 1) {
2010            return false;
2011        }
2012        //
2013
ASTNode fullyCoveredNode= (ASTNode) coveredNodes.get(0);
2014
2015        Expression expression= getBooleanExpression(fullyCoveredNode);
2016        if (expression == null) {
2017            return false;
2018        }
2019        // we could produce quick assist
2020
if (resultingCollections == null) {
2021            return true;
2022        }
2023        //
2024
AST ast= expression.getAST();
2025        final ASTRewrite rewrite= ASTRewrite.create(ast);
2026        // prepared inverted expression
2027
Expression inversedExpression= getInversedBooleanExpression(rewrite, expression);
2028        // prepare ParenthesizedExpression
2029
ParenthesizedExpression parenthesizedExpression = ast.newParenthesizedExpression();
2030        parenthesizedExpression.setExpression(inversedExpression);
2031        // prepare NOT prefix expression
2032
PrefixExpression prefixExpression = ast.newPrefixExpression();
2033        prefixExpression.setOperator(PrefixExpression.Operator.NOT);
2034        prefixExpression.setOperand(parenthesizedExpression);
2035        // replace old expression
2036
rewrite.replace(expression, prefixExpression, null);
2037        // add correction proposal
2038
String JavaDoc label= CorrectionMessages.AdvancedQuickAssistProcessor_pullNegationUp;
2039        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
2040        ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 1, image);
2041        resultingCollections.add(proposal);
2042        return true;
2043    }
2044    private static boolean getJoinIfListInIfElseIfProposals(IInvocationContext context,
2045            ASTNode covering,
2046            ArrayList JavaDoc coveredNodes,
2047            Collection JavaDoc resultingCollections) {
2048        if (coveredNodes.isEmpty()) {
2049            return false;
2050        }
2051        // check that we have more than one covered statement
2052
if (coveredNodes.size() < 2) {
2053            return false;
2054        }
2055        // check that all selected nodes are 'if' statements with only 'then' statement
2056
for (Iterator JavaDoc iter= coveredNodes.iterator(); iter.hasNext();) {
2057            ASTNode node= (ASTNode) iter.next();
2058            if (!(node instanceof IfStatement)) {
2059                return false;
2060            }
2061            IfStatement ifStatement= (IfStatement) node;
2062            if (ifStatement.getElseStatement() != null) {
2063                return false;
2064            }
2065        }
2066        // we could produce quick assist
2067
if (resultingCollections == null) {
2068            return true;
2069        }
2070        //
2071
final AST ast= covering.getAST();
2072        final ASTRewrite rewrite= ASTRewrite.create(ast);
2073        //
2074
IfStatement firstIfStatement= (IfStatement) coveredNodes.get(0);
2075        IfStatement firstNewIfStatement= null;
2076        //
2077
IfStatement prevIfStatement= null;
2078        for (Iterator JavaDoc iter= coveredNodes.iterator(); iter.hasNext();) {
2079            IfStatement ifStatement= (IfStatement) iter.next();
2080            // prepare new 'if' statement
2081
IfStatement newIfStatement= ast.newIfStatement();
2082            newIfStatement.setExpression((Expression) rewrite.createMoveTarget(ifStatement.getExpression()));
2083            // prepare 'then' statement and convert into block if needed
2084
Statement thenStatement= (Statement) rewrite.createMoveTarget(ifStatement.getThenStatement());
2085            if (ifStatement.getThenStatement() instanceof IfStatement) {
2086                IfStatement ifBodyStatement= (IfStatement) ifStatement.getThenStatement();
2087                if (ifBodyStatement.getElseStatement() == null) {
2088                    Block thenBlock= ast.newBlock();
2089                    thenBlock.statements().add(thenStatement);
2090                    thenStatement= thenBlock;
2091                }
2092            }
2093            newIfStatement.setThenStatement(thenStatement);
2094            //
2095
if (prevIfStatement != null) {
2096                prevIfStatement.setElseStatement(newIfStatement);
2097                rewrite.remove(ifStatement, null);
2098            } else {
2099                firstNewIfStatement= newIfStatement;
2100            }
2101            prevIfStatement= newIfStatement;
2102        }
2103        rewrite.replace(firstIfStatement, firstNewIfStatement, null);
2104        // add correction proposal
2105
String JavaDoc label= CorrectionMessages.AdvancedQuickAssistProcessor_joinIfSequence;
2106        Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
2107        ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label, context.getCompilationUnit(), rewrite, 1, image);
2108        resultingCollections.add(proposal);
2109        return true;
2110    }
2111    private static boolean getConvertSwitchToIfProposals(IInvocationContext context,
2112            ASTNode covering,
2113            Collection JavaDoc resultingCollections) {
2114        if (!(covering instanceof SwitchStatement)) {
2115            return false;
2116        }
2117        // we could produce quick assist (if all 'case' statements end with 'break')
2118
if (resultingCollections == null) {
2119            return true;
2120        }
2121        //
2122
final AST ast= covering.getAST();
2123        final ASTRewrite rewrite= ASTRewrite.create(ast);
2124        final ImportRewrite importRewrite= CodeStyleConfiguration.createImportRewrite(context.getASTRoot(), true);
2125        //
2126
SwitchStatement switchStatement= (SwitchStatement) covering;
2127        IfStatement firstIfStatement= null;
2128        IfStatement currentIfStatement= null;
2129        Block currentBlock= null;
2130        boolean hasStopAsLastExecutableStatement = false;
2131        Block defaultBlock= null;
2132        InfixExpression currentCondition= null;
2133        boolean defaultFound= false;
2134        int caseCount = 0;
2135        
2136        ArrayList JavaDoc allBlocks= new ArrayList JavaDoc();
2137        //
2138
for (Iterator JavaDoc iter= switchStatement.statements().iterator(); iter.hasNext();) {
2139            Statement statement= (Statement) iter.next();
2140            if (statement instanceof SwitchCase) {
2141                SwitchCase switchCase= (SwitchCase) statement;
2142                caseCount++;
2143                // special case: pass through
2144
if (currentBlock != null) {
2145                    if (!hasStopAsLastExecutableStatement) {
2146                        return false;
2147                    }
2148                    currentBlock= null;
2149                }
2150                // for 'default' we just will not create condition
2151
if (switchCase.isDefault()) {
2152                    defaultFound= true;
2153                    if (currentCondition != null) {
2154                        // we can not convert one or more 'case' statements and 'default' nor in conditional if, nor in 'else' without code duplication
2155
return false;
2156                    }
2157                    continue;
2158                }
2159                if (defaultFound) {
2160                    return false;
2161                }
2162                // prepare condition
2163
InfixExpression switchCaseCondition= createSwitchCaseCondition(ast, rewrite, importRewrite, switchStatement, switchCase);
2164                if (currentCondition == null) {
2165                    currentCondition= switchCaseCondition;
2166                } else {
2167                    InfixExpression condition= ast.newInfixExpression();
2168                    condition.setOperator(InfixExpression.Operator.CONDITIONAL_OR);
2169                    condition.setLeftOperand(currentCondition);
2170                    condition.setRightOperand(switchCaseCondition);
2171                    currentCondition= condition;
2172                }
2173            } else if (statement instanceof BreakStatement) {
2174                currentBlock= null;
2175            } else {
2176                // ensure that current block exists as 'then' statement of 'if'
2177
if (currentBlock == null) {
2178                    defaultFound= false;
2179                    if (currentCondition != null) {
2180                        IfStatement ifStatement;
2181                        if (firstIfStatement == null) {
2182                            firstIfStatement= ast.newIfStatement();
2183                            ifStatement= firstIfStatement;
2184                        } else {
2185                            ifStatement= ast.newIfStatement();
2186                            currentIfStatement.setElseStatement(ifStatement);
2187                        }
2188                        currentIfStatement= ifStatement;
2189                        ifStatement.setExpression(currentCondition);
2190                        currentCondition= null;
2191                        currentBlock= ast.newBlock();
2192                        ifStatement.setThenStatement(currentBlock);
2193                        allBlocks.add(currentBlock);
2194                    } else {
2195                        // case for default:
2196
defaultBlock= ast.newBlock();
2197                        currentBlock= defaultBlock;
2198                        allBlocks.add(currentBlock);
2199                        // delay adding of default block
2200
}
2201                }
2202                // add current statement in current block
2203
{
2204                    hasStopAsLastExecutableStatement = hasStopAsLastExecutableStatement(statement);
2205                    Statement copyStatement= copyStatementExceptBreak(ast, rewrite, statement);
2206                                        
2207                    
2208                    currentBlock.statements().add(copyStatement);
2209                }
2210            }
2211        }
2212        // check, may be we have delayed default block
2213
if (defaultBlock != null) {
2214            currentIfStatement.setElseStatement(defaultBlock);
2215        }
2216        // remove unnecessary blocks in blocks
2217
for (int i= 0; i < allBlocks.size(); i++) {
2218            Block block= (Block) allBlocks.get(i);
2219            List JavaDoc statements= block.statements();
2220            if (statements.size() == 1 && statements.get(0) instanceof Block) {
2221                Block innerBlock= (Block) statements.remove(0);
2222                block.getParent().setStructuralProperty(block.getLocationInParent(), innerBlock);
2223            }
2224        }
2225        // replace 'switch' with single if-else-if statement
2226
rewrite.replace(switchStatement, firstIfStatement, null);
2227        // prepare label, specially for Daniel :-)
2228
String JavaDoc label= CorrectionMessages.AdvancedQuickAssistProcessor_convertSwitchToIf;
2229
2230        // add correction proposal
2231
Image image= JavaPluginImages.get(JavaPluginImages.IMG_CORRECTION_CHANGE);
2232        ASTRewriteCorrectionProposal proposal= new ASTRewriteCorrectionProposal(label,
2233            context.getCompilationUnit(),
2234            rewrite,
2235            1,
2236            image);
2237        proposal.setImportRewrite(importRewrite);
2238        resultingCollections.add(proposal);
2239        return true;
2240    }
2241    private static InfixExpression createSwitchCaseCondition(AST ast, ASTRewrite rewrite, ImportRewrite importRewrite,
2242                                                          SwitchStatement switchStatement, SwitchCase switchCase) {
2243        InfixExpression condition= ast.newInfixExpression();
2244        condition.setOperator(InfixExpression.Operator.EQUALS);
2245        //
2246
Expression leftExpression= (Expression) rewrite.createCopyTarget(switchStatement.getExpression());
2247        condition.setLeftOperand(leftExpression);
2248        //
2249
Expression rightExpression= null;
2250        Expression expression= switchCase.getExpression();
2251        if (expression instanceof SimpleName && ((SimpleName) expression).resolveBinding() instanceof IVariableBinding) {
2252            IVariableBinding binding= (IVariableBinding) ((SimpleName) expression).resolveBinding();
2253            if (binding.isEnumConstant()) {
2254                String JavaDoc qualifiedName= importRewrite.addImport(binding.getDeclaringClass()) + '.' + binding.getName();
2255                rightExpression= ast.newName(qualifiedName);
2256            }
2257        }
2258        if (rightExpression == null) {
2259            rightExpression= (Expression) rewrite.createCopyTarget(expression);
2260        }
2261        condition.setRightOperand(rightExpression);
2262        //
2263
return condition;
2264    }
2265    
2266    
2267    private static boolean hasStopAsLastExecutableStatement(Statement lastStatement) {
2268        if ((lastStatement instanceof ReturnStatement) || (lastStatement instanceof BreakStatement)) {
2269            return true;
2270        }
2271        if (lastStatement instanceof Block) {
2272            Block block= (Block)lastStatement;
2273            lastStatement = (Statement) block.statements().get(block.statements().size() - 1);
2274            return hasStopAsLastExecutableStatement(lastStatement);
2275        }
2276        return false;
2277    }
2278    private static Statement copyStatementExceptBreak(AST ast, ASTRewrite rewrite, Statement source) {
2279        if (source instanceof Block) {
2280            Block block= (Block) source;
2281            Block newBlock= ast.newBlock();
2282            for (Iterator JavaDoc iter= block.statements().iterator(); iter.hasNext();) {
2283                Statement statement= (Statement) iter.next();
2284                if (statement instanceof BreakStatement) {
2285                    continue;
2286                }
2287                newBlock.statements().add(copyStatementExceptBreak(ast, rewrite, statement));
2288            }
2289            return newBlock;
2290        }
2291        return (Statement) rewrite.createMoveTarget(source);
2292    }
2293}
2294
Popular Tags