mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
IDEA-90499 Ctrl+Backspace deletes delimiters instead of whitespaces only and leads to SyntaxErrors in code
Differentiate quotes processing between 'delete to word start' and 'move to word start' actions
This commit is contained in:
@@ -755,7 +755,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
|
||||
* @see FileTypeIndentOptionsProvider
|
||||
* @see LanguageCodeStyleSettingsProvider
|
||||
*/
|
||||
public IndentOptions getIndentOptions(FileType fileType) {
|
||||
public IndentOptions getIndentOptions(@Nullable FileType fileType) {
|
||||
IndentOptions indentOptions = getLanguageIndentOptions(fileType);
|
||||
if (indentOptions != null) return indentOptions;
|
||||
|
||||
@@ -771,7 +771,7 @@ public class CodeStyleSettings extends CommonCodeStyleSettings implements Clonea
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private IndentOptions getLanguageIndentOptions(FileType fileType) {
|
||||
private IndentOptions getLanguageIndentOptions(@Nullable FileType fileType) {
|
||||
if (fileType == null || !(fileType instanceof LanguageFileType)) return null;
|
||||
Language lang = ((LanguageFileType)fileType).getLanguage();
|
||||
CommonCodeStyleSettings langSettings = getCommonSettings(lang);
|
||||
|
||||
+86
-7
@@ -24,31 +24,110 @@
|
||||
*/
|
||||
package com.intellij.openapi.editor.actions;
|
||||
|
||||
import com.intellij.openapi.editor.CaretModel;
|
||||
import com.intellij.openapi.editor.Document;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorAction;
|
||||
import com.intellij.openapi.editor.actionSystem.EditorWriteActionHandler;
|
||||
import com.intellij.openapi.command.CommandProcessor;
|
||||
import com.intellij.openapi.actionSystem.DataContext;
|
||||
import gnu.trove.TIntHashSet;
|
||||
import gnu.trove.TIntIntHashMap;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class DeleteToWordStartAction extends TextComponentEditorAction {
|
||||
|
||||
/**
|
||||
* We need to provide special processing for quote symbols.
|
||||
* <p/>
|
||||
* Examples:
|
||||
* <table border='1'>
|
||||
* <tr>
|
||||
* <th>Text before action call</td>
|
||||
* <th>Text after action call</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>one "two" [caret]</td>
|
||||
* <td>one [caret]</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>one "two[caret]"</td>
|
||||
* <td>one "[caret]"</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*/
|
||||
private static final TIntHashSet QUOTE_SYMBOLS = new TIntHashSet();
|
||||
|
||||
static {
|
||||
QUOTE_SYMBOLS.add('\'');
|
||||
QUOTE_SYMBOLS.add('\"');
|
||||
}
|
||||
|
||||
private static final int[] QUOTE_SYMBOLS_ARRAY = QUOTE_SYMBOLS.toArray();
|
||||
|
||||
public DeleteToWordStartAction() {
|
||||
super(new Handler());
|
||||
}
|
||||
|
||||
private static class Handler extends EditorWriteActionHandler {
|
||||
|
||||
@NotNull private final TIntIntHashMap myQuotesNumber = new TIntIntHashMap();
|
||||
|
||||
@Override
|
||||
public void executeWriteAction(Editor editor, DataContext dataContext) {
|
||||
CommandProcessor.getInstance().setCurrentCommandGroupId(EditorActionUtil.DELETE_COMMAND_GROUP);
|
||||
deleteToWordStart(editor);
|
||||
}
|
||||
|
||||
private void deleteToWordStart(Editor editor) {
|
||||
CharSequence text = editor.getDocument().getCharsSequence();
|
||||
CaretModel caretModel = editor.getCaretModel();
|
||||
int endOffset = caretModel.getOffset();
|
||||
int minOffset = editor.getDocument().getLineStartOffset(caretModel.getLogicalPosition().line);
|
||||
|
||||
myQuotesNumber.clear();
|
||||
for (int i : QUOTE_SYMBOLS_ARRAY) {
|
||||
myQuotesNumber.put(i, 0);
|
||||
}
|
||||
countQuotes(myQuotesNumber, text, minOffset, endOffset);
|
||||
|
||||
EditorActionUtil.moveCaretToPreviousWord(editor, false);
|
||||
|
||||
for (int offset = caretModel.getOffset(); offset > minOffset; offset = caretModel.getOffset()) {
|
||||
char previous = text.charAt(offset - 1);
|
||||
char current = text.charAt(offset);
|
||||
if (QUOTE_SYMBOLS.contains(current)) {
|
||||
if (Character.isWhitespace(previous)) {
|
||||
break;
|
||||
}
|
||||
if (myQuotesNumber.get(current) % 2 == 0) {
|
||||
// Was 'one "two" [caret]', now 'one "two[caret]"', we want to get 'one [caret]"two"'
|
||||
EditorActionUtil.moveCaretToPreviousWord(editor, false);
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (QUOTE_SYMBOLS.contains(previous)) {
|
||||
if (myQuotesNumber.get(previous) % 2 == 0) {
|
||||
// Was 'one "two[caret]", now 'one "[caret]two"', we want 'one [caret]"two"'
|
||||
editor.getCaretModel().moveToOffset(offset - 1);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
int startOffset = caretModel.getOffset();
|
||||
Document document = editor.getDocument();
|
||||
document.deleteString(startOffset, endOffset);
|
||||
}
|
||||
}
|
||||
|
||||
private static void deleteToWordStart(Editor editor) {
|
||||
int endOffset = editor.getCaretModel().getOffset();
|
||||
EditorActionUtil.moveCaretToPreviousWord(editor, false);
|
||||
int startOffset = editor.getCaretModel().getOffset();
|
||||
Document document = editor.getDocument();
|
||||
document.deleteString(startOffset, endOffset);
|
||||
private static void countQuotes(@NotNull TIntIntHashMap holder, @NotNull CharSequence text, int start, int end) {
|
||||
for (int i = end - 1; i >= start; i--) {
|
||||
char c = text.charAt(i);
|
||||
if (holder.containsKey(c)) {
|
||||
holder.put(c, holder.get(c) + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+9
-27
@@ -44,7 +44,6 @@ import com.intellij.openapi.util.Pair;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.openapi.vfs.VirtualFile;
|
||||
import com.intellij.util.EditorPopupHandler;
|
||||
import gnu.trove.TIntHashSet;
|
||||
|
||||
import java.awt.*;
|
||||
import java.awt.event.MouseEvent;
|
||||
@@ -65,23 +64,16 @@ public class EditorActionUtil {
|
||||
* expect the caret to be located at the near future.
|
||||
*/
|
||||
public static final Key<Integer> EXPECTED_CARET_OFFSET = Key.create("expectedEditorOffset");
|
||||
|
||||
protected static final Object EDIT_COMMAND_GROUP = Key.create("EditGroup");
|
||||
public static final Object DELETE_COMMAND_GROUP = Key.create("DeleteGroup");
|
||||
|
||||
private static final TIntHashSet SPECIAL_NON_ID_SYMBOLS = new TIntHashSet();
|
||||
|
||||
static {
|
||||
SPECIAL_NON_ID_SYMBOLS.add('\'');
|
||||
SPECIAL_NON_ID_SYMBOLS.add('\"');
|
||||
}
|
||||
|
||||
protected static final Object EDIT_COMMAND_GROUP = Key.create("EditGroup");
|
||||
public static final Object DELETE_COMMAND_GROUP = Key.create("DeleteGroup");
|
||||
|
||||
private EditorActionUtil() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to change given editor's viewport position in vertical dimension by the given number of visual lines.
|
||||
*
|
||||
*
|
||||
* @param editor target editor which viewport position should be changed
|
||||
* @param lineShift defines viewport position's vertical change length
|
||||
* @param columnShift defines viewport position's horizontal change length
|
||||
@@ -102,7 +94,7 @@ public class EditorActionUtil {
|
||||
if (!moveCaret) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
Rectangle viewRectangle = editor.getScrollingModel().getVisibleArea();
|
||||
int lineNumber = editor.getCaretModel().getVisualPosition().line;
|
||||
if (viewRectangle != null) {
|
||||
@@ -228,26 +220,16 @@ public class EditorActionUtil {
|
||||
|
||||
final boolean firstIsIdentifierPart = Character.isJavaIdentifierPart(prev);
|
||||
final boolean secondIsIdentifierPart = Character.isJavaIdentifierPart(current);
|
||||
if (!firstIsIdentifierPart && secondIsIdentifierPart && !SPECIAL_NON_ID_SYMBOLS.contains(prev)) {
|
||||
if (!firstIsIdentifierPart && secondIsIdentifierPart) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (isCamel && firstIsIdentifierPart && secondIsIdentifierPart && isHumpBound(text, offset, true)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Character.isWhitespace(current)) {
|
||||
return false;
|
||||
}
|
||||
else if (Character.isWhitespace(prev)) {
|
||||
return true;
|
||||
}
|
||||
else if (SPECIAL_NON_ID_SYMBOLS.contains(current)) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return firstIsIdentifierPart && !secondIsIdentifierPart;
|
||||
}
|
||||
|
||||
return (Character.isWhitespace(prev) || firstIsIdentifierPart) &&
|
||||
!Character.isWhitespace(current) && !secondIsIdentifierPart;
|
||||
}
|
||||
|
||||
private static boolean isLowerCaseOrDigit(char c) {
|
||||
|
||||
Reference in New Issue
Block a user