]> git.uio.no Git - ifi-stolz-refaktor.git/blame - case-study/jdt-after/core refactoring/org/eclipse/jdt/internal/corext/refactoring/structure/ChangeSignatureProcessor.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / core refactoring / org / eclipse / jdt / internal / corext / refactoring / structure / ChangeSignatureProcessor.java
CommitLineData
1b2798f6
EK
1/*******************************************************************************
2 * Copyright (c) 2000, 2012 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 *******************************************************************************/
11package org.eclipse.jdt.internal.corext.refactoring.structure;
12
13import java.util.ArrayList;
14import java.util.Arrays;
15import java.util.HashMap;
16import java.util.HashSet;
17import java.util.Iterator;
18import java.util.LinkedHashMap;
19import java.util.List;
20import java.util.Map;
21import java.util.Set;
22
23import org.eclipse.swt.events.SelectionAdapter;
24import org.eclipse.swt.events.SelectionEvent;
25
26import org.eclipse.core.runtime.Assert;
27import org.eclipse.core.runtime.CoreException;
28import org.eclipse.core.runtime.IProgressMonitor;
29import org.eclipse.core.runtime.NullProgressMonitor;
30import org.eclipse.core.runtime.OperationCanceledException;
31import org.eclipse.core.runtime.SubProgressMonitor;
32
33import org.eclipse.core.resources.IFile;
34
35import org.eclipse.text.edits.TextEditGroup;
36
37import org.eclipse.ltk.core.refactoring.Change;
38import org.eclipse.ltk.core.refactoring.RefactoringDescriptor;
39import org.eclipse.ltk.core.refactoring.RefactoringStatus;
40import org.eclipse.ltk.core.refactoring.RefactoringStatusContext;
41import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry;
42import org.eclipse.ltk.core.refactoring.TextChange;
43import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext;
44import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant;
45import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor;
46import org.eclipse.ltk.core.refactoring.participants.SharableParticipants;
47
48import org.eclipse.jdt.core.Flags;
49import org.eclipse.jdt.core.ICompilationUnit;
50import org.eclipse.jdt.core.IJavaElement;
51import org.eclipse.jdt.core.IJavaProject;
52import org.eclipse.jdt.core.IMethod;
53import org.eclipse.jdt.core.IType;
54import org.eclipse.jdt.core.ITypeHierarchy;
55import org.eclipse.jdt.core.JavaModelException;
56import org.eclipse.jdt.core.Signature;
57import org.eclipse.jdt.core.compiler.IProblem;
58import org.eclipse.jdt.core.dom.AST;
59import org.eclipse.jdt.core.dom.ASTNode;
60import org.eclipse.jdt.core.dom.ASTParser;
61import org.eclipse.jdt.core.dom.AbstractTypeDeclaration;
62import org.eclipse.jdt.core.dom.Block;
63import org.eclipse.jdt.core.dom.BodyDeclaration;
64import org.eclipse.jdt.core.dom.ClassInstanceCreation;
65import org.eclipse.jdt.core.dom.CompilationUnit;
66import org.eclipse.jdt.core.dom.ConstructorInvocation;
67import org.eclipse.jdt.core.dom.EnumConstantDeclaration;
68import org.eclipse.jdt.core.dom.EnumDeclaration;
69import org.eclipse.jdt.core.dom.Expression;
70import org.eclipse.jdt.core.dom.IMethodBinding;
71import org.eclipse.jdt.core.dom.ITypeBinding;
72import org.eclipse.jdt.core.dom.ImportDeclaration;
73import org.eclipse.jdt.core.dom.Javadoc;
74import org.eclipse.jdt.core.dom.MemberRef;
75import org.eclipse.jdt.core.dom.MethodDeclaration;
76import org.eclipse.jdt.core.dom.MethodInvocation;
77import org.eclipse.jdt.core.dom.MethodRef;
78import org.eclipse.jdt.core.dom.MethodRefParameter;
79import org.eclipse.jdt.core.dom.Modifier;
80import org.eclipse.jdt.core.dom.Name;
81import org.eclipse.jdt.core.dom.NodeFinder;
82import org.eclipse.jdt.core.dom.PrimitiveType;
83import org.eclipse.jdt.core.dom.QualifiedName;
84import org.eclipse.jdt.core.dom.SimpleName;
85import org.eclipse.jdt.core.dom.SingleVariableDeclaration;
86import org.eclipse.jdt.core.dom.SuperConstructorInvocation;
87import org.eclipse.jdt.core.dom.SuperMethodInvocation;
88import org.eclipse.jdt.core.dom.TagElement;
89import org.eclipse.jdt.core.dom.TextElement;
90import org.eclipse.jdt.core.dom.Type;
91import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
92import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
93import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
94import org.eclipse.jdt.core.dom.rewrite.ListRewrite;
95import org.eclipse.jdt.core.refactoring.descriptors.ChangeMethodSignatureDescriptor;
96import org.eclipse.jdt.core.refactoring.descriptors.IntroduceParameterDescriptor;
97import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor;
98import org.eclipse.jdt.core.refactoring.participants.ChangeMethodSignatureArguments;
99import org.eclipse.jdt.core.refactoring.participants.ChangeMethodSignatureArguments.Parameter;
100import org.eclipse.jdt.core.refactoring.participants.ChangeMethodSignatureArguments.ThrownException;
101import org.eclipse.jdt.core.refactoring.participants.IRefactoringProcessorIds;
102import org.eclipse.jdt.core.refactoring.participants.JavaParticipantManager;
103import org.eclipse.jdt.core.search.IJavaSearchScope;
104import org.eclipse.jdt.core.search.MethodReferenceMatch;
105import org.eclipse.jdt.core.search.SearchMatch;
106import org.eclipse.jdt.core.search.SearchPattern;
107
108import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory;
109import org.eclipse.jdt.internal.corext.Corext;
110import org.eclipse.jdt.internal.corext.SourceRangeFactory;
111import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
112import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility;
113import org.eclipse.jdt.internal.corext.dom.ASTNodes;
114import org.eclipse.jdt.internal.corext.dom.Bindings;
115import org.eclipse.jdt.internal.corext.dom.ModifierRewrite;
116import org.eclipse.jdt.internal.corext.dom.Selection;
117import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer;
118import org.eclipse.jdt.internal.corext.refactoring.Checks;
119import org.eclipse.jdt.internal.corext.refactoring.CuCollectingSearchRequestor;
120import org.eclipse.jdt.internal.corext.refactoring.ExceptionInfo;
121import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment;
122import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments;
123import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil;
124import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo;
125import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester;
126import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages;
127import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory;
128import org.eclipse.jdt.internal.corext.refactoring.ReturnTypeInfo;
129import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
130import org.eclipse.jdt.internal.corext.refactoring.StubTypeContext;
131import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker;
132import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext;
133import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext;
134import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes;
135import org.eclipse.jdt.internal.corext.refactoring.base.ReferencesInBinaryContext;
136import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange;
137import org.eclipse.jdt.internal.corext.refactoring.code.IntroduceParameterRefactoring;
138import org.eclipse.jdt.internal.corext.refactoring.code.Invocations;
139import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator;
140import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors;
141import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks;
142import org.eclipse.jdt.internal.corext.refactoring.rename.RefactoringAnalyzeUtil;
143import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2;
144import org.eclipse.jdt.internal.corext.refactoring.rename.TempOccurrenceAnalyzer;
145import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating;
146import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil;
147import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil;
148import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser;
149import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil;
150import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager;
151import org.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer;
152import org.eclipse.jdt.internal.corext.util.JdtFlags;
153import org.eclipse.jdt.internal.corext.util.Messages;
154
155import org.eclipse.jdt.ui.JavaElementLabels;
156
157import org.eclipse.jdt.internal.ui.JavaPlugin;
158import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider;
159import org.eclipse.jdt.internal.ui.refactoring.ChangeSignatureWizard.ChangeSignatureInputPage;
160import org.eclipse.jdt.internal.ui.refactoring.DelegateUIHelper;
161import org.eclipse.jdt.internal.ui.refactoring.IntroduceParameterObjectWizard.IntroduceParameterObjectInputPage;
162import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
163
164
165public class ChangeSignatureProcessor extends RefactoringProcessor implements IDelegateUpdating {
166
167 public static final String ATTRIBUTE_RETURN= "return"; //$NON-NLS-1$
168 public static final String ATTRIBUTE_VISIBILITY= "visibility"; //$NON-NLS-1$
169 public static final String ATTRIBUTE_PARAMETER= "parameter"; //$NON-NLS-1$
170 public static final String ATTRIBUTE_DEFAULT= "default"; //$NON-NLS-1$
171 public static final String ATTRIBUTE_KIND= "kind"; //$NON-NLS-1$
172 public static final String ATTRIBUTE_DELEGATE= "delegate"; //$NON-NLS-1$
173 public static final String ATTRIBUTE_DEPRECATE= "deprecate"; //$NON-NLS-1$
174
175 public List<ParameterInfo> fParameterInfos;
176
177 CompilationUnitRewrite fBaseCuRewrite;
178 public List<ExceptionInfo> fExceptionInfos;
179 private TextChangeManager fChangeManager;
180
181 public IMethod fMethod;
182 private IMethod fTopMethod;
183 public IMethod[] fRippleMethods;
184 private SearchResultGroup[] fOccurrences;
185 public ReturnTypeInfo fReturnTypeInfo;
186 public String fMethodName;
187 public int fVisibility;
188 private static final String CONST_CLASS_DECL = "class A{";//$NON-NLS-1$
189 private static final String CONST_ASSIGN = " i="; //$NON-NLS-1$
190 private static final String CONST_CLOSE = ";}"; //$NON-NLS-1$
191
192 private StubTypeContext fContextCuStartEnd;
193 private int fOldVarargIndex; // initialized in checkVarargs()
194
195 private BodyUpdater fBodyUpdater;
196 public IDefaultValueAdvisor fDefaultValueAdvisor;
197
198 private ITypeHierarchy fCachedTypeHierarchy= null;
199 public boolean fDelegateUpdating;
200 public boolean fDelegateDeprecation;
201
202 public ChangeSignatureProcessor(JavaRefactoringArguments arguments, RefactoringStatus status) throws JavaModelException {
203 this((IMethod) null);
204 status.merge(initialize(arguments));
205 }
206
207 /**
208 * Creates a new change signature refactoring.
209 * @param method the method, or <code>null</code> if invoked by scripting framework
210 * @throws JavaModelException if something's wrong with the given method
211 */
212 public ChangeSignatureProcessor(IMethod method) throws JavaModelException {
213 fMethod= method;
214 fOldVarargIndex= -1;
215 fDelegateUpdating= false;
216 fDelegateDeprecation= true;
217 if (fMethod != null) {
218 fParameterInfos= createParameterInfoList(method);
219 // fExceptionInfos is created in checkInitialConditions
220 fReturnTypeInfo= new ReturnTypeInfo(Signature.toString(Signature.getReturnType(fMethod.getSignature())));
221 fMethodName= fMethod.getElementName();
222 fVisibility= JdtFlags.getVisibilityCode(fMethod);
223 }
224 }
225
226 private static List<ParameterInfo> createParameterInfoList(IMethod method) {
227 try {
228 String[] typeNames= method.getParameterTypes();
229 String[] oldNames= method.getParameterNames();
230 List<ParameterInfo> result= new ArrayList<ParameterInfo>(typeNames.length);
231 for (int i= 0; i < oldNames.length; i++){
232 ParameterInfo parameterInfo;
233 if (i == oldNames.length - 1 && Flags.isVarargs(method.getFlags())) {
234 String varargSignature= typeNames[i];
235 int arrayCount= Signature.getArrayCount(varargSignature);
236 String baseSignature= Signature.getElementType(varargSignature);
237 if (arrayCount > 1)
238 baseSignature= Signature.createArraySignature(baseSignature, arrayCount - 1);
239 parameterInfo= new ParameterInfo(Signature.toString(baseSignature) + ParameterInfo.ELLIPSIS, oldNames[i], i);
240 } else {
241 parameterInfo= new ParameterInfo(Signature.toString(typeNames[i]), oldNames[i], i);
242 }
243 result.add(parameterInfo);
244 }
245 return result;
246 } catch(JavaModelException e) {
247 JavaPlugin.log(e);
248 return new ArrayList<ParameterInfo>(0);
249 }
250 }
251
252 /* (non-Javadoc)
253 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#getProcessorName()
254 */
255 @Override
256 public String getProcessorName() {
257 return RefactoringCoreMessages.ChangeSignatureRefactoring_modify_Parameters;
258 }
259
260 public IMethod getMethod() {
261 return fMethod;
262 }
263
264 public String getMethodName() {
265 return fMethodName;
266 }
267
268 public String getReturnTypeString() {
269 return fReturnTypeInfo.getNewTypeName();
270 }
271
272 public void setNewMethodName(String newMethodName){
273 Assert.isNotNull(newMethodName);
274 fMethodName= newMethodName;
275 }
276
277 public void setNewReturnTypeName(String newReturnTypeName){
278 Assert.isNotNull(newReturnTypeName);
279 fReturnTypeInfo.setNewTypeName(newReturnTypeName);
280 }
281
282 public boolean canChangeNameAndReturnType(){
283 try {
284 return ! fMethod.isConstructor();
285 } catch (JavaModelException e) {
286 JavaPlugin.log(e);
287 return false;
288 }
289 }
290
291 /**
292 * @return visibility
293 * @see org.eclipse.jdt.core.dom.Modifier
294 */
295 public int getVisibility(){
296 return fVisibility;
297 }
298
299 /**
300 * @param visibility new visibility
301 * @see org.eclipse.jdt.core.dom.Modifier
302 */
303 public void setVisibility(int visibility){
304 Assert.isTrue( visibility == Modifier.PUBLIC ||
305 visibility == Modifier.PROTECTED ||
306 visibility == Modifier.NONE ||
307 visibility == Modifier.PRIVATE);
308 fVisibility= visibility;
309 }
310
311 /*
312 * @see JdtFlags
313 */
314 public int[] getAvailableVisibilities() throws JavaModelException{
315 if (fTopMethod.getDeclaringType().isInterface())
316 return new int[]{Modifier.PUBLIC};
317 else if (fTopMethod.getDeclaringType().isEnum() && fTopMethod.isConstructor())
318 return new int[]{ Modifier.NONE,
319 Modifier.PRIVATE};
320 else
321 return new int[]{ Modifier.PUBLIC,
322 Modifier.PROTECTED,
323 Modifier.NONE,
324 Modifier.PRIVATE};
325 }
326
327 /**
328 *
329 * @return List of <code>ParameterInfo</code> objects.
330 */
331 public List<ParameterInfo> getParameterInfos(){
332 return fParameterInfos;
333 }
334
335 /**
336 * @return List of <code>ExceptionInfo</code> objects.
337 */
338 public List<ExceptionInfo> getExceptionInfos(){
339 return fExceptionInfos;
340 }
341
342 public void setBodyUpdater(BodyUpdater bodyUpdater) {
343 fBodyUpdater= bodyUpdater;
344 }
345
346 public CompilationUnitRewrite getBaseCuRewrite() {
347 return fBaseCuRewrite;
348 }
349
350 //------------------- IDelegateUpdating ----------------------
351
352 public boolean canEnableDelegateUpdating() {
353 return true;
354 }
355
356 public boolean getDelegateUpdating() {
357 return fDelegateUpdating;
358 }
359
360 public void setDelegateUpdating(boolean updating) {
361 fDelegateUpdating= updating;
362 }
363
364 public void setDeprecateDelegates(boolean deprecate) {
365 fDelegateDeprecation= deprecate;
366 }
367
368 public boolean getDeprecateDelegates() {
369 return fDelegateDeprecation;
370 }
371
372 public String getDelegateUpdatingTitle(boolean plural) {
373 if (plural)
374 return RefactoringCoreMessages.DelegateCreator_keep_original_changed_plural;
375 else
376 return RefactoringCoreMessages.DelegateCreator_keep_original_changed_singular;
377 }
378
379 //------------------- /IDelegateUpdating ---------------------
380
381 public RefactoringStatus checkSignature() {
382 return checkSignature(false);
383 }
384
385 private RefactoringStatus checkSignature(boolean resolveBindings) {
386 RefactoringStatus result= new RefactoringStatus();
387 checkMethodName(result);
388 if (result.hasFatalError())
389 return result;
390
391 checkParameterNamesAndValues(result);
392 if (result.hasFatalError())
393 return result;
394
395 checkForDuplicateParameterNames(result);
396 if (result.hasFatalError())
397 return result;
398
399 return fReturnTypeInfo.generated_4290602752965600854(this, resolveBindings, result);
400 }
401
402 public boolean isSignatureSameAsInitial() throws JavaModelException {
403 if (! isVisibilitySameAsInitial())
404 return false;
405 if (! isMethodNameSameAsInitial())
406 return false;
407 if (! isReturnTypeSameAsInitial())
408 return false;
409 if (! areExceptionsSameAsInitial())
410 return false;
411
412 if (fMethod.getNumberOfParameters() == 0 && fParameterInfos.isEmpty())
413 return true;
414
415 if (areNamesSameAsInitial() && isOrderSameAsInitial() && areParameterTypesSameAsInitial())
416 return true;
417
418 return false;
419 }
420
421 /**
422 * @return true if the new method cannot coexist with the old method since
423 * the signatures are too much alike
424 */
425 public boolean isSignatureClashWithInitial() {
426
427 if (!isMethodNameSameAsInitial())
428 return false; // name has changed.
429
430 if (fMethod.getNumberOfParameters() == 0 && fParameterInfos.isEmpty())
431 return true; // name is equal and both parameter lists are empty
432
433 // name is equal and there are some parameters.
434 // check if there are more or less parameters than before
435
436 int no= getNotDeletedInfos().size();
437
438 if (fMethod.getNumberOfParameters() != no)
439 return false;
440
441 // name is equal and parameter count is equal.
442 // check whether types remained the same
443
444 if (isOrderSameAsInitial())
445 return areParameterTypesSameAsInitial();
446 else
447 return false; // could be more specific here
448 }
449
450 private boolean areParameterTypesSameAsInitial() {
451 for (Iterator<ParameterInfo> iter= fParameterInfos.iterator(); iter.hasNext();) {
452 ParameterInfo info= iter.next();
453 if (! info.isAdded() && ! info.isDeleted() && info.isTypeNameChanged())
454 return false;
455 }
456 return true;
457 }
458
459 private boolean isReturnTypeSameAsInitial() {
460 return ! fReturnTypeInfo.isTypeNameChanged();
461 }
462
463 private boolean isMethodNameSameAsInitial() {
464 return fMethodName.equals(fMethod.getElementName());
465 }
466
467 private boolean areExceptionsSameAsInitial() {
468 for (Iterator<ExceptionInfo> iter= fExceptionInfos.iterator(); iter.hasNext();) {
469 ExceptionInfo info= iter.next();
470 if (! info.isOld())
471 return false;
472 }
473 return true;
474 }
475
476 private void checkParameterNamesAndValues(RefactoringStatus result) {
477 int i= 1;
478 for (Iterator<ParameterInfo> iter= fParameterInfos.iterator(); iter.hasNext(); i++) {
479 ParameterInfo info= iter.next();
480 if (info.isDeleted())
481 continue;
482 checkParameterName(result, info, i);
483 if (result.hasFatalError())
484 return;
485 if (info.isAdded()) {
486 checkParameterDefaultValue(result, info);
487 if (result.hasFatalError())
488 return;
489 }
490 }
491 }
492
493 private void checkParameterName(RefactoringStatus result, ParameterInfo info, int position) {
494 info.generated_1031965852893150868(result, this, position);
495 }
496
497 private void checkMethodName(RefactoringStatus result) {
498 if (isMethodNameSameAsInitial() || ! canChangeNameAndReturnType())
499 return;
500 if ("".equals(fMethodName.trim())) { //$NON-NLS-1$
501 String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_method_name_not_empty;
502 result.addFatalError(msg);
503 return;
504 }
505 if (fMethodName.equals(fMethod.getDeclaringType().getElementName())) {
506 String msg= RefactoringCoreMessages.ChangeSignatureRefactoring_constructor_name;
507 result.addWarning(msg);
508 }
509 result.merge(Checks.checkMethodName(fMethodName, fMethod));
510 }
511
512 private void checkParameterDefaultValue(RefactoringStatus result, ParameterInfo info) {
513 info.generated_3376835700802108579(result, this);
514 }
515
516 public RefactoringStatus checkVarargs() throws JavaModelException {
517 RefactoringStatus result= checkOriginalVarargs();
518 if (result != null)
519 return result;
520
521 if (fRippleMethods != null) {
522 for (int iRipple= 0; iRipple < fRippleMethods.length; iRipple++) {
523 IMethod rippleMethod= fRippleMethods[iRipple];
524 if (! JdtFlags.isVarargs(rippleMethod))
525 continue;
526
527 // Vararg method can override method that takes an array as last argument
528 fOldVarargIndex= rippleMethod.getNumberOfParameters() - 1;
529 List<ParameterInfo> notDeletedInfos= getNotDeletedInfos();
530 for (int i= 0; i < notDeletedInfos.size(); i++) {
531 ParameterInfo info= notDeletedInfos.get(i);
532 if (fOldVarargIndex != -1 && info.getOldIndex() == fOldVarargIndex && ! info.isNewVarargs()) {
533 String rippleMethodType= rippleMethod.getDeclaringType().getFullyQualifiedName('.');
534 String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_ripple_cannot_convert_vararg, new Object[] { BasicElementLabels.getJavaElementName(info.getNewName()), BasicElementLabels.getJavaElementName(rippleMethodType)});
535 return RefactoringStatus.createFatalErrorStatus(message, JavaStatusContext.create(rippleMethod));
536 }
537 }
538 }
539 }
540
541 return null;
542 }
543
544 private RefactoringStatus checkOriginalVarargs() throws JavaModelException {
545 if (JdtFlags.isVarargs(fMethod))
546 fOldVarargIndex= fMethod.getNumberOfParameters() - 1;
547 List<ParameterInfo> notDeletedInfos= getNotDeletedInfos();
548 for (int i= 0; i < notDeletedInfos.size(); i++) {
549 ParameterInfo info= notDeletedInfos.get(i);
550 if (info.isOldVarargs() && ! info.isNewVarargs())
551 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_cannot_convert_vararg, BasicElementLabels.getJavaElementName(info.getNewName())));
552 if (i != notDeletedInfos.size() - 1) {
553 // not the last parameter
554 if (info.isNewVarargs())
555 return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_vararg_must_be_last, BasicElementLabels.getJavaElementName(info.getNewName())));
556 }
557 }
558 return null;
559 }
560
561 private RefactoringStatus checkTypeVariables() {
562 if (fRippleMethods.length == 1)
563 return null;
564
565 RefactoringStatus result= new RefactoringStatus();
566 if (fReturnTypeInfo.isTypeNameChanged() && fReturnTypeInfo.getNewTypeBinding() != null) {
567 HashSet<ITypeBinding> typeVariablesCollector= new HashSet<ITypeBinding>();
568 collectTypeVariables(fReturnTypeInfo.getNewTypeBinding(), typeVariablesCollector);
569 if (typeVariablesCollector.size() != 0) {
570 ITypeBinding first= typeVariablesCollector.iterator().next();
571 String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_return_type_contains_type_variable, new String[] {BasicElementLabels.getJavaElementName(fReturnTypeInfo.getNewTypeName()), BasicElementLabels.getJavaElementName(first.getName())});
572 result.addError(msg);
573 }
574 }
575
576 for (Iterator<ParameterInfo> iter= getNotDeletedInfos().iterator(); iter.hasNext();) {
577 ParameterInfo info= iter.next();
578 info.generated_5431281952837806884(result, this);
579 }
580 return result;
581 }
582
583 public void collectTypeVariables(ITypeBinding typeBinding, Set<ITypeBinding> typeVariablesCollector) {
584 if (typeBinding.isTypeVariable()) {
585 typeVariablesCollector.add(typeBinding);
586 ITypeBinding[] typeBounds= typeBinding.getTypeBounds();
587 for (int i= 0; i < typeBounds.length; i++)
588 collectTypeVariables(typeBounds[i], typeVariablesCollector);
589
590 } else if (typeBinding.isArray()) {
591 collectTypeVariables(typeBinding.getElementType(), typeVariablesCollector);
592
593 } else if (typeBinding.isParameterizedType()) {
594 ITypeBinding[] typeArguments= typeBinding.getTypeArguments();
595 for (int i= 0; i < typeArguments.length; i++)
596 collectTypeVariables(typeArguments[i], typeVariablesCollector);
597
598 } else if (typeBinding.isWildcardType()) {
599 ITypeBinding bound= typeBinding.getBound();
600 if (bound != null) {
601 collectTypeVariables(bound, typeVariablesCollector);
602 }
603 }
604 }
605
606 public static boolean isValidExpression(String string){
607 String trimmed= string.trim();
608 if ("".equals(trimmed)) //speed up for a common case //$NON-NLS-1$
609 return false;
610 StringBuffer cuBuff= new StringBuffer();
611 cuBuff.append(CONST_CLASS_DECL)
612 .append("Object") //$NON-NLS-1$
613 .append(CONST_ASSIGN);
614 int offset= cuBuff.length();
615 cuBuff.append(trimmed)
616 .append(CONST_CLOSE);
617 ASTParser p= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL);
618 p.setSource(cuBuff.toString().toCharArray());
619 CompilationUnit cu= (CompilationUnit) p.createAST(null);
620 Selection selection= Selection.createFromStartLength(offset, trimmed.length());
621 SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false);
622 cu.accept(analyzer);
623 ASTNode selected= analyzer.getFirstSelectedNode();
624 return (selected instanceof Expression) &&
625 trimmed.equals(cuBuff.substring(cu.getExtendedStartPosition(selected), cu.getExtendedStartPosition(selected) + cu.getExtendedLength(selected)));
626 }
627
628 public static boolean isValidVarargsExpression(String string) {
629 String trimmed= string.trim();
630 if ("".equals(trimmed)) //speed up for a common case //$NON-NLS-1$
631 return true;
632 StringBuffer cuBuff= new StringBuffer();
633 cuBuff.append("class A{ {m("); //$NON-NLS-1$
634 int offset= cuBuff.length();
635 cuBuff.append(trimmed)
636 .append(");}}"); //$NON-NLS-1$
637 ASTParser p= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL);
638 p.setSource(cuBuff.toString().toCharArray());
639 CompilationUnit cu= (CompilationUnit) p.createAST(null);
640 Selection selection= Selection.createFromStartLength(offset, trimmed.length());
641 SelectionAnalyzer analyzer= new SelectionAnalyzer(selection, false);
642 cu.accept(analyzer);
643 ASTNode[] selectedNodes= analyzer.getSelectedNodes();
644 if (selectedNodes.length == 0)
645 return false;
646 for (int i= 0; i < selectedNodes.length; i++) {
647 if (! (selectedNodes[i] instanceof Expression))
648 return false;
649 }
650 return true;
651 }
652
653 public StubTypeContext getStubTypeContext() {
654 try {
655 if (fContextCuStartEnd == null)
656 fContextCuStartEnd= TypeContextChecker.createStubTypeContext(getCu(), fBaseCuRewrite.getRoot(), fMethod.getSourceRange().getOffset());
657 } catch (CoreException e) {
658 //cannot do anything here
659 throw new RuntimeException(e);
660 }
661 return fContextCuStartEnd;
662 }
663
664 private ITypeHierarchy getCachedTypeHierarchy(IProgressMonitor monitor) throws JavaModelException {
665 if (fCachedTypeHierarchy == null)
666 fCachedTypeHierarchy= fMethod.getDeclaringType().newTypeHierarchy(new SubProgressMonitor(monitor, 1));
667 return fCachedTypeHierarchy;
668 }
669
670 /* (non-Javadoc)
671 * @see org.eclipse.ltk.core.refactoring.Refactoring#checkInitialConditions(org.eclipse.core.runtime.IProgressMonitor)
672 */
673 @Override
674 public RefactoringStatus checkInitialConditions(IProgressMonitor monitor) throws CoreException {
675 try {
676 monitor.beginTask("", 5); //$NON-NLS-1$
677 RefactoringStatus result= Checks.checkIfCuBroken(fMethod);
678 if (result.hasFatalError())
679 return result;
680 if (fMethod == null || !fMethod.exists()) {
681 String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_method_deleted, BasicElementLabels.getFileName(getCu()));
682 return RefactoringStatus.createFatalErrorStatus(message);
683 }
684 if (fMethod.getDeclaringType().isInterface()) {
685 fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, fMethod.getDeclaringType().newSupertypeHierarchy(new SubProgressMonitor(monitor, 1)));
686 monitor.worked(1);
687 } else if (MethodChecks.isVirtual(fMethod)) {
688 ITypeHierarchy hierarchy= getCachedTypeHierarchy(new SubProgressMonitor(monitor, 1));
689 fTopMethod= MethodChecks.isDeclaredInInterface(fMethod, hierarchy, new SubProgressMonitor(monitor, 1));
690 if (fTopMethod == null)
691 fTopMethod= MethodChecks.overridesAnotherMethod(fMethod, hierarchy);
692 }
693 if (fTopMethod == null)
694 fTopMethod= fMethod;
695 if (! fTopMethod.equals(fMethod)) {
696 if (fTopMethod.getDeclaringType().isInterface()) {
697 RefactoringStatusContext context= JavaStatusContext.create(fTopMethod);
698 String message= Messages.format(RefactoringCoreMessages.MethodChecks_implements,
699 new String[]{JavaElementUtil.createMethodSignature(fTopMethod), BasicElementLabels.getJavaElementName(fTopMethod.getDeclaringType().getFullyQualifiedName('.'))});
700 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.METHOD_DECLARED_IN_INTERFACE, fTopMethod);
701 } else {
702 RefactoringStatusContext context= JavaStatusContext.create(fTopMethod);
703 String message= Messages.format(RefactoringCoreMessages.MethodChecks_overrides,
704 new String[]{JavaElementUtil.createMethodSignature(fTopMethod), BasicElementLabels.getJavaElementName(fTopMethod.getDeclaringType().getFullyQualifiedName('.'))});
705 return RefactoringStatus.createStatus(RefactoringStatus.FATAL, message, context, Corext.getPluginId(), RefactoringStatusCodes.OVERRIDES_ANOTHER_METHOD, fTopMethod);
706 }
707 }
708
709 if (monitor.isCanceled())
710 throw new OperationCanceledException();
711
712 if (fBaseCuRewrite == null || !fBaseCuRewrite.getCu().equals(getCu())) {
713 fBaseCuRewrite= new CompilationUnitRewrite(getCu());
714 fBaseCuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
715 }
716 RefactoringStatus[] status= TypeContextChecker.checkMethodTypesSyntax(fMethod, getParameterInfos(), fReturnTypeInfo);
717 for (int i= 0; i < status.length; i++) {
718 result.merge(status[i]);
719 }
720 monitor.worked(1);
721 result.merge(createExceptionInfoList());
722 monitor.worked(1);
723 return result;
724 } finally {
725 monitor.done();
726 }
727 }
728
729 private RefactoringStatus createExceptionInfoList() {
730 if (fExceptionInfos == null || fExceptionInfos.isEmpty()) {
731 fExceptionInfos= new ArrayList<ExceptionInfo>(0);
732 try {
733 ASTNode nameNode= NodeFinder.perform(fBaseCuRewrite.getRoot(), fMethod.getNameRange());
734 if (nameNode == null || !(nameNode instanceof Name) || !(nameNode.getParent() instanceof MethodDeclaration))
735 return null;
736 MethodDeclaration methodDeclaration= (MethodDeclaration) nameNode.getParent();
737 List<Name> exceptions= methodDeclaration.thrownExceptions();
738 List<ExceptionInfo> result= new ArrayList<ExceptionInfo>(exceptions.size());
739 for (int i= 0; i < exceptions.size(); i++) {
740 Name name= exceptions.get(i);
741 ITypeBinding typeBinding= name.resolveTypeBinding();
742 if (typeBinding == null)
743 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_no_exception_binding);
744 IJavaElement element= typeBinding.getJavaElement();
745 result.add(ExceptionInfo.createInfoForOldException(element, typeBinding));
746 }
747 fExceptionInfos= result;
748 } catch (JavaModelException e) {
749 JavaPlugin.log(e);
750 }
751 }
752 return null;
753 }
754
755 /* (non-Javadoc)
756 * @see org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor#checkFinalConditions(org.eclipse.core.runtime.IProgressMonitor, org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext)
757 */
758 @Override
759 public RefactoringStatus checkFinalConditions(IProgressMonitor pm, CheckConditionsContext context) throws CoreException, OperationCanceledException {
760 try {
761 pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 8);
762 RefactoringStatus result= new RefactoringStatus();
763 clearManagers();
764 fBaseCuRewrite.generated_8282258358391446550();
765
766 if (isSignatureSameAsInitial())
767 return RefactoringStatus.createFatalErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_unchanged);
768 result.merge(checkSignature(true));
769 if (result.hasFatalError())
770 return result;
771
772 if (fDelegateUpdating && isSignatureClashWithInitial())
773 result.merge(RefactoringStatus.createErrorStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_old_and_new_signatures_not_sufficiently_different ));
774
775 String binaryRefsDescription= Messages.format(RefactoringCoreMessages.ReferencesInBinaryContext_ref_in_binaries_description , BasicElementLabels.getJavaElementName(getMethodName()));
776 ReferencesInBinaryContext binaryRefs= new ReferencesInBinaryContext(binaryRefsDescription);
777
778 fRippleMethods= RippleMethodFinder2.getRelatedMethods(fMethod, binaryRefs, new SubProgressMonitor(pm, 1), null);
779 result.merge(checkVarargs());
780 if (result.hasFatalError())
781 return result;
782
783 fOccurrences= findOccurrences(new SubProgressMonitor(pm, 1), binaryRefs, result);
784 binaryRefs.addErrorIfNecessary(result);
785
786 result.merge(checkVisibilityChanges());
787 result.merge(checkTypeVariables());
788
789 //TODO:
790 // We need a common way of dealing with possible compilation errors for all occurrences,
791 // including visibility problems, shadowing and missing throws declarations.
792
793 if (! isOrderSameAsInitial())
794 result.merge(checkReorderings(new SubProgressMonitor(pm, 1)));
795 else
796 pm.worked(1);
797
798 //TODO (bug 58616): check whether changed signature already exists somewhere in the ripple,
799 // - error if exists
800 // - warn if exists with different parameter types (may cause overloading)
801
802 if (! areNamesSameAsInitial())
803 result.merge(checkRenamings(new SubProgressMonitor(pm, 1)));
804 else
805 pm.worked(1);
806 if (result.hasFatalError())
807 return result;
808
809// resolveTypesWithoutBindings(new SubProgressMonitor(pm, 1)); // already done in checkSignature(true)
810
811 createChangeManager(new SubProgressMonitor(pm, 1), result);
812 fCachedTypeHierarchy= null;
813
814 if (mustAnalyzeAstOfDeclaringCu())
815 result.merge(checkCompilationofDeclaringCu()); //TODO: should also check in ripple methods (move into createChangeManager)
816 if (result.hasFatalError())
817 return result;
818
819 Checks.addModifiedFilesToChecker(getAllFilesToModify(), context);
820 return result;
821 } finally {
822 pm.done();
823 }
824 }
825
826 protected void clearManagers() {
827 fChangeManager= null;
828 }
829
830 private RefactoringStatus checkVisibilityChanges() throws JavaModelException {
831 if (isVisibilitySameAsInitial())
832 return null;
833 if (fRippleMethods.length == 1)
834 return null;
835 Assert.isTrue(JdtFlags.getVisibilityCode(fMethod) != Modifier.PRIVATE);
836 if (fVisibility == Modifier.PRIVATE)
837 return RefactoringStatus.createWarningStatus(RefactoringCoreMessages.ChangeSignatureRefactoring_non_virtual);
838 return null;
839 }
840
841 public String getOldMethodSignature() throws JavaModelException{
842 StringBuffer buff= new StringBuffer();
843
844 int flags= getMethod().getFlags();
845 buff.append(getVisibilityString(flags));
846 if (Flags.isStatic(flags))
847 buff.append("static "); //$NON-NLS-1$
848 if (! getMethod().isConstructor())
849 buff.append(fReturnTypeInfo.getOldTypeName())
850 .append(' ');
851
852 buff.append(JavaElementLabels.getElementLabel(fMethod.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED));
853 buff.append('.');
854 buff.append(fMethod.getElementName())
855 .append(Signature.C_PARAM_START)
856 .append(getOldMethodParameters())
857 .append(Signature.C_PARAM_END);
858
859 buff.append(getOldMethodThrows());
860
861 return BasicElementLabels.getJavaCodeString(buff.toString());
862 }
863
864 public String getNewMethodSignature() throws JavaModelException{
865 StringBuffer buff= new StringBuffer();
866
867 buff.append(getVisibilityString(fVisibility));
868 if (Flags.isStatic(getMethod().getFlags()))
869 buff.append("static "); //$NON-NLS-1$
870 if (! getMethod().isConstructor())
871 buff.append(getReturnTypeString())
872 .append(' ');
873
874 buff.append(getMethodName())
875 .append(Signature.C_PARAM_START)
876 .append(getMethodParameters())
877 .append(Signature.C_PARAM_END);
878
879 buff.append(getMethodThrows());
880
881 return BasicElementLabels.getJavaCodeString(buff.toString());
882 }
883
884 private String getVisibilityString(int visibility) {
885 String visibilityString= JdtFlags.getVisibilityString(visibility);
886 if ("".equals(visibilityString)) //$NON-NLS-1$
887 return visibilityString;
888 return visibilityString + ' ';
889 }
890
891 private String getMethodThrows() {
892 final String throwsString= " throws "; //$NON-NLS-1$
893 StringBuffer buff= new StringBuffer(throwsString);
894 for (Iterator<ExceptionInfo> iter= fExceptionInfos.iterator(); iter.hasNext(); ) {
895 ExceptionInfo info= iter.next();
896 info.generated_2013278585315255092(buff);
897 }
898 if (buff.length() == throwsString.length())
899 return ""; //$NON-NLS-1$
900 buff.delete(buff.length() - 2, buff.length());
901 return buff.toString();
902 }
903
904 private String getOldMethodThrows() {
905 final String throwsString= " throws "; //$NON-NLS-1$
906 StringBuffer buff= new StringBuffer(throwsString);
907 for (Iterator<ExceptionInfo> iter= fExceptionInfos.iterator(); iter.hasNext(); ) {
908 ExceptionInfo info= iter.next();
909 info.generated_7135583258020944911(buff);
910 }
911 if (buff.length() == throwsString.length())
912 return ""; //$NON-NLS-1$
913 buff.delete(buff.length() - 2, buff.length());
914 return buff.toString();
915 }
916
917 private void checkForDuplicateParameterNames(RefactoringStatus result){
918 Set<String> found= new HashSet<String>();
919 Set<String> doubled= new HashSet<String>();
920 for (Iterator<ParameterInfo> iter = getNotDeletedInfos().iterator(); iter.hasNext();) {
921 ParameterInfo info= iter.next();
922 String newName= info.getNewName();
923 if (found.contains(newName) && !doubled.contains(newName)){
924 result.addFatalError(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_duplicate_name, BasicElementLabels.getJavaElementName(newName)));
925 doubled.add(newName);
926 } else {
927 found.add(newName);
928 }
929 }
930 }
931
932 private ICompilationUnit getCu() {
933 return fMethod.getCompilationUnit();
934 }
935
936 private boolean mustAnalyzeAstOfDeclaringCu() throws JavaModelException{
937 if (JdtFlags.isAbstract(getMethod()))
938 return false;
939 else if (JdtFlags.isNative(getMethod()))
940 return false;
941 else if (getMethod().getDeclaringType().isInterface())
942 return false;
943 else
944 return true;
945 }
946
947 private RefactoringStatus checkCompilationofDeclaringCu() throws CoreException {
948 ICompilationUnit cu= getCu();
949 TextChange change= fChangeManager.get(cu);
950 String newCuSource= change.getPreviewContent(new NullProgressMonitor());
951 CompilationUnit newCUNode= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(newCuSource, cu, true, false, null);
952 IProblem[] problems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, fBaseCuRewrite.getRoot());
953 RefactoringStatus result= new RefactoringStatus();
954 for (int i= 0; i < problems.length; i++) {
955 IProblem problem= problems[i];
956 if (shouldReport(problem, newCUNode))
957 result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource, SourceRangeFactory.create(problem))));
958 }
959 return result;
960 }
961
962 /**
963 * Evaluates if a problem needs to be reported.
964 * @param problem the problem
965 * @param cu the AST containing the new source
966 * @return return <code>true</code> if the problem needs to be reported
967 */
968 protected boolean shouldReport(IProblem problem, CompilationUnit cu) {
969 if (! problem.isError())
970 return false;
971 if (problem.getID() == IProblem.UndefinedType) //reported when trying to import
972 return false;
973 return true;
974 }
975
976 private String getOldMethodParameters() {
977 StringBuffer buff= new StringBuffer();
978 int i= 0;
979 for (Iterator<ParameterInfo> iter= getNotAddedInfos().iterator(); iter.hasNext(); i++) {
980 ParameterInfo info= iter.next();
981 if (i != 0 )
982 buff.append(", "); //$NON-NLS-1$
983 buff.append(createDeclarationString(info));
984 }
985 return buff.toString();
986 }
987
988 private String getMethodParameters() {
989 StringBuffer buff= new StringBuffer();
990 int i= 0;
991 for (Iterator<ParameterInfo> iter= getNotDeletedInfos().iterator(); iter.hasNext(); i++) {
992 ParameterInfo info= iter.next();
993 if (i != 0 )
994 buff.append(", "); //$NON-NLS-1$
995 buff.append(createDeclarationString(info));
996 }
997 return buff.toString();
998 }
999
1000 private List<ParameterInfo> getAddedInfos(){
1001 List<ParameterInfo> result= new ArrayList<ParameterInfo>(1);
1002 for (Iterator<ParameterInfo> iter= fParameterInfos.iterator(); iter.hasNext();) {
1003 ParameterInfo info= iter.next();
1004 info.generated_2735091511995382303(result);
1005 }
1006 return result;
1007 }
1008
1009 private List<ParameterInfo> getDeletedInfos(){
1010 List<ParameterInfo> result= new ArrayList<ParameterInfo>(1);
1011 for (Iterator<ParameterInfo> iter= fParameterInfos.iterator(); iter.hasNext();) {
1012 ParameterInfo info= iter.next();
1013 info.generated_7666982753681897163(result);
1014 }
1015 return result;
1016 }
1017
1018 private List<ParameterInfo> getNotAddedInfos(){
1019 List<ParameterInfo> all= new ArrayList<ParameterInfo>(fParameterInfos);
1020 all.removeAll(getAddedInfos());
1021 return all;
1022 }
1023
1024 public List<ParameterInfo> getNotDeletedInfos(){
1025 List<ParameterInfo> all= new ArrayList<ParameterInfo>(fParameterInfos);
1026 all.removeAll(getDeletedInfos());
1027 return all;
1028 }
1029
1030 private boolean areNamesSameAsInitial() {
1031 for (Iterator<ParameterInfo> iter= fParameterInfos.iterator(); iter.hasNext();) {
1032 ParameterInfo info= iter.next();
1033 if (info.isRenamed())
1034 return false;
1035 }
1036 return true;
1037 }
1038
1039 private boolean isOrderSameAsInitial(){
1040 int i= 0;
1041 for (Iterator<ParameterInfo> iter= fParameterInfos.iterator(); iter.hasNext(); i++) {
1042 ParameterInfo info= iter.next();
1043 if (info.getOldIndex() != i) // includes info.isAdded()
1044 return false;
1045 if (info.isDeleted())
1046 return false;
1047 }
1048 return true;
1049 }
1050
1051 private RefactoringStatus checkReorderings(IProgressMonitor pm) throws JavaModelException {
1052 try{
1053 pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1);
1054 return checkNativeMethods();
1055 } finally{
1056 pm.done();
1057 }
1058 }
1059
1060 private RefactoringStatus checkRenamings(IProgressMonitor pm) throws JavaModelException {
1061 try{
1062 pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_checking_preconditions, 1);
1063 return checkParameterNamesInRippleMethods();
1064 } finally{
1065 pm.done();
1066 }
1067 }
1068
1069 private RefactoringStatus checkParameterNamesInRippleMethods() throws JavaModelException {
1070 RefactoringStatus result= new RefactoringStatus();
1071 Set<String> newParameterNames= getNewParameterNamesList();
1072 for (int i= 0; i < fRippleMethods.length; i++) {
1073 String[] paramNames= fRippleMethods[i].getParameterNames();
1074 for (int j= 0; j < paramNames.length; j++) {
1075 if (newParameterNames.contains(paramNames[j])){
1076 String[] args= new String[]{ JavaElementUtil.createMethodSignature(fRippleMethods[i]), BasicElementLabels.getJavaElementName(paramNames[j])};
1077 String msg= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_already_has, args);
1078 RefactoringStatusContext context= JavaStatusContext.create(fRippleMethods[i].getCompilationUnit(), fRippleMethods[i].getNameRange());
1079 result.addError(msg, context);
1080 }
1081 }
1082 }
1083 return result;
1084 }
1085
1086 private Set<String> getNewParameterNamesList() {
1087 Set<String> oldNames= getOriginalParameterNames();
1088 Set<String> currentNames= getNamesOfNotDeletedParameters();
1089 currentNames.removeAll(oldNames);
1090 return currentNames;
1091 }
1092
1093 private Set<String> getNamesOfNotDeletedParameters() {
1094 Set<String> result= new HashSet<String>();
1095 for (Iterator<ParameterInfo> iter= getNotDeletedInfos().iterator(); iter.hasNext();) {
1096 ParameterInfo info= iter.next();
1097 result.add(info.getNewName());
1098 }
1099 return result;
1100 }
1101
1102 private Set<String> getOriginalParameterNames() {
1103 Set<String> result= new HashSet<String>();
1104 for (Iterator<ParameterInfo> iter= fParameterInfos.iterator(); iter.hasNext();) {
1105 ParameterInfo info= iter.next();
1106 info.generated_4717070005832400089(result);
1107 }
1108 return result;
1109 }
1110
1111 private RefactoringStatus checkNativeMethods() throws JavaModelException{
1112 RefactoringStatus result= new RefactoringStatus();
1113 for (int i= 0; i < fRippleMethods.length; i++) {
1114 if (JdtFlags.isNative(fRippleMethods[i])){
1115 String message= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_native,
1116 new String[]{JavaElementUtil.createMethodSignature(fRippleMethods[i]), BasicElementLabels.getJavaElementName(fRippleMethods[i].getDeclaringType().getFullyQualifiedName('.'))});
1117 result.addError(message, JavaStatusContext.create(fRippleMethods[i]));
1118 }
1119 }
1120 return result;
1121 }
1122
1123 private IFile[] getAllFilesToModify(){
1124 return ResourceUtil.getFiles(fChangeManager.getAllCompilationUnits());
1125 }
1126
1127 public Change[] getAllChanges() {
1128 return fChangeManager.getAllChanges();
1129 }
1130
1131 /* (non-Javadoc)
1132 * @see org.eclipse.ltk.core.refactoring.Refactoring#createChange(org.eclipse.core.runtime.IProgressMonitor)
1133 */
1134 @Override
1135 public Change createChange(IProgressMonitor pm) {
1136 pm.beginTask("", 1); //$NON-NLS-1$
1137 try {
1138 return new DynamicValidationRefactoringChange(createDescriptor(), doGetRefactoringChangeName(), getAllChanges());
1139 } finally {
1140 clearManagers();
1141 pm.done();
1142 }
1143 }
1144
1145 private ChangeMethodSignatureArguments getParticipantArguments() {
1146 ArrayList<Parameter> parameterList= new ArrayList<Parameter>();
1147 List<ParameterInfo> pis= getParameterInfos();
1148 String[] originalParameterTypeSigs= fMethod.getParameterTypes();
1149
1150 for (Iterator<ParameterInfo> iter= pis.iterator(); iter.hasNext();) {
1151 ParameterInfo pi= iter.next();
1152 pi.generated_3995637469964058751(parameterList, originalParameterTypeSigs);
1153 }
1154 Parameter[] parameters= parameterList.toArray(new Parameter[parameterList.size()]);
1155
1156 ArrayList<ThrownException> exceptionList= new ArrayList<ThrownException>();
1157 List<ExceptionInfo> exceptionInfos= getExceptionInfos();
1158 for (int i= 0; i < exceptionInfos.size(); i++) {
1159 ExceptionInfo ei= exceptionInfos.get(i);
1160 if (!ei.isDeleted()) {
1161 int oldIndex= ei.isAdded() ? -1 : i;
1162 String qualifiedTypeName= ei.getFullyQualifiedName();
1163 String newTypeSig= Signature.createTypeSignature(qualifiedTypeName, true);
1164 exceptionList.add(new ThrownException(oldIndex, newTypeSig));
1165 }
1166 }
1167 ThrownException[] exceptions= exceptionList.toArray(new ThrownException[exceptionList.size()]);
1168 String returnTypeSig;
1169 if (fReturnTypeInfo.isTypeNameChanged()) {
1170 returnTypeSig= Signature.createTypeSignature(fReturnTypeInfo.getNewTypeName(), false);
1171 } else {
1172 try {
1173 returnTypeSig= fMethod.getReturnType();
1174 } catch (JavaModelException e) {
1175 returnTypeSig= Signature.createTypeSignature(fReturnTypeInfo.getNewTypeName(), false);
1176 }
1177 }
1178 return new ChangeMethodSignatureArguments(fMethodName, returnTypeSig, fVisibility, parameters, exceptions, fDelegateUpdating);
1179 }
1180
1181 public JavaRefactoringDescriptor createDescriptor() {
1182 final Map<String, String> arguments= new HashMap<String, String>();
1183 String project= null;
1184 IJavaProject javaProject= fMethod.getJavaProject();
1185 if (javaProject != null)
1186 project= javaProject.getElementName();
1187 ChangeMethodSignatureDescriptor descriptor= null;
1188 try {
1189 final String description= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description_short, BasicElementLabels.getJavaElementName(fMethod.getElementName()));
1190 final String header= Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_descriptor_description, new String[] { getOldMethodSignature(), getNewMethodSignature()});
1191 final JDTRefactoringDescriptorComment comment= createComment(project, header);
1192 descriptor= RefactoringSignatureDescriptorFactory.createChangeMethodSignatureDescriptor(project, description, comment.asString(), arguments, getDescriptorFlags());
1193 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(project,fMethod));
1194 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_NAME, fMethodName);
1195 arguments.put(ATTRIBUTE_DELEGATE, Boolean.valueOf(fDelegateUpdating).toString());
1196 arguments.put(ATTRIBUTE_DEPRECATE, Boolean.valueOf(fDelegateDeprecation).toString());
1197 if (fReturnTypeInfo.isTypeNameChanged())
1198 arguments.put(ATTRIBUTE_RETURN, fReturnTypeInfo.getNewTypeName());
1199 try {
1200 if (!isVisibilitySameAsInitial())
1201 arguments.put(ATTRIBUTE_VISIBILITY, new Integer(fVisibility).toString());
1202 } catch (JavaModelException exception) {
1203 JavaPlugin.log(exception);
1204 }
1205 int count= 1;
1206 for (final Iterator<ParameterInfo> iterator= fParameterInfos.iterator(); iterator.hasNext();) {
1207 final ParameterInfo info= iterator.next();
1208 final StringBuffer buffer= new StringBuffer(64);
1209 count= info.generated_7420041729356732013(arguments, count, buffer);
1210 }
1211 count= 1;
1212 for (final Iterator<ExceptionInfo> iterator= fExceptionInfos.iterator(); iterator.hasNext();) {
1213 final ExceptionInfo info= iterator.next();
1214 arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_ELEMENT + count, JavaRefactoringDescriptorUtil.elementToHandle(project,info.getElement()));
1215 arguments.put(ATTRIBUTE_KIND + count, new Integer(info.getKind()).toString());
1216 count++;
1217 }
1218 } catch (JavaModelException exception) {
1219 JavaPlugin.log(exception);
1220 return null;
1221 }
1222 return descriptor;
1223 }
1224
1225 protected int getDescriptorFlags() {
1226 int flags= JavaRefactoringDescriptor.JAR_MIGRATION | JavaRefactoringDescriptor.JAR_REFACTORING | RefactoringDescriptor.STRUCTURAL_CHANGE;
1227 try {
1228 if (!Flags.isPrivate(fMethod.getFlags()))
1229 flags|= RefactoringDescriptor.MULTI_CHANGE;
1230 final IType declaring= fMethod.getDeclaringType();
1231 if (declaring.isAnonymous() || declaring.isLocal())
1232 flags|= JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT;
1233 } catch (JavaModelException exception) {
1234 JavaPlugin.log(exception);
1235 }
1236 return flags;
1237 }
1238
1239 private JDTRefactoringDescriptorComment createComment(String project, final String header) throws JavaModelException {
1240 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header);
1241 if (!fMethod.getElementName().equals(fMethodName))
1242 comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_name_pattern, BasicElementLabels.getJavaElementName(fMethodName)));
1243 if (!isVisibilitySameAsInitial()) {
1244 String visibility= JdtFlags.getVisibilityString(fVisibility);
1245 if ("".equals(visibility)) //$NON-NLS-1$
1246 visibility= RefactoringCoreMessages.ChangeSignatureRefactoring_default_visibility;
1247 comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_visibility_pattern, visibility));
1248 }
1249 if (fReturnTypeInfo.isTypeNameChanged())
1250 comment.addSetting(Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_new_return_type_pattern, BasicElementLabels.getJavaElementName(fReturnTypeInfo.getNewTypeName())));
1251 List<String> deleted= new ArrayList<String>();
1252 List<String> added= new ArrayList<String>();
1253 List<String> changed= new ArrayList<String>();
1254 for (final Iterator<ParameterInfo> iterator= fParameterInfos.iterator(); iterator.hasNext();) {
1255 final ParameterInfo info= iterator.next();
1256 info.generated_1906015980534280815(deleted, added, changed);
1257 }
1258 if (!added.isEmpty())
1259 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_parameters, added.toArray(new String[added.size()])));
1260 if (!deleted.isEmpty())
1261 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_parameters, deleted.toArray(new String[deleted.size()])));
1262 if (!changed.isEmpty())
1263 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_changed_parameters, changed.toArray(new String[changed.size()])));
1264 added.clear();
1265 deleted.clear();
1266 changed.clear();
1267 for (final Iterator<ExceptionInfo> iterator= fExceptionInfos.iterator(); iterator.hasNext();) {
1268 final ExceptionInfo info= iterator.next();
1269 if (info.isAdded())
1270 added.add(info.getElement().getElementName());
1271 else if (info.isDeleted())
1272 deleted.add(info.getElement().getElementName());
1273 }
1274 if (!added.isEmpty())
1275 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_added_exceptions, added.toArray(new String[added.size()])));
1276 if (!deleted.isEmpty())
1277 comment.addSetting(JDTRefactoringDescriptorComment.createCompositeSetting(RefactoringCoreMessages.ChangeSignatureRefactoring_removed_exceptions, deleted.toArray(new String[deleted.size()])));
1278 return comment;
1279 }
1280
1281 protected String doGetRefactoringChangeName() {
1282 return RefactoringCoreMessages.ChangeSignatureRefactoring_restructure_parameters;
1283 }
1284
1285 private TextChangeManager createChangeManager(IProgressMonitor pm, RefactoringStatus result) throws CoreException {
1286 pm.beginTask(RefactoringCoreMessages.ChangeSignatureRefactoring_preview, 2);
1287 fChangeManager= new TextChangeManager();
1288 boolean isNoArgConstructor= isNoArgConstructor();
1289 Map<ICompilationUnit, Set<IType>> namedSubclassMapping= null;
1290 if (isNoArgConstructor){
1291 //create only when needed;
1292 namedSubclassMapping= createNamedSubclassMapping(new SubProgressMonitor(pm, 1));
1293 }else{
1294 pm.worked(1);
1295 }
1296 for (int i= 0; i < fOccurrences.length; i++) {
1297 if (pm.isCanceled())
1298 throw new OperationCanceledException();
1299 SearchResultGroup group= fOccurrences[i];
1300 ICompilationUnit cu= group.getCompilationUnit();
1301 if (cu == null)
1302 continue;
1303 CompilationUnitRewrite cuRewrite;
1304 if (cu.equals(getCu())) {
1305 cuRewrite= fBaseCuRewrite;
1306 } else {
1307 cuRewrite= new CompilationUnitRewrite(cu);
1308 cuRewrite.getASTRewrite().setTargetSourceRangeComputer(new TightSourceRangeComputer());
1309 }
1310 ASTNode[] nodes= ASTNodeSearchUtil.findNodes(group.getSearchResults(), cuRewrite.getRoot());
1311
1312 //IntroduceParameterObjectRefactoring needs to update declarations first:
1313 List<OccurrenceUpdate<? extends ASTNode>> deferredUpdates= new ArrayList<OccurrenceUpdate<? extends ASTNode>>();
1314 for (int j= 0; j < nodes.length; j++) {
1315 OccurrenceUpdate<? extends ASTNode> update= createOccurrenceUpdate(nodes[j], cuRewrite, result);
1316 if (update instanceof DeclarationUpdate) {
1317 update.updateNode();
1318 } else {
1319 deferredUpdates.add(update);
1320 }
1321 }
1322 for (Iterator<OccurrenceUpdate<? extends ASTNode>> iter= deferredUpdates.iterator(); iter.hasNext();) {
1323 iter.next().updateNode();
1324 }
1325
1326 if (isNoArgConstructor && namedSubclassMapping.containsKey(cu)){
1327 //only non-anonymous subclasses may have noArgConstructors to modify - see bug 43444
1328 Set<IType> subtypes= namedSubclassMapping.get(cu);
1329 for (Iterator<IType> iter= subtypes.iterator(); iter.hasNext();) {
1330 IType subtype= iter.next();
1331 AbstractTypeDeclaration subtypeNode= ASTNodeSearchUtil.getAbstractTypeDeclarationNode(subtype, cuRewrite.getRoot());
1332 if (subtypeNode != null)
1333 modifyImplicitCallsToNoArgConstructor(subtypeNode, cuRewrite);
1334 }
1335 }
1336 TextChange change= cuRewrite.createChange(true);
1337 if (change != null)
1338 fChangeManager.manage(cu, change);
1339 }
1340
1341 pm.done();
1342 return fChangeManager;
1343 }
1344
1345 private Map<ICompilationUnit, Set<IType>> createNamedSubclassMapping(IProgressMonitor pm) throws JavaModelException{
1346 IType[] subclasses= getCachedTypeHierarchy(new SubProgressMonitor(pm, 1)).getSubclasses(fMethod.getDeclaringType());
1347 Map<ICompilationUnit, Set<IType>> result= new HashMap<ICompilationUnit, Set<IType>>();
1348 for (int i= 0; i < subclasses.length; i++) {
1349 IType subclass= subclasses[i];
1350 if (subclass.isAnonymous())
1351 continue;
1352 ICompilationUnit cu= subclass.getCompilationUnit();
1353 if (! result.containsKey(cu))
1354 result.put(cu, new HashSet<IType>());
1355 result.get(cu).add(subclass);
1356 }
1357 return result;
1358 }
1359
1360 private void modifyImplicitCallsToNoArgConstructor(AbstractTypeDeclaration subclass, CompilationUnitRewrite cuRewrite) {
1361 MethodDeclaration[] constructors= getAllConstructors(subclass);
1362 cuRewrite.generated_8142113877248082095(subclass, this, constructors);
1363 }
1364
1365 void addExplicitSuperConstructorCall(MethodDeclaration constructor, CompilationUnitRewrite cuRewrite) {
1366 SuperConstructorInvocation superCall= constructor.getAST().newSuperConstructorInvocation();
1367 cuRewrite.generated_4627481949351033098(constructor, this, superCall);
1368 }
1369
1370 void addArgumentsToNewSuperConstructorCall(SuperConstructorInvocation superCall, CompilationUnitRewrite cuRewrite) {
1371 Iterator<ParameterInfo> iter= getNotDeletedInfos().iterator();
1372 while (iter.hasNext()) {
1373 ParameterInfo info= iter.next();
1374 Expression newExpression= createNewExpression(info, getParameterInfos(), superCall.arguments(), cuRewrite, (MethodDeclaration) ASTNodes.getParent(superCall, MethodDeclaration.class));
1375 if (newExpression != null)
1376 superCall.arguments().add(newExpression);
1377 }
1378 }
1379
1380 static boolean containsImplicitCallToSuperConstructor(MethodDeclaration constructor) {
1381 Assert.isTrue(constructor.isConstructor());
1382 Block body= constructor.getBody();
1383 if (body == null)
1384 return false;
1385 if (body.statements().size() == 0)
1386 return true;
1387 if (body.statements().get(0) instanceof ConstructorInvocation)
1388 return false;
1389 if (body.statements().get(0) instanceof SuperConstructorInvocation)
1390 return false;
1391 return true;
1392 }
1393
1394 void addNewConstructorToSubclass(AbstractTypeDeclaration subclass, CompilationUnitRewrite cuRewrite) {
1395 AST ast= subclass.getAST();
1396 MethodDeclaration newConstructor= ast.newMethodDeclaration();
1397 cuRewrite.generated_8363840589174779188(subclass, this, ast, newConstructor);
1398
1399 // TODO use AbstractTypeDeclaration
1400 }
1401
1402 static int getAccessModifier(AbstractTypeDeclaration subclass) {
1403 int modifiers= subclass.getModifiers();
1404 if (Modifier.isPublic(modifiers))
1405 return Modifier.PUBLIC;
1406 else if (Modifier.isProtected(modifiers))
1407 return Modifier.PROTECTED;
1408 else if (Modifier.isPrivate(modifiers))
1409 return Modifier.PRIVATE;
1410 else
1411 return Modifier.NONE;
1412 }
1413
1414 private MethodDeclaration[] getAllConstructors(AbstractTypeDeclaration typeDeclaration) {
1415 BodyDeclaration decl;
1416 List<BodyDeclaration> result= new ArrayList<BodyDeclaration>(1);
1417 for (Iterator<BodyDeclaration> it = typeDeclaration.bodyDeclarations().listIterator(); it.hasNext(); ) {
1418 decl= it.next();
1419 if (decl instanceof MethodDeclaration && ((MethodDeclaration) decl).isConstructor())
1420 result.add(decl);
1421 }
1422 return result.toArray(new MethodDeclaration[result.size()]);
1423 }
1424
1425 private boolean isNoArgConstructor() throws JavaModelException {
1426 return fMethod.isConstructor() && fMethod.getNumberOfParameters() == 0;
1427 }
1428
1429 private Expression createNewExpression(ParameterInfo info, List<ParameterInfo> parameterInfos, List<Expression> nodes, CompilationUnitRewrite cuRewrite, MethodDeclaration method) {
1430 if (info.isNewVarargs() && info.getDefaultValue().trim().length() == 0)
1431 return null;
1432 else {
1433 return cuRewrite.generated_8509678262293722505(info, parameterInfos, nodes, this, method);
1434 }
1435 }
1436
1437 private boolean isVisibilitySameAsInitial() throws JavaModelException {
1438 return fVisibility == JdtFlags.getVisibilityCode(fMethod);
1439 }
1440
1441 public IJavaSearchScope createRefactoringScope() throws JavaModelException{
1442 return RefactoringScopeFactory.create(fMethod, true, false);
1443 }
1444
1445 private SearchResultGroup[] findOccurrences(IProgressMonitor pm, ReferencesInBinaryContext binaryRefs, RefactoringStatus status) throws JavaModelException{
1446 final boolean isConstructor= fMethod.isConstructor();
1447 CuCollectingSearchRequestor requestor= new CuCollectingSearchRequestor(binaryRefs) {
1448 @Override
1449 protected void acceptSearchMatch(ICompilationUnit unit, SearchMatch match) throws CoreException {
1450 // workaround for https://bugs.eclipse.org/bugs/show_bug.cgi?id=27236 :
1451 if (isConstructor && match instanceof MethodReferenceMatch) {
1452 MethodReferenceMatch mrm= (MethodReferenceMatch) match;
1453 if (mrm.isSynthetic()) {
1454 return;
1455 }
1456 }
1457 collectMatch(match);
1458 }
1459 };
1460
1461 SearchPattern pattern;
1462 return requestor.generated_6617977053482112261(pm, status, isConstructor, this, pattern);
1463 }
1464
1465 private static String createDeclarationString(ParameterInfo info) {
1466 String newTypeName= info.getNewTypeName();
1467 int varargsIndex= newTypeName.lastIndexOf("..."); //$NON-NLS-1$
1468 if (varargsIndex != -1) {
1469 newTypeName= newTypeName.substring(0, varargsIndex);
1470 }
1471 int index= newTypeName.lastIndexOf('.');
1472 if (index != -1) {
1473 newTypeName= newTypeName.substring(index+1);
1474 }
1475 return newTypeName + (varargsIndex != -1 ? "..." : "") + " " + info.getNewName(); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
1476 }
1477
1478 private static final boolean BUG_89686= true; //see bug 83693: Search for References to methods/constructors: do ranges include parameter lists?
1479
1480 private OccurrenceUpdate<? extends ASTNode> createOccurrenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
1481 if (BUG_89686 && node instanceof SimpleName && node.getParent() instanceof EnumConstantDeclaration)
1482 node= node.getParent();
1483
1484 if (Invocations.isInvocationWithArguments(node))
1485 return new ReferenceUpdate(node, cuRewrite, result);
1486
1487 else if (node instanceof SimpleName && node.getParent() instanceof MethodDeclaration)
1488 return new DeclarationUpdate((MethodDeclaration) node.getParent(), cuRewrite, result);
1489
1490 else if (node instanceof MemberRef || node instanceof MethodRef)
1491 return new DocReferenceUpdate(node, cuRewrite, result);
1492
1493 else if (ASTNodes.getParent(node, ImportDeclaration.class) != null)
1494 return new StaticImportUpdate((ImportDeclaration) ASTNodes.getParent(node, ImportDeclaration.class), cuRewrite, result);
1495
1496 else
1497 return new NullOccurrenceUpdate(node, cuRewrite, result);
1498 }
1499
1500 public abstract class OccurrenceUpdate<N extends ASTNode> {
1501 public final CompilationUnitRewrite fCuRewrite;
1502 public final TextEditGroup fDescription;
1503 public RefactoringStatus fResult;
1504
1505 protected OccurrenceUpdate(CompilationUnitRewrite cuRewrite, TextEditGroup description, RefactoringStatus result) {
1506 fCuRewrite= cuRewrite;
1507 fDescription= description;
1508 fResult= result;
1509 }
1510
1511 public final ASTRewrite getASTRewrite() {
1512 return fCuRewrite.getASTRewrite();
1513 }
1514
1515 public final ImportRewrite getImportRewrite() {
1516 return fCuRewrite.getImportRewrite();
1517 }
1518
1519 public final ImportRemover getImportRemover() {
1520 return fCuRewrite.getImportRemover();
1521 }
1522
1523 protected final CompilationUnitRewrite getCompilationUnitRewrite() {
1524 return fCuRewrite;
1525 }
1526
1527 public abstract void updateNode() throws CoreException;
1528
1529 protected void registerImportRemoveNode(ASTNode node) {
1530 getImportRemover().registerRemovedNode(node);
1531 }
1532
1533 protected final void reshuffleElements() {
1534 if (isOrderSameAsInitial())
1535 return;
1536
1537 //varargs; method(p1, p2, .., pn), call(a1, a2, .., ax) :
1538 // if (method_was_vararg) {
1539 // assert fOldVarargIndex != -1
1540 // if (vararg_retained) {
1541 // assert vararg_is_last_non_deleted (pn)
1542 // assert no_other_varargs
1543 // => reshuffle [1..n-1] then append remaining nodes [n..x], possibly none
1544 //
1545 // } else (vararg_deleted) {
1546 // assert all_are_non_vararg
1547 // => reshuffle [1..n-1], drop all remaining nodes [n..x], possibly none
1548 // }
1549 //
1550 // } else if (method_became_vararg) {
1551 // assert n == x
1552 // assert fOldVarargIndex == -1
1553 // => reshuffle [1..n]
1554 //
1555 // } else (JLS2_case) {
1556 // assert n == x
1557 // assert fOldVarargIndex == -1
1558 // => reshuffle [1..n]
1559 // }
1560
1561 ListRewrite listRewrite= getParamgumentsRewrite();
1562 Map<N, N> newOldMap= new LinkedHashMap<N, N>();
1563 List<N> nodes= listRewrite.getRewrittenList();
1564 Iterator<N> rewriteIter= nodes.iterator();
1565 List<N> original= listRewrite.getOriginalList();
1566 for (Iterator<N> iter= original.iterator(); iter.hasNext();) {
1567 newOldMap.put(rewriteIter.next(),iter.next());
1568 }
1569 List<N> newNodes= new ArrayList<N>();
1570 // register removed nodes, and collect nodes in new sequence:
1571 for (int i= 0; i < fParameterInfos.size(); i++) {
1572 ParameterInfo info= fParameterInfos.get(i);
1573 int oldIndex= info.getOldIndex();
1574
1575 if (info.isDeleted()) {
1576 if (oldIndex != fOldVarargIndex) {
1577 registerImportRemoveNode(nodes.get(oldIndex));
1578 } else {
1579 //vararg deleted -> remove all remaining nodes:
1580 for (int n= oldIndex; n < nodes.size(); n++) {
1581 registerImportRemoveNode(nodes.get(n));
1582 }
1583 }
1584
1585 } else if (info.isAdded()) {
1586 N newParamgument= createNewParamgument(info, fParameterInfos, nodes);
1587 if (newParamgument != null)
1588 newNodes.add(newParamgument);
1589
1590 } else /* parameter stays */ {
1591 if (oldIndex != fOldVarargIndex) {
1592 N oldNode= nodes.get(oldIndex);
1593 N movedNode= moveNode(oldNode, getASTRewrite());
1594 newNodes.add(movedNode);
1595 } else {
1596 //vararg stays and is last parameter -> copy all remaining nodes:
1597 for (int n= oldIndex; n < nodes.size(); n++) {
1598 N oldNode= nodes.get(n);
1599 N movedNode= moveNode(oldNode, getASTRewrite());
1600 newNodes.add(movedNode);
1601 }
1602 }
1603 }
1604 }
1605
1606 Iterator<N> nodesIter= nodes.iterator();
1607 Iterator<N> newIter= newNodes.iterator();
1608 //replace existing nodes with new ones:
1609 while (nodesIter.hasNext() && newIter.hasNext()) {
1610 ASTNode node= nodesIter.next();
1611 ASTNode newNode= newIter.next();
1612 if (!ASTNodes.isExistingNode(node)) //XXX:should better be addressed in ListRewriteEvent.replaceEntry(ASTNode, ASTNode)
1613 listRewrite.replace(newOldMap.get(node), newNode, fDescription);
1614 else
1615 listRewrite.replace(node, newNode, fDescription);
1616 }
1617 //remove remaining existing nodes:
1618 while (nodesIter.hasNext()) {
1619 ASTNode node= nodesIter.next();
1620 if (!ASTNodes.isExistingNode(node))
1621 listRewrite.remove(newOldMap.get(node), fDescription);
1622 else
1623 listRewrite.remove(node, fDescription);
1624 }
1625 //add additional new nodes:
1626 while (newIter.hasNext()) {
1627 ASTNode node= newIter.next();
1628 listRewrite.insertLast(node, fDescription);
1629 }
1630 }
1631
1632 /**
1633 * @return ListRewrite of parameters or arguments
1634 */
1635 protected abstract ListRewrite getParamgumentsRewrite();
1636
1637 protected final void changeParamguments() {
1638 for (Iterator<ParameterInfo> iter= getParameterInfos().iterator(); iter.hasNext();) {
1639 ParameterInfo info= iter.next();
1640 if (info.isAdded() || info.isDeleted())
1641 continue;
1642
1643 if (info.isRenamed())
1644 changeParamgumentName(info);
1645
1646 if (info.isTypeNameChanged())
1647 changeParamgumentType(info);
1648 }
1649 }
1650
1651 /**
1652 * @param info the parameter info
1653 */
1654 protected void changeParamgumentName(ParameterInfo info) {
1655 // no-op
1656 }
1657
1658 /**
1659 * @param info the parameter info
1660 */
1661 protected void changeParamgumentType(ParameterInfo info) {
1662 // no-op
1663 }
1664
1665 public final void replaceTypeNode(Type typeNode, String newTypeName, ITypeBinding newTypeBinding){
1666 Type newTypeNode= createNewTypeNode(newTypeName, newTypeBinding);
1667 getASTRewrite().replace(typeNode, newTypeNode, fDescription);
1668 registerImportRemoveNode(typeNode);
1669 getTightSourceRangeComputer().addTightSourceNode(typeNode);
1670 }
1671
1672 /**
1673 * @param info TODO
1674 * @param parameterInfos TODO
1675 * @param nodes TODO
1676 * @return a new method parameter or argument, or <code>null</code> for an empty vararg argument
1677 */
1678 protected abstract N createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<N> nodes);
1679
1680 protected abstract SimpleName getMethodNameNode();
1681
1682 protected final void changeMethodName() {
1683 if (! isMethodNameSameAsInitial()) {
1684 SimpleName nameNode= getMethodNameNode();
1685 SimpleName newNameNode= nameNode.getAST().newSimpleName(fMethodName);
1686 getASTRewrite().replace(nameNode, newNameNode, fDescription);
1687 registerImportRemoveNode(nameNode);
1688 getTightSourceRangeComputer().addTightSourceNode(nameNode);
1689 }
1690 }
1691
1692 public final Type createNewTypeNode(String newTypeName, ITypeBinding newTypeBinding) {
1693 Type newTypeNode;
1694 if (newTypeBinding == null) {
1695 if (fDefaultValueAdvisor != null)
1696 newTypeNode= fDefaultValueAdvisor.createType(newTypeName, getMethodNameNode().getStartPosition(), getCompilationUnitRewrite());
1697 else
1698 newTypeNode= (Type) getASTRewrite().createStringPlaceholder(newTypeName, ASTNode.SIMPLE_TYPE);
1699 //Don't import if not resolved.
1700 } else {
1701 ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(fCuRewrite.getRoot(), getMethodNameNode().getStartPosition(), getImportRewrite());
1702 newTypeNode= getImportRewrite().addImport(newTypeBinding, fCuRewrite.getAST(), importRewriteContext);
1703 getImportRemover().registerAddedImports(newTypeNode);
1704 }
1705 return newTypeNode;
1706 }
1707
1708 protected final TightSourceRangeComputer getTightSourceRangeComputer() {
1709 return (TightSourceRangeComputer) fCuRewrite.getASTRewrite().getExtendedSourceRangeComputer();
1710 }
1711 }
1712
1713 class ReferenceUpdate extends OccurrenceUpdate<Expression> {
1714 /** isReferenceNode(fNode) */
1715 private ASTNode fNode;
1716
1717 protected ReferenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
1718 super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_update_reference), result);
1719 fNode= node; //holds: Assert.isTrue(isReferenceNode(node));
1720 }
1721
1722 @Override
1723 public void updateNode() {
1724 reshuffleElements();
1725 changeMethodName();
1726 }
1727
1728 /** @return {@inheritDoc} (element type: Expression) */
1729 @Override
1730 protected ListRewrite getParamgumentsRewrite() {
1731 return getASTRewrite().getListRewrite(fNode, Invocations.getArgumentsProperty(fNode));
1732 }
1733
1734 @Override
1735 protected Expression createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<Expression> nodes) {
1736 CompilationUnitRewrite cuRewrite= getCompilationUnitRewrite();
1737 MethodDeclaration declaration= (MethodDeclaration) ASTNodes.getParent(fNode, MethodDeclaration.class);
1738 if (isRecursiveReference()) {
1739 return createNewExpressionRecursive(info, parameterInfos, nodes, cuRewrite, declaration);
1740 } else
1741 return createNewExpression(info, parameterInfos, nodes, cuRewrite, declaration);
1742 }
1743
1744 private Expression createNewExpressionRecursive(ParameterInfo info, List<ParameterInfo> parameterInfos, List<Expression> nodes, CompilationUnitRewrite cuRewrite, MethodDeclaration methodDeclaration) {
1745 if (fDefaultValueAdvisor != null && info.isAdded()) {
1746 return fDefaultValueAdvisor.createDefaultExpression(nodes, info, parameterInfos, methodDeclaration, true, cuRewrite);
1747 }
1748 return (Expression) getASTRewrite().createStringPlaceholder(info.getNewName(), ASTNode.METHOD_INVOCATION);
1749 }
1750
1751 @Override
1752 protected SimpleName getMethodNameNode() {
1753 if (fNode instanceof MethodInvocation)
1754 return ((MethodInvocation)fNode).getName();
1755
1756 if (fNode instanceof SuperMethodInvocation)
1757 return ((SuperMethodInvocation)fNode).getName();
1758
1759 return null;
1760 }
1761
1762 private boolean isRecursiveReference() {
1763 MethodDeclaration enclosingMethodDeclaration= (MethodDeclaration) ASTNodes.getParent(fNode, MethodDeclaration.class);
1764 if (enclosingMethodDeclaration == null)
1765 return false;
1766
1767 IMethodBinding enclosingMethodBinding= enclosingMethodDeclaration.resolveBinding();
1768 if (enclosingMethodBinding == null)
1769 return false;
1770
1771 if (fNode instanceof MethodInvocation)
1772 return enclosingMethodBinding == ((MethodInvocation)fNode).resolveMethodBinding();
1773
1774 if (fNode instanceof SuperMethodInvocation) {
1775 IMethodBinding methodBinding= ((SuperMethodInvocation)fNode).resolveMethodBinding();
1776 return isSameMethod(methodBinding, enclosingMethodBinding);
1777 }
1778
1779 if (fNode instanceof ClassInstanceCreation)
1780 return enclosingMethodBinding == ((ClassInstanceCreation)fNode).resolveConstructorBinding();
1781
1782 if (fNode instanceof ConstructorInvocation)
1783 return enclosingMethodBinding == ((ConstructorInvocation)fNode).resolveConstructorBinding();
1784
1785 if (fNode instanceof SuperConstructorInvocation) {
1786 return false; //Constructors don't override -> enclosing has not been changed -> no recursion
1787 }
1788
1789 if (fNode instanceof EnumConstantDeclaration) {
1790 return false; //cannot define enum constant inside enum constructor
1791 }
1792
1793 Assert.isTrue(false);
1794 return false;
1795 }
1796
1797 /**
1798 * @param m1 method 1
1799 * @param m2 method 2
1800 * @return true iff
1801 * <ul><li>the methods are both constructors with same argument types, or</li>
1802 * <li>the methods have the same name and the same argument types</li></ul>
1803 */
1804 private boolean isSameMethod(IMethodBinding m1, IMethodBinding m2) {
1805 if (m1.isConstructor()) {
1806 if (! m2.isConstructor())
1807 return false;
1808 } else {
1809 if (! m1.getName().equals(m2.getName()))
1810 return false;
1811 }
1812
1813 ITypeBinding[] m1Parameters= m1.getParameterTypes();
1814 ITypeBinding[] m2Parameters= m2.getParameterTypes();
1815 if (m1Parameters.length != m2Parameters.length)
1816 return false;
1817 for (int i= 0; i < m1Parameters.length; i++) {
1818 if (m1Parameters[i].getErasure() != m2Parameters[i].getErasure())
1819 return false;
1820 }
1821 return true;
1822 }
1823
1824 }
1825
1826 public class DeclarationUpdate extends OccurrenceUpdate<SingleVariableDeclaration> {
1827 public MethodDeclaration fMethDecl;
1828
1829 protected DeclarationUpdate(MethodDeclaration decl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
1830 super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_change_signature), result);
1831 fMethDecl= decl;
1832 }
1833
1834 // Prevent import removing if delegate is created.
1835 @Override
1836 protected void registerImportRemoveNode(ASTNode node) {
1837 if (!fDelegateUpdating)
1838 super.registerImportRemoveNode(node);
1839 }
1840
1841 @Override
1842 public void updateNode() throws CoreException {
1843 changeParamguments();
1844
1845 if (canChangeNameAndReturnType()) {
1846 changeMethodName();
1847 changeReturnType();
1848 }
1849
1850 if (needsVisibilityUpdate())
1851 changeVisibility();
1852 reshuffleElements();
1853 changeExceptions();
1854
1855 changeJavadocTags();
1856
1857 if (fBodyUpdater == null || fBodyUpdater.needsParameterUsedCheck())
1858 checkIfDeletedParametersUsed();
1859
1860 if (fBodyUpdater != null)
1861 fBodyUpdater.updateBody(fMethDecl, fCuRewrite, fResult);
1862
1863 if (fDelegateUpdating)
1864 addDelegate();
1865 }
1866
1867 private void addDelegate() throws JavaModelException {
1868
1869 DelegateMethodCreator creator= new DelegateMethodCreator();
1870 creator.setDeclaration(fMethDecl);
1871 creator.setDeclareDeprecated(fDelegateDeprecation);
1872 creator.generated_7071724438348472777(DeclarationUpdate.this);
1873
1874 /*
1875 * The delegate now contains a call and a javadoc reference to the
1876 * old method (i.e., to itself).
1877 *
1878 * Use ReferenceUpdate() / DocReferenceUpdate() to update these
1879 * references like any other reference.
1880 */
1881 final ASTNode delegateInvocation= creator.getDelegateInvocation();
1882 if (delegateInvocation != null)
1883 // may be null if the delegate is an interface method or
1884 // abstract -> no body
1885 new ReferenceUpdate(delegateInvocation, creator.getDelegateRewrite(), fResult).updateNode();
1886 MethodRef javadocReference= creator.getJavadocReference();
1887 if (javadocReference != null)
1888 new DocReferenceUpdate(javadocReference, creator.getDelegateRewrite(), fResult).updateNode();
1889
1890 creator.createEdit();
1891 }
1892
1893 /** @return {@inheritDoc} (element type: SingleVariableDeclaration) */
1894 @Override
1895 protected ListRewrite getParamgumentsRewrite() {
1896 return getASTRewrite().getListRewrite(fMethDecl, MethodDeclaration.PARAMETERS_PROPERTY);
1897 }
1898
1899 @Override
1900 protected void changeParamgumentName(ParameterInfo info) {
1901 info.generated_1694571263349927414(DeclarationUpdate.this);
1902 }
1903
1904 @Override
1905 protected void changeParamgumentType(ParameterInfo info) {
1906 SingleVariableDeclaration oldParam= info.generated_2764139213922116428(DeclarationUpdate.this);
1907 removeExtraDimensions(oldParam);
1908 }
1909
1910 private void removeExtraDimensions(SingleVariableDeclaration oldParam) {
1911 if (oldParam.getExtraDimensions() != 0) {
1912 getASTRewrite().set(oldParam, SingleVariableDeclaration.EXTRA_DIMENSIONS_PROPERTY, new Integer(0), fDescription);
1913 }
1914 }
1915
1916 private void changeReturnType() {
1917 if (isReturnTypeSameAsInitial())
1918 return;
1919 replaceTypeNode(fMethDecl.getReturnType2(), fReturnTypeInfo.getNewTypeName(), fReturnTypeInfo.getNewTypeBinding());
1920 removeExtraDimensions(fMethDecl);
1921 //Remove expression from return statement when changed to void? No, would lose information!
1922 //Could add return statement with default value and add todo comment, but compile error is better.
1923 }
1924
1925 private void removeExtraDimensions(MethodDeclaration methDecl) {
1926 if (methDecl.getExtraDimensions() != 0)
1927 getASTRewrite().set(methDecl, MethodDeclaration.EXTRA_DIMENSIONS_PROPERTY, new Integer(0), fDescription);
1928 }
1929
1930 private boolean needsVisibilityUpdate() throws JavaModelException {
1931 if (isVisibilitySameAsInitial())
1932 return false;
1933 if (isIncreasingVisibility())
1934 return JdtFlags.isHigherVisibility(fVisibility, JdtFlags.getVisibilityCode(fMethDecl));
1935 else
1936 return JdtFlags.isHigherVisibility(JdtFlags.getVisibilityCode(fMethDecl), fVisibility);
1937 }
1938
1939 private boolean isIncreasingVisibility() throws JavaModelException{
1940 return JdtFlags.isHigherVisibility(fVisibility, JdtFlags.getVisibilityCode(fMethod));
1941 }
1942
1943 private void changeVisibility() {
1944 ModifierRewrite.create(getASTRewrite(), fMethDecl).setVisibility(fVisibility, fDescription);
1945 }
1946
1947 private void changeExceptions() {
1948 for (Iterator<ExceptionInfo> iter= fExceptionInfos.iterator(); iter.hasNext();) {
1949 ExceptionInfo info= iter.next();
1950 if (info.isOld())
1951 continue;
1952 info.generated_4799697167381318345(DeclarationUpdate.this);
1953 }
1954 }
1955
1956 public void removeExceptionFromNodeList(ExceptionInfo toRemove, List<Name> list) {
1957 ITypeBinding typeToRemove= toRemove.getTypeBinding();
1958 for (Iterator<Name> iter= list.iterator(); iter.hasNext(); ) {
1959 Name currentName= iter.next();
1960 ITypeBinding currentType= currentName.resolveTypeBinding();
1961 /* Maybe remove all subclasses of typeToRemove too.
1962 * Problem:
1963 * - B extends A;
1964 * - A.m() throws IOException, Exception;
1965 * - B.m() throws IOException, AWTException;
1966 * Removing Exception should remove AWTException,
1967 * but NOT remove IOException (or a subclass of JavaModelException). */
1968 // if (Bindings.isSuperType(typeToRemove, currentType))
1969 if (currentType == null)
1970 continue; // newly added or unresolvable type
1971 if (Bindings.equals(currentType, typeToRemove) || toRemove.getElement().getElementName().equals(currentType.getName())) {
1972 getASTRewrite().remove(currentName, fDescription);
1973 registerImportRemoveNode(currentName);
1974 }
1975 }
1976 }
1977
1978 public void addExceptionToNodeList(ExceptionInfo exceptionInfo, ListRewrite exceptionListRewrite) {
1979 exceptionInfo.generated_575812899652886805(DeclarationUpdate.this, exceptionListRewrite);
1980 }
1981
1982 private void changeJavadocTags() throws JavaModelException {
1983 //update tags in javadoc: @param, @return, @exception, @throws, ...
1984 Javadoc javadoc= fMethDecl.getJavadoc();
1985 if (javadoc == null)
1986 return;
1987
1988 ITypeBinding typeBinding= Bindings.getBindingOfParentType(fMethDecl);
1989 if (typeBinding == null)
1990 return;
1991 IMethodBinding methodBinding= fMethDecl.resolveBinding();
1992 if (methodBinding == null)
1993 return;
1994
1995 boolean isTopOfRipple= (Bindings.findOverriddenMethod(methodBinding, false) == null);
1996 //add tags: only iff top of ripple; change and remove: always.
1997 //TODO: should have preference for adding tags in (overriding) methods (with template: todo, inheritDoc, ...)
1998
1999 List<TagElement> tags= javadoc.tags();
2000 ListRewrite tagsRewrite= getASTRewrite().getListRewrite(javadoc, Javadoc.TAGS_PROPERTY);
2001
2002 if (! isReturnTypeSameAsInitial()) {
2003 if (PrimitiveType.VOID.toString().equals(fReturnTypeInfo.getNewTypeName())) {
2004 for (int i = 0; i < tags.size(); i++) {
2005 TagElement tag= tags.get(i);
2006 if (TagElement.TAG_RETURN.equals(tag.getTagName())) {
2007 getASTRewrite().remove(tag, fDescription);
2008 registerImportRemoveNode(tag);
2009 }
2010 }
2011 } else if (isTopOfRipple && Signature.SIG_VOID.equals(fMethod.getReturnType())){
2012 TagElement returnNode= createReturnTag();
2013 TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_RETURN);
2014 insertTag(returnNode, previousTag, tagsRewrite);
2015 tags= tagsRewrite.getRewrittenList();
2016 }
2017 }
2018
2019 if (! (areNamesSameAsInitial() && isOrderSameAsInitial())) {
2020 ArrayList<TagElement> paramTags= new ArrayList<TagElement>(); // <TagElement>, only not deleted tags with simpleName
2021 // delete & rename:
2022 for (Iterator<TagElement> iter = tags.iterator(); iter.hasNext(); ) {
2023 TagElement tag = iter.next();
2024 String tagName= tag.getTagName();
2025 List<? extends ASTNode> fragments= tag.fragments();
2026 if (! (TagElement.TAG_PARAM.equals(tagName) && fragments.size() > 0 && fragments.get(0) instanceof SimpleName))
2027 continue;
2028 SimpleName simpleName= (SimpleName) fragments.get(0);
2029 String identifier= simpleName.getIdentifier();
2030 boolean removed= false;
2031 for (int i= 0; i < fParameterInfos.size(); i++) {
2032 ParameterInfo info= fParameterInfos.get(i);
2033 if (identifier.equals(info.getOldName())) {
2034 if (info.isDeleted()) {
2035 getASTRewrite().remove(tag, fDescription);
2036 registerImportRemoveNode(tag);
2037 removed= true;
2038 } else if (info.isRenamed()) {
2039 SimpleName newName= simpleName.getAST().newSimpleName(info.getNewName());
2040 getASTRewrite().replace(simpleName, newName, fDescription);
2041 registerImportRemoveNode(tag);
2042 }
2043 break;
2044 }
2045 }
2046 if (! removed)
2047 paramTags.add(tag);
2048 }
2049 tags= tagsRewrite.getRewrittenList();
2050
2051 if (! isOrderSameAsInitial()) {
2052 // reshuffle (sort in declaration sequence) & add (only add to top of ripple):
2053 TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_PARAM);
2054 boolean first= true; // workaround for bug 92111: preserve first tag if possible
2055 // reshuffle:
2056 for (Iterator<ParameterInfo> infoIter= fParameterInfos.iterator(); infoIter.hasNext();) {
2057 ParameterInfo info= infoIter.next();
2058 String oldName= info.getOldName();
2059 String newName= info.getNewName();
2060 if (info.isAdded()) {
2061 first= false;
2062 if (! isTopOfRipple)
2063 continue;
2064 TagElement paramNode= JavadocUtil.createParamTag(newName, fCuRewrite.getRoot().getAST(), fCuRewrite.getCu().getJavaProject());
2065 insertTag(paramNode, previousTag, tagsRewrite);
2066 previousTag= paramNode;
2067 } else {
2068 for (Iterator<TagElement> tagIter= paramTags.iterator(); tagIter.hasNext();) {
2069 TagElement tag= tagIter.next();
2070 SimpleName tagName= (SimpleName) tag.fragments().get(0);
2071 if (oldName.equals(tagName.getIdentifier())) {
2072 tagIter.remove();
2073 if (first) {
2074 previousTag= tag;
2075 } else {
2076 TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
2077 getASTRewrite().remove(tag, fDescription);
2078 insertTag(movedTag, previousTag, tagsRewrite);
2079 previousTag= movedTag;
2080 }
2081 }
2082 first= false;
2083 }
2084 }
2085 }
2086 // params with bad names:
2087 for (Iterator<TagElement> iter= paramTags.iterator(); iter.hasNext();) {
2088 TagElement tag= iter.next();
2089 TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
2090 getASTRewrite().remove(tag, fDescription);
2091 insertTag(movedTag, previousTag, tagsRewrite);
2092 previousTag= movedTag;
2093 }
2094 }
2095 tags= tagsRewrite.getRewrittenList();
2096 }
2097
2098 if (! areExceptionsSameAsInitial()) {
2099 // collect exceptionTags and remove deleted:
2100 ArrayList<TagElement> exceptionTags= new ArrayList<TagElement>(); // <TagElement>, only not deleted tags with name
2101 for (int i= 0; i < tags.size(); i++) {
2102 TagElement tag= tags.get(i);
2103 if (! TagElement.TAG_THROWS.equals(tag.getTagName()) && ! TagElement.TAG_EXCEPTION.equals(tag.getTagName()))
2104 continue;
2105 if (! (tag.fragments().size() > 0 && tag.fragments().get(0) instanceof Name))
2106 continue;
2107 boolean tagDeleted= false;
2108 Name name= (Name) tag.fragments().get(0);
2109 for (int j= 0; j < fExceptionInfos.size(); j++) {
2110 ExceptionInfo info= fExceptionInfos.get(j);
2111 if (info.isDeleted()) {
2112 boolean remove= false;
2113 final ITypeBinding nameBinding= name.resolveTypeBinding();
2114 if (nameBinding != null) {
2115 final ITypeBinding infoBinding= info.getTypeBinding();
2116 if (infoBinding != null && Bindings.equals(infoBinding, nameBinding))
2117 remove= true;
2118 else if (info.getElement().getElementName().equals(nameBinding.getName()))
2119 remove= true;
2120 if (remove) {
2121 getASTRewrite().remove(tag, fDescription);
2122 registerImportRemoveNode(tag);
2123 tagDeleted= true;
2124 break;
2125 }
2126 }
2127 }
2128 }
2129 if (! tagDeleted)
2130 exceptionTags.add(tag);
2131 }
2132 // reshuffle:
2133 tags= tagsRewrite.getRewrittenList();
2134 TagElement previousTag= findTagElementToInsertAfter(tags, TagElement.TAG_THROWS);
2135 for (Iterator<ExceptionInfo> infoIter= fExceptionInfos.iterator(); infoIter.hasNext();) {
2136 ExceptionInfo info= infoIter.next();
2137 if (info.isAdded()) {
2138 if (!isTopOfRipple)
2139 continue;
2140 TagElement excptNode= createExceptionTag(info.getElement().getElementName());
2141 insertTag(excptNode, previousTag, tagsRewrite);
2142 previousTag= excptNode;
2143 } else {
2144 for (Iterator<TagElement> tagIter= exceptionTags.iterator(); tagIter.hasNext();) {
2145 TagElement tag= tagIter.next();
2146 previousTag= info.generated_469295385871681356(tagsRewrite, previousTag, DeclarationUpdate.this, tagIter, tag);
2147 }
2148 }
2149 }
2150 // exceptions with bad names:
2151 for (Iterator<TagElement> iter= exceptionTags.iterator(); iter.hasNext();) {
2152 TagElement tag= iter.next();
2153 TagElement movedTag= (TagElement) getASTRewrite().createMoveTarget(tag);
2154 getASTRewrite().remove(tag, fDescription);
2155 insertTag(movedTag, previousTag, tagsRewrite);
2156 previousTag= movedTag;
2157 }
2158 }
2159 }
2160
2161 private TagElement createReturnTag() {
2162 TagElement returnNode= getASTRewrite().getAST().newTagElement();
2163 returnNode.setTagName(TagElement.TAG_RETURN);
2164
2165 TextElement textElement= getASTRewrite().getAST().newTextElement();
2166 String text= StubUtility.getTodoTaskTag(fCuRewrite.getCu().getJavaProject());
2167 if (text != null)
2168 textElement.setText(text); //TODO: use template with {@todo} ...
2169 returnNode.fragments().add(textElement);
2170
2171 return returnNode;
2172 }
2173
2174 private TagElement createExceptionTag(String simpleName) {
2175 TagElement excptNode= getASTRewrite().getAST().newTagElement();
2176 excptNode.setTagName(TagElement.TAG_THROWS);
2177
2178 SimpleName nameNode= getASTRewrite().getAST().newSimpleName(simpleName);
2179 excptNode.fragments().add(nameNode);
2180
2181 TextElement textElement= getASTRewrite().getAST().newTextElement();
2182 String text= StubUtility.getTodoTaskTag(fCuRewrite.getCu().getJavaProject());
2183 if (text != null)
2184 textElement.setText(text); //TODO: use template with {@todo} ...
2185 excptNode.fragments().add(textElement);
2186
2187 return excptNode;
2188 }
2189
2190 public void insertTag(TagElement tag, TagElement previousTag, ListRewrite tagsRewrite) {
2191 if (previousTag == null)
2192 tagsRewrite.insertFirst(tag, fDescription);
2193 else
2194 tagsRewrite.insertAfter(tag, previousTag, fDescription);
2195 }
2196
2197 /**
2198 * @param tags existing tags
2199 * @param tagName name of tag to add
2200 * @return the <code>TagElement<code> just before a new <code>TagElement</code> with name <code>tagName</code>,
2201 * or <code>null</code>.
2202 */
2203 private TagElement findTagElementToInsertAfter(List<TagElement> tags, String tagName) {
2204 List<String> tagOrder= Arrays.asList(new String[] {
2205 TagElement.TAG_AUTHOR,
2206 TagElement.TAG_VERSION,
2207 TagElement.TAG_PARAM,
2208 TagElement.TAG_RETURN,
2209 TagElement.TAG_THROWS,
2210 TagElement.TAG_EXCEPTION,
2211 TagElement.TAG_SEE,
2212 TagElement.TAG_SINCE,
2213 TagElement.TAG_SERIAL,
2214 TagElement.TAG_SERIALFIELD,
2215 TagElement.TAG_SERIALDATA,
2216 TagElement.TAG_DEPRECATED,
2217 TagElement.TAG_VALUE
2218 });
2219 int goalOrdinal= tagOrder.indexOf(tagName);
2220 if (goalOrdinal == -1) // unknown tag -> to end
2221 return (tags.size() == 0) ? null : (TagElement) tags.get(tags.size());
2222 for (int i= 0; i < tags.size(); i++) {
2223 int tagOrdinal= tagOrder.indexOf(tags.get(i).getTagName());
2224 if (tagOrdinal >= goalOrdinal)
2225 return (i == 0) ? null : (TagElement) tags.get(i-1);
2226 }
2227 return (tags.size() == 0) ? null : (TagElement) tags.get(tags.size()-1);
2228 }
2229
2230 //TODO: already reported as compilation error -> don't report there?
2231 private void checkIfDeletedParametersUsed() {
2232 for (Iterator<ParameterInfo> iter= getDeletedInfos().iterator(); iter.hasNext();) {
2233 ParameterInfo info= iter.next();
2234 SingleVariableDeclaration paramDecl= (SingleVariableDeclaration) fMethDecl.parameters().get(info.getOldIndex());
2235 TempOccurrenceAnalyzer analyzer= new TempOccurrenceAnalyzer(paramDecl, false);
2236 analyzer.generated_7876152855956296739(paramDecl, DeclarationUpdate.this);
2237 }
2238 }
2239
2240 public String getFullTypeName(MethodDeclaration decl) {
2241 ASTNode node= decl;
2242 while (true) {
2243 node= node.getParent();
2244 if (node instanceof AbstractTypeDeclaration) {
2245 return ((AbstractTypeDeclaration) node).getName().getIdentifier();
2246 } else if (node instanceof ClassInstanceCreation) {
2247 ClassInstanceCreation cic= (ClassInstanceCreation) node;
2248 return Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_anonymous_subclass, BasicElementLabels.getJavaElementName(ASTNodes.asString(cic.getType())));
2249 } else if (node instanceof EnumConstantDeclaration) {
2250 EnumDeclaration ed= (EnumDeclaration) node.getParent();
2251 return Messages.format(RefactoringCoreMessages.ChangeSignatureRefactoring_anonymous_subclass, BasicElementLabels.getJavaElementName(ASTNodes.asString(ed.getName())));
2252 }
2253 }
2254 }
2255
2256 @Override
2257 protected SingleVariableDeclaration createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<SingleVariableDeclaration> nodes) {
2258 return createNewSingleVariableDeclaration(info);
2259 }
2260
2261 private SingleVariableDeclaration createNewSingleVariableDeclaration(ParameterInfo info) {
2262 SingleVariableDeclaration newP= info.generated_5313258361311384693(DeclarationUpdate.this);
2263 return newP;
2264 }
2265
2266 @Override
2267 protected SimpleName getMethodNameNode() {
2268 return fMethDecl.getName();
2269 }
2270
2271 }
2272
2273 public class DocReferenceUpdate extends OccurrenceUpdate<MethodRefParameter> {
2274 /** instanceof MemberRef || MethodRef */
2275 public ASTNode fNode;
2276
2277 protected DocReferenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
2278 super(cuRewrite, cuRewrite.createGroupDescription(RefactoringCoreMessages.ChangeSignatureRefactoring_update_javadoc_reference), result);
2279 fNode= node;
2280 }
2281
2282 @Override
2283 public void updateNode() {
2284 if (fNode instanceof MethodRef) {
2285 changeParamguments();
2286 reshuffleElements();
2287 }
2288 if (canChangeNameAndReturnType())
2289 changeMethodName();
2290 }
2291
2292 @Override
2293 protected MethodRefParameter createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<MethodRefParameter> nodes) {
2294 return createNewMethodRefParameter(info);
2295 }
2296
2297 private MethodRefParameter createNewMethodRefParameter(ParameterInfo info) {
2298 MethodRefParameter newP= getASTRewrite().getAST().newMethodRefParameter();
2299
2300 // only add name iff first parameter already has a name:
2301 List<? extends ASTNode> parameters= getParamgumentsRewrite().getOriginalList();
2302 info.generated_5231910928367892209(DocReferenceUpdate.this, newP, parameters);
2303 return newP;
2304 }
2305
2306 public Type createNewDocRefType(ParameterInfo info) {
2307 return info.generated_1237834770889977205(DocReferenceUpdate.this);
2308 }
2309
2310 @Override
2311 protected SimpleName getMethodNameNode() {
2312 if (fNode instanceof MemberRef)
2313 return ((MemberRef) fNode).getName();
2314
2315 if (fNode instanceof MethodRef)
2316 return ((MethodRef) fNode).getName();
2317
2318 return null;
2319 }
2320
2321 /** @return {@inheritDoc} (element type: MethodRefParameter) */
2322 @Override
2323 protected ListRewrite getParamgumentsRewrite() {
2324 return getASTRewrite().getListRewrite(fNode, MethodRef.PARAMETERS_PROPERTY);
2325 }
2326
2327 @Override
2328 protected void changeParamgumentName(ParameterInfo info) {
2329 info.generated_4770463881283348118(DocReferenceUpdate.this);
2330 }
2331
2332 @Override
2333 protected void changeParamgumentType(ParameterInfo info) {
2334 if (! (fNode instanceof MethodRef))
2335 return;
2336
2337 Type oldTypeNode= info.generated_6550062184257611391(DocReferenceUpdate.this);
2338 registerImportRemoveNode(oldTypeNode);
2339 }
2340 }
2341
2342 class StaticImportUpdate extends OccurrenceUpdate<ASTNode> {
2343
2344 private final ImportDeclaration fImportDecl;
2345
2346 public StaticImportUpdate(ImportDeclaration importDecl, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
2347 super(cuRewrite, null, result);
2348 fImportDecl= importDecl;
2349 }
2350
2351 @Override
2352 public void updateNode() throws JavaModelException {
2353 ImportRewrite importRewrite= fCuRewrite.getImportRewrite();
2354 QualifiedName name= (QualifiedName) fImportDecl.getName();
2355 //will be removed by importRemover if not used elsewhere ... importRewrite.removeStaticImport(name.getFullyQualifiedName());
2356 importRewrite.addStaticImport(name.getQualifier().getFullyQualifiedName(), fMethodName, false);
2357 }
2358
2359 @Override
2360 protected ListRewrite getParamgumentsRewrite() {
2361 return null;
2362 }
2363
2364 @Override
2365 protected ASTNode createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<ASTNode> nodes) {
2366 return null;
2367 }
2368
2369 @Override
2370 protected SimpleName getMethodNameNode() {
2371 return null;
2372 }
2373 }
2374
2375 class NullOccurrenceUpdate extends OccurrenceUpdate<ASTNode> {
2376 ASTNode fNode;
2377 protected NullOccurrenceUpdate(ASTNode node, CompilationUnitRewrite cuRewrite, RefactoringStatus result) {
2378 super(cuRewrite, null, result);
2379 fNode= node;
2380 }
2381 @Override
2382 public void updateNode() throws JavaModelException {
2383 int start= fNode.getStartPosition();
2384 fCuRewrite.generated_3597592135106011143(this, start);
2385 }
2386 @Override
2387 protected ListRewrite getParamgumentsRewrite() {
2388 return null;
2389 }
2390 @Override
2391 protected ASTNode createNewParamgument(ParameterInfo info, List<ParameterInfo> parameterInfos, List<ASTNode> nodes) {
2392 return null;
2393 }
2394 @Override
2395 protected SimpleName getMethodNameNode() {
2396 return null;
2397 }
2398 }
2399
2400 private RefactoringStatus initialize(JavaRefactoringArguments arguments) {
2401 return arguments.generated_7739884842264948662(this);
2402 }
2403
2404 /**
2405 * If this occurrence update is called from within a declaration update
2406 * (i.e., to update the call inside the newly created delegate), the old
2407 * node does not yet exist and therefore cannot be a move target.
2408 *
2409 * Normally, always use createMoveTarget as this has the advantage of
2410 * being able to add changes inside changed nodes (for example, a method
2411 * call within a method call, see test case #4) and preserving comments
2412 * inside calls.
2413 * @param oldNode original node
2414 * @param rewrite an AST rewrite
2415 * @return the node to insert at the target location
2416 */
2417 protected <T extends ASTNode> T moveNode(T oldNode, ASTRewrite rewrite) {
2418 T movedNode;
2419 if (ASTNodes.isExistingNode(oldNode))
2420 movedNode= (T) rewrite.createMoveTarget(oldNode); //node must be one of ast
2421 else
2422 movedNode= (T) ASTNode.copySubtree(rewrite.getAST(), oldNode);
2423 return movedNode;
2424 }
2425
2426 public IDefaultValueAdvisor getDefaultValueAdvisor() {
2427 return fDefaultValueAdvisor;
2428 }
2429
2430 public void setDefaultValueAdvisor(IDefaultValueAdvisor defaultValueAdvisor) {
2431 fDefaultValueAdvisor= defaultValueAdvisor;
2432 }
2433
2434 @Override
2435 public Object[] getElements() {
2436 return new Object[] { fMethod };
2437 }
2438
2439 @Override
2440 public String getIdentifier() {
2441 return IRefactoringProcessorIds.CHANGE_METHOD_SIGNATURE_PROCESSOR;
2442 }
2443
2444 @Override
2445 public boolean isApplicable() throws CoreException {
2446 return RefactoringAvailabilityTester.isChangeSignatureAvailable(fMethod);
2447 }
2448
2449 @Override
2450 public RefactoringParticipant[] loadParticipants(RefactoringStatus status, SharableParticipants sharedParticipants) throws CoreException {
2451 String[] affectedNatures= JavaProcessors.computeAffectedNatures(fMethod);
2452 return JavaParticipantManager.loadChangeMethodSignatureParticipants(status, this, fMethod, getParticipantArguments(), null, affectedNatures, sharedParticipants);
2453 }
2454
2455 public void generated_6776289915833737591(final ChangeSignatureInputPage changesignatureinputpage) {
2456 changesignatureinputpage.fDeprecateDelegateCheckBox.setSelection(DelegateUIHelper.loadDeprecateDelegateSetting(this));
2457 setDeprecateDelegates(changesignatureinputpage.fDeprecateDelegateCheckBox.getSelection());
2458 changesignatureinputpage.fDeprecateDelegateCheckBox.addSelectionListener(new SelectionAdapter() {
2459 @Override
2460 public void widgetSelected(SelectionEvent e) {
2461 setDeprecateDelegates(changesignatureinputpage.fDeprecateDelegateCheckBox.getSelection());
2462 }
2463 });
2464 changesignatureinputpage.fDeprecateDelegateCheckBox.setEnabled(changesignatureinputpage.fLeaveDelegateCheckBox.getSelection());
2465 }
2466
2467 public void generated_260053480955835230(IntroduceParameterObjectInputPage introduceparameterobjectinputpage) {
2468 introduceparameterobjectinputpage.fDeprecateDelegateCheckBox.setSelection(DelegateUIHelper.loadDeprecateDelegateSetting(this));
2469 setDeprecateDelegates(introduceparameterobjectinputpage.fDeprecateDelegateCheckBox.getSelection());
2470 }
2471
2472 public IntroduceParameterDescriptor generated_8156777813229824559(IntroduceParameterRefactoring introduceparameterrefactoring, ChangeMethodSignatureDescriptor extended, final Map<String, String> arguments) {
2473 String signature= getMethodName();
2474 try {
2475 signature= getOldMethodSignature();
2476 } catch (JavaModelException exception) {
2477 JavaPlugin.log(exception);
2478 }
2479 final String description= Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_descriptor_description_short, BasicElementLabels.getJavaElementName(getMethod().getElementName()));
2480 final String header= Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_descriptor_description, new String[] { BasicElementLabels.getJavaElementName(introduceparameterrefactoring.fParameter.getNewName()), signature, BasicElementLabels.getJavaCodeString(ASTNodes.asString(introduceparameterrefactoring.fSelectedExpression))});
2481 final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(extended.getProject(), introduceparameterrefactoring, header);
2482 comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_original_pattern, JavaElementLabels.getTextLabel(getMethod(),
2483 JavaElementLabels.ALL_FULLY_QUALIFIED)));
2484 comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_expression_pattern, BasicElementLabels.getJavaCodeString(ASTNodes.asString(introduceparameterrefactoring.fSelectedExpression))));
2485 comment.addSetting(Messages.format(RefactoringCoreMessages.IntroduceParameterRefactoring_parameter_pattern, BasicElementLabels.getJavaElementName(introduceparameterrefactoring.getAddedParameterInfo().getNewName())));
2486 return RefactoringSignatureDescriptorFactory.createIntroduceParameterDescriptor(extended.getProject(), description, comment.asString(), arguments, extended.getFlags());
2487 }
2488}