]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/core extension/org/eclipse/jdt/internal/corext/fix/ConvertForLoopOperation.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core extension / org / eclipse / jdt / internal / corext / fix / ConvertForLoopOperation.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 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  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package org.eclipse.jdt.internal.corext.fix;
12
13 import java.util.List;
14
15 import org.eclipse.core.runtime.CoreException;
16 import org.eclipse.core.runtime.IStatus;
17 import org.eclipse.core.runtime.Status;
18
19 import org.eclipse.text.edits.TextEditGroup;
20
21 import org.eclipse.jdt.core.IJavaElement;
22 import org.eclipse.jdt.core.IJavaProject;
23 import org.eclipse.jdt.core.dom.AST;
24 import org.eclipse.jdt.core.dom.ASTNode;
25 import org.eclipse.jdt.core.dom.ArrayAccess;
26 import org.eclipse.jdt.core.dom.Assignment;
27 import org.eclipse.jdt.core.dom.CompilationUnit;
28 import org.eclipse.jdt.core.dom.EnhancedForStatement;
29 import org.eclipse.jdt.core.dom.Expression;
30 import org.eclipse.jdt.core.dom.FieldAccess;
31 import org.eclipse.jdt.core.dom.ForStatement;
32 import org.eclipse.jdt.core.dom.IBinding;
33 import org.eclipse.jdt.core.dom.ITypeBinding;
34 import org.eclipse.jdt.core.dom.IVariableBinding;
35 import org.eclipse.jdt.core.dom.InfixExpression;
36 import org.eclipse.jdt.core.dom.InfixExpression.Operator;
37 import org.eclipse.jdt.core.dom.Modifier;
38 import org.eclipse.jdt.core.dom.Name;
39 import org.eclipse.jdt.core.dom.NumberLiteral;
40 import org.eclipse.jdt.core.dom.PostfixExpression;
41 import org.eclipse.jdt.core.dom.PrefixExpression;
42 import org.eclipse.jdt.core.dom.PrimitiveType;
43 import org.eclipse.jdt.core.dom.QualifiedName;
44 import org.eclipse.jdt.core.dom.SimpleName;
45 import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
46 import org.eclipse.jdt.core.dom.Statement;
47 import org.eclipse.jdt.core.dom.ThisExpression;
48 import org.eclipse.jdt.core.dom.Type;
49 import org.eclipse.jdt.core.dom.VariableDeclarationExpression;
50 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
51 import org.eclipse.jdt.core.dom.VariableDeclarationStatement;
52 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
53 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
54 import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
55
56 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
57 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
58 import org.eclipse.jdt.internal.corext.dom.GenericVisitor;
59 import org.eclipse.jdt.internal.corext.dom.JdtASTMatcher;
60 import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
61 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
62 import org.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer;
63 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
64
65
66 public class ConvertForLoopOperation extends ConvertLoopOperation {
67
68         private static final String LENGTH_QUERY= "length"; //$NON-NLS-1$
69         private static final String LITERAL_0= "0"; //$NON-NLS-1$
70         private static final String LITERAL_1= "1"; //$NON-NLS-1$
71         private static final class InvalidBodyError extends Error {
72                 private static final long serialVersionUID= 1L;
73         }
74
75         IVariableBinding fIndexBinding;
76         private IVariableBinding fLengthBinding;
77         IBinding fArrayBinding;
78         Expression fArrayAccess;
79         VariableDeclarationFragment fElementDeclaration;
80         boolean fMakeFinal;
81
82         public ConvertForLoopOperation(ForStatement forStatement) {
83                 this(forStatement, new String[0], false);
84         }
85
86         public ConvertForLoopOperation(ForStatement forStatement, String[] usedNames, boolean makeFinal) {
87                 super(forStatement, usedNames);
88                 fMakeFinal= makeFinal;
89         }
90
91         @Override
92         public IStatus satisfiesPreconditions() {
93                 ForStatement statement= getForStatement();
94                 CompilationUnit ast= (CompilationUnit)statement.getRoot();
95
96                 IJavaElement javaElement= ast.getJavaElement();
97                 if (javaElement == null)
98                         return ERROR_STATUS;
99
100                 if (!JavaModelUtil.is50OrHigher(javaElement.getJavaProject()))
101                         return ERROR_STATUS;
102
103                 if (!validateInitializers(statement))
104                         return ERROR_STATUS;
105
106                 if (!validateExpression(statement))
107                         return ERROR_STATUS;
108
109                 if (!validateUpdaters(statement))
110                         return ERROR_STATUS;
111
112                 if (!validateBody(statement))
113                         return ERROR_STATUS;
114
115                 return Status.OK_STATUS;
116         }
117
118
119         /*
120          * Must be one of:
121          * <ul>
122          * <li>int [result]= 0;</li>
123          * <li>int [result]= 0, [lengthBinding]= [arrayBinding].length;</li>
124          * <li>int , [result]= 0;</li>
125          * </ul>
126          */
127         private boolean validateInitializers(ForStatement statement) {
128                 List<Expression> initializers= statement.initializers();
129                 if (initializers.size() != 1)
130                         return false;
131
132                 Expression expression= initializers.get(0);
133                 if (!(expression instanceof VariableDeclarationExpression))
134                         return false;
135
136                 VariableDeclarationExpression declaration= (VariableDeclarationExpression)expression;
137                 ITypeBinding declarationBinding= declaration.resolveTypeBinding();
138                 if (declarationBinding == null)
139                         return false;
140
141                 if (!declarationBinding.isPrimitive())
142                         return false;
143
144                 if (!PrimitiveType.INT.toString().equals(declarationBinding.getQualifiedName()))
145                         return false;
146
147                 List<VariableDeclarationFragment> fragments= declaration.fragments();
148                 if (fragments.size() == 1) {
149                         IVariableBinding indexBinding= getIndexBindingFromFragment(fragments.get(0));
150                         if (indexBinding == null)
151                                 return false;
152
153                         fIndexBinding= indexBinding;
154                         return true;
155                 } else if (fragments.size() == 2) {
156                         IVariableBinding indexBinding= getIndexBindingFromFragment(fragments.get(0));
157                         if (indexBinding == null) {
158                                 indexBinding= getIndexBindingFromFragment(fragments.get(1));
159                                 if (indexBinding == null)
160                                         return false;
161
162                                 if (!validateLengthFragment(fragments.get(0)))
163                                         return false;
164                         } else {
165                                 if (!validateLengthFragment(fragments.get(1)))
166                                         return false;
167                         }
168
169                         fIndexBinding= indexBinding;
170                         return true;
171                 }
172                 return false;
173         }
174
175
176         /*
177          * [lengthBinding]= [arrayBinding].length
178          */
179         private boolean validateLengthFragment(VariableDeclarationFragment fragment) {
180                 Expression initializer= fragment.getInitializer();
181                 if (initializer == null)
182                         return false;
183
184                 if (!validateLengthQuery(initializer))
185                         return false;
186
187                 IVariableBinding lengthBinding= (IVariableBinding)fragment.getName().resolveBinding();
188                 if (lengthBinding == null)
189                         return false;
190                 fLengthBinding= lengthBinding;
191
192                 return true;
193         }
194
195
196         /*
197          * Must be one of:
198          * <ul>
199          * <li>[result]= 0</li>
200          * </ul>
201          */
202         private IVariableBinding getIndexBindingFromFragment(VariableDeclarationFragment fragment) {
203                 Expression initializer= fragment.getInitializer();
204                 if (!(initializer instanceof NumberLiteral))
205                         return null;
206
207                 NumberLiteral number= (NumberLiteral)initializer;
208                 if (!LITERAL_0.equals(number.getToken()))
209                         return null;
210
211                 return (IVariableBinding)fragment.getName().resolveBinding();
212         }
213
214
215         /*
216          * Must be one of:
217          * <ul>
218          * <li>[indexBinding] < [result].length;</li>
219          * <li>[result].length > [indexBinding];</li>
220          * <li>[indexBinding] < [lengthBinding];</li>
221          * <li>[lengthBinding] > [indexBinding];</li>
222          * </ul>
223          */
224         private boolean validateExpression(ForStatement statement) {
225                 Expression expression= statement.getExpression();
226                 if (!(expression instanceof InfixExpression))
227                         return false;
228
229                 InfixExpression infix= (InfixExpression)expression;
230
231                 Expression left= infix.getLeftOperand();
232                 Expression right= infix.getRightOperand();
233                 if (left instanceof SimpleName && right instanceof SimpleName) {
234                         IVariableBinding lengthBinding= fLengthBinding;
235                         if (lengthBinding == null)
236                                 return false;
237
238                         IBinding leftBinding= ((SimpleName)left).resolveBinding();
239                         IBinding righBinding= ((SimpleName)right).resolveBinding();
240
241                         if (fIndexBinding.equals(leftBinding)) {
242                                 return lengthBinding.equals(righBinding);
243                         } else if (fIndexBinding.equals(righBinding)) {
244                                 return lengthBinding.equals(leftBinding);
245                         }
246
247                         return false;
248                 } else if (left instanceof SimpleName) {
249                         if (!fIndexBinding.equals(((SimpleName)left).resolveBinding()))
250                                 return false;
251
252                         if (!Operator.LESS.equals(infix.getOperator()))
253                                 return false;
254
255                         return validateLengthQuery(right);
256                 } else if (right instanceof SimpleName) {
257                         if (!fIndexBinding.equals(((SimpleName)right).resolveBinding()))
258                                 return false;
259
260                         if (!Operator.GREATER.equals(infix.getOperator()))
261                                 return false;
262
263                         return validateLengthQuery(left);
264                 }
265
266                 return false;
267         }
268
269
270         /*
271          * Must be one of:
272          * <ul>
273          * <li>[result].length</li>
274          * </ul>
275          */
276         private boolean validateLengthQuery(Expression lengthQuery) {
277                 if (lengthQuery instanceof QualifiedName) {
278                         QualifiedName qualifiedName= (QualifiedName)lengthQuery;
279                         SimpleName name= qualifiedName.getName();
280                         if (!LENGTH_QUERY.equals(name.getIdentifier()))
281                                 return false;
282
283                         Name arrayAccess= qualifiedName.getQualifier();
284                         ITypeBinding accessType= arrayAccess.resolveTypeBinding();
285                         if (accessType == null)
286                                 return false;
287
288                         if (!accessType.isArray())
289                                 return false;
290
291                         IBinding arrayBinding= arrayAccess.resolveBinding();
292                         if (arrayBinding == null)
293                                 return false;
294
295                         fArrayBinding= arrayBinding;
296                         fArrayAccess= arrayAccess;
297                         return true;
298                 } else if (lengthQuery instanceof FieldAccess) {
299                         FieldAccess fieldAccess= (FieldAccess)lengthQuery;
300                         SimpleName name= fieldAccess.getName();
301                         if (!LENGTH_QUERY.equals(name.getIdentifier()))
302                                 return false;
303
304                         Expression arrayAccess= fieldAccess.getExpression();
305                         ITypeBinding accessType= arrayAccess.resolveTypeBinding();
306                         if (accessType == null)
307                                 return false;
308
309                         if (!accessType.isArray())
310                                 return false;
311
312                         IBinding arrayBinding= getBinding(arrayAccess);
313                         if (arrayBinding == null)
314                                 return false;
315
316                         fArrayBinding= arrayBinding;
317                         fArrayAccess= arrayAccess;
318                         return true;
319                 }
320
321                 return false;
322         }
323
324
325         /*
326          * Must be one of:
327          * <ul>
328          * <li>[indexBinding]++</li>
329          * <li>++[indexBinding]</li>
330          * <li>[indexBinding]+= 1</li>
331          * <li>[indexBinding]= [indexBinding] + 1</li>
332          * <li>[indexBinding]= 1 + [indexBinding]</li>
333          * <ul>
334          */
335         private boolean validateUpdaters(ForStatement statement) {
336                 List<Expression> updaters= statement.updaters();
337                 if (updaters.size() != 1)
338                         return false;
339
340                 Expression updater= updaters.get(0);
341                 if (updater instanceof PostfixExpression) {
342                         PostfixExpression postfix= (PostfixExpression)updater;
343
344                         if (!PostfixExpression.Operator.INCREMENT.equals(postfix.getOperator()))
345                                 return false;
346
347                         IBinding binding= getBinding(postfix.getOperand());
348                         if (!fIndexBinding.equals(binding))
349                                 return false;
350
351                         return true;
352                 } else if (updater instanceof PrefixExpression) {
353                         PrefixExpression prefix= (PrefixExpression) updater;
354
355                         if (!PrefixExpression.Operator.INCREMENT.equals(prefix.getOperator()))
356                                 return false;
357
358                         IBinding binding= getBinding(prefix.getOperand());
359                         if (!fIndexBinding.equals(binding))
360                                 return false;
361
362                         return true;
363                 } else if (updater instanceof Assignment) {
364                         Assignment assignment= (Assignment)updater;
365                         Expression left= assignment.getLeftHandSide();
366                         IBinding binding= getBinding(left);
367                         if (!fIndexBinding.equals(binding))
368                                 return false;
369
370                         if (Assignment.Operator.PLUS_ASSIGN.equals(assignment.getOperator())) {
371                                 return isOneLiteral(assignment.getRightHandSide());
372                         } else if (Assignment.Operator.ASSIGN.equals(assignment.getOperator())) {
373                                 Expression right= assignment.getRightHandSide();
374                                 if (!(right instanceof InfixExpression))
375                                         return false;
376
377                                 InfixExpression infixExpression= (InfixExpression)right;
378                                 Expression leftOperand= infixExpression.getLeftOperand();
379                                 IBinding leftBinding= getBinding(leftOperand);
380                                 Expression rightOperand= infixExpression.getRightOperand();
381                                 IBinding rightBinding= getBinding(rightOperand);
382
383                                 if (fIndexBinding.equals(leftBinding)) {
384                                         return isOneLiteral(rightOperand);
385                                 } else if (fIndexBinding.equals(rightBinding)) {
386                                         return isOneLiteral(leftOperand);
387                                 }
388                         }
389                 }
390                 return false;
391         }
392
393         private boolean isOneLiteral(Expression expression) {
394                 if (!(expression instanceof NumberLiteral))
395                         return false;
396
397                 NumberLiteral literal= (NumberLiteral)expression;
398                 return LITERAL_1.equals(literal.getToken());
399         }
400
401
402         /*
403          * returns false iff
404          * <ul>
405          * <li><code>indexBinding</code> is used for anything else then accessing
406          * an element of <code>arrayBinding</code></li>
407          * <li><code>arrayBinding</code> is assigned</li>
408          * <li>an element of <code>arrayBinding</code> is assigned</li>
409          * <li><code>lengthBinding</code> is referenced</li>
410          * </ul>
411          * within <code>body</code>
412          */
413         private boolean validateBody(ForStatement statement) {
414                 Statement body= statement.getBody();
415                 try {
416                         body.accept(new GenericVisitor() {
417                                 /**
418                                  * {@inheritDoc}
419                                  */
420                                 @Override
421                                 protected boolean visitNode(ASTNode node) {
422                                         if (node instanceof Name) {
423                                                 Name name= (Name)node;
424                                                 IBinding nameBinding= name.resolveBinding();
425                                                 if (nameBinding == null)
426                                                         throw new InvalidBodyError();
427
428                                                 if (nameBinding.equals(fIndexBinding)) {
429                                                         if (node.getLocationInParent() != ArrayAccess.INDEX_PROPERTY)
430                                                                 throw new InvalidBodyError();
431
432                                                         ArrayAccess arrayAccess= (ArrayAccess)node.getParent();
433                                                         Expression array= arrayAccess.getArray();
434                                                         if (array instanceof QualifiedName) {
435                                                                 if (!(fArrayAccess instanceof QualifiedName))
436                                                                         throw new InvalidBodyError();
437
438                                                                 IBinding varBinding1= ((QualifiedName) array).getQualifier().resolveBinding();
439                                                                 if (varBinding1 == null)
440                                                                         throw new InvalidBodyError();
441
442                                                                 IBinding varBinding2= ((QualifiedName) fArrayAccess).getQualifier().resolveBinding();
443                                                                 if (!varBinding1.equals(varBinding2))
444                                                                         throw new InvalidBodyError();
445                                                         } else if (array instanceof FieldAccess) {
446                                                                 Expression arrayExpression= ((FieldAccess) array).getExpression();
447                                                                 if (arrayExpression instanceof ThisExpression) {
448                                                                         if (fArrayAccess instanceof FieldAccess) {
449                                                                                 Expression arrayAccessExpression= ((FieldAccess) fArrayAccess).getExpression();
450                                                                                 if (!(arrayAccessExpression instanceof ThisExpression))
451                                                                                         throw new InvalidBodyError();
452                                                                         } else if (fArrayAccess instanceof QualifiedName) {
453                                                                                 throw new InvalidBodyError();
454                                                                         }
455                                                                 } else {
456                                                                         if (!(fArrayAccess instanceof FieldAccess))
457                                                                                 throw new InvalidBodyError();
458
459                                                                         Expression arrayAccessExpression= ((FieldAccess) fArrayAccess).getExpression();
460                                                                         if (!arrayExpression.subtreeMatch(new JdtASTMatcher(), arrayAccessExpression)) {
461                                                                                 throw new InvalidBodyError();
462                                                                         }
463                                                                 }
464                                                         } else {
465                                                                 if (fArrayAccess instanceof QualifiedName) {
466                                                                         throw new InvalidBodyError();
467                                                                 }
468                                                                 if (fArrayAccess instanceof FieldAccess) {
469                                                                         Expression arrayAccessExpression= ((FieldAccess) fArrayAccess).getExpression();
470                                                                         if (!(arrayAccessExpression instanceof ThisExpression))
471                                                                                 throw new InvalidBodyError();
472                                                                 }
473                                                         }
474
475                                                         IBinding binding= getBinding(array);
476                                                         if (binding == null)
477                                                                 throw new InvalidBodyError();
478
479                                                         if (!fArrayBinding.equals(binding))
480                                                                 throw new InvalidBodyError();
481
482                                                 } else if (nameBinding.equals(fArrayBinding)) {
483                                                         if (isAssigned(node))
484                                                                 throw new InvalidBodyError();
485                                                 } else if (nameBinding.equals(fLengthBinding)) {
486                                                         throw new InvalidBodyError();
487                                                 } else if (fElementDeclaration != null && nameBinding.equals(fElementDeclaration.getName().resolveBinding())) {
488                                                         if (isAssigned(node))
489                                                                 fElementDeclaration= null;
490                                                 }
491                                         }
492
493                                         return true;
494                                 }
495
496                                 private boolean isAssigned(ASTNode current) {
497                                         while (current != null && !(current instanceof Statement)) {
498                                                 if (current.getLocationInParent() == Assignment.LEFT_HAND_SIDE_PROPERTY)
499                                                         return true;
500
501                                                 if (current instanceof PrefixExpression)
502                                                         return true;
503
504                                                 if (current instanceof PostfixExpression)
505                                                         return true;
506
507                                                 current= current.getParent();
508                                         }
509
510                                         return false;
511                                 }
512
513                                 @Override
514                                 public boolean visit(ArrayAccess node) {
515                                         if (fElementDeclaration != null)
516                                                 return super.visit(node);
517
518                                         IBinding binding= getBinding(node.getArray());
519                                         if (fArrayBinding.equals(binding)) {
520                                                 IBinding index= getBinding(node.getIndex());
521                                                 if (fIndexBinding.equals(index)) {
522                                                         if (node.getLocationInParent() == VariableDeclarationFragment.INITIALIZER_PROPERTY) {
523                                                                 fElementDeclaration= (VariableDeclarationFragment)node.getParent();
524                                                         }
525                                                 }
526                                         }
527                                         return super.visit(node);
528                                 }
529
530                         });
531                 } catch (InvalidBodyError e) {
532                         return false;
533                 }
534
535                 return true;
536         }
537
538         private static IBinding getBinding(Expression expression) {
539                 if (expression instanceof FieldAccess) {
540                         return ((FieldAccess)expression).resolveFieldBinding();
541                 } else if (expression instanceof Name) {
542                         return ((Name)expression).resolveBinding();
543                 }
544
545                 return null;
546         }
547
548         @Override
549         public String getIntroducedVariableName() {
550                 if (fElementDeclaration != null) {
551                         return fElementDeclaration.getName().getIdentifier();
552                 } else {
553                         ForStatement forStatement= getForStatement();
554                         IJavaProject javaProject= ((CompilationUnit)forStatement.getRoot()).getJavaElement().getJavaProject();
555                         String[] proposals= getVariableNameProposals(fArrayAccess.resolveTypeBinding(), javaProject);
556                         return proposals[0];
557                 }
558         }
559
560         /**
561          * {@inheritDoc}
562          */
563         @Override
564         public void rewriteAST(CompilationUnitRewrite cuRewrite, LinkedProposalModel positionGroups) throws CoreException {
565                 TextEditGroup group= createTextEditGroup(FixMessages.Java50Fix_ConvertToEnhancedForLoop_description, cuRewrite);
566                 ASTRewrite rewrite= cuRewrite.getASTRewrite();
567
568                 TightSourceRangeComputer rangeComputer;
569                 if (rewrite.getExtendedSourceRangeComputer() instanceof TightSourceRangeComputer) {
570                         rangeComputer= (TightSourceRangeComputer)rewrite.getExtendedSourceRangeComputer();
571                 } else {
572                         rangeComputer= new TightSourceRangeComputer();
573                 }
574                 rangeComputer.addTightSourceNode(getForStatement());
575                 rewrite.setTargetSourceRangeComputer(rangeComputer);
576
577                 Statement statement= convert(cuRewrite, group, positionGroups);
578                 rewrite.replace(getForStatement(), statement, group);
579         }
580
581         @Override
582         protected Statement convert(CompilationUnitRewrite cuRewrite, TextEditGroup group, LinkedProposalModel positionGroups) throws CoreException {
583                 ASTRewrite rewrite= cuRewrite.getASTRewrite();
584                 ImportRewrite importRewrite= cuRewrite.getImportRewrite();
585
586                 ForStatement forStatement= getForStatement();
587
588                 IJavaProject javaProject= ((CompilationUnit)forStatement.getRoot()).getJavaElement().getJavaProject();
589                 String[] proposals= getVariableNameProposals(fArrayAccess.resolveTypeBinding(), javaProject);
590
591                 String parameterName;
592                 if (fElementDeclaration != null) {
593                         parameterName= fElementDeclaration.getName().getIdentifier();
594                 } else {
595                         parameterName= proposals[0];
596                 }
597
598                 LinkedProposalPositionGroup pg= positionGroups.getPositionGroup(parameterName, true);
599                 EnhancedForStatement result= pg.generated_1448160073152004877(group, rewrite, importRewrite, forStatement, proposals, parameterName, this);
600                 result.setBody(getBody(cuRewrite, group, positionGroups));
601
602                 positionGroups.setEndPosition(rewrite.track(result));
603
604                 return result;
605         }
606
607         void convertBody(Statement body, final IBinding indexBinding, final IBinding arrayBinding, final String parameterName, final ASTRewrite rewrite, final TextEditGroup editGroup, final LinkedProposalPositionGroup pg) {
608                 final AST ast= body.getAST();
609
610                 body.accept(new GenericVisitor() {
611                         @Override
612                         public boolean visit(ArrayAccess node) {
613                                 IBinding binding= getBinding(node.getArray());
614                                 if (arrayBinding.equals(binding)) {
615                                         IBinding index= getBinding(node.getIndex());
616                                         if (indexBinding.equals(index)) {
617                                                 replaceAccess(node);
618                                         }
619                                 }
620
621                                 return super.visit(node);
622                         }
623
624                         private void replaceAccess(ASTNode node) {
625                                 if (fElementDeclaration != null && node.getLocationInParent() == VariableDeclarationFragment.INITIALIZER_PROPERTY) {
626                                         VariableDeclarationFragment fragment= (VariableDeclarationFragment)node.getParent();
627                                         IBinding targetBinding= fragment.getName().resolveBinding();
628                                         if (targetBinding != null) {
629                                                 VariableDeclarationStatement statement= (VariableDeclarationStatement)fragment.getParent();
630
631                                                 if (statement.fragments().size() == 1) {
632                                                         rewrite.remove(statement, editGroup);
633                                                 } else {
634                                                         ListRewrite listRewrite= rewrite.getListRewrite(statement, VariableDeclarationStatement.FRAGMENTS_PROPERTY);
635                                                         listRewrite.remove(fragment, editGroup);
636                                                 }
637
638                                         } else {
639                                                 SimpleName name= ast.newSimpleName(parameterName);
640                                                 rewrite.replace(node, name, editGroup);
641                                                 pg.addPosition(rewrite.track(name), true);
642                                         }
643                                 } else {
644                                         SimpleName name= ast.newSimpleName(parameterName);
645                                         rewrite.replace(node, name, editGroup);
646                                         pg.addPosition(rewrite.track(name), true);
647                                 }
648                         }
649                 });
650         }
651
652         SingleVariableDeclaration createParameterDeclaration(String parameterName, VariableDeclarationFragment fragement, Expression arrayAccess, ForStatement statement, ImportRewrite importRewrite, ASTRewrite rewrite, TextEditGroup group, LinkedProposalPositionGroup pg, boolean makeFinal) {
653                 CompilationUnit compilationUnit= (CompilationUnit)arrayAccess.getRoot();
654                 AST ast= compilationUnit.getAST();
655
656                 SingleVariableDeclaration result= ast.newSingleVariableDeclaration();
657
658                 SimpleName name= ast.newSimpleName(parameterName);
659                 pg.addPosition(rewrite.track(name), true);
660                 result.setName(name);
661
662                 ITypeBinding arrayTypeBinding= arrayAccess.resolveTypeBinding();
663                 Type type= importType(arrayTypeBinding.getElementType(), statement, importRewrite, compilationUnit);
664                 if (arrayTypeBinding.getDimensions() != 1) {
665                         type= ast.newArrayType(type, arrayTypeBinding.getDimensions() - 1);
666                 }
667                 result.setType(type);
668
669                 if (fragement != null) {
670                         VariableDeclarationStatement declaration= (VariableDeclarationStatement)fragement.getParent();
671                         ModifierRewrite.create(rewrite, result).copyAllModifiers(declaration, group);
672                 }
673                 if (makeFinal && (fragement == null || ASTNodes.findModifierNode(Modifier.FINAL, ASTNodes.getModifiers(fragement)) == null)) {
674                         ModifierRewrite.create(rewrite, result).setModifiers(Modifier.FINAL, 0, group);
675                 }
676
677                 return result;
678         }
679
680         private String[] getVariableNameProposals(ITypeBinding arrayTypeBinding, IJavaProject project) {
681                 String[] variableNames= getUsedVariableNames();
682                 String baseName= FOR_LOOP_ELEMENT_IDENTIFIER;
683                 String name= fArrayBinding.getName();
684                 if (name.length() > 2 && name.charAt(name.length() - 1) == 's') {
685                         baseName= name.substring(0, name.length() - 1);
686                 }
687                 String[] elementSuggestions= StubUtility.getLocalNameSuggestions(project, baseName, 0, variableNames);
688
689                 String type= arrayTypeBinding.getElementType().getName();
690                 String[] typeSuggestions= StubUtility.getLocalNameSuggestions(project, type, arrayTypeBinding.getDimensions() - 1, variableNames);
691
692                 String[] result= new String[elementSuggestions.length + typeSuggestions.length];
693                 System.arraycopy(elementSuggestions, 0, result, 0, elementSuggestions.length);
694                 System.arraycopy(typeSuggestions, 0, result, elementSuggestions.length, typeSuggestions.length);
695                 return result;
696         }
697
698 }