com.intellij.refactoring.extractMethod.ExtractMethodHelper.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.refactoring.extractMethod.ExtractMethodHelper.java

Source

/*
 * Copyright 2000-2013 JetBrains s.r.o.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.intellij.refactoring.extractMethod;

import com.intellij.codeInsight.highlighting.HighlightManager;
import com.intellij.find.FindManager;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.application.ApplicationNamesInfo;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.colors.EditorColors;
import com.intellij.openapi.editor.colors.EditorColorsManager;
import com.intellij.openapi.editor.markup.RangeHighlighter;
import com.intellij.openapi.editor.markup.TextAttributes;
import com.intellij.openapi.progress.ProgressIndicator;
import com.intellij.openapi.progress.ProgressManager;
import com.intellij.openapi.progress.Task;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.Messages;
import com.intellij.openapi.util.Computable;
import com.intellij.openapi.util.Pair;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.ui.ReplacePromptDialog;
import com.intellij.util.Consumer;
import org.jetbrains.annotations.NotNull;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * @author Dennis.Ushakov
 */
public class ExtractMethodHelper {
    public static void processDuplicates(@NotNull final PsiElement callElement,
            @NotNull final PsiElement generatedMethod, @NotNull final List<PsiElement> scope,
            @NotNull final SimpleDuplicatesFinder finder, @NotNull final Editor editor,
            @NotNull final Consumer<Pair<SimpleMatch, PsiElement>> replacer) {
        if (ApplicationManager.getApplication().isUnitTestMode()) {
            replaceDuplicates(callElement, editor, replacer, finder.findDuplicates(scope, generatedMethod));
            return;
        }
        final Project project = callElement.getProject();
        ProgressManager.getInstance().run(new Task.Backgroundable(project, "Searching for duplicates...", true) {
            @Override
            public void run(@NotNull ProgressIndicator indicator) {
                if (myProject == null || myProject.isDisposed())
                    return;
                final List<SimpleMatch> duplicates = ApplicationManager.getApplication()
                        .runReadAction(new Computable<List<SimpleMatch>>() {
                            @Override
                            public List<SimpleMatch> compute() {
                                return finder.findDuplicates(scope, generatedMethod);
                            }
                        });

                ApplicationManager.getApplication().invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        replaceDuplicates(callElement, editor, replacer, duplicates);
                    }
                });
            }
        });
    }

    private static void replaceDuplicates(PsiElement callElement, Editor editor,
            Consumer<Pair<SimpleMatch, PsiElement>> replacer, List<SimpleMatch> duplicates) {
        if (duplicates.size() > 0) {
            final String message = RefactoringBundle.message(
                    "0.has.detected.1.code.fragments.in.this.file.that.can.be.replaced.with.a.call.to.extracted.method",
                    ApplicationNamesInfo.getInstance().getProductName(), duplicates.size());
            final boolean isUnittest = ApplicationManager.getApplication().isUnitTestMode();
            final Project project = callElement.getProject();
            final int exitCode = !isUnittest ? Messages.showYesNoDialog(project, message,
                    RefactoringBundle.message("refactoring.extract.method.dialog.title"),
                    Messages.getInformationIcon()) : Messages.YES;
            if (exitCode == Messages.YES) {
                boolean replaceAll = false;
                final Map<SimpleMatch, RangeHighlighter> highlighterMap = new HashMap<SimpleMatch, RangeHighlighter>();
                for (SimpleMatch match : duplicates) {
                    final Pair<SimpleMatch, PsiElement> replacement = Pair.create(match, callElement);
                    if (!replaceAll) {
                        highlightInEditor(project, match, editor, highlighterMap);

                        int promptResult = FindManager.PromptResult.ALL;
                        //noinspection ConstantConditions
                        if (!isUnittest) {
                            ReplacePromptDialog promptDialog = new ReplacePromptDialog(false,
                                    RefactoringBundle.message("replace.fragment"), project);
                            promptDialog.show();
                            promptResult = promptDialog.getExitCode();
                        }
                        if (promptResult == FindManager.PromptResult.SKIP) {
                            final HighlightManager highlightManager = HighlightManager.getInstance(project);
                            final RangeHighlighter highlighter = highlighterMap.get(match);
                            if (highlighter != null)
                                highlightManager.removeSegmentHighlighter(editor, highlighter);
                            continue;
                        }
                        if (promptResult == FindManager.PromptResult.CANCEL)
                            break;

                        if (promptResult == FindManager.PromptResult.OK) {
                            replaceDuplicate(project, replacer, replacement);
                        } else if (promptResult == FindManager.PromptResult.ALL) {
                            replaceDuplicate(project, replacer, replacement);
                            replaceAll = true;
                        }
                    } else {
                        replaceDuplicate(project, replacer, replacement);
                    }
                }
            }
        }
    }

    private static void replaceDuplicate(final Project project,
            final Consumer<Pair<SimpleMatch, PsiElement>> replacer,
            final Pair<SimpleMatch, PsiElement> replacement) {
        CommandProcessor.getInstance().executeCommand(project, new Runnable() {
            @Override
            public void run() {
                ApplicationManager.getApplication().runWriteAction(new Runnable() {
                    @Override
                    public void run() {
                        replacer.consume(replacement);
                    }
                });
            }
        }, "Replace duplicate", null);
    }

    private static void highlightInEditor(@NotNull final Project project, @NotNull final SimpleMatch match,
            @NotNull final Editor editor, Map<SimpleMatch, RangeHighlighter> highlighterMap) {
        final List<RangeHighlighter> highlighters = new ArrayList<RangeHighlighter>();
        final HighlightManager highlightManager = HighlightManager.getInstance(project);
        final EditorColorsManager colorsManager = EditorColorsManager.getInstance();
        final TextAttributes attributes = colorsManager.getGlobalScheme()
                .getAttributes(EditorColors.SEARCH_RESULT_ATTRIBUTES);
        final int startOffset = match.getStartElement().getTextRange().getStartOffset();
        final int endOffset = match.getEndElement().getTextRange().getEndOffset();
        highlightManager.addRangeHighlight(editor, startOffset, endOffset, attributes, true, highlighters);
        highlighterMap.put(match, highlighters.get(0));
        final LogicalPosition logicalPosition = editor.offsetToLogicalPosition(startOffset);
        editor.getScrollingModel().scrollTo(logicalPosition, ScrollType.MAKE_VISIBLE);
    }
}