]>
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.rename; | |
12 | ||
13 | import java.util.ArrayList; | |
14 | import java.util.Arrays; | |
15 | import java.util.Collection; | |
16 | import java.util.HashMap; | |
17 | import java.util.HashSet; | |
18 | import java.util.Iterator; | |
19 | import java.util.Map; | |
20 | import java.util.Map.Entry; | |
21 | ||
22 | import org.eclipse.core.runtime.Assert; | |
23 | import org.eclipse.core.runtime.CoreException; | |
24 | import org.eclipse.core.runtime.NullProgressMonitor; | |
25 | import org.eclipse.core.runtime.SubProgressMonitor; | |
26 | ||
27 | import org.eclipse.core.resources.IResource; | |
28 | ||
29 | import org.eclipse.text.edits.TextEdit; | |
30 | ||
31 | import org.eclipse.jface.text.IRegion; | |
32 | import org.eclipse.jface.text.Region; | |
33 | ||
34 | import org.eclipse.ltk.core.refactoring.RefactoringStatus; | |
35 | import org.eclipse.ltk.core.refactoring.RefactoringStatusContext; | |
36 | import org.eclipse.ltk.core.refactoring.RefactoringStatusEntry; | |
37 | import org.eclipse.ltk.core.refactoring.TextChange; | |
38 | import org.eclipse.ltk.core.refactoring.TextEditChangeGroup; | |
39 | ||
40 | import org.eclipse.jdt.core.ICompilationUnit; | |
41 | import org.eclipse.jdt.core.IJavaElement; | |
42 | import org.eclipse.jdt.core.ISourceRange; | |
43 | import org.eclipse.jdt.core.ISourceReference; | |
44 | import org.eclipse.jdt.core.JavaModelException; | |
45 | import org.eclipse.jdt.core.SourceRange; | |
46 | import org.eclipse.jdt.core.WorkingCopyOwner; | |
47 | import org.eclipse.jdt.core.compiler.IProblem; | |
48 | import org.eclipse.jdt.core.dom.ASTNode; | |
49 | import org.eclipse.jdt.core.dom.ASTVisitor; | |
50 | import org.eclipse.jdt.core.dom.CompilationUnit; | |
51 | import org.eclipse.jdt.core.dom.IBinding; | |
52 | import org.eclipse.jdt.core.dom.IVariableBinding; | |
53 | import org.eclipse.jdt.core.dom.Name; | |
54 | import org.eclipse.jdt.core.dom.NodeFinder; | |
55 | import org.eclipse.jdt.core.dom.SimpleName; | |
56 | import org.eclipse.jdt.core.dom.VariableDeclaration; | |
57 | import org.eclipse.jdt.core.search.FieldDeclarationMatch; | |
58 | import org.eclipse.jdt.core.search.MethodDeclarationMatch; | |
59 | import org.eclipse.jdt.core.search.SearchMatch; | |
60 | ||
61 | import org.eclipse.jdt.internal.corext.SourceRangeFactory; | |
62 | import org.eclipse.jdt.internal.corext.dom.ASTNodes; | |
63 | import org.eclipse.jdt.internal.corext.refactoring.RefactoringCoreMessages; | |
64 | import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup; | |
65 | import org.eclipse.jdt.internal.corext.refactoring.base.JavaStatusContext; | |
66 | import org.eclipse.jdt.internal.corext.refactoring.base.JavaStringStatusContext; | |
67 | import org.eclipse.jdt.internal.corext.refactoring.util.RefactoringASTParser; | |
68 | import org.eclipse.jdt.internal.corext.refactoring.util.TextChangeManager; | |
69 | import org.eclipse.jdt.internal.corext.util.Messages; | |
70 | import org.eclipse.jdt.internal.corext.util.SearchUtils; | |
71 | ||
72 | import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; | |
73 | import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; | |
74 | ||
75 | class RenameAnalyzeUtil { | |
76 | ||
77 | private static class ProblemNodeFinder { | |
78 | ||
79 | private ProblemNodeFinder() { | |
80 | //static | |
81 | } | |
82 | ||
83 | public static SimpleName[] getProblemNodes(ASTNode methodNode, VariableDeclaration variableNode, TextEdit[] edits, TextChange change) { | |
84 | String key= variableNode.resolveBinding().getKey(); | |
85 | NameNodeVisitor visitor= new NameNodeVisitor(edits, change, key); | |
86 | methodNode.accept(visitor); | |
87 | return visitor.getProblemNodes(); | |
88 | } | |
89 | ||
90 | private static class NameNodeVisitor extends ASTVisitor { | |
91 | ||
92 | private Collection<IRegion> fRanges; | |
93 | private Collection<SimpleName> fProblemNodes; | |
94 | private String fKey; | |
95 | ||
96 | public NameNodeVisitor(TextEdit[] edits, TextChange change, String key) { | |
97 | Assert.isNotNull(edits); | |
98 | Assert.isNotNull(key); | |
99 | ||
100 | fRanges= new HashSet<IRegion>(Arrays.asList(RefactoringAnalyzeUtil.getNewRanges(edits, change))); | |
101 | fProblemNodes= new ArrayList<SimpleName>(0); | |
102 | fKey= key; | |
103 | } | |
104 | ||
105 | public SimpleName[] getProblemNodes() { | |
106 | return fProblemNodes.toArray(new SimpleName[fProblemNodes.size()]); | |
107 | } | |
108 | ||
109 | //----- visit methods | |
110 | ||
111 | @Override | |
112 | public boolean visit(SimpleName node) { | |
113 | VariableDeclaration decl= getVariableDeclaration(node); | |
114 | if (decl == null) | |
115 | return super.visit(node); | |
116 | ||
117 | IVariableBinding binding= decl.resolveBinding(); | |
118 | if (binding == null) | |
119 | return super.visit(node); | |
120 | ||
121 | boolean keysEqual= fKey.equals(binding.getKey()); | |
122 | boolean rangeInSet= fRanges.contains(new Region(node.getStartPosition(), node.getLength())); | |
123 | ||
124 | if (keysEqual && !rangeInSet) | |
125 | fProblemNodes.add(node); | |
126 | ||
127 | if (!keysEqual && rangeInSet) | |
128 | fProblemNodes.add(node); | |
129 | ||
130 | /* | |
131 | * if (!keyEquals && !rangeInSet) | |
132 | * ok, different local variable. | |
133 | * | |
134 | * if (keyEquals && rangeInSet) | |
135 | * ok, renamed local variable & has been renamed. | |
136 | */ | |
137 | ||
138 | return super.visit(node); | |
139 | } | |
140 | } | |
141 | } | |
142 | ||
143 | static class LocalAnalyzePackage { | |
144 | public final TextEdit fDeclarationEdit; | |
145 | public final TextEdit[] fOccurenceEdits; | |
146 | ||
147 | public LocalAnalyzePackage(final TextEdit declarationEdit, final TextEdit[] occurenceEdits) { | |
148 | fDeclarationEdit = declarationEdit; | |
149 | fOccurenceEdits = occurenceEdits; | |
150 | } | |
151 | } | |
152 | ||
153 | private RenameAnalyzeUtil() { | |
154 | //no instance | |
155 | } | |
156 | ||
157 | static RefactoringStatus analyzeRenameChanges(TextChangeManager manager, SearchResultGroup[] oldOccurrences, SearchResultGroup[] newOccurrences) { | |
158 | RefactoringStatus result= new RefactoringStatus(); | |
159 | for (int i= 0; i < oldOccurrences.length; i++) { | |
160 | SearchResultGroup oldGroup= oldOccurrences[i]; | |
161 | SearchMatch[] oldSearchResults= oldGroup.getSearchResults(); | |
162 | ICompilationUnit cunit= oldGroup.getCompilationUnit(); | |
163 | if (cunit == null) | |
164 | continue; | |
165 | for (int j= 0; j < oldSearchResults.length; j++) { | |
166 | SearchMatch oldSearchResult= oldSearchResults[j]; | |
167 | if (! RenameAnalyzeUtil.existsInNewOccurrences(oldSearchResult, newOccurrences, manager)){ | |
168 | addShadowsError(cunit, oldSearchResult, result); | |
169 | } | |
170 | } | |
171 | } | |
172 | return result; | |
173 | } | |
174 | ||
175 | static ICompilationUnit findWorkingCopyForCu(ICompilationUnit[] newWorkingCopies, ICompilationUnit cu){ | |
176 | ICompilationUnit original= cu == null ? null : cu.getPrimary(); | |
177 | for (int i= 0; i < newWorkingCopies.length; i++) { | |
178 | if (newWorkingCopies[i].getPrimary().equals(original)) | |
179 | return newWorkingCopies[i]; | |
180 | } | |
181 | return null; | |
182 | } | |
183 | ||
184 | static ICompilationUnit[] createNewWorkingCopies(ICompilationUnit[] compilationUnitsToModify, TextChangeManager manager, WorkingCopyOwner owner, SubProgressMonitor pm) throws CoreException { | |
185 | pm.beginTask("", compilationUnitsToModify.length); //$NON-NLS-1$ | |
186 | ICompilationUnit[] newWorkingCopies= new ICompilationUnit[compilationUnitsToModify.length]; | |
187 | for (int i= 0; i < compilationUnitsToModify.length; i++) { | |
188 | ICompilationUnit cu= compilationUnitsToModify[i]; | |
189 | newWorkingCopies[i]= createNewWorkingCopy(cu, manager, owner, new SubProgressMonitor(pm, 1)); | |
190 | } | |
191 | pm.done(); | |
192 | return newWorkingCopies; | |
193 | } | |
194 | ||
195 | static ICompilationUnit createNewWorkingCopy(ICompilationUnit cu, TextChangeManager manager, | |
196 | WorkingCopyOwner owner, SubProgressMonitor pm) throws CoreException { | |
197 | ICompilationUnit newWc= cu.getWorkingCopy(owner, null); | |
198 | String previewContent= manager.get(cu).getPreviewContent(new NullProgressMonitor()); | |
199 | newWc.getBuffer().setContents(previewContent); | |
200 | newWc.reconcile(ICompilationUnit.NO_AST, false, owner, pm); | |
201 | return newWc; | |
202 | } | |
203 | ||
204 | private static boolean existsInNewOccurrences(SearchMatch searchResult, SearchResultGroup[] newOccurrences, TextChangeManager manager) { | |
205 | SearchResultGroup newGroup= findOccurrenceGroup(searchResult.getResource(), newOccurrences); | |
206 | if (newGroup == null) | |
207 | return false; | |
208 | ||
209 | IRegion oldEditRange= getCorrespondingEditChangeRange(searchResult, manager); | |
210 | if (oldEditRange == null) | |
211 | return false; | |
212 | ||
213 | SearchMatch[] newSearchResults= newGroup.getSearchResults(); | |
214 | int oldRangeOffset = oldEditRange.getOffset(); | |
215 | for (int i= 0; i < newSearchResults.length; i++) { | |
216 | if (newSearchResults[i].getOffset() == oldRangeOffset) | |
217 | return true; | |
218 | } | |
219 | return false; | |
220 | } | |
221 | ||
222 | private static IRegion getCorrespondingEditChangeRange(SearchMatch searchResult, TextChangeManager manager) { | |
223 | TextChange change= getTextChange(searchResult, manager); | |
224 | if (change == null) | |
225 | return null; | |
226 | ||
227 | IRegion oldMatchRange= createTextRange(searchResult); | |
228 | TextEditChangeGroup[] editChanges= change.getTextEditChangeGroups(); | |
229 | for (int i= 0; i < editChanges.length; i++) { | |
230 | if (oldMatchRange.equals(editChanges[i].getRegion())) | |
231 | return TextEdit.getCoverage(change.getPreviewEdits(editChanges[i].getTextEdits())); | |
232 | } | |
233 | return null; | |
234 | } | |
235 | ||
236 | private static TextChange getTextChange(SearchMatch searchResult, TextChangeManager manager) { | |
237 | ICompilationUnit cu= SearchUtils.getCompilationUnit(searchResult); | |
238 | if (cu == null) | |
239 | return null; | |
240 | return manager.get(cu); | |
241 | } | |
242 | ||
243 | private static IRegion createTextRange(SearchMatch searchResult) { | |
244 | return new Region(searchResult.getOffset(), searchResult.getLength()); | |
245 | } | |
246 | ||
247 | private static SearchResultGroup findOccurrenceGroup(IResource resource, SearchResultGroup[] newOccurrences) { | |
248 | for (int i= 0; i < newOccurrences.length; i++) { | |
249 | if (newOccurrences[i].getResource().equals(resource)) | |
250 | return newOccurrences[i]; | |
251 | } | |
252 | return null; | |
253 | } | |
254 | ||
255 | //--- find missing changes in BOTH directions | |
256 | ||
257 | //TODO: Currently filters out declarations (MethodDeclarationMatch, FieldDeclarationMatch). | |
258 | //Long term solution: only pass reference search results in. | |
259 | static RefactoringStatus analyzeRenameChanges2(TextChangeManager manager, | |
260 | SearchResultGroup[] oldReferences, SearchResultGroup[] newReferences, String newElementName) { | |
261 | RefactoringStatus result= new RefactoringStatus(); | |
262 | ||
263 | HashMap<ICompilationUnit, SearchMatch[]> cuToNewResults= new HashMap<ICompilationUnit, SearchMatch[]>(newReferences.length); | |
264 | for (int i1= 0; i1 < newReferences.length; i1++) { | |
265 | ICompilationUnit cu= newReferences[i1].getCompilationUnit(); | |
266 | if (cu != null) | |
267 | cuToNewResults.put(cu.getPrimary(), newReferences[i1].getSearchResults()); | |
268 | } | |
269 | ||
270 | for (int i= 0; i < oldReferences.length; i++) { | |
271 | SearchResultGroup oldGroup= oldReferences[i]; | |
272 | SearchMatch[] oldMatches= oldGroup.getSearchResults(); | |
273 | ICompilationUnit cu= oldGroup.getCompilationUnit(); | |
274 | if (cu == null) | |
275 | continue; | |
276 | ||
277 | SearchMatch[] newSearchMatches= cuToNewResults.remove(cu); | |
278 | if (newSearchMatches == null) { | |
279 | for (int j = 0; j < oldMatches.length; j++) { | |
280 | SearchMatch oldMatch = oldMatches[j]; | |
281 | addShadowsError(cu, oldMatch, result); | |
282 | } | |
283 | } else { | |
284 | analyzeChanges(cu, manager.get(cu), oldMatches, newSearchMatches, newElementName, result); | |
285 | } | |
286 | } | |
287 | ||
288 | for (Iterator<Entry<ICompilationUnit, SearchMatch[]>> iter= cuToNewResults.entrySet().iterator(); iter.hasNext();) { | |
289 | Entry<ICompilationUnit, SearchMatch[]> entry= iter.next(); | |
290 | ICompilationUnit cu= entry.getKey(); | |
291 | SearchMatch[] newSearchMatches= entry.getValue(); | |
292 | for (int i= 0; i < newSearchMatches.length; i++) { | |
293 | SearchMatch newMatch= newSearchMatches[i]; | |
294 | addReferenceShadowedError(cu, newMatch, newElementName, result); | |
295 | } | |
296 | } | |
297 | return result; | |
298 | } | |
299 | ||
300 | private static void analyzeChanges(ICompilationUnit cu, TextChange change, | |
301 | SearchMatch[] oldMatches, SearchMatch[] newMatches, String newElementName, RefactoringStatus result) { | |
302 | Map<Integer, SearchMatch> updatedOldOffsets= getUpdatedChangeOffsets(change, oldMatches); | |
303 | for (int i= 0; i < newMatches.length; i++) { | |
304 | SearchMatch newMatch= newMatches[i]; | |
305 | Integer offsetInNew= new Integer(newMatch.getOffset()); | |
306 | SearchMatch oldMatch= updatedOldOffsets.remove(offsetInNew); | |
307 | if (oldMatch == null) { | |
308 | addReferenceShadowedError(cu, newMatch, newElementName, result); | |
309 | } | |
310 | } | |
311 | for (Iterator<SearchMatch> iter= updatedOldOffsets.values().iterator(); iter.hasNext();) { | |
312 | // remaining old matches are not found any more -> they have been shadowed | |
313 | SearchMatch oldMatch= iter.next(); | |
314 | addShadowsError(cu, oldMatch, result); | |
315 | } | |
316 | } | |
317 | ||
318 | /** | |
319 | * | |
320 | * @param change | |
321 | * @param oldMatches | |
322 | * @return Map <Integer updatedOffset, SearchMatch oldMatch> | |
323 | */ | |
324 | private static Map<Integer, SearchMatch> getUpdatedChangeOffsets(TextChange change, SearchMatch[] oldMatches) { | |
325 | Map<Integer, SearchMatch> updatedOffsets= new HashMap<Integer, SearchMatch>(); | |
326 | Map<Integer, Integer> oldToUpdatedOffsets= getEditChangeOffsetUpdates(change); | |
327 | for (int i= 0; i < oldMatches.length; i++) { | |
328 | SearchMatch oldMatch= oldMatches[i]; | |
329 | Integer updatedOffset= oldToUpdatedOffsets.get(new Integer(oldMatch.getOffset())); | |
330 | if (updatedOffset == null) | |
331 | updatedOffset= new Integer(-1); //match not updated | |
332 | updatedOffsets.put(updatedOffset, oldMatch); | |
333 | } | |
334 | return updatedOffsets; | |
335 | } | |
336 | ||
337 | /** | |
338 | * | |
339 | * @param change | |
340 | * @return Map <Integer oldOffset, Integer updatedOffset> | |
341 | */ | |
342 | private static Map<Integer, Integer> getEditChangeOffsetUpdates(TextChange change) { | |
343 | TextEditChangeGroup[] editChanges= change.getTextEditChangeGroups(); | |
344 | Map<Integer, Integer> offsetUpdates= new HashMap<Integer, Integer>(editChanges.length); | |
345 | for (int i= 0; i < editChanges.length; i++) { | |
346 | TextEditChangeGroup editChange= editChanges[i]; | |
347 | IRegion oldRegion= editChange.getRegion(); | |
348 | if (oldRegion == null) | |
349 | continue; | |
350 | IRegion updatedRegion= TextEdit.getCoverage(change.getPreviewEdits(editChange.getTextEdits())); | |
351 | if (updatedRegion == null) | |
352 | continue; | |
353 | ||
354 | offsetUpdates.put(new Integer(oldRegion.getOffset()), new Integer(updatedRegion.getOffset())); | |
355 | } | |
356 | return offsetUpdates; | |
357 | } | |
358 | ||
359 | private static void addReferenceShadowedError(ICompilationUnit cu, SearchMatch newMatch, String newElementName, RefactoringStatus result) { | |
360 | //Found a new match with no corresponding old match. | |
361 | //-> The new match is a reference which was pointing to another element, | |
362 | //but that other element has been shadowed | |
363 | ||
364 | //TODO: should not have to filter declarations: | |
365 | if (newMatch instanceof MethodDeclarationMatch || newMatch instanceof FieldDeclarationMatch) | |
366 | return; | |
367 | ISourceRange range= getOldSourceRange(newMatch); | |
368 | RefactoringStatusContext context= JavaStatusContext.create(cu, range); | |
369 | String message= Messages.format( | |
370 | RefactoringCoreMessages.RenameAnalyzeUtil_reference_shadowed, | |
371 | new String[] {BasicElementLabels.getFileName(cu), BasicElementLabels.getJavaElementName(newElementName)}); | |
372 | result.addError(message, context); | |
373 | } | |
374 | ||
375 | private static ISourceRange getOldSourceRange(SearchMatch newMatch) { | |
376 | // cannot transfom offset in preview to offset in original -> just show enclosing method | |
377 | IJavaElement newMatchElement= (IJavaElement) newMatch.getElement(); | |
378 | IJavaElement primaryElement= newMatchElement.getPrimaryElement(); | |
379 | ISourceRange range= null; | |
380 | if (primaryElement.exists() && primaryElement instanceof ISourceReference) { | |
381 | try { | |
382 | range= ((ISourceReference) primaryElement).getSourceRange(); | |
383 | } catch (JavaModelException e) { | |
384 | // can live without source range | |
385 | } | |
386 | } | |
387 | return range; | |
388 | } | |
389 | ||
390 | private static void addShadowsError(ICompilationUnit cu, SearchMatch oldMatch, RefactoringStatus result) { | |
391 | // Old match not found in new matches -> reference has been shadowed | |
392 | ||
393 | //TODO: should not have to filter declarations: | |
394 | if (oldMatch instanceof MethodDeclarationMatch || oldMatch instanceof FieldDeclarationMatch) | |
395 | return; | |
396 | ISourceRange range= new SourceRange(oldMatch.getOffset(), oldMatch.getLength()); | |
397 | RefactoringStatusContext context= JavaStatusContext.create(cu, range); | |
398 | String message= Messages.format(RefactoringCoreMessages.RenameAnalyzeUtil_shadows, BasicElementLabels.getFileName(cu)); | |
399 | result.addError(message, context); | |
400 | } | |
401 | ||
402 | /** | |
403 | * This method analyzes a set of local variable renames inside one cu. It checks whether | |
404 | * any new compile errors have been introduced by the rename(s) and whether the correct | |
405 | * node(s) has/have been renamed. | |
406 | * | |
407 | * @param analyzePackages the LocalAnalyzePackages containing the information about the local renames | |
408 | * @param cuChange the TextChange containing all local variable changes to be applied. | |
409 | * @param oldCUNode the fully (incl. bindings) resolved AST node of the original compilation unit | |
410 | * @param recovery whether statements and bindings recovery should be performed when parsing the changed CU | |
411 | * @return a RefactoringStatus containing errors if compile errors or wrongly renamed nodes are found | |
412 | * @throws CoreException thrown if there was an error greating the preview content of the change | |
413 | */ | |
414 | public static RefactoringStatus analyzeLocalRenames(LocalAnalyzePackage[] analyzePackages, TextChange cuChange, CompilationUnit oldCUNode, boolean recovery) throws CoreException { | |
415 | ||
416 | RefactoringStatus result= new RefactoringStatus(); | |
417 | ICompilationUnit compilationUnit= (ICompilationUnit) oldCUNode.getJavaElement(); | |
418 | ||
419 | String newCuSource= cuChange.getPreviewContent(new NullProgressMonitor()); | |
420 | CompilationUnit newCUNode= new RefactoringASTParser(ASTProvider.SHARED_AST_LEVEL).parse(newCuSource, compilationUnit, true, recovery, null); | |
421 | ||
422 | result.merge(analyzeCompileErrors(newCuSource, newCUNode, oldCUNode)); | |
423 | if (result.hasError()) | |
424 | return result; | |
425 | ||
426 | for (int i= 0; i < analyzePackages.length; i++) { | |
427 | ASTNode enclosing= getEnclosingBlockOrMethod(analyzePackages[i].fDeclarationEdit, cuChange, newCUNode); | |
428 | ||
429 | // get new declaration | |
430 | IRegion newRegion= RefactoringAnalyzeUtil.getNewTextRange(analyzePackages[i].fDeclarationEdit, cuChange); | |
431 | ASTNode newDeclaration= NodeFinder.perform(newCUNode, newRegion.getOffset(), newRegion.getLength()); | |
432 | Assert.isTrue(newDeclaration instanceof Name); | |
433 | ||
434 | VariableDeclaration declaration= getVariableDeclaration((Name) newDeclaration); | |
435 | Assert.isNotNull(declaration); | |
436 | ||
437 | SimpleName[] problemNodes= ProblemNodeFinder.getProblemNodes(enclosing, declaration, analyzePackages[i].fOccurenceEdits, cuChange); | |
438 | result.merge(RefactoringAnalyzeUtil.reportProblemNodes(newCuSource, problemNodes)); | |
439 | } | |
440 | return result; | |
441 | } | |
442 | ||
443 | private static VariableDeclaration getVariableDeclaration(Name node) { | |
444 | IBinding binding= node.resolveBinding(); | |
445 | if (binding == null && node.getParent() instanceof VariableDeclaration) | |
446 | return (VariableDeclaration) node.getParent(); | |
447 | ||
448 | if (binding != null && binding.getKind() == IBinding.VARIABLE) { | |
449 | CompilationUnit cu= (CompilationUnit) ASTNodes.getParent(node, CompilationUnit.class); | |
450 | return ASTNodes.findVariableDeclaration( ((IVariableBinding) binding), cu); | |
451 | } | |
452 | return null; | |
453 | } | |
454 | ||
455 | private static ASTNode getEnclosingBlockOrMethod(TextEdit declarationEdit, TextChange change, CompilationUnit newCUNode) { | |
456 | ASTNode enclosing= RefactoringAnalyzeUtil.getBlock(declarationEdit, change, newCUNode); | |
457 | if (enclosing == null) | |
458 | enclosing= RefactoringAnalyzeUtil.getMethodDeclaration(declarationEdit, change, newCUNode); | |
459 | return enclosing; | |
460 | } | |
461 | ||
462 | private static RefactoringStatus analyzeCompileErrors(String newCuSource, CompilationUnit newCUNode, CompilationUnit oldCUNode) { | |
463 | RefactoringStatus result= new RefactoringStatus(); | |
464 | IProblem[] newProblems= RefactoringAnalyzeUtil.getIntroducedCompileProblems(newCUNode, oldCUNode); | |
465 | for (int i= 0; i < newProblems.length; i++) { | |
466 | IProblem problem= newProblems[i]; | |
467 | if (problem.isError()) | |
468 | result.addEntry(new RefactoringStatusEntry((problem.isError() ? RefactoringStatus.ERROR : RefactoringStatus.WARNING), problem.getMessage(), new JavaStringStatusContext(newCuSource, | |
469 | SourceRangeFactory.create(problem)))); | |
470 | } | |
471 | return result; | |
472 | } | |
473 | } |