mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-121060 Multiple carets: comment/uncomment works incorrectly
Fix for 'comment by block comment' action
This commit is contained in:
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+133
@@ -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;
|
||||
}
|
||||
}
|
||||
+26
@@ -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);
|
||||
}
|
||||
+41
-54
@@ -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,
|
||||
|
||||
+7
-6
@@ -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();
|
||||
|
||||
+17
@@ -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;
|
||||
}
|
||||
|
||||
+6
@@ -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() {
|
||||
|
||||
Reference in New Issue
Block a user