mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
WEB-24696, WEB-31891 Copy-paste from-to JSON strings now handles string escaping
This commit is contained in:
@@ -0,0 +1,72 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.json.editor;
|
||||
|
||||
import com.intellij.codeInsight.editorActions.CopyPastePreProcessor;
|
||||
import com.intellij.json.psi.JsonStringLiteral;
|
||||
import com.intellij.openapi.editor.Editor;
|
||||
import com.intellij.openapi.editor.RawText;
|
||||
import com.intellij.openapi.editor.SelectionModel;
|
||||
import com.intellij.openapi.project.Project;
|
||||
import com.intellij.openapi.util.TextRange;
|
||||
import com.intellij.openapi.util.text.StringUtil;
|
||||
import com.intellij.psi.PsiElement;
|
||||
import com.intellij.psi.PsiFile;
|
||||
import com.intellij.psi.util.PsiTreeUtil;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
public class JsonCopyPasteProcessor implements CopyPastePreProcessor {
|
||||
@Nullable
|
||||
@Override
|
||||
public String preprocessOnCopy(PsiFile file, int[] startOffsets, int[] endOffsets, String text) {
|
||||
if (!JsonEditorOptions.getInstance().ESCAPE_PASTED_TEXT) {
|
||||
return null;
|
||||
}
|
||||
if (!file.isPhysical() || startOffsets.length > 1 || endOffsets.length > 1) {
|
||||
return null;
|
||||
}
|
||||
final int selectionStart = startOffsets[0];
|
||||
final int selectionEnd = endOffsets[0];
|
||||
final JsonStringLiteral literalExpression = getSingleElementFromSelectionOrNull(file, selectionStart, selectionEnd);
|
||||
|
||||
if (literalExpression == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return StringUtil.unescapeStringCharacters(StringUtil.replaceUnicodeEscapeSequences(text));
|
||||
}
|
||||
|
||||
@Nullable
|
||||
private static JsonStringLiteral getSingleElementFromSelectionOrNull(PsiFile file, int start, int end) {
|
||||
final PsiElement element = file.findElementAt(start);
|
||||
final JsonStringLiteral literalExpression = PsiTreeUtil.getParentOfType(element, JsonStringLiteral.class);
|
||||
if (literalExpression == null) return null;
|
||||
TextRange textRange = literalExpression.getTextRange();
|
||||
if (start <= textRange.getStartOffset() || end >= textRange.getEndOffset()) return null;
|
||||
String text = literalExpression.getText();
|
||||
if (!text.startsWith("\"") || !text.endsWith("\"")) return null;
|
||||
return literalExpression;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public String preprocessOnPaste(Project project, PsiFile file, Editor editor, String text, RawText rawText) {
|
||||
if (!JsonEditorOptions.getInstance().ESCAPE_PASTED_TEXT) {
|
||||
return text;
|
||||
}
|
||||
if (!file.isPhysical()) {
|
||||
return text;
|
||||
}
|
||||
|
||||
final SelectionModel selectionModel = editor.getSelectionModel();
|
||||
final int selectionStart = selectionModel.getSelectionStart();
|
||||
final int selectionEnd = selectionModel.getSelectionEnd();
|
||||
|
||||
final JsonStringLiteral literalExpression = getSingleElementFromSelectionOrNull(file, selectionStart, selectionEnd);
|
||||
if (literalExpression == null) {
|
||||
return text;
|
||||
}
|
||||
|
||||
return StringUtil.escapeStringCharacters(text);
|
||||
}
|
||||
}
|
||||
@@ -16,6 +16,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
public class JsonEditorOptions implements PersistentStateComponent<JsonEditorOptions> {
|
||||
public boolean COMMA_ON_ENTER = true;
|
||||
public boolean COMMA_ON_MATCHING_BRACES = true;
|
||||
public boolean ESCAPE_PASTED_TEXT = true;
|
||||
|
||||
@Nullable
|
||||
@Override
|
||||
|
||||
@@ -18,6 +18,9 @@ public class JsonSmartKeysConfigurable extends BeanConfigurable<JsonEditorOption
|
||||
checkBox("Insert missing comma after matching braces and quotes",
|
||||
() -> settings.COMMA_ON_MATCHING_BRACES,
|
||||
v -> settings.COMMA_ON_MATCHING_BRACES = v);
|
||||
checkBox("Escape text on paste in string literals",
|
||||
() -> settings.ESCAPE_PASTED_TEXT,
|
||||
v -> settings.ESCAPE_PASTED_TEXT = v);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,48 @@
|
||||
// Copyright 2000-2018 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package com.intellij.json;
|
||||
|
||||
import com.intellij.openapi.actionSystem.IdeActions;
|
||||
import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase;
|
||||
|
||||
public class JsonCopyPasteTest extends CodeInsightFixtureTestCase {
|
||||
|
||||
private void doCopyPasteTest(String source, String dest, String expected, String filename1, String filename2) {
|
||||
myFixture.configureByText(filename1, source);
|
||||
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_COPY);
|
||||
myFixture.configureByText(filename2, dest);
|
||||
myFixture.performEditorAction(IdeActions.ACTION_EDITOR_PASTE);
|
||||
myFixture.checkResult(expected);
|
||||
}
|
||||
|
||||
private void doTestFromTextToJson(String source, String dest, String expected) {
|
||||
doCopyPasteTest(source, dest, expected, "dummy.txt", "dummy.json");
|
||||
}
|
||||
|
||||
private void doTestFromJsonToText(String source, String dest, String expected) {
|
||||
doCopyPasteTest(source, dest, expected, "dummy.json", "dummy.txt");
|
||||
}
|
||||
|
||||
public void testUnescapeQuotes() {
|
||||
doTestFromJsonToText("{\"p\": \"<selection>\\\"quoted\\\"</selection>\"}", "<caret>", "\"quoted\"");
|
||||
}
|
||||
|
||||
public void testUnescapeWhitespaces() {
|
||||
doTestFromJsonToText("{\"p\": \"<selection>lorem ipsum\\tdolor sit amet</selection>\"}", "<caret>", "lorem ipsum\tdolor sit amet");
|
||||
}
|
||||
|
||||
public void testUnescapeFromPropNames() {
|
||||
doTestFromJsonToText("{\"<selection>lorem ipsum\\tdolor sit amet</selection>\": \"foo\"}", "<caret>", "lorem ipsum\tdolor sit amet");
|
||||
}
|
||||
|
||||
public void testEscapeQuotes() {
|
||||
doTestFromTextToJson("<selection>\"quoted\"</selection>", "{\"p\": \"<caret>\"}", "{\"p\": \"\\\"quoted\\\"\"}");
|
||||
}
|
||||
|
||||
public void testEscapeWhitespaces() {
|
||||
doTestFromTextToJson("<selection>lorem ipsum\tdolor sit amet</selection>", "{\"p\": \"<caret>\"}", "{\"p\": \"lorem ipsum\\tdolor sit amet\"}");
|
||||
}
|
||||
|
||||
public void testEscapeInPropNames() {
|
||||
doTestFromTextToJson("<selection>lorem ipsum\tdolor sit amet</selection>", "{\"<caret>\": \"foo\"}", "{\"lorem ipsum\\tdolor sit amet\": \"foo\"}");
|
||||
}
|
||||
}
|
||||
@@ -33,6 +33,7 @@
|
||||
<enterBetweenBracesDelegate language="JSON" implementationClass="com.intellij.codeInsight.editorActions.enter.EnterBetweenBracesAndBracketsDelegate"/>
|
||||
<enterHandlerDelegate implementation="com.intellij.json.editor.JsonEnterHandler" id="JsonEnterHandler"/>
|
||||
<typedHandler implementation="com.intellij.json.editor.JsonTypedHandler" id="JsonTypedHandler"/>
|
||||
<copyPastePreProcessor implementation="com.intellij.json.editor.JsonCopyPasteProcessor"/>
|
||||
<editorSmartKeysConfigurable instance="com.intellij.json.editor.JsonSmartKeysConfigurable"/>
|
||||
<applicationService serviceInterface="com.intellij.json.editor.JsonEditorOptions"
|
||||
serviceImplementation="com.intellij.json.editor.JsonEditorOptions"/>
|
||||
|
||||
Reference in New Issue
Block a user