com.intellij.refactoring.ui.ConflictsDialog.java Source code

Java tutorial

Introduction

Here is the source code for com.intellij.refactoring.ui.ConflictsDialog.java

Source

/*
 * Copyright 2000-2011 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.
 */

/**
 * created at Sep 12, 2001
 * @author Jeka
 */
package com.intellij.refactoring.ui;

import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileEditor.FileEditorLocation;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.ui.DialogWrapper;
import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiElement;
import com.intellij.refactoring.RefactoringBundle;
import com.intellij.ui.ScrollPaneFactory;
import com.intellij.ui.SimpleTextAttributes;
import com.intellij.usageView.UsageInfo;
import com.intellij.usages.*;
import com.intellij.util.ArrayUtil;
import com.intellij.util.containers.MultiMap;
import com.intellij.util.ui.UIUtil;
import org.jetbrains.annotations.NonNls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.util.Collection;
import java.util.LinkedHashSet;
import java.util.regex.Pattern;

public class ConflictsDialog extends DialogWrapper {
    private static final int SHOW_CONFLICTS_EXIT_CODE = 4;

    private String[] myConflictDescriptions;
    private MultiMap<PsiElement, String> myElementConflictDescription;
    private final Project myProject;
    private Runnable myDoRefactoringRunnable;
    private final boolean myCanShowConflictsInView;
    private String myCommandName;

    public ConflictsDialog(@NotNull Project project, @NotNull MultiMap<PsiElement, String> conflictDescriptions) {
        this(project, conflictDescriptions, null, true, true);
    }

    public ConflictsDialog(@NotNull Project project, @NotNull MultiMap<PsiElement, String> conflictDescriptions,
            @Nullable Runnable doRefactoringRunnable) {
        this(project, conflictDescriptions, doRefactoringRunnable, true, true);
    }

    public ConflictsDialog(@NotNull Project project, @NotNull MultiMap<PsiElement, String> conflictDescriptions,
            @Nullable Runnable doRefactoringRunnable, boolean alwaysShowOkButton, boolean canShowConflictsInView) {
        super(project, true);
        myProject = project;
        myDoRefactoringRunnable = doRefactoringRunnable;
        myCanShowConflictsInView = canShowConflictsInView;
        final LinkedHashSet<String> conflicts = new LinkedHashSet<String>();

        for (String conflict : conflictDescriptions.values()) {
            conflicts.add(conflict);
        }
        myConflictDescriptions = ArrayUtil.toStringArray(conflicts);
        myElementConflictDescription = conflictDescriptions;
        setTitle(RefactoringBundle.message("problems.detected.title"));
        setOKButtonText(RefactoringBundle.message("continue.button"));
        setOKActionEnabled(alwaysShowOkButton || myDoRefactoringRunnable != null);
        init();
    }

    @SuppressWarnings("deprecation")
    @Deprecated
    public ConflictsDialog(Project project, Collection<String> conflictDescriptions) {
        this(project, ArrayUtil.toStringArray(conflictDescriptions));
    }

    @Deprecated
    public ConflictsDialog(Project project, String... conflictDescriptions) {
        super(project, true);
        myProject = project;
        myConflictDescriptions = conflictDescriptions;
        myCanShowConflictsInView = true;
        setTitle(RefactoringBundle.message("problems.detected.title"));
        setOKButtonText(RefactoringBundle.message("continue.button"));
        init();
    }

    @Override
    @NotNull
    protected Action[] createActions() {
        final Action okAction = getOKAction();
        boolean showUsagesButton = myElementConflictDescription != null && myCanShowConflictsInView;

        if (showUsagesButton || !okAction.isEnabled()) {
            okAction.putValue(DEFAULT_ACTION, null);
        }

        if (!showUsagesButton) {
            return new Action[] { okAction, new CancelAction() };
        }
        return new Action[] { okAction, new MyShowConflictsInUsageViewAction(), new CancelAction() };
    }

    public boolean isShowConflicts() {
        return getExitCode() == SHOW_CONFLICTS_EXIT_CODE;
    }

    @Override
    protected JComponent createCenterPanel() {
        JPanel panel = new JPanel(new BorderLayout(0, 2));

        panel.add(new JLabel(RefactoringBundle.message("the.following.problems.were.found")), BorderLayout.NORTH);

        @NonNls
        StringBuilder buf = new StringBuilder();
        for (String description : myConflictDescriptions) {
            buf.append(description);
            buf.append("<br><br>");
        }
        JEditorPane messagePane = new JEditorPane(UIUtil.HTML_MIME, buf.toString());
        messagePane.setEditable(false);
        JScrollPane scrollPane = ScrollPaneFactory.createScrollPane(messagePane,
                ScrollPaneConstants.VERTICAL_SCROLLBAR_ALWAYS, ScrollPaneConstants.HORIZONTAL_SCROLLBAR_AS_NEEDED);
        scrollPane.setPreferredSize(new Dimension(500, 400));
        panel.add(scrollPane, BorderLayout.CENTER);

        if (getOKAction().isEnabled()) {
            panel.add(new JLabel(RefactoringBundle.message("do.you.wish.to.ignore.them.and.continue")),
                    BorderLayout.SOUTH);
        }

        return panel;
    }

    public void setCommandName(String commandName) {
        myCommandName = commandName;
    }

