summaryrefslogtreecommitdiff
path: root/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectionQuotingTypedHandler.java
diff options
context:
space:
mode:
Diffstat (limited to 'platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectionQuotingTypedHandler.java')
-rw-r--r--platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectionQuotingTypedHandler.java149
1 files changed, 61 insertions, 88 deletions
diff --git a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectionQuotingTypedHandler.java b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectionQuotingTypedHandler.java
index 954b804561ce..76dc70fe7116 100644
--- a/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectionQuotingTypedHandler.java
+++ b/platform/lang-impl/src/com/intellij/codeInsight/editorActions/SelectionQuotingTypedHandler.java
@@ -17,19 +17,16 @@ package com.intellij.codeInsight.editorActions;
import com.intellij.codeInsight.CodeInsightSettings;
import com.intellij.injected.editor.EditorWindow;
-import com.intellij.openapi.editor.Caret;
-import com.intellij.openapi.editor.CaretAction;
+import com.intellij.openapi.editor.CaretModel;
import com.intellij.openapi.editor.Editor;
+import com.intellij.openapi.editor.SelectionModel;
import com.intellij.openapi.editor.ex.EditorEx;
import com.intellij.openapi.extensions.ExtensionPointName;
import com.intellij.openapi.extensions.Extensions;
import com.intellij.openapi.fileTypes.FileType;
import com.intellij.openapi.project.Project;
-import com.intellij.openapi.util.Key;
-import com.intellij.openapi.util.Ref;
import com.intellij.openapi.util.TextRange;
import com.intellij.openapi.util.registry.Registry;
-import com.intellij.openapi.util.text.StringUtil;
import com.intellij.psi.PsiFile;
import org.jetbrains.annotations.NotNull;
@@ -40,63 +37,49 @@ import org.jetbrains.annotations.NotNull;
public class SelectionQuotingTypedHandler extends TypedHandlerDelegate {
public static final ExtensionPointName<DequotingFilter> EP_NAME =
ExtensionPointName.create("com.intellij.selectionDequotingFilter");
+ private TextRange myReplacedTextRange;
private boolean myRestoreStickySelection;
-
- private static final Key<String> REPLACEMENT_TEXT = Key.create("SelectionQuotingTypedHandler.replacementText");
- private static final Key<TextRange> REPLACED_TEXT_RANGE = Key.create("SelectionQuotingTypedHandler.replacedTextRange");
- private static final Key<Boolean> LTR_SELECTION = Key.create("SelectionQuotingTypedHandler.ltrSelection");
+ private boolean myLtrSelection;
@Override
- public Result checkAutoPopup(final char c, Project project, final Editor editor, final PsiFile psiFile) {
+ public Result checkAutoPopup(char c, Project project, Editor editor, PsiFile psiFile) {
// TODO[oleg] provide adequate API not to use this hack
// beforeCharTyped always works with removed selection
- if(CodeInsightSettings.getInstance().SURROUND_SELECTION_ON_QUOTE_TYPED && editor.getSelectionModel().hasSelection(true) && isDelimiter(c)) {
- myRestoreStickySelection = (editor instanceof EditorEx) && ((EditorEx)editor).isStickySelection();
-
- // first we determine replacement texts for each caret, then we apply all the changes
- // this is to make PSI consistent with document state for the calculation of replacement text for all carets
- editor.getCaretModel().runForEachCaret(new CaretAction() {
- @Override
- public void perform(Caret caret) {
- String replacementText = null;
- String selectedText = caret.getSelectedText();
- if (!StringUtil.isEmpty(selectedText)) {
- if (selectedText.length() > 1) {
- final char firstChar = selectedText.charAt(0);
- final char lastChar = selectedText.charAt(selectedText.length() - 1);
- if (isSimilarDelimiters(firstChar, c) && lastChar == getMatchingDelimiter(firstChar) &&
- (isQuote(firstChar) || firstChar != c) && !shouldSkipReplacementOfQuotesOrBraces(psiFile, editor, selectedText, c) &&
- selectedText.indexOf(lastChar, 1) == selectedText.length() - 1) {
- selectedText = selectedText.substring(1, selectedText.length() - 1);
- }
- }
- final char c2 = getMatchingDelimiter(c);
- replacementText = String.valueOf(c) + selectedText + c2;
- }
- caret.putUserData(REPLACEMENT_TEXT, replacementText);
- }
- });
- editor.getCaretModel().runForEachCaret(new CaretAction() {
- @Override
- public void perform(Caret caret) {
- String replacementText = caret.getUserData(REPLACEMENT_TEXT);
- caret.putUserData(REPLACEMENT_TEXT, null);
- if (replacementText == null) {
- caret.putUserData(LTR_SELECTION, null);
- caret.putUserData(REPLACED_TEXT_RANGE, null);
- }
- else {
- int selectionStart = caret.getSelectionStart();
- int selectionEnd = caret.getSelectionEnd();
- caret.putUserData(LTR_SELECTION, caret.getLeadSelectionOffset() != selectionEnd);
- caret.putUserData(REPLACED_TEXT_RANGE, Registry.is("editor.smarterSelectionQuoting")
- ? new TextRange(selectionStart + 1, selectionStart + replacementText.length() - 1)
- : new TextRange(selectionStart, selectionStart + replacementText.length()));
- caret.removeSelection();
- editor.getDocument().replaceString(selectionStart, selectionEnd, replacementText);
- }
+ SelectionModel selectionModel = editor.getSelectionModel();
+ if(CodeInsightSettings.getInstance().SURROUND_SELECTION_ON_QUOTE_TYPED && selectionModel.hasSelection() && isDelimiter(c)) {
+ String selectedText = selectionModel.getSelectedText();
+ if (selectedText.length() < 1) {
+ return super.checkAutoPopup(c, project, editor, psiFile);
+ }
+
+ final int selectionStart = selectionModel.getSelectionStart();
+ final int selectionEnd = selectionModel.getSelectionEnd();
+ if (selectedText.length() > 1) {
+ final char firstChar = selectedText.charAt(0);
+ final char lastChar = selectedText.charAt(selectedText.length() - 1);
+ if (isSimilarDelimiters(firstChar, c) && lastChar == getMatchingDelimiter(firstChar) &&
+ (isQuote(firstChar) || firstChar != c) && !shouldSkipReplacementOfQuotesOrBraces(psiFile, editor, selectedText, c) &&
+ selectedText.indexOf(lastChar, 1) == selectedText.length() - 1) {
+ selectedText = selectedText.substring(1, selectedText.length() - 1);
}
- });
+ }
+ final int caretOffset = selectionModel.getSelectionStart();
+ final char c2 = getMatchingDelimiter(c);
+ final String newText = String.valueOf(c) + selectedText + c2;
+ myLtrSelection = selectionModel.getLeadSelectionOffset() != selectionModel.getSelectionEnd();
+ if (editor instanceof EditorEx) {
+ myRestoreStickySelection = ((EditorEx)editor).isStickySelection();
+ }
+ else {
+ myRestoreStickySelection = false;
+ }
+ selectionModel.removeSelection();
+ editor.getDocument().replaceString(selectionStart, selectionEnd, newText);
+ if (Registry.is("editor.smarterSelectionQuoting")) {
+ myReplacedTextRange = new TextRange(caretOffset + 1, caretOffset + newText.length() - 1);
+ } else {
+ myReplacedTextRange = new TextRange(caretOffset, caretOffset + newText.length());
+ }
return Result.STOP;
}
return super.checkAutoPopup(c, project, editor, psiFile);
@@ -136,41 +119,31 @@ public class SelectionQuotingTypedHandler extends TypedHandlerDelegate {
@Override
public Result beforeCharTyped(final char charTyped, final Project project, final Editor editor, final PsiFile file, final FileType fileType) {
// TODO[oleg] remove this hack when API changes
- final Ref<Boolean> caretUpdated = new Ref<Boolean>(Boolean.FALSE);
- editor.getCaretModel().runForEachCaret(new CaretAction() {
- @Override
- public void perform(Caret caret) {
- TextRange replacedTextRange = caret.getUserData(REPLACED_TEXT_RANGE);
- caret.putUserData(REPLACED_TEXT_RANGE, null);
- if (replacedTextRange != null) {
- Boolean ltrSelectionBoxed = caret.getUserData(LTR_SELECTION);
- caret.putUserData(LTR_SELECTION, null);
- boolean ltrSelection = ltrSelectionBoxed == null ? false : ltrSelectionBoxed;
- if (replacedTextRange.getEndOffset() <= editor.getDocument().getTextLength()) {
- if (myRestoreStickySelection && editor instanceof EditorEx) {
- EditorEx editorEx = (EditorEx)editor;
- editorEx.setStickySelection(false);
- caret.moveToOffset(ltrSelection ? replacedTextRange.getStartOffset() : replacedTextRange.getEndOffset());
- editorEx.setStickySelection(true);
- caret.moveToOffset(ltrSelection ? replacedTextRange.getEndOffset() : replacedTextRange.getStartOffset());
- }
- else {
- if (ltrSelection || editor instanceof EditorWindow) {
- caret.setSelection(replacedTextRange.getStartOffset(), replacedTextRange.getEndOffset());
- }
- else {
- caret.setSelection(replacedTextRange.getEndOffset(), replacedTextRange.getStartOffset());
- }
- if (Registry.is("editor.smarterSelectionQuoting")) {
- caret.moveToOffset(ltrSelection ? replacedTextRange.getEndOffset() : replacedTextRange.getStartOffset());
- }
- }
+ if (myReplacedTextRange != null) {
+ if (myReplacedTextRange.getEndOffset() <= editor.getDocument().getTextLength()) {
+ if (myRestoreStickySelection && editor instanceof EditorEx) {
+ EditorEx editorEx = (EditorEx)editor;
+ CaretModel caretModel = editorEx.getCaretModel();
+ caretModel.moveToOffset(myLtrSelection ? myReplacedTextRange.getStartOffset() : myReplacedTextRange.getEndOffset());
+ editorEx.setStickySelection(true);
+ caretModel.moveToOffset(myLtrSelection ? myReplacedTextRange.getEndOffset() : myReplacedTextRange.getStartOffset());
+ }
+ else {
+ if (myLtrSelection || editor instanceof EditorWindow) {
+ editor.getSelectionModel().setSelection(myReplacedTextRange.getStartOffset(), myReplacedTextRange.getEndOffset());
+ }
+ else {
+ editor.getSelectionModel().setSelection(myReplacedTextRange.getEndOffset(), myReplacedTextRange.getStartOffset());
+ }
+ if (Registry.is("editor.smarterSelectionQuoting")) {
+ editor.getCaretModel().moveToOffset(myLtrSelection ? myReplacedTextRange.getEndOffset() : myReplacedTextRange.getStartOffset());
}
- caretUpdated.set(Boolean.TRUE);
}
}
- });
- return caretUpdated.get() ? Result.STOP : Result.CONTINUE;
+ myReplacedTextRange = null;
+ return Result.STOP;
+ }
+ return Result.CONTINUE;
}
public static abstract class DequotingFilter {