]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 IBM Corporation and others. | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * IBM Corporation - initial API and implementation | |
10 | *******************************************************************************/ | |
11 | package org.eclipse.jdt.internal.corext.refactoring.code; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.HashMap; | |
15 | import java.util.HashSet; | |
16 | import java.util.Iterator; | |
17 | import java.util.List; | |
18 | import java.util.Map; | |
19 | import java.util.Set; | |
20 | import java.util.StringTokenizer; | |
21 | ||
22 | import org.eclipse.core.runtime.Assert; | |
23 | import org.eclipse.core.runtime.CoreException; | |
24 | import org.eclipse.core.runtime.IProgressMonitor; | |
25 | import org.eclipse.core.runtime.OperationCanceledException; | |
26 | import org.eclipse.core.runtime.SubProgressMonitor; | |
27 | ||
28 | import org.eclipse.text.edits.MalformedTreeException; | |
29 | import org.eclipse.text.edits.RangeMarker; | |
30 | import org.eclipse.text.edits.TextEdit; | |
31 | import org.eclipse.text.edits.TextEditGroup; | |
32 | ||
33 | import org.eclipse.jface.text.BadLocationException; | |
34 | import org.eclipse.jface.text.Document; | |
35 | import org.eclipse.jface.text.IDocument; | |
36 | import org.eclipse.jface.text.IRegion; | |
37 | import org.eclipse.jface.text.TextUtilities; | |
38 | ||
39 | import org.eclipse.ltk.core.refactoring.Change; | |
40 | import org.eclipse.ltk.core.refactoring.Refactoring; | |
41 | import org.eclipse.ltk.core.refactoring.RefactoringDescriptor; | |
42 | import org.eclipse.ltk.core.refactoring.RefactoringStatus; | |
43 | ||
44 | import org.eclipse.jdt.core.Flags; | |
45 | import org.eclipse.jdt.core.ICompilationUnit; | |
46 | import org.eclipse.jdt.core.IField; | |
47 | import org.eclipse.jdt.core.IJavaElement; | |
48 | import org.eclipse.jdt.core.IJavaProject; | |
49 | import org.eclipse.jdt.core.ISourceRange; | |
50 | import org.eclipse.jdt.core.JavaModelException; | |
51 | import org.eclipse.jdt.core.dom.AST; | |
52 | import org.eclipse.jdt.core.dom.ASTNode; | |
53 | import org.eclipse.jdt.core.dom.ASTParser; | |
54 | import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; | |
55 | import org.eclipse.jdt.core.dom.AnonymousClassDeclaration; | |
56 | import org.eclipse.jdt.core.dom.ArrayCreation; | |
57 | import org.eclipse.jdt.core.dom.ArrayInitializer; | |
58 | import org.eclipse.jdt.core.dom.ArrayType; | |
59 | import org.eclipse.jdt.core.dom.Assignment; | |
60 | import org.eclipse.jdt.core.dom.BodyDeclaration; | |
61 | import org.eclipse.jdt.core.dom.CastExpression; | |
62 | import org.eclipse.jdt.core.dom.CompilationUnit; | |
63 | import org.eclipse.jdt.core.dom.EnumConstantDeclaration; | |
64 | import org.eclipse.jdt.core.dom.Expression; | |
65 | import org.eclipse.jdt.core.dom.FieldAccess; | |
66 | import org.eclipse.jdt.core.dom.FieldDeclaration; | |
67 | import org.eclipse.jdt.core.dom.IBinding; | |
68 | import org.eclipse.jdt.core.dom.IMethodBinding; | |
69 | import org.eclipse.jdt.core.dom.ITypeBinding; | |
70 | import org.eclipse.jdt.core.dom.IVariableBinding; | |
71 | import org.eclipse.jdt.core.dom.ImportDeclaration; | |
72 | import org.eclipse.jdt.core.dom.MethodInvocation; | |
73 | import org.eclipse.jdt.core.dom.Modifier; | |
74 | import org.eclipse.jdt.core.dom.Name; | |
75 | import org.eclipse.jdt.core.dom.NodeFinder; | |
76 | import org.eclipse.jdt.core.dom.ParenthesizedExpression; | |
77 | import org.eclipse.jdt.core.dom.QualifiedName; | |
78 | import org.eclipse.jdt.core.dom.SimpleName; | |
79 | import org.eclipse.jdt.core.dom.SingleVariableDeclaration; | |
80 | import org.eclipse.jdt.core.dom.Type; | |
81 | import org.eclipse.jdt.core.dom.TypeDeclarationStatement; | |
82 | import org.eclipse.jdt.core.dom.VariableDeclaration; | |
83 | import org.eclipse.jdt.core.dom.VariableDeclarationFragment; | |
84 | import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; | |
85 | import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; | |
86 | import org.eclipse.jdt.core.dom.rewrite.ListRewrite; | |
87 | import org.eclipse.jdt.core.refactoring.CompilationUnitChange; | |
88 | import org.eclipse.jdt.core.refactoring.IJavaRefactorings; | |
89 | import org.eclipse.jdt.core.refactoring.descriptors.InlineConstantDescriptor; | |
90 | import org.eclipse.jdt.core.refactoring.descriptors.JavaRefactoringDescriptor; | |
91 | import org.eclipse.jdt.core.search.IJavaSearchConstants; | |
92 | import org.eclipse.jdt.core.search.SearchMatch; | |
93 | import org.eclipse.jdt.core.search.SearchPattern; | |
94 | ||
95 | import org.eclipse.jdt.internal.core.refactoring.descriptors.RefactoringSignatureDescriptorFactory; | |
96 | import org.eclipse.jdt.internal.corext.Corext; | |
97 | import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; | |
98 | import org.eclipse.jdt.internal.corext.codemanipulation.ImportReferencesCollector; | |
99 | import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; | |
100 | import org.eclipse.jdt.internal.corext.dom.ASTNodes; | |
101 | import org.eclipse.jdt.internal.corext.dom.HierarchicalASTVisitor; | |
102 | import org.eclipse.jdt.internal.corext.dom.NecessaryParenthesesChecker; | |
103 | import org.eclipse.jdt.internal.corext.dom.fragments.ASTFragmentFactory; | |
104 | import org.eclipse.jdt.internal.corext.dom.fragments.IExpressionFragment; | |
105 | import org.eclipse.jdt.internal.corext.refactoring.Checks; | |
106 | import org.eclipse.jdt.internal.corext.refactoring.IRefactoringSearchRequestor; | |
107 | import org.eclipse.jdt.internal.corext.refactoring.JDTRefactoringDescriptorComment; | |
108 | import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringArguments; | |
109 | import org.eclipse.jdt.internal.corext.refactoring.JavaRefactoringDescriptorUtil; | |
110 | import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; | |
111 | import org.eclipse.jdt.internal.corext.refactoring.RefactoringScopeFactory; | |
112 | import org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine2; | |
113 | import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; | |
114 | import org.eclipse.jdt.internal.corext.refactoring.base.RefactoringStatusCodes; | |
115 | import org.eclipse.jdt.internal.corext.refactoring.changes.DynamicValidationRefactoringChange; | |
116 | import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil; | |
117 | import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite; | |
118 | import org.eclipse.jdt.internal.corext.refactoring.util.ResourceUtil; | |
119 | import org.eclipse.jdt.internal.corext.refactoring.util.TightSourceRangeComputer; | |
120 | import org.eclipse.jdt.internal.corext.util.JavaModelUtil; | |
121 | import org.eclipse.jdt.internal.corext.util.Messages; | |
122 | import org.eclipse.jdt.internal.corext.util.Strings; | |
123 | ||
124 | import org.eclipse.jdt.ui.JavaElementLabels; | |
125 | ||
126 | import org.eclipse.jdt.internal.ui.JavaPlugin; | |
127 | import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; | |
128 | ||
129 | public class InlineConstantRefactoring extends Refactoring { | |
130 | ||
131 | private static final String ATTRIBUTE_REPLACE= "replace"; //$NON-NLS-1$ | |
132 | private static final String ATTRIBUTE_REMOVE= "remove"; //$NON-NLS-1$ | |
133 | ||
134 | private static class InlineTargetCompilationUnit { | |
135 | ||
136 | private static class InitializerTraversal extends HierarchicalASTVisitor { | |
137 | ||
138 | private static boolean areInSameType(ASTNode one, ASTNode other) { | |
139 | ASTNode onesContainer= getContainingTypeDeclaration(one); | |
140 | ASTNode othersContainer= getContainingTypeDeclaration(other); | |
141 | ||
142 | if (onesContainer == null || othersContainer == null) | |
143 | return false; | |
144 | ||
145 | ITypeBinding onesContainerBinding= getTypeBindingForTypeDeclaration(onesContainer); | |
146 | ITypeBinding othersContainerBinding= getTypeBindingForTypeDeclaration(othersContainer); | |
147 | ||
148 | Assert.isNotNull(onesContainerBinding); | |
149 | Assert.isNotNull(othersContainerBinding); | |
150 | ||
151 | String onesKey= onesContainerBinding.getKey(); | |
152 | String othersKey= othersContainerBinding.getKey(); | |
153 | ||
154 | if (onesKey == null || othersKey == null) | |
155 | return false; | |
156 | ||
157 | return onesKey.equals(othersKey); | |
158 | } | |
159 | ||
160 | private static boolean isStaticAccess(SimpleName memberName) { | |
161 | IBinding binding= memberName.resolveBinding(); | |
162 | Assert.isTrue(binding instanceof IVariableBinding || binding instanceof IMethodBinding || binding instanceof ITypeBinding); | |
163 | ||
164 | if (binding instanceof ITypeBinding) | |
165 | return true; | |
166 | ||
167 | if (binding instanceof IVariableBinding) | |
168 | return ((IVariableBinding) binding).isField(); | |
169 | ||
170 | int modifiers= binding.getModifiers(); | |
171 | return Modifier.isStatic(modifiers); | |
172 | } | |
173 | ||
174 | private static ASTNode getContainingTypeDeclaration(ASTNode node) { | |
175 | while (node != null && !(node instanceof AbstractTypeDeclaration) && !(node instanceof AnonymousClassDeclaration)) { | |
176 | node= node.getParent(); | |
177 | } | |
178 | return node; | |
179 | } | |
180 | ||
181 | private static ITypeBinding getTypeBindingForTypeDeclaration(ASTNode declaration) { | |
182 | if (declaration instanceof AnonymousClassDeclaration) | |
183 | return ((AnonymousClassDeclaration) declaration).resolveBinding(); | |
184 | ||
185 | if (declaration instanceof AbstractTypeDeclaration) | |
186 | return ((AbstractTypeDeclaration) declaration).resolveBinding(); | |
187 | ||
188 | Assert.isTrue(false); | |
189 | return null; | |
190 | } | |
191 | ||
192 | private final Expression fInitializer; | |
193 | private ASTRewrite fInitializerRewrite; | |
194 | private final HashSet<SimpleName> fStaticImportsInInitializer2; | |
195 | ||
196 | // cache: | |
197 | private Set<String> fNamesDeclaredLocallyAtNewLocation; | |
198 | ||
199 | private final Expression fNewLocation; | |
200 | private final HashSet<SimpleName> fStaticImportsInReference; | |
201 | private final CompilationUnitRewrite fNewLocationCuRewrite; | |
202 | private final ImportRewriteContext fNewLocationContext; | |
203 | ||
204 | public InitializerTraversal(Expression initializer, HashSet<SimpleName> staticImportsInInitializer, Expression newLocation, HashSet<SimpleName> staticImportsInReference, CompilationUnitRewrite newLocationCuRewrite) { | |
205 | fInitializer= initializer; | |
206 | fInitializerRewrite= ASTRewrite.create(initializer.getAST()); | |
207 | fStaticImportsInInitializer2= staticImportsInInitializer; | |
208 | ||
209 | fNewLocation= newLocation; | |
210 | fStaticImportsInReference= staticImportsInReference; | |
211 | fNewLocationCuRewrite= newLocationCuRewrite; | |
212 | fNewLocationContext= new ContextSensitiveImportRewriteContext(fNewLocation, fNewLocationCuRewrite.getImportRewrite()); | |
213 | ||
214 | perform(initializer); | |
215 | } | |
216 | ||
217 | /** | |
218 | * @param scope not a TypeDeclaration | |
219 | * @return Set containing Strings representing simple names | |
220 | */ | |
221 | private Set<String> getLocallyDeclaredNames(BodyDeclaration scope) { | |
222 | Assert.isTrue(!(scope instanceof AbstractTypeDeclaration)); | |
223 | ||
224 | final Set<String> result= new HashSet<String>(); | |
225 | ||
226 | if (scope instanceof FieldDeclaration) | |
227 | return result; | |
228 | ||
229 | scope.accept(new HierarchicalASTVisitor() { | |
230 | ||
231 | @Override | |
232 | public boolean visit(AbstractTypeDeclaration node) { | |
233 | Assert.isTrue(node.getParent() instanceof TypeDeclarationStatement); | |
234 | ||
235 | result.add(node.getName().getIdentifier()); | |
236 | return false; | |
237 | } | |
238 | ||
239 | @Override | |
240 | public boolean visit(AnonymousClassDeclaration anonDecl) { | |
241 | return false; | |
242 | } | |
243 | ||
244 | @Override | |
245 | public boolean visit(VariableDeclaration varDecl) { | |
246 | result.add(varDecl.getName().getIdentifier()); | |
247 | return false; | |
248 | } | |
249 | }); | |
250 | return result; | |
251 | } | |
252 | ||
253 | public ASTRewrite getInitializerRewrite() { | |
254 | return fInitializerRewrite; | |
255 | } | |
256 | ||
257 | private void perform(Expression initializer) { | |
258 | initializer.accept(this); | |
259 | addExplicitTypeArgumentsIfNecessary(initializer); | |
260 | } | |
261 | ||
262 | private void addExplicitTypeArgumentsIfNecessary(Expression invocation) { | |
263 | if (Invocations.isResolvedTypeInferredFromExpectedType(invocation)) { | |
264 | ASTNode referenceContext= fNewLocation.getParent(); | |
265 | if (! (referenceContext instanceof VariableDeclarationFragment | |
266 | || referenceContext instanceof SingleVariableDeclaration | |
267 | || referenceContext instanceof Assignment)) { | |
268 | ITypeBinding[] typeArguments= Invocations.getInferredTypeArguments(invocation); | |
269 | ListRewrite typeArgsRewrite= Invocations.getInferredTypeArgumentsRewrite(fInitializerRewrite, invocation); | |
270 | for (int i= 0; i < typeArguments.length; i++) { | |
271 | Type typeArgument= fNewLocationCuRewrite.getImportRewrite().addImport(typeArguments[i], fNewLocationCuRewrite.getAST(), fNewLocationContext); | |
272 | fNewLocationCuRewrite.getImportRemover().registerAddedImports(typeArgument); | |
273 | typeArgsRewrite.insertLast(typeArgument, null); | |
274 | } | |
275 | ||
276 | if (invocation instanceof MethodInvocation) { | |
277 | MethodInvocation methodInvocation= (MethodInvocation) invocation; | |
278 | Expression expression= methodInvocation.getExpression(); | |
279 | if (expression == null) { | |
280 | IMethodBinding methodBinding= methodInvocation.resolveMethodBinding(); | |
281 | if (methodBinding != null) { | |
282 | expression= fNewLocationCuRewrite.getAST().newName(fNewLocationCuRewrite.getImportRewrite().addImport(methodBinding.getDeclaringClass().getTypeDeclaration(), fNewLocationContext)); | |
283 | fInitializerRewrite.set(invocation, MethodInvocation.EXPRESSION_PROPERTY, expression, null); | |
284 | } | |
285 | } | |
286 | } | |
287 | } | |
288 | } | |
289 | } | |
290 | ||
291 | @Override | |
292 | public boolean visit(FieldAccess fieldAccess) { | |
293 | fieldAccess.getExpression().accept(this); | |
294 | return false; | |
295 | } | |
296 | ||
297 | @Override | |
298 | public boolean visit(MethodInvocation invocation) { | |
299 | if (invocation.getExpression() == null) | |
300 | qualifyUnqualifiedMemberNameIfNecessary(invocation.getName()); | |
301 | else | |
302 | invocation.getExpression().accept(this); | |
303 | ||
304 | for (Iterator<Expression> it= invocation.arguments().iterator(); it.hasNext();) | |
305 | it.next().accept(this); | |
306 | ||
307 | return false; | |
308 | } | |
309 | ||
310 | @Override | |
311 | public boolean visit(Name name) { | |
312 | SimpleName leftmost= getLeftmost(name); | |
313 | ||
314 | IBinding leftmostBinding= leftmost.resolveBinding(); | |
315 | if (leftmostBinding instanceof IVariableBinding || leftmostBinding instanceof IMethodBinding || leftmostBinding instanceof ITypeBinding) { | |
316 | if (shouldUnqualify(leftmost)) | |
317 | unqualifyMemberName(leftmost); | |
318 | else | |
319 | qualifyUnqualifiedMemberNameIfNecessary(leftmost); | |
320 | } | |
321 | ||
322 | if (leftmostBinding instanceof ITypeBinding) { | |
323 | String addedImport= fNewLocationCuRewrite.getImportRewrite().addImport((ITypeBinding)leftmostBinding, fNewLocationContext); | |
324 | fNewLocationCuRewrite.getImportRemover().registerAddedImport(addedImport); | |
325 | } | |
326 | ||
327 | return false; | |
328 | } | |
329 | ||
330 | private void qualifyUnqualifiedMemberNameIfNecessary(SimpleName memberName) { | |
331 | if (shouldQualify(memberName)) | |
332 | qualifyMemberName(memberName); | |
333 | } | |
334 | ||
335 | private boolean shouldUnqualify(SimpleName memberName) { | |
336 | if (areInSameType(memberName, fNewLocation)) | |
337 | return ! mayBeShadowedByLocalDeclaration(memberName); | |
338 | ||
339 | return false; | |
340 | } | |
341 | ||
342 | private void unqualifyMemberName(SimpleName memberName) { | |
343 | if (doesParentQualify(memberName)) | |
344 | fInitializerRewrite.replace(memberName.getParent(), memberName, null); | |
345 | } | |
346 | ||
347 | private boolean shouldQualify(SimpleName memberName) { | |
348 | if (! areInSameType(fInitializer, fNewLocation)) | |
349 | return true; | |
350 | ||
351 | return mayBeShadowedByLocalDeclaration(memberName); | |
352 | } | |
353 | ||
354 | private boolean mayBeShadowedByLocalDeclaration(SimpleName memberName) { | |
355 | return getNamesDeclaredLocallyAtNewLocation().contains(memberName.getIdentifier()); | |
356 | } | |
357 | ||
358 | private Set<String> getNamesDeclaredLocallyAtNewLocation() { | |
359 | if (fNamesDeclaredLocallyAtNewLocation != null) | |
360 | return fNamesDeclaredLocallyAtNewLocation; | |
361 | ||
362 | BodyDeclaration enclosingBodyDecl= (BodyDeclaration) ASTNodes.getParent(fNewLocation, BodyDeclaration.class); | |
363 | Assert.isTrue(!(enclosingBodyDecl instanceof AbstractTypeDeclaration)); | |
364 | ||
365 | return fNamesDeclaredLocallyAtNewLocation= getLocallyDeclaredNames(enclosingBodyDecl); | |
366 | } | |
367 | ||
368 | private void qualifyMemberName(SimpleName memberName) { | |
369 | if (isStaticAccess(memberName)) { | |
370 | IBinding memberBinding= memberName.resolveBinding(); | |
371 | ||
372 | if (memberBinding instanceof IVariableBinding || memberBinding instanceof IMethodBinding) { | |
373 | if (fStaticImportsInReference.contains(fNewLocation)) { // use static import if reference location used static import | |
374 | importStatically(memberName, memberBinding); | |
375 | return; | |
376 | } else if (fStaticImportsInInitializer2.contains(memberName)) { // use static import if already imported statically in initializer | |
377 | importStatically(memberName, memberBinding); | |
378 | return; | |
379 | } | |
380 | } | |
381 | qualifyToTopLevelClass(memberName); //otherwise: qualify and import non-static | |
382 | } | |
383 | } | |
384 | ||
385 | private void importStatically(SimpleName toImport, IBinding binding) { | |
386 | String newName= fNewLocationCuRewrite.getImportRewrite().addStaticImport(binding); | |
387 | fNewLocationCuRewrite.getImportRemover().registerAddedStaticImport(binding); | |
388 | ||
389 | Name newReference= ASTNodeFactory.newName(fInitializerRewrite.getAST(), newName); | |
390 | fInitializerRewrite.replace(toImport, newReference, null); | |
391 | } | |
392 | ||
393 | private void qualifyToTopLevelClass(SimpleName toQualify) { | |
394 | ITypeBinding declaringClass= getDeclaringClassBinding(toQualify); | |
395 | if (declaringClass == null) | |
396 | return; | |
397 | ||
398 | Type newQualification= fNewLocationCuRewrite.getImportRewrite().addImport(declaringClass, fInitializerRewrite.getAST(), fNewLocationContext); | |
399 | fNewLocationCuRewrite.getImportRemover().registerAddedImports(newQualification); | |
400 | ||
401 | SimpleName newToQualify= (SimpleName) fInitializerRewrite.createMoveTarget(toQualify); | |
402 | Type newType= fInitializerRewrite.getAST().newQualifiedType(newQualification, newToQualify); | |
403 | fInitializerRewrite.replace(toQualify, newType, null); | |
404 | } | |
405 | ||
406 | private static ITypeBinding getDeclaringClassBinding(SimpleName memberName) { | |
407 | ||
408 | IBinding binding= memberName.resolveBinding(); | |
409 | if (binding instanceof IMethodBinding) | |
410 | return ((IMethodBinding) binding).getDeclaringClass(); | |
411 | ||
412 | if (binding instanceof IVariableBinding) | |
413 | return ((IVariableBinding) binding).getDeclaringClass(); | |
414 | ||
415 | if (binding instanceof ITypeBinding) | |
416 | return ((ITypeBinding) binding).getDeclaringClass(); | |
417 | ||
418 | Assert.isTrue(false); | |
419 | return null; | |
420 | ||
421 | } | |
422 | ||
423 | } | |
424 | ||
425 | private final Expression fInitializer; | |
426 | private final ICompilationUnit fInitializerUnit; | |
427 | private final VariableDeclarationFragment fOriginalDeclaration; | |
428 | ||
429 | /** The references in this compilation unit, represented as AST Nodes in the parsed representation of the compilation unit */ | |
430 | private final Expression[] fReferences; | |
431 | private final VariableDeclarationFragment fDeclarationToRemove; | |
432 | private final CompilationUnitRewrite fCuRewrite; | |
433 | private final TightSourceRangeComputer fSourceRangeComputer; | |
434 | private final HashSet<SimpleName> fStaticImportsInInitializer; | |
435 | private final boolean fIs15; | |
436 | ||
437 | private InlineTargetCompilationUnit(CompilationUnitRewrite cuRewrite, Name[] references, InlineConstantRefactoring refactoring, HashSet<SimpleName> staticImportsInInitializer) { | |
438 | fInitializer= refactoring.getInitializer(); | |
439 | fInitializerUnit= refactoring.getDeclaringCompilationUnit(); | |
440 | ||
441 | fCuRewrite= cuRewrite; | |
442 | fSourceRangeComputer= new TightSourceRangeComputer(); | |
443 | fCuRewrite.getASTRewrite().setTargetSourceRangeComputer(fSourceRangeComputer); | |
444 | if (refactoring.getRemoveDeclaration() && refactoring.getReplaceAllReferences() && cuRewrite.getCu().equals(fInitializerUnit)) | |
445 | fDeclarationToRemove= refactoring.getDeclaration(); | |
446 | else | |
447 | fDeclarationToRemove= null; | |
448 | ||
449 | fOriginalDeclaration= refactoring.getDeclaration(); | |
450 | ||
451 | fReferences= new Expression[references.length]; | |
452 | for (int i= 0; i < references.length; i++) | |
453 | fReferences[i]= getQualifiedReference(references[i]); | |
454 | ||
455 | fIs15= JavaModelUtil.is50OrHigher(cuRewrite.getCu().getJavaProject()); | |
456 | fStaticImportsInInitializer= fIs15 ? staticImportsInInitializer : new HashSet<SimpleName>(0); | |
457 | } | |
458 | ||
459 | private static Expression getQualifiedReference(Name fieldName) { | |
460 | if (doesParentQualify(fieldName)) | |
461 | return (Expression) fieldName.getParent(); | |
462 | ||
463 | return fieldName; | |
464 | } | |
465 | ||
466 | private static boolean doesParentQualify(Name fieldName) { | |
467 | ASTNode parent= fieldName.getParent(); | |
468 | Assert.isNotNull(parent); | |
469 | ||
470 | if (parent instanceof FieldAccess && ((FieldAccess) parent).getName() == fieldName) | |
471 | return true; | |
472 | ||
473 | if (parent instanceof QualifiedName && ((QualifiedName) parent).getName() == fieldName) | |
474 | return true; | |
475 | ||
476 | if (parent instanceof MethodInvocation && ((MethodInvocation) parent).getName() == fieldName) | |
477 | return true; | |
478 | ||
479 | return false; | |
480 | } | |
481 | ||
482 | public CompilationUnitChange getChange() throws CoreException { | |
483 | for (int i= 0; i < fReferences.length; i++) | |
484 | inlineReference(fReferences[i]); | |
485 | ||
486 | removeConstantDeclarationIfNecessary(); | |
487 | ||
488 | return fCuRewrite.createChange(true); | |
489 | } | |
490 | ||
491 | private void inlineReference(Expression reference) throws CoreException { | |
492 | ASTNode importDecl= ASTNodes.getParent(reference, ImportDeclaration.class); | |
493 | if (importDecl != null) { | |
494 | fCuRewrite.getImportRemover().registerInlinedStaticImport((ImportDeclaration) importDecl); | |
495 | return; | |
496 | } | |
497 | ||
498 | String modifiedInitializer= prepareInitializerForLocation(reference); | |
499 | if (modifiedInitializer == null) | |
500 | return; | |
501 | ||
502 | TextEditGroup msg= fCuRewrite.createGroupDescription(RefactoringCoreMessages.InlineConstantRefactoring_Inline); | |
503 | ||
504 | Expression newReference; | |
505 | boolean isStringPlaceholder= false; | |
506 | ||
507 | AST ast= fCuRewrite.getAST(); | |
508 | ITypeBinding explicitCast= ASTNodes.getExplicitCast(fInitializer, reference); | |
509 | if (explicitCast != null) { | |
510 | CastExpression cast= ast.newCastExpression(); | |
511 | Expression modifiedInitializerExpr= (Expression) fCuRewrite.getASTRewrite().createStringPlaceholder(modifiedInitializer, reference.getNodeType()); | |
512 | if (NecessaryParenthesesChecker.needsParentheses(fInitializer, cast, CastExpression.EXPRESSION_PROPERTY)) { | |
513 | ParenthesizedExpression parenthesized= ast.newParenthesizedExpression(); | |
514 | parenthesized.setExpression(modifiedInitializerExpr); | |
515 | modifiedInitializerExpr= parenthesized; | |
516 | } | |
517 | cast.setExpression(modifiedInitializerExpr); | |
518 | ImportRewriteContext context= new ContextSensitiveImportRewriteContext(reference, fCuRewrite.getImportRewrite()); | |
519 | cast.setType(fCuRewrite.getImportRewrite().addImport(explicitCast, ast, context)); | |
520 | newReference= cast; | |
521 | ||
522 | } else if (fInitializer instanceof ArrayInitializer) { | |
523 | ArrayCreation arrayCreation= ast.newArrayCreation(); | |
524 | ArrayType arrayType= (ArrayType) ASTNodeFactory.newType(ast, fOriginalDeclaration); | |
525 | arrayCreation.setType(arrayType); | |
526 | ||
527 | ArrayInitializer newArrayInitializer= (ArrayInitializer) fCuRewrite.getASTRewrite().createStringPlaceholder(modifiedInitializer, | |
528 | ASTNode.ARRAY_INITIALIZER); | |
529 | arrayCreation.setInitializer(newArrayInitializer); | |
530 | newReference= arrayCreation; | |
531 | ||
532 | ITypeBinding typeToAddToImport= ASTNodes.getType(fOriginalDeclaration).resolveBinding(); | |
533 | ImportRewriteContext context= new ContextSensitiveImportRewriteContext(reference, fCuRewrite.getImportRewrite()); | |
534 | fCuRewrite.getImportRewrite().addImport(typeToAddToImport, context); | |
535 | fCuRewrite.getImportRemover().registerAddedImport(typeToAddToImport.getName()); | |
536 | ||
537 | } else { | |
538 | newReference= (Expression) fCuRewrite.getASTRewrite().createStringPlaceholder(modifiedInitializer, reference.getNodeType()); | |
539 | isStringPlaceholder= true; | |
540 | } | |
541 | ||
542 | if (NecessaryParenthesesChecker.needsParentheses((isStringPlaceholder ? fInitializer : newReference), reference.getParent(), reference.getLocationInParent())) { | |
543 | ParenthesizedExpression parenthesized= ast.newParenthesizedExpression(); | |
544 | parenthesized.setExpression(newReference); | |
545 | newReference= parenthesized; | |
546 | } | |
547 | fCuRewrite.getASTRewrite().replace(reference, newReference, msg); | |
548 | fSourceRangeComputer.addTightSourceNode(reference); | |
549 | fCuRewrite.getImportRemover().registerRemovedNode(reference); | |
550 | } | |
551 | ||
552 | private String prepareInitializerForLocation(Expression location) throws CoreException { | |
553 | HashSet<SimpleName> staticImportsInReference= new HashSet<SimpleName>(); | |
554 | final IJavaProject project= fCuRewrite.getCu().getJavaProject(); | |
555 | if (fIs15) | |
556 | ImportReferencesCollector.collect(location, project, null, new ArrayList<SimpleName>(), staticImportsInReference); | |
557 | ||
558 | InitializerTraversal traversal= new InitializerTraversal(fInitializer, fStaticImportsInInitializer, location, staticImportsInReference, fCuRewrite); | |
559 | ASTRewrite initializerRewrite= traversal.getInitializerRewrite(); | |
560 | IDocument document= new Document(fInitializerUnit.getBuffer().getContents()); // could reuse document when generating and applying undo edits | |
561 | ||
562 | final RangeMarker marker= new RangeMarker(fInitializer.getStartPosition(), fInitializer.getLength()); | |
563 | TextEdit[] rewriteEdits= initializerRewrite.rewriteAST(document, fInitializerUnit.getJavaProject().getOptions(true)).removeChildren(); | |
564 | marker.addChildren(rewriteEdits); | |
565 | try { | |
566 | marker.apply(document, TextEdit.UPDATE_REGIONS); | |
567 | String rewrittenInitializer= document.get(marker.getOffset(), marker.getLength()); | |
568 | IRegion region= document.getLineInformation(document.getLineOfOffset(marker.getOffset())); | |
569 | int oldIndent= Strings.computeIndentUnits(document.get(region.getOffset(), region.getLength()), project); | |
570 | return Strings.changeIndent(rewrittenInitializer, oldIndent, project, "", TextUtilities.getDefaultLineDelimiter(document)); //$NON-NLS-1$ | |
571 | } catch (MalformedTreeException e) { | |
572 | JavaPlugin.log(e); | |
573 | } catch (BadLocationException e) { | |
574 | JavaPlugin.log(e); | |
575 | } | |
576 | return fInitializerUnit.getBuffer().getText(fInitializer.getStartPosition(), fInitializer.getLength()); | |
577 | } | |
578 | ||
579 | private void removeConstantDeclarationIfNecessary() { | |
580 | if (fDeclarationToRemove == null) | |
581 | return; | |
582 | ||
583 | FieldDeclaration parentDeclaration= (FieldDeclaration) fDeclarationToRemove.getParent(); | |
584 | ASTNode toRemove; | |
585 | if (parentDeclaration.fragments().size() == 1) | |
586 | toRemove= parentDeclaration; | |
587 | else | |
588 | toRemove= fDeclarationToRemove; | |
589 | ||
590 | TextEditGroup msg= fCuRewrite.createGroupDescription(RefactoringCoreMessages.InlineConstantRefactoring_remove_declaration); | |
591 | fCuRewrite.getASTRewrite().remove(toRemove, msg); | |
592 | fCuRewrite.getImportRemover().registerRemovedNode(toRemove); | |
593 | } | |
594 | } | |
595 | ||
596 | // ---- End InlineTargetCompilationUnit ---------------------------------------------------------------------------------------------- | |
597 | ||
598 | private static SimpleName getLeftmost(Name name) { | |
599 | if (name instanceof SimpleName) | |
600 | return (SimpleName) name; | |
601 | ||
602 | return getLeftmost(((QualifiedName) name).getQualifier()); | |
603 | } | |
604 | ||
605 | private int fSelectionStart; | |
606 | private int fSelectionLength; | |
607 | ||
608 | private ICompilationUnit fSelectionCu; | |
609 | private CompilationUnitRewrite fSelectionCuRewrite; | |
610 | private Name fSelectedConstantName; | |
611 | ||
612 | private IField fField; | |
613 | private CompilationUnitRewrite fDeclarationCuRewrite; | |
614 | private VariableDeclarationFragment fDeclaration; | |
615 | private boolean fDeclarationSelected; | |
616 | private boolean fDeclarationSelectedChecked= false; | |
617 | private boolean fInitializerAllStaticFinal; | |
618 | private boolean fInitializerChecked= false; | |
619 | ||
620 | private boolean fRemoveDeclaration= false; | |
621 | private boolean fReplaceAllReferences= true; | |
622 | ||
623 | private CompilationUnitChange[] fChanges; | |
624 | ||
625 | /** | |
626 | * Creates a new inline constant refactoring. | |
627 | * <p> | |
628 | * This constructor is only used by <code>DelegateCreator</code>. | |
629 | * </p> | |
630 | * | |
631 | * @param field the field to inline | |
632 | */ | |
633 | public InlineConstantRefactoring(IField field) { | |
634 | Assert.isNotNull(field); | |
635 | Assert.isTrue(!field.isBinary()); | |
636 | fField= field; | |
637 | } | |
638 | ||
639 | /** | |
640 | * Creates a new inline constant refactoring. | |
641 | * | |
642 | * @param unit the compilation unit, or <code>null</code> if invoked by scripting | |
643 | * @param node the compilation unit node, or <code>null</code> if invoked by scripting | |
644 | * @param selectionStart the start of the selection | |
645 | * @param selectionLength the length of the selection | |
646 | */ | |
647 | public InlineConstantRefactoring(ICompilationUnit unit, CompilationUnit node, int selectionStart, int selectionLength) { | |
648 | Assert.isTrue(selectionStart >= 0); | |
649 | Assert.isTrue(selectionLength >= 0); | |
650 | fSelectionCu= unit; | |
651 | fSelectionStart= selectionStart; | |
652 | fSelectionLength= selectionLength; | |
653 | if (unit != null) | |
654 | initialize(unit, node); | |
655 | } | |
656 | ||
657 | public InlineConstantRefactoring(JavaRefactoringArguments arguments, RefactoringStatus status) { | |
658 | this(null, null, 0, 0); | |
659 | RefactoringStatus initializeStatus= initialize(arguments); | |
660 | status.merge(initializeStatus); | |
661 | } | |
662 | ||
663 | private void initialize(ICompilationUnit cu, CompilationUnit node) { | |
664 | fSelectionCuRewrite= new CompilationUnitRewrite(cu, node); | |
665 | fSelectedConstantName= findConstantNameNode(); | |
666 | } | |
667 | ||
668 | private Name findConstantNameNode() { | |
669 | ASTNode node= NodeFinder.perform(fSelectionCuRewrite.getRoot(), fSelectionStart, fSelectionLength); | |
670 | if (node == null) | |
671 | return null; | |
672 | if (node instanceof FieldAccess) | |
673 | node= ((FieldAccess) node).getName(); | |
674 | if (node.getParent() instanceof EnumConstantDeclaration) | |
675 | return null; | |
676 | if (!(node instanceof Name)) | |
677 | return null; | |
678 | Name name= (Name) node; | |
679 | IBinding binding= name.resolveBinding(); | |
680 | if (!(binding instanceof IVariableBinding)) | |
681 | return null; | |
682 | IVariableBinding variableBinding= (IVariableBinding) binding; | |
683 | if (!variableBinding.isField() || variableBinding.isEnumConstant()) | |
684 | return null; | |
685 | int modifiers= binding.getModifiers(); | |
686 | if (! (Modifier.isStatic(modifiers) && Modifier.isFinal(modifiers))) | |
687 | return null; | |
688 | ||
689 | return name; | |
690 | } | |
691 | ||
692 | public RefactoringStatus checkStaticFinalConstantNameSelected() { | |
693 | if (fSelectedConstantName == null) | |
694 | return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.InlineConstantRefactoring_static_final_field, null, Corext.getPluginId(), RefactoringStatusCodes.NOT_STATIC_FINAL_SELECTED, null); | |
695 | ||
696 | return new RefactoringStatus(); | |
697 | } | |
698 | ||
699 | @Override | |
700 | public String getName() { | |
701 | return RefactoringCoreMessages.InlineConstantRefactoring_name; | |
702 | } | |
703 | ||
704 | /** | |
705 | * Returns the field to inline, or null if the field could not be found or | |
706 | * {@link #checkInitialConditions(IProgressMonitor)} has not been called yet. | |
707 | * | |
708 | * @return the field, or <code>null</code> | |
709 | */ | |
710 | public IJavaElement getField() { | |
711 | return fField; | |
712 | } | |
713 | ||
714 | @Override | |
715 | public RefactoringStatus checkInitialConditions(IProgressMonitor pm) throws CoreException { | |
716 | try { | |
717 | pm.beginTask("", 3); //$NON-NLS-1$ | |
718 | ||
719 | if (!fSelectionCu.isStructureKnown()) | |
720 | return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.InlineConstantRefactoring_syntax_errors, null, Corext.getPluginId(), RefactoringStatusCodes.SYNTAX_ERRORS, null); | |
721 | ||
722 | RefactoringStatus result= checkStaticFinalConstantNameSelected(); | |
723 | if (result.hasFatalError()) | |
724 | return result; | |
725 | ||
726 | result.merge(findField()); | |
727 | if (result.hasFatalError()) | |
728 | return result; | |
729 | pm.worked(1); | |
730 | ||
731 | result.merge(findDeclaration()); | |
732 | if (result.hasFatalError()) | |
733 | return result; | |
734 | pm.worked(1); | |
735 | ||
736 | result.merge(checkInitializer()); | |
737 | if (result.hasFatalError()) | |
738 | return result; | |
739 | pm.worked(1); | |
740 | ||
741 | return result; | |
742 | ||
743 | } finally { | |
744 | pm.done(); | |
745 | } | |
746 | } | |
747 | ||
748 | private RefactoringStatus findField() { | |
749 | fField= (IField) ((IVariableBinding) fSelectedConstantName.resolveBinding()).getJavaElement(); | |
750 | if (fField != null && ! fField.exists()) | |
751 | return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.InlineConstantRefactoring_local_anonymous_unsupported, null, Corext.getPluginId(), RefactoringStatusCodes.LOCAL_AND_ANONYMOUS_NOT_SUPPORTED, null); | |
752 | ||
753 | return null; | |
754 | } | |
755 | private RefactoringStatus findDeclaration() throws JavaModelException { | |
756 | fDeclarationSelectedChecked= true; | |
757 | fDeclarationSelected= false; | |
758 | ASTNode parent= fSelectedConstantName.getParent(); | |
759 | if (parent instanceof VariableDeclarationFragment) { | |
760 | VariableDeclarationFragment parentDeclaration= (VariableDeclarationFragment) parent; | |
761 | if (parentDeclaration.getName() == fSelectedConstantName) { | |
762 | fDeclarationSelected= true; | |
763 | fDeclarationCuRewrite= fSelectionCuRewrite; | |
764 | fDeclaration= (VariableDeclarationFragment) fSelectedConstantName.getParent(); | |
765 | return null; | |
766 | } | |
767 | } | |
768 | ||
769 | VariableDeclarationFragment declaration= (VariableDeclarationFragment) fSelectionCuRewrite.getRoot().findDeclaringNode(fSelectedConstantName.resolveBinding()); | |
770 | if (declaration != null) { | |
771 | fDeclarationCuRewrite= fSelectionCuRewrite; | |
772 | fDeclaration= declaration; | |
773 | return null; | |
774 | } | |
775 | ||
776 | if (fField.getCompilationUnit() == null) | |
777 | return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.InlineConstantRefactoring_binary_file, null, Corext.getPluginId(), RefactoringStatusCodes.DECLARED_IN_CLASSFILE, null); | |
778 | ||
779 | fDeclarationCuRewrite= new CompilationUnitRewrite(fField.getCompilationUnit()); | |
780 | fDeclaration= ASTNodeSearchUtil.getFieldDeclarationFragmentNode(fField, fDeclarationCuRewrite.getRoot()); | |
781 | return null; | |
782 | } | |
783 | ||
784 | private RefactoringStatus checkInitializer() { | |
785 | Expression initializer= getInitializer(); | |
786 | if (initializer == null) | |
787 | return RefactoringStatus.createStatus(RefactoringStatus.FATAL, RefactoringCoreMessages.InlineConstantRefactoring_blank_finals, null, Corext.getPluginId(), RefactoringStatusCodes.CANNOT_INLINE_BLANK_FINAL, null); | |
788 | ||
789 | fInitializerAllStaticFinal= ConstantChecks.isStaticFinalConstant((IExpressionFragment) ASTFragmentFactory.createFragmentForFullSubtree(initializer)); | |
790 | fInitializerChecked= true; | |
791 | return new RefactoringStatus(); | |
792 | } | |
793 | ||
794 | private VariableDeclarationFragment getDeclaration() { | |
795 | return fDeclaration; | |
796 | } | |
797 | ||
798 | private Expression getInitializer() { | |
799 | return fDeclaration.getInitializer(); | |
800 | } | |
801 | ||
802 | private ICompilationUnit getDeclaringCompilationUnit() { | |
803 | return fField.getCompilationUnit(); | |
804 | } | |
805 | ||
806 | @Override | |
807 | public RefactoringStatus checkFinalConditions(IProgressMonitor pm) throws CoreException { | |
808 | RefactoringStatus result= new RefactoringStatus(); | |
809 | pm.beginTask("", 3); //$NON-NLS-1$ | |
810 | ||
811 | try { | |
812 | List<CompilationUnitChange>changes= new ArrayList<CompilationUnitChange>(); | |
813 | HashSet<SimpleName> staticImportsInInitializer= new HashSet<SimpleName>(); | |
814 | ImportReferencesCollector.collect(getInitializer(), fField.getJavaProject(), null, new ArrayList<SimpleName>(), staticImportsInInitializer); | |
815 | ||
816 | if (getReplaceAllReferences()) { | |
817 | SearchResultGroup[] searchResultGroups= findReferences(pm, result); | |
818 | for (int i= 0; i < searchResultGroups.length; i++) { | |
819 | if (pm.isCanceled()) | |
820 | throw new OperationCanceledException(); | |
821 | SearchResultGroup group= searchResultGroups[i]; | |
822 | ICompilationUnit cu= group.getCompilationUnit(); | |
823 | ||
824 | CompilationUnitRewrite cuRewrite= getCuRewrite(cu); | |
825 | Name[] references= extractReferenceNodes(group.getSearchResults(), cuRewrite.getRoot()); | |
826 | InlineTargetCompilationUnit targetCompilationUnit= new InlineTargetCompilationUnit( | |
827 | cuRewrite, references, this, staticImportsInInitializer); | |
828 | CompilationUnitChange change= targetCompilationUnit.getChange(); | |
829 | if (change != null) | |
830 | changes.add(change); | |
831 | } | |
832 | ||
833 | } else { | |
834 | Assert.isTrue(! isDeclarationSelected()); | |
835 | InlineTargetCompilationUnit targetForOnlySelectedReference= new InlineTargetCompilationUnit( | |
836 | fSelectionCuRewrite, new Name[] { fSelectedConstantName }, this, staticImportsInInitializer); | |
837 | CompilationUnitChange change= targetForOnlySelectedReference.getChange(); | |
838 | if (change != null) | |
839 | changes.add(change); | |
840 | } | |
841 | ||
842 | if (result.hasFatalError()) | |
843 | return result; | |
844 | ||
845 | if (getRemoveDeclaration() && getReplaceAllReferences()) { | |
846 | boolean declarationRemoved= false; | |
847 | for (Iterator<CompilationUnitChange> iter= changes.iterator(); iter.hasNext();) { | |
848 | CompilationUnitChange change= iter.next(); | |
849 | if (change.getCompilationUnit().equals(fDeclarationCuRewrite.getCu())) { | |
850 | declarationRemoved= true; | |
851 | break; | |
852 | } | |
853 | } | |
854 | if (! declarationRemoved) { | |
855 | InlineTargetCompilationUnit targetForDeclaration= new InlineTargetCompilationUnit(fDeclarationCuRewrite, new Name[0], this, staticImportsInInitializer); | |
856 | CompilationUnitChange change= targetForDeclaration.getChange(); | |
857 | if (change != null) | |
858 | changes.add(change); | |
859 | } | |
860 | } | |
861 | ||
862 | ICompilationUnit[] cus= new ICompilationUnit[changes.size()]; | |
863 | for (int i= 0; i < changes.size(); i++) { | |
864 | CompilationUnitChange change= changes.get(i); | |
865 | cus[i]= change.getCompilationUnit(); | |
866 | } | |
867 | result.merge(Checks.validateModifiesFiles(ResourceUtil.getFiles(cus), getValidationContext())); | |
868 | ||
869 | pm.worked(1); | |
870 | ||
871 | fChanges= changes.toArray(new CompilationUnitChange[changes.size()]); | |
872 | ||
873 | return result; | |
874 | ||
875 | } finally { | |
876 | fSelectionCuRewrite= null; | |
877 | fSelectedConstantName= null; | |
878 | fDeclarationCuRewrite= null; | |
879 | fDeclaration= null; | |
880 | pm.done(); | |
881 | } | |
882 | } | |
883 | ||
884 | private Name[] extractReferenceNodes(SearchMatch[] searchResults, CompilationUnit cuNode) { | |
885 | Name[] references= new Name[searchResults.length]; | |
886 | for (int i= 0; i < searchResults.length; i++) | |
887 | references[i]= (Name) NodeFinder.perform(cuNode, searchResults[i].getOffset(), searchResults[i].getLength()); | |
888 | return references; | |
889 | } | |
890 | ||
891 | private CompilationUnitRewrite getCuRewrite(ICompilationUnit cu) { | |
892 | CompilationUnitRewrite cuRewrite; | |
893 | if (cu.equals(fSelectionCu)) { | |
894 | cuRewrite= fSelectionCuRewrite; | |
895 | } else if (cu.equals(fField.getCompilationUnit())) { | |
896 | cuRewrite= fDeclarationCuRewrite; | |
897 | } else { | |
898 | cuRewrite= new CompilationUnitRewrite(cu); | |
899 | } | |
900 | return cuRewrite; | |
901 | } | |
902 | ||
903 | private SearchResultGroup[] findReferences(IProgressMonitor pm, RefactoringStatus status) throws JavaModelException { | |
904 | final RefactoringSearchEngine2 engine= new RefactoringSearchEngine2(SearchPattern.createPattern(fField, IJavaSearchConstants.REFERENCES)); | |
905 | engine.setFiltering(true, true); | |
906 | engine.setScope(RefactoringScopeFactory.create(fField)); | |
907 | engine.setStatus(status); | |
908 | engine.setRequestor(new IRefactoringSearchRequestor() { | |
909 | public SearchMatch acceptSearchMatch(SearchMatch match) { | |
910 | return match.isInsideDocComment() ? null : match; | |
911 | } | |
912 | }); | |
913 | engine.searchPattern(new SubProgressMonitor(pm, 1)); | |
914 | return (SearchResultGroup[]) engine.getResults(); | |
915 | } | |
916 | ||
917 | @Override | |
918 | public Change createChange(IProgressMonitor pm) throws CoreException { | |
919 | try { | |
920 | pm.beginTask(RefactoringCoreMessages.InlineConstantRefactoring_preview, 2); | |
921 | final Map<String, String> arguments= new HashMap<String, String>(); | |
922 | String project= null; | |
923 | IJavaProject javaProject= fSelectionCu.getJavaProject(); | |
924 | if (javaProject != null) | |
925 | project= javaProject.getElementName(); | |
926 | int flags= RefactoringDescriptor.STRUCTURAL_CHANGE | JavaRefactoringDescriptor.JAR_REFACTORING | JavaRefactoringDescriptor.JAR_SOURCE_ATTACHMENT; | |
927 | try { | |
928 | if (!Flags.isPrivate(fField.getFlags())) | |
929 | flags|= RefactoringDescriptor.MULTI_CHANGE; | |
930 | } catch (JavaModelException exception) { | |
931 | JavaPlugin.log(exception); | |
932 | } | |
933 | final String description= Messages.format(RefactoringCoreMessages.InlineConstantRefactoring_descriptor_description_short, JavaElementLabels.getElementLabel(fField, JavaElementLabels.ALL_DEFAULT)); | |
934 | final String header= Messages.format(RefactoringCoreMessages.InlineConstantRefactoring_descriptor_description, new String[] { JavaElementLabels.getElementLabel(fField, JavaElementLabels.ALL_FULLY_QUALIFIED), JavaElementLabels.getElementLabel(fField.getParent(), JavaElementLabels.ALL_FULLY_QUALIFIED)}); | |
935 | final JDTRefactoringDescriptorComment comment= new JDTRefactoringDescriptorComment(project, this, header); | |
936 | comment.addSetting(Messages.format(RefactoringCoreMessages.InlineConstantRefactoring_original_pattern, JavaElementLabels.getElementLabel(fField, JavaElementLabels.ALL_FULLY_QUALIFIED))); | |
937 | if (fRemoveDeclaration) | |
938 | comment.addSetting(RefactoringCoreMessages.InlineConstantRefactoring_remove_declaration); | |
939 | if (fReplaceAllReferences) | |
940 | comment.addSetting(RefactoringCoreMessages.InlineConstantRefactoring_replace_references); | |
941 | final InlineConstantDescriptor descriptor= RefactoringSignatureDescriptorFactory.createInlineConstantDescriptor(project, description, comment.asString(), arguments, flags); | |
942 | arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT, JavaRefactoringDescriptorUtil.elementToHandle(project, fSelectionCu)); | |
943 | arguments.put(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION, new Integer(fSelectionStart).toString() + " " + new Integer(fSelectionLength).toString()); //$NON-NLS-1$ | |
944 | arguments.put(ATTRIBUTE_REMOVE, Boolean.valueOf(fRemoveDeclaration).toString()); | |
945 | arguments.put(ATTRIBUTE_REPLACE, Boolean.valueOf(fReplaceAllReferences).toString()); | |
946 | return new DynamicValidationRefactoringChange(descriptor, RefactoringCoreMessages.InlineConstantRefactoring_inline, fChanges); | |
947 | } finally { | |
948 | pm.done(); | |
949 | fChanges= null; | |
950 | } | |
951 | } | |
952 | ||
953 | private void checkInvariant() { | |
954 | if (isDeclarationSelected()) | |
955 | Assert.isTrue(fReplaceAllReferences); | |
956 | } | |
957 | ||
958 | public boolean getRemoveDeclaration() { | |
959 | return fRemoveDeclaration; | |
960 | } | |
961 | ||
962 | public boolean getReplaceAllReferences() { | |
963 | checkInvariant(); | |
964 | return fReplaceAllReferences; | |
965 | } | |
966 | ||
967 | public boolean isDeclarationSelected() { | |
968 | Assert.isTrue(fDeclarationSelectedChecked); | |
969 | return fDeclarationSelected; | |
970 | } | |
971 | ||
972 | public boolean isInitializerAllStaticFinal() { | |
973 | Assert.isTrue(fInitializerChecked); | |
974 | return fInitializerAllStaticFinal; | |
975 | } | |
976 | ||
977 | public void setRemoveDeclaration(boolean removeDeclaration) { | |
978 | fRemoveDeclaration= removeDeclaration; | |
979 | } | |
980 | ||
981 | public void setReplaceAllReferences(boolean replaceAllReferences) { | |
982 | fReplaceAllReferences= replaceAllReferences; | |
983 | checkInvariant(); | |
984 | } | |
985 | ||
986 | private RefactoringStatus initialize(JavaRefactoringArguments arguments) { | |
987 | final String selection= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION); | |
988 | if (selection != null) { | |
989 | int offset= -1; | |
990 | int length= -1; | |
991 | final StringTokenizer tokenizer= new StringTokenizer(selection); | |
992 | if (tokenizer.hasMoreTokens()) | |
993 | offset= Integer.valueOf(tokenizer.nextToken()).intValue(); | |
994 | if (tokenizer.hasMoreTokens()) | |
995 | length= Integer.valueOf(tokenizer.nextToken()).intValue(); | |
996 | if (offset >= 0 && length >= 0) { | |
997 | fSelectionStart= offset; | |
998 | fSelectionLength= length; | |
999 | } else | |
1000 | return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { selection, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION})); | |
1001 | } | |
1002 | final String handle= arguments.getAttribute(JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT); | |
1003 | if (handle != null) { | |
1004 | final IJavaElement element= JavaRefactoringDescriptorUtil.handleToElement(arguments.getProject(), handle, false); | |
1005 | if (element == null || !element.exists()) | |
1006 | return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.INLINE_CONSTANT); | |
1007 | else { | |
1008 | if (element instanceof ICompilationUnit) { | |
1009 | fSelectionCu= (ICompilationUnit) element; | |
1010 | if (selection == null) | |
1011 | return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_SELECTION)); | |
1012 | } else if (element instanceof IField) { | |
1013 | final IField field= (IField) element; | |
1014 | try { | |
1015 | final ISourceRange range= field.getNameRange(); | |
1016 | if (range != null) { | |
1017 | fSelectionStart= range.getOffset(); | |
1018 | fSelectionLength= range.getLength(); | |
1019 | } else | |
1020 | return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, IJavaRefactorings.INLINE_CONSTANT)); | |
1021 | } catch (JavaModelException exception) { | |
1022 | return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.INLINE_CONSTANT); | |
1023 | } | |
1024 | fSelectionCu= field.getCompilationUnit(); | |
1025 | } else | |
1026 | return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_illegal_argument, new Object[] { handle, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT})); | |
1027 | final ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); | |
1028 | parser.setResolveBindings(true); | |
1029 | parser.setSource(fSelectionCu); | |
1030 | final CompilationUnit unit= (CompilationUnit) parser.createAST(null); | |
1031 | initialize(fSelectionCu, unit); | |
1032 | if (checkStaticFinalConstantNameSelected().hasFatalError()) | |
1033 | return JavaRefactoringDescriptorUtil.createInputFatalStatus(element, getName(), IJavaRefactorings.INLINE_CONSTANT); | |
1034 | } | |
1035 | } else | |
1036 | return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, JavaRefactoringDescriptorUtil.ATTRIBUTE_INPUT)); | |
1037 | final String replace= arguments.getAttribute(ATTRIBUTE_REPLACE); | |
1038 | if (replace != null) { | |
1039 | fReplaceAllReferences= Boolean.valueOf(replace).booleanValue(); | |
1040 | } else | |
1041 | return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REPLACE)); | |
1042 | final String remove= arguments.getAttribute(ATTRIBUTE_REMOVE); | |
1043 | if (remove != null) | |
1044 | fRemoveDeclaration= Boolean.valueOf(remove).booleanValue(); | |
1045 | else | |
1046 | return RefactoringStatus.createFatalErrorStatus(Messages.format(RefactoringCoreMessages.InitializableRefactoring_argument_not_exist, ATTRIBUTE_REMOVE)); | |
1047 | return new RefactoringStatus(); | |
1048 | } | |
1049 | } |