]>
Commit | Line | Data |
---|---|---|
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 | *******************************************************************************/ | |
11 | package org.eclipse.jdt.internal.corext.refactoring.structure; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.Arrays; | |
15 | import java.util.HashMap; | |
16 | import java.util.HashSet; | |
17 | import java.util.Iterator; | |
18 | import java.util.LinkedHashMap; | |
19 | import java.util.List; | |
20 | import java.util.Map; | |
21 | import java.util.Set; | |
22 | ||
23 | import org.eclipse.swt.events.SelectionAdapter; | |
24 | import org.eclipse.swt.events.SelectionEvent; | |
25 | ||
26 | import org.eclipse.core.runtime.Assert; | |
27 | import org.eclipse.core.runtime.CoreException; | |
28 | import org.eclipse.core.runtime.IProgressMonitor; | |
29 | import org.eclipse.core.runtime.NullProgressMonitor; | |
30 | import org.eclipse.core.runtime.OperationCanceledException; | |
31 | import org.eclipse.core.runtime.SubProgressMonitor; | |
32 | ||
33 | import org.eclipse.core.resources.IFile; | |
34 | ||
35 | import org.eclipse.text.edits.TextEditGroup; | |
36 | ||
37 | import org.eclipse.ltk.core.refactoring.Change; | |
38 | import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; | |
39 | import org.eclipse.ltk.core.refactoring.RefactoringStatus; | |
40 | import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; | |
41 | import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; | |
42 | import org.eclipse.ltk.core.refactoring.TextChange; | |
43 | import org.eclipse.ltk.core.refactoring.participants.CheckConditionsContext; | |
44 | import org.eclipse.ltk.core.refactoring.participants.RefactoringParticipant; | |
45 | import org.eclipse.ltk.core.refactoring.participants.RefactoringProcessor; | |
46 | import org.eclipse.ltk.core.refactoring.participants.SharableParticipants; | |
47 | ||
48 | import org.eclipse.jdt.core.Flags; | |
49 | import org.eclipse.jdt.core.ICompilationUnit; | |
50 | import org.eclipse.jdt.core.IJavaElement; | |
51 | import org.eclipse.jdt.core.IJavaProject; | |
52 | import org.eclipse.jdt.core.IMethod; | |
53 | import org.eclipse.jdt.core.IType; | |
54 | import org.eclipse.jdt.core.ITypeHierarchy; | |
55 | import org.eclipse.jdt.core.JavaModelException; | |
56 | import org.eclipse.jdt.core.Signature; | |
57 | import org.eclipse.jdt.core.compiler.IProblem; | |
58 | import org.eclipse.jdt.core.dom.AST; | |
59 | import org.eclipse.jdt.core.dom.ASTNode; | |
60 | import org.eclipse.jdt.core.dom.ASTParser; | |
61 | import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; | |
62 | import org.eclipse.jdt.core.dom.Block; | |
63 | import org.eclipse.jdt.core.dom.BodyDeclaration; | |
64 | import org.eclipse.jdt.core.dom.ClassInstanceCreation; | |
65 | import org.eclipse.jdt.core.dom.CompilationUnit; | |
66 | import org.eclipse.jdt.core.dom.ConstructorInvocation; | |
67 | import org.eclipse.jdt.core.dom.EnumConstantDeclaration; | |
68 | import org.eclipse.jdt.core.dom.EnumDeclaration; | |
69 | import org.eclipse.jdt.core.dom.Expression; | |
70 | import org.eclipse.jdt.core.dom.IMethodBinding; | |
71 | import org.eclipse.jdt.core.dom.ITypeBinding; | |
72 | import org.eclipse.jdt.core.dom.ImportDeclaration; | |
73 | import org.eclipse.jdt.core.dom.Javadoc; | |
74 | import org.eclipse.jdt.core.dom.MemberRef; | |
75 | import org.eclipse.jdt.core.dom.MethodDeclaration; | |
76 | import org.eclipse.jdt.core.dom.MethodInvocation; | |
77 | import org.eclipse.jdt.core.dom.MethodRef; | |
78 | import org.eclipse.jdt.core.dom.MethodRefParameter; | |
79 | import org.eclipse.jdt.core.dom.Modifier; | |
80 | import org.eclipse.jdt.core.dom.Name; | |
81 | import org.eclipse.jdt.core.dom.NodeFinder; | |
82 | import org.eclipse.jdt.core.dom.PrimitiveType; | |
83 | import org.eclipse.jdt.core.dom.QualifiedName; | |
84 | import org.eclipse.jdt.core.dom.SimpleName; | |
85 | import org.eclipse.jdt.core.dom.SingleVariableDeclaration; | |
86 | import org.eclipse.jdt.core.dom.SuperConstructorInvocation; | |
87 | import org.eclipse.jdt.core.dom.SuperMethodInvocation; | |
88 | import org.eclipse.jdt.core.dom.TagElement; | |
89 | import org.eclipse.jdt.core.dom.TextElement; | |
90 | import org.eclipse.jdt.core.dom.Type; | |
91 | import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; | |
92 | import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; | |
93 | import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; | |
94 | import org.eclipse.jdt.core.dom.rewrite.ListRewrite; | |
95 | import org.eclipse.jdt.core.refactoring.descriptors.ChangeMethodSignatureDescriptor; | |
96 | import org.eclipse.jdt.core.refactoring.descriptors.IntroduceParameterDescriptor; | |
97 | import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; | |
98 | import org.eclipse.jdt.core.refactoring.participants.ChangeMethodSignatureArguments; | |
99 | import org.eclipse.jdt.core.refactoring.participants.ChangeMethodSignatureArguments.Parameter; | |
100 | import org.eclipse.jdt.core.refactoring.participants.ChangeMethodSignatureArguments.ThrownException; | |
101 | import org.eclipse.jdt.core.refactoring.participants.IRefactoringProcessorIds; | |
102 | import org.eclipse.jdt.core.refactoring.participants.JavaParticipantManager; | |
103 | import org.eclipse.jdt.core.search.IJavaSearchScope; | |
104 | import org.eclipse.jdt.core.search.MethodReferenceMatch; | |
105 | import org.eclipse.jdt.core.search.SearchMatch; | |
106 | import org.eclipse.jdt.core.search.SearchPattern; | |
107 | ||
108 | import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory; | |
109 | import org.eclipse.jdt.internal.corext.Corext; | |
110 | import org.eclipse.jdt.internal.corext.SourceRangeFactory; | |
111 | import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; | |
112 | import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; | |
113 | import org.eclipse.jdt.internal.corext.dom.ASTNodes; | |
114 | import org.eclipse.jdt.internal.corext.dom.Bindings; | |
115 | import org.eclipse.jdt.internal.corext.dom.ModifierRewrite; | |
116 | import org.eclipse.jdt.internal.corext.dom.Selection; | |
117 | import org.eclipse.jdt.internal.corext.dom.SelectionAnalyzer; | |
118 | import org.eclipse.jdt.internal.corext.refactoring.Checks; | |
119 | import org.eclipse.jdt.internal.corext.refactoring.CuCollectingSearchRequestor; | |
120 | import org.eclipse.jdt.internal.corext.refactoring.ExceptionInfo; | |
121 | import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; | |
122 | import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; | |
123 | import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil; | |
124 | import org.eclipse.jdt.internal.corext.refactoring.ParameterInfo; | |
125 | import org.eclipse.jdt.internal.corext.refactoring.RefactoringAvailabilityTester; | |
126 | import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; | |
127 | import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; | |
128 | import org.eclipse.jdt.internal.corext.refactoring.ReturnTypeInfo; | |
129 | import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; | |
130 | import org.eclipse.jdt.internal.corext.refactoring.StubTypeContext; | |
131 | import org.eclipse.jdt.internal.corext.refactoring.TypeContextChecker; | |
132 | import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; | |
133 | import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext; | |
134 | import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes; | |
135 | import org.eclipse.jdt.internal.corext.refactoring.base.ReferencesInBinaryContext; | |
136 | import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; | |
137 | import org.eclipse.jdt.internal.corext.refactoring.code.IntroduceParameterRefactoring; | |
138 | import org.eclipse.jdt.internal.corext.refactoring.code.Invocations; | |
139 | import org.eclipse.jdt.internal.corext.refactoring.delegates.DelegateMethodCreator; | |
140 | import org.eclipse.jdt.internal.corext.refactoring.participants.JavaProcessors; | |
141 | import org.eclipse.jdt.internal.corext.refactoring.rename.MethodChecks; | |
142 | import org.eclipse.jdt.internal.corext.refactoring.rename.RefactoringAnalyzeUtil; | |
143 | import org.eclipse.jdt.internal.corext.refactoring.rename.RippleMethodFinder2; | |
144 | import org.eclipse.jdt.internal.corext.refactoring.rename.TempOccurrenceAnalyzer; | |
145 | import org.eclipse.jdt.internal.corext.refactoring.tagging.IDelegateUpdating; | |
146 | import org.eclipse.jdt.internal.corext.refactoring.util.JavaElementUtil; | |
147 | import org.eclipse.jdt.internal.corext.refactoring.util.JavadocUtil; | |
148 | import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; | |
149 | import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; | |
150 | import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; | |
151 | import org.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer; | |
152 | import org.eclipse.jdt.internal.corext.util.JdtFlags; | |
153 | import org.eclipse.jdt.internal.corext.util.Messages; | |
154 | ||
155 | import org.eclipse.jdt.ui.JavaElementLabels; | |
156 | ||
157 | import org.eclipse.jdt.internal.ui.JavaPlugin; | |
158 | import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; | |
159 | import org.eclipse.jdt.internal.ui.refactoring.ChangeSignatureWizard.ChangeSignatureInputPage; | |
160 | import org.eclipse.jdt.internal.ui.refactoring.DelegateUIHelper; | |
161 | import org.eclipse.jdt.internal.ui.refactoring.IntroduceParameterObjectWizard.IntroduceParameterObjectInputPage; | |
162 | import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; | |
163 | ||
164 | ||
165 | public 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 | } |