/*
* Copyright 2000-2017 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.codeInsight.intention.impl;
import com.intellij.codeInsight.daemon.impl.HighlightInfo;
import com.intellij.codeInsight.intention.IntentionAction;
import com.intellij.codeInsight.intention.IntentionActionDelegate;
import com.intellij.openapi.actionSystem.ShortcutProvider;
import com.intellij.openapi.actionSystem.ShortcutSet;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.DumbService;
import com.intellij.openapi.project.PossiblyDumbAware;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Comparing;
import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.util.IncorrectOperationException;
import org.jetbrains.annotations.Nls;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
import java.util.function.BiConsumer;
/**
* @author cdr
*/
public class IntentionActionWithTextCaching implements Comparable<IntentionActionWithTextCaching>, PossiblyDumbAware, ShortcutProvider {
private static final Logger LOG = Logger.getInstance("#com.intellij.codeInsight.intention.impl.IntentionActionWithTextCaching");
private final List<IntentionAction> myOptionIntentions = new ArrayList<>();
private final List<IntentionAction> myOptionErrorFixes = new ArrayList<>();
private final List<IntentionAction> myOptionInspectionFixes = new ArrayList<>();
private final String myText;
private final IntentionAction myAction;
private final String myDisplayName;
private final Icon myIcon;
IntentionActionWithTextCaching(@NotNull IntentionAction action){
this(action, action.getText(), null, null);
}
IntentionActionWithTextCaching(@NotNull HighlightInfo.IntentionActionDescriptor descriptor, @Nullable BiConsumer<IntentionActionWithTextCaching,IntentionAction> markInvoked){
this(descriptor.getAction(), descriptor.getDisplayName(), descriptor.getIcon(), markInvoked);
}
private IntentionActionWithTextCaching(@NotNull IntentionAction action, String displayName, @Nullable Icon icon, @Nullable BiConsumer<IntentionActionWithTextCaching, IntentionAction> markInvoked) {
myIcon = icon;
myText = action.getText();
// needed for checking errors in user written actions
//noinspection ConstantConditions
LOG.assertTrue(myText != null, "action "+action.getClass()+" text returned null");
myAction = new MyIntentionAction(action, markInvoked);
myDisplayName = displayName;
}
@NotNull
String getText() {
return myText;
}
void addIntention(@NotNull IntentionAction action) {
myOptionIntentions.add(action);
}
void addErrorFix(@NotNull IntentionAction action) {
myOptionErrorFixes.add(action);
}
void addInspectionFix(@NotNull IntentionAction action) {
myOptionInspectionFixes.add(action);
}
@NotNull
public IntentionAction getAction() {
return myAction;
}
@NotNull
List<IntentionAction> getOptionIntentions() {
return myOptionIntentions;
}
@NotNull
List<IntentionAction> getOptionErrorFixes() {
return myOptionErrorFixes;
}
@NotNull
List<IntentionAction> getOptionInspectionFixes() {
return myOptionInspectionFixes;
}
String getToolName() {
return myDisplayName;
}
@NotNull
public String toString() {
return getText();
}
@Override
public int compareTo(@NotNull final IntentionActionWithTextCaching other) {
if (myAction instanceof Comparable) {
//noinspection unchecked
return ((Comparable)myAction).compareTo(other.getAction());
}
if (other.getAction() instanceof Comparable) {
//noinspection unchecked
return -((Comparable)other.getAction()).compareTo(myAction);
}
return Comparing.compare(getText(), other.getText());
}
Icon getIcon() {
return myIcon;
}
@Override
public boolean isDumbAware() {
return DumbService.isDumbAware(myAction);
}
@Nullable
@Override
public ShortcutSet getShortcut() {
return myAction instanceof ShortcutProvider ? ((ShortcutProvider)myAction).getShortcut() : null;
}
// IntentionAction which wraps the original action and then marks it as executed to hide it from the popup to avoid invoking it twice accidentally
private class MyIntentionAction implements IntentionAction, IntentionActionDelegate, Comparable<MyIntentionAction>, ShortcutProvider {
private final IntentionAction myAction;
private final BiConsumer<IntentionActionWithTextCaching, IntentionAction> myMarkInvoked;
MyIntentionAction(IntentionAction action, BiConsumer<IntentionActionWithTextCaching, IntentionAction> markInvoked) {
myAction = action;
myMarkInvoked = markInvoked;
}
@Nls
@NotNull
@Override
public String getText() {
return myAction.getText();
}
@Override
public String toString() {
return getDelegate().getClass()+": "+getDelegate();
}
@Nls
@NotNull
@Override
public String getFamilyName() {
return myAction.getFamilyName();
}
@Override
public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) {
return myAction.isAvailable(project, editor, file);
}
@Override
public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException {
try {
myAction.invoke(project, editor, file);
}
finally {
if (myMarkInvoked != null) {
myMarkInvoked.accept(IntentionActionWithTextCaching.this, myAction);
}
}
}
@Override
public boolean startInWriteAction() {
return myAction.startInWriteAction();
}
@NotNull
@Override
public IntentionAction getDelegate() {
return myAction;
}
@Nullable
@Override
public PsiElement getElementToMakeWritable(@NotNull PsiFile currentFile) {
return myAction.getElementToMakeWritable(currentFile);
}
@Nullable
@Override
public ShortcutSet getShortcut() {
return myAction instanceof ShortcutProvider ? ((ShortcutProvider)myAction).getShortcut() : null;
}
@Override
public int compareTo(@NotNull final MyIntentionAction other) {
if (myAction instanceof Comparable) {
//noinspection unchecked
return ((Comparable)myAction).compareTo(other.getDelegate());
}
if (other.getDelegate() instanceof Comparable) {
//noinspection unchecked
return -((Comparable)other.getDelegate()).compareTo(myAction);
}
return Comparing.compare(getText(), other.getText());
}
}
}