    private class CancelAction extends AbstractAction {
        public CancelAction() {
            super(RefactoringBundle.message("cancel.button"));
            putValue(DEFAULT_ACTION, Boolean.TRUE);
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            doCancelAction();
        }
    }

    private class MyShowConflictsInUsageViewAction extends AbstractAction {

        public MyShowConflictsInUsageViewAction() {
            super("Show conflicts in view");
        }

        @Override
        public void actionPerformed(ActionEvent e) {
            final UsageViewPresentation presentation = new UsageViewPresentation();
            final String codeUsagesString = "Conflicts";
            presentation.setCodeUsagesString(codeUsagesString);
            presentation.setTabName(codeUsagesString);
            presentation.setTabText(codeUsagesString);
            presentation.setShowCancelButton(true);

            final Usage[] usages = new Usage[myElementConflictDescription.size()];
            int i = 0;
            for (final PsiElement element : myElementConflictDescription.keySet()) {
                if (element == null) {
                    usages[i++] = new DescriptionOnlyUsage();
                    continue;
                }
                boolean isRead = false;
                boolean isWrite = false;
                for (ReadWriteAccessDetector detector : Extensions.getExtensions(ReadWriteAccessDetector.EP_NAME)) {
                    if (detector.isReadWriteAccessible(element)) {
                        final ReadWriteAccessDetector.Access access = detector.getExpressionAccess(element);
                        isRead = access != ReadWriteAccessDetector.Access.Write;
                        isWrite = access != ReadWriteAccessDetector.Access.Read;
                        break;
                    }
                }

                usages[i++] = isRead || isWrite
                        ? new ReadWriteAccessUsageInfo2UsageAdapter(new UsageInfo(element), isRead, isWrite) {
                            @NotNull
                            @Override
                            public UsagePresentation getPresentation() {
                                final UsagePresentation usagePresentation = super.getPresentation();
                                return MyShowConflictsInUsageViewAction.this.getPresentation(usagePresentation,
                                        element);
                            }
                        }
                        : new UsageInfo2UsageAdapter(new UsageInfo(element)) {
                            @NotNull
                            @Override
                            public UsagePresentation getPresentation() {
                                final UsagePresentation usagePresentation = super.getPresentation();
                                return MyShowConflictsInUsageViewAction.this.getPresentation(usagePresentation,
                                        element);
                            }
                        };
            }
            final UsageView usageView = UsageViewManager.getInstance(myProject).showUsages(UsageTarget.EMPTY_ARRAY,
                    usages, presentation);
            if (myDoRefactoringRunnable != null) {
                usageView.addPerformOperationAction(myDoRefactoringRunnable,
                        myCommandName != null ? myCommandName : RefactoringBundle.message("retry.command"),
                        "Unable to perform refactoring. There were changes in code after the usages have been found.",
                        RefactoringBundle.message("usageView.doAction"));
            }
            close(SHOW_CONFLICTS_EXIT_CODE);
        }

        private UsagePresentation getPresentation(final UsagePresentation usagePresentation, PsiElement element) {
            final Collection<String> elementConflicts = new LinkedHashSet<String>(
                    myElementConflictDescription.get(element));
            final String conflictDescription = " ("
                    + Pattern.compile("<[^<>]*>").matcher(StringUtil.join(elementConflicts, "\n")).replaceAll("")
                    + ")";
            return new UsagePresentation() {
                @Override
                @NotNull
                public TextChunk[] getText() {
                    final TextChunk[] chunks = usagePresentation.getText();
                    return ArrayUtil.append(chunks, new TextChunk(
                            SimpleTextAttributes.GRAY_ITALIC_ATTRIBUTES.toTextAttributes(), conflictDescription));
                }

                @Override
                @NotNull
                public String getPlainText() {
                    return usagePresentation.getPlainText() + conflictDescription;
                }

                @Override
                public Icon getIcon() {
                    return usagePresentation.getIcon();
                }

                @Override
                public String getTooltipText() {
                    return usagePresentation.getTooltipText();
                }
            };
        }

        private class DescriptionOnlyUsage implements Usage {
            private final String myConflictDescription = Pattern
                    .compile("<[^<>]*>").matcher(StringUtil
                            .join(new LinkedHashSet<String>(myElementConflictDescription.get(null)), "\n"))
                    .replaceAll("");

            @Override
            @NotNull
            public UsagePresentation getPresentation() {
                return new UsagePresentation() {
                    @Override
                    @NotNull
                    public TextChunk[] getText() {
                        return new TextChunk[0];
                    }

                    @Override
                    @Nullable
                    public Icon getIcon() {
                        return null;
                    }

                    @Override
                    public String getTooltipText() {
                        return myConflictDescription;
                    }

                    @Override
                    @NotNull
                    public String getPlainText() {
                        return myConflictDescription;
                    }
                };
            }

            @Override
            public boolean canNavigateToSource() {
                return false;
            }

            @Override
            public boolean canNavigate() {
                return false;
            }

            @Override
            public void navigate(boolean requestFocus) {
            }

            @Override
            public FileEditorLocation getLocation() {
                return null;
            }

            @Override
            public boolean isReadOnly() {
                return false;
            }

            @Override
            public boolean isValid() {
                return true;
            }

            @Override
            public void selectInEditor() {
            }

            @Override
            public void highlightInEditor() {
            }
        }
    }
}