2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com
.intellij
.refactoring
.util
.duplicates
;
18 import com
.intellij
.codeInsight
.folding
.CodeFoldingManager
;
19 import com
.intellij
.codeInsight
.highlighting
.HighlightManager
;
20 import com
.intellij
.openapi
.application
.ApplicationManager
;
21 import com
.intellij
.openapi
.application
.ApplicationNamesInfo
;
22 import com
.intellij
.openapi
.diagnostic
.Logger
;
23 import com
.intellij
.openapi
.editor
.Editor
;
24 import com
.intellij
.openapi
.editor
.FoldRegion
;
25 import com
.intellij
.openapi
.editor
.LogicalPosition
;
26 import com
.intellij
.openapi
.editor
.ScrollType
;
27 import com
.intellij
.openapi
.editor
.colors
.EditorColors
;
28 import com
.intellij
.openapi
.editor
.colors
.EditorColorsManager
;
29 import com
.intellij
.openapi
.editor
.markup
.RangeHighlighter
;
30 import com
.intellij
.openapi
.editor
.markup
.TextAttributes
;
31 import com
.intellij
.openapi
.fileEditor
.FileEditorManager
;
32 import com
.intellij
.openapi
.fileEditor
.OpenFileDescriptor
;
33 import com
.intellij
.openapi
.project
.Project
;
34 import com
.intellij
.openapi
.ui
.Messages
;
35 import com
.intellij
.openapi
.util
.TextRange
;
36 import com
.intellij
.openapi
.vfs
.VirtualFile
;
37 import com
.intellij
.psi
.PsiFile
;
38 import com
.intellij
.refactoring
.RefactoringBundle
;
39 import com
.intellij
.refactoring
.util
.CommonRefactoringUtil
;
40 import com
.intellij
.util
.IncorrectOperationException
;
42 import java
.util
.ArrayList
;
43 import java
.util
.List
;
48 public class DuplicatesImpl
{
49 private static final Logger LOG
= Logger
.getInstance("#com.intellij.refactoring.util.duplicates.DuplicatesImpl");
51 private DuplicatesImpl() {}
53 public static void invoke(final Project project
, Editor editor
, final MatchProvider provider
) {
54 final List
<Match
> duplicates
= provider
.getDuplicates();
56 for (final Match match
: duplicates
) {
57 if (!match
.getMatchStart().isValid() || !match
.getMatchEnd().isValid()) continue;
58 if (replaceMatch(project
, provider
, match
, editor
, ++idx
, duplicates
.size())) return;
62 public static void invoke(final Project project
, final MatchProvider provider
) {
63 final List
<Match
> duplicates
= provider
.getDuplicates();
65 for (final Match match
: duplicates
) {
66 final PsiFile file
= match
.getFile();
67 final VirtualFile virtualFile
= file
.getVirtualFile();
68 if (virtualFile
== null || !virtualFile
.isValid()) return;
69 if (!CommonRefactoringUtil
.checkReadOnlyStatus(project
, file
)) return;
70 final Editor editor
= FileEditorManager
.getInstance(project
).openTextEditor(new OpenFileDescriptor(project
, virtualFile
), false);
71 LOG
.assertTrue(editor
!= null);
72 if (!match
.getMatchStart().isValid() || !match
.getMatchEnd().isValid()) continue;
73 if (replaceMatch(project
, provider
, match
, editor
, ++idx
, duplicates
.size())) return;
77 private static boolean replaceMatch(final Project project
, final MatchProvider provider
, final Match match
, final Editor editor
,
78 final int idx
, final int size
) {
79 final ArrayList
<RangeHighlighter
> highlighters
= new ArrayList
<RangeHighlighter
>();
80 highlightMatch(project
, editor
, match
, highlighters
);
81 final TextRange textRange
= match
.getTextRange();
82 final LogicalPosition logicalPosition
= editor
.offsetToLogicalPosition(textRange
.getStartOffset());
83 expandAllRegionsCoveringRange(project
, editor
, textRange
);
84 editor
.getScrollingModel().scrollTo(logicalPosition
, ScrollType
.MAKE_VISIBLE
);
85 String prompt
= provider
.getConfirmDuplicatePrompt(match
);
86 final int matchAnswer
= ApplicationManager
.getApplication().isUnitTestMode()
88 : Messages
.showYesNoCancelDialog(project
, prompt
, RefactoringBundle
.message("process.duplicates.title", idx
, size
),
89 Messages
.getQuestionIcon());
90 HighlightManager
.getInstance(project
).removeSegmentHighlighter(editor
, highlighters
.get(0));
91 if (matchAnswer
== 0) {
92 final Runnable action
= new Runnable() {
95 provider
.processMatch(match
);
97 catch (IncorrectOperationException e
) {
104 ApplicationManager
.getApplication().runWriteAction(action
);
106 else if (matchAnswer
== 2) {
112 private static void expandAllRegionsCoveringRange(final Project project
, Editor editor
, final TextRange textRange
) {
113 final FoldRegion
[] foldRegions
= CodeFoldingManager
.getInstance(project
).getFoldRegionsAtOffset(editor
, textRange
.getStartOffset());
114 boolean anyCollapsed
= false;
115 for (final FoldRegion foldRegion
: foldRegions
) {
116 if (!foldRegion
.isExpanded()) {
122 editor
.getFoldingModel().runBatchFoldingOperation(new Runnable() {
124 for (final FoldRegion foldRegion
: foldRegions
) {
125 if (!foldRegion
.isExpanded()) {
126 foldRegion
.setExpanded(true);
134 public static void highlightMatch(final Project project
, Editor editor
, final Match match
, final ArrayList
<RangeHighlighter
> highlighters
) {
135 EditorColorsManager colorsManager
= EditorColorsManager
.getInstance();
136 TextAttributes attributes
= colorsManager
.getGlobalScheme().getAttributes(EditorColors
.SEARCH_RESULT_ATTRIBUTES
);
137 HighlightManager
.getInstance(project
).addRangeHighlight(editor
, match
.getTextRange().getStartOffset(), match
.getTextRange().getEndOffset(),
138 attributes
, true, highlighters
);
141 public static void processDuplicates(final MatchProvider provider
, final Project project
, Editor editor
) {
142 boolean hasDuplicates
= provider
.hasDuplicates();
144 final int answer
= Messages
.showYesNoDialog(project
,
145 RefactoringBundle
.message("0.has.detected.1.code.fragments.in.this.file.that.can.be.replaced.with.a.call.to.extracted.method",
146 ApplicationNamesInfo
.getInstance().getProductName(), provider
.getDuplicates().size()),
147 "Process Duplicates", Messages
.getQuestionIcon());
149 invoke(project
, editor
, provider
);