diff --git a/json/src/com/intellij/json/editor/JsonEditorOptions.java b/json/src/com/intellij/json/editor/JsonEditorOptions.java index f2d2f80a3280..cf4f311125dd 100644 --- a/json/src/com/intellij/json/editor/JsonEditorOptions.java +++ b/json/src/com/intellij/json/editor/JsonEditorOptions.java @@ -16,6 +16,7 @@ import org.jetbrains.annotations.Nullable; public class JsonEditorOptions implements PersistentStateComponent { public boolean COMMA_ON_ENTER = true; public boolean COMMA_ON_MATCHING_BRACES = true; + public boolean AUTO_QUOTE_PROP_NAME = true; public boolean ESCAPE_PASTED_TEXT = true; @Nullable diff --git a/json/src/com/intellij/json/editor/JsonSmartKeysConfigurable.java b/json/src/com/intellij/json/editor/JsonSmartKeysConfigurable.java index 6ebc99fc4efb..74b50729894b 100644 --- a/json/src/com/intellij/json/editor/JsonSmartKeysConfigurable.java +++ b/json/src/com/intellij/json/editor/JsonSmartKeysConfigurable.java @@ -21,6 +21,9 @@ public class JsonSmartKeysConfigurable extends BeanConfigurable settings.ESCAPE_PASTED_TEXT, v -> settings.ESCAPE_PASTED_TEXT = v); + checkBox("Automatically add quotes to property names when typing ':'", + () -> settings.AUTO_QUOTE_PROP_NAME, + v -> settings.AUTO_QUOTE_PROP_NAME = v); } @Override diff --git a/json/src/com/intellij/json/editor/JsonTypedHandler.java b/json/src/com/intellij/json/editor/JsonTypedHandler.java index 47327f98a1ac..0c4ca7cc6cec 100644 --- a/json/src/com/intellij/json/editor/JsonTypedHandler.java +++ b/json/src/com/intellij/json/editor/JsonTypedHandler.java @@ -3,9 +3,12 @@ package com.intellij.json.editor; import com.intellij.codeInsight.editorActions.TypedHandlerDelegate; import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor; +import com.intellij.json.JsonDialectUtil; import com.intellij.json.psi.*; import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiDocumentManager; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; @@ -22,9 +25,36 @@ public class JsonTypedHandler extends TypedHandlerDelegate { return Result.CONTINUE; } + @NotNull + @Override + public Result beforeCharTyped(char c, + @NotNull Project project, + @NotNull Editor editor, + @NotNull PsiFile file, + @NotNull FileType fileType) { + if (file instanceof JsonFile) { + addPropertyNameQuotesIfNeeded(c, editor, file); + } + return Result.CONTINUE; + } + + private static void addPropertyNameQuotesIfNeeded(char c, + @NotNull Editor editor, + @NotNull PsiFile file) { + if (c != ':' || !JsonDialectUtil.isStandardJson(file) || !JsonEditorOptions.getInstance().AUTO_QUOTE_PROP_NAME) return; + int offset = editor.getCaretModel().getOffset(); + PsiElement element = PsiTreeUtil.skipWhitespacesBackward(file.findElementAt(offset)); + if (!(element instanceof JsonProperty)) return; + final JsonValue nameElement = ((JsonProperty)element).getNameElement(); + if (nameElement instanceof JsonReferenceExpression) { + ((JsonProperty)element).setName(nameElement.getText()); + PsiDocumentManager.getInstance(file.getProject()).doPostponedOperationsAndUnblockDocument(editor.getDocument()); + } + } + public static void processPairedBracesComma(char c, - @NotNull Editor editor, - @NotNull PsiFile file) { + @NotNull Editor editor, + @NotNull PsiFile file) { if (!JsonEditorOptions.getInstance().COMMA_ON_MATCHING_BRACES) return; if (c != '[' && c != '{' && c != '"') return; SmartEnterProcessor.commitDocument(editor); diff --git a/json/tests/test/com/intellij/json/JsonTypingHandlingTest.java b/json/tests/test/com/intellij/json/JsonTypingHandlingTest.java index ee1b91290c3a..d890a564409b 100644 --- a/json/tests/test/com/intellij/json/JsonTypingHandlingTest.java +++ b/json/tests/test/com/intellij/json/JsonTypingHandlingTest.java @@ -16,6 +16,9 @@ public class JsonTypingHandlingTest extends JsonTestCase { private void doTestQuote(@NotNull final String before, @NotNull final String expected) { doTypingTest('"', before, expected, "json"); } + private void doTestColon(@NotNull final String before, @NotNull final String expected) { + doTypingTest(':', before, expected, "json"); + } @SuppressWarnings("SameParameterValue") private void doTypingTest(char c, @@ -63,4 +66,15 @@ public class JsonTypingHandlingTest extends JsonTestCase { public void testAutoCommaAfterQuoteInObject() { doTestQuote("{ \"x\": \"y\": {\"a\": 5} }", "{ \"x\": \"\", \"y\": {\"a\": 5} }"); } + public void testAutoQuotesForPropName() { + doTestColon( "{ x}", "{\n" + + " \"x\":\n" + + "}"); + } + public void testAutoQuotesForPropNameFalse1() { + doTestColon( "{ \"x\"}", "{ \"x\":}"); + } + public void testAutoQuotesForPropNameFalse2() { + doTestColon( "{ \"x\"}", "{ \"x:\"}"); + } }