/* * Copyright 2000-2015 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.jetbrains.lang.dart.assists; import com.intellij.CommonBundle; import com.intellij.codeInsight.intention.IntentionAction; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import com.intellij.refactoring.util.CommonRefactoringUtil; import com.intellij.util.IncorrectOperationException; import com.jetbrains.lang.dart.DartBundle; import com.jetbrains.lang.dart.analyzer.DartAnalysisServerService; import com.jetbrains.lang.dart.psi.DartFile; import org.dartlang.analysis.server.protocol.SourceChange; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; /** * This intention is registered in plugin.xml to make sure that it appears in Preferences (Settings) UI and can be switched on/off. * But the instance created this way (using default constructor) always says that it is not available. * Real intentions are added dynamically in {@link DartAnalysisServerService#registerQuickAssistIntentions()}. * We need to register them not via plugin.xml for 2 reasons: * <ul> * <li>intentions amount, text and behavior are loaded dynamically</li> * <li>intentions registered via plugin.xml are wrapped in IntentionActionWrapper that doesn't implement Comparable, but order is important for us</li> * </ul> */ public class DartQuickAssistIntention implements IntentionAction, Comparable<IntentionAction> { @Nullable private final QuickAssistSet quickAssistSet; private final int index; @Nullable private SourceChange sourceChange; // invoked by Platform because registered in plugin.xml @SuppressWarnings("unused") public DartQuickAssistIntention() { quickAssistSet = null; index = -1; } public DartQuickAssistIntention(@NotNull final QuickAssistSet quickAssistSet, final int index) { this.quickAssistSet = quickAssistSet; this.index = index; } @Override public int compareTo(IntentionAction o) { if (o instanceof DartQuickAssistIntention) { final DartQuickAssistIntention other = (DartQuickAssistIntention)o; return index - other.index; } return 0; } @NotNull @Override public String getFamilyName() { final String message = DartBundle.message("dart.quick.assist.family.name"); // a bit hacky way to make inspections enabling/disabling work, see IntentionActionWrapper.getFullFamilyName() return quickAssistSet == null ? message : "Dart/" + message; } @NotNull @Override public String getText() { return sourceChange == null ? "" : sourceChange.getMessage(); } @Override public void invoke(@NotNull Project project, Editor editor, PsiFile file) throws IncorrectOperationException { if (sourceChange != null) { try { AssistUtils.applySourceChange(project, sourceChange, true); } catch (DartSourceEditException e) { CommonRefactoringUtil.showErrorHint(project, editor, e.getMessage(), CommonBundle.getErrorTitle(), null); } } } @Override public boolean isAvailable(@NotNull Project project, Editor editor, PsiFile file) { if (quickAssistSet == null || !(file instanceof DartFile)) return false; final List<SourceChange> sourceChanges = quickAssistSet.getQuickAssists(editor, file); if (sourceChanges.size() <= index) { sourceChange = null; return false; } sourceChange = sourceChanges.get(index); return true; } @Override public boolean startInWriteAction() { return true; } }