IDEA-121060 Multiple carets: comment/uncomment works incorrectly

Fix for 'comment by block comment' action
This commit is contained in:
Dmitry Batrak
2014-07-09 11:35:20 +04:00
parent 0e8564a197
commit d51dd50463
11 changed files with 273 additions and 84 deletions
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2013 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -15,13 +15,13 @@
*/
package com.intellij.codeInsight;
import com.intellij.codeInsight.actions.CodeInsightAction;
import com.intellij.ide.DataManager;
import com.intellij.openapi.actionSystem.ActionManager;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
public class CodeInsightTestCaseUtil {
public static void doAction(CodeInsightTestCase testCase, CodeInsightAction action, String testName, String ext) throws Exception {
public static void doAction(CodeInsightTestCase testCase, AnAction action, String testName, String ext) throws Exception {
testCase.configureByFile(testName + "." + ext);
action.actionPerformed(new AnActionEvent(
@@ -25,6 +25,12 @@ import org.jetbrains.annotations.Nullable;
* Provides methods to query and modify caret position and caret's associated selection.
*/
public interface Caret extends UserDataHolderEx, Disposable {
/**
* Returns an instance of Editor, current caret belongs to.
*/
@NotNull
Editor getEditor();
/**
* Returns an instance of CaretModel, current caret is associated with.
*/
@@ -23,9 +23,9 @@ import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.DataContext;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.fileEditor.FileEditor;
import com.intellij.openapi.fileEditor.FileEditorManager;
import com.intellij.openapi.fileEditor.TextEditor;
@@ -83,20 +83,22 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil {
@Nullable
public static Language getLanguageInEditor(@NotNull final Editor editor, @NotNull final Project project) {
return getLanguageInEditor(editor.getCaretModel().getCurrentCaret(), project);
}
@Nullable
public static Language getLanguageInEditor(@NotNull Caret caret, @NotNull final Project project) {
Editor editor = caret.getEditor();
PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
if (file == null) return null;
final SelectionModel selectionModel = editor.getSelectionModel();
int caretOffset = editor.getCaretModel().getOffset();
int mostProbablyCorrectLanguageOffset = caretOffset == selectionModel.getSelectionStart() ||
caretOffset == selectionModel.getSelectionEnd()
? selectionModel.getSelectionStart()
: caretOffset;
int caretOffset = caret.getOffset();
int mostProbablyCorrectLanguageOffset = caretOffset == caret.getSelectionEnd() ? caret.getSelectionStart() : caretOffset;
PsiElement elt = getElementAtOffset(file, mostProbablyCorrectLanguageOffset);
Language lang = findLanguageFromElement(elt);
if (selectionModel.hasSelection()) {
final Language rangeLanguage = evaluateLanguageInRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd(), file);
if (caret.hasSelection()) {
final Language rangeLanguage = evaluateLanguageInRange(caret.getSelectionStart(), caret.getSelectionEnd(), file);
if (rangeLanguage == null) return file.getLanguage();
lang = rangeLanguage;
@@ -115,22 +117,24 @@ public class PsiUtilBase extends PsiUtilCore implements PsiEditorUtil {
@Nullable
public static PsiFile getPsiFileInEditor(@NotNull final Editor editor, @NotNull final Project project) {
return getPsiFileInEditor(editor.getCaretModel().getCurrentCaret(), project);
}
@Nullable
public static PsiFile getPsiFileInEditor(@NotNull Caret caret, @NotNull final Project project) {
Editor editor = caret.getEditor();
final PsiFile file = PsiDocumentManager.getInstance(project).getPsiFile(editor.getDocument());
if (file == null) return null;
PsiUtilCore.ensureValid(file);
final Language language = getLanguageInEditor(editor, project);
final Language language = getLanguageInEditor(caret, project);
if (language == null) return file;
if (language == file.getLanguage()) return file;
final SelectionModel selectionModel = editor.getSelectionModel();
int caretOffset = editor.getCaretModel().getOffset();
int mostProbablyCorrectLanguageOffset = caretOffset == selectionModel.getSelectionStart() ||
caretOffset == selectionModel.getSelectionEnd()
? selectionModel.getSelectionStart()
: caretOffset;
int caretOffset = caret.getOffset();
int mostProbablyCorrectLanguageOffset = caretOffset == caret.getSelectionEnd() ? caret.getSelectionStart() : caretOffset;
return getPsiFileAtOffset(file, mostProbablyCorrectLanguageOffset);
}
@@ -0,0 +1,133 @@
/*
* Copyright 2000-2014 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.actions;
import com.intellij.openapi.actionSystem.AnAction;
import com.intellij.openapi.actionSystem.AnActionEvent;
import com.intellij.openapi.actionSystem.CommonDataKeys;
import com.intellij.openapi.actionSystem.Presentation;
import com.intellij.openapi.application.ApplicationManager;
import com.intellij.openapi.command.CommandProcessor;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.CaretAction;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.ScrollType;
import com.intellij.openapi.editor.actionSystem.DocCommandGroupId;
import com.intellij.openapi.project.Project;
import com.intellij.openapi.util.Ref;
import com.intellij.psi.PsiDocumentManager;
import com.intellij.psi.PsiFile;
import com.intellij.psi.impl.source.tree.injected.InjectedLanguageUtil;
import com.intellij.psi.util.PsiUtilBase;
import org.jetbrains.annotations.NotNull;
public abstract class MultiCaretCodeInsightAction extends AnAction {
@Override
public void actionPerformed(AnActionEvent e) {
final Project project = e.getProject();
if (project == null) {
return;
}
final Editor hostEditor = CommonDataKeys.EDITOR.getData(e.getDataContext());
if (hostEditor == null) {
return;
}
actionPerformedImpl(project, hostEditor);
}
public void actionPerformedImpl(final Project project, final Editor hostEditor) {
CommandProcessor.getInstance().executeCommand(project, new Runnable() {
@Override
public void run() {
ApplicationManager.getApplication().runWriteAction(new Runnable() {
@Override
public void run() {
iterateOverCarets(project, hostEditor, getHandler());
}
});
}
}, getCommandName(), DocCommandGroupId.noneGroupId(hostEditor.getDocument()));
hostEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
}
@Override
public void update(AnActionEvent e) {
final Presentation presentation = e.getPresentation();
Project project = e.getProject();
if (project == null) {
presentation.setEnabled(false);
return;
}
Editor hostEditor = CommonDataKeys.EDITOR.getData(e.getDataContext());
if (hostEditor == null) {
presentation.setEnabled(false);
return;
}
final Ref<Boolean> enabled = new Ref<Boolean>(Boolean.FALSE);
iterateOverCarets(project, hostEditor, new MultiCaretCodeInsightActionHandler() {
@Override
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull Caret caret, @NotNull PsiFile file) {
if (isValidFor(project, editor, caret, file)) {
enabled.set(Boolean.TRUE);
}
}
});
presentation.setEnabled(enabled.get());
}
private static void iterateOverCarets(@NotNull final Project project,
@NotNull final Editor hostEditor,
@NotNull final MultiCaretCodeInsightActionHandler handler) {
PsiDocumentManager documentManager = PsiDocumentManager.getInstance(project);
final PsiFile psiFile = documentManager.getCachedPsiFile(hostEditor.getDocument());
documentManager.commitAllDocuments();
hostEditor.getCaretModel().runForEachCaret(new CaretAction() {
@Override
public void perform(Caret caret) {
Editor editor = hostEditor;
if (psiFile != null) {
Caret injectedCaret = InjectedLanguageUtil.getCaretForInjectedLanguageNoCommit(caret, psiFile);
if (injectedCaret != null) {
caret = injectedCaret;
editor = caret.getEditor();
}
}
final PsiFile file = PsiUtilBase.getPsiFileInEditor(caret, project);
if (file != null) {
handler.invoke(project, editor, caret, file);
}
}
}, true);
}
protected boolean isValidFor(@NotNull Project project, @NotNull Editor editor, @NotNull Caret caret, @NotNull PsiFile file) {
return true;
}
@NotNull
protected abstract MultiCaretCodeInsightActionHandler getHandler();
protected String getCommandName() {
String text = getTemplatePresentation().getText();
return text == null ? "" : text;
}
}
@@ -0,0 +1,26 @@
/*
* Copyright 2000-2014 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.actions;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
public abstract class MultiCaretCodeInsightActionHandler {
public abstract void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull Caret caret, @NotNull PsiFile file);
}
@@ -16,9 +16,9 @@
package com.intellij.codeInsight.generation;
import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.CodeInsightUtilBase;
import com.intellij.codeInsight.CommentUtil;
import com.intellij.codeInsight.actions.MultiCaretCodeInsightActionHandler;
import com.intellij.featureStatistics.FeatureUsageTracker;
import com.intellij.ide.highlighter.custom.CustomFileTypeLexer;
import com.intellij.lang.Commenter;
@@ -52,18 +52,20 @@ import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
public class CommentByBlockCommentHandler extends MultiCaretCodeInsightActionHandler {
private Project myProject;
private Editor myEditor;
private Caret myCaret;
private @NotNull PsiFile myFile;
private Document myDocument;
private CommenterDataHolder mySelfManagedCommenterData;
@Override
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull PsiFile file) {
public void invoke(@NotNull Project project, @NotNull Editor editor, @NotNull Caret caret, @NotNull PsiFile file) {
if (!CodeInsightUtilBase.prepareEditorForWrite(editor)) return;
myProject = project;
myEditor = editor;
myCaret = caret;
myFile = file;
myDocument = editor.getDocument();
@@ -72,19 +74,17 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
return;
}
FeatureUsageTracker.getInstance().triggerFeatureUsed("codeassists.comment.block");
final Commenter commenter = findCommenter(myFile, myEditor);
final Commenter commenter = findCommenter(myFile, myEditor, caret);
if (commenter == null) return;
final SelectionModel selectionModel = myEditor.getSelectionModel();
final String prefix;
final String suffix;
if (commenter instanceof SelfManagingCommenter) {
final SelfManagingCommenter selfManagingCommenter = (SelfManagingCommenter)commenter;
mySelfManagedCommenterData = selfManagingCommenter.createBlockCommentingState(
selectionModel.getSelectionStart(),
selectionModel.getSelectionEnd(),
caret.getSelectionStart(),
caret.getSelectionEnd(),
myDocument,
myFile
);
@@ -94,12 +94,12 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
}
prefix = selfManagingCommenter.getBlockCommentPrefix(
selectionModel.getSelectionStart(),
caret.getSelectionStart(),
myDocument,
mySelfManagedCommenterData
);
suffix = selfManagingCommenter.getBlockCommentSuffix(
selectionModel.getSelectionEnd(),
caret.getSelectionEnd(),
myDocument,
mySelfManagedCommenterData
);
@@ -117,9 +117,9 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
final int commentEnd = commentedRange.getEndOffset();
int selectionStart = commentStart;
int selectionEnd = commentEnd;
if (selectionModel.hasSelection()) {
selectionStart = selectionModel.getSelectionStart();
selectionEnd = selectionModel.getSelectionEnd();
if (myCaret.hasSelection()) {
selectionStart = myCaret.getSelectionStart();
selectionEnd = myCaret.getSelectionEnd();
}
if ((commentStart < selectionStart || commentStart >= selectionEnd) && (commentEnd <= selectionStart || commentEnd > selectionEnd)) {
commentRange(selectionStart, selectionEnd, prefix, suffix, commenter);
@@ -129,9 +129,9 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
}
}
else {
if (selectionModel.hasBlockSelection()) {
final LogicalPosition start = selectionModel.getBlockStart();
final LogicalPosition end = selectionModel.getBlockEnd();
if (myEditor.getSelectionModel().hasBlockSelection()) {
final LogicalPosition start = myEditor.getSelectionModel().getBlockStart();
final LogicalPosition end = myEditor.getSelectionModel().getBlockEnd();
assert start != null;
assert end != null;
@@ -151,9 +151,9 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
EditorModificationUtil.insertStringAtCaret(editor, prefix, true, true);
}
}
else if (selectionModel.hasSelection()) {
int selectionStart = selectionModel.getSelectionStart();
int selectionEnd = selectionModel.getSelectionEnd();
else if (myCaret.hasSelection()) {
int selectionStart = myCaret.getSelectionStart();
int selectionEnd = myCaret.getSelectionEnd();
if (commenter instanceof IndentedCommenter) {
final Boolean value = ((IndentedCommenter)commenter).forceIndentedLineComment();
if (value != null && value == Boolean.TRUE) {
@@ -165,7 +165,7 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
}
else {
EditorUtil.fillVirtualSpaceUntilCaret(editor);
int caretOffset = myEditor.getCaretModel().getOffset();
int caretOffset = myCaret.getOffset();
if (commenter instanceof IndentedCommenter) {
final Boolean value = ((IndentedCommenter)commenter).forceIndentedLineComment();
if (value != null && value == Boolean.TRUE) {
@@ -177,7 +177,7 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
}
}
myDocument.insertString(caretOffset, prefix + suffix);
myEditor.getCaretModel().moveToOffset(caretOffset + prefix.length());
myCaret.moveToOffset(caretOffset + prefix.length());
}
}
}
@@ -188,12 +188,11 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
}
private boolean testSelectionForNonComments() {
SelectionModel model = myEditor.getSelectionModel();
if (!model.hasSelection()) {
if (!myCaret.hasSelection()) {
return true;
}
TextRange range
= new TextRange(model.getSelectionStart(), model.getSelectionEnd() - 1);
= new TextRange(myCaret.getSelectionStart(), myCaret.getSelectionEnd() - 1);
for (PsiElement element = myFile.findElementAt(range.getStartOffset()); element != null && range.intersects(element.getTextRange());
element = element.getNextSibling()) {
if (element instanceof OuterLanguageElement) {
@@ -247,7 +246,7 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
final FileType fileType = myFile.getFileType();
if (fileType instanceof CustomSyntaxTableFileType) {
Lexer lexer = new CustomFileTypeLexer(((CustomSyntaxTableFileType)fileType).getSyntaxTable());
final int caretOffset = myEditor.getCaretModel().getOffset();
final int caretOffset = myCaret.getOffset();
int commentStart = CharArrayUtil.lastIndexOf(text, commenter.getBlockCommentPrefix(), caretOffset);
if (commentStart == -1) return null;
@@ -261,17 +260,16 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
final String prefix;
final String suffix;
final SelectionModel selectionModel = myEditor.getSelectionModel();
if (commenter instanceof SelfManagingCommenter) {
SelfManagingCommenter selfManagingCommenter = (SelfManagingCommenter)commenter;
prefix = selfManagingCommenter.getBlockCommentPrefix(
selectionModel.getSelectionStart(),
myCaret.getSelectionStart(),
myDocument,
mySelfManagedCommenterData
);
suffix = selfManagingCommenter.getBlockCommentSuffix(
selectionModel.getSelectionEnd(),
myCaret.getSelectionEnd(),
myDocument,
mySelfManagedCommenterData
);
@@ -286,8 +284,8 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
if (commenter instanceof SelfManagingCommenter) {
commentedRange = ((SelfManagingCommenter)commenter).getBlockCommentRange(
selectionModel.getSelectionStart(),
selectionModel.getSelectionEnd(),
myCaret.getSelectionStart(),
myCaret.getSelectionEnd(),
myDocument,
mySelfManagedCommenterData
);
@@ -316,11 +314,10 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
@Nullable
private TextRange getSelectedComments(CharSequence text, String prefix, String suffix) {
TextRange commentedRange = null;
final SelectionModel selectionModel = myEditor.getSelectionModel();
if (selectionModel.hasSelection()) {
int selectionStart = selectionModel.getSelectionStart();
if (myCaret.hasSelection()) {
int selectionStart = myCaret.getSelectionStart();
selectionStart = CharArrayUtil.shiftForward(text, selectionStart, " \t\n");
int selectionEnd = selectionModel.getSelectionEnd() - 1;
int selectionEnd = myCaret.getSelectionEnd() - 1;
selectionEnd = CharArrayUtil.shiftBackward(text, selectionEnd, " \t\n") + 1;
if (selectionEnd - selectionStart >= prefix.length() + suffix.length() &&
CharArrayUtil.regionMatches(text, selectionStart, prefix) &&
@@ -332,13 +329,13 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
}
@Nullable
private static Commenter findCommenter(PsiFile file, Editor editor) {
private static Commenter findCommenter(PsiFile file, Editor editor, Caret caret) {
final FileType fileType = file.getFileType();
if (fileType instanceof AbstractFileType) {
return ((AbstractFileType)fileType).getCommenter();
}
Language lang = PsiUtilBase.getLanguageInEditor(editor, file.getProject());
Language lang = PsiUtilBase.getLanguageInEditor(caret, file.getProject());
return getCommenter(file, editor, lang, lang);
}
@@ -371,9 +368,8 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
@Nullable
private PsiElement findCommentAtCaret() {
int offset = myEditor.getCaretModel().getOffset();
SelectionModel selectionModel = myEditor.getSelectionModel();
TextRange range = new TextRange(selectionModel.getSelectionStart(), selectionModel.getSelectionEnd());
int offset = myCaret.getOffset();
TextRange range = new TextRange(myCaret.getSelectionStart(), myCaret.getSelectionEnd());
if (offset == range.getEndOffset()) {
offset--;
}
@@ -383,21 +379,16 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
PsiElement elt = myFile.getViewProvider().findElementAt(offset);
if (elt == null) return null;
PsiElement comment = PsiTreeUtil.getParentOfType(elt, PsiComment.class, false);
if (comment == null || selectionModel.hasSelection() && !range.contains(comment.getTextRange())) {
if (comment == null || myCaret.hasSelection() && !range.contains(comment.getTextRange())) {
return null;
}
return comment;
}
@Override
public boolean startInWriteAction() {
return true;
}
public void commentRange(int startOffset, int endOffset, String commentPrefix, String commentSuffix, Commenter commenter) {
CharSequence chars = myDocument.getCharsSequence();
LogicalPosition caretPosition = myEditor.getCaretModel().getLogicalPosition();
LogicalPosition caretPosition = myCaret.getLogicalPosition();
if (startOffset == 0 || chars.charAt(startOffset - 1) == '\n') {
if (endOffset == myDocument.getTextLength() || endOffset > 0 && chars.charAt(endOffset - 1) == '\n') {
@@ -426,21 +417,17 @@ public class CommentByBlockCommentHandler implements CodeInsightActionHandler {
nestingSuffix.append("\n");
TextRange range =
insertNestedComments(chars, startOffset, endOffset, nestingPrefix.toString(), nestingSuffix.toString(), commenter);
myEditor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
//myEditor.getSelectionModel().removeSelection();
myCaret.setSelection(range.getStartOffset(), range.getEndOffset());
LogicalPosition pos = new LogicalPosition(caretPosition.line + 1, caretPosition.column);
myEditor.getCaretModel().moveToLogicalPosition(pos);
myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
myCaret.moveToLogicalPosition(pos);
return;
}
}
TextRange range = insertNestedComments(chars, startOffset, endOffset, commentPrefix, commentSuffix, commenter);
myEditor.getSelectionModel().setSelection(range.getStartOffset(), range.getEndOffset());
//myEditor.getSelectionModel().removeSelection();
myCaret.setSelection(range.getStartOffset(), range.getEndOffset());
LogicalPosition pos = new LogicalPosition(caretPosition.line, caretPosition.column + commentPrefix.length());
myEditor.getCaretModel().moveToLogicalPosition(pos);
myEditor.getScrollingModel().scrollToCaret(ScrollType.RELATIVE);
myCaret.moveToLogicalPosition(pos);
}
private int doBoundCommentingAndGetShift(int offset,
@@ -1,5 +1,5 @@
/*
* Copyright 2000-2009 JetBrains s.r.o.
* Copyright 2000-2014 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.
@@ -16,11 +16,12 @@
package com.intellij.codeInsight.generation.actions;
import com.intellij.codeInsight.CodeInsightActionHandler;
import com.intellij.codeInsight.actions.BaseCodeInsightAction;
import com.intellij.codeInsight.actions.MultiCaretCodeInsightAction;
import com.intellij.codeInsight.actions.MultiCaretCodeInsightActionHandler;
import com.intellij.codeInsight.generation.CommentByBlockCommentHandler;
import com.intellij.lang.Commenter;
import com.intellij.lang.LanguageCommenters;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.fileTypes.impl.AbstractFileType;
@@ -29,19 +30,19 @@ import com.intellij.openapi.project.Project;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
public class CommentByBlockCommentAction extends BaseCodeInsightAction implements DumbAware {
public class CommentByBlockCommentAction extends MultiCaretCodeInsightAction implements DumbAware {
public CommentByBlockCommentAction() {
setEnabledInModalContext(true);
}
@NotNull
@Override
protected CodeInsightActionHandler getHandler() {
protected MultiCaretCodeInsightActionHandler getHandler() {
return new CommentByBlockCommentHandler();
}
@Override
protected boolean isValidForFile(@NotNull Project project, @NotNull Editor editor, @NotNull final PsiFile file) {
protected boolean isValidFor(@NotNull Project project, @NotNull Editor editor, @NotNull Caret caret, @NotNull final PsiFile file) {
final FileType fileType = file.getFileType();
if (fileType instanceof AbstractFileType) {
return ((AbstractFileType)fileType).getCommenter() != null;
@@ -15,17 +15,14 @@
*/
package com.intellij.injected.editor;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.LogicalPosition;
import com.intellij.openapi.editor.VisualPosition;
import com.intellij.openapi.editor.*;
import com.intellij.openapi.util.Key;
import com.intellij.openapi.util.ProperTextRange;
import com.intellij.openapi.util.TextRange;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
class InjectedCaret implements Caret {
public class InjectedCaret implements Caret {
private final EditorWindow myEditorWindow;
final Caret myDelegate;
@@ -34,12 +31,22 @@ class InjectedCaret implements Caret {
myDelegate = delegate;
}
@NotNull
@Override
public Editor getEditor() {
return myEditorWindow;
}
@NotNull
@Override
public CaretModel getCaretModel() {
return myEditorWindow.getCaretModel();
}
public Caret getDelegate() {
return myDelegate;
}
@Override
public boolean isValid() {
return myDelegate.isValid();
@@ -20,6 +20,7 @@ import com.intellij.injected.editor.*;
import com.intellij.lang.Language;
import com.intellij.lang.LanguageUtil;
import com.intellij.lang.injection.InjectedLanguageManager;
import com.intellij.openapi.editor.Caret;
import com.intellij.openapi.editor.Document;
import com.intellij.openapi.editor.Editor;
import com.intellij.openapi.editor.SelectionModel;
@@ -158,6 +159,22 @@ public class InjectedLanguageUtil {
return getEditorForInjectedLanguageNoCommit(editor, file, offset);
}
public static Caret getCaretForInjectedLanguageNoCommit(@Nullable Caret caret, @Nullable PsiFile file) {
if (caret == null || file == null || caret instanceof InjectedCaret) return caret;
PsiFile injectedFile = findInjectedPsiNoCommit(file, caret.getOffset());
Editor injectedEditor = getInjectedEditorForInjectedFile(caret.getEditor(), injectedFile);
if (!(injectedEditor instanceof EditorWindow)) {
return caret;
}
for (Caret injectedCaret : injectedEditor.getCaretModel().getAllCarets()) {
if (((InjectedCaret)injectedCaret).getDelegate() == caret) {
return injectedCaret;
}
}
return null;
}
public static Editor getEditorForInjectedLanguageNoCommit(@Nullable Editor editor, @Nullable PsiFile file, final int offset) {
if (editor == null || file == null || editor instanceof EditorWindow) return editor;
PsiFile injectedFile = findInjectedPsiNoCommit(file, offset);
@@ -1453,6 +1453,8 @@ public class CaretImpl extends UserDataHolderBase implements Caret {
return marker != null && marker.isValid() && isVirtualSelectionEnabled() && myEndVirtualOffset > myStartVirtualOffset;
}
@Override
@NotNull
public EditorImpl getEditor() {
return myEditor;
}
@@ -27,6 +27,12 @@ public class TextComponentCaret extends UserDataHolderBase implements Caret {
myEditor = editor;
}
@NotNull
@Override
public Editor getEditor() {
return myEditor;
}
@NotNull
@Override
public CaretModel getCaretModel() {