From 164dc6614e0f60a48ccf681e6a414b2338823852 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 28 Oct 2013 21:05:40 +0400 Subject: [PATCH 01/85] Add new plugin/module in project. Migrate GrammarKit based JSON parser from appcode-json. --- .idea/modules.xml | 5 +- plugins/json/META-INF/plugin.xml | 42 ++ .../com/jetbrains/json/JsonParserTypes.java | 54 ++ .../com/jetbrains/json/JsonParserUtil.java | 9 + .../json/gen/com/jetbrains/json/Parser.java | 251 ++++++++ .../gen/com/jetbrains/json/_JsonLexer.java | 558 ++++++++++++++++++ .../gen/com/jetbrains/json/psi/JsonArray.java | 13 + .../com/jetbrains/json/psi/JsonLiteral.java | 12 + .../com/jetbrains/json/psi/JsonObject.java | 16 + .../com/jetbrains/json/psi/JsonProperty.java | 21 + .../jetbrains/json/psi/JsonPropertyName.java | 10 + .../jetbrains/json/psi/JsonPropertyValue.java | 10 + .../com/jetbrains/json/psi/JsonVisitor.java | 38 ++ .../json/psi/impl/JsonArrayImpl.java | 30 + .../json/psi/impl/JsonLiteralImpl.java | 28 + .../json/psi/impl/JsonObjectImpl.java | 35 ++ .../json/psi/impl/JsonPropertyImpl.java | 46 ++ .../json/psi/impl/JsonPropertyNameImpl.java | 25 + .../json/psi/impl/JsonPropertyValueImpl.java | 25 + plugins/json/json.iml | 14 + .../com/jetbrains/json/JsonElementType.java | 11 + .../json/src/com/jetbrains/json/JsonFile.java | 21 + .../src/com/jetbrains/json/JsonLanguage.java | 12 + .../json/JsonParserDefinitionBase.java | 75 +++ .../json/JsonSyntaxHighlighterFactory.java | 57 ++ .../src/com/jetbrains/json/JsonTokenType.java | 11 + .../json/psi/JsonLiteralManipulator.java | 24 + .../json/psi/JsonPsiChangeUtils.java | 61 ++ .../jetbrains/json/psi/JsonPsiImplUtils.java | 37 ++ .../json/psi/impl/JsonLiteralMixin.java | 33 ++ plugins/json/src/json.bnf | 56 ++ plugins/json/src/json.flex | 54 ++ 32 files changed, 1692 insertions(+), 2 deletions(-) create mode 100644 plugins/json/META-INF/plugin.xml create mode 100644 plugins/json/gen/com/jetbrains/json/JsonParserTypes.java create mode 100644 plugins/json/gen/com/jetbrains/json/JsonParserUtil.java create mode 100644 plugins/json/gen/com/jetbrains/json/Parser.java create mode 100644 plugins/json/gen/com/jetbrains/json/_JsonLexer.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonArray.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonObject.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonPropertyValue.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java create mode 100644 plugins/json/json.iml create mode 100644 plugins/json/src/com/jetbrains/json/JsonElementType.java create mode 100644 plugins/json/src/com/jetbrains/json/JsonFile.java create mode 100644 plugins/json/src/com/jetbrains/json/JsonLanguage.java create mode 100644 plugins/json/src/com/jetbrains/json/JsonParserDefinitionBase.java create mode 100644 plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java create mode 100644 plugins/json/src/com/jetbrains/json/JsonTokenType.java create mode 100644 plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java create mode 100644 plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java create mode 100644 plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java create mode 100644 plugins/json/src/com/jetbrains/json/psi/impl/JsonLiteralMixin.java create mode 100644 plugins/json/src/json.bnf create mode 100644 plugins/json/src/json.flex diff --git a/.idea/modules.xml b/.idea/modules.xml index b01a3db7ff6b..a70d2ed28116 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -94,6 +94,7 @@ + @@ -173,6 +174,8 @@ + + @@ -182,8 +185,6 @@ - - diff --git a/plugins/json/META-INF/plugin.xml b/plugins/json/META-INF/plugin.xml new file mode 100644 index 000000000000..42edb8789f74 --- /dev/null +++ b/plugins/json/META-INF/plugin.xml @@ -0,0 +1,42 @@ + + com.intellij.json + JSON support for IntelliJ IDEA + 1.0 + JetBrains + + + most HTML tags may be used + ]]> + + + most HTML tags may be used + ]]> + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/plugins/json/gen/com/jetbrains/json/JsonParserTypes.java b/plugins/json/gen/com/jetbrains/json/JsonParserTypes.java new file mode 100644 index 000000000000..0e63ec9e5fea --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/JsonParserTypes.java @@ -0,0 +1,54 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json; + +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.PsiElement; +import com.intellij.lang.ASTNode; +import com.jetbrains.json.psi.impl.*; + +public interface JsonParserTypes { + + IElementType ARRAY = new JsonElementType("ARRAY"); + IElementType LITERAL = new JsonElementType("LITERAL"); + IElementType OBJECT = new JsonElementType("OBJECT"); + IElementType PROPERTY = new JsonElementType("PROPERTY"); + IElementType PROPERTY_NAME = new JsonElementType("PROPERTY_NAME"); + IElementType PROPERTY_VALUE = new JsonElementType("PROPERTY_VALUE"); + + IElementType COLON = new JsonTokenType(":"); + IElementType COMMA = new JsonTokenType(","); + IElementType FALSE = new JsonTokenType("false"); + IElementType L_BRAKET = new JsonTokenType("["); + IElementType L_CURLY = new JsonTokenType("{"); + IElementType NULL = new JsonTokenType("null"); + IElementType NUMBER = new JsonTokenType("NUMBER"); + IElementType R_BRAKET = new JsonTokenType("]"); + IElementType R_CURLY = new JsonTokenType("}"); + IElementType STRING = new JsonTokenType("STRING"); + IElementType TRUE = new JsonTokenType("true"); + + class Factory { + public static PsiElement createElement(ASTNode node) { + IElementType type = node.getElementType(); + if (type == ARRAY) { + return new JsonArrayImpl(node); + } + else if (type == LITERAL) { + return new JsonLiteralImpl(node); + } + else if (type == OBJECT) { + return new JsonObjectImpl(node); + } + else if (type == PROPERTY) { + return new JsonPropertyImpl(node); + } + else if (type == PROPERTY_NAME) { + return new JsonPropertyNameImpl(node); + } + else if (type == PROPERTY_VALUE) { + return new JsonPropertyValueImpl(node); + } + throw new AssertionError("Unknown element type: " + type); + } + } +} diff --git a/plugins/json/gen/com/jetbrains/json/JsonParserUtil.java b/plugins/json/gen/com/jetbrains/json/JsonParserUtil.java new file mode 100644 index 000000000000..dd82e3a43f36 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/JsonParserUtil.java @@ -0,0 +1,9 @@ +package com.jetbrains.json; + +import com.intellij.lang.parser.GeneratedParserUtilBase; + +/** + * @author Mikhail Golubev + */ +public class JsonParserUtil extends GeneratedParserUtilBase { +} diff --git a/plugins/json/gen/com/jetbrains/json/Parser.java b/plugins/json/gen/com/jetbrains/json/Parser.java new file mode 100644 index 000000000000..335faf04e5d3 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/Parser.java @@ -0,0 +1,251 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json; + +import com.intellij.lang.PsiBuilder; +import com.intellij.lang.PsiBuilder.Marker; +import com.intellij.openapi.diagnostic.Logger; +import static com.jetbrains.json.JsonParserTypes.*; +import static com.intellij.lang.parser.GeneratedParserUtilBase.*; +import com.intellij.psi.tree.IElementType; +import com.intellij.lang.ASTNode; +import com.intellij.psi.tree.TokenSet; +import com.intellij.lang.PsiParser; + +@SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"}) +public class Parser implements PsiParser { + + public static final Logger LOG_ = Logger.getInstance("com.jetbrains.json.Parser"); + + public ASTNode parse(IElementType root_, PsiBuilder builder_) { + int level_ = 0; + boolean result_; + builder_ = adapt_builder_(root_, builder_, this, EXTENDS_SETS_); + if (root_ == ARRAY) { + result_ = array(builder_, level_ + 1); + } + else if (root_ == LITERAL) { + result_ = literal(builder_, level_ + 1); + } + else if (root_ == OBJECT) { + result_ = object(builder_, level_ + 1); + } + else if (root_ == PROPERTY) { + result_ = property(builder_, level_ + 1); + } + else if (root_ == PROPERTY_NAME) { + result_ = property_name(builder_, level_ + 1); + } + else if (root_ == PROPERTY_VALUE) { + result_ = property_value(builder_, level_ + 1); + } + else { + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); + result_ = parse_root_(root_, builder_, level_); + exit_section_(builder_, level_, marker_, root_, result_, true, TOKEN_ADVANCER); + } + return builder_.getTreeBuilt(); + } + + protected boolean parse_root_(final IElementType root_, final PsiBuilder builder_, final int level_) { + return json(builder_, level_ + 1); + } + + public static final TokenSet[] EXTENDS_SETS_ = new TokenSet[] { + create_token_set_(ARRAY, LITERAL, OBJECT, PROPERTY_VALUE), + }; + + /* ********************************************************** */ + // L_BRAKET values? R_BRAKET + public static boolean array(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array")) return false; + if (!nextTokenIs(builder_, L_BRAKET)) return false; + boolean result_ = false; + boolean pinned_ = false; + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); + result_ = consumeToken(builder_, L_BRAKET); + pinned_ = result_; // pin = 1 + result_ = result_ && report_error_(builder_, array_1(builder_, level_ + 1)); + result_ = pinned_ && consumeToken(builder_, R_BRAKET) && result_; + exit_section_(builder_, level_, marker_, ARRAY, result_, pinned_, null); + return result_ || pinned_; + } + + // values? + private static boolean array_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_1")) return false; + values(builder_, level_ + 1); + return true; + } + + /* ********************************************************** */ + // object | array + static boolean json(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "json")) return false; + if (!nextTokenIs(builder_, L_BRAKET) && !nextTokenIs(builder_, L_CURLY)) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = object(builder_, level_ + 1); + if (!result_) result_ = array(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + /* ********************************************************** */ + // STRING | NUMBER | TRUE | FALSE | NULL + public static boolean literal(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "literal")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); + result_ = consumeToken(builder_, STRING); + if (!result_) result_ = consumeToken(builder_, NUMBER); + if (!result_) result_ = consumeToken(builder_, TRUE); + if (!result_) result_ = consumeToken(builder_, FALSE); + if (!result_) result_ = consumeToken(builder_, NULL); + exit_section_(builder_, level_, marker_, LITERAL, result_, false, null); + return result_; + } + + /* ********************************************************** */ + // L_CURLY properties? R_CURLY + public static boolean object(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "object")) return false; + if (!nextTokenIs(builder_, L_CURLY)) return false; + boolean result_ = false; + boolean pinned_ = false; + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); + result_ = consumeToken(builder_, L_CURLY); + pinned_ = result_; // pin = 1 + result_ = result_ && report_error_(builder_, object_1(builder_, level_ + 1)); + result_ = pinned_ && consumeToken(builder_, R_CURLY) && result_; + exit_section_(builder_, level_, marker_, OBJECT, result_, pinned_, null); + return result_ || pinned_; + } + + // properties? + private static boolean object_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "object_1")) return false; + properties(builder_, level_ + 1); + return true; + } + + /* ********************************************************** */ + // property (COMMA property)* + static boolean properties(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "properties")) return false; + if (!nextTokenIs(builder_, STRING)) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = property(builder_, level_ + 1); + result_ = result_ && properties_1(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // (COMMA property)* + private static boolean properties_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "properties_1")) return false; + int offset_ = builder_.getCurrentOffset(); + while (true) { + if (!properties_1_0(builder_, level_ + 1)) break; + int next_offset_ = builder_.getCurrentOffset(); + if (offset_ == next_offset_) { + empty_element_parsed_guard_(builder_, offset_, "properties_1"); + break; + } + offset_ = next_offset_; + } + return true; + } + + // COMMA property + private static boolean properties_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "properties_1_0")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, COMMA); + result_ = result_ && property(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + /* ********************************************************** */ + // property_name COLON property_value + public static boolean property(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "property")) return false; + if (!nextTokenIs(builder_, STRING)) return false; + boolean result_ = false; + boolean pinned_ = false; + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); + result_ = property_name(builder_, level_ + 1); + pinned_ = result_; // pin = 1 + result_ = result_ && report_error_(builder_, consumeToken(builder_, COLON)); + result_ = pinned_ && property_value(builder_, level_ + 1) && result_; + exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, null); + return result_ || pinned_; + } + + /* ********************************************************** */ + // STRING + public static boolean property_name(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "property_name")) return false; + if (!nextTokenIs(builder_, STRING)) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, STRING); + exit_section_(builder_, marker_, PROPERTY_NAME, result_); + return result_; + } + + /* ********************************************************** */ + // object | array | literal + public static boolean property_value(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "property_value")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); + result_ = object(builder_, level_ + 1); + if (!result_) result_ = array(builder_, level_ + 1); + if (!result_) result_ = literal(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, PROPERTY_VALUE, result_, false, null); + return result_; + } + + /* ********************************************************** */ + // property_value (COMMA property_value)* + static boolean values(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "values")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = property_value(builder_, level_ + 1); + result_ = result_ && values_1(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // (COMMA property_value)* + private static boolean values_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "values_1")) return false; + int offset_ = builder_.getCurrentOffset(); + while (true) { + if (!values_1_0(builder_, level_ + 1)) break; + int next_offset_ = builder_.getCurrentOffset(); + if (offset_ == next_offset_) { + empty_element_parsed_guard_(builder_, offset_, "values_1"); + break; + } + offset_ = next_offset_; + } + return true; + } + + // COMMA property_value + private static boolean values_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "values_1_0")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, COMMA); + result_ = result_ && property_value(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java new file mode 100644 index 000000000000..f5601dbad561 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java @@ -0,0 +1,558 @@ +/* The following code was generated by JFlex 1.4.3 on 10/28/13 8:52 PM */ + +package com.jetbrains.json; +import com.intellij.lexer.*; +import com.intellij.psi.tree.IElementType; +import static com.jetbrains.json.JsonParserTypes.*; + + +/** + * This class is a scanner generated by + * JFlex 1.4.3 + * on 10/28/13 8:52 PM from the specification file + * json.flex + */ +public class _JsonLexer implements FlexLexer { + /** initial size of the lookahead buffer */ + private static final int ZZ_BUFFERSIZE = 16384; + + /** lexical states */ + public static final int YYINITIAL = 0; + + /** + * ZZ_LEXSTATE[l] is the state in the DFA for the lexical state l + * ZZ_LEXSTATE[l+1] is the state in the DFA for the lexical state l + * at the beginning of a line + * l is of the form l = 2*k, k a non negative integer + */ + private static final int ZZ_LEXSTATE[] = { + 0, 0 + }; + + /** + * Translates characters to character classes + */ + private static final String ZZ_CMAP_PACKED = + "\11\0\2\1\2\0\1\1\22\0\1\1\1\0\1\10\10\0\1\23"+ + "\1\6\1\16\1\21\1\12\12\20\1\7\6\0\4\14\1\22\1\14"+ + "\24\0\1\4\1\11\1\5\3\0\1\30\1\15\2\14\1\26\1\27"+ + "\5\0\1\31\1\0\1\33\3\0\1\25\1\32\1\24\1\13\5\0"+ + "\1\2\1\0\1\3\u05e2\0\12\17\206\0\12\17\306\0\12\17\u019c\0"+ + "\12\17\166\0\12\17\166\0\12\17\166\0\12\17\166\0\12\17\166\0"+ + "\12\17\166\0\12\17\166\0\12\17\166\0\12\17\340\0\12\17\166\0"+ + "\12\17\106\0\12\17\u0116\0\12\17\106\0\12\17\u0746\0\12\17\46\0"+ + "\12\17\u012c\0\12\17\200\0\12\17\246\0\12\17\6\0\12\17\266\0"+ + "\12\17\126\0\12\17\206\0\12\17\6\0\12\17\u89c6\0\12\17\u02a6\0"+ + "\12\17\46\0\12\17\306\0\12\17\166\0\12\17\u0196\0\12\17\u5316\0"+ + "\12\17\346\0"; + + /** + * Translates characters to character classes + */ + private static final char [] ZZ_CMAP = zzUnpackCMap(ZZ_CMAP_PACKED); + + /** + * Translates DFA states to action switch labels. + */ + private static final int [] ZZ_ACTION = zzUnpackAction(); + + private static final String ZZ_ACTION_PACKED_0 = + "\1\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7"+ + "\1\10\2\1\1\11\3\1\1\0\1\12\6\0\1\11"+ + "\5\0\1\13\1\0\1\14\2\0\1\11\1\15\1\0"; + + private static int [] zzUnpackAction() { + int [] result = new int[37]; + int offset = 0; + offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAction(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /** + * Translates a state to a row index in the transition table + */ + private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); + + private static final String ZZ_ROWMAP_PACKED_0 = + "\0\0\0\34\0\70\0\34\0\34\0\34\0\34\0\34"+ + "\0\34\0\124\0\160\0\214\0\250\0\304\0\340\0\124"+ + "\0\34\0\374\0\u0118\0\u0134\0\u0150\0\u016c\0\u0188\0\u01a4"+ + "\0\u01c0\0\u01dc\0\u01f8\0\u0214\0\u0230\0\34\0\u024c\0\34"+ + "\0\u0268\0\u0284\0\u0284\0\34\0\u02a0"; + + private static int [] zzUnpackRowMap() { + int [] result = new int[37]; + int offset = 0; + offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackRowMap(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int high = packed.charAt(i++) << 16; + result[j++] = high | packed.charAt(i++); + } + return j; + } + + /** + * The transition table of the DFA + */ + private static final int [] ZZ_TRANS = zzUnpackTrans(); + + private static final String ZZ_TRANS_PACKED_0 = + "\1\2\1\3\1\4\1\5\1\6\1\7\1\10\1\11"+ + "\1\12\5\2\1\13\2\14\3\2\1\15\2\2\1\16"+ + "\3\2\1\17\35\0\1\3\32\0\10\20\1\21\1\22"+ + "\22\20\17\0\2\14\32\0\2\14\1\23\37\0\1\24"+ + "\36\0\1\25\16\0\1\26\30\0\3\20\1\27\1\0"+ + "\1\20\6\0\2\20\1\0\1\20\3\0\1\20\17\0"+ + "\2\30\26\0\1\31\51\0\1\32\33\0\1\33\16\0"+ + "\2\34\2\0\1\34\1\0\1\34\3\0\3\34\22\0"+ + "\2\30\1\0\1\35\3\0\1\35\33\0\1\36\37\0"+ + "\1\37\32\0\1\40\16\0\2\41\2\0\1\41\1\0"+ + "\1\41\3\0\3\41\21\0\1\42\2\43\2\0\1\42"+ + "\36\0\1\44\21\0\2\45\2\0\1\45\1\0\1\45"+ + "\3\0\3\45\22\0\2\43\27\0\2\20\2\0\1\20"+ + "\1\0\1\20\3\0\3\20\3\0"; + + private static int [] zzUnpackTrans() { + int [] result = new int[700]; + int offset = 0; + offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackTrans(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + value--; + do result[j++] = value; while (--count > 0); + } + return j; + } + + + /* error codes */ + private static final int ZZ_UNKNOWN_ERROR = 0; + private static final int ZZ_NO_MATCH = 1; + private static final int ZZ_PUSHBACK_2BIG = 2; + private static final char[] EMPTY_BUFFER = new char[0]; + private static final int YYEOF = -1; + private static java.io.Reader zzReader = null; // Fake + + /* error messages for the codes above */ + private static final String ZZ_ERROR_MSG[] = { + "Unkown internal scanner error", + "Error: could not match input", + "Error: pushback value was too large" + }; + + /** + * ZZ_ATTRIBUTE[aState] contains the attributes of state aState + */ + private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); + + private static final String ZZ_ATTRIBUTE_PACKED_0 = + "\1\0\1\11\1\1\6\11\6\1\1\0\1\11\6\0"+ + "\1\1\5\0\1\11\1\0\1\11\2\0\1\1\1\11"+ + "\1\0"; + + private static int [] zzUnpackAttribute() { + int [] result = new int[37]; + int offset = 0; + offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); + return result; + } + + private static int zzUnpackAttribute(String packed, int offset, int [] result) { + int i = 0; /* index in packed string */ + int j = offset; /* index in unpacked array */ + int l = packed.length(); + while (i < l) { + int count = packed.charAt(i++); + int value = packed.charAt(i++); + do result[j++] = value; while (--count > 0); + } + return j; + } + + /** the current state of the DFA */ + private int zzState; + + /** the current lexical state */ + private int zzLexicalState = YYINITIAL; + + /** this buffer contains the current text to be matched and is + the source of the yytext() string */ + private CharSequence zzBuffer = ""; + + /** this buffer may contains the current text array to be matched when it is cheap to acquire it */ + private char[] zzBufferArray; + + /** the textposition at the last accepting state */ + private int zzMarkedPos; + + /** the textposition at the last state to be included in yytext */ + private int zzPushbackPos; + + /** the current text position in the buffer */ + private int zzCurrentPos; + + /** startRead marks the beginning of the yytext() string in the buffer */ + private int zzStartRead; + + /** endRead marks the last character in the buffer, that has been read + from input */ + private int zzEndRead; + + /** + * zzAtBOL == true <=> the scanner is currently at the beginning of a line + */ + private boolean zzAtBOL = true; + + /** zzAtEOF == true <=> the scanner is at the EOF */ + private boolean zzAtEOF; + + /** denotes if the user-EOF-code has already been executed */ + private boolean zzEOFDone; + + /* user code: */ + public _JsonLexer() { + this((java.io.Reader)null); + } + + + public _JsonLexer(java.io.Reader in) { + this.zzReader = in; + } + + /** + * Creates a new scanner. + * There is also java.io.Reader version of this constructor. + * + * @param in the java.io.Inputstream to read input from. + */ + public _JsonLexer(java.io.InputStream in) { + this(new java.io.InputStreamReader(in)); + } + + /** + * Unpacks the compressed character translation table. + * + * @param packed the packed character translation table + * @return the unpacked character translation table + */ + private static char [] zzUnpackCMap(String packed) { + char [] map = new char[0x10000]; + int i = 0; /* index in packed string */ + int j = 0; /* index in unpacked array */ + while (i < 224) { + int count = packed.charAt(i++); + char value = packed.charAt(i++); + do map[j++] = value; while (--count > 0); + } + return map; + } + + public final int getTokenStart(){ + return zzStartRead; + } + + public final int getTokenEnd(){ + return getTokenStart() + yylength(); + } + + public void reset(CharSequence buffer, int start, int end,int initialState){ + zzBuffer = buffer; + zzBufferArray = com.intellij.util.text.CharArrayUtil.fromSequenceWithoutCopying(buffer); + zzCurrentPos = zzMarkedPos = zzStartRead = start; + zzPushbackPos = 0; + zzAtEOF = false; + zzAtBOL = true; + zzEndRead = end; + yybegin(initialState); + } + + /** + * Refills the input buffer. + * + * @return false, iff there was new input. + * + * @exception java.io.IOException if any I/O-Error occurs + */ + private boolean zzRefill() throws java.io.IOException { + return true; + } + + + /** + * Returns the current lexical state. + */ + public final int yystate() { + return zzLexicalState; + } + + + /** + * Enters a new lexical state + * + * @param newState the new lexical state + */ + public final void yybegin(int newState) { + zzLexicalState = newState; + } + + + /** + * Returns the text matched by the current regular expression. + */ + public final CharSequence yytext() { + return zzBuffer.subSequence(zzStartRead, zzMarkedPos); + } + + + /** + * Returns the character at position pos from the + * matched text. + * + * It is equivalent to yytext().charAt(pos), but faster + * + * @param pos the position of the character to fetch. + * A value from 0 to yylength()-1. + * + * @return the character at position pos + */ + public final char yycharat(int pos) { + return zzBufferArray != null ? zzBufferArray[zzStartRead+pos]:zzBuffer.charAt(zzStartRead+pos); + } + + + /** + * Returns the length of the matched text region. + */ + public final int yylength() { + return zzMarkedPos-zzStartRead; + } + + + /** + * Reports an error that occured while scanning. + * + * In a wellformed scanner (no or only correct usage of + * yypushback(int) and a match-all fallback rule) this method + * will only be called with things that "Can't Possibly Happen". + * If this method is called, something is seriously wrong + * (e.g. a JFlex bug producing a faulty scanner etc.). + * + * Usual syntax/scanner level error handling should be done + * in error fallback rules. + * + * @param errorCode the code of the errormessage to display + */ + private void zzScanError(int errorCode) { + String message; + try { + message = ZZ_ERROR_MSG[errorCode]; + } + catch (ArrayIndexOutOfBoundsException e) { + message = ZZ_ERROR_MSG[ZZ_UNKNOWN_ERROR]; + } + + throw new Error(message); + } + + + /** + * Pushes the specified amount of characters back into the input stream. + * + * They will be read again by then next call of the scanning method + * + * @param number the number of characters to be read again. + * This number must not be greater than yylength()! + */ + public void yypushback(int number) { + if ( number > yylength() ) + zzScanError(ZZ_PUSHBACK_2BIG); + + zzMarkedPos -= number; + } + + + /** + * Contains user EOF-code, which will be executed exactly once, + * when the end of file is reached + */ + private void zzDoEOF() { + if (!zzEOFDone) { + zzEOFDone = true; + + } + } + + + /** + * Resumes scanning until the next regular expression is matched, + * the end of input is encountered or an I/O-Error occurs. + * + * @return the next token + * @exception java.io.IOException if any I/O-Error occurs + */ + public IElementType advance() throws java.io.IOException { + int zzInput; + int zzAction; + + // cached fields: + int zzCurrentPosL; + int zzMarkedPosL; + int zzEndReadL = zzEndRead; + CharSequence zzBufferL = zzBuffer; + char[] zzBufferArrayL = zzBufferArray; + char [] zzCMapL = ZZ_CMAP; + + int [] zzTransL = ZZ_TRANS; + int [] zzRowMapL = ZZ_ROWMAP; + int [] zzAttrL = ZZ_ATTRIBUTE; + + while (true) { + zzMarkedPosL = zzMarkedPos; + + zzAction = -1; + + zzCurrentPosL = zzCurrentPos = zzStartRead = zzMarkedPosL; + + zzState = ZZ_LEXSTATE[zzLexicalState]; + + + zzForAction: { + while (true) { + + if (zzCurrentPosL < zzEndReadL) + zzInput = zzBufferL.charAt(zzCurrentPosL++); + else if (zzAtEOF) { + zzInput = YYEOF; + break zzForAction; + } + else { + // store back cached positions + zzCurrentPos = zzCurrentPosL; + zzMarkedPos = zzMarkedPosL; + boolean eof = zzRefill(); + // get translated positions and possibly new buffer + zzCurrentPosL = zzCurrentPos; + zzMarkedPosL = zzMarkedPos; + zzBufferL = zzBuffer; + zzEndReadL = zzEndRead; + if (eof) { + zzInput = YYEOF; + break zzForAction; + } + else { + zzInput = zzBufferL.charAt(zzCurrentPosL++); + } + } + int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; + if (zzNext == -1) break zzForAction; + zzState = zzNext; + + int zzAttributes = zzAttrL[zzState]; + if ( (zzAttributes & 1) == 1 ) { + zzAction = zzState; + zzMarkedPosL = zzCurrentPosL; + if ( (zzAttributes & 8) == 8 ) break zzForAction; + } + + } + } + + // store back cached position + zzMarkedPos = zzMarkedPosL; + + switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { + case 4: + { return R_CURLY; + } + case 14: break; + case 3: + { return L_CURLY; + } + case 15: break; + case 12: + { return NULL; + } + case 16: break; + case 5: + { return L_BRAKET; + } + case 17: break; + case 2: + { return com.intellij.psi.TokenType.WHITE_SPACE; + } + case 18: break; + case 7: + { return COMMA; + } + case 19: break; + case 1: + { return com.intellij.psi.TokenType.BAD_CHARACTER; + } + case 20: break; + case 6: + { return R_BRAKET; + } + case 21: break; + case 11: + { return TRUE; + } + case 22: break; + case 10: + { return STRING; + } + case 23: break; + case 8: + { return COLON; + } + case 24: break; + case 9: + { return NUMBER; + } + case 25: break; + case 13: + { return FALSE; + } + case 26: break; + default: + if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { + zzAtEOF = true; + zzDoEOF(); + return null; + } + else { + zzScanError(ZZ_NO_MATCH); + } + } + } + } + + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonArray.java b/plugins/json/gen/com/jetbrains/json/psi/JsonArray.java new file mode 100644 index 000000000000..33dd7c36ebba --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonArray.java @@ -0,0 +1,13 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonArray extends JsonPropertyValue { + + @NotNull + List getPropertyValueList(); + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java new file mode 100644 index 000000000000..9fd27f7aa760 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java @@ -0,0 +1,12 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonLiteral extends JsonPropertyValue { + + boolean isQuotedString(); + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java b/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java new file mode 100644 index 000000000000..626e2242ed65 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java @@ -0,0 +1,16 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonObject extends JsonPropertyValue { + + @NotNull + List getPropertyList(); + + @Nullable + JsonProperty findProperty(String name); + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java b/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java new file mode 100644 index 000000000000..56c9b9661ae6 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java @@ -0,0 +1,21 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonProperty extends PsiElement { + + @NotNull + JsonPropertyName getPropertyName(); + + @Nullable + JsonPropertyValue getPropertyValue(); + + @NotNull + String getName(); + + void delete(); + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java b/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java new file mode 100644 index 000000000000..92730cc10eae --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java @@ -0,0 +1,10 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonPropertyName extends PsiElement { + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyValue.java b/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyValue.java new file mode 100644 index 000000000000..3a0a3e5081bc --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyValue.java @@ -0,0 +1,10 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonPropertyValue extends PsiElement { + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java b/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java new file mode 100644 index 000000000000..a666d45a75ed --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java @@ -0,0 +1,38 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiElement; + +public class JsonVisitor extends PsiElementVisitor { + + public void visitArray(@NotNull JsonArray o) { + visitPropertyValue(o); + } + + public void visitLiteral(@NotNull JsonLiteral o) { + visitPropertyValue(o); + } + + public void visitObject(@NotNull JsonObject o) { + visitPropertyValue(o); + } + + public void visitProperty(@NotNull JsonProperty o) { + visitPsiElement(o); + } + + public void visitPropertyName(@NotNull JsonPropertyName o) { + visitPsiElement(o); + } + + public void visitPropertyValue(@NotNull JsonPropertyValue o) { + visitPsiElement(o); + } + + public void visitPsiElement(@NotNull PsiElement o) { + visitElement(o); + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java new file mode 100644 index 000000000000..046470864193 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java @@ -0,0 +1,30 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.jetbrains.json.psi.*; + +public class JsonArrayImpl extends JsonPropertyValueImpl implements JsonArray { + + public JsonArrayImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitArray(this); + else super.accept(visitor); + } + + @Override + @NotNull + public List getPropertyValueList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonPropertyValue.class); + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java new file mode 100644 index 000000000000..36ec18b65c44 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java @@ -0,0 +1,28 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.jetbrains.json.psi.*; + +public class JsonLiteralImpl extends JsonLiteralMixin implements JsonLiteral { + + public JsonLiteralImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitLiteral(this); + else super.accept(visitor); + } + + public boolean isQuotedString() { + return JsonPsiImplUtils.isQuotedString(this); + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java new file mode 100644 index 000000000000..81312a1d8ae8 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java @@ -0,0 +1,35 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.jetbrains.json.psi.*; + +public class JsonObjectImpl extends JsonPropertyValueImpl implements JsonObject { + + public JsonObjectImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitObject(this); + else super.accept(visitor); + } + + @Override + @NotNull + public List getPropertyList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonProperty.class); + } + + @Nullable + public JsonProperty findProperty(String name) { + return JsonPsiImplUtils.findProperty(this, name); + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java new file mode 100644 index 000000000000..f265365ab25b --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java @@ -0,0 +1,46 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.jetbrains.json.psi.*; + +public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProperty { + + public JsonPropertyImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitProperty(this); + else super.accept(visitor); + } + + @Override + @NotNull + public JsonPropertyName getPropertyName() { + return findNotNullChildByClass(JsonPropertyName.class); + } + + @Override + @Nullable + public JsonPropertyValue getPropertyValue() { + return findChildByClass(JsonPropertyValue.class); + } + + @NotNull + public String getName() { + return JsonPsiImplUtils.getName(this); + } + + public void delete() { + JsonPsiImplUtils.delete(this); + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java new file mode 100644 index 000000000000..e6a244f5ccd7 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java @@ -0,0 +1,25 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.jetbrains.json.psi.*; + +public class JsonPropertyNameImpl extends ASTWrapperPsiElement implements JsonPropertyName { + + public JsonPropertyNameImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitPropertyName(this); + else super.accept(visitor); + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java new file mode 100644 index 000000000000..fa568524f91a --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java @@ -0,0 +1,25 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.jetbrains.json.psi.*; + +public class JsonPropertyValueImpl extends ASTWrapperPsiElement implements JsonPropertyValue { + + public JsonPropertyValueImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitPropertyValue(this); + else super.accept(visitor); + } + +} diff --git a/plugins/json/json.iml b/plugins/json/json.iml new file mode 100644 index 000000000000..9596e3928acc --- /dev/null +++ b/plugins/json/json.iml @@ -0,0 +1,14 @@ + + + + + + + + + + + + + + diff --git a/plugins/json/src/com/jetbrains/json/JsonElementType.java b/plugins/json/src/com/jetbrains/json/JsonElementType.java new file mode 100644 index 000000000000..f05720de5112 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonElementType.java @@ -0,0 +1,11 @@ +package com.jetbrains.json; + +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class JsonElementType extends IElementType { + public JsonElementType(@NotNull @NonNls String debugName) { + super(debugName, JsonLanguage.INSTANCE); + } +} diff --git a/plugins/json/src/com/jetbrains/json/JsonFile.java b/plugins/json/src/com/jetbrains/json/JsonFile.java new file mode 100644 index 000000000000..3e1bc349d3be --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonFile.java @@ -0,0 +1,21 @@ +package com.jetbrains.json; + +import com.intellij.extapi.psi.PsiFileBase; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.psi.FileViewProvider; +import org.jetbrains.annotations.NotNull; + +public class JsonFile extends PsiFileBase { + @NotNull private final FileType myType; + + public JsonFile(FileViewProvider fileViewProvider, @NotNull FileType type) { + super(fileViewProvider, JsonLanguage.INSTANCE); + myType = type; + } + + @NotNull + @Override + public FileType getFileType() { + return myType; + } +} diff --git a/plugins/json/src/com/jetbrains/json/JsonLanguage.java b/plugins/json/src/com/jetbrains/json/JsonLanguage.java new file mode 100644 index 000000000000..a7e607ca88fe --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonLanguage.java @@ -0,0 +1,12 @@ +package com.jetbrains.json; + +import com.intellij.lang.Language; +import org.jetbrains.annotations.NotNull; + +public class JsonLanguage extends Language { + @NotNull public static final Language INSTANCE = new JsonLanguage(); + + private JsonLanguage() { + super("AppCode.JSON"); + } +} diff --git a/plugins/json/src/com/jetbrains/json/JsonParserDefinitionBase.java b/plugins/json/src/com/jetbrains/json/JsonParserDefinitionBase.java new file mode 100644 index 000000000000..5cfff22d1b14 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonParserDefinitionBase.java @@ -0,0 +1,75 @@ +package com.jetbrains.json; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.ParserDefinition; +import com.intellij.lang.PsiParser; +import com.intellij.lexer.FlexAdapter; +import com.intellij.lexer.Lexer; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.project.Project; +import com.intellij.psi.FileViewProvider; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.TokenType; +import com.intellij.psi.tree.IFileElementType; +import com.intellij.psi.tree.TokenSet; +import org.jetbrains.annotations.NotNull; + +public abstract class JsonParserDefinitionBase implements ParserDefinition { + public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE); + public static final TokenSet STRING_LITERALS = TokenSet.create(JsonParserTypes.STRING); + + private static final IFileElementType FILE = new IFileElementType(JsonLanguage.INSTANCE); + + protected abstract FileType getFileType(); + + @NotNull + @Override + public Lexer createLexer(Project project) { + return new FlexAdapter(new _JsonLexer()); + } + + @Override + public PsiParser createParser(Project project) { + return new Parser(); + } + + @Override + public IFileElementType getFileNodeType() { + return FILE; + } + + @NotNull + @Override + public TokenSet getWhitespaceTokens() { + return WHITE_SPACES; + } + + @NotNull + @Override + public TokenSet getCommentTokens() { + return TokenSet.EMPTY; + } + + @NotNull + @Override + public TokenSet getStringLiteralElements() { + return STRING_LITERALS; + } + + @NotNull + @Override + public PsiElement createElement(ASTNode astNode) { + return JsonParserTypes.Factory.createElement(astNode); + } + + @Override + public PsiFile createFile(FileViewProvider fileViewProvider) { + return new JsonFile(fileViewProvider, getFileType()); + } + + @Override + public SpaceRequirements spaceExistanceTypeBetweenTokens(ASTNode astNode, ASTNode astNode2) { + return SpaceRequirements.MAY; + } +} diff --git a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java new file mode 100644 index 000000000000..4e12c9692034 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java @@ -0,0 +1,57 @@ +package com.jetbrains.json; + +import com.intellij.lexer.FlexAdapter; +import com.intellij.lexer.Lexer; +import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; +import com.intellij.openapi.editor.colors.TextAttributesKey; +import com.intellij.openapi.fileTypes.SyntaxHighlighter; +import com.intellij.openapi.fileTypes.SyntaxHighlighterBase; +import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.HashMap; +import java.util.Map; + +import static com.jetbrains.json.JsonParserTypes.*; + +public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { + @NotNull + @Override + public SyntaxHighlighter getSyntaxHighlighter(@Nullable Project project, @Nullable VirtualFile virtualFile) { + return new Highlighter(); + } + + private static class Highlighter extends SyntaxHighlighterBase { + private static final Map ATTRIBUTES = new HashMap(); + + static { + ATTRIBUTES.put(L_CURLY, DefaultLanguageHighlighterColors.BRACES); + ATTRIBUTES.put(R_CURLY, DefaultLanguageHighlighterColors.BRACES ); + ATTRIBUTES.put(L_BRAKET, DefaultLanguageHighlighterColors.BRACKETS ); + ATTRIBUTES.put(R_BRAKET, DefaultLanguageHighlighterColors.BRACES ); + ATTRIBUTES.put(COMMA, DefaultLanguageHighlighterColors.COMMA); + ATTRIBUTES.put(COLON, DefaultLanguageHighlighterColors.SEMICOLON); + ATTRIBUTES.put(STRING, DefaultLanguageHighlighterColors.STRING); + ATTRIBUTES.put(NUMBER, DefaultLanguageHighlighterColors.NUMBER); + ATTRIBUTES.put(TRUE, DefaultLanguageHighlighterColors.KEYWORD); + ATTRIBUTES.put(FALSE, DefaultLanguageHighlighterColors.KEYWORD); + ATTRIBUTES.put(NULL, DefaultLanguageHighlighterColors.KEYWORD); + } + + @NotNull + @Override + public Lexer getHighlightingLexer() { + return new FlexAdapter(new _JsonLexer()); + } + + @NotNull + @Override + public TextAttributesKey[] getTokenHighlights(IElementType type) { + return pack(ATTRIBUTES.get(type)); + } + } +} diff --git a/plugins/json/src/com/jetbrains/json/JsonTokenType.java b/plugins/json/src/com/jetbrains/json/JsonTokenType.java new file mode 100644 index 000000000000..51238ab7e4c1 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonTokenType.java @@ -0,0 +1,11 @@ +package com.jetbrains.json; + +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +public class JsonTokenType extends IElementType { + public JsonTokenType(@NotNull @NonNls String debugName) { + super(debugName, JsonLanguage.INSTANCE); + } +} diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java b/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java new file mode 100644 index 000000000000..5145130b97a0 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java @@ -0,0 +1,24 @@ +package com.jetbrains.json.psi; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.AbstractElementManipulator; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; + +public class JsonLiteralManipulator extends AbstractElementManipulator { + + @Override + public JsonLiteral handleContentChange(JsonLiteral element, TextRange range, String newContent) throws IncorrectOperationException { + String text = "{\"\":\"" + newContent + "\"}"; + + final PsiFile dummy = JsonPsiChangeUtils.createDummyFile(element, text); + JsonProperty property = PsiTreeUtil.findChildOfType(dummy, JsonProperty.class); + assert property != null; + + JsonPropertyValue value = property.getPropertyValue(); + assert value instanceof JsonLiteral; + + return (JsonLiteral)element.replace(value); + } +} diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java b/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java new file mode 100644 index 000000000000..c6ed696c2613 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java @@ -0,0 +1,61 @@ +package com.jetbrains.json.psi; + +import com.intellij.lang.ASTNode; +import com.intellij.lang.Language; +import com.intellij.lang.LanguageParserDefinitions; +import com.intellij.lang.ParserDefinition; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.TokenType; +import com.jetbrains.json.JsonFile; +import com.jetbrains.json.JsonParserTypes; +import org.jetbrains.annotations.NotNull; + +public class JsonPsiChangeUtils { + public static void removeCommaSeparatedFromList(final ASTNode myNode, final ASTNode parent) { + ASTNode from = myNode, to = myNode.getTreeNext(); + + boolean seenComma = false; + + ASTNode toCandidate = to; + while (toCandidate != null && toCandidate.getElementType() == TokenType.WHITE_SPACE) { + toCandidate = toCandidate.getTreeNext(); + } + + if (toCandidate != null && toCandidate.getElementType() == JsonParserTypes.COMMA) { + toCandidate = toCandidate.getTreeNext(); + to = toCandidate; + seenComma = true; + + if (to != null && to.getElementType() == TokenType.WHITE_SPACE) { + to = to.getTreeNext(); + } + } + + if (!seenComma) { + ASTNode treePrev = from.getTreePrev(); + + while (treePrev != null && treePrev.getElementType() == TokenType.WHITE_SPACE) { + from = treePrev; + treePrev = treePrev.getTreePrev(); + } + if (treePrev != null && treePrev.getElementType() == JsonParserTypes.COMMA) { + from = treePrev; + } + } + + parent.removeRange(from, to); + } + + @NotNull + public static PsiFile createDummyFile(JsonLiteral element, String text) { + Language language = element.getLanguage(); + ParserDefinition def = LanguageParserDefinitions.INSTANCE.forLanguage(language); + assert def != null; + Project project = element.getProject(); + final PsiFile dummyFile = PsiFileFactory.getInstance(project).createFileFromText("dummy.json", language, text, false, true); + assert dummyFile instanceof JsonFile; + return dummyFile; + } +} diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java b/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java new file mode 100644 index 000000000000..e5f741dfb1ff --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java @@ -0,0 +1,37 @@ +package com.jetbrains.json.psi; + +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.util.PsiTreeUtil; +import com.jetbrains.json.JsonParserTypes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; + +public class JsonPsiImplUtils { + public static boolean isQuotedString(@NotNull JsonLiteral literal) { + return literal.getNode().findChildByType(JsonParserTypes.STRING) != null; + } + + @NotNull + public static String getName(@NotNull JsonProperty property) { + return StringUtil.unquoteString(property.getPropertyName().getText()); + } + + public static void delete(@NotNull JsonProperty property) { + final ASTNode myNode = property.getNode(); + JsonPsiChangeUtils.removeCommaSeparatedFromList(myNode, myNode.getTreeParent()); + } + + @Nullable + public static JsonProperty findProperty(@NotNull JsonObject object, @NotNull String name) { + Collection properties = PsiTreeUtil.findChildrenOfType(object, JsonProperty.class); + for (JsonProperty property : properties) { + if (property.getName().equals(name)) { + return property; + } + } + return null; + } +} diff --git a/plugins/json/src/com/jetbrains/json/psi/impl/JsonLiteralMixin.java b/plugins/json/src/com/jetbrains/json/psi/impl/JsonLiteralMixin.java new file mode 100644 index 000000000000..c2426395c85a --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/psi/impl/JsonLiteralMixin.java @@ -0,0 +1,33 @@ +package com.jetbrains.json.psi.impl; + +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiReference; +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; +import com.jetbrains.json.psi.JsonLiteral; +import org.jetbrains.annotations.NotNull; + +abstract class JsonLiteralMixin extends JsonPropertyValueImpl implements JsonLiteral { + private final Object myRefLock = new Object(); + private volatile PsiReference[] myRefs; + private volatile long myModCount = -1; + + protected JsonLiteralMixin(ASTNode node) { + super(node); + } + + @NotNull + @Override + public PsiReference[] getReferences() { + final long count = getManager().getModificationTracker().getModificationCount(); + if (count != myModCount) { + synchronized (myRefLock) { + if (count != myModCount) { + myRefs = ReferenceProvidersRegistry.getReferencesFromProviders(this); + myModCount = count; + } + } + } + + return myRefs; + } +} diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf new file mode 100644 index 000000000000..08447225f315 --- /dev/null +++ b/plugins/json/src/json.bnf @@ -0,0 +1,56 @@ +{ + parserClass='com.jetbrains.json.Parser' + parserUtilClass="com.jetbrains.json.JsonParserUtil" + psiPackage='com.jetbrains.json.psi' + psiImplPackage='com.jetbrains.json.psi.impl' + + elementTypeHolderClass='com.jetbrains.json.JsonParserTypes' + elementTypeClass='com.jetbrains.json.JsonElementType' + psiClassPrefix="Json" + + psiImplUtilClass='com.jetbrains.json.psi.JsonPsiImplUtils' + tokenTypeClass='com.jetbrains.json.JsonTokenType' + + tokens = [ + L_CURLY='{' + R_CURLY='}' + L_BRAKET='[' + R_BRAKET=']' + + COMMA=',' + COLON=':' + STRING='regexp:"([^\\"]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"' + NUMBER='regexp:-?\d+(\.\d+([eE][+-]?\d+)?)?' + TRUE='true' + FALSE='false' + NULL='null' + ] + + extends("object|array|literal")=property_value +} + +json ::= object | array + +object ::= L_CURLY properties? R_CURLY { + pin=1 + methods=[ + findProperty + ] +} +private properties ::= property (COMMA property)* +property ::= property_name COLON property_value { + pin=1 + methods=[ + getName + delete + ] +} +property_name ::= STRING +property_value ::= object | array | literal +literal ::= STRING | NUMBER | TRUE | FALSE | NULL { + methods=[isQuotedString] + mixin="com.jetbrains.json.psi.impl.JsonLiteralMixin" +} + +array ::= L_BRAKET values? R_BRAKET {pin=1} +private values ::= property_value (COMMA property_value)* \ No newline at end of file diff --git a/plugins/json/src/json.flex b/plugins/json/src/json.flex new file mode 100644 index 000000000000..f59e64cf46ca --- /dev/null +++ b/plugins/json/src/json.flex @@ -0,0 +1,54 @@ +package com.jetbrains.json; +import com.intellij.lexer.*; +import com.intellij.psi.tree.IElementType; +import static com.jetbrains.json.JsonParserTypes.*; + +%% + +%{ + public _JsonLexer() { + this((java.io.Reader)null); + } +%} + +%public +%class _JsonLexer +%implements FlexLexer +%function advance +%type IElementType +%unicode +%eof{ return; +%eof} + +WHITE_SPACE=[ \t\n\r] + +L_CURLY="{" +R_CURLY="}" +L_BRAKET="[" +R_BRAKET="]" +COMMA="," +COLON=":" +STRING=\"([^\\\"]|\\([\\\"/bfnrt]|u[a-fA-F0-9]{4}))*\" +NUMBER=-?[:digit:]+(\.[:digit:]+([eE][+-]?[:digit:]+)?)? +TRUE="true" +FALSE="false" +NULL="null" + + +%% + { +{L_CURLY} { return L_CURLY; } +{R_CURLY} { return R_CURLY; } +{L_BRAKET} { return L_BRAKET; } +{R_BRAKET} { return R_BRAKET; } +{COMMA} { return COMMA; } +{COLON} { return COLON; } +{STRING} { return STRING; } +{NUMBER} { return NUMBER; } +{TRUE} { return TRUE; } +{FALSE} { return FALSE; } +{NULL} { return NULL; } + +{WHITE_SPACE}+ { return com.intellij.psi.TokenType.WHITE_SPACE; } +[^] { return com.intellij.psi.TokenType.BAD_CHARACTER; } +} From fbda4aa15d2d0c6edc59cb0fec5b35dd7534a1cd Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 30 Oct 2013 13:21:59 +0400 Subject: [PATCH 02/85] Refactored module to be plain Java module instead of plugin, added it to main module dependencies. --- plugins/json/META-INF/plugin.xml | 42 ---------------------------- plugins/json/json.iml | 10 ++++--- plugins/json/src/META-INF/plugin.xml | 30 ++++++++++++++++++++ 3 files changed, 36 insertions(+), 46 deletions(-) delete mode 100644 plugins/json/META-INF/plugin.xml create mode 100644 plugins/json/src/META-INF/plugin.xml diff --git a/plugins/json/META-INF/plugin.xml b/plugins/json/META-INF/plugin.xml deleted file mode 100644 index 42edb8789f74..000000000000 --- a/plugins/json/META-INF/plugin.xml +++ /dev/null @@ -1,42 +0,0 @@ - - com.intellij.json - JSON support for IntelliJ IDEA - 1.0 - JetBrains - - - most HTML tags may be used - ]]> - - - most HTML tags may be used - ]]> - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/plugins/json/json.iml b/plugins/json/json.iml index 9596e3928acc..05d4fec511cd 100644 --- a/plugins/json/json.iml +++ b/plugins/json/json.iml @@ -1,14 +1,16 @@ - - + - + - + + + + diff --git a/plugins/json/src/META-INF/plugin.xml b/plugins/json/src/META-INF/plugin.xml new file mode 100644 index 000000000000..f7a04262fe60 --- /dev/null +++ b/plugins/json/src/META-INF/plugin.xml @@ -0,0 +1,30 @@ + + com.intellij.json + JSON Support + 1.0 + JetBrains + + com.intellij.modules.xml + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From 2862887d95947466c264de05017ac595da244411 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 30 Oct 2013 13:23:15 +0400 Subject: [PATCH 03/85] Added Language, FileType and FileTypeFactory for JSON. --- .../src/com/jetbrains/json/JsonFileType.java | 45 +++++++++++++++++++ .../jetbrains/json/JsonFileTypeFactory.java | 15 +++++++ .../src/com/jetbrains/json/JsonLanguage.java | 10 +++-- 3 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 plugins/json/src/com/jetbrains/json/JsonFileType.java create mode 100644 plugins/json/src/com/jetbrains/json/JsonFileTypeFactory.java diff --git a/plugins/json/src/com/jetbrains/json/JsonFileType.java b/plugins/json/src/com/jetbrains/json/JsonFileType.java new file mode 100644 index 000000000000..8379ed708790 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonFileType.java @@ -0,0 +1,45 @@ +package com.jetbrains.json; + +import com.intellij.icons.AllIcons; +import com.intellij.openapi.fileTypes.LanguageFileType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.Icon; + +/** + * @author Mikhail Golubev + */ +public class JsonFileType extends LanguageFileType{ + public static final JsonFileType INSTANCE = new JsonFileType(); + public static final String DEFAULT_EXTENSION = "json"; + + public JsonFileType() { + super(JsonLanguage.INSTANCE); + } + + @NotNull + @Override + public String getName() { + return "JSON"; + } + + @NotNull + @Override + public String getDescription() { + return "JSON language"; + } + + @NotNull + @Override + public String getDefaultExtension() { + return DEFAULT_EXTENSION; + } + + @Nullable + @Override + public Icon getIcon() { + // TODO: add JSON icon instead + return AllIcons.FileTypes.Json; + } +} diff --git a/plugins/json/src/com/jetbrains/json/JsonFileTypeFactory.java b/plugins/json/src/com/jetbrains/json/JsonFileTypeFactory.java new file mode 100644 index 000000000000..0930485df4ce --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonFileTypeFactory.java @@ -0,0 +1,15 @@ +package com.jetbrains.json; + +import com.intellij.openapi.fileTypes.FileTypeConsumer; +import com.intellij.openapi.fileTypes.FileTypeFactory; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class JsonFileTypeFactory extends FileTypeFactory { + @Override + public void createFileTypes(@NotNull FileTypeConsumer consumer) { + consumer.consume(JsonFileType.INSTANCE, JsonFileType.DEFAULT_EXTENSION); + } +} diff --git a/plugins/json/src/com/jetbrains/json/JsonLanguage.java b/plugins/json/src/com/jetbrains/json/JsonLanguage.java index a7e607ca88fe..bd2156a22f5f 100644 --- a/plugins/json/src/com/jetbrains/json/JsonLanguage.java +++ b/plugins/json/src/com/jetbrains/json/JsonLanguage.java @@ -1,12 +1,16 @@ package com.jetbrains.json; import com.intellij.lang.Language; -import org.jetbrains.annotations.NotNull; public class JsonLanguage extends Language { - @NotNull public static final Language INSTANCE = new JsonLanguage(); + public static final JsonLanguage INSTANCE = new JsonLanguage(); private JsonLanguage() { - super("AppCode.JSON"); + super("JSON"); + } + + @Override + public boolean isCaseSensitive() { + return true; } } From ac00485af5e5edca21b4556eab3ec4f994ebe229 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 30 Oct 2013 14:55:35 +0400 Subject: [PATCH 04/85] Added more elements to PSI structure of JSON --- .../com/jetbrains/json/JsonParserTypes.java | 16 ++ .../json/gen/com/jetbrains/json/Parser.java | 181 ++++++++++++------ .../json/psi/JsonBooleanLiteral.java | 10 + .../jetbrains/json/psi/JsonNullLiteral.java | 10 + .../jetbrains/json/psi/JsonNumberLiteral.java | 10 + .../com/jetbrains/json/psi/JsonProperty.java | 4 + .../jetbrains/json/psi/JsonPropertyName.java | 3 + .../jetbrains/json/psi/JsonStringLiteral.java | 10 + .../com/jetbrains/json/psi/JsonVisitor.java | 16 ++ .../json/psi/impl/JsonBooleanLiteralImpl.java | 24 +++ .../json/psi/impl/JsonNullLiteralImpl.java | 24 +++ .../json/psi/impl/JsonNumberLiteralImpl.java | 24 +++ .../json/psi/impl/JsonPropertyImpl.java | 5 + .../json/psi/impl/JsonPropertyNameImpl.java | 6 + .../json/psi/impl/JsonStringLiteralImpl.java | 24 +++ .../json/src/com/jetbrains/json/JsonFile.java | 6 +- .../src/com/jetbrains/json/JsonLanguage.java | 2 +- ...ionBase.java => JsonParserDefinition.java} | 6 +- .../jetbrains/json/psi/JsonPsiImplUtils.java | 6 + plugins/json/src/json.bnf | 25 ++- 20 files changed, 335 insertions(+), 77 deletions(-) create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonBooleanLiteral.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonNullLiteral.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java create mode 100644 plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java rename plugins/json/src/com/jetbrains/json/{JsonParserDefinitionBase.java => JsonParserDefinition.java} (90%) diff --git a/plugins/json/gen/com/jetbrains/json/JsonParserTypes.java b/plugins/json/gen/com/jetbrains/json/JsonParserTypes.java index 0e63ec9e5fea..2cfb0e11d33c 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonParserTypes.java +++ b/plugins/json/gen/com/jetbrains/json/JsonParserTypes.java @@ -9,11 +9,15 @@ import com.jetbrains.json.psi.impl.*; public interface JsonParserTypes { IElementType ARRAY = new JsonElementType("ARRAY"); + IElementType BOOLEAN_LITERAL = new JsonElementType("BOOLEAN_LITERAL"); IElementType LITERAL = new JsonElementType("LITERAL"); + IElementType NULL_LITERAL = new JsonElementType("NULL_LITERAL"); + IElementType NUMBER_LITERAL = new JsonElementType("NUMBER_LITERAL"); IElementType OBJECT = new JsonElementType("OBJECT"); IElementType PROPERTY = new JsonElementType("PROPERTY"); IElementType PROPERTY_NAME = new JsonElementType("PROPERTY_NAME"); IElementType PROPERTY_VALUE = new JsonElementType("PROPERTY_VALUE"); + IElementType STRING_LITERAL = new JsonElementType("STRING_LITERAL"); IElementType COLON = new JsonTokenType(":"); IElementType COMMA = new JsonTokenType(","); @@ -33,9 +37,18 @@ public interface JsonParserTypes { if (type == ARRAY) { return new JsonArrayImpl(node); } + else if (type == BOOLEAN_LITERAL) { + return new JsonBooleanLiteralImpl(node); + } else if (type == LITERAL) { return new JsonLiteralImpl(node); } + else if (type == NULL_LITERAL) { + return new JsonNullLiteralImpl(node); + } + else if (type == NUMBER_LITERAL) { + return new JsonNumberLiteralImpl(node); + } else if (type == OBJECT) { return new JsonObjectImpl(node); } @@ -48,6 +61,9 @@ public interface JsonParserTypes { else if (type == PROPERTY_VALUE) { return new JsonPropertyValueImpl(node); } + else if (type == STRING_LITERAL) { + return new JsonStringLiteralImpl(node); + } throw new AssertionError("Unknown element type: " + type); } } diff --git a/plugins/json/gen/com/jetbrains/json/Parser.java b/plugins/json/gen/com/jetbrains/json/Parser.java index 335faf04e5d3..0e11dea7dac2 100644 --- a/plugins/json/gen/com/jetbrains/json/Parser.java +++ b/plugins/json/gen/com/jetbrains/json/Parser.java @@ -5,7 +5,7 @@ import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiBuilder.Marker; import com.intellij.openapi.diagnostic.Logger; import static com.jetbrains.json.JsonParserTypes.*; -import static com.intellij.lang.parser.GeneratedParserUtilBase.*; +import static com.jetbrains.json.JsonParserUtil.*; import com.intellij.psi.tree.IElementType; import com.intellij.lang.ASTNode; import com.intellij.psi.tree.TokenSet; @@ -23,9 +23,18 @@ public class Parser implements PsiParser { if (root_ == ARRAY) { result_ = array(builder_, level_ + 1); } + else if (root_ == BOOLEAN_LITERAL) { + result_ = boolean_literal(builder_, level_ + 1); + } else if (root_ == LITERAL) { result_ = literal(builder_, level_ + 1); } + else if (root_ == NULL_LITERAL) { + result_ = null_literal(builder_, level_ + 1); + } + else if (root_ == NUMBER_LITERAL) { + result_ = number_literal(builder_, level_ + 1); + } else if (root_ == OBJECT) { result_ = object(builder_, level_ + 1); } @@ -38,6 +47,9 @@ public class Parser implements PsiParser { else if (root_ == PROPERTY_VALUE) { result_ = property_value(builder_, level_ + 1); } + else if (root_ == STRING_LITERAL) { + result_ = string_literal(builder_, level_ + 1); + } else { Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = parse_root_(root_, builder_, level_); @@ -51,11 +63,14 @@ public class Parser implements PsiParser { } public static final TokenSet[] EXTENDS_SETS_ = new TokenSet[] { - create_token_set_(ARRAY, LITERAL, OBJECT, PROPERTY_VALUE), + create_token_set_(BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, NUMBER_LITERAL, + STRING_LITERAL), + create_token_set_(ARRAY, BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, + NUMBER_LITERAL, OBJECT, PROPERTY_VALUE, STRING_LITERAL), }; /* ********************************************************** */ - // L_BRAKET values? R_BRAKET + // L_BRAKET (property_value (COMMA property_value)*)? R_BRAKET public static boolean array(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array")) return false; if (!nextTokenIs(builder_, L_BRAKET)) return false; @@ -70,13 +85,65 @@ public class Parser implements PsiParser { return result_ || pinned_; } - // values? + // (property_value (COMMA property_value)*)? private static boolean array_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_1")) return false; - values(builder_, level_ + 1); + array_1_0(builder_, level_ + 1); return true; } + // property_value (COMMA property_value)* + private static boolean array_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_1_0")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = property_value(builder_, level_ + 1); + result_ = result_ && array_1_0_1(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // (COMMA property_value)* + private static boolean array_1_0_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_1_0_1")) return false; + int offset_ = builder_.getCurrentOffset(); + while (true) { + if (!array_1_0_1_0(builder_, level_ + 1)) break; + int next_offset_ = builder_.getCurrentOffset(); + if (offset_ == next_offset_) { + empty_element_parsed_guard_(builder_, offset_, "array_1_0_1"); + break; + } + offset_ = next_offset_; + } + return true; + } + + // COMMA property_value + private static boolean array_1_0_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_1_0_1_0")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, COMMA); + result_ = result_ && property_value(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + /* ********************************************************** */ + // TRUE | FALSE + public static boolean boolean_literal(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "boolean_literal")) return false; + if (!nextTokenIs(builder_, FALSE) && !nextTokenIs(builder_, TRUE) + && replaceVariants(builder_, 2, "")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); + result_ = consumeToken(builder_, TRUE); + if (!result_) result_ = consumeToken(builder_, FALSE); + exit_section_(builder_, level_, marker_, BOOLEAN_LITERAL, result_, false, null); + return result_; + } + /* ********************************************************** */ // object | array static boolean json(PsiBuilder builder_, int level_) { @@ -91,22 +158,45 @@ public class Parser implements PsiParser { } /* ********************************************************** */ - // STRING | NUMBER | TRUE | FALSE | NULL + // string_literal | number_literal | boolean_literal | null_literal public static boolean literal(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "literal")) return false; boolean result_ = false; Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); - result_ = consumeToken(builder_, STRING); - if (!result_) result_ = consumeToken(builder_, NUMBER); - if (!result_) result_ = consumeToken(builder_, TRUE); - if (!result_) result_ = consumeToken(builder_, FALSE); - if (!result_) result_ = consumeToken(builder_, NULL); + result_ = string_literal(builder_, level_ + 1); + if (!result_) result_ = number_literal(builder_, level_ + 1); + if (!result_) result_ = boolean_literal(builder_, level_ + 1); + if (!result_) result_ = null_literal(builder_, level_ + 1); exit_section_(builder_, level_, marker_, LITERAL, result_, false, null); return result_; } /* ********************************************************** */ - // L_CURLY properties? R_CURLY + // NULL + public static boolean null_literal(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "null_literal")) return false; + if (!nextTokenIs(builder_, NULL)) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, NULL); + exit_section_(builder_, marker_, NULL_LITERAL, result_); + return result_; + } + + /* ********************************************************** */ + // NUMBER + public static boolean number_literal(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "number_literal")) return false; + if (!nextTokenIs(builder_, NUMBER)) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, NUMBER); + exit_section_(builder_, marker_, NUMBER_LITERAL, result_); + return result_; + } + + /* ********************************************************** */ + // L_CURLY (property (COMMA property)*)? R_CURLY public static boolean object(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object")) return false; if (!nextTokenIs(builder_, L_CURLY)) return false; @@ -121,35 +211,33 @@ public class Parser implements PsiParser { return result_ || pinned_; } - // properties? + // (property (COMMA property)*)? private static boolean object_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object_1")) return false; - properties(builder_, level_ + 1); + object_1_0(builder_, level_ + 1); return true; } - /* ********************************************************** */ // property (COMMA property)* - static boolean properties(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "properties")) return false; - if (!nextTokenIs(builder_, STRING)) return false; + private static boolean object_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "object_1_0")) return false; boolean result_ = false; Marker marker_ = enter_section_(builder_); result_ = property(builder_, level_ + 1); - result_ = result_ && properties_1(builder_, level_ + 1); + result_ = result_ && object_1_0_1(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; } // (COMMA property)* - private static boolean properties_1(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "properties_1")) return false; + private static boolean object_1_0_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "object_1_0_1")) return false; int offset_ = builder_.getCurrentOffset(); while (true) { - if (!properties_1_0(builder_, level_ + 1)) break; + if (!object_1_0_1_0(builder_, level_ + 1)) break; int next_offset_ = builder_.getCurrentOffset(); if (offset_ == next_offset_) { - empty_element_parsed_guard_(builder_, offset_, "properties_1"); + empty_element_parsed_guard_(builder_, offset_, "object_1_0_1"); break; } offset_ = next_offset_; @@ -158,8 +246,8 @@ public class Parser implements PsiParser { } // COMMA property - private static boolean properties_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "properties_1_0")) return false; + private static boolean object_1_0_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "object_1_0_1_0")) return false; boolean result_ = false; Marker marker_ = enter_section_(builder_); result_ = consumeToken(builder_, COMMA); @@ -185,13 +273,13 @@ public class Parser implements PsiParser { } /* ********************************************************** */ - // STRING + // string_literal public static boolean property_name(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property_name")) return false; if (!nextTokenIs(builder_, STRING)) return false; boolean result_ = false; Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, STRING); + result_ = string_literal(builder_, level_ + 1); exit_section_(builder_, marker_, PROPERTY_NAME, result_); return result_; } @@ -210,41 +298,14 @@ public class Parser implements PsiParser { } /* ********************************************************** */ - // property_value (COMMA property_value)* - static boolean values(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "values")) return false; + // STRING + public static boolean string_literal(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "string_literal")) return false; + if (!nextTokenIs(builder_, STRING)) return false; boolean result_ = false; Marker marker_ = enter_section_(builder_); - result_ = property_value(builder_, level_ + 1); - result_ = result_ && values_1(builder_, level_ + 1); - exit_section_(builder_, marker_, null, result_); - return result_; - } - - // (COMMA property_value)* - private static boolean values_1(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "values_1")) return false; - int offset_ = builder_.getCurrentOffset(); - while (true) { - if (!values_1_0(builder_, level_ + 1)) break; - int next_offset_ = builder_.getCurrentOffset(); - if (offset_ == next_offset_) { - empty_element_parsed_guard_(builder_, offset_, "values_1"); - break; - } - offset_ = next_offset_; - } - return true; - } - - // COMMA property_value - private static boolean values_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "values_1_0")) return false; - boolean result_ = false; - Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, COMMA); - result_ = result_ && property_value(builder_, level_ + 1); - exit_section_(builder_, marker_, null, result_); + result_ = consumeToken(builder_, STRING); + exit_section_(builder_, marker_, STRING_LITERAL, result_); return result_; } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonBooleanLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonBooleanLiteral.java new file mode 100644 index 000000000000..c7eccd0d603d --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonBooleanLiteral.java @@ -0,0 +1,10 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonBooleanLiteral extends JsonLiteral { + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonNullLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonNullLiteral.java new file mode 100644 index 000000000000..d42112dd08af --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonNullLiteral.java @@ -0,0 +1,10 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonNullLiteral extends JsonLiteral { + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java new file mode 100644 index 000000000000..296f37567e59 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java @@ -0,0 +1,10 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonNumberLiteral extends JsonLiteral { + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java b/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java index 56c9b9661ae6..6c4cecbcb14a 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java @@ -4,6 +4,7 @@ package com.jetbrains.json.psi; import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; +import com.jetbrains.json.psi.impl.JsonPropertyImpl; public interface JsonProperty extends PsiElement { @@ -16,6 +17,9 @@ public interface JsonProperty extends PsiElement { @NotNull String getName(); + @Nullable + JsonPropertyValue getValue(); + void delete(); } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java b/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java index 92730cc10eae..3c7a9fc2b1cc 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java @@ -7,4 +7,7 @@ import com.intellij.psi.PsiElement; public interface JsonPropertyName extends PsiElement { + @NotNull + JsonStringLiteral getStringLiteral(); + } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java new file mode 100644 index 000000000000..ade19da79d77 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java @@ -0,0 +1,10 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonStringLiteral extends JsonLiteral { + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java b/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java index a666d45a75ed..e03959594151 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java @@ -11,10 +11,22 @@ public class JsonVisitor extends PsiElementVisitor { visitPropertyValue(o); } + public void visitBooleanLiteral(@NotNull JsonBooleanLiteral o) { + visitLiteral(o); + } + public void visitLiteral(@NotNull JsonLiteral o) { visitPropertyValue(o); } + public void visitNullLiteral(@NotNull JsonNullLiteral o) { + visitLiteral(o); + } + + public void visitNumberLiteral(@NotNull JsonNumberLiteral o) { + visitLiteral(o); + } + public void visitObject(@NotNull JsonObject o) { visitPropertyValue(o); } @@ -31,6 +43,10 @@ public class JsonVisitor extends PsiElementVisitor { visitPsiElement(o); } + public void visitStringLiteral(@NotNull JsonStringLiteral o) { + visitLiteral(o); + } + public void visitPsiElement(@NotNull PsiElement o) { visitElement(o); } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java new file mode 100644 index 000000000000..6112add3eee0 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java @@ -0,0 +1,24 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.jetbrains.json.psi.*; + +public class JsonBooleanLiteralImpl extends JsonLiteralImpl implements JsonBooleanLiteral { + + public JsonBooleanLiteralImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitBooleanLiteral(this); + else super.accept(visitor); + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java new file mode 100644 index 000000000000..7324d2617f6a --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java @@ -0,0 +1,24 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.jetbrains.json.psi.*; + +public class JsonNullLiteralImpl extends JsonLiteralImpl implements JsonNullLiteral { + + public JsonNullLiteralImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitNullLiteral(this); + else super.accept(visitor); + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java new file mode 100644 index 000000000000..a712487766ac --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java @@ -0,0 +1,24 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.jetbrains.json.psi.*; + +public class JsonNumberLiteralImpl extends JsonLiteralImpl implements JsonNumberLiteral { + + public JsonNumberLiteralImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitNumberLiteral(this); + else super.accept(visitor); + } + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java index f265365ab25b..523f65c36560 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java @@ -39,6 +39,11 @@ public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProper return JsonPsiImplUtils.getName(this); } + @Nullable + public JsonPropertyValue getValue() { + return JsonPsiImplUtils.getValue(this); + } + public void delete() { JsonPsiImplUtils.delete(this); } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java index e6a244f5ccd7..86a9a2f402a7 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java @@ -22,4 +22,10 @@ public class JsonPropertyNameImpl extends ASTWrapperPsiElement implements JsonPr else super.accept(visitor); } + @Override + @NotNull + public JsonStringLiteral getStringLiteral() { + return findNotNullChildByClass(JsonStringLiteral.class); + } + } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java new file mode 100644 index 000000000000..907521dcbbbe --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java @@ -0,0 +1,24 @@ +// This is a generated file. Not intended for manual editing. +package com.jetbrains.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.jetbrains.json.JsonParserTypes.*; +import com.jetbrains.json.psi.*; + +public class JsonStringLiteralImpl extends JsonLiteralImpl implements JsonStringLiteral { + + public JsonStringLiteralImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitStringLiteral(this); + else super.accept(visitor); + } + +} diff --git a/plugins/json/src/com/jetbrains/json/JsonFile.java b/plugins/json/src/com/jetbrains/json/JsonFile.java index 3e1bc349d3be..ec192b20c8c0 100644 --- a/plugins/json/src/com/jetbrains/json/JsonFile.java +++ b/plugins/json/src/com/jetbrains/json/JsonFile.java @@ -6,16 +6,14 @@ import com.intellij.psi.FileViewProvider; import org.jetbrains.annotations.NotNull; public class JsonFile extends PsiFileBase { - @NotNull private final FileType myType; - public JsonFile(FileViewProvider fileViewProvider, @NotNull FileType type) { + public JsonFile(FileViewProvider fileViewProvider) { super(fileViewProvider, JsonLanguage.INSTANCE); - myType = type; } @NotNull @Override public FileType getFileType() { - return myType; + return JsonFileType.INSTANCE; } } diff --git a/plugins/json/src/com/jetbrains/json/JsonLanguage.java b/plugins/json/src/com/jetbrains/json/JsonLanguage.java index bd2156a22f5f..c9788b776e02 100644 --- a/plugins/json/src/com/jetbrains/json/JsonLanguage.java +++ b/plugins/json/src/com/jetbrains/json/JsonLanguage.java @@ -6,7 +6,7 @@ public class JsonLanguage extends Language { public static final JsonLanguage INSTANCE = new JsonLanguage(); private JsonLanguage() { - super("JSON"); + super("JSON", "application/json"); } @Override diff --git a/plugins/json/src/com/jetbrains/json/JsonParserDefinitionBase.java b/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java similarity index 90% rename from plugins/json/src/com/jetbrains/json/JsonParserDefinitionBase.java rename to plugins/json/src/com/jetbrains/json/JsonParserDefinition.java index 5cfff22d1b14..5fcfd1dcc4f2 100644 --- a/plugins/json/src/com/jetbrains/json/JsonParserDefinitionBase.java +++ b/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java @@ -15,14 +15,12 @@ import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; -public abstract class JsonParserDefinitionBase implements ParserDefinition { +public class JsonParserDefinition implements ParserDefinition { public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE); public static final TokenSet STRING_LITERALS = TokenSet.create(JsonParserTypes.STRING); private static final IFileElementType FILE = new IFileElementType(JsonLanguage.INSTANCE); - protected abstract FileType getFileType(); - @NotNull @Override public Lexer createLexer(Project project) { @@ -65,7 +63,7 @@ public abstract class JsonParserDefinitionBase implements ParserDefinition { @Override public PsiFile createFile(FileViewProvider fileViewProvider) { - return new JsonFile(fileViewProvider, getFileType()); + return new JsonFile(fileViewProvider); } @Override diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java b/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java index e5f741dfb1ff..be58ae958cf0 100644 --- a/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java +++ b/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java @@ -4,6 +4,7 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.json.JsonParserTypes; +import com.jetbrains.json.psi.impl.JsonPropertyImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -19,6 +20,11 @@ public class JsonPsiImplUtils { return StringUtil.unquoteString(property.getPropertyName().getText()); } + @Nullable + public static JsonPropertyValue getValue(JsonPropertyImpl property) { + return PsiTreeUtil.getChildOfType(property, JsonPropertyValue.class); + } + public static void delete(@NotNull JsonProperty property) { final ASTNode myNode = property.getNode(); JsonPsiChangeUtils.removeCommaSeparatedFromList(myNode, myNode.getTreeParent()); diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index 08447225f315..9192cd621f24 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -19,6 +19,8 @@ COMMA=',' COLON=':' +// COMMENT='regexp:"//.*|/\*.*?\*/"' + // else /\*(?:[^*]|\*[^/])*\*/ STRING='regexp:"([^\\"]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"' NUMBER='regexp:-?\d+(\.\d+([eE][+-]?\d+)?)?' TRUE='true' @@ -27,30 +29,37 @@ ] extends("object|array|literal")=property_value + extends("string_literal|number_literal|boolean_literal|null_literal")=literal } json ::= object | array -object ::= L_CURLY properties? R_CURLY { +object ::= L_CURLY (property (COMMA property)*)? R_CURLY { pin=1 methods=[ findProperty ] } -private properties ::= property (COMMA property)* property ::= property_name COLON property_value { pin=1 methods=[ getName + getValue delete ] } -property_name ::= STRING + +array ::= L_BRAKET (property_value (COMMA property_value)*)? R_BRAKET {pin=1} + +property_name ::= string_literal property_value ::= object | array | literal -literal ::= STRING | NUMBER | TRUE | FALSE | NULL { + +string_literal ::= STRING +number_literal ::= NUMBER +boolean_literal ::= TRUE | FALSE +null_literal ::= NULL + +literal ::= string_literal | number_literal | boolean_literal | null_literal { methods=[isQuotedString] mixin="com.jetbrains.json.psi.impl.JsonLiteralMixin" -} - -array ::= L_BRAKET values? R_BRAKET {pin=1} -private values ::= property_value (COMMA property_value)* \ No newline at end of file +} \ No newline at end of file From ca035642b495a870b2dbad8758a62f5be97d4881 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 1 Nov 2013 13:47:06 +0400 Subject: [PATCH 05/85] Add initial version of formatter and code style page in IDE Preferences --- .../json/{Parser.java => JsonParser.java} | 13 +- plugins/json/src/META-INF/plugin.xml | 5 + .../jetbrains/json/JsonParserDefinition.java | 6 +- .../jetbrains/json/formatter/JsonBlock.java | 168 ++++++++++++++++++ .../json/formatter/JsonCodeStyleSettings.java | 21 +++ .../JsonCodeStyleSettingsProvider.java | 55 ++++++ .../formatter/JsonFormattingBuilderModel.java | 59 ++++++ ...JsonLanguageCodeStyleSettingsProvider.java | 59 ++++++ plugins/json/src/json.bnf | 14 +- 9 files changed, 389 insertions(+), 11 deletions(-) rename plugins/json/gen/com/jetbrains/json/{Parser.java => JsonParser.java} (99%) create mode 100644 plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java create mode 100644 plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettings.java create mode 100644 plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java create mode 100644 plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java create mode 100644 plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java diff --git a/plugins/json/gen/com/jetbrains/json/Parser.java b/plugins/json/gen/com/jetbrains/json/JsonParser.java similarity index 99% rename from plugins/json/gen/com/jetbrains/json/Parser.java rename to plugins/json/gen/com/jetbrains/json/JsonParser.java index 0e11dea7dac2..6b3c5291b9c2 100644 --- a/plugins/json/gen/com/jetbrains/json/Parser.java +++ b/plugins/json/gen/com/jetbrains/json/JsonParser.java @@ -1,20 +1,21 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json; +import com.intellij.lang.ASTNode; import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiBuilder.Marker; +import com.intellij.lang.PsiParser; import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; + import static com.jetbrains.json.JsonParserTypes.*; import static com.jetbrains.json.JsonParserUtil.*; -import com.intellij.psi.tree.IElementType; -import com.intellij.lang.ASTNode; -import com.intellij.psi.tree.TokenSet; -import com.intellij.lang.PsiParser; @SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"}) -public class Parser implements PsiParser { +public class JsonParser implements PsiParser { - public static final Logger LOG_ = Logger.getInstance("com.jetbrains.json.Parser"); + public static final Logger LOG_ = Logger.getInstance("com.jetbrains.json.JsonParser"); public ASTNode parse(IElementType root_, PsiBuilder builder_) { int level_ = 0; diff --git a/plugins/json/src/META-INF/plugin.xml b/plugins/json/src/META-INF/plugin.xml index f7a04262fe60..328b7dd0e332 100644 --- a/plugins/json/src/META-INF/plugin.xml +++ b/plugins/json/src/META-INF/plugin.xml @@ -26,5 +26,10 @@ + + + + + \ No newline at end of file diff --git a/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java b/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java index 5fcfd1dcc4f2..12054b3e690f 100644 --- a/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java +++ b/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java @@ -5,7 +5,6 @@ import com.intellij.lang.ParserDefinition; import com.intellij.lang.PsiParser; import com.intellij.lexer.FlexAdapter; import com.intellij.lexer.Lexer; -import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.project.Project; import com.intellij.psi.FileViewProvider; import com.intellij.psi.PsiElement; @@ -18,8 +17,9 @@ import org.jetbrains.annotations.NotNull; public class JsonParserDefinition implements ParserDefinition { public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE); public static final TokenSet STRING_LITERALS = TokenSet.create(JsonParserTypes.STRING); + public static final IFileElementType FILE = new IFileElementType(JsonLanguage.INSTANCE); + public static final TokenSet CONTAINERS = TokenSet.create(JsonParserTypes.ARRAY, JsonParserTypes.OBJECT); - private static final IFileElementType FILE = new IFileElementType(JsonLanguage.INSTANCE); @NotNull @Override @@ -29,7 +29,7 @@ public class JsonParserDefinition implements ParserDefinition { @Override public PsiParser createParser(Project project) { - return new Parser(); + return new JsonParser(); } @Override diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java b/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java new file mode 100644 index 000000000000..d47096e030bd --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java @@ -0,0 +1,168 @@ +package com.jetbrains.json.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.TokenType; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.tree.TokenSet; +import com.intellij.util.Function; +import com.intellij.util.containers.ContainerUtil; +import com.jetbrains.json.psi.JsonProperty; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +import static com.jetbrains.json.JsonParserDefinition.CONTAINERS; +import static com.jetbrains.json.JsonParserTypes.*; + +/** + * @author Mikhail Golubev + */ +public class JsonBlock implements ASTBlock { + private static final TokenSet OPEN_BRACES = TokenSet.create(L_BRAKET, L_CURLY); + private static final TokenSet CLOSE_BRACES = TokenSet.create(R_BRAKET, R_CURLY); + private static final TokenSet BRACES = TokenSet.orSet(OPEN_BRACES, CLOSE_BRACES); + private JsonBlock myParent; + + + private ASTNode myNode; + private IElementType myNodeType; + private Alignment myAlignment; + private Indent myIndent; + private Wrap myWrap; + private CodeStyleSettings mySettings; + private SpacingBuilder mySpacingBuilder; + // lazy initialized on first call to #getSubBlocks() + private List mySubBlocks = null; + + private Wrap myChildWrap = null; + private Alignment myChildAlignment = null; + + public JsonBlock(JsonBlock parent, ASTNode node, CodeStyleSettings settings, Alignment alignment, Indent indent, Wrap wrap) { + myParent = parent; + myNode = node; + myNodeType = node.getElementType(); + myAlignment = alignment; + myIndent = indent; + myWrap = wrap; + mySettings = settings; + + mySpacingBuilder = JsonFormattingBuilderModel.createSpacingBuilder(settings); + + if (CONTAINERS.contains(myNode.getElementType())) { + myChildWrap = Wrap.createWrap(WrapType.NORMAL, false); + myChildAlignment = Alignment.createAlignment(); + } + } + + @Override + public ASTNode getNode() { + return myNode; + } + + @NotNull + @Override + public TextRange getTextRange() { + return myNode.getTextRange(); + } + + @NotNull + @Override + public List getSubBlocks() { + if (mySubBlocks == null) { + mySubBlocks = ContainerUtil.mapNotNull(myNode.getChildren(null), new Function() { + @Override + public Block fun(ASTNode node) { + if (node.getElementType() == TokenType.WHITE_SPACE || node.getTextLength() == 0) { + return null; + } + return createSubBlock(node); + } + }); + } + return mySubBlocks; + } + + private Block createSubBlock(ASTNode childNode) { + IElementType childNodeType = childNode.getElementType(); + + Indent indent = Indent.getNoneIndent(); + Alignment alignment = null; + Wrap wrap = null; + + if (CONTAINERS.contains(myNode.getElementType())) { + if (childNodeType != COMMA && !BRACES.contains(childNodeType)) { + wrap = Wrap.createWrap(WrapType.NORMAL, true); + alignment = myChildAlignment; + indent = Indent.getNormalIndent(); + } + } + return new JsonBlock(this, childNode, mySettings, alignment, indent, wrap); + } + + @Nullable + @Override + public Wrap getWrap() { + return myWrap; + } + + @Nullable + @Override + public Indent getIndent() { + return myIndent; + } + + @Nullable + @Override + public Alignment getAlignment() { + return myAlignment; + } + + @Nullable + @Override + public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + return mySpacingBuilder.getSpacing(this, child1, child2); + } + + @NotNull + @Override + public ChildAttributes getChildAttributes(int newChildIndex) { + Indent indent = Indent.getNormalIndent(); + Alignment alignment = myChildAlignment; + + if (CONTAINERS.contains(myNodeType) && newChildIndex != 0) { + IElementType prevChildType = ((JsonBlock)mySubBlocks.get(newChildIndex - 1)).myNode.getElementType(); + if (OPEN_BRACES.contains(prevChildType)) { + indent = Indent.getNormalIndent(); + } + } + return new ChildAttributes(indent, alignment); +// return ChildAttributes.DELEGATE_TO_PREV_CHILD; + } + + @Override + public boolean isIncomplete() { + IElementType nodeType = myNode.getElementType(); + ASTNode lastChildNode = myNode.getLastChildNode(); + PsiElement psiElement = myNode.getPsi(); + if (nodeType == OBJECT) { + return lastChildNode != null && lastChildNode.getElementType() == R_CURLY; + } + else if (nodeType == ARRAY) { + return lastChildNode != null && lastChildNode.getElementType() == R_BRAKET; + } + else if (psiElement instanceof JsonProperty) { + return ((JsonProperty)psiElement).getValue() != null; + } + return false; + } + + @Override + public boolean isLeaf() { + return myNode.getFirstChildNode() == null; + } +} diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettings.java b/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettings.java new file mode 100644 index 000000000000..0d2d14475f86 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettings.java @@ -0,0 +1,21 @@ +package com.jetbrains.json.formatter; + +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CustomCodeStyleSettings; +import com.jetbrains.json.JsonLanguage; + +/** + * @author Mikhail Golubev + */ +public class JsonCodeStyleSettings extends CustomCodeStyleSettings { + + // Standard option has awkward description "Code braces" + public boolean SPACE_WITHIN_BRACES = false; + public boolean SPACE_AFTER_COLON = true; + public boolean SPACE_BEFORE_COLON = false; + + + public JsonCodeStyleSettings(CodeStyleSettings container) { + super(JsonLanguage.INSTANCE.getID(), container); + } +} diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java b/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java new file mode 100644 index 000000000000..68b530ec2027 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java @@ -0,0 +1,55 @@ +package com.jetbrains.json.formatter; + +import com.intellij.application.options.CodeStyleAbstractConfigurable; +import com.intellij.application.options.CodeStyleAbstractPanel; +import com.intellij.application.options.TabbedLanguageCodeStylePanel; +import com.intellij.lang.Language; +import com.intellij.openapi.options.Configurable; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsProvider; +import com.intellij.psi.codeStyle.CustomCodeStyleSettings; +import com.jetbrains.json.JsonLanguage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public class JsonCodeStyleSettingsProvider extends CodeStyleSettingsProvider { + @NotNull + @Override + public Configurable createSettingsPage(CodeStyleSettings settings, CodeStyleSettings originalSettings) { + return new CodeStyleAbstractConfigurable(settings, originalSettings, "JSON") { + @Override + protected CodeStyleAbstractPanel createPanel(CodeStyleSettings settings) { + final Language language = JsonLanguage.INSTANCE; + final CodeStyleSettings currentSettings = getCurrentSettings(); + return new TabbedLanguageCodeStylePanel(language, currentSettings, settings) { + @Override + protected void initTabs(CodeStyleSettings settings) { + addIndentOptionsTab(settings); + addSpacesTab(settings); + } + }; + } + + @Nullable + @Override + public String getHelpTopic() { + return null; + } + }; + } + + @Nullable + @Override + public String getConfigurableDisplayName() { + return JsonLanguage.INSTANCE.getDisplayName(); + } + + @Nullable + @Override + public CustomCodeStyleSettings createCustomSettings(CodeStyleSettings settings) { + return new JsonCodeStyleSettings(settings); + } +} diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java new file mode 100644 index 000000000000..d8fa957ed6f4 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java @@ -0,0 +1,59 @@ +package com.jetbrains.json.formatter; + +import com.intellij.formatting.*; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.impl.DebugUtil; +import com.jetbrains.json.JsonLanguage; +import com.jetbrains.json.JsonParserTypes; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.jetbrains.json.JsonParserTypes.*; + +/** + * @author Mikhail Golubev + */ +public class JsonFormattingBuilderModel implements FormattingModelBuilder { + private static final Logger LOG = Logger.getInstance(JsonFormattingBuilderModel.class); + + @NotNull + @Override + public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { + if (LOG.isDebugEnabled()) { + LOG.debug("PSI Tree:\n" + DebugUtil.psiToString(element, false)); + } + + JsonBlock block = new JsonBlock(null, element.getNode(), settings, null, Indent.getNoneIndent(), null); + if (LOG.isDebugEnabled()) { + StringBuilder builder = new StringBuilder(); + FormattingModelDumper.dumpFormattingModel(block, 2, builder); + LOG.debug("Format Model:\n" + builder.toString()); + } + return FormattingModelProvider.createFormattingModelForPsiFile(element.getContainingFile(), block, settings); + } + + @Nullable + @Override + public TextRange getRangeAffectingIndent(PsiFile file, int offset, ASTNode elementAtOffset) { + return null; + } + + // create spacing model once for all subsequent blocks + static SpacingBuilder createSpacingBuilder(CodeStyleSettings settings) { + JsonCodeStyleSettings jsonSettings = settings.getCustomSettings(JsonCodeStyleSettings.class); + CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JsonLanguage.INSTANCE); + return new SpacingBuilder(settings, JsonLanguage.INSTANCE) + .afterInside(COLON, JsonParserTypes.PROPERTY).spaceIf(jsonSettings.SPACE_AFTER_COLON) + .beforeInside(COLON, JsonParserTypes.PROPERTY).spaceIf(jsonSettings.SPACE_BEFORE_COLON) + .withinPair(L_BRAKET, R_BRAKET).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS) + .withinPair(L_CURLY, R_CURLY).spaceIf(jsonSettings.SPACE_WITHIN_BRACES) + .after(COMMA).spaceIf(commonSettings.SPACE_AFTER_COMMA) + .before(COMMA).spaceIf(commonSettings.SPACE_BEFORE_COMMA); + } +} diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java b/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java new file mode 100644 index 000000000000..7e8cc51530f0 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java @@ -0,0 +1,59 @@ +package com.jetbrains.json.formatter; + +import com.intellij.application.options.IndentOptionsEditor; +import com.intellij.application.options.SmartIndentOptionsEditor; +import com.intellij.lang.Language; +import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable; +import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; +import com.jetbrains.json.JsonLanguage; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import static com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable.SPACES_OTHER; +import static com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable.SPACES_WITHIN; + +/** + * @author Mikhail Golubev + */ +public class JsonLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSettingsProvider { + private static final String SAMPLE = "{\n" + + " \"json literals are\": {\n" + + " \"strings\": [\"foo\", \"bar\", \"\\u0062\\u0061\\u0072\"],\n" + + " \"numbers\": [42, 6.62606975e-34],\n" + + " \"boolean values\": [true, false],\n" + + " \"and null\": null\n" + + " }\n" + + "}"; + + + @Override + public void customizeSettings(@NotNull CodeStyleSettingsCustomizable consumer, @NotNull SettingsType settingsType) { + if (settingsType == SettingsType.SPACING_SETTINGS) { + consumer.showStandardOptions("SPACE_WITHIN_BRACKETS", + "SPACE_AFTER_COMMA", + "SPACE_BEFORE_COMMA"); + consumer.showCustomOption(JsonCodeStyleSettings.class, "SPACE_WITHIN_BRACES", "Braces", SPACES_WITHIN); + consumer.showCustomOption(JsonCodeStyleSettings.class, "SPACE_BEFORE_COLON", "Before ':'", SPACES_OTHER); + consumer.showCustomOption(JsonCodeStyleSettings.class, "SPACE_AFTER_COLON", "After ':'", SPACES_OTHER); + } + super.customizeSettings(consumer, settingsType); + } + + @NotNull + @Override + public Language getLanguage() { + return JsonLanguage.INSTANCE; + } + + @Nullable + @Override + public IndentOptionsEditor getIndentOptionsEditor() { + // TODO: read sources of this one carefully + return new SmartIndentOptionsEditor(); + } + + @Override + public String getCodeSample(@NotNull SettingsType settingsType) { + return SAMPLE; + } +} diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index 9192cd621f24..75559813db83 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -1,5 +1,5 @@ { - parserClass='com.jetbrains.json.Parser' + parserClass='com.jetbrains.json.JsonParser' parserUtilClass="com.jetbrains.json.JsonParserUtil" psiPackage='com.jetbrains.json.psi' psiImplPackage='com.jetbrains.json.psi.impl' @@ -36,10 +36,15 @@ json ::= object | array object ::= L_CURLY (property (COMMA property)*)? R_CURLY { pin=1 +// recoverUntil=closing_brace +// recoverUntil=comma methods=[ findProperty ] } +//private comma ::= ',' +//private closing_brace ::= !('}') + property ::= property_name COLON property_value { pin=1 methods=[ @@ -49,7 +54,12 @@ property ::= property_name COLON property_value { ] } -array ::= L_BRAKET (property_value (COMMA property_value)*)? R_BRAKET {pin=1} +array ::= L_BRAKET (property_value (COMMA property_value)*)? R_BRAKET { + pin=1 +// recoverUntil=comma +} +//private closing_bracket ::= !(']') + property_name ::= string_literal property_value ::= object | array | literal From 375acb28e282fbf4697546727b410b7cc2931c7c Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 18 Nov 2013 20:41:47 +0400 Subject: [PATCH 06/85] Rename JsonParserTypes to more canonical JsonElementTypes. Improve JSON formatting. --- ...ParserTypes.java => JsonElementTypes.java} | 6 +- .../gen/com/jetbrains/json/JsonParser.java | 2 +- .../gen/com/jetbrains/json/_JsonLexer.java | 6 +- .../json/psi/impl/JsonArrayImpl.java | 11 +-- .../json/psi/impl/JsonBooleanLiteralImpl.java | 9 +-- .../json/psi/impl/JsonLiteralImpl.java | 10 ++- .../json/psi/impl/JsonNullLiteralImpl.java | 9 +-- .../json/psi/impl/JsonNumberLiteralImpl.java | 9 +-- .../json/psi/impl/JsonObjectImpl.java | 13 ++-- .../json/psi/impl/JsonPropertyImpl.java | 11 ++- .../json/psi/impl/JsonPropertyNameImpl.java | 14 ++-- .../json/psi/impl/JsonPropertyValueImpl.java | 13 ++-- .../json/psi/impl/JsonStringLiteralImpl.java | 9 +-- .../jetbrains/json/JsonParserDefinition.java | 6 +- .../json/JsonSyntaxHighlighterFactory.java | 2 +- .../jetbrains/json/formatter/JsonBlock.java | 71 +++++++++++-------- .../formatter/JsonFormattingBuilderModel.java | 8 +-- .../json/psi/JsonPsiChangeUtils.java | 6 +- .../jetbrains/json/psi/JsonPsiImplUtils.java | 4 +- plugins/json/src/json.bnf | 5 +- 20 files changed, 111 insertions(+), 113 deletions(-) rename plugins/json/gen/com/jetbrains/json/{JsonParserTypes.java => JsonElementTypes.java} (98%) diff --git a/plugins/json/gen/com/jetbrains/json/JsonParserTypes.java b/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java similarity index 98% rename from plugins/json/gen/com/jetbrains/json/JsonParserTypes.java rename to plugins/json/gen/com/jetbrains/json/JsonElementTypes.java index 2cfb0e11d33c..92b240f07b58 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonParserTypes.java +++ b/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java @@ -1,12 +1,12 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json; -import com.intellij.psi.tree.IElementType; -import com.intellij.psi.PsiElement; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.tree.IElementType; import com.jetbrains.json.psi.impl.*; -public interface JsonParserTypes { +public interface JsonElementTypes { IElementType ARRAY = new JsonElementType("ARRAY"); IElementType BOOLEAN_LITERAL = new JsonElementType("BOOLEAN_LITERAL"); diff --git a/plugins/json/gen/com/jetbrains/json/JsonParser.java b/plugins/json/gen/com/jetbrains/json/JsonParser.java index 6b3c5291b9c2..5c5aab7bf891 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonParser.java +++ b/plugins/json/gen/com/jetbrains/json/JsonParser.java @@ -9,7 +9,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; -import static com.jetbrains.json.JsonParserTypes.*; +import static com.jetbrains.json.JsonElementTypes.*; import static com.jetbrains.json.JsonParserUtil.*; @SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"}) diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java index f5601dbad561..ad6b7a89a531 100644 --- a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java +++ b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java @@ -1,9 +1,11 @@ /* The following code was generated by JFlex 1.4.3 on 10/28/13 8:52 PM */ package com.jetbrains.json; -import com.intellij.lexer.*; + +import com.intellij.lexer.FlexLexer; import com.intellij.psi.tree.IElementType; -import static com.jetbrains.json.JsonParserTypes.*; + +import static com.jetbrains.json.JsonElementTypes.*; /** diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java index 046470864193..e942eca1ec93 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java @@ -1,14 +1,15 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; -import com.jetbrains.json.psi.*; +import com.jetbrains.json.psi.JsonArray; +import com.jetbrains.json.psi.JsonPropertyValue; +import com.jetbrains.json.psi.JsonVisitor; +import org.jetbrains.annotations.NotNull; + +import java.util.List; public class JsonArrayImpl extends JsonPropertyValueImpl implements JsonArray { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java index 6112add3eee0..43283dfe89e6 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java @@ -1,14 +1,11 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; -import com.jetbrains.json.psi.*; +import com.jetbrains.json.psi.JsonBooleanLiteral; +import com.jetbrains.json.psi.JsonVisitor; +import org.jetbrains.annotations.NotNull; public class JsonBooleanLiteralImpl extends JsonLiteralImpl implements JsonBooleanLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java index 36ec18b65c44..7518c207427b 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java @@ -1,14 +1,12 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; -import com.jetbrains.json.psi.*; +import com.jetbrains.json.psi.JsonLiteral; +import com.jetbrains.json.psi.JsonPsiImplUtils; +import com.jetbrains.json.psi.JsonVisitor; +import org.jetbrains.annotations.NotNull; public class JsonLiteralImpl extends JsonLiteralMixin implements JsonLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java index 7324d2617f6a..e9800487b836 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java @@ -1,14 +1,11 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; -import com.jetbrains.json.psi.*; +import com.jetbrains.json.psi.JsonNullLiteral; +import com.jetbrains.json.psi.JsonVisitor; +import org.jetbrains.annotations.NotNull; public class JsonNullLiteralImpl extends JsonLiteralImpl implements JsonNullLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java index a712487766ac..4d061f8d3617 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java @@ -1,14 +1,11 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; -import com.jetbrains.json.psi.*; +import com.jetbrains.json.psi.JsonNumberLiteral; +import com.jetbrains.json.psi.JsonVisitor; +import org.jetbrains.annotations.NotNull; public class JsonNumberLiteralImpl extends JsonLiteralImpl implements JsonNumberLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java index 81312a1d8ae8..e2f3b4482f55 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java @@ -1,14 +1,17 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; -import com.jetbrains.json.psi.*; +import com.jetbrains.json.psi.JsonObject; +import com.jetbrains.json.psi.JsonProperty; +import com.jetbrains.json.psi.JsonPsiImplUtils; +import com.jetbrains.json.psi.JsonVisitor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; public class JsonObjectImpl extends JsonPropertyValueImpl implements JsonObject { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java index 523f65c36560..f5f3b3f6f9b1 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java @@ -1,15 +1,12 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElementVisitor; import com.jetbrains.json.psi.*; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProperty { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java index 86a9a2f402a7..1cdaa39eca88 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java @@ -1,15 +1,13 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; import com.intellij.extapi.psi.ASTWrapperPsiElement; -import com.jetbrains.json.psi.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElementVisitor; +import com.jetbrains.json.psi.JsonPropertyName; +import com.jetbrains.json.psi.JsonStringLiteral; +import com.jetbrains.json.psi.JsonVisitor; +import org.jetbrains.annotations.NotNull; public class JsonPropertyNameImpl extends ASTWrapperPsiElement implements JsonPropertyName { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java index fa568524f91a..6b194bb6d4d8 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java @@ -1,15 +1,12 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; import com.intellij.extapi.psi.ASTWrapperPsiElement; -import com.jetbrains.json.psi.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElementVisitor; +import com.jetbrains.json.psi.JsonPropertyValue; +import com.jetbrains.json.psi.JsonVisitor; +import org.jetbrains.annotations.NotNull; public class JsonPropertyValueImpl extends ASTWrapperPsiElement implements JsonPropertyValue { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java index 907521dcbbbe..d4ab8c38b82b 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java @@ -1,14 +1,11 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi.impl; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.jetbrains.json.JsonParserTypes.*; -import com.jetbrains.json.psi.*; +import com.jetbrains.json.psi.JsonStringLiteral; +import com.jetbrains.json.psi.JsonVisitor; +import org.jetbrains.annotations.NotNull; public class JsonStringLiteralImpl extends JsonLiteralImpl implements JsonStringLiteral { diff --git a/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java b/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java index 12054b3e690f..8116a88acf05 100644 --- a/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java +++ b/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java @@ -16,9 +16,9 @@ import org.jetbrains.annotations.NotNull; public class JsonParserDefinition implements ParserDefinition { public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE); - public static final TokenSet STRING_LITERALS = TokenSet.create(JsonParserTypes.STRING); + public static final TokenSet STRING_LITERALS = TokenSet.create(JsonElementTypes.STRING); public static final IFileElementType FILE = new IFileElementType(JsonLanguage.INSTANCE); - public static final TokenSet CONTAINERS = TokenSet.create(JsonParserTypes.ARRAY, JsonParserTypes.OBJECT); + public static final TokenSet CONTAINERS = TokenSet.create(JsonElementTypes.ARRAY, JsonElementTypes.OBJECT); @NotNull @@ -58,7 +58,7 @@ public class JsonParserDefinition implements ParserDefinition { @NotNull @Override public PsiElement createElement(ASTNode astNode) { - return JsonParserTypes.Factory.createElement(astNode); + return JsonElementTypes.Factory.createElement(astNode); } @Override diff --git a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java index 4e12c9692034..89b3a30645ff 100644 --- a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java +++ b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java @@ -16,7 +16,7 @@ import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; -import static com.jetbrains.json.JsonParserTypes.*; +import static com.jetbrains.json.JsonElementTypes.*; public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { @NotNull diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java b/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java index d47096e030bd..28d0e5783402 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java @@ -11,13 +11,14 @@ import com.intellij.psi.tree.TokenSet; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.jetbrains.json.psi.JsonProperty; +import com.jetbrains.json.psi.JsonPropertyValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; +import static com.jetbrains.json.JsonElementTypes.*; import static com.jetbrains.json.JsonParserDefinition.CONTAINERS; -import static com.jetbrains.json.JsonParserTypes.*; /** * @author Mikhail Golubev @@ -26,10 +27,11 @@ public class JsonBlock implements ASTBlock { private static final TokenSet OPEN_BRACES = TokenSet.create(L_BRAKET, L_CURLY); private static final TokenSet CLOSE_BRACES = TokenSet.create(R_BRAKET, R_CURLY); private static final TokenSet BRACES = TokenSet.orSet(OPEN_BRACES, CLOSE_BRACES); + private JsonBlock myParent; - private ASTNode myNode; + private PsiElement myPsiElement; private IElementType myNodeType; private Alignment myAlignment; private Indent myIndent; @@ -39,12 +41,17 @@ public class JsonBlock implements ASTBlock { // lazy initialized on first call to #getSubBlocks() private List mySubBlocks = null; - private Wrap myChildWrap = null; - private Alignment myChildAlignment = null; + private Alignment myChildAlignment = Alignment.createAlignment(); - public JsonBlock(JsonBlock parent, ASTNode node, CodeStyleSettings settings, Alignment alignment, Indent indent, Wrap wrap) { + public JsonBlock(@Nullable JsonBlock parent, + @NotNull ASTNode node, + @NotNull CodeStyleSettings settings, + @Nullable Alignment alignment, + @NotNull Indent indent, + @Nullable Wrap wrap) { myParent = parent; myNode = node; + myPsiElement = node.getPsi(); myNodeType = node.getElementType(); myAlignment = alignment; myIndent = indent; @@ -52,11 +59,6 @@ public class JsonBlock implements ASTBlock { mySettings = settings; mySpacingBuilder = JsonFormattingBuilderModel.createSpacingBuilder(settings); - - if (CONTAINERS.contains(myNode.getElementType())) { - myChildWrap = Wrap.createWrap(WrapType.NORMAL, false); - myChildAlignment = Alignment.createAlignment(); - } } @Override @@ -77,29 +79,32 @@ public class JsonBlock implements ASTBlock { mySubBlocks = ContainerUtil.mapNotNull(myNode.getChildren(null), new Function() { @Override public Block fun(ASTNode node) { - if (node.getElementType() == TokenType.WHITE_SPACE || node.getTextLength() == 0) { + if (isWhitespaceOrEmpty(node)) { return null; } - return createSubBlock(node); + return makeSubBlock(node); } }); } return mySubBlocks; } - private Block createSubBlock(ASTNode childNode) { + private Block makeSubBlock(ASTNode childNode) { IElementType childNodeType = childNode.getElementType(); + PsiElement childPsiElement = childNode.getPsi(); Indent indent = Indent.getNoneIndent(); Alignment alignment = null; Wrap wrap = null; - if (CONTAINERS.contains(myNode.getElementType())) { - if (childNodeType != COMMA && !BRACES.contains(childNodeType)) { - wrap = Wrap.createWrap(WrapType.NORMAL, true); - alignment = myChildAlignment; - indent = Indent.getNormalIndent(); - } + if (isContainer(myNode) && childNodeType != COMMA && !BRACES.contains(childNodeType)) { + wrap = Wrap.createWrap(WrapType.NORMAL, true); + alignment = myChildAlignment; + indent = Indent.getNormalIndent(); + } + if (myNode.getElementType() == PROPERTY && childPsiElement instanceof JsonPropertyValue) { + wrap = Wrap.createWrap(WrapType.NORMAL, true); + indent = Indent.getNormalIndent(); } return new JsonBlock(this, childNode, mySettings, alignment, indent, wrap); } @@ -131,17 +136,18 @@ public class JsonBlock implements ASTBlock { @NotNull @Override public ChildAttributes getChildAttributes(int newChildIndex) { - Indent indent = Indent.getNormalIndent(); - Alignment alignment = myChildAlignment; - - if (CONTAINERS.contains(myNodeType) && newChildIndex != 0) { - IElementType prevChildType = ((JsonBlock)mySubBlocks.get(newChildIndex - 1)).myNode.getElementType(); - if (OPEN_BRACES.contains(prevChildType)) { - indent = Indent.getNormalIndent(); + JsonBlock prevBlock = newChildIndex > 0 ? (JsonBlock)mySubBlocks.get(newChildIndex - 1) : null; + ASTNode prevChild = prevBlock != null? prevBlock.myNode : null; + if (isContainer(myNode) && prevChild != null) { + // correctly indent first element after opening brace + if (OPEN_BRACES.contains(prevChild.getElementType())) { + return new ChildAttributes(Indent.getNormalIndent(), myChildAlignment); } + return ChildAttributes.DELEGATE_TO_PREV_CHILD; } - return new ChildAttributes(indent, alignment); -// return ChildAttributes.DELEGATE_TO_PREV_CHILD; + // TODO find out why inside object then cursor is after '"a": []', myNode is instance + // of JsonArray + return new ChildAttributes(Indent.getNormalIndent(), null); } @Override @@ -165,4 +171,13 @@ public class JsonBlock implements ASTBlock { public boolean isLeaf() { return myNode.getFirstChildNode() == null; } + + private static boolean isWhitespaceOrEmpty(ASTNode node) { + return node.getElementType() == TokenType.WHITE_SPACE || node.getTextLength() == 0; + } + + private static boolean isContainer(ASTNode node) { + return CONTAINERS.contains(node.getElementType()); + } + } diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java index d8fa957ed6f4..2405bdf53482 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java @@ -9,12 +9,12 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.impl.DebugUtil; +import com.jetbrains.json.JsonElementTypes; import com.jetbrains.json.JsonLanguage; -import com.jetbrains.json.JsonParserTypes; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.jetbrains.json.JsonParserTypes.*; +import static com.jetbrains.json.JsonElementTypes.*; /** * @author Mikhail Golubev @@ -49,8 +49,8 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { JsonCodeStyleSettings jsonSettings = settings.getCustomSettings(JsonCodeStyleSettings.class); CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JsonLanguage.INSTANCE); return new SpacingBuilder(settings, JsonLanguage.INSTANCE) - .afterInside(COLON, JsonParserTypes.PROPERTY).spaceIf(jsonSettings.SPACE_AFTER_COLON) - .beforeInside(COLON, JsonParserTypes.PROPERTY).spaceIf(jsonSettings.SPACE_BEFORE_COLON) + .afterInside(COLON, JsonElementTypes.PROPERTY).spaceIf(jsonSettings.SPACE_AFTER_COLON) + .beforeInside(COLON, JsonElementTypes.PROPERTY).spaceIf(jsonSettings.SPACE_BEFORE_COLON) .withinPair(L_BRAKET, R_BRAKET).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS) .withinPair(L_CURLY, R_CURLY).spaceIf(jsonSettings.SPACE_WITHIN_BRACES) .after(COMMA).spaceIf(commonSettings.SPACE_AFTER_COMMA) diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java b/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java index c6ed696c2613..257a7fd6197c 100644 --- a/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java +++ b/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java @@ -8,8 +8,8 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.TokenType; +import com.jetbrains.json.JsonElementTypes; import com.jetbrains.json.JsonFile; -import com.jetbrains.json.JsonParserTypes; import org.jetbrains.annotations.NotNull; public class JsonPsiChangeUtils { @@ -23,7 +23,7 @@ public class JsonPsiChangeUtils { toCandidate = toCandidate.getTreeNext(); } - if (toCandidate != null && toCandidate.getElementType() == JsonParserTypes.COMMA) { + if (toCandidate != null && toCandidate.getElementType() == JsonElementTypes.COMMA) { toCandidate = toCandidate.getTreeNext(); to = toCandidate; seenComma = true; @@ -40,7 +40,7 @@ public class JsonPsiChangeUtils { from = treePrev; treePrev = treePrev.getTreePrev(); } - if (treePrev != null && treePrev.getElementType() == JsonParserTypes.COMMA) { + if (treePrev != null && treePrev.getElementType() == JsonElementTypes.COMMA) { from = treePrev; } } diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java b/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java index be58ae958cf0..e35be643144f 100644 --- a/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java +++ b/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java @@ -3,7 +3,7 @@ package com.jetbrains.json.psi; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.util.PsiTreeUtil; -import com.jetbrains.json.JsonParserTypes; +import com.jetbrains.json.JsonElementTypes; import com.jetbrains.json.psi.impl.JsonPropertyImpl; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -12,7 +12,7 @@ import java.util.Collection; public class JsonPsiImplUtils { public static boolean isQuotedString(@NotNull JsonLiteral literal) { - return literal.getNode().findChildByType(JsonParserTypes.STRING) != null; + return literal.getNode().findChildByType(JsonElementTypes.STRING) != null; } @NotNull diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index 75559813db83..11e8b14097b3 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -4,7 +4,7 @@ psiPackage='com.jetbrains.json.psi' psiImplPackage='com.jetbrains.json.psi.impl' - elementTypeHolderClass='com.jetbrains.json.JsonParserTypes' + elementTypeHolderClass='com.jetbrains.json.JsonElementTypes' elementTypeClass='com.jetbrains.json.JsonElementType' psiClassPrefix="Json" @@ -36,7 +36,6 @@ json ::= object | array object ::= L_CURLY (property (COMMA property)*)? R_CURLY { pin=1 -// recoverUntil=closing_brace // recoverUntil=comma methods=[ findProperty @@ -56,7 +55,7 @@ property ::= property_name COLON property_value { array ::= L_BRAKET (property_value (COMMA property_value)*)? R_BRAKET { pin=1 -// recoverUntil=comma +// recoverUntil=closing_bracket } //private closing_bracket ::= !(']') From 1da6acb50ad70f8f28ae0d8ac1c09041b579748c Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 19 Nov 2013 16:02:53 +0400 Subject: [PATCH 07/85] Update spacing in JSON formatter: remove blank lines by default --- .../jetbrains/json/formatter/JsonBlock.java | 24 +++++++---------- .../JsonCodeStyleSettingsProvider.java | 1 + .../formatter/JsonFormattingBuilderModel.java | 27 ++++++++++++++----- ...JsonLanguageCodeStyleSettingsProvider.java | 18 +++++++++++-- 4 files changed, 48 insertions(+), 22 deletions(-) diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java b/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java index 28d0e5783402..f4cf21b6afbb 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java @@ -32,7 +32,6 @@ public class JsonBlock implements ASTBlock { private ASTNode myNode; private PsiElement myPsiElement; - private IElementType myNodeType; private Alignment myAlignment; private Indent myIndent; private Wrap myWrap; @@ -52,7 +51,6 @@ public class JsonBlock implements ASTBlock { myParent = parent; myNode = node; myPsiElement = node.getPsi(); - myNodeType = node.getElementType(); myAlignment = alignment; myIndent = indent; myWrap = wrap; @@ -97,7 +95,7 @@ public class JsonBlock implements ASTBlock { Alignment alignment = null; Wrap wrap = null; - if (isContainer(myNode) && childNodeType != COMMA && !BRACES.contains(childNodeType)) { + if (isContainer() && childNodeType != COMMA && !BRACES.contains(childNodeType)) { wrap = Wrap.createWrap(WrapType.NORMAL, true); alignment = myChildAlignment; indent = Indent.getNormalIndent(); @@ -136,17 +134,16 @@ public class JsonBlock implements ASTBlock { @NotNull @Override public ChildAttributes getChildAttributes(int newChildIndex) { - JsonBlock prevBlock = newChildIndex > 0 ? (JsonBlock)mySubBlocks.get(newChildIndex - 1) : null; - ASTNode prevChild = prevBlock != null? prevBlock.myNode : null; - if (isContainer(myNode) && prevChild != null) { + JsonBlock prevChildBlock = newChildIndex > 0 ? (JsonBlock)mySubBlocks.get(newChildIndex - 1) : null; + ASTNode prevChildNode = prevChildBlock != null? prevChildBlock.myNode : null; + if (isContainer() && prevChildNode != null) { // correctly indent first element after opening brace - if (OPEN_BRACES.contains(prevChild.getElementType())) { + if (OPEN_BRACES.contains(prevChildNode.getElementType())) { return new ChildAttributes(Indent.getNormalIndent(), myChildAlignment); } return ChildAttributes.DELEGATE_TO_PREV_CHILD; } - // TODO find out why inside object then cursor is after '"a": []', myNode is instance - // of JsonArray + // TODO find out why inside object then cursor is after '"a": []', myNode is instance of JsonArray return new ChildAttributes(Indent.getNormalIndent(), null); } @@ -154,15 +151,14 @@ public class JsonBlock implements ASTBlock { public boolean isIncomplete() { IElementType nodeType = myNode.getElementType(); ASTNode lastChildNode = myNode.getLastChildNode(); - PsiElement psiElement = myNode.getPsi(); if (nodeType == OBJECT) { return lastChildNode != null && lastChildNode.getElementType() == R_CURLY; } else if (nodeType == ARRAY) { return lastChildNode != null && lastChildNode.getElementType() == R_BRAKET; } - else if (psiElement instanceof JsonProperty) { - return ((JsonProperty)psiElement).getValue() != null; + else if (myPsiElement instanceof JsonProperty) { + return ((JsonProperty)myPsiElement).getValue() != null; } return false; } @@ -176,8 +172,8 @@ public class JsonBlock implements ASTBlock { return node.getElementType() == TokenType.WHITE_SPACE || node.getTextLength() == 0; } - private static boolean isContainer(ASTNode node) { - return CONTAINERS.contains(node.getElementType()); + private boolean isContainer() { + return CONTAINERS.contains(myNode.getElementType()); } } diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java b/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java index 68b530ec2027..bab129809fb4 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java @@ -29,6 +29,7 @@ public class JsonCodeStyleSettingsProvider extends CodeStyleSettingsProvider { protected void initTabs(CodeStyleSettings settings) { addIndentOptionsTab(settings); addSpacesTab(settings); + addBlankLinesTab(settings); } }; } diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java index 2405bdf53482..fb9391277a38 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java @@ -9,7 +9,7 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.impl.DebugUtil; -import com.jetbrains.json.JsonElementTypes; +import com.intellij.psi.tree.TokenSet; import com.jetbrains.json.JsonLanguage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -22,6 +22,14 @@ import static com.jetbrains.json.JsonElementTypes.*; public class JsonFormattingBuilderModel implements FormattingModelBuilder { private static final Logger LOG = Logger.getInstance(JsonFormattingBuilderModel.class); + private static final TokenSet VALUES = TokenSet.create( + OBJECT, ARRAY, STRING_LITERAL, NUMBER_LITERAL, BOOLEAN_LITERAL, NULL + ); + + private static final TokenSet SIGNS = TokenSet.create( + L_BRAKET, R_BRAKET, L_CURLY, R_CURLY, COMMA, COLON + ); + @NotNull @Override public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { @@ -48,12 +56,19 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { static SpacingBuilder createSpacingBuilder(CodeStyleSettings settings) { JsonCodeStyleSettings jsonSettings = settings.getCustomSettings(JsonCodeStyleSettings.class); CommonCodeStyleSettings commonSettings = settings.getCommonSettings(JsonLanguage.INSTANCE); - return new SpacingBuilder(settings, JsonLanguage.INSTANCE) - .afterInside(COLON, JsonElementTypes.PROPERTY).spaceIf(jsonSettings.SPACE_AFTER_COLON) - .beforeInside(COLON, JsonElementTypes.PROPERTY).spaceIf(jsonSettings.SPACE_BEFORE_COLON) + + + int spacesBeforeComma = commonSettings.SPACE_BEFORE_COMMA ? 1 : 0; + int spacesBeforeColon = commonSettings.SPACE_BEFORE_COLON ? 1 : 0; + // not allow to keep line breaks before colon/comma, because it looks horrible + SpacingBuilder builder = new SpacingBuilder(settings, JsonLanguage.INSTANCE) + .before(COLON).spacing(spacesBeforeColon, spacesBeforeColon, 0, false, 0) + .after(COLON).spaceIf(jsonSettings.SPACE_AFTER_COLON) .withinPair(L_BRAKET, R_BRAKET).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS) .withinPair(L_CURLY, R_CURLY).spaceIf(jsonSettings.SPACE_WITHIN_BRACES) - .after(COMMA).spaceIf(commonSettings.SPACE_AFTER_COMMA) - .before(COMMA).spaceIf(commonSettings.SPACE_BEFORE_COMMA); + .before(COMMA).spacing(spacesBeforeComma, spacesBeforeComma, 0, false, 0) + .after(COMMA).spaceIf(commonSettings.SPACE_AFTER_COMMA); + + return builder; } } diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java b/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java index 7e8cc51530f0..864d80bf6c81 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java @@ -4,6 +4,7 @@ import com.intellij.application.options.IndentOptionsEditor; import com.intellij.application.options.SmartIndentOptionsEditor; import com.intellij.lang.Language; import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; import com.jetbrains.json.JsonLanguage; import org.jetbrains.annotations.NotNull; @@ -21,7 +22,7 @@ public class JsonLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett " \"strings\": [\"foo\", \"bar\", \"\\u0062\\u0061\\u0072\"],\n" + " \"numbers\": [42, 6.62606975e-34],\n" + " \"boolean values\": [true, false],\n" + - " \"and null\": null\n" + + " \"and\": {\"null\": null}\n" + " }\n" + "}"; @@ -31,11 +32,15 @@ public class JsonLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett if (settingsType == SettingsType.SPACING_SETTINGS) { consumer.showStandardOptions("SPACE_WITHIN_BRACKETS", "SPACE_AFTER_COMMA", - "SPACE_BEFORE_COMMA"); + "SPACE_BEFORE_COMMA" + ); consumer.showCustomOption(JsonCodeStyleSettings.class, "SPACE_WITHIN_BRACES", "Braces", SPACES_WITHIN); consumer.showCustomOption(JsonCodeStyleSettings.class, "SPACE_BEFORE_COLON", "Before ':'", SPACES_OTHER); consumer.showCustomOption(JsonCodeStyleSettings.class, "SPACE_AFTER_COLON", "After ':'", SPACES_OTHER); } + if (settingsType == SettingsType.BLANK_LINES_SETTINGS) { + consumer.showStandardOptions("KEEP_BLANK_LINES_IN_CODE"); + } super.customizeSettings(consumer, settingsType); } @@ -56,4 +61,13 @@ public class JsonLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett public String getCodeSample(@NotNull SettingsType settingsType) { return SAMPLE; } + + @Nullable + @Override + public CommonCodeStyleSettings getDefaultCommonSettings() { + CommonCodeStyleSettings commonSettings = new CommonCodeStyleSettings(JsonLanguage.INSTANCE); + // strip all blank lines by default + commonSettings.KEEP_BLANK_LINES_IN_CODE = 0; + return commonSettings; + } } From c7d91588bb37ca2b5f120e4a8f5b5a43c67da8d9 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 19 Nov 2013 16:03:17 +0400 Subject: [PATCH 08/85] Add BraceMatcher for JSON --- plugins/json/src/META-INF/plugin.xml | 1 + .../com/jetbrains/json/JsonBraceMatcher.java | 33 +++++++++++++++++++ 2 files changed, 34 insertions(+) create mode 100644 plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java diff --git a/plugins/json/src/META-INF/plugin.xml b/plugins/json/src/META-INF/plugin.xml index 328b7dd0e332..aecd5d5aa480 100644 --- a/plugins/json/src/META-INF/plugin.xml +++ b/plugins/json/src/META-INF/plugin.xml @@ -31,5 +31,6 @@ + \ No newline at end of file diff --git a/plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java b/plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java new file mode 100644 index 000000000000..b5ab7544de01 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java @@ -0,0 +1,33 @@ +package com.jetbrains.json; + +import com.intellij.lang.BracePair; +import com.intellij.lang.PairedBraceMatcher; +import com.intellij.psi.PsiFile; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public class JsonBraceMatcher implements PairedBraceMatcher { + private static BracePair[] PAIRS = { + new BracePair(JsonElementTypes.L_BRAKET, JsonElementTypes.R_BRAKET, true), + new BracePair(JsonElementTypes.L_CURLY, JsonElementTypes.R_CURLY, true) + }; + + @Override + public BracePair[] getPairs() { + return PAIRS; + } + + @Override + public boolean isPairedBracesAllowedBeforeType(@NotNull IElementType lbraceType, @Nullable IElementType contextType) { + return true; + } + + @Override + public int getCodeConstructStart(PsiFile file, int openingBraceOffset) { + return openingBraceOffset; + } +} From bfc7ab5f8bdc29978ab3c8f5fc3fb0d5b171e348 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 20 Nov 2013 15:50:26 +0400 Subject: [PATCH 09/85] Update grammar to match closing braces/brackets --- plugins/json/src/json.bnf | 36 +++++++++++++++++++++--------------- 1 file changed, 21 insertions(+), 15 deletions(-) diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index 11e8b14097b3..c6874f7a6111 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -14,8 +14,8 @@ tokens = [ L_CURLY='{' R_CURLY='}' - L_BRAKET='[' - R_BRAKET=']' + L_BRACKET='[' + R_BRACKET=']' COMMA=',' COLON=':' @@ -28,40 +28,43 @@ NULL='null' ] - extends("object|array|literal")=property_value + extends("object|array|literal")=value extends("string_literal|number_literal|boolean_literal|null_literal")=literal } json ::= object | array -object ::= L_CURLY (property (COMMA property)*)? R_CURLY { +object ::= L_CURLY properties? R_CURLY { pin=1 -// recoverUntil=comma methods=[ findProperty ] } -//private comma ::= ',' -//private closing_brace ::= !('}') -property ::= property_name COLON property_value { - pin=1 +private properties ::= property (COMMA property)* { + pin = 1 + recoverUntil = closing_brace +} + +property ::= property_name COLON value { methods=[ getName - getValue delete ] } -array ::= L_BRAKET (property_value (COMMA property_value)*)? R_BRAKET { +array ::= L_BRACKET elements? R_BRACKET { pin=1 -// recoverUntil=closing_bracket } -//private closing_bracket ::= !(']') + +private elements ::= value (COMMA value)* { + pin = 1 + recoverUntil = closing_bracket +} property_name ::= string_literal -property_value ::= object | array | literal +value ::= object | array | literal string_literal ::= STRING number_literal ::= NUMBER @@ -71,4 +74,7 @@ null_literal ::= NULL literal ::= string_literal | number_literal | boolean_literal | null_literal { methods=[isQuotedString] mixin="com.jetbrains.json.psi.impl.JsonLiteralMixin" -} \ No newline at end of file +} + +private closing_bracket ::= !R_BRACKET +private closing_brace ::= !R_CURLY \ No newline at end of file From d15b43f68c2f739e1adf8699e65a4a10817481dc Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 20 Nov 2013 18:16:54 +0400 Subject: [PATCH 10/85] Update grammar and formatter --- .../com/jetbrains/json/JsonElementTypes.java | 12 +- .../gen/com/jetbrains/json/JsonLexer.java | 14 ++ .../gen/com/jetbrains/json/JsonParser.java | 221 ++++++++++++------ .../gen/com/jetbrains/json/_JsonLexer.flex | 46 ++++ .../gen/com/jetbrains/json/_JsonLexer.java | 123 ++++------ .../gen/com/jetbrains/json/psi/JsonArray.java | 10 +- .../com/jetbrains/json/psi/JsonLiteral.java | 6 +- .../com/jetbrains/json/psi/JsonObject.java | 9 +- .../com/jetbrains/json/psi/JsonProperty.java | 10 +- ...{JsonPropertyValue.java => JsonValue.java} | 4 +- .../com/jetbrains/json/psi/JsonVisitor.java | 18 +- .../json/psi/impl/JsonArrayImpl.java | 8 +- .../json/psi/impl/JsonObjectImpl.java | 2 +- .../json/psi/impl/JsonPropertyImpl.java | 9 +- ...pertyValueImpl.java => JsonValueImpl.java} | 8 +- .../com/jetbrains/json/JsonBraceMatcher.java | 2 +- .../jetbrains/json/JsonParserDefinition.java | 3 +- .../json/JsonSyntaxHighlighterFactory.java | 41 ++-- .../jetbrains/json/formatter/JsonBlock.java | 22 +- .../formatter/JsonFormattingBuilderModel.java | 6 +- .../json/psi/JsonLiteralManipulator.java | 2 +- .../jetbrains/json/psi/JsonPsiImplUtils.java | 4 +- .../json/psi/impl/JsonLiteralMixin.java | 2 +- plugins/json/src/json.bnf | 27 +-- plugins/json/src/json.flex | 54 ----- 25 files changed, 356 insertions(+), 307 deletions(-) create mode 100644 plugins/json/gen/com/jetbrains/json/JsonLexer.java create mode 100644 plugins/json/gen/com/jetbrains/json/_JsonLexer.flex rename plugins/json/gen/com/jetbrains/json/psi/{JsonPropertyValue.java => JsonValue.java} (54%) rename plugins/json/gen/com/jetbrains/json/psi/impl/{JsonPropertyValueImpl.java => JsonValueImpl.java} (69%) delete mode 100644 plugins/json/src/json.flex diff --git a/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java b/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java index 92b240f07b58..952f0a0b5b4a 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java +++ b/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java @@ -16,17 +16,17 @@ public interface JsonElementTypes { IElementType OBJECT = new JsonElementType("OBJECT"); IElementType PROPERTY = new JsonElementType("PROPERTY"); IElementType PROPERTY_NAME = new JsonElementType("PROPERTY_NAME"); - IElementType PROPERTY_VALUE = new JsonElementType("PROPERTY_VALUE"); IElementType STRING_LITERAL = new JsonElementType("STRING_LITERAL"); + IElementType VALUE = new JsonElementType("VALUE"); IElementType COLON = new JsonTokenType(":"); IElementType COMMA = new JsonTokenType(","); IElementType FALSE = new JsonTokenType("false"); - IElementType L_BRAKET = new JsonTokenType("["); + IElementType L_BRACKET = new JsonTokenType("["); IElementType L_CURLY = new JsonTokenType("{"); IElementType NULL = new JsonTokenType("null"); IElementType NUMBER = new JsonTokenType("NUMBER"); - IElementType R_BRAKET = new JsonTokenType("]"); + IElementType R_BRACKET = new JsonTokenType("]"); IElementType R_CURLY = new JsonTokenType("}"); IElementType STRING = new JsonTokenType("STRING"); IElementType TRUE = new JsonTokenType("true"); @@ -58,12 +58,12 @@ public interface JsonElementTypes { else if (type == PROPERTY_NAME) { return new JsonPropertyNameImpl(node); } - else if (type == PROPERTY_VALUE) { - return new JsonPropertyValueImpl(node); - } else if (type == STRING_LITERAL) { return new JsonStringLiteralImpl(node); } + else if (type == VALUE) { + return new JsonValueImpl(node); + } throw new AssertionError("Unknown element type: " + type); } } diff --git a/plugins/json/gen/com/jetbrains/json/JsonLexer.java b/plugins/json/gen/com/jetbrains/json/JsonLexer.java new file mode 100644 index 000000000000..4b71bcc887bd --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/JsonLexer.java @@ -0,0 +1,14 @@ +package com.jetbrains.json; + +import com.intellij.lexer.FlexAdapter; + +import java.io.Reader; + +/** + * @author Mikhail Golubev + */ +public class JsonLexer extends FlexAdapter { + public JsonLexer() { + super(new _JsonLexer((Reader)null)); + } +} diff --git a/plugins/json/gen/com/jetbrains/json/JsonParser.java b/plugins/json/gen/com/jetbrains/json/JsonParser.java index 5c5aab7bf891..bfe11935d084 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonParser.java +++ b/plugins/json/gen/com/jetbrains/json/JsonParser.java @@ -45,12 +45,12 @@ public class JsonParser implements PsiParser { else if (root_ == PROPERTY_NAME) { result_ = property_name(builder_, level_ + 1); } - else if (root_ == PROPERTY_VALUE) { - result_ = property_value(builder_, level_ + 1); - } else if (root_ == STRING_LITERAL) { result_ = string_literal(builder_, level_ + 1); } + else if (root_ == VALUE) { + result_ = value(builder_, level_ + 1); + } else { Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = parse_root_(root_, builder_, level_); @@ -67,52 +67,66 @@ public class JsonParser implements PsiParser { create_token_set_(BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, NUMBER_LITERAL, STRING_LITERAL), create_token_set_(ARRAY, BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, - NUMBER_LITERAL, OBJECT, PROPERTY_VALUE, STRING_LITERAL), + NUMBER_LITERAL, OBJECT, STRING_LITERAL, VALUE), }; /* ********************************************************** */ - // L_BRAKET (property_value (COMMA property_value)*)? R_BRAKET + // L_BRACKET [array_elements] R_BRACKET public static boolean array(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array")) return false; - if (!nextTokenIs(builder_, L_BRAKET)) return false; + if (!nextTokenIs(builder_, L_BRACKET)) return false; boolean result_ = false; boolean pinned_ = false; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); - result_ = consumeToken(builder_, L_BRAKET); + result_ = consumeToken(builder_, L_BRACKET); pinned_ = result_; // pin = 1 result_ = result_ && report_error_(builder_, array_1(builder_, level_ + 1)); - result_ = pinned_ && consumeToken(builder_, R_BRAKET) && result_; + result_ = pinned_ && consumeToken(builder_, R_BRACKET) && result_; exit_section_(builder_, level_, marker_, ARRAY, result_, pinned_, null); return result_ || pinned_; } - // (property_value (COMMA property_value)*)? + // [array_elements] private static boolean array_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_1")) return false; - array_1_0(builder_, level_ + 1); + array_elements(builder_, level_ + 1); return true; } - // property_value (COMMA property_value)* - private static boolean array_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "array_1_0")) return false; + /* ********************************************************** */ + // value + static boolean array_element(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_element")) return false; boolean result_ = false; - Marker marker_ = enter_section_(builder_); - result_ = property_value(builder_, level_ + 1); - result_ = result_ && array_1_0_1(builder_, level_ + 1); - exit_section_(builder_, marker_, null, result_); + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); + result_ = value(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, false, bracket_or_comma_parser_); return result_; } - // (COMMA property_value)* - private static boolean array_1_0_1(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "array_1_0_1")) return false; + /* ********************************************************** */ + // array_element (COMMA array_element)* + static boolean array_elements(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_elements")) return false; + boolean result_ = false; + boolean pinned_ = false; + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); + result_ = array_element(builder_, level_ + 1); + pinned_ = result_; // pin = 1 + result_ = result_ && array_elements_1(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, pinned_, null); + return result_ || pinned_; + } + + // (COMMA array_element)* + private static boolean array_elements_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_elements_1")) return false; int offset_ = builder_.getCurrentOffset(); while (true) { - if (!array_1_0_1_0(builder_, level_ + 1)) break; + if (!array_elements_1_0(builder_, level_ + 1)) break; int next_offset_ = builder_.getCurrentOffset(); if (offset_ == next_offset_) { - empty_element_parsed_guard_(builder_, offset_, "array_1_0_1"); + empty_element_parsed_guard_(builder_, offset_, "array_elements_1"); break; } offset_ = next_offset_; @@ -120,15 +134,17 @@ public class JsonParser implements PsiParser { return true; } - // COMMA property_value - private static boolean array_1_0_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "array_1_0_1_0")) return false; + // COMMA array_element + private static boolean array_elements_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_elements_1_0")) return false; boolean result_ = false; - Marker marker_ = enter_section_(builder_); + boolean pinned_ = false; + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = consumeToken(builder_, COMMA); - result_ = result_ && property_value(builder_, level_ + 1); - exit_section_(builder_, marker_, null, result_); - return result_; + pinned_ = result_; // pin = 1 + result_ = result_ && array_element(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, pinned_, null); + return result_ || pinned_; } /* ********************************************************** */ @@ -145,11 +161,55 @@ public class JsonParser implements PsiParser { return result_; } + /* ********************************************************** */ + // !(R_CURLY|COMMA) + static boolean brace_or_comma(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "brace_or_comma")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_, level_, _NOT_, null); + result_ = !brace_or_comma_0(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, false, null); + return result_; + } + + // R_CURLY|COMMA + private static boolean brace_or_comma_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "brace_or_comma_0")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, R_CURLY); + if (!result_) result_ = consumeToken(builder_, COMMA); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + /* ********************************************************** */ + // !(R_BRACKET|COMMA) + static boolean bracket_or_comma(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "bracket_or_comma")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_, level_, _NOT_, null); + result_ = !bracket_or_comma_0(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, false, null); + return result_; + } + + // R_BRACKET|COMMA + private static boolean bracket_or_comma_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "bracket_or_comma_0")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, R_BRACKET); + if (!result_) result_ = consumeToken(builder_, COMMA); + exit_section_(builder_, marker_, null, result_); + return result_; + } + /* ********************************************************** */ // object | array static boolean json(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "json")) return false; - if (!nextTokenIs(builder_, L_BRAKET) && !nextTokenIs(builder_, L_CURLY)) return false; + if (!nextTokenIs(builder_, L_BRACKET) && !nextTokenIs(builder_, L_CURLY)) return false; boolean result_ = false; Marker marker_ = enter_section_(builder_); result_ = object(builder_, level_ + 1); @@ -197,7 +257,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // L_CURLY (property (COMMA property)*)? R_CURLY + // L_CURLY [properties] R_CURLY public static boolean object(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object")) return false; if (!nextTokenIs(builder_, L_CURLY)) return false; @@ -212,33 +272,37 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } - // (property (COMMA property)*)? + // [properties] private static boolean object_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object_1")) return false; - object_1_0(builder_, level_ + 1); + properties(builder_, level_ + 1); return true; } + /* ********************************************************** */ // property (COMMA property)* - private static boolean object_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "object_1_0")) return false; + static boolean properties(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "properties")) return false; + if (!nextTokenIs(builder_, STRING)) return false; boolean result_ = false; - Marker marker_ = enter_section_(builder_); + boolean pinned_ = false; + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = property(builder_, level_ + 1); - result_ = result_ && object_1_0_1(builder_, level_ + 1); - exit_section_(builder_, marker_, null, result_); - return result_; + pinned_ = result_; // pin = 1 + result_ = result_ && properties_1(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, pinned_, null); + return result_ || pinned_; } // (COMMA property)* - private static boolean object_1_0_1(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "object_1_0_1")) return false; + private static boolean properties_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "properties_1")) return false; int offset_ = builder_.getCurrentOffset(); while (true) { - if (!object_1_0_1_0(builder_, level_ + 1)) break; + if (!properties_1_0(builder_, level_ + 1)) break; int next_offset_ = builder_.getCurrentOffset(); if (offset_ == next_offset_) { - empty_element_parsed_guard_(builder_, offset_, "object_1_0_1"); + empty_element_parsed_guard_(builder_, offset_, "properties_1"); break; } offset_ = next_offset_; @@ -247,29 +311,30 @@ public class JsonParser implements PsiParser { } // COMMA property - private static boolean object_1_0_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "object_1_0_1_0")) return false; - boolean result_ = false; - Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, COMMA); - result_ = result_ && property(builder_, level_ + 1); - exit_section_(builder_, marker_, null, result_); - return result_; - } - - /* ********************************************************** */ - // property_name COLON property_value - public static boolean property(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "property")) return false; - if (!nextTokenIs(builder_, STRING)) return false; + private static boolean properties_1_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "properties_1_0")) return false; boolean result_ = false; boolean pinned_ = false; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); + result_ = consumeToken(builder_, COMMA); + pinned_ = result_; // pin = 1 + result_ = result_ && property(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, pinned_, null); + return result_ || pinned_; + } + + /* ********************************************************** */ + // property_name COLON value + public static boolean property(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "property")) return false; + boolean result_ = false; + boolean pinned_ = false; + Marker marker_ = enter_section_(builder_, level_, _NONE_, ""); result_ = property_name(builder_, level_ + 1); pinned_ = result_; // pin = 1 result_ = result_ && report_error_(builder_, consumeToken(builder_, COLON)); - result_ = pinned_ && property_value(builder_, level_ + 1) && result_; - exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, null); + result_ = pinned_ && value(builder_, level_ + 1) && result_; + exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, brace_or_comma_parser_); return result_ || pinned_; } @@ -285,19 +350,6 @@ public class JsonParser implements PsiParser { return result_; } - /* ********************************************************** */ - // object | array | literal - public static boolean property_value(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "property_value")) return false; - boolean result_ = false; - Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); - result_ = object(builder_, level_ + 1); - if (!result_) result_ = array(builder_, level_ + 1); - if (!result_) result_ = literal(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, PROPERTY_VALUE, result_, false, null); - return result_; - } - /* ********************************************************** */ // STRING public static boolean string_literal(PsiBuilder builder_, int level_) { @@ -310,4 +362,27 @@ public class JsonParser implements PsiParser { return result_; } + /* ********************************************************** */ + // object | array | literal + public static boolean value(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "value")) return false; + boolean result_ = false; + Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); + result_ = object(builder_, level_ + 1); + if (!result_) result_ = array(builder_, level_ + 1); + if (!result_) result_ = literal(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, VALUE, result_, false, null); + return result_; + } + + final static Parser brace_or_comma_parser_ = new Parser() { + public boolean parse(PsiBuilder builder_, int level_) { + return brace_or_comma(builder_, level_ + 1); + } + }; + final static Parser bracket_or_comma_parser_ = new Parser() { + public boolean parse(PsiBuilder builder_, int level_) { + return bracket_or_comma(builder_, level_ + 1); + } + }; } diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex b/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex new file mode 100644 index 000000000000..2dc24f28bc68 --- /dev/null +++ b/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex @@ -0,0 +1,46 @@ +package com.jetbrains.json; +import com.intellij.lexer.*; +import com.intellij.psi.tree.IElementType; +import static com.jetbrains.json.JsonElementTypes.*; + +%% + +%{ + public _JsonLexer() { + this((java.io.Reader)null); + } +%} + +%public +%class _JsonLexer +%implements FlexLexer +%function advance +%type IElementType +%unicode + +EOL="\r"|"\n"|"\r\n" +LINE_WS=[\ \t\f] +WHITE_SPACE=({LINE_WS}|{EOL})+ + +STRING=\"([^\\\"]|\\([\\\"/bfnrt]|u[a-fA-F0-9]{4}))*\" +NUMBER=-?[0-9]+(\.[0-9]+([eE][+-]?[0-9]+)?)? + +%% + { + {WHITE_SPACE} { return com.intellij.psi.TokenType.WHITE_SPACE; } + + "{" { return L_CURLY; } + "}" { return R_CURLY; } + "[" { return L_BRACKET; } + "]" { return R_BRACKET; } + "," { return COMMA; } + ":" { return COLON; } + "true" { return TRUE; } + "false" { return FALSE; } + "null" { return NULL; } + + {STRING} { return STRING; } + {NUMBER} { return NUMBER; } + + [^] { return com.intellij.psi.TokenType.BAD_CHARACTER; } +} diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java index ad6b7a89a531..f6759187504d 100644 --- a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java +++ b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 10/28/13 8:52 PM */ +/* The following code was generated by JFlex 1.4.3 on 11/20/13 2:33 PM */ package com.jetbrains.json; @@ -11,8 +11,8 @@ import static com.jetbrains.json.JsonElementTypes.*; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 10/28/13 8:52 PM from the specification file - * json.flex + * on 11/20/13 2:33 PM from the specification file + * /home/east825/development/repos/IDEA/community/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex */ public class _JsonLexer implements FlexLexer { /** initial size of the lookahead buffer */ @@ -35,18 +35,11 @@ public class _JsonLexer implements FlexLexer { * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = - "\11\0\2\1\2\0\1\1\22\0\1\1\1\0\1\10\10\0\1\23"+ - "\1\6\1\16\1\21\1\12\12\20\1\7\6\0\4\14\1\22\1\14"+ - "\24\0\1\4\1\11\1\5\3\0\1\30\1\15\2\14\1\26\1\27"+ - "\5\0\1\31\1\0\1\33\3\0\1\25\1\32\1\24\1\13\5\0"+ - "\1\2\1\0\1\3\u05e2\0\12\17\206\0\12\17\306\0\12\17\u019c\0"+ - "\12\17\166\0\12\17\166\0\12\17\166\0\12\17\166\0\12\17\166\0"+ - "\12\17\166\0\12\17\166\0\12\17\166\0\12\17\340\0\12\17\166\0"+ - "\12\17\106\0\12\17\u0116\0\12\17\106\0\12\17\u0746\0\12\17\46\0"+ - "\12\17\u012c\0\12\17\200\0\12\17\246\0\12\17\6\0\12\17\266\0"+ - "\12\17\126\0\12\17\206\0\12\17\6\0\12\17\u89c6\0\12\17\u02a6\0"+ - "\12\17\46\0\12\17\306\0\12\17\166\0\12\17\u0196\0\12\17\u5316\0"+ - "\12\17\346\0"; + "\11\0\1\1\1\1\1\0\1\1\1\1\22\0\1\1\1\0\1\2"+ + "\10\0\1\14\1\21\1\10\1\12\1\4\12\11\1\22\6\0\4\6"+ + "\1\13\1\6\24\0\1\17\1\3\1\20\3\0\1\27\1\7\2\6"+ + "\1\25\1\26\5\0\1\30\1\0\1\32\3\0\1\24\1\31\1\23"+ + "\1\5\5\0\1\15\1\0\1\16\uff82\0"; /** * Translates characters to character classes @@ -59,9 +52,9 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\1\0\1\1\1\2\1\3\1\4\1\5\1\6\1\7"+ - "\1\10\2\1\1\11\3\1\1\0\1\12\6\0\1\11"+ - "\5\0\1\13\1\0\1\14\2\0\1\11\1\15\1\0"; + "\1\0\1\1\1\2\2\1\1\3\1\4\1\5\1\6"+ + "\1\7\1\10\1\11\3\1\1\0\1\12\6\0\1\3"+ + "\5\0\1\13\1\0\1\14\2\0\1\3\1\15\1\0"; private static int [] zzUnpackAction() { int [] result = new int[37]; @@ -89,11 +82,11 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\34\0\70\0\34\0\34\0\34\0\34\0\34"+ - "\0\34\0\124\0\160\0\214\0\250\0\304\0\340\0\124"+ - "\0\34\0\374\0\u0118\0\u0134\0\u0150\0\u016c\0\u0188\0\u01a4"+ - "\0\u01c0\0\u01dc\0\u01f8\0\u0214\0\u0230\0\34\0\u024c\0\34"+ - "\0\u0268\0\u0284\0\u0284\0\34\0\u02a0"; + "\0\0\0\33\0\66\0\121\0\154\0\207\0\33\0\33"+ + "\0\33\0\33\0\33\0\33\0\242\0\275\0\330\0\121"+ + "\0\33\0\363\0\u010e\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+ + "\0\u01b0\0\u01cb\0\u01e6\0\u0201\0\u021c\0\33\0\u0237\0\33"+ + "\0\u0252\0\u026d\0\u026d\0\33\0\u0288"; private static int [] zzUnpackRowMap() { int [] result = new int[37]; @@ -119,23 +112,23 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = - "\1\2\1\3\1\4\1\5\1\6\1\7\1\10\1\11"+ - "\1\12\5\2\1\13\2\14\3\2\1\15\2\2\1\16"+ - "\3\2\1\17\35\0\1\3\32\0\10\20\1\21\1\22"+ - "\22\20\17\0\2\14\32\0\2\14\1\23\37\0\1\24"+ - "\36\0\1\25\16\0\1\26\30\0\3\20\1\27\1\0"+ - "\1\20\6\0\2\20\1\0\1\20\3\0\1\20\17\0"+ - "\2\30\26\0\1\31\51\0\1\32\33\0\1\33\16\0"+ - "\2\34\2\0\1\34\1\0\1\34\3\0\3\34\22\0"+ - "\2\30\1\0\1\35\3\0\1\35\33\0\1\36\37\0"+ - "\1\37\32\0\1\40\16\0\2\41\2\0\1\41\1\0"+ - "\1\41\3\0\3\41\21\0\1\42\2\43\2\0\1\42"+ - "\36\0\1\44\21\0\2\45\2\0\1\45\1\0\1\45"+ - "\3\0\3\45\22\0\2\43\27\0\2\20\2\0\1\20"+ - "\1\0\1\20\3\0\3\20\3\0"; + "\1\2\1\3\1\4\5\2\1\5\1\6\3\2\1\7"+ + "\1\10\1\11\1\12\1\13\1\14\1\15\2\2\1\16"+ + "\3\2\1\17\34\0\1\3\31\0\2\20\1\21\1\22"+ + "\27\20\11\0\1\6\32\0\1\6\1\23\44\0\1\24"+ + "\35\0\1\25\10\0\1\26\27\0\3\20\1\27\1\0"+ + "\1\20\13\0\2\20\1\0\1\20\3\0\1\20\11\0"+ + "\1\30\26\0\1\31\55\0\1\32\32\0\1\33\10\0"+ + "\2\34\1\0\1\34\1\0\1\34\11\0\3\34\14\0"+ + "\1\30\1\0\1\35\11\0\1\35\32\0\1\36\36\0"+ + "\1\37\31\0\1\40\10\0\2\41\1\0\1\41\1\0"+ + "\1\41\11\0\3\41\13\0\1\42\1\43\2\0\1\42"+ + "\43\0\1\44\13\0\2\45\1\0\1\45\1\0\1\45"+ + "\11\0\3\45\14\0\1\43\27\0\2\20\1\0\1\20"+ + "\1\0\1\20\11\0\3\20\3\0"; private static int [] zzUnpackTrans() { - int [] result = new int[700]; + int [] result = new int[675]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -176,7 +169,7 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\1\0\1\11\1\1\6\11\6\1\1\0\1\11\6\0"+ + "\1\0\1\11\4\1\6\11\3\1\1\0\1\11\6\0"+ "\1\1\5\0\1\11\1\0\1\11\2\0\1\1\1\11"+ "\1\0"; @@ -236,9 +229,6 @@ public class _JsonLexer implements FlexLexer { /** zzAtEOF == true <=> the scanner is at the EOF */ private boolean zzAtEOF; - /** denotes if the user-EOF-code has already been executed */ - private boolean zzEOFDone; - /* user code: */ public _JsonLexer() { this((java.io.Reader)null); @@ -269,7 +259,7 @@ public class _JsonLexer implements FlexLexer { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ - while (i < 224) { + while (i < 92) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); @@ -401,18 +391,6 @@ public class _JsonLexer implements FlexLexer { } - /** - * Contains user EOF-code, which will be executed exactly once, - * when the end of file is reached - */ - private void zzDoEOF() { - if (!zzEOFDone) { - zzEOFDone = true; - - } - } - - /** * Resumes scanning until the next regular expression is matched, * the end of input is encountered or an I/O-Error occurs. @@ -450,7 +428,7 @@ public class _JsonLexer implements FlexLexer { while (true) { if (zzCurrentPosL < zzEndReadL) - zzInput = zzBufferL.charAt(zzCurrentPosL++); + zzInput = (zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++] : zzBufferL.charAt(zzCurrentPosL++)); else if (zzAtEOF) { zzInput = YYEOF; break zzForAction; @@ -470,7 +448,7 @@ public class _JsonLexer implements FlexLexer { break zzForAction; } else { - zzInput = zzBufferL.charAt(zzCurrentPosL++); + zzInput = (zzBufferArrayL != null ? zzBufferArrayL[zzCurrentPosL++] : zzBufferL.charAt(zzCurrentPosL++)); } } int zzNext = zzTransL[ zzRowMapL[zzState] + zzCMapL[zzInput] ]; @@ -491,11 +469,11 @@ public class _JsonLexer implements FlexLexer { zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 4: + case 5: { return R_CURLY; } case 14: break; - case 3: + case 4: { return L_CURLY; } case 15: break; @@ -503,15 +481,15 @@ public class _JsonLexer implements FlexLexer { { return NULL; } case 16: break; - case 5: - { return L_BRAKET; + case 6: + { return L_BRACKET; } case 17: break; case 2: { return com.intellij.psi.TokenType.WHITE_SPACE; } case 18: break; - case 7: + case 8: { return COMMA; } case 19: break; @@ -519,34 +497,33 @@ public class _JsonLexer implements FlexLexer { { return com.intellij.psi.TokenType.BAD_CHARACTER; } case 20: break; - case 6: - { return R_BRAKET; - } - case 21: break; case 11: { return TRUE; } - case 22: break; + case 21: break; case 10: { return STRING; } - case 23: break; - case 8: + case 22: break; + case 9: { return COLON; } - case 24: break; - case 9: + case 23: break; + case 3: { return NUMBER; } - case 25: break; + case 24: break; case 13: { return FALSE; } + case 25: break; + case 7: + { return R_BRACKET; + } case 26: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; - zzDoEOF(); return null; } else { diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonArray.java b/plugins/json/gen/com/jetbrains/json/psi/JsonArray.java index 33dd7c36ebba..ef4204d79d8b 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonArray.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonArray.java @@ -1,13 +1,13 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi; -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; -public interface JsonArray extends JsonPropertyValue { +import java.util.List; + +public interface JsonArray extends JsonValue { @NotNull - List getPropertyValueList(); + List getValueList(); } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java index 9fd27f7aa760..8953dfabcc56 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java @@ -1,11 +1,7 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi; -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.psi.PsiElement; - -public interface JsonLiteral extends JsonPropertyValue { +public interface JsonLiteral extends JsonValue { boolean isQuotedString(); diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java b/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java index 626e2242ed65..dbfd6e0d629a 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java @@ -1,11 +1,12 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi; -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; -public interface JsonObject extends JsonPropertyValue { +import java.util.List; + +public interface JsonObject extends JsonValue { @NotNull List getPropertyList(); diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java b/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java index 6c4cecbcb14a..508081381305 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java @@ -1,10 +1,9 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -import com.jetbrains.json.psi.impl.JsonPropertyImpl; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; public interface JsonProperty extends PsiElement { @@ -12,14 +11,11 @@ public interface JsonProperty extends PsiElement { JsonPropertyName getPropertyName(); @Nullable - JsonPropertyValue getPropertyValue(); + JsonValue getValue(); @NotNull String getName(); - @Nullable - JsonPropertyValue getValue(); - void delete(); } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyValue.java b/plugins/json/gen/com/jetbrains/json/psi/JsonValue.java similarity index 54% rename from plugins/json/gen/com/jetbrains/json/psi/JsonPropertyValue.java rename to plugins/json/gen/com/jetbrains/json/psi/JsonValue.java index 3a0a3e5081bc..5b10db9bdf64 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyValue.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonValue.java @@ -1,10 +1,8 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonPropertyValue extends PsiElement { +public interface JsonValue extends PsiElement { } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java b/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java index e03959594151..2f86ac8b4377 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java @@ -1,14 +1,14 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi; -import org.jetbrains.annotations.*; -import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import org.jetbrains.annotations.NotNull; public class JsonVisitor extends PsiElementVisitor { public void visitArray(@NotNull JsonArray o) { - visitPropertyValue(o); + visitValue(o); } public void visitBooleanLiteral(@NotNull JsonBooleanLiteral o) { @@ -16,7 +16,7 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitLiteral(@NotNull JsonLiteral o) { - visitPropertyValue(o); + visitValue(o); } public void visitNullLiteral(@NotNull JsonNullLiteral o) { @@ -28,7 +28,7 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitObject(@NotNull JsonObject o) { - visitPropertyValue(o); + visitValue(o); } public void visitProperty(@NotNull JsonProperty o) { @@ -39,14 +39,14 @@ public class JsonVisitor extends PsiElementVisitor { visitPsiElement(o); } - public void visitPropertyValue(@NotNull JsonPropertyValue o) { - visitPsiElement(o); - } - public void visitStringLiteral(@NotNull JsonStringLiteral o) { visitLiteral(o); } + public void visitValue(@NotNull JsonValue o) { + visitPsiElement(o); + } + public void visitPsiElement(@NotNull PsiElement o) { visitElement(o); } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java index e942eca1ec93..db46cea302ee 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java @@ -5,13 +5,13 @@ import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.json.psi.JsonArray; -import com.jetbrains.json.psi.JsonPropertyValue; +import com.jetbrains.json.psi.JsonValue; import com.jetbrains.json.psi.JsonVisitor; import org.jetbrains.annotations.NotNull; import java.util.List; -public class JsonArrayImpl extends JsonPropertyValueImpl implements JsonArray { +public class JsonArrayImpl extends JsonValueImpl implements JsonArray { public JsonArrayImpl(ASTNode node) { super(node); @@ -24,8 +24,8 @@ public class JsonArrayImpl extends JsonPropertyValueImpl implements JsonArray { @Override @NotNull - public List getPropertyValueList() { - return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonPropertyValue.class); + public List getValueList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonValue.class); } } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java index e2f3b4482f55..68b01387afaf 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java @@ -13,7 +13,7 @@ import org.jetbrains.annotations.Nullable; import java.util.List; -public class JsonObjectImpl extends JsonPropertyValueImpl implements JsonObject { +public class JsonObjectImpl extends JsonValueImpl implements JsonObject { public JsonObjectImpl(ASTNode node) { super(node); diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java index f5f3b3f6f9b1..39b956d4530f 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java @@ -27,8 +27,8 @@ public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProper @Override @Nullable - public JsonPropertyValue getPropertyValue() { - return findChildByClass(JsonPropertyValue.class); + public JsonValue getValue() { + return findChildByClass(JsonValue.class); } @NotNull @@ -36,11 +36,6 @@ public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProper return JsonPsiImplUtils.getName(this); } - @Nullable - public JsonPropertyValue getValue() { - return JsonPsiImplUtils.getValue(this); - } - public void delete() { JsonPsiImplUtils.delete(this); } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonValueImpl.java similarity index 69% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java rename to plugins/json/gen/com/jetbrains/json/psi/impl/JsonValueImpl.java index 6b194bb6d4d8..5f08571bcb71 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyValueImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonValueImpl.java @@ -4,18 +4,18 @@ package com.jetbrains.json.psi.impl; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.json.psi.JsonPropertyValue; +import com.jetbrains.json.psi.JsonValue; import com.jetbrains.json.psi.JsonVisitor; import org.jetbrains.annotations.NotNull; -public class JsonPropertyValueImpl extends ASTWrapperPsiElement implements JsonPropertyValue { +public class JsonValueImpl extends ASTWrapperPsiElement implements JsonValue { - public JsonPropertyValueImpl(ASTNode node) { + public JsonValueImpl(ASTNode node) { super(node); } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitPropertyValue(this); + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitValue(this); else super.accept(visitor); } diff --git a/plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java b/plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java index b5ab7544de01..29b810c4a4e1 100644 --- a/plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java +++ b/plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java @@ -12,7 +12,7 @@ import org.jetbrains.annotations.Nullable; */ public class JsonBraceMatcher implements PairedBraceMatcher { private static BracePair[] PAIRS = { - new BracePair(JsonElementTypes.L_BRAKET, JsonElementTypes.R_BRAKET, true), + new BracePair(JsonElementTypes.L_BRACKET, JsonElementTypes.R_BRACKET, true), new BracePair(JsonElementTypes.L_CURLY, JsonElementTypes.R_CURLY, true) }; diff --git a/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java b/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java index 8116a88acf05..2b73e9502697 100644 --- a/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java +++ b/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java @@ -3,7 +3,6 @@ package com.jetbrains.json; import com.intellij.lang.ASTNode; import com.intellij.lang.ParserDefinition; import com.intellij.lang.PsiParser; -import com.intellij.lexer.FlexAdapter; import com.intellij.lexer.Lexer; import com.intellij.openapi.project.Project; import com.intellij.psi.FileViewProvider; @@ -24,7 +23,7 @@ public class JsonParserDefinition implements ParserDefinition { @NotNull @Override public Lexer createLexer(Project project) { - return new FlexAdapter(new _JsonLexer()); + return new JsonLexer(); } @Override diff --git a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java index 89b3a30645ff..98dae50647d7 100644 --- a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java +++ b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java @@ -1,14 +1,15 @@ package com.jetbrains.json; -import com.intellij.lexer.FlexAdapter; import com.intellij.lexer.Lexer; import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; +import com.intellij.openapi.editor.HighlighterColors; import com.intellij.openapi.editor.colors.TextAttributesKey; import com.intellij.openapi.fileTypes.SyntaxHighlighter; import com.intellij.openapi.fileTypes.SyntaxHighlighterBase; import com.intellij.openapi.fileTypes.SyntaxHighlighterFactory; import com.intellij.openapi.project.Project; import com.intellij.openapi.vfs.VirtualFile; +import com.intellij.psi.TokenType; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,42 +17,48 @@ import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; +import static com.intellij.psi.StringEscapesTokenTypes.*; import static com.jetbrains.json.JsonElementTypes.*; public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { @NotNull @Override public SyntaxHighlighter getSyntaxHighlighter(@Nullable Project project, @Nullable VirtualFile virtualFile) { - return new Highlighter(); + return new MyHighlighter(); } - private static class Highlighter extends SyntaxHighlighterBase { - private static final Map ATTRIBUTES = new HashMap(); + private static class MyHighlighter extends SyntaxHighlighterBase { + private static final Map ourAttributes = new HashMap(); static { - ATTRIBUTES.put(L_CURLY, DefaultLanguageHighlighterColors.BRACES); - ATTRIBUTES.put(R_CURLY, DefaultLanguageHighlighterColors.BRACES ); - ATTRIBUTES.put(L_BRAKET, DefaultLanguageHighlighterColors.BRACKETS ); - ATTRIBUTES.put(R_BRAKET, DefaultLanguageHighlighterColors.BRACES ); - ATTRIBUTES.put(COMMA, DefaultLanguageHighlighterColors.COMMA); - ATTRIBUTES.put(COLON, DefaultLanguageHighlighterColors.SEMICOLON); - ATTRIBUTES.put(STRING, DefaultLanguageHighlighterColors.STRING); - ATTRIBUTES.put(NUMBER, DefaultLanguageHighlighterColors.NUMBER); - ATTRIBUTES.put(TRUE, DefaultLanguageHighlighterColors.KEYWORD); - ATTRIBUTES.put(FALSE, DefaultLanguageHighlighterColors.KEYWORD); - ATTRIBUTES.put(NULL, DefaultLanguageHighlighterColors.KEYWORD); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.BRACES, L_CURLY, R_CURLY); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.BRACKETS, L_BRACKET, R_BRACKET); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.COMMA, COMMA); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.SEMICOLON, COLON); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.STRING, STRING); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.NUMBER, NUMBER); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.KEYWORD, TRUE, FALSE, NULL); + fillMap(ourAttributes, HighlighterColors.BAD_CHARACTER, TokenType.BAD_CHARACTER); + + // StringLexer's tokens + fillMap(ourAttributes, DefaultLanguageHighlighterColors.VALID_STRING_ESCAPE, VALID_STRING_ESCAPE_TOKEN); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE, INVALID_CHARACTER_ESCAPE_TOKEN); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.INVALID_STRING_ESCAPE, INVALID_UNICODE_ESCAPE_TOKEN); } @NotNull @Override public Lexer getHighlightingLexer() { - return new FlexAdapter(new _JsonLexer()); +// LayeredLexer layeredLexer = new LayeredLexer(new JsonLexer()); +// StringLiteralLexer stringLexer = new StringLiteralLexer('\"', STRING, false, "/", false, false); +// layeredLexer.registerSelfStoppingLayer(stringLexer, new IElementType[]{STRING}, IElementType.EMPTY_ARRAY); + return new JsonLexer(); } @NotNull @Override public TextAttributesKey[] getTokenHighlights(IElementType type) { - return pack(ATTRIBUTES.get(type)); + return pack(ourAttributes.get(type)); } } } diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java b/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java index f4cf21b6afbb..172f7edba390 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java @@ -10,8 +10,9 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; +import com.jetbrains.json.JsonParserDefinition; import com.jetbrains.json.psi.JsonProperty; -import com.jetbrains.json.psi.JsonPropertyValue; +import com.jetbrains.json.psi.JsonValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -24,8 +25,8 @@ import static com.jetbrains.json.JsonParserDefinition.CONTAINERS; * @author Mikhail Golubev */ public class JsonBlock implements ASTBlock { - private static final TokenSet OPEN_BRACES = TokenSet.create(L_BRAKET, L_CURLY); - private static final TokenSet CLOSE_BRACES = TokenSet.create(R_BRAKET, R_CURLY); + private static final TokenSet OPEN_BRACES = TokenSet.create(L_BRACKET, L_CURLY); + private static final TokenSet CLOSE_BRACES = TokenSet.create(R_BRACKET, R_CURLY); private static final TokenSet BRACES = TokenSet.orSet(OPEN_BRACES, CLOSE_BRACES); private JsonBlock myParent; @@ -100,7 +101,7 @@ public class JsonBlock implements ASTBlock { alignment = myChildAlignment; indent = Indent.getNormalIndent(); } - if (myNode.getElementType() == PROPERTY && childPsiElement instanceof JsonPropertyValue) { + if (myNode.getElementType() == PROPERTY && childPsiElement instanceof JsonValue) { wrap = Wrap.createWrap(WrapType.NORMAL, true); indent = Indent.getNormalIndent(); } @@ -136,14 +137,19 @@ public class JsonBlock implements ASTBlock { public ChildAttributes getChildAttributes(int newChildIndex) { JsonBlock prevChildBlock = newChildIndex > 0 ? (JsonBlock)mySubBlocks.get(newChildIndex - 1) : null; ASTNode prevChildNode = prevChildBlock != null? prevChildBlock.myNode : null; + if (myNode.getElementType() == JsonParserDefinition.FILE) { + return new ChildAttributes(Indent.getNoneIndent(), null); + } if (isContainer() && prevChildNode != null) { // correctly indent first element after opening brace - if (OPEN_BRACES.contains(prevChildNode.getElementType())) { + if (OPEN_BRACES.contains(prevChildNode.getElementType()) || prevChildNode.getElementType() == COMMA) { return new ChildAttributes(Indent.getNormalIndent(), myChildAlignment); } - return ChildAttributes.DELEGATE_TO_PREV_CHILD; } - // TODO find out why inside object then cursor is after '"a": []', myNode is instance of JsonArray +// // TODO find out why inside object then cursor is after '"a": []', myNode is instance of JsonArray +// if (isContainer() && prevChildBlock != null) { +// return ChildAttributes.DELEGATE_TO_PREV_CHILD; +// } return new ChildAttributes(Indent.getNormalIndent(), null); } @@ -155,7 +161,7 @@ public class JsonBlock implements ASTBlock { return lastChildNode != null && lastChildNode.getElementType() == R_CURLY; } else if (nodeType == ARRAY) { - return lastChildNode != null && lastChildNode.getElementType() == R_BRAKET; + return lastChildNode != null && lastChildNode.getElementType() == R_BRACKET; } else if (myPsiElement instanceof JsonProperty) { return ((JsonProperty)myPsiElement).getValue() != null; diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java index fb9391277a38..0f6aeeefd449 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java @@ -27,7 +27,7 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { ); private static final TokenSet SIGNS = TokenSet.create( - L_BRAKET, R_BRAKET, L_CURLY, R_CURLY, COMMA, COLON + L_BRACKET, R_BRACKET, L_CURLY, R_CURLY, COMMA, COLON ); @NotNull @@ -59,12 +59,12 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { int spacesBeforeComma = commonSettings.SPACE_BEFORE_COMMA ? 1 : 0; - int spacesBeforeColon = commonSettings.SPACE_BEFORE_COLON ? 1 : 0; + int spacesBeforeColon = jsonSettings.SPACE_BEFORE_COLON ? 1 : 0; // not allow to keep line breaks before colon/comma, because it looks horrible SpacingBuilder builder = new SpacingBuilder(settings, JsonLanguage.INSTANCE) .before(COLON).spacing(spacesBeforeColon, spacesBeforeColon, 0, false, 0) .after(COLON).spaceIf(jsonSettings.SPACE_AFTER_COLON) - .withinPair(L_BRAKET, R_BRAKET).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS) + .withinPair(L_BRACKET, R_BRACKET).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS) .withinPair(L_CURLY, R_CURLY).spaceIf(jsonSettings.SPACE_WITHIN_BRACES) .before(COMMA).spacing(spacesBeforeComma, spacesBeforeComma, 0, false, 0) .after(COMMA).spaceIf(commonSettings.SPACE_AFTER_COMMA); diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java b/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java index 5145130b97a0..dc3d0f413bba 100644 --- a/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java +++ b/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java @@ -16,7 +16,7 @@ public class JsonLiteralManipulator extends AbstractElementManipulator { -{L_CURLY} { return L_CURLY; } -{R_CURLY} { return R_CURLY; } -{L_BRAKET} { return L_BRAKET; } -{R_BRAKET} { return R_BRAKET; } -{COMMA} { return COMMA; } -{COLON} { return COLON; } -{STRING} { return STRING; } -{NUMBER} { return NUMBER; } -{TRUE} { return TRUE; } -{FALSE} { return FALSE; } -{NULL} { return NULL; } - -{WHITE_SPACE}+ { return com.intellij.psi.TokenType.WHITE_SPACE; } -[^] { return com.intellij.psi.TokenType.BAD_CHARACTER; } -} From 6e0884a7786cbd0237a5b02a7030d68509e1ae55 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 21 Nov 2013 14:11:55 +0400 Subject: [PATCH 11/85] Add debug AST tree dumping in LOG --- .../json/formatter/JsonFormattingBuilderModel.java | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java index 0f6aeeefd449..acd074ab4af5 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java @@ -4,6 +4,7 @@ import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; 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.codeStyle.CodeStyleSettings; @@ -35,6 +36,7 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { if (LOG.isDebugEnabled()) { LOG.debug("PSI Tree:\n" + DebugUtil.psiToString(element, false)); + LOG.debug("AST Tree:\n" + dumpAST(element.getNode())); } JsonBlock block = new JsonBlock(null, element.getNode(), settings, null, Indent.getNoneIndent(), null); @@ -71,4 +73,16 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { return builder; } + + private static String dumpAST(ASTNode root) { + return dumpAST(root, 0); + } + + private static String dumpAST(ASTNode node, int indent) { + StringBuilder builder = new StringBuilder(StringUtil.repeat(" ", indent) + node); + for (ASTNode child : node.getChildren(null)) { + builder.append('\n').append(dumpAST(child, indent + 2)); + } + return builder.toString(); + } } From 751ac97656fa9601b21f5c485757c9f000ea43e4 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 21 Nov 2013 14:13:03 +0400 Subject: [PATCH 12/85] Correctly initialize language specific settings. Set default indentation size for JSON to 2 spaces. --- .../json/formatter/JsonLanguageCodeStyleSettingsProvider.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java b/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java index 864d80bf6c81..6cbb7803c6fe 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java @@ -66,6 +66,8 @@ public class JsonLanguageCodeStyleSettingsProvider extends LanguageCodeStyleSett @Override public CommonCodeStyleSettings getDefaultCommonSettings() { CommonCodeStyleSettings commonSettings = new CommonCodeStyleSettings(JsonLanguage.INSTANCE); + CommonCodeStyleSettings.IndentOptions indentOptions = commonSettings.initIndentOptions(); + indentOptions.INDENT_SIZE = 2; // strip all blank lines by default commonSettings.KEEP_BLANK_LINES_IN_CODE = 0; return commonSettings; From d630380bd1ac59e960eaa6e1a46eb4f93fc00cad Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 25 Nov 2013 17:35:00 +0400 Subject: [PATCH 13/85] Fix issue with highlighting by inserting special 'identifier-like' token in grammar. String literals are matched till the end of line like in other languages. --- .../com/jetbrains/json/JsonElementTypes.java | 1 + .../gen/com/jetbrains/json/JsonLexer.java | 4 +- .../gen/com/jetbrains/json/_JsonLexer.flex | 4 +- .../gen/com/jetbrains/json/_JsonLexer.java | 146 ++++++++++-------- .../json/JsonSyntaxHighlighterFactory.java | 1 + plugins/json/src/json.bnf | 8 +- 6 files changed, 95 insertions(+), 69 deletions(-) diff --git a/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java b/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java index 952f0a0b5b4a..7a1cd0676c56 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java +++ b/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java @@ -29,6 +29,7 @@ public interface JsonElementTypes { IElementType R_BRACKET = new JsonTokenType("]"); IElementType R_CURLY = new JsonTokenType("}"); IElementType STRING = new JsonTokenType("STRING"); + IElementType TEXT = new JsonTokenType("TEXT"); IElementType TRUE = new JsonTokenType("true"); class Factory { diff --git a/plugins/json/gen/com/jetbrains/json/JsonLexer.java b/plugins/json/gen/com/jetbrains/json/JsonLexer.java index 4b71bcc887bd..52197d92be2a 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonLexer.java +++ b/plugins/json/gen/com/jetbrains/json/JsonLexer.java @@ -2,13 +2,11 @@ package com.jetbrains.json; import com.intellij.lexer.FlexAdapter; -import java.io.Reader; - /** * @author Mikhail Golubev */ public class JsonLexer extends FlexAdapter { public JsonLexer() { - super(new _JsonLexer((Reader)null)); + super(new _JsonLexer()); } } diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex b/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex index 2dc24f28bc68..fe88100bd399 100644 --- a/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex +++ b/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex @@ -22,8 +22,9 @@ EOL="\r"|"\n"|"\r\n" LINE_WS=[\ \t\f] WHITE_SPACE=({LINE_WS}|{EOL})+ -STRING=\"([^\\\"]|\\([\\\"/bfnrt]|u[a-fA-F0-9]{4}))*\" +STRING=\"([^\\\"\r\n]|\\([\\\"/bfnrt]|u[a-fA-F0-9]{4}))*\"? NUMBER=-?[0-9]+(\.[0-9]+([eE][+-]?[0-9]+)?)? +TEXT=[a-zA-Z_0-9]+ %% { @@ -41,6 +42,7 @@ NUMBER=-?[0-9]+(\.[0-9]+([eE][+-]?[0-9]+)?)? {STRING} { return STRING; } {NUMBER} { return NUMBER; } + {TEXT} { return TEXT; } [^] { return com.intellij.psi.TokenType.BAD_CHARACTER; } } diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java index f6759187504d..a5134ddcdae6 100644 --- a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java +++ b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 11/20/13 2:33 PM */ +/* The following code was generated by JFlex 1.4.3 on 11/25/13 5:22 PM */ package com.jetbrains.json; @@ -11,7 +11,7 @@ import static com.jetbrains.json.JsonElementTypes.*; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 11/20/13 2:33 PM from the specification file + * on 11/25/13 5:22 PM from the specification file * /home/east825/development/repos/IDEA/community/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex */ public class _JsonLexer implements FlexLexer { @@ -35,11 +35,11 @@ public class _JsonLexer implements FlexLexer { * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = - "\11\0\1\1\1\1\1\0\1\1\1\1\22\0\1\1\1\0\1\2"+ - "\10\0\1\14\1\21\1\10\1\12\1\4\12\11\1\22\6\0\4\6"+ - "\1\13\1\6\24\0\1\17\1\3\1\20\3\0\1\27\1\7\2\6"+ - "\1\25\1\26\5\0\1\30\1\0\1\32\3\0\1\24\1\31\1\23"+ - "\1\5\5\0\1\15\1\0\1\16\uff82\0"; + "\11\0\1\2\1\1\1\0\1\2\1\1\22\0\1\2\1\0\1\3"+ + "\10\0\1\15\1\24\1\11\1\13\1\5\12\12\1\25\6\0\4\7"+ + "\1\14\1\7\24\16\1\22\1\4\1\23\1\0\1\16\1\0\1\32"+ + "\1\10\2\7\1\30\1\31\5\16\1\33\1\16\1\17\3\16\1\27"+ + "\1\34\1\26\1\6\5\16\1\20\1\0\1\21\uff82\0"; /** * Translates characters to character classes @@ -52,12 +52,13 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\1\0\1\1\1\2\2\1\1\3\1\4\1\5\1\6"+ - "\1\7\1\10\1\11\3\1\1\0\1\12\6\0\1\3"+ - "\5\0\1\13\1\0\1\14\2\0\1\3\1\15\1\0"; + "\1\0\1\1\1\2\1\3\1\4\1\1\1\5\1\4"+ + "\1\6\1\7\1\10\1\11\1\12\1\13\2\4\1\3"+ + "\1\0\1\5\1\0\3\4\1\0\1\5\3\4\2\0"+ + "\1\14\1\15\1\4\2\0\1\5\1\16\1\0"; private static int [] zzUnpackAction() { - int [] result = new int[37]; + int [] result = new int[38]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -82,14 +83,14 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\33\0\66\0\121\0\154\0\207\0\33\0\33"+ - "\0\33\0\33\0\33\0\33\0\242\0\275\0\330\0\121"+ - "\0\33\0\363\0\u010e\0\u0129\0\u0144\0\u015f\0\u017a\0\u0195"+ - "\0\u01b0\0\u01cb\0\u01e6\0\u0201\0\u021c\0\33\0\u0237\0\33"+ - "\0\u0252\0\u026d\0\u026d\0\33\0\u0288"; + "\0\0\0\35\0\72\0\127\0\164\0\221\0\256\0\313"+ + "\0\35\0\35\0\35\0\35\0\35\0\35\0\350\0\u0105"+ + "\0\35\0\u0122\0\u013f\0\u015c\0\u0179\0\u0196\0\u01b3\0\u01d0"+ + "\0\u01ed\0\u020a\0\u0227\0\u0244\0\u0261\0\u027e\0\164\0\164"+ + "\0\u029b\0\u02b8\0\u02d5\0\u02d5\0\164\0\u02f2"; private static int [] zzUnpackRowMap() { - int [] result = new int[37]; + int [] result = new int[38]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -112,23 +113,38 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = - "\1\2\1\3\1\4\5\2\1\5\1\6\3\2\1\7"+ - "\1\10\1\11\1\12\1\13\1\14\1\15\2\2\1\16"+ - "\3\2\1\17\34\0\1\3\31\0\2\20\1\21\1\22"+ - "\27\20\11\0\1\6\32\0\1\6\1\23\44\0\1\24"+ - "\35\0\1\25\10\0\1\26\27\0\3\20\1\27\1\0"+ - "\1\20\13\0\2\20\1\0\1\20\3\0\1\20\11\0"+ - "\1\30\26\0\1\31\55\0\1\32\32\0\1\33\10\0"+ - "\2\34\1\0\1\34\1\0\1\34\11\0\3\34\14\0"+ - "\1\30\1\0\1\35\11\0\1\35\32\0\1\36\36\0"+ - "\1\37\31\0\1\40\10\0\2\41\1\0\1\41\1\0"+ - "\1\41\11\0\3\41\13\0\1\42\1\43\2\0\1\42"+ - "\43\0\1\44\13\0\2\45\1\0\1\45\1\0\1\45"+ - "\11\0\3\45\14\0\1\43\27\0\2\20\1\0\1\20"+ - "\1\0\1\20\11\0\3\20\3\0"; + "\1\2\2\3\1\4\2\2\3\5\1\6\1\7\1\2"+ + "\1\5\1\2\1\5\1\10\1\11\1\12\1\13\1\14"+ + "\1\15\1\16\1\17\2\5\1\20\3\5\36\0\2\3"+ + "\32\0\1\4\1\0\1\4\1\21\1\22\30\4\6\0"+ + "\3\5\1\0\1\5\1\0\1\5\1\0\2\5\6\0"+ + "\7\5\12\0\1\23\30\0\3\5\1\0\1\7\1\24"+ + "\1\5\1\0\2\5\6\0\7\5\6\0\1\25\2\5"+ + "\1\0\1\5\1\0\1\5\1\0\2\5\6\0\7\5"+ + "\6\0\3\5\1\0\1\5\1\0\1\5\1\0\2\5"+ + "\6\0\1\5\1\26\5\5\6\0\3\5\1\0\1\5"+ + "\1\0\1\5\1\0\2\5\6\0\4\5\1\27\2\5"+ + "\3\0\3\4\1\30\1\0\1\4\6\0\1\4\6\0"+ + "\2\4\1\0\1\4\15\0\1\23\1\24\33\0\1\31"+ + "\30\0\3\5\1\0\1\5\1\0\1\5\1\0\2\5"+ + "\6\0\5\5\1\32\1\5\6\0\1\33\2\5\1\0"+ + "\1\5\1\0\1\5\1\0\2\5\6\0\7\5\6\0"+ + "\3\5\1\0\1\5\1\0\1\5\1\0\2\5\6\0"+ + "\5\5\1\34\1\5\7\0\2\35\1\0\1\35\1\0"+ + "\1\35\13\0\3\35\14\0\1\31\1\0\1\36\13\0"+ + "\1\36\12\0\3\5\1\0\1\5\1\0\1\5\1\0"+ + "\2\5\6\0\5\5\1\37\1\5\6\0\3\5\1\0"+ + "\1\5\1\0\1\5\1\0\2\5\6\0\2\5\1\40"+ + "\4\5\6\0\3\5\1\0\1\5\1\0\1\5\1\0"+ + "\2\5\6\0\6\5\1\41\7\0\2\42\1\0\1\42"+ + "\1\0\1\42\13\0\3\42\13\0\1\43\1\44\2\0"+ + "\1\43\25\0\3\5\1\0\1\5\1\0\1\5\1\0"+ + "\2\5\6\0\2\5\1\45\4\5\7\0\2\46\1\0"+ + "\1\46\1\0\1\46\13\0\3\46\14\0\1\44\31\0"+ + "\2\4\1\0\1\4\1\0\1\4\13\0\3\4\2\0"; private static int [] zzUnpackTrans() { - int [] result = new int[675]; + int [] result = new int[783]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -169,12 +185,12 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\1\0\1\11\4\1\6\11\3\1\1\0\1\11\6\0"+ - "\1\1\5\0\1\11\1\0\1\11\2\0\1\1\1\11"+ + "\1\0\1\11\6\1\6\11\2\1\1\11\1\0\1\1"+ + "\1\0\3\1\1\0\4\1\2\0\3\1\2\0\2\1"+ "\1\0"; private static int [] zzUnpackAttribute() { - int [] result = new int[37]; + int [] result = new int[38]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -259,7 +275,7 @@ public class _JsonLexer implements FlexLexer { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ - while (i < 92) { + while (i < 96) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); @@ -469,58 +485,62 @@ public class _JsonLexer implements FlexLexer { zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 5: + case 7: { return R_CURLY; } - case 14: break; - case 4: + case 15: break; + case 6: { return L_CURLY; } - case 15: break; + case 16: break; case 12: { return NULL; } - case 16: break; - case 6: + case 17: break; + case 8: { return L_BRACKET; } - case 17: break; - case 2: - { return com.intellij.psi.TokenType.WHITE_SPACE; - } case 18: break; - case 8: + case 10: { return COMMA; } case 19: break; + case 2: + { return com.intellij.psi.TokenType.WHITE_SPACE; + } + case 20: break; + case 4: + { return TEXT; + } + case 21: break; case 1: { return com.intellij.psi.TokenType.BAD_CHARACTER; } - case 20: break; - case 11: + case 22: break; + case 13: { return TRUE; } - case 21: break; - case 10: - { return STRING; - } - case 22: break; - case 9: + case 23: break; + case 11: { return COLON; } - case 23: break; - case 3: - { return NUMBER; - } case 24: break; - case 13: - { return FALSE; + case 3: + { return STRING; } case 25: break; - case 7: - { return R_BRACKET; + case 5: + { return NUMBER; } case 26: break; + case 14: + { return FALSE; + } + case 27: break; + case 9: + { return R_BRACKET; + } + case 28: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; diff --git a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java index 98dae50647d7..533891aacfb6 100644 --- a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java +++ b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java @@ -38,6 +38,7 @@ public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { fillMap(ourAttributes, DefaultLanguageHighlighterColors.STRING, STRING); fillMap(ourAttributes, DefaultLanguageHighlighterColors.NUMBER, NUMBER); fillMap(ourAttributes, DefaultLanguageHighlighterColors.KEYWORD, TRUE, FALSE, NULL); + fillMap(ourAttributes, HighlighterColors.TEXT, TEXT); fillMap(ourAttributes, HighlighterColors.BAD_CHARACTER, TokenType.BAD_CHARACTER); // StringLexer's tokens diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index 056bca54ed45..6fd19df967f4 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -19,13 +19,17 @@ COMMA=',' COLON=':' -// COMMENT='regexp:"//.*|/\*.*?\*/"' + // COMMENT='regexp:"//.*|/\*.*?\*/"' // else /\*(?:[^*]|\*[^/])*\*/ - STRING='regexp:"([^\\"]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"' + // unclosed string literal matches till the line's end + STRING='regexp:"([^\\"\r\n]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"?' NUMBER='regexp:-?\d+(\.\d+([eE][+-]?\d+)?)?' TRUE='true' FALSE='false' NULL='null' + // Workaround for highlighting issue + // plays role of IDENTIFIER or NAME token in other languages + TEXT='regexp:\w+' ] extends("object|array|literal")=value From f6f259d2b44bc25d06d6ce603c0e7b4a8795cdaf Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 25 Nov 2013 17:51:56 +0400 Subject: [PATCH 14/85] Return highlighting of string literal escapes. --- plugins/json/gen/com/jetbrains/json/_JsonLexer.java | 4 ++-- .../jetbrains/json/JsonSyntaxHighlighterFactory.java | 10 ++++++---- plugins/json/src/json.bnf | 6 +++++- 3 files changed, 13 insertions(+), 7 deletions(-) diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java index a5134ddcdae6..fb11e1aeceef 100644 --- a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java +++ b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 11/25/13 5:22 PM */ +/* The following code was generated by JFlex 1.4.3 on 11/25/13 5:48 PM */ package com.jetbrains.json; @@ -11,7 +11,7 @@ import static com.jetbrains.json.JsonElementTypes.*; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 11/25/13 5:22 PM from the specification file + * on 11/25/13 5:48 PM from the specification file * /home/east825/development/repos/IDEA/community/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex */ public class _JsonLexer implements FlexLexer { diff --git a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java index 533891aacfb6..3b783f1be4fa 100644 --- a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java +++ b/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java @@ -1,6 +1,8 @@ package com.jetbrains.json; +import com.intellij.lexer.LayeredLexer; import com.intellij.lexer.Lexer; +import com.intellij.lexer.StringLiteralLexer; import com.intellij.openapi.editor.DefaultLanguageHighlighterColors; import com.intellij.openapi.editor.HighlighterColors; import com.intellij.openapi.editor.colors.TextAttributesKey; @@ -50,10 +52,10 @@ public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { @NotNull @Override public Lexer getHighlightingLexer() { -// LayeredLexer layeredLexer = new LayeredLexer(new JsonLexer()); -// StringLiteralLexer stringLexer = new StringLiteralLexer('\"', STRING, false, "/", false, false); -// layeredLexer.registerSelfStoppingLayer(stringLexer, new IElementType[]{STRING}, IElementType.EMPTY_ARRAY); - return new JsonLexer(); + LayeredLexer layeredLexer = new LayeredLexer(new JsonLexer()); + StringLiteralLexer stringLexer = new StringLiteralLexer('\"', STRING, false, "/", false, false); + layeredLexer.registerSelfStoppingLayer(stringLexer, new IElementType[]{STRING}, IElementType.EMPTY_ARRAY); + return layeredLexer; } @NotNull diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index 6fd19df967f4..38a789323995 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -20,7 +20,11 @@ COMMA=',' COLON=':' // COMMENT='regexp:"//.*|/\*.*?\*/"' - // else /\*(?:[^*]|\*[^/])*\*/ + // else /\*(?:[^*]|\*[^/])*\*+/ + + // any escape sequences included, illegal escapes are indicated by SyntaxHighlighter + // STRING='regexp:"([^\\"\r\n]|\\[^\r\n])*"?' + // unclosed string literal matches till the line's end STRING='regexp:"([^\\"\r\n]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"?' NUMBER='regexp:-?\d+(\.\d+([eE][+-]?\d+)?)?' From dd711a397947536d7a3e60a639d0a760ec560905 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 25 Nov 2013 18:50:08 +0400 Subject: [PATCH 15/85] Add breadcrumbs support in JSON plugin --- plugins/json/json.iml | 1 + plugins/json/src/META-INF/plugin.xml | 4 +- .../breadcrumbs/JsonBreadcrumbsProvider.java | 61 +++++++++++++++++++ 3 files changed, 65 insertions(+), 1 deletion(-) create mode 100644 plugins/json/src/com/jetbrains/json/breadcrumbs/JsonBreadcrumbsProvider.java diff --git a/plugins/json/json.iml b/plugins/json/json.iml index 05d4fec511cd..e493411e36bb 100644 --- a/plugins/json/json.iml +++ b/plugins/json/json.iml @@ -11,6 +11,7 @@ + diff --git a/plugins/json/src/META-INF/plugin.xml b/plugins/json/src/META-INF/plugin.xml index aecd5d5aa480..9d40116a2bfd 100644 --- a/plugins/json/src/META-INF/plugin.xml +++ b/plugins/json/src/META-INF/plugin.xml @@ -19,7 +19,7 @@ - + @@ -32,5 +32,7 @@ + + \ No newline at end of file diff --git a/plugins/json/src/com/jetbrains/json/breadcrumbs/JsonBreadcrumbsProvider.java b/plugins/json/src/com/jetbrains/json/breadcrumbs/JsonBreadcrumbsProvider.java new file mode 100644 index 000000000000..fc2f64f8065e --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/breadcrumbs/JsonBreadcrumbsProvider.java @@ -0,0 +1,61 @@ +package com.jetbrains.json.breadcrumbs; + +import com.intellij.lang.Language; +import com.intellij.psi.PsiElement; +import com.intellij.xml.breadcrumbs.BreadcrumbsInfoProvider; +import com.jetbrains.json.JsonLanguage; +import com.jetbrains.json.psi.JsonArray; +import com.jetbrains.json.psi.JsonProperty; +import com.jetbrains.json.psi.JsonValue; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.List; + +/** + * @author Mikhail Golubev + */ +public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider { + private static final Language[] LANGUAGES = new Language[]{JsonLanguage.INSTANCE}; + + @Override + public Language[] getLanguages() { + return LANGUAGES; + } + + @Override + public boolean acceptElement(@NotNull PsiElement e) { + return isProperty(e) || isArrayElement(e); + } + + @NotNull + @Override + public String getElementInfo(@NotNull PsiElement e) { + if (isProperty(e)) { + return ((JsonProperty)e).getName(); + } + else if (isArrayElement(e)) { + List elements = ((JsonArray)e.getParent()).getValueList(); + for (int i = 0; i < elements.size(); i++) { + if (e == elements.get(i)) { + return String.valueOf(i); + } + } + } + throw new AssertionError("Breadcrumbs can be taken only for JsonProperty or JsonArray's element"); + } + + @Nullable + @Override + public String getElementTooltip(@NotNull PsiElement e) { + return null; + } + + private static boolean isProperty(PsiElement element) { + return element instanceof JsonProperty; + } + + private static boolean isArrayElement(PsiElement element) { + return element instanceof JsonValue && element.getParent() instanceof JsonArray; + } +} From fbe8e1814ac3885d3ee513902e58234e364e0220 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 25 Nov 2013 20:18:51 +0400 Subject: [PATCH 16/85] Add keywords completion for JSON --- plugins/json/src/META-INF/plugin.xml | 4 ++ .../JsonCompletionContributor.java | 58 +++++++++++++++++++ 2 files changed, 62 insertions(+) create mode 100644 plugins/json/src/com/jetbrains/json/codeinsight/JsonCompletionContributor.java diff --git a/plugins/json/src/META-INF/plugin.xml b/plugins/json/src/META-INF/plugin.xml index 9d40116a2bfd..d4c33448f1c4 100644 --- a/plugins/json/src/META-INF/plugin.xml +++ b/plugins/json/src/META-INF/plugin.xml @@ -32,7 +32,11 @@ + + + + \ No newline at end of file diff --git a/plugins/json/src/com/jetbrains/json/codeinsight/JsonCompletionContributor.java b/plugins/json/src/com/jetbrains/json/codeinsight/JsonCompletionContributor.java new file mode 100644 index 000000000000..dda6ed0de184 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/codeinsight/JsonCompletionContributor.java @@ -0,0 +1,58 @@ +package com.jetbrains.json.codeinsight; + +import com.intellij.codeInsight.completion.*; +import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.patterns.PsiElementPattern; +import com.intellij.psi.PsiElement; +import com.intellij.psi.impl.DebugUtil; +import com.intellij.util.ProcessingContext; +import com.jetbrains.json.psi.JsonArray; +import com.jetbrains.json.psi.JsonProperty; +import org.jetbrains.annotations.NotNull; + +import static com.intellij.patterns.PlatformPatterns.psiElement; + +/** + * @author Mikhail Golubev + */ +public class JsonCompletionContributor extends CompletionContributor { + private static final Logger LOG = Logger.getInstance(JsonCompletionContributor.class); + private static final String COMPLETION_PLACEHOLDER = "\"" + CompletionInitializationContext.DUMMY_IDENTIFIER + "\""; + + private static final PsiElementPattern.Capture AFTER_COLON_IN_PROPERTY = psiElement() + .afterLeaf(":").withSuperParent(2, JsonProperty.class); + private static final PsiElementPattern.Capture AFTER_COMMA_OR_BRACKET_IN_ARRAY = psiElement() + .afterLeaf("[", ",").withSuperParent(2, JsonArray.class); + @Override + public void fillCompletionVariants(CompletionParameters parameters, CompletionResultSet result) { + LOG.debug(DebugUtil.psiToString(parameters.getPosition().getContainingFile(), true)); + super.fillCompletionVariants(parameters, result); + } + + + public JsonCompletionContributor() { + extend(CompletionType.BASIC, AFTER_COLON_IN_PROPERTY, MyKeywordsCompletionProvider.INSTANCE); + extend(CompletionType.BASIC, AFTER_COMMA_OR_BRACKET_IN_ARRAY, MyKeywordsCompletionProvider.INSTANCE); + } + + + @Override + public void beforeCompletion(@NotNull CompletionInitializationContext context) { + context.setDummyIdentifier(COMPLETION_PLACEHOLDER); + } + + private static class MyKeywordsCompletionProvider extends CompletionProvider { + private static final MyKeywordsCompletionProvider INSTANCE = new MyKeywordsCompletionProvider(); + private static final String[] KEYWORDS = new String[]{"null", "true", "false"}; + + @Override + protected void addCompletions(@NotNull CompletionParameters parameters, + ProcessingContext context, + @NotNull CompletionResultSet result) { + for (String keyword : KEYWORDS) { + result.addElement(LookupElementBuilder.create(keyword).bold()); + } + } + } +} From d6d5cbb0b0d849b8b9ebf268911841d5b8a75586 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 25 Nov 2013 20:25:06 +0400 Subject: [PATCH 17/85] Update JSON formatter: remove blank lines after colon in object literal --- .../formatter/JsonFormattingBuilderModel.java | 17 ++++------------- 1 file changed, 4 insertions(+), 13 deletions(-) diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java index acd074ab4af5..75e2d6a54f88 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java @@ -10,7 +10,6 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.impl.DebugUtil; -import com.intellij.psi.tree.TokenSet; import com.jetbrains.json.JsonLanguage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,14 +22,6 @@ import static com.jetbrains.json.JsonElementTypes.*; public class JsonFormattingBuilderModel implements FormattingModelBuilder { private static final Logger LOG = Logger.getInstance(JsonFormattingBuilderModel.class); - private static final TokenSet VALUES = TokenSet.create( - OBJECT, ARRAY, STRING_LITERAL, NUMBER_LITERAL, BOOLEAN_LITERAL, NULL - ); - - private static final TokenSet SIGNS = TokenSet.create( - L_BRACKET, R_BRACKET, L_CURLY, R_CURLY, COMMA, COLON - ); - @NotNull @Override public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { @@ -62,16 +53,16 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { int spacesBeforeComma = commonSettings.SPACE_BEFORE_COMMA ? 1 : 0; int spacesBeforeColon = jsonSettings.SPACE_BEFORE_COLON ? 1 : 0; + int spacesAfterColon = jsonSettings.SPACE_AFTER_COLON ? 1 : 0; // not allow to keep line breaks before colon/comma, because it looks horrible - SpacingBuilder builder = new SpacingBuilder(settings, JsonLanguage.INSTANCE) + + return new SpacingBuilder(settings, JsonLanguage.INSTANCE) .before(COLON).spacing(spacesBeforeColon, spacesBeforeColon, 0, false, 0) - .after(COLON).spaceIf(jsonSettings.SPACE_AFTER_COLON) + .after(COLON).spacing(spacesAfterColon, spacesAfterColon, 0, false, 0) .withinPair(L_BRACKET, R_BRACKET).spaceIf(commonSettings.SPACE_WITHIN_BRACKETS) .withinPair(L_CURLY, R_CURLY).spaceIf(jsonSettings.SPACE_WITHIN_BRACES) .before(COMMA).spacing(spacesBeforeComma, spacesBeforeComma, 0, false, 0) .after(COMMA).spaceIf(commonSettings.SPACE_AFTER_COMMA); - - return builder; } private static String dumpAST(ASTNode root) { From f9fa60d3937f1e6235a91d70068adab2f3acd478 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 26 Nov 2013 16:24:31 +0400 Subject: [PATCH 18/85] Add automatic closing quote insertion and missing quote check for string literals in JSON --- plugins/json/src/META-INF/plugin.xml | 3 +- .../com/jetbrains/json/JsonQuoteHandler.java | 12 +++++++ .../JsonStringLiteralAnnotator.java | 31 +++++++++++++++++++ 3 files changed, 45 insertions(+), 1 deletion(-) create mode 100644 plugins/json/src/com/jetbrains/json/JsonQuoteHandler.java create mode 100644 plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java diff --git a/plugins/json/src/META-INF/plugin.xml b/plugins/json/src/META-INF/plugin.xml index d4c33448f1c4..5a977832e02f 100644 --- a/plugins/json/src/META-INF/plugin.xml +++ b/plugins/json/src/META-INF/plugin.xml @@ -32,11 +32,12 @@ + - + \ No newline at end of file diff --git a/plugins/json/src/com/jetbrains/json/JsonQuoteHandler.java b/plugins/json/src/com/jetbrains/json/JsonQuoteHandler.java new file mode 100644 index 000000000000..5eeebd34eef0 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/JsonQuoteHandler.java @@ -0,0 +1,12 @@ +package com.jetbrains.json; + +import com.intellij.codeInsight.editorActions.SimpleTokenSetQuoteHandler; + +/** + * @author Mikhail Golubev + */ +public class JsonQuoteHandler extends SimpleTokenSetQuoteHandler { + public JsonQuoteHandler() { + super(JsonParserDefinition.STRING_LITERALS); + } +} diff --git a/plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java b/plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java new file mode 100644 index 000000000000..1cad8bf68c79 --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java @@ -0,0 +1,31 @@ +package com.jetbrains.json.codeinsight; + +import com.intellij.lang.annotation.AnnotationHolder; +import com.intellij.lang.annotation.Annotator; +import com.intellij.psi.PsiElement; +import com.jetbrains.json.psi.JsonStringLiteral; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class JsonStringLiteralAnnotator implements Annotator { + @Override + public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { + if (element instanceof JsonStringLiteral) { + String text = element.getText(); + int length = text.length(); + if (length <= 1 || text.charAt(length - 1) != '\"' || quoteEscaped(text, length - 1)) { + holder.createErrorAnnotation(element.getTextRange(), "Missing closing quote"); + } + } + } + + private static boolean quoteEscaped(String text, int quotePos) { + int count = 0; + for (int i = quotePos - 1; i >= 0 && text.charAt(i) == '\\'; i--) { + count++; + } + return count % 2 != 0; + } +} From b6fdfcfd01d7779b7d035fc2cd40b78d9993488d Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 27 Nov 2013 15:22:38 +0400 Subject: [PATCH 19/85] Update StringLiteralAnnotator to report illegal escape sequences as well --- .../gen/com/jetbrains/json/_JsonLexer.flex | 2 +- .../gen/com/jetbrains/json/_JsonLexer.java | 104 ++++++++---------- .../JsonStringLiteralAnnotator.java | 54 ++++++++- plugins/json/src/json.bnf | 9 +- 4 files changed, 107 insertions(+), 62 deletions(-) diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex b/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex index fe88100bd399..1282e02ba639 100644 --- a/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex +++ b/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex @@ -22,7 +22,7 @@ EOL="\r"|"\n"|"\r\n" LINE_WS=[\ \t\f] WHITE_SPACE=({LINE_WS}|{EOL})+ -STRING=\"([^\\\"\r\n]|\\([\\\"/bfnrt]|u[a-fA-F0-9]{4}))*\"? +STRING=\"([^\\\"\r\n]|\\[^\r\n])*\"? NUMBER=-?[0-9]+(\.[0-9]+([eE][+-]?[0-9]+)?)? TEXT=[a-zA-Z_0-9]+ diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java index fb11e1aeceef..550cfe742c17 100644 --- a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java +++ b/plugins/json/gen/com/jetbrains/json/_JsonLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 11/25/13 5:48 PM */ +/* The following code was generated by JFlex 1.4.3 on 11/27/13 3:16 PM */ package com.jetbrains.json; @@ -11,7 +11,7 @@ import static com.jetbrains.json.JsonElementTypes.*; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 11/25/13 5:48 PM from the specification file + * on 11/27/13 3:16 PM from the specification file * /home/east825/development/repos/IDEA/community/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex */ public class _JsonLexer implements FlexLexer { @@ -36,10 +36,10 @@ public class _JsonLexer implements FlexLexer { */ private static final String ZZ_CMAP_PACKED = "\11\0\1\2\1\1\1\0\1\2\1\1\22\0\1\2\1\0\1\3"+ - "\10\0\1\15\1\24\1\11\1\13\1\5\12\12\1\25\6\0\4\7"+ - "\1\14\1\7\24\16\1\22\1\4\1\23\1\0\1\16\1\0\1\32"+ - "\1\10\2\7\1\30\1\31\5\16\1\33\1\16\1\17\3\16\1\27"+ - "\1\34\1\26\1\6\5\16\1\20\1\0\1\21\uff82\0"; + "\10\0\1\11\1\17\1\5\1\7\1\0\12\6\1\20\6\0\4\12"+ + "\1\10\25\12\1\15\1\4\1\16\1\0\1\12\1\0\1\26\3\12"+ + "\1\24\1\25\5\12\1\27\1\12\1\31\3\12\1\22\1\30\1\21"+ + "\1\23\5\12\1\13\1\0\1\14\uff82\0"; /** * Translates characters to character classes @@ -52,13 +52,13 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\1\0\1\1\1\2\1\3\1\4\1\1\1\5\1\4"+ - "\1\6\1\7\1\10\1\11\1\12\1\13\2\4\1\3"+ - "\1\0\1\5\1\0\3\4\1\0\1\5\3\4\2\0"+ - "\1\14\1\15\1\4\2\0\1\5\1\16\1\0"; + "\1\0\1\1\1\2\1\3\1\1\1\4\1\5\1\6"+ + "\1\7\1\10\1\11\1\12\1\13\3\5\1\3\1\0"+ + "\1\4\1\0\3\5\1\4\3\5\1\0\1\14\1\5"+ + "\1\15\1\0\1\4\1\16"; private static int [] zzUnpackAction() { - int [] result = new int[38]; + int [] result = new int[34]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -83,14 +83,14 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\35\0\72\0\127\0\164\0\221\0\256\0\313"+ - "\0\35\0\35\0\35\0\35\0\35\0\35\0\350\0\u0105"+ - "\0\35\0\u0122\0\u013f\0\u015c\0\u0179\0\u0196\0\u01b3\0\u01d0"+ - "\0\u01ed\0\u020a\0\u0227\0\u0244\0\u0261\0\u027e\0\164\0\164"+ - "\0\u029b\0\u02b8\0\u02d5\0\u02d5\0\164\0\u02f2"; + "\0\0\0\32\0\64\0\116\0\150\0\202\0\234\0\32"+ + "\0\32\0\32\0\32\0\32\0\32\0\266\0\320\0\352"+ + "\0\32\0\u0104\0\u011e\0\u0138\0\u0152\0\u016c\0\u0186\0\u01a0"+ + "\0\u01ba\0\u01d4\0\u01ee\0\u0208\0\234\0\u0222\0\234\0\u023c"+ + "\0\u023c\0\234"; private static int [] zzUnpackRowMap() { - int [] result = new int[38]; + int [] result = new int[34]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -113,38 +113,31 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = - "\1\2\2\3\1\4\2\2\3\5\1\6\1\7\1\2"+ - "\1\5\1\2\1\5\1\10\1\11\1\12\1\13\1\14"+ - "\1\15\1\16\1\17\2\5\1\20\3\5\36\0\2\3"+ - "\32\0\1\4\1\0\1\4\1\21\1\22\30\4\6\0"+ - "\3\5\1\0\1\5\1\0\1\5\1\0\2\5\6\0"+ - "\7\5\12\0\1\23\30\0\3\5\1\0\1\7\1\24"+ - "\1\5\1\0\2\5\6\0\7\5\6\0\1\25\2\5"+ - "\1\0\1\5\1\0\1\5\1\0\2\5\6\0\7\5"+ - "\6\0\3\5\1\0\1\5\1\0\1\5\1\0\2\5"+ - "\6\0\1\5\1\26\5\5\6\0\3\5\1\0\1\5"+ - "\1\0\1\5\1\0\2\5\6\0\4\5\1\27\2\5"+ - "\3\0\3\4\1\30\1\0\1\4\6\0\1\4\6\0"+ - "\2\4\1\0\1\4\15\0\1\23\1\24\33\0\1\31"+ - "\30\0\3\5\1\0\1\5\1\0\1\5\1\0\2\5"+ - "\6\0\5\5\1\32\1\5\6\0\1\33\2\5\1\0"+ - "\1\5\1\0\1\5\1\0\2\5\6\0\7\5\6\0"+ - "\3\5\1\0\1\5\1\0\1\5\1\0\2\5\6\0"+ - "\5\5\1\34\1\5\7\0\2\35\1\0\1\35\1\0"+ - "\1\35\13\0\3\35\14\0\1\31\1\0\1\36\13\0"+ - "\1\36\12\0\3\5\1\0\1\5\1\0\1\5\1\0"+ - "\2\5\6\0\5\5\1\37\1\5\6\0\3\5\1\0"+ - "\1\5\1\0\1\5\1\0\2\5\6\0\2\5\1\40"+ - "\4\5\6\0\3\5\1\0\1\5\1\0\1\5\1\0"+ - "\2\5\6\0\6\5\1\41\7\0\2\42\1\0\1\42"+ - "\1\0\1\42\13\0\3\42\13\0\1\43\1\44\2\0"+ - "\1\43\25\0\3\5\1\0\1\5\1\0\1\5\1\0"+ - "\2\5\6\0\2\5\1\45\4\5\7\0\2\46\1\0"+ - "\1\46\1\0\1\46\13\0\3\46\14\0\1\44\31\0"+ - "\2\4\1\0\1\4\1\0\1\4\13\0\3\4\2\0"; + "\1\2\2\3\1\4\1\2\1\5\1\6\1\2\1\7"+ + "\1\2\1\7\1\10\1\11\1\12\1\13\1\14\1\15"+ + "\1\16\3\7\1\17\3\7\1\20\33\0\2\3\27\0"+ + "\1\4\1\0\1\4\1\21\1\22\25\4\6\0\1\23"+ + "\31\0\1\6\1\24\1\7\1\0\1\7\6\0\11\7"+ + "\6\0\1\7\1\0\1\7\1\0\1\7\6\0\11\7"+ + "\6\0\1\7\1\0\1\7\1\0\1\7\6\0\1\7"+ + "\1\25\7\7\6\0\1\7\1\0\1\7\1\0\1\7"+ + "\6\0\5\7\1\26\3\7\6\0\1\7\1\0\1\7"+ + "\1\0\1\7\6\0\2\7\1\27\6\7\1\4\1\0"+ + "\30\4\6\0\1\23\1\24\30\0\1\30\31\0\1\7"+ + "\1\0\1\7\1\0\1\7\6\0\2\7\1\31\6\7"+ + "\6\0\1\7\1\0\1\7\1\0\1\7\6\0\6\7"+ + "\1\32\2\7\6\0\1\7\1\0\1\7\1\0\1\7"+ + "\6\0\6\7\1\33\2\7\6\0\1\30\1\0\1\34"+ + "\13\0\1\34\13\0\1\7\1\0\1\7\1\0\1\7"+ + "\6\0\3\7\1\35\5\7\6\0\1\7\1\0\1\7"+ + "\1\0\1\7\6\0\7\7\1\36\1\7\6\0\1\7"+ + "\1\0\1\7\1\0\1\7\6\0\6\7\1\37\2\7"+ + "\5\0\1\40\1\41\2\0\1\40\26\0\1\7\1\0"+ + "\1\7\1\0\1\7\6\0\3\7\1\42\5\7\6\0"+ + "\1\41\23\0"; private static int [] zzUnpackTrans() { - int [] result = new int[783]; + int [] result = new int[598]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -185,12 +178,11 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\1\0\1\11\6\1\6\11\2\1\1\11\1\0\1\1"+ - "\1\0\3\1\1\0\4\1\2\0\3\1\2\0\2\1"+ - "\1\0"; + "\1\0\1\11\5\1\6\11\3\1\1\11\1\0\1\1"+ + "\1\0\7\1\1\0\3\1\1\0\2\1"; private static int [] zzUnpackAttribute() { - int [] result = new int[38]; + int [] result = new int[34]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -275,7 +267,7 @@ public class _JsonLexer implements FlexLexer { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ - while (i < 96) { + while (i < 92) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); @@ -493,7 +485,7 @@ public class _JsonLexer implements FlexLexer { { return L_CURLY; } case 16: break; - case 12: + case 13: { return NULL; } case 17: break; @@ -509,7 +501,7 @@ public class _JsonLexer implements FlexLexer { { return com.intellij.psi.TokenType.WHITE_SPACE; } case 20: break; - case 4: + case 5: { return TEXT; } case 21: break; @@ -517,7 +509,7 @@ public class _JsonLexer implements FlexLexer { { return com.intellij.psi.TokenType.BAD_CHARACTER; } case 22: break; - case 13: + case 12: { return TRUE; } case 23: break; @@ -529,7 +521,7 @@ public class _JsonLexer implements FlexLexer { { return STRING; } case 25: break; - case 5: + case 4: { return NUMBER; } case 26: break; diff --git a/plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java b/plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java index 1cad8bf68c79..cac306d83dab 100644 --- a/plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java +++ b/plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java @@ -2,21 +2,73 @@ package com.jetbrains.json.codeinsight; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; +import com.intellij.openapi.util.TextRange; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.jetbrains.json.psi.JsonStringLiteral; +import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; /** * @author Mikhail Golubev */ public class JsonStringLiteralAnnotator implements Annotator { + + @NonNls public static final String MISSING_CLOSING_QUOTE = "Missing closing quote"; + @NonNls public static final String ILLEGAL_ESCAPE_SEQUENCE = "Illegal escape sequence"; + @NonNls public static final String ILLEGAL_UNICODE_ESCAPE_SEQUENCE = "Illegal unicode escape sequence"; + @Override public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { if (element instanceof JsonStringLiteral) { String text = element.getText(); + int offset = element.getTextOffset(); int length = text.length(); + // Check that string literal closed properly if (length <= 1 || text.charAt(length - 1) != '\"' || quoteEscaped(text, length - 1)) { - holder.createErrorAnnotation(element.getTextRange(), "Missing closing quote"); + holder.createErrorAnnotation(element.getTextRange(), MISSING_CLOSING_QUOTE); + } + // Check escape sequences validity + int pos = 1; + while (pos < length) { + if (text.charAt(pos) == '\\') { + if (pos >= length - 1) { + TextRange range = new TextRange(offset + pos, offset + pos + 1); + holder.createErrorAnnotation(range, ILLEGAL_ESCAPE_SEQUENCE); + break; + } + char next = text.charAt(pos + 1); + switch (next) { + case '"': + case '\\': + case '/': + case 'b': + case 'f': + case 'n': + case 'r': + case 't': + pos += 2; + break; + case 'u': + int i = pos + 2; + for (; i < pos + 6; i++) { + if (i == length || !StringUtil.isHexDigit(text.charAt(i))) { + TextRange range = new TextRange(offset + pos, offset + i); + holder.createErrorAnnotation(range, ILLEGAL_UNICODE_ESCAPE_SEQUENCE); + break; + } + } + pos = i; + break; + default: + TextRange range = new TextRange(offset + pos, offset + pos + 2); + holder.createErrorAnnotation(range, ILLEGAL_ESCAPE_SEQUENCE); + pos += 2; + } + } + else { + pos++; + } } } } diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index 38a789323995..94f87fa4faca 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -22,11 +22,12 @@ // COMMENT='regexp:"//.*|/\*.*?\*/"' // else /\*(?:[^*]|\*[^/])*\*+/ - // any escape sequences included, illegal escapes are indicated by SyntaxHighlighter - // STRING='regexp:"([^\\"\r\n]|\\[^\r\n])*"?' - // unclosed string literal matches till the line's end - STRING='regexp:"([^\\"\r\n]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"?' + // any escape sequences included, illegal escapes are indicated by SyntaxHighlighter + // and JsonStringLiteralAnnotator + STRING='regexp:"([^\\"\r\n]|\\[^\r\n])*"?' +// STRING='regexp:"([^\\"\r\n]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"?' + NUMBER='regexp:-?\d+(\.\d+([eE][+-]?\d+)?)?' TRUE='true' FALSE='false' From 8e1c44452f896b535cb302a4d4ca046afbe75c83 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 27 Nov 2013 17:02:47 +0400 Subject: [PATCH 20/85] Add enter handler for JSON to automatically insert new line between opening and closing braces/brackets. --- plugins/json/src/META-INF/plugin.xml | 1 + .../formatter/JsonEnterBetweenBracesHandler.java | 13 +++++++++++++ 2 files changed, 14 insertions(+) create mode 100644 plugins/json/src/com/jetbrains/json/formatter/JsonEnterBetweenBracesHandler.java diff --git a/plugins/json/src/META-INF/plugin.xml b/plugins/json/src/META-INF/plugin.xml index 5a977832e02f..30fd09dfa764 100644 --- a/plugins/json/src/META-INF/plugin.xml +++ b/plugins/json/src/META-INF/plugin.xml @@ -33,6 +33,7 @@ + diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonEnterBetweenBracesHandler.java b/plugins/json/src/com/jetbrains/json/formatter/JsonEnterBetweenBracesHandler.java new file mode 100644 index 000000000000..247a3774092d --- /dev/null +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonEnterBetweenBracesHandler.java @@ -0,0 +1,13 @@ +package com.jetbrains.json.formatter; + +import com.intellij.codeInsight.editorActions.enter.EnterBetweenBracesHandler; + +/** + * @author Mikhail Golubev + */ +public class JsonEnterBetweenBracesHandler extends EnterBetweenBracesHandler { + @Override + protected boolean isBracePair(char c1, char c2) { + return (c1 == '{' && c2 == '}') || (c1 == '[' && c2 == ']'); + } +} From 9bbe8c24034f60bcd2491c5dbb3e85e50b53957f Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 28 Nov 2013 17:10:12 +0400 Subject: [PATCH 21/85] Add test cases for parsing and completion in JSON plugin --- plugins/json-tests/json-tests.iml | 15 ++++++ .../com/intellij/json/CompletionTest.java | 52 +++++++++++++++++++ .../test/com/intellij/json/ParsingTest.java | 39 ++++++++++++++ .../completion/InsideArrayElement1.json | 1 + .../completion/InsideArrayElement2.json | 1 + .../completion/InsidePropertyKey1.json | 1 + .../completion/InsidePropertyKey2.json | 1 + .../completion/InsidePropertyValue.json | 1 + plugins/json-tests/testData/psi/Keywords.json | 1 + plugins/json-tests/testData/psi/Keywords.txt | 14 +++++ .../testData/psi/NestedArrayLiterals.json | 1 + .../testData/psi/NestedArrayLiterals.txt | 20 +++++++ .../testData/psi/NestedObjectLiterals.json | 1 + .../testData/psi/NestedObjectLiterals.txt | 33 ++++++++++++ .../testData/psi/TopLevelStringLiteral.json | 1 + .../testData/psi/TopLevelStringLiteral.txt | 4 ++ 16 files changed, 186 insertions(+) create mode 100644 plugins/json-tests/json-tests.iml create mode 100644 plugins/json-tests/test/com/intellij/json/CompletionTest.java create mode 100644 plugins/json-tests/test/com/intellij/json/ParsingTest.java create mode 100644 plugins/json-tests/testData/completion/InsideArrayElement1.json create mode 100644 plugins/json-tests/testData/completion/InsideArrayElement2.json create mode 100644 plugins/json-tests/testData/completion/InsidePropertyKey1.json create mode 100644 plugins/json-tests/testData/completion/InsidePropertyKey2.json create mode 100644 plugins/json-tests/testData/completion/InsidePropertyValue.json create mode 100644 plugins/json-tests/testData/psi/Keywords.json create mode 100644 plugins/json-tests/testData/psi/Keywords.txt create mode 100644 plugins/json-tests/testData/psi/NestedArrayLiterals.json create mode 100644 plugins/json-tests/testData/psi/NestedArrayLiterals.txt create mode 100644 plugins/json-tests/testData/psi/NestedObjectLiterals.json create mode 100644 plugins/json-tests/testData/psi/NestedObjectLiterals.txt create mode 100644 plugins/json-tests/testData/psi/TopLevelStringLiteral.json create mode 100644 plugins/json-tests/testData/psi/TopLevelStringLiteral.txt diff --git a/plugins/json-tests/json-tests.iml b/plugins/json-tests/json-tests.iml new file mode 100644 index 000000000000..b399fc32f657 --- /dev/null +++ b/plugins/json-tests/json-tests.iml @@ -0,0 +1,15 @@ + + + + + + + + + + + + + + + diff --git a/plugins/json-tests/test/com/intellij/json/CompletionTest.java b/plugins/json-tests/test/com/intellij/json/CompletionTest.java new file mode 100644 index 000000000000..fa3c0c3b6702 --- /dev/null +++ b/plugins/json-tests/test/com/intellij/json/CompletionTest.java @@ -0,0 +1,52 @@ +package com.intellij.json; + +import com.intellij.testFramework.IdeaTestCase; +import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; +import com.intellij.util.ArrayUtil; + +/** + * @author Mikhail Golubev + */ +public class CompletionTest extends CodeInsightFixtureTestCase { + private static final String[] KEYWORDS = new String[]{"true", "false", "null"}; + private static final String[] NOTHING = ArrayUtil.EMPTY_STRING_ARRAY; + + @Override + public void setUp() throws Exception { + IdeaTestCase.initPlatformPrefix(); + super.setUp(); + } + @Override + protected String getBasePath() { + return "/plugins/json-tests/testData/completion"; + } + + @Override + protected boolean isCommunity() { + return true; + } + + public void testInsideArrayElement1() throws Exception { + doTest(KEYWORDS); + } + + public void testInsideArrayElement2() throws Exception { + doTest(KEYWORDS); + } + + public void testInsidePropertyKey1() throws Exception { + doTest(NOTHING); + } + + public void testInsidePropertyKey2() throws Exception { + doTest(NOTHING); + } + + public void testInsidePropertyValue() throws Exception { + doTest(KEYWORDS); + } + + private void doTest(String... variants) { + myFixture.testCompletionVariants(getTestName(false) + ".json", variants); + } +} diff --git a/plugins/json-tests/test/com/intellij/json/ParsingTest.java b/plugins/json-tests/test/com/intellij/json/ParsingTest.java new file mode 100644 index 000000000000..5241419accc9 --- /dev/null +++ b/plugins/json-tests/test/com/intellij/json/ParsingTest.java @@ -0,0 +1,39 @@ +package com.intellij.json; + +import com.intellij.testFramework.ParsingTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import com.jetbrains.json.JsonParserDefinition; + +/** + * @author Mikhail Golubev + */ +public class ParsingTest extends ParsingTestCase { + public ParsingTest() { + super("psi", "json", new JsonParserDefinition()); + } + + public void testKeywords() throws Exception { + doTest(); + } + + public void testNestedArrayLiterals() throws Exception { + doTest(); + } + + public void testNestedObjectLiterals() throws Exception { + doTest(); + } + + public void testTopLevelStringLiteral() throws Exception { + doTest(); + } + + private void doTest() { + doTest(true); + } + + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath() + "/plugins/json-tests/testData"; + } +} diff --git a/plugins/json-tests/testData/completion/InsideArrayElement1.json b/plugins/json-tests/testData/completion/InsideArrayElement1.json new file mode 100644 index 000000000000..646916b66a4b --- /dev/null +++ b/plugins/json-tests/testData/completion/InsideArrayElement1.json @@ -0,0 +1 @@ +[] \ No newline at end of file diff --git a/plugins/json-tests/testData/completion/InsideArrayElement2.json b/plugins/json-tests/testData/completion/InsideArrayElement2.json new file mode 100644 index 000000000000..26f9f8d31c91 --- /dev/null +++ b/plugins/json-tests/testData/completion/InsideArrayElement2.json @@ -0,0 +1 @@ +[1, ] \ No newline at end of file diff --git a/plugins/json-tests/testData/completion/InsidePropertyKey1.json b/plugins/json-tests/testData/completion/InsidePropertyKey1.json new file mode 100644 index 000000000000..1c6ca653aea7 --- /dev/null +++ b/plugins/json-tests/testData/completion/InsidePropertyKey1.json @@ -0,0 +1 @@ +{: "foo"} \ No newline at end of file diff --git a/plugins/json-tests/testData/completion/InsidePropertyKey2.json b/plugins/json-tests/testData/completion/InsidePropertyKey2.json new file mode 100644 index 000000000000..2014e6d669cc --- /dev/null +++ b/plugins/json-tests/testData/completion/InsidePropertyKey2.json @@ -0,0 +1 @@ +{"foo": 42, } \ No newline at end of file diff --git a/plugins/json-tests/testData/completion/InsidePropertyValue.json b/plugins/json-tests/testData/completion/InsidePropertyValue.json new file mode 100644 index 000000000000..b18a6cc075a6 --- /dev/null +++ b/plugins/json-tests/testData/completion/InsidePropertyValue.json @@ -0,0 +1 @@ +{"foo": } \ No newline at end of file diff --git a/plugins/json-tests/testData/psi/Keywords.json b/plugins/json-tests/testData/psi/Keywords.json new file mode 100644 index 000000000000..6e6569203669 --- /dev/null +++ b/plugins/json-tests/testData/psi/Keywords.json @@ -0,0 +1 @@ +[true, false, null] \ No newline at end of file diff --git a/plugins/json-tests/testData/psi/Keywords.txt b/plugins/json-tests/testData/psi/Keywords.txt new file mode 100644 index 000000000000..3d58b73a66d0 --- /dev/null +++ b/plugins/json-tests/testData/psi/Keywords.txt @@ -0,0 +1,14 @@ +FILE + JsonArrayImpl(ARRAY) + PsiElement([)('[') + JsonBooleanLiteralImpl(BOOLEAN_LITERAL) + PsiElement(true)('true') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonBooleanLiteralImpl(BOOLEAN_LITERAL) + PsiElement(false)('false') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonNullLiteralImpl(NULL_LITERAL) + PsiElement(null)('null') + PsiElement(])(']') \ No newline at end of file diff --git a/plugins/json-tests/testData/psi/NestedArrayLiterals.json b/plugins/json-tests/testData/psi/NestedArrayLiterals.json new file mode 100644 index 000000000000..87b6305b04bb --- /dev/null +++ b/plugins/json-tests/testData/psi/NestedArrayLiterals.json @@ -0,0 +1 @@ +[1, ["foo", [null]]] \ No newline at end of file diff --git a/plugins/json-tests/testData/psi/NestedArrayLiterals.txt b/plugins/json-tests/testData/psi/NestedArrayLiterals.txt new file mode 100644 index 000000000000..ac42ee2bad2a --- /dev/null +++ b/plugins/json-tests/testData/psi/NestedArrayLiterals.txt @@ -0,0 +1,20 @@ +FILE + JsonArrayImpl(ARRAY) + PsiElement([)('[') + JsonNumberLiteralImpl(NUMBER_LITERAL) + PsiElement(NUMBER)('1') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonArrayImpl(ARRAY) + PsiElement([)('[') + JsonStringLiteralImpl(STRING_LITERAL) + PsiElement(STRING)('"foo"') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonArrayImpl(ARRAY) + PsiElement([)('[') + JsonNullLiteralImpl(NULL_LITERAL) + PsiElement(null)('null') + PsiElement(])(']') + PsiElement(])(']') + PsiElement(])(']') \ No newline at end of file diff --git a/plugins/json-tests/testData/psi/NestedObjectLiterals.json b/plugins/json-tests/testData/psi/NestedObjectLiterals.json new file mode 100644 index 000000000000..0294a5555c81 --- /dev/null +++ b/plugins/json-tests/testData/psi/NestedObjectLiterals.json @@ -0,0 +1 @@ +{ "foo": { "bar": {"baz": null} }} \ No newline at end of file diff --git a/plugins/json-tests/testData/psi/NestedObjectLiterals.txt b/plugins/json-tests/testData/psi/NestedObjectLiterals.txt new file mode 100644 index 000000000000..4706ab8230ff --- /dev/null +++ b/plugins/json-tests/testData/psi/NestedObjectLiterals.txt @@ -0,0 +1,33 @@ +FILE + JsonObjectImpl(OBJECT) + PsiElement({)('{') + PsiWhiteSpace(' ') + JsonPropertyImpl(PROPERTY) + JsonPropertyNameImpl(PROPERTY_NAME) + JsonStringLiteralImpl(STRING_LITERAL) + PsiElement(STRING)('"foo"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonObjectImpl(OBJECT) + PsiElement({)('{') + PsiWhiteSpace(' ') + JsonPropertyImpl(PROPERTY) + JsonPropertyNameImpl(PROPERTY_NAME) + JsonStringLiteralImpl(STRING_LITERAL) + PsiElement(STRING)('"bar"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonObjectImpl(OBJECT) + PsiElement({)('{') + JsonPropertyImpl(PROPERTY) + JsonPropertyNameImpl(PROPERTY_NAME) + JsonStringLiteralImpl(STRING_LITERAL) + PsiElement(STRING)('"baz"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonNullLiteralImpl(NULL_LITERAL) + PsiElement(null)('null') + PsiElement(})('}') + PsiWhiteSpace(' ') + PsiElement(})('}') + PsiElement(})('}') \ No newline at end of file diff --git a/plugins/json-tests/testData/psi/TopLevelStringLiteral.json b/plugins/json-tests/testData/psi/TopLevelStringLiteral.json new file mode 100644 index 000000000000..13fea57a234e --- /dev/null +++ b/plugins/json-tests/testData/psi/TopLevelStringLiteral.json @@ -0,0 +1 @@ +"should not be here" \ No newline at end of file diff --git a/plugins/json-tests/testData/psi/TopLevelStringLiteral.txt b/plugins/json-tests/testData/psi/TopLevelStringLiteral.txt new file mode 100644 index 000000000000..50cd54e3bed7 --- /dev/null +++ b/plugins/json-tests/testData/psi/TopLevelStringLiteral.txt @@ -0,0 +1,4 @@ +FILE + PsiElement(STRING)('"should not be here"') + PsiErrorElement:unexpected end of file + \ No newline at end of file From da374f59f1444cf3bae3b3f3a1a7fae5d62a6f6c Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 29 Nov 2013 16:07:12 +0400 Subject: [PATCH 22/85] Add test cases and data for JSON formatter --- .../com/intellij/json/JsonFormattingTest.java | 63 +++++++++++++++++++ .../formatting/BlankLinesStripping.json | 19 ++++++ .../formatting/BlankLinesStripping_after.json | 9 +++ .../ContainerElementsAlignment.json | 12 ++++ .../ContainerElementsAlignment_after.json | 12 ++++ .../testData/formatting/SpacesInsertion.json | 1 + .../formatting/SpacesInsertion_after.json | 1 + .../testData/formatting/Wrapping.json | 5 ++ .../testData/formatting/Wrapping_after.json | 8 +++ 9 files changed, 130 insertions(+) create mode 100644 plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java create mode 100644 plugins/json-tests/testData/formatting/BlankLinesStripping.json create mode 100644 plugins/json-tests/testData/formatting/BlankLinesStripping_after.json create mode 100644 plugins/json-tests/testData/formatting/ContainerElementsAlignment.json create mode 100644 plugins/json-tests/testData/formatting/ContainerElementsAlignment_after.json create mode 100644 plugins/json-tests/testData/formatting/SpacesInsertion.json create mode 100644 plugins/json-tests/testData/formatting/SpacesInsertion_after.json create mode 100644 plugins/json-tests/testData/formatting/Wrapping.json create mode 100644 plugins/json-tests/testData/formatting/Wrapping_after.json diff --git a/plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java b/plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java new file mode 100644 index 000000000000..c1651e1f7d6a --- /dev/null +++ b/plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java @@ -0,0 +1,63 @@ +package com.intellij.json; + +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.formatter.FormatterTestCase; +import com.intellij.testFramework.IdeaTestCase; +import com.intellij.testFramework.PlatformTestUtil; +import com.jetbrains.json.JsonLanguage; + +/** + * @author Mikhail Golubev + */ +public class JsonFormattingTest extends FormatterTestCase { + private static final Logger LOG = Logger.getInstance(JsonFormattingTest.class); + + @Override + protected void setUp() throws Exception { + IdeaTestCase.initPlatformPrefix(); + super.setUp(); + } + + @Override + protected String getBasePath() { + return "formatting"; + } + + // Why the heck do I specify path to testData in each kind of test differently? + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath() + "/plugins/json-tests/testData/"; + } + + @Override + protected String getFileExtension() { + return "json"; + } + + public void testContainerElementsAlignment() throws Exception { + doTest(); + } + + public void testBlankLinesStripping() throws Exception { + doTest(); + } + + public void testSpacesInsertion() throws Exception { + doTest(); + } + + public void testWrapping() throws Exception { + CodeStyleSettings settings = getSettings(); + int indentSize = settings.getCommonSettings(JsonLanguage.INSTANCE).getIndentOptions().INDENT_SIZE; +// LOG.debug("Intend size for JSON: " + indentSize); + settings.RIGHT_MARGIN = 20; + doTest(); + } + + @Override + protected String getTestName(boolean ignored) { + // always use uppercase first letter for consistency + return super.getTestName(false); + } +} diff --git a/plugins/json-tests/testData/formatting/BlankLinesStripping.json b/plugins/json-tests/testData/formatting/BlankLinesStripping.json new file mode 100644 index 000000000000..69a90e18ff9d --- /dev/null +++ b/plugins/json-tests/testData/formatting/BlankLinesStripping.json @@ -0,0 +1,19 @@ +{ + "foo": + + + [ + + 42, + + null, + + { + + + "bar": "baz" + } + + + ] +} \ No newline at end of file diff --git a/plugins/json-tests/testData/formatting/BlankLinesStripping_after.json b/plugins/json-tests/testData/formatting/BlankLinesStripping_after.json new file mode 100644 index 000000000000..9ec9afd41975 --- /dev/null +++ b/plugins/json-tests/testData/formatting/BlankLinesStripping_after.json @@ -0,0 +1,9 @@ +{ + "foo": [ + 42, + null, + { + "bar": "baz" + } + ] +} \ No newline at end of file diff --git a/plugins/json-tests/testData/formatting/ContainerElementsAlignment.json b/plugins/json-tests/testData/formatting/ContainerElementsAlignment.json new file mode 100644 index 000000000000..43c477e371e0 --- /dev/null +++ b/plugins/json-tests/testData/formatting/ContainerElementsAlignment.json @@ -0,0 +1,12 @@ +{ + "array": [ + 1, + {}, + "eggs", +null + ], + "object": { + "foo": [1, 2], +"bar": true + } +} \ No newline at end of file diff --git a/plugins/json-tests/testData/formatting/ContainerElementsAlignment_after.json b/plugins/json-tests/testData/formatting/ContainerElementsAlignment_after.json new file mode 100644 index 000000000000..1bc85add7eaa --- /dev/null +++ b/plugins/json-tests/testData/formatting/ContainerElementsAlignment_after.json @@ -0,0 +1,12 @@ +{ + "array": [ + 1, + {}, + "eggs", + null + ], + "object": { + "foo": [1, 2], + "bar": true + } +} \ No newline at end of file diff --git a/plugins/json-tests/testData/formatting/SpacesInsertion.json b/plugins/json-tests/testData/formatting/SpacesInsertion.json new file mode 100644 index 000000000000..3f77fd3e9348 --- /dev/null +++ b/plugins/json-tests/testData/formatting/SpacesInsertion.json @@ -0,0 +1 @@ +{"foo":[1,2 ,"bar"],"baz":null} \ No newline at end of file diff --git a/plugins/json-tests/testData/formatting/SpacesInsertion_after.json b/plugins/json-tests/testData/formatting/SpacesInsertion_after.json new file mode 100644 index 000000000000..f15d71731671 --- /dev/null +++ b/plugins/json-tests/testData/formatting/SpacesInsertion_after.json @@ -0,0 +1 @@ +{"foo": [1, 2, "bar"], "baz": null} \ No newline at end of file diff --git a/plugins/json-tests/testData/formatting/Wrapping.json b/plugins/json-tests/testData/formatting/Wrapping.json new file mode 100644 index 000000000000..33722e73f6a4 --- /dev/null +++ b/plugins/json-tests/testData/formatting/Wrapping.json @@ -0,0 +1,5 @@ +[ + "spam!spam!spam!spam!", "ham!ham!ham!", + 1, 2, 3, 4, 5, 6, 7, + ["this line is long too"] +] \ No newline at end of file diff --git a/plugins/json-tests/testData/formatting/Wrapping_after.json b/plugins/json-tests/testData/formatting/Wrapping_after.json new file mode 100644 index 000000000000..d0e8a0201505 --- /dev/null +++ b/plugins/json-tests/testData/formatting/Wrapping_after.json @@ -0,0 +1,8 @@ +[ + "spam!spam!spam!spam!", + "ham!ham!ham!", + 1, 2, 3, 4, 5, 6, + 7, + [ + "this line is long too"] +] \ No newline at end of file From 7f7a961db9c4e11e36d58c480c9efb1cf0f6f3bb Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 29 Nov 2013 16:08:22 +0400 Subject: [PATCH 23/85] Add 'Json' prefix to parser and completion tests for JSON. Remove redundant hand-written AST dump from its formatting model. --- ...mpletionTest.java => JsonCompletionTest.java} | 4 +++- .../{ParsingTest.java => JsonParsingTest.java} | 4 ++-- .../formatter/JsonFormattingBuilderModel.java | 16 +--------------- 3 files changed, 6 insertions(+), 18 deletions(-) rename plugins/json-tests/test/com/intellij/json/{CompletionTest.java => JsonCompletionTest.java} (94%) rename plugins/json-tests/test/com/intellij/json/{ParsingTest.java => JsonParsingTest.java} (90%) diff --git a/plugins/json-tests/test/com/intellij/json/CompletionTest.java b/plugins/json-tests/test/com/intellij/json/JsonCompletionTest.java similarity index 94% rename from plugins/json-tests/test/com/intellij/json/CompletionTest.java rename to plugins/json-tests/test/com/intellij/json/JsonCompletionTest.java index fa3c0c3b6702..94a1ab744084 100644 --- a/plugins/json-tests/test/com/intellij/json/CompletionTest.java +++ b/plugins/json-tests/test/com/intellij/json/JsonCompletionTest.java @@ -7,7 +7,7 @@ import com.intellij.util.ArrayUtil; /** * @author Mikhail Golubev */ -public class CompletionTest extends CodeInsightFixtureTestCase { +public class JsonCompletionTest extends CodeInsightFixtureTestCase { private static final String[] KEYWORDS = new String[]{"true", "false", "null"}; private static final String[] NOTHING = ArrayUtil.EMPTY_STRING_ARRAY; @@ -21,6 +21,8 @@ public class CompletionTest extends CodeInsightFixtureTestCase { return "/plugins/json-tests/testData/completion"; } + + @Override protected boolean isCommunity() { return true; diff --git a/plugins/json-tests/test/com/intellij/json/ParsingTest.java b/plugins/json-tests/test/com/intellij/json/JsonParsingTest.java similarity index 90% rename from plugins/json-tests/test/com/intellij/json/ParsingTest.java rename to plugins/json-tests/test/com/intellij/json/JsonParsingTest.java index 5241419accc9..0962b15962f3 100644 --- a/plugins/json-tests/test/com/intellij/json/ParsingTest.java +++ b/plugins/json-tests/test/com/intellij/json/JsonParsingTest.java @@ -7,8 +7,8 @@ import com.jetbrains.json.JsonParserDefinition; /** * @author Mikhail Golubev */ -public class ParsingTest extends ParsingTestCase { - public ParsingTest() { +public class JsonParsingTest extends ParsingTestCase { + public JsonParsingTest() { super("psi", "json", new JsonParserDefinition()); } diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java index 75e2d6a54f88..7f8017efea8b 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java +++ b/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java @@ -4,7 +4,6 @@ import com.intellij.formatting.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.diagnostic.Logger; 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.codeStyle.CodeStyleSettings; @@ -27,9 +26,8 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { public FormattingModel createModel(PsiElement element, CodeStyleSettings settings) { if (LOG.isDebugEnabled()) { LOG.debug("PSI Tree:\n" + DebugUtil.psiToString(element, false)); - LOG.debug("AST Tree:\n" + dumpAST(element.getNode())); } - + LOG.debug("Right margin: " + settings.RIGHT_MARGIN); JsonBlock block = new JsonBlock(null, element.getNode(), settings, null, Indent.getNoneIndent(), null); if (LOG.isDebugEnabled()) { StringBuilder builder = new StringBuilder(); @@ -64,16 +62,4 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { .before(COMMA).spacing(spacesBeforeComma, spacesBeforeComma, 0, false, 0) .after(COMMA).spaceIf(commonSettings.SPACE_AFTER_COMMA); } - - private static String dumpAST(ASTNode root) { - return dumpAST(root, 0); - } - - private static String dumpAST(ASTNode node, int indent) { - StringBuilder builder = new StringBuilder(StringUtil.repeat(" ", indent) + node); - for (ASTNode child : node.getChildren(null)) { - builder.append('\n').append(dumpAST(child, indent + 2)); - } - return builder.toString(); - } } From 70b724da540bc9b6c9d33ce5a1fea80cbef33c9c Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 29 Nov 2013 16:26:27 +0400 Subject: [PATCH 24/85] Remove redundant utility methods left from AppCode JSON support --- .../com/jetbrains/json/psi/JsonLiteral.java | 2 - .../com/jetbrains/json/psi/JsonObject.java | 4 -- .../com/jetbrains/json/psi/JsonProperty.java | 2 - .../json/psi/impl/JsonLiteralImpl.java | 7 +-- .../json/psi/impl/JsonObjectImpl.java | 7 --- .../json/psi/impl/JsonPropertyImpl.java | 4 -- .../json/psi/JsonLiteralManipulator.java | 24 -------- .../json/psi/JsonPsiChangeUtils.java | 61 ------------------- .../jetbrains/json/psi/JsonPsiImplUtils.java | 32 ---------- .../json/psi/impl/JsonLiteralMixin.java | 33 ---------- plugins/json/src/json.bnf | 13 +--- 11 files changed, 3 insertions(+), 186 deletions(-) delete mode 100644 plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java delete mode 100644 plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java delete mode 100644 plugins/json/src/com/jetbrains/json/psi/impl/JsonLiteralMixin.java diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java index 8953dfabcc56..e0eba8964f22 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java @@ -3,6 +3,4 @@ package com.jetbrains.json.psi; public interface JsonLiteral extends JsonValue { - boolean isQuotedString(); - } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java b/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java index dbfd6e0d629a..bc532ebe42cb 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java @@ -2,7 +2,6 @@ package com.jetbrains.json.psi; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -11,7 +10,4 @@ public interface JsonObject extends JsonValue { @NotNull List getPropertyList(); - @Nullable - JsonProperty findProperty(String name); - } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java b/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java index 508081381305..a17664ad1782 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java @@ -16,6 +16,4 @@ public interface JsonProperty extends PsiElement { @NotNull String getName(); - void delete(); - } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java index 7518c207427b..2e6e652b9158 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java @@ -4,11 +4,10 @@ package com.jetbrains.json.psi.impl; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElementVisitor; import com.jetbrains.json.psi.JsonLiteral; -import com.jetbrains.json.psi.JsonPsiImplUtils; import com.jetbrains.json.psi.JsonVisitor; import org.jetbrains.annotations.NotNull; -public class JsonLiteralImpl extends JsonLiteralMixin implements JsonLiteral { +public class JsonLiteralImpl extends JsonValueImpl implements JsonLiteral { public JsonLiteralImpl(ASTNode node) { super(node); @@ -19,8 +18,4 @@ public class JsonLiteralImpl extends JsonLiteralMixin implements JsonLiteral { else super.accept(visitor); } - public boolean isQuotedString() { - return JsonPsiImplUtils.isQuotedString(this); - } - } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java index 68b01387afaf..da7c1e98d639 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java @@ -6,10 +6,8 @@ import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import com.jetbrains.json.psi.JsonObject; import com.jetbrains.json.psi.JsonProperty; -import com.jetbrains.json.psi.JsonPsiImplUtils; import com.jetbrains.json.psi.JsonVisitor; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; import java.util.List; @@ -30,9 +28,4 @@ public class JsonObjectImpl extends JsonValueImpl implements JsonObject { return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonProperty.class); } - @Nullable - public JsonProperty findProperty(String name) { - return JsonPsiImplUtils.findProperty(this, name); - } - } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java index 39b956d4530f..4edba140a018 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java @@ -36,8 +36,4 @@ public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProper return JsonPsiImplUtils.getName(this); } - public void delete() { - JsonPsiImplUtils.delete(this); - } - } diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java b/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java deleted file mode 100644 index dc3d0f413bba..000000000000 --- a/plugins/json/src/com/jetbrains/json/psi/JsonLiteralManipulator.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.jetbrains.json.psi; - -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.AbstractElementManipulator; -import com.intellij.psi.PsiFile; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.IncorrectOperationException; - -public class JsonLiteralManipulator extends AbstractElementManipulator { - - @Override - public JsonLiteral handleContentChange(JsonLiteral element, TextRange range, String newContent) throws IncorrectOperationException { - String text = "{\"\":\"" + newContent + "\"}"; - - final PsiFile dummy = JsonPsiChangeUtils.createDummyFile(element, text); - JsonProperty property = PsiTreeUtil.findChildOfType(dummy, JsonProperty.class); - assert property != null; - - JsonValue value = property.getValue(); - assert value instanceof JsonLiteral; - - return (JsonLiteral)element.replace(value); - } -} diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java b/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java deleted file mode 100644 index 257a7fd6197c..000000000000 --- a/plugins/json/src/com/jetbrains/json/psi/JsonPsiChangeUtils.java +++ /dev/null @@ -1,61 +0,0 @@ -package com.jetbrains.json.psi; - -import com.intellij.lang.ASTNode; -import com.intellij.lang.Language; -import com.intellij.lang.LanguageParserDefinitions; -import com.intellij.lang.ParserDefinition; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiFileFactory; -import com.intellij.psi.TokenType; -import com.jetbrains.json.JsonElementTypes; -import com.jetbrains.json.JsonFile; -import org.jetbrains.annotations.NotNull; - -public class JsonPsiChangeUtils { - public static void removeCommaSeparatedFromList(final ASTNode myNode, final ASTNode parent) { - ASTNode from = myNode, to = myNode.getTreeNext(); - - boolean seenComma = false; - - ASTNode toCandidate = to; - while (toCandidate != null && toCandidate.getElementType() == TokenType.WHITE_SPACE) { - toCandidate = toCandidate.getTreeNext(); - } - - if (toCandidate != null && toCandidate.getElementType() == JsonElementTypes.COMMA) { - toCandidate = toCandidate.getTreeNext(); - to = toCandidate; - seenComma = true; - - if (to != null && to.getElementType() == TokenType.WHITE_SPACE) { - to = to.getTreeNext(); - } - } - - if (!seenComma) { - ASTNode treePrev = from.getTreePrev(); - - while (treePrev != null && treePrev.getElementType() == TokenType.WHITE_SPACE) { - from = treePrev; - treePrev = treePrev.getTreePrev(); - } - if (treePrev != null && treePrev.getElementType() == JsonElementTypes.COMMA) { - from = treePrev; - } - } - - parent.removeRange(from, to); - } - - @NotNull - public static PsiFile createDummyFile(JsonLiteral element, String text) { - Language language = element.getLanguage(); - ParserDefinition def = LanguageParserDefinitions.INSTANCE.forLanguage(language); - assert def != null; - Project project = element.getProject(); - final PsiFile dummyFile = PsiFileFactory.getInstance(project).createFileFromText("dummy.json", language, text, false, true); - assert dummyFile instanceof JsonFile; - return dummyFile; - } -} diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java b/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java index 1d1e4870ea44..9535f9252f0b 100644 --- a/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java +++ b/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java @@ -1,43 +1,11 @@ package com.jetbrains.json.psi; -import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.util.PsiTreeUtil; -import com.jetbrains.json.JsonElementTypes; -import com.jetbrains.json.psi.impl.JsonPropertyImpl; import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -import java.util.Collection; public class JsonPsiImplUtils { - public static boolean isQuotedString(@NotNull JsonLiteral literal) { - return literal.getNode().findChildByType(JsonElementTypes.STRING) != null; - } - @NotNull public static String getName(@NotNull JsonProperty property) { return StringUtil.unquoteString(property.getPropertyName().getText()); } - - @Nullable - public static JsonValue getValue(JsonPropertyImpl property) { - return PsiTreeUtil.getChildOfType(property, JsonValue.class); - } - - public static void delete(@NotNull JsonProperty property) { - final ASTNode myNode = property.getNode(); - JsonPsiChangeUtils.removeCommaSeparatedFromList(myNode, myNode.getTreeParent()); - } - - @Nullable - public static JsonProperty findProperty(@NotNull JsonObject object, @NotNull String name) { - Collection properties = PsiTreeUtil.findChildrenOfType(object, JsonProperty.class); - for (JsonProperty property : properties) { - if (property.getName().equals(name)) { - return property; - } - } - return null; - } } diff --git a/plugins/json/src/com/jetbrains/json/psi/impl/JsonLiteralMixin.java b/plugins/json/src/com/jetbrains/json/psi/impl/JsonLiteralMixin.java deleted file mode 100644 index 3350bf83cbf3..000000000000 --- a/plugins/json/src/com/jetbrains/json/psi/impl/JsonLiteralMixin.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.jetbrains.json.psi.impl; - -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiReference; -import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; -import com.jetbrains.json.psi.JsonLiteral; -import org.jetbrains.annotations.NotNull; - -abstract class JsonLiteralMixin extends JsonValueImpl implements JsonLiteral { - private final Object myRefLock = new Object(); - private volatile PsiReference[] myRefs; - private volatile long myModCount = -1; - - protected JsonLiteralMixin(ASTNode node) { - super(node); - } - - @NotNull - @Override - public PsiReference[] getReferences() { - final long count = getManager().getModificationTracker().getModificationCount(); - if (count != myModCount) { - synchronized (myRefLock) { - if (count != myModCount) { - myRefs = ReferenceProvidersRegistry.getReferencesFromProviders(this); - myModCount = count; - } - } - } - - return myRefs; - } -} diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index 94f87fa4faca..f81902ae3753 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -45,17 +45,11 @@ json ::= object | array object ::= L_CURLY [properties] R_CURLY { pin=1 - methods=[ - findProperty - ] } private properties ::= property (COMMA property)* { pin(".*")=1 } property ::= property_name COLON value { pin = 1 - methods=[ - getName - delete - ] + methods=[ getName ] recoverUntil = brace_or_comma } @@ -73,10 +67,7 @@ number_literal ::= NUMBER boolean_literal ::= TRUE | FALSE null_literal ::= NULL -literal ::= string_literal | number_literal | boolean_literal | null_literal { - methods=[isQuotedString] - mixin="com.jetbrains.json.psi.impl.JsonLiteralMixin" -} +literal ::= string_literal | number_literal | boolean_literal | null_literal private bracket_or_comma ::= !(R_BRACKET|COMMA) private brace_or_comma ::= !(R_CURLY|COMMA) \ No newline at end of file From 7c4cfdd02a47138cc0391b4152b9b0f5321b7548 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 14 Jul 2014 18:19:27 +0400 Subject: [PATCH 25/85] Regenerate JSON parser, fix stale testData --- .../testData/psi/TopLevelStringLiteral.txt | 5 +- .../gen/com/jetbrains/json/JsonParser.java | 52 ++++++++----------- .../jetbrains/json/psi/JsonNumberLiteral.java | 6 ++- .../jetbrains/json/psi/JsonStringLiteral.java | 6 ++- .../json/psi/impl/JsonNumberLiteralImpl.java | 9 ++++ .../json/psi/impl/JsonStringLiteralImpl.java | 9 ++++ plugins/json/src/json.bnf | 4 +- 7 files changed, 51 insertions(+), 40 deletions(-) diff --git a/plugins/json-tests/testData/psi/TopLevelStringLiteral.txt b/plugins/json-tests/testData/psi/TopLevelStringLiteral.txt index 50cd54e3bed7..6166316f83ff 100644 --- a/plugins/json-tests/testData/psi/TopLevelStringLiteral.txt +++ b/plugins/json-tests/testData/psi/TopLevelStringLiteral.txt @@ -1,4 +1,3 @@ FILE - PsiElement(STRING)('"should not be here"') - PsiErrorElement:unexpected end of file - \ No newline at end of file + PsiErrorElement:'[' or '{' expected, got '"should not be here"' + PsiElement(STRING)('"should not be here"') \ No newline at end of file diff --git a/plugins/json/gen/com/jetbrains/json/JsonParser.java b/plugins/json/gen/com/jetbrains/json/JsonParser.java index bfe11935d084..86064cbdef37 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonParser.java +++ b/plugins/json/gen/com/jetbrains/json/JsonParser.java @@ -18,44 +18,43 @@ public class JsonParser implements PsiParser { public static final Logger LOG_ = Logger.getInstance("com.jetbrains.json.JsonParser"); public ASTNode parse(IElementType root_, PsiBuilder builder_) { - int level_ = 0; boolean result_; builder_ = adapt_builder_(root_, builder_, this, EXTENDS_SETS_); + Marker marker_ = enter_section_(builder_, 0, _COLLAPSE_, null); if (root_ == ARRAY) { - result_ = array(builder_, level_ + 1); + result_ = array(builder_, 0); } else if (root_ == BOOLEAN_LITERAL) { - result_ = boolean_literal(builder_, level_ + 1); + result_ = boolean_literal(builder_, 0); } else if (root_ == LITERAL) { - result_ = literal(builder_, level_ + 1); + result_ = literal(builder_, 0); } else if (root_ == NULL_LITERAL) { - result_ = null_literal(builder_, level_ + 1); + result_ = null_literal(builder_, 0); } else if (root_ == NUMBER_LITERAL) { - result_ = number_literal(builder_, level_ + 1); + result_ = number_literal(builder_, 0); } else if (root_ == OBJECT) { - result_ = object(builder_, level_ + 1); + result_ = object(builder_, 0); } else if (root_ == PROPERTY) { - result_ = property(builder_, level_ + 1); + result_ = property(builder_, 0); } else if (root_ == PROPERTY_NAME) { - result_ = property_name(builder_, level_ + 1); + result_ = property_name(builder_, 0); } else if (root_ == STRING_LITERAL) { - result_ = string_literal(builder_, level_ + 1); + result_ = string_literal(builder_, 0); } else if (root_ == VALUE) { - result_ = value(builder_, level_ + 1); + result_ = value(builder_, 0); } else { - Marker marker_ = enter_section_(builder_, level_, _NONE_, null); - result_ = parse_root_(root_, builder_, level_); - exit_section_(builder_, level_, marker_, root_, result_, true, TOKEN_ADVANCER); + result_ = parse_root_(root_, builder_, 0); } + exit_section_(builder_, 0, marker_, root_, result_, true, TRUE_CONDITION); return builder_.getTreeBuilt(); } @@ -121,15 +120,11 @@ public class JsonParser implements PsiParser { // (COMMA array_element)* private static boolean array_elements_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_elements_1")) return false; - int offset_ = builder_.getCurrentOffset(); + int pos_ = current_position_(builder_); while (true) { if (!array_elements_1_0(builder_, level_ + 1)) break; - int next_offset_ = builder_.getCurrentOffset(); - if (offset_ == next_offset_) { - empty_element_parsed_guard_(builder_, offset_, "array_elements_1"); - break; - } - offset_ = next_offset_; + if (!empty_element_parsed_guard_(builder_, "array_elements_1", pos_)) break; + pos_ = current_position_(builder_); } return true; } @@ -151,8 +146,7 @@ public class JsonParser implements PsiParser { // TRUE | FALSE public static boolean boolean_literal(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "boolean_literal")) return false; - if (!nextTokenIs(builder_, FALSE) && !nextTokenIs(builder_, TRUE) - && replaceVariants(builder_, 2, "")) return false; + if (!nextTokenIs(builder_, "", FALSE, TRUE)) return false; boolean result_ = false; Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); result_ = consumeToken(builder_, TRUE); @@ -209,7 +203,7 @@ public class JsonParser implements PsiParser { // object | array static boolean json(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "json")) return false; - if (!nextTokenIs(builder_, L_BRACKET) && !nextTokenIs(builder_, L_CURLY)) return false; + if (!nextTokenIs(builder_, "", L_BRACKET, L_CURLY)) return false; boolean result_ = false; Marker marker_ = enter_section_(builder_); result_ = object(builder_, level_ + 1); @@ -297,15 +291,11 @@ public class JsonParser implements PsiParser { // (COMMA property)* private static boolean properties_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "properties_1")) return false; - int offset_ = builder_.getCurrentOffset(); + int pos_ = current_position_(builder_); while (true) { if (!properties_1_0(builder_, level_ + 1)) break; - int next_offset_ = builder_.getCurrentOffset(); - if (offset_ == next_offset_) { - empty_element_parsed_guard_(builder_, offset_, "properties_1"); - break; - } - offset_ = next_offset_; + if (!empty_element_parsed_guard_(builder_, "properties_1", pos_)) break; + pos_ = current_position_(builder_); } return true; } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java index 296f37567e59..5d68b5a2e95b 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java @@ -1,10 +1,12 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; public interface JsonNumberLiteral extends JsonLiteral { + @NotNull + PsiElement getNumber(); + } diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java index ade19da79d77..3e4f7ebab903 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java +++ b/plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java @@ -1,10 +1,12 @@ // This is a generated file. Not intended for manual editing. package com.jetbrains.json.psi; -import java.util.List; -import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; public interface JsonStringLiteral extends JsonLiteral { + @NotNull + PsiElement getString(); + } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java index 4d061f8d3617..c450638e2507 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java @@ -2,11 +2,14 @@ package com.jetbrains.json.psi.impl; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.jetbrains.json.psi.JsonNumberLiteral; import com.jetbrains.json.psi.JsonVisitor; import org.jetbrains.annotations.NotNull; +import static com.jetbrains.json.JsonElementTypes.NUMBER; + public class JsonNumberLiteralImpl extends JsonLiteralImpl implements JsonNumberLiteral { public JsonNumberLiteralImpl(ASTNode node) { @@ -18,4 +21,10 @@ public class JsonNumberLiteralImpl extends JsonLiteralImpl implements JsonNumber else super.accept(visitor); } + @Override + @NotNull + public PsiElement getNumber() { + return findNotNullChildByType(NUMBER); + } + } diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java index d4ab8c38b82b..8db009266899 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java +++ b/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java @@ -2,11 +2,14 @@ package com.jetbrains.json.psi.impl; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.jetbrains.json.psi.JsonStringLiteral; import com.jetbrains.json.psi.JsonVisitor; import org.jetbrains.annotations.NotNull; +import static com.jetbrains.json.JsonElementTypes.STRING; + public class JsonStringLiteralImpl extends JsonLiteralImpl implements JsonStringLiteral { public JsonStringLiteralImpl(ASTNode node) { @@ -18,4 +21,10 @@ public class JsonStringLiteralImpl extends JsonLiteralImpl implements JsonString else super.accept(visitor); } + @Override + @NotNull + public PsiElement getString() { + return findNotNullChildByType(STRING); + } + } diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index f81902ae3753..6776d9740478 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -50,13 +50,13 @@ private properties ::= property (COMMA property)* { pin(".*")=1 } property ::= property_name COLON value { pin = 1 methods=[ getName ] - recoverUntil = brace_or_comma + recoverWhile = brace_or_comma } array ::= L_BRACKET [array_elements] R_BRACKET { pin=1 } private array_elements ::= array_element (COMMA array_element)* { pin(".*")=1 } private array_element ::= value { - recoverUntil = bracket_or_comma + recoverWhile = bracket_or_comma } property_name ::= string_literal From 6399dd689087ddadef3abcfb7d36855c5096ec1b Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 15 Jul 2014 13:37:53 +0400 Subject: [PATCH 26/85] Add json and json-tests modules to community-main dependencies --- .idea/modules.xml | 5 +++-- community-main.iml | 2 ++ 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.idea/modules.xml b/.idea/modules.xml index 2275453f4929..e28445a81b67 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -107,7 +107,8 @@ - + + @@ -168,8 +169,8 @@ - + diff --git a/community-main.iml b/community-main.iml index 51f709d431a1..6d76dc43b685 100644 --- a/community-main.iml +++ b/community-main.iml @@ -105,6 +105,8 @@ + + From 17a31c49f37ff97740199024f137fbe962adc634 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 15 Jul 2014 14:12:37 +0400 Subject: [PATCH 27/85] Rename 'com.jetbrains.json' package to 'com.intellij.json' --- .../com/intellij/json/JsonFormattingTest.java | 1 - .../com/intellij/json/JsonParsingTest.java | 1 - .../json/JsonElementTypes.java | 8 +++---- .../json/JsonLexer.java | 2 +- .../json/JsonParser.java | 13 +++++----- .../json/JsonParserUtil.java | 2 +- .../json/_JsonLexer.flex | 4 ++-- .../json/_JsonLexer.java | 14 +++++------ .../json/psi/JsonArray.java | 6 ++--- .../json/psi/JsonBooleanLiteral.java | 2 +- .../com/intellij/json/psi/JsonLiteral.java | 10 ++++++++ .../json/psi/JsonNullLiteral.java | 2 +- .../json/psi/JsonNumberLiteral.java | 5 ++-- .../json/psi/JsonObject.java | 6 ++--- .../json/psi/JsonProperty.java | 6 ++--- .../json/psi/JsonPropertyName.java | 2 +- .../json/psi/JsonStringLiteral.java | 5 ++-- .../json/psi/JsonValue.java | 4 +++- .../json/psi/JsonVisitor.java | 6 ++--- .../json/psi/impl/JsonArrayImpl.java | 17 +++++++------ .../json/psi/impl/JsonBooleanLiteralImpl.java | 11 +++++---- .../json/psi/impl/JsonLiteralImpl.java | 11 +++++---- .../json/psi/impl/JsonNullLiteralImpl.java | 11 +++++---- .../json/psi/impl/JsonNumberLiteralImpl.java | 12 +++++----- .../json/psi/impl/JsonObjectImpl.java | 17 +++++++------ .../json/psi/impl/JsonPropertyImpl.java | 13 ++++++---- .../json/psi/impl/JsonPropertyNameImpl.java | 14 ++++++----- .../json/psi/impl/JsonStringLiteralImpl.java | 12 +++++----- .../json/psi/impl/JsonValueImpl.java | 13 ++++++---- .../com/jetbrains/json/psi/JsonLiteral.java | 6 ----- plugins/json/json.iml | 2 +- plugins/json/src/META-INF/plugin.xml | 24 +++++++++---------- .../json/JsonBraceMatcher.java | 2 +- .../json/JsonElementType.java | 2 +- .../json/JsonFile.java | 2 +- .../json/JsonFileType.java | 2 +- .../json/JsonFileTypeFactory.java | 2 +- .../json/JsonLanguage.java | 2 +- .../json/JsonParserDefinition.java | 2 +- .../json/JsonQuoteHandler.java | 2 +- .../json/JsonSyntaxHighlighterFactory.java | 4 ++-- .../json/JsonTokenType.java | 2 +- .../breadcrumbs/JsonBreadcrumbsProvider.java | 10 ++++---- .../JsonCompletionContributor.java | 6 ++--- .../JsonStringLiteralAnnotator.java | 4 ++-- .../json/formatter/JsonBlock.java | 13 +++++----- .../json/formatter/JsonCodeStyleSettings.java | 4 ++-- .../JsonCodeStyleSettingsProvider.java | 4 ++-- .../JsonEnterBetweenBracesHandler.java | 2 +- .../formatter/JsonFormattingBuilderModel.java | 6 ++--- ...JsonLanguageCodeStyleSettingsProvider.java | 4 ++-- .../json/psi/JsonPsiImplUtils.java | 2 +- plugins/json/src/json.bnf | 16 ++++++------- 53 files changed, 186 insertions(+), 169 deletions(-) rename plugins/json/gen/com/{jetbrains => intellij}/json/JsonElementTypes.java (97%) rename plugins/json/gen/com/{jetbrains => intellij}/json/JsonLexer.java (86%) rename plugins/json/gen/com/{jetbrains => intellij}/json/JsonParser.java (98%) rename plugins/json/gen/com/{jetbrains => intellij}/json/JsonParserUtil.java (84%) rename plugins/json/gen/com/{jetbrains => intellij}/json/_JsonLexer.flex (92%) rename plugins/json/gen/com/{jetbrains => intellij}/json/_JsonLexer.java (97%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonArray.java (63%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonBooleanLiteral.java (87%) create mode 100644 plugins/json/gen/com/intellij/json/psi/JsonLiteral.java rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonNullLiteral.java (87%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonNumberLiteral.java (68%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonObject.java (64%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonProperty.java (70%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonPropertyName.java (89%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonStringLiteral.java (68%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonValue.java (62%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/JsonVisitor.java (93%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonArrayImpl.java (76%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonBooleanLiteralImpl.java (65%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonLiteralImpl.java (64%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonNullLiteralImpl.java (65%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonNumberLiteralImpl.java (73%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonObjectImpl.java (76%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonPropertyImpl.java (76%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonPropertyNameImpl.java (72%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonStringLiteralImpl.java (73%) rename plugins/json/gen/com/{jetbrains => intellij}/json/psi/impl/JsonValueImpl.java (66%) delete mode 100644 plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java rename plugins/json/src/com/{jetbrains => intellij}/json/JsonBraceMatcher.java (96%) rename plugins/json/src/com/{jetbrains => intellij}/json/JsonElementType.java (91%) rename plugins/json/src/com/{jetbrains => intellij}/json/JsonFile.java (93%) rename plugins/json/src/com/{jetbrains => intellij}/json/JsonFileType.java (96%) rename plugins/json/src/com/{jetbrains => intellij}/json/JsonFileTypeFactory.java (93%) rename plugins/json/src/com/{jetbrains => intellij}/json/JsonLanguage.java (91%) rename plugins/json/src/com/{jetbrains => intellij}/json/JsonParserDefinition.java (98%) rename plugins/json/src/com/{jetbrains => intellij}/json/JsonQuoteHandler.java (90%) rename plugins/json/src/com/{jetbrains => intellij}/json/JsonSyntaxHighlighterFactory.java (97%) rename plugins/json/src/com/{jetbrains => intellij}/json/JsonTokenType.java (91%) rename plugins/json/src/com/{jetbrains => intellij}/json/breadcrumbs/JsonBreadcrumbsProvider.java (88%) rename plugins/json/src/com/{jetbrains => intellij}/json/codeinsight/JsonCompletionContributor.java (95%) rename plugins/json/src/com/{jetbrains => intellij}/json/codeinsight/JsonStringLiteralAnnotator.java (96%) rename plugins/json/src/com/{jetbrains => intellij}/json/formatter/JsonBlock.java (93%) rename plugins/json/src/com/{jetbrains => intellij}/json/formatter/JsonCodeStyleSettings.java (87%) rename plugins/json/src/com/{jetbrains => intellij}/json/formatter/JsonCodeStyleSettingsProvider.java (95%) rename plugins/json/src/com/{jetbrains => intellij}/json/formatter/JsonEnterBetweenBracesHandler.java (89%) rename plugins/json/src/com/{jetbrains => intellij}/json/formatter/JsonFormattingBuilderModel.java (95%) rename plugins/json/src/com/{jetbrains => intellij}/json/formatter/JsonLanguageCodeStyleSettingsProvider.java (97%) rename plugins/json/src/com/{jetbrains => intellij}/json/psi/JsonPsiImplUtils.java (89%) diff --git a/plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java b/plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java index c1651e1f7d6a..81b75709e94a 100644 --- a/plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java +++ b/plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java @@ -5,7 +5,6 @@ import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.formatter.FormatterTestCase; import com.intellij.testFramework.IdeaTestCase; import com.intellij.testFramework.PlatformTestUtil; -import com.jetbrains.json.JsonLanguage; /** * @author Mikhail Golubev diff --git a/plugins/json-tests/test/com/intellij/json/JsonParsingTest.java b/plugins/json-tests/test/com/intellij/json/JsonParsingTest.java index 0962b15962f3..b7d374bdc92f 100644 --- a/plugins/json-tests/test/com/intellij/json/JsonParsingTest.java +++ b/plugins/json-tests/test/com/intellij/json/JsonParsingTest.java @@ -2,7 +2,6 @@ package com.intellij.json; import com.intellij.testFramework.ParsingTestCase; import com.intellij.testFramework.PlatformTestUtil; -import com.jetbrains.json.JsonParserDefinition; /** * @author Mikhail Golubev diff --git a/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java b/plugins/json/gen/com/intellij/json/JsonElementTypes.java similarity index 97% rename from plugins/json/gen/com/jetbrains/json/JsonElementTypes.java rename to plugins/json/gen/com/intellij/json/JsonElementTypes.java index 7a1cd0676c56..019f10dd51ec 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonElementTypes.java +++ b/plugins/json/gen/com/intellij/json/JsonElementTypes.java @@ -1,10 +1,10 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json; +package com.intellij.json; -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; import com.intellij.psi.tree.IElementType; -import com.jetbrains.json.psi.impl.*; +import com.intellij.psi.PsiElement; +import com.intellij.lang.ASTNode; +import com.intellij.json.psi.impl.*; public interface JsonElementTypes { diff --git a/plugins/json/gen/com/jetbrains/json/JsonLexer.java b/plugins/json/gen/com/intellij/json/JsonLexer.java similarity index 86% rename from plugins/json/gen/com/jetbrains/json/JsonLexer.java rename to plugins/json/gen/com/intellij/json/JsonLexer.java index 52197d92be2a..ce771b9d23b5 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonLexer.java +++ b/plugins/json/gen/com/intellij/json/JsonLexer.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.lexer.FlexAdapter; diff --git a/plugins/json/gen/com/jetbrains/json/JsonParser.java b/plugins/json/gen/com/intellij/json/JsonParser.java similarity index 98% rename from plugins/json/gen/com/jetbrains/json/JsonParser.java rename to plugins/json/gen/com/intellij/json/JsonParser.java index 86064cbdef37..c85f7321d2e7 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonParser.java +++ b/plugins/json/gen/com/intellij/json/JsonParser.java @@ -1,21 +1,20 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json; +package com.intellij.json; -import com.intellij.lang.ASTNode; import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiBuilder.Marker; -import com.intellij.lang.PsiParser; import com.intellij.openapi.diagnostic.Logger; +import static com.intellij.json.JsonElementTypes.*; +import static com.intellij.json.JsonParserUtil.*; import com.intellij.psi.tree.IElementType; +import com.intellij.lang.ASTNode; import com.intellij.psi.tree.TokenSet; - -import static com.jetbrains.json.JsonElementTypes.*; -import static com.jetbrains.json.JsonParserUtil.*; +import com.intellij.lang.PsiParser; @SuppressWarnings({"SimplifiableIfStatement", "UnusedAssignment"}) public class JsonParser implements PsiParser { - public static final Logger LOG_ = Logger.getInstance("com.jetbrains.json.JsonParser"); + public static final Logger LOG_ = Logger.getInstance("com.intellij.json.JsonParser"); public ASTNode parse(IElementType root_, PsiBuilder builder_) { boolean result_; diff --git a/plugins/json/gen/com/jetbrains/json/JsonParserUtil.java b/plugins/json/gen/com/intellij/json/JsonParserUtil.java similarity index 84% rename from plugins/json/gen/com/jetbrains/json/JsonParserUtil.java rename to plugins/json/gen/com/intellij/json/JsonParserUtil.java index dd82e3a43f36..a2e6ef5aad93 100644 --- a/plugins/json/gen/com/jetbrains/json/JsonParserUtil.java +++ b/plugins/json/gen/com/intellij/json/JsonParserUtil.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.lang.parser.GeneratedParserUtilBase; diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex b/plugins/json/gen/com/intellij/json/_JsonLexer.flex similarity index 92% rename from plugins/json/gen/com/jetbrains/json/_JsonLexer.flex rename to plugins/json/gen/com/intellij/json/_JsonLexer.flex index 1282e02ba639..0083719fb629 100644 --- a/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex +++ b/plugins/json/gen/com/intellij/json/_JsonLexer.flex @@ -1,7 +1,7 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.lexer.*; import com.intellij.psi.tree.IElementType; -import static com.jetbrains.json.JsonElementTypes.*; +import static com.intellij.json.JsonElementTypes.*; %% diff --git a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java b/plugins/json/gen/com/intellij/json/_JsonLexer.java similarity index 97% rename from plugins/json/gen/com/jetbrains/json/_JsonLexer.java rename to plugins/json/gen/com/intellij/json/_JsonLexer.java index 550cfe742c17..1cf42f524aa8 100644 --- a/plugins/json/gen/com/jetbrains/json/_JsonLexer.java +++ b/plugins/json/gen/com/intellij/json/_JsonLexer.java @@ -1,18 +1,16 @@ -/* The following code was generated by JFlex 1.4.3 on 11/27/13 3:16 PM */ +/* The following code was generated by JFlex 1.4.3 on 7/15/14 2:07 PM */ -package com.jetbrains.json; - -import com.intellij.lexer.FlexLexer; +package com.intellij.json; +import com.intellij.lexer.*; import com.intellij.psi.tree.IElementType; - -import static com.jetbrains.json.JsonElementTypes.*; +import static com.intellij.json.JsonElementTypes.*; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 11/27/13 3:16 PM from the specification file - * /home/east825/development/repos/IDEA/community/plugins/json/gen/com/jetbrains/json/_JsonLexer.flex + * on 7/15/14 2:07 PM from the specification file + * /home/east825/develop/repos/IDEA-branch/community/plugins/json/gen/com/intellij/json/_JsonLexer.flex */ public class _JsonLexer implements FlexLexer { /** initial size of the lookahead buffer */ diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonArray.java b/plugins/json/gen/com/intellij/json/psi/JsonArray.java similarity index 63% rename from plugins/json/gen/com/jetbrains/json/psi/JsonArray.java rename to plugins/json/gen/com/intellij/json/psi/JsonArray.java index ef4204d79d8b..a46a8b8ff047 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonArray.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonArray.java @@ -1,9 +1,9 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; - -import org.jetbrains.annotations.NotNull; +package com.intellij.json.psi; import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; public interface JsonArray extends JsonValue { diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonBooleanLiteral.java b/plugins/json/gen/com/intellij/json/psi/JsonBooleanLiteral.java similarity index 87% rename from plugins/json/gen/com/jetbrains/json/psi/JsonBooleanLiteral.java rename to plugins/json/gen/com/intellij/json/psi/JsonBooleanLiteral.java index c7eccd0d603d..684d79897ff7 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonBooleanLiteral.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonBooleanLiteral.java @@ -1,5 +1,5 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; +package com.intellij.json.psi; import java.util.List; import org.jetbrains.annotations.*; diff --git a/plugins/json/gen/com/intellij/json/psi/JsonLiteral.java b/plugins/json/gen/com/intellij/json/psi/JsonLiteral.java new file mode 100644 index 000000000000..b11833e7d7c0 --- /dev/null +++ b/plugins/json/gen/com/intellij/json/psi/JsonLiteral.java @@ -0,0 +1,10 @@ +// This is a generated file. Not intended for manual editing. +package com.intellij.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonLiteral extends JsonValue { + +} diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonNullLiteral.java b/plugins/json/gen/com/intellij/json/psi/JsonNullLiteral.java similarity index 87% rename from plugins/json/gen/com/jetbrains/json/psi/JsonNullLiteral.java rename to plugins/json/gen/com/intellij/json/psi/JsonNullLiteral.java index d42112dd08af..a57448e643f6 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonNullLiteral.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonNullLiteral.java @@ -1,5 +1,5 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; +package com.intellij.json.psi; import java.util.List; import org.jetbrains.annotations.*; diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java b/plugins/json/gen/com/intellij/json/psi/JsonNumberLiteral.java similarity index 68% rename from plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java rename to plugins/json/gen/com/intellij/json/psi/JsonNumberLiteral.java index 5d68b5a2e95b..c189357829ef 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonNumberLiteral.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonNumberLiteral.java @@ -1,8 +1,9 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; +package com.intellij.json.psi; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; public interface JsonNumberLiteral extends JsonLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java b/plugins/json/gen/com/intellij/json/psi/JsonObject.java similarity index 64% rename from plugins/json/gen/com/jetbrains/json/psi/JsonObject.java rename to plugins/json/gen/com/intellij/json/psi/JsonObject.java index bc532ebe42cb..308b0a6c9c7e 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonObject.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonObject.java @@ -1,9 +1,9 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; - -import org.jetbrains.annotations.NotNull; +package com.intellij.json.psi; import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; public interface JsonObject extends JsonValue { diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java b/plugins/json/gen/com/intellij/json/psi/JsonProperty.java similarity index 70% rename from plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java rename to plugins/json/gen/com/intellij/json/psi/JsonProperty.java index a17664ad1782..a62e40046445 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonProperty.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonProperty.java @@ -1,9 +1,9 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; +package com.intellij.json.psi; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; public interface JsonProperty extends PsiElement { diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java b/plugins/json/gen/com/intellij/json/psi/JsonPropertyName.java similarity index 89% rename from plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java rename to plugins/json/gen/com/intellij/json/psi/JsonPropertyName.java index 3c7a9fc2b1cc..986dfc47e55f 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonPropertyName.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonPropertyName.java @@ -1,5 +1,5 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; +package com.intellij.json.psi; import java.util.List; import org.jetbrains.annotations.*; diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java b/plugins/json/gen/com/intellij/json/psi/JsonStringLiteral.java similarity index 68% rename from plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java rename to plugins/json/gen/com/intellij/json/psi/JsonStringLiteral.java index 3e4f7ebab903..b1bc0e89096b 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonStringLiteral.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonStringLiteral.java @@ -1,8 +1,9 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; +package com.intellij.json.psi; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -import org.jetbrains.annotations.NotNull; public interface JsonStringLiteral extends JsonLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonValue.java b/plugins/json/gen/com/intellij/json/psi/JsonValue.java similarity index 62% rename from plugins/json/gen/com/jetbrains/json/psi/JsonValue.java rename to plugins/json/gen/com/intellij/json/psi/JsonValue.java index 5b10db9bdf64..46995ec879b3 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonValue.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonValue.java @@ -1,6 +1,8 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; +package com.intellij.json.psi; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; public interface JsonValue extends PsiElement { diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java b/plugins/json/gen/com/intellij/json/psi/JsonVisitor.java similarity index 93% rename from plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java rename to plugins/json/gen/com/intellij/json/psi/JsonVisitor.java index 2f86ac8b4377..cdb8755ffbaa 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonVisitor.java +++ b/plugins/json/gen/com/intellij/json/psi/JsonVisitor.java @@ -1,9 +1,9 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; +package com.intellij.json.psi; -import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.*; import com.intellij.psi.PsiElementVisitor; -import org.jetbrains.annotations.NotNull; +import com.intellij.psi.PsiElement; public class JsonVisitor extends PsiElementVisitor { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java similarity index 76% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java index db46cea302ee..54a96032a755 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonArrayImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java @@ -1,15 +1,14 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; - -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import com.jetbrains.json.psi.JsonArray; -import com.jetbrains.json.psi.JsonValue; -import com.jetbrains.json.psi.JsonVisitor; -import org.jetbrains.annotations.NotNull; +package com.intellij.json.psi.impl; import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.json.psi.*; public class JsonArrayImpl extends JsonValueImpl implements JsonArray { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java similarity index 65% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java index 43283dfe89e6..107879c43c83 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonBooleanLiteralImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java @@ -1,11 +1,14 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; +package com.intellij.json.psi.impl; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.json.psi.JsonBooleanLiteral; -import com.jetbrains.json.psi.JsonVisitor; -import org.jetbrains.annotations.NotNull; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.json.psi.*; public class JsonBooleanLiteralImpl extends JsonLiteralImpl implements JsonBooleanLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java similarity index 64% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java index 2e6e652b9158..54aac5d5ac67 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonLiteralImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java @@ -1,11 +1,14 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; +package com.intellij.json.psi.impl; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.json.psi.JsonLiteral; -import com.jetbrains.json.psi.JsonVisitor; -import org.jetbrains.annotations.NotNull; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.json.psi.*; public class JsonLiteralImpl extends JsonValueImpl implements JsonLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java similarity index 65% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java index e9800487b836..78454b01c6e5 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNullLiteralImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java @@ -1,11 +1,14 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; +package com.intellij.json.psi.impl; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.json.psi.JsonNullLiteral; -import com.jetbrains.json.psi.JsonVisitor; -import org.jetbrains.annotations.NotNull; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.json.psi.*; public class JsonNullLiteralImpl extends JsonLiteralImpl implements JsonNullLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java similarity index 73% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java index c450638e2507..f4469bca25d6 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonNumberLiteralImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java @@ -1,14 +1,14 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; +package com.intellij.json.psi.impl; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.json.psi.JsonNumberLiteral; -import com.jetbrains.json.psi.JsonVisitor; -import org.jetbrains.annotations.NotNull; - -import static com.jetbrains.json.JsonElementTypes.NUMBER; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.json.psi.*; public class JsonNumberLiteralImpl extends JsonLiteralImpl implements JsonNumberLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java similarity index 76% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java index da7c1e98d639..c2e5b3278e8c 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonObjectImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java @@ -1,15 +1,14 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; - -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import com.jetbrains.json.psi.JsonObject; -import com.jetbrains.json.psi.JsonProperty; -import com.jetbrains.json.psi.JsonVisitor; -import org.jetbrains.annotations.NotNull; +package com.intellij.json.psi.impl; import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.json.psi.*; public class JsonObjectImpl extends JsonValueImpl implements JsonObject { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java similarity index 76% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java index 4edba140a018..5265b1c24605 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java @@ -1,12 +1,15 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; +package com.intellij.json.psi.impl; -import com.intellij.extapi.psi.ASTWrapperPsiElement; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.json.psi.*; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.intellij.json.psi.*; public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProperty { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java similarity index 72% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java index 1cdaa39eca88..39f9573ee6c8 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonPropertyNameImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java @@ -1,13 +1,15 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; +package com.intellij.json.psi.impl; -import com.intellij.extapi.psi.ASTWrapperPsiElement; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.json.psi.JsonPropertyName; -import com.jetbrains.json.psi.JsonStringLiteral; -import com.jetbrains.json.psi.JsonVisitor; -import org.jetbrains.annotations.NotNull; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.intellij.json.psi.*; public class JsonPropertyNameImpl extends ASTWrapperPsiElement implements JsonPropertyName { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java similarity index 73% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java index 8db009266899..e018ce64eb39 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonStringLiteralImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java @@ -1,14 +1,14 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; +package com.intellij.json.psi.impl; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.json.psi.JsonStringLiteral; -import com.jetbrains.json.psi.JsonVisitor; -import org.jetbrains.annotations.NotNull; - -import static com.jetbrains.json.JsonElementTypes.STRING; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.json.psi.*; public class JsonStringLiteralImpl extends JsonLiteralImpl implements JsonStringLiteral { diff --git a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonValueImpl.java b/plugins/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java similarity index 66% rename from plugins/json/gen/com/jetbrains/json/psi/impl/JsonValueImpl.java rename to plugins/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java index 5f08571bcb71..28bcf95a47a6 100644 --- a/plugins/json/gen/com/jetbrains/json/psi/impl/JsonValueImpl.java +++ b/plugins/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java @@ -1,12 +1,15 @@ // This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi.impl; +package com.intellij.json.psi.impl; -import com.intellij.extapi.psi.ASTWrapperPsiElement; +import java.util.List; +import org.jetbrains.annotations.*; import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; -import com.jetbrains.json.psi.JsonValue; -import com.jetbrains.json.psi.JsonVisitor; -import org.jetbrains.annotations.NotNull; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.intellij.json.psi.*; public class JsonValueImpl extends ASTWrapperPsiElement implements JsonValue { diff --git a/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java b/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java deleted file mode 100644 index e0eba8964f22..000000000000 --- a/plugins/json/gen/com/jetbrains/json/psi/JsonLiteral.java +++ /dev/null @@ -1,6 +0,0 @@ -// This is a generated file. Not intended for manual editing. -package com.jetbrains.json.psi; - -public interface JsonLiteral extends JsonValue { - -} diff --git a/plugins/json/json.iml b/plugins/json/json.iml index e493411e36bb..d58b456b56c2 100644 --- a/plugins/json/json.iml +++ b/plugins/json/json.iml @@ -4,7 +4,7 @@ - + diff --git a/plugins/json/src/META-INF/plugin.xml b/plugins/json/src/META-INF/plugin.xml index 30fd09dfa764..5f6952c73c6b 100644 --- a/plugins/json/src/META-INF/plugin.xml +++ b/plugins/json/src/META-INF/plugin.xml @@ -23,22 +23,22 @@ - - - + + + - - - - - - + + + + + + - - - + + + \ No newline at end of file diff --git a/plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java b/plugins/json/src/com/intellij/json/JsonBraceMatcher.java similarity index 96% rename from plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java rename to plugins/json/src/com/intellij/json/JsonBraceMatcher.java index 29b810c4a4e1..2504f3040ba8 100644 --- a/plugins/json/src/com/jetbrains/json/JsonBraceMatcher.java +++ b/plugins/json/src/com/intellij/json/JsonBraceMatcher.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.lang.BracePair; import com.intellij.lang.PairedBraceMatcher; diff --git a/plugins/json/src/com/jetbrains/json/JsonElementType.java b/plugins/json/src/com/intellij/json/JsonElementType.java similarity index 91% rename from plugins/json/src/com/jetbrains/json/JsonElementType.java rename to plugins/json/src/com/intellij/json/JsonElementType.java index f05720de5112..54e05dfc65c6 100644 --- a/plugins/json/src/com/jetbrains/json/JsonElementType.java +++ b/plugins/json/src/com/intellij/json/JsonElementType.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NonNls; diff --git a/plugins/json/src/com/jetbrains/json/JsonFile.java b/plugins/json/src/com/intellij/json/JsonFile.java similarity index 93% rename from plugins/json/src/com/jetbrains/json/JsonFile.java rename to plugins/json/src/com/intellij/json/JsonFile.java index ec192b20c8c0..e8971563543d 100644 --- a/plugins/json/src/com/jetbrains/json/JsonFile.java +++ b/plugins/json/src/com/intellij/json/JsonFile.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.extapi.psi.PsiFileBase; import com.intellij.openapi.fileTypes.FileType; diff --git a/plugins/json/src/com/jetbrains/json/JsonFileType.java b/plugins/json/src/com/intellij/json/JsonFileType.java similarity index 96% rename from plugins/json/src/com/jetbrains/json/JsonFileType.java rename to plugins/json/src/com/intellij/json/JsonFileType.java index 8379ed708790..3a2d0a448ad7 100644 --- a/plugins/json/src/com/jetbrains/json/JsonFileType.java +++ b/plugins/json/src/com/intellij/json/JsonFileType.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.icons.AllIcons; import com.intellij.openapi.fileTypes.LanguageFileType; diff --git a/plugins/json/src/com/jetbrains/json/JsonFileTypeFactory.java b/plugins/json/src/com/intellij/json/JsonFileTypeFactory.java similarity index 93% rename from plugins/json/src/com/jetbrains/json/JsonFileTypeFactory.java rename to plugins/json/src/com/intellij/json/JsonFileTypeFactory.java index 0930485df4ce..2cfaa2f1466b 100644 --- a/plugins/json/src/com/jetbrains/json/JsonFileTypeFactory.java +++ b/plugins/json/src/com/intellij/json/JsonFileTypeFactory.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.openapi.fileTypes.FileTypeConsumer; import com.intellij.openapi.fileTypes.FileTypeFactory; diff --git a/plugins/json/src/com/jetbrains/json/JsonLanguage.java b/plugins/json/src/com/intellij/json/JsonLanguage.java similarity index 91% rename from plugins/json/src/com/jetbrains/json/JsonLanguage.java rename to plugins/json/src/com/intellij/json/JsonLanguage.java index c9788b776e02..09e2807c1cfd 100644 --- a/plugins/json/src/com/jetbrains/json/JsonLanguage.java +++ b/plugins/json/src/com/intellij/json/JsonLanguage.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.lang.Language; diff --git a/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java b/plugins/json/src/com/intellij/json/JsonParserDefinition.java similarity index 98% rename from plugins/json/src/com/jetbrains/json/JsonParserDefinition.java rename to plugins/json/src/com/intellij/json/JsonParserDefinition.java index 2b73e9502697..473a716e00d4 100644 --- a/plugins/json/src/com/jetbrains/json/JsonParserDefinition.java +++ b/plugins/json/src/com/intellij/json/JsonParserDefinition.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.lang.ASTNode; import com.intellij.lang.ParserDefinition; diff --git a/plugins/json/src/com/jetbrains/json/JsonQuoteHandler.java b/plugins/json/src/com/intellij/json/JsonQuoteHandler.java similarity index 90% rename from plugins/json/src/com/jetbrains/json/JsonQuoteHandler.java rename to plugins/json/src/com/intellij/json/JsonQuoteHandler.java index 5eeebd34eef0..4ddac1ac07af 100644 --- a/plugins/json/src/com/jetbrains/json/JsonQuoteHandler.java +++ b/plugins/json/src/com/intellij/json/JsonQuoteHandler.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.codeInsight.editorActions.SimpleTokenSetQuoteHandler; diff --git a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java b/plugins/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java similarity index 97% rename from plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java rename to plugins/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java index 3b783f1be4fa..a9c29dea68b3 100644 --- a/plugins/json/src/com/jetbrains/json/JsonSyntaxHighlighterFactory.java +++ b/plugins/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.lexer.LayeredLexer; import com.intellij.lexer.Lexer; @@ -20,7 +20,7 @@ import java.util.HashMap; import java.util.Map; import static com.intellij.psi.StringEscapesTokenTypes.*; -import static com.jetbrains.json.JsonElementTypes.*; +import static com.intellij.json.JsonElementTypes.*; public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { @NotNull diff --git a/plugins/json/src/com/jetbrains/json/JsonTokenType.java b/plugins/json/src/com/intellij/json/JsonTokenType.java similarity index 91% rename from plugins/json/src/com/jetbrains/json/JsonTokenType.java rename to plugins/json/src/com/intellij/json/JsonTokenType.java index 51238ab7e4c1..a7752cd8a4e2 100644 --- a/plugins/json/src/com/jetbrains/json/JsonTokenType.java +++ b/plugins/json/src/com/intellij/json/JsonTokenType.java @@ -1,4 +1,4 @@ -package com.jetbrains.json; +package com.intellij.json; import com.intellij.psi.tree.IElementType; import org.jetbrains.annotations.NonNls; diff --git a/plugins/json/src/com/jetbrains/json/breadcrumbs/JsonBreadcrumbsProvider.java b/plugins/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java similarity index 88% rename from plugins/json/src/com/jetbrains/json/breadcrumbs/JsonBreadcrumbsProvider.java rename to plugins/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java index fc2f64f8065e..e41f316e08bb 100644 --- a/plugins/json/src/com/jetbrains/json/breadcrumbs/JsonBreadcrumbsProvider.java +++ b/plugins/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java @@ -1,12 +1,12 @@ -package com.jetbrains.json.breadcrumbs; +package com.intellij.json.breadcrumbs; +import com.intellij.json.JsonLanguage; import com.intellij.lang.Language; import com.intellij.psi.PsiElement; import com.intellij.xml.breadcrumbs.BreadcrumbsInfoProvider; -import com.jetbrains.json.JsonLanguage; -import com.jetbrains.json.psi.JsonArray; -import com.jetbrains.json.psi.JsonProperty; -import com.jetbrains.json.psi.JsonValue; +import com.intellij.json.psi.JsonArray; +import com.intellij.json.psi.JsonProperty; +import com.intellij.json.psi.JsonValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugins/json/src/com/jetbrains/json/codeinsight/JsonCompletionContributor.java b/plugins/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java similarity index 95% rename from plugins/json/src/com/jetbrains/json/codeinsight/JsonCompletionContributor.java rename to plugins/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java index dda6ed0de184..aed1217aa036 100644 --- a/plugins/json/src/com/jetbrains/json/codeinsight/JsonCompletionContributor.java +++ b/plugins/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java @@ -1,4 +1,4 @@ -package com.jetbrains.json.codeinsight; +package com.intellij.json.codeinsight; import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.lookup.LookupElementBuilder; @@ -7,8 +7,8 @@ import com.intellij.patterns.PsiElementPattern; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.DebugUtil; import com.intellij.util.ProcessingContext; -import com.jetbrains.json.psi.JsonArray; -import com.jetbrains.json.psi.JsonProperty; +import com.intellij.json.psi.JsonArray; +import com.intellij.json.psi.JsonProperty; import org.jetbrains.annotations.NotNull; import static com.intellij.patterns.PlatformPatterns.psiElement; diff --git a/plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java b/plugins/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java similarity index 96% rename from plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java rename to plugins/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java index cac306d83dab..92c63adfa746 100644 --- a/plugins/json/src/com/jetbrains/json/codeinsight/JsonStringLiteralAnnotator.java +++ b/plugins/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java @@ -1,11 +1,11 @@ -package com.jetbrains.json.codeinsight; +package com.intellij.json.codeinsight; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; -import com.jetbrains.json.psi.JsonStringLiteral; +import com.intellij.json.psi.JsonStringLiteral; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java b/plugins/json/src/com/intellij/json/formatter/JsonBlock.java similarity index 93% rename from plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java rename to plugins/json/src/com/intellij/json/formatter/JsonBlock.java index 172f7edba390..69d6a89fb12e 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonBlock.java +++ b/plugins/json/src/com/intellij/json/formatter/JsonBlock.java @@ -1,6 +1,7 @@ -package com.jetbrains.json.formatter; +package com.intellij.json.formatter; import com.intellij.formatting.*; +import com.intellij.json.JsonParserDefinition; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; @@ -10,16 +11,14 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.jetbrains.json.JsonParserDefinition; -import com.jetbrains.json.psi.JsonProperty; -import com.jetbrains.json.psi.JsonValue; +import com.intellij.json.psi.JsonProperty; +import com.intellij.json.psi.JsonValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.util.List; -import static com.jetbrains.json.JsonElementTypes.*; -import static com.jetbrains.json.JsonParserDefinition.CONTAINERS; +import static com.intellij.json.JsonElementTypes.*; /** * @author Mikhail Golubev @@ -179,7 +178,7 @@ public class JsonBlock implements ASTBlock { } private boolean isContainer() { - return CONTAINERS.contains(myNode.getElementType()); + return JsonParserDefinition.CONTAINERS.contains(myNode.getElementType()); } } diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettings.java b/plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettings.java similarity index 87% rename from plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettings.java rename to plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettings.java index 0d2d14475f86..5bb29b5707bb 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettings.java +++ b/plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettings.java @@ -1,8 +1,8 @@ -package com.jetbrains.json.formatter; +package com.intellij.json.formatter; +import com.intellij.json.JsonLanguage; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CustomCodeStyleSettings; -import com.jetbrains.json.JsonLanguage; /** * @author Mikhail Golubev diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java b/plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java similarity index 95% rename from plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java rename to plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java index bab129809fb4..712a4cdedb88 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonCodeStyleSettingsProvider.java +++ b/plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java @@ -1,14 +1,14 @@ -package com.jetbrains.json.formatter; +package com.intellij.json.formatter; import com.intellij.application.options.CodeStyleAbstractConfigurable; import com.intellij.application.options.CodeStyleAbstractPanel; import com.intellij.application.options.TabbedLanguageCodeStylePanel; +import com.intellij.json.JsonLanguage; import com.intellij.lang.Language; import com.intellij.openapi.options.Configurable; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CodeStyleSettingsProvider; import com.intellij.psi.codeStyle.CustomCodeStyleSettings; -import com.jetbrains.json.JsonLanguage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonEnterBetweenBracesHandler.java b/plugins/json/src/com/intellij/json/formatter/JsonEnterBetweenBracesHandler.java similarity index 89% rename from plugins/json/src/com/jetbrains/json/formatter/JsonEnterBetweenBracesHandler.java rename to plugins/json/src/com/intellij/json/formatter/JsonEnterBetweenBracesHandler.java index 247a3774092d..71638e80fba0 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonEnterBetweenBracesHandler.java +++ b/plugins/json/src/com/intellij/json/formatter/JsonEnterBetweenBracesHandler.java @@ -1,4 +1,4 @@ -package com.jetbrains.json.formatter; +package com.intellij.json.formatter; import com.intellij.codeInsight.editorActions.enter.EnterBetweenBracesHandler; diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java b/plugins/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java similarity index 95% rename from plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java rename to plugins/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java index 7f8017efea8b..041e6095bb04 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonFormattingBuilderModel.java +++ b/plugins/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java @@ -1,4 +1,4 @@ -package com.jetbrains.json.formatter; +package com.intellij.json.formatter; import com.intellij.formatting.*; import com.intellij.lang.ASTNode; @@ -9,11 +9,11 @@ import com.intellij.psi.PsiFile; import com.intellij.psi.codeStyle.CodeStyleSettings; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.impl.DebugUtil; -import com.jetbrains.json.JsonLanguage; +import com.intellij.json.JsonLanguage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import static com.jetbrains.json.JsonElementTypes.*; +import static com.intellij.json.JsonElementTypes.*; /** * @author Mikhail Golubev diff --git a/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java b/plugins/json/src/com/intellij/json/formatter/JsonLanguageCodeStyleSettingsProvider.java similarity index 97% rename from plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java rename to plugins/json/src/com/intellij/json/formatter/JsonLanguageCodeStyleSettingsProvider.java index 6cbb7803c6fe..541e54c3828f 100644 --- a/plugins/json/src/com/jetbrains/json/formatter/JsonLanguageCodeStyleSettingsProvider.java +++ b/plugins/json/src/com/intellij/json/formatter/JsonLanguageCodeStyleSettingsProvider.java @@ -1,4 +1,4 @@ -package com.jetbrains.json.formatter; +package com.intellij.json.formatter; import com.intellij.application.options.IndentOptionsEditor; import com.intellij.application.options.SmartIndentOptionsEditor; @@ -6,7 +6,7 @@ import com.intellij.lang.Language; import com.intellij.psi.codeStyle.CodeStyleSettingsCustomizable; import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.codeStyle.LanguageCodeStyleSettingsProvider; -import com.jetbrains.json.JsonLanguage; +import com.intellij.json.JsonLanguage; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; diff --git a/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java b/plugins/json/src/com/intellij/json/psi/JsonPsiImplUtils.java similarity index 89% rename from plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java rename to plugins/json/src/com/intellij/json/psi/JsonPsiImplUtils.java index 9535f9252f0b..80cdceebbb6f 100644 --- a/plugins/json/src/com/jetbrains/json/psi/JsonPsiImplUtils.java +++ b/plugins/json/src/com/intellij/json/psi/JsonPsiImplUtils.java @@ -1,4 +1,4 @@ -package com.jetbrains.json.psi; +package com.intellij.json.psi; import com.intellij.openapi.util.text.StringUtil; import org.jetbrains.annotations.NotNull; diff --git a/plugins/json/src/json.bnf b/plugins/json/src/json.bnf index 6776d9740478..51626b56bc5c 100644 --- a/plugins/json/src/json.bnf +++ b/plugins/json/src/json.bnf @@ -1,15 +1,15 @@ { - parserClass='com.jetbrains.json.JsonParser' - parserUtilClass="com.jetbrains.json.JsonParserUtil" - psiPackage='com.jetbrains.json.psi' - psiImplPackage='com.jetbrains.json.psi.impl' + parserClass='com.intellij.json.JsonParser' + parserUtilClass="com.intellij.json.JsonParserUtil" + psiPackage='com.intellij.json.psi' + psiImplPackage='com.intellij.json.psi.impl' - elementTypeHolderClass='com.jetbrains.json.JsonElementTypes' - elementTypeClass='com.jetbrains.json.JsonElementType' + elementTypeHolderClass='com.intellij.json.JsonElementTypes' + elementTypeClass='com.intellij.json.JsonElementType' psiClassPrefix="Json" - psiImplUtilClass='com.jetbrains.json.psi.JsonPsiImplUtils' - tokenTypeClass='com.jetbrains.json.JsonTokenType' + psiImplUtilClass='com.intellij.json.psi.JsonPsiImplUtils' + tokenTypeClass='com.intellij.json.JsonTokenType' tokens = [ L_CURLY='{' From 7e1814b47e6b88e516d46228b2300e44315a9f40 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 19 Aug 2014 15:05:44 +0400 Subject: [PATCH 28/85] Move JSON plugin to the root of community repository (as done for XML) --- .idea/modules.xml | 4 ++-- .../json => json}/gen/com/intellij/json/JsonElementTypes.java | 0 {plugins/json => json}/gen/com/intellij/json/JsonLexer.java | 0 {plugins/json => json}/gen/com/intellij/json/JsonParser.java | 0 .../json => json}/gen/com/intellij/json/JsonParserUtil.java | 0 {plugins/json => json}/gen/com/intellij/json/_JsonLexer.flex | 0 {plugins/json => json}/gen/com/intellij/json/_JsonLexer.java | 0 .../json => json}/gen/com/intellij/json/psi/JsonArray.java | 0 .../gen/com/intellij/json/psi/JsonBooleanLiteral.java | 0 .../json => json}/gen/com/intellij/json/psi/JsonLiteral.java | 0 .../gen/com/intellij/json/psi/JsonNullLiteral.java | 0 .../gen/com/intellij/json/psi/JsonNumberLiteral.java | 0 .../json => json}/gen/com/intellij/json/psi/JsonObject.java | 0 .../json => json}/gen/com/intellij/json/psi/JsonProperty.java | 0 .../gen/com/intellij/json/psi/JsonPropertyName.java | 0 .../gen/com/intellij/json/psi/JsonStringLiteral.java | 0 .../json => json}/gen/com/intellij/json/psi/JsonValue.java | 0 .../json => json}/gen/com/intellij/json/psi/JsonVisitor.java | 0 .../gen/com/intellij/json/psi/impl/JsonArrayImpl.java | 0 .../com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java | 0 .../gen/com/intellij/json/psi/impl/JsonLiteralImpl.java | 0 .../gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java | 0 .../gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java | 0 .../gen/com/intellij/json/psi/impl/JsonObjectImpl.java | 0 .../gen/com/intellij/json/psi/impl/JsonPropertyImpl.java | 0 .../gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java | 0 .../gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java | 0 .../gen/com/intellij/json/psi/impl/JsonValueImpl.java | 0 {plugins/json => json}/json.iml | 0 {plugins/json => json}/src/META-INF/plugin.xml | 0 .../json => json}/src/com/intellij/json/JsonBraceMatcher.java | 0 .../json => json}/src/com/intellij/json/JsonElementType.java | 0 {plugins/json => json}/src/com/intellij/json/JsonFile.java | 0 .../json => json}/src/com/intellij/json/JsonFileType.java | 0 .../src/com/intellij/json/JsonFileTypeFactory.java | 0 .../json => json}/src/com/intellij/json/JsonLanguage.java | 0 .../src/com/intellij/json/JsonParserDefinition.java | 0 .../json => json}/src/com/intellij/json/JsonQuoteHandler.java | 0 .../src/com/intellij/json/JsonSyntaxHighlighterFactory.java | 0 .../json => json}/src/com/intellij/json/JsonTokenType.java | 0 .../intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java | 0 .../intellij/json/codeinsight/JsonCompletionContributor.java | 0 .../intellij/json/codeinsight/JsonStringLiteralAnnotator.java | 0 .../src/com/intellij/json/formatter/JsonBlock.java | 0 .../com/intellij/json/formatter/JsonCodeStyleSettings.java | 0 .../json/formatter/JsonCodeStyleSettingsProvider.java | 0 .../json/formatter/JsonEnterBetweenBracesHandler.java | 0 .../intellij/json/formatter/JsonFormattingBuilderModel.java | 0 .../json/formatter/JsonLanguageCodeStyleSettingsProvider.java | 0 .../src/com/intellij/json/psi/JsonPsiImplUtils.java | 0 {plugins/json => json}/src/json.bnf | 0 {plugins/json-tests => json/tests}/json-tests.iml | 0 .../tests}/test/com/intellij/json/JsonCompletionTest.java | 0 .../tests}/test/com/intellij/json/JsonFormattingTest.java | 0 .../tests}/test/com/intellij/json/JsonParsingTest.java | 0 .../tests}/testData/completion/InsideArrayElement1.json | 0 .../tests}/testData/completion/InsideArrayElement2.json | 0 .../tests}/testData/completion/InsidePropertyKey1.json | 0 .../tests}/testData/completion/InsidePropertyKey2.json | 0 .../tests}/testData/completion/InsidePropertyValue.json | 0 .../tests}/testData/formatting/BlankLinesStripping.json | 0 .../tests}/testData/formatting/BlankLinesStripping_after.json | 0 .../testData/formatting/ContainerElementsAlignment.json | 0 .../testData/formatting/ContainerElementsAlignment_after.json | 0 .../tests}/testData/formatting/SpacesInsertion.json | 0 .../tests}/testData/formatting/SpacesInsertion_after.json | 0 .../tests}/testData/formatting/Wrapping.json | 0 .../tests}/testData/formatting/Wrapping_after.json | 0 {plugins/json-tests => json/tests}/testData/psi/Keywords.json | 0 {plugins/json-tests => json/tests}/testData/psi/Keywords.txt | 0 .../tests}/testData/psi/NestedArrayLiterals.json | 0 .../tests}/testData/psi/NestedArrayLiterals.txt | 0 .../tests}/testData/psi/NestedObjectLiterals.json | 0 .../tests}/testData/psi/NestedObjectLiterals.txt | 0 .../tests}/testData/psi/TopLevelStringLiteral.json | 0 .../tests}/testData/psi/TopLevelStringLiteral.txt | 0 76 files changed, 2 insertions(+), 2 deletions(-) rename {plugins/json => json}/gen/com/intellij/json/JsonElementTypes.java (100%) rename {plugins/json => json}/gen/com/intellij/json/JsonLexer.java (100%) rename {plugins/json => json}/gen/com/intellij/json/JsonParser.java (100%) rename {plugins/json => json}/gen/com/intellij/json/JsonParserUtil.java (100%) rename {plugins/json => json}/gen/com/intellij/json/_JsonLexer.flex (100%) rename {plugins/json => json}/gen/com/intellij/json/_JsonLexer.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonArray.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonBooleanLiteral.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonLiteral.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonNullLiteral.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonNumberLiteral.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonObject.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonProperty.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonPropertyName.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonStringLiteral.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonValue.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/JsonVisitor.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonArrayImpl.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonObjectImpl.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java (100%) rename {plugins/json => json}/gen/com/intellij/json/psi/impl/JsonValueImpl.java (100%) rename {plugins/json => json}/json.iml (100%) rename {plugins/json => json}/src/META-INF/plugin.xml (100%) rename {plugins/json => json}/src/com/intellij/json/JsonBraceMatcher.java (100%) rename {plugins/json => json}/src/com/intellij/json/JsonElementType.java (100%) rename {plugins/json => json}/src/com/intellij/json/JsonFile.java (100%) rename {plugins/json => json}/src/com/intellij/json/JsonFileType.java (100%) rename {plugins/json => json}/src/com/intellij/json/JsonFileTypeFactory.java (100%) rename {plugins/json => json}/src/com/intellij/json/JsonLanguage.java (100%) rename {plugins/json => json}/src/com/intellij/json/JsonParserDefinition.java (100%) rename {plugins/json => json}/src/com/intellij/json/JsonQuoteHandler.java (100%) rename {plugins/json => json}/src/com/intellij/json/JsonSyntaxHighlighterFactory.java (100%) rename {plugins/json => json}/src/com/intellij/json/JsonTokenType.java (100%) rename {plugins/json => json}/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java (100%) rename {plugins/json => json}/src/com/intellij/json/codeinsight/JsonCompletionContributor.java (100%) rename {plugins/json => json}/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java (100%) rename {plugins/json => json}/src/com/intellij/json/formatter/JsonBlock.java (100%) rename {plugins/json => json}/src/com/intellij/json/formatter/JsonCodeStyleSettings.java (100%) rename {plugins/json => json}/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java (100%) rename {plugins/json => json}/src/com/intellij/json/formatter/JsonEnterBetweenBracesHandler.java (100%) rename {plugins/json => json}/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java (100%) rename {plugins/json => json}/src/com/intellij/json/formatter/JsonLanguageCodeStyleSettingsProvider.java (100%) rename {plugins/json => json}/src/com/intellij/json/psi/JsonPsiImplUtils.java (100%) rename {plugins/json => json}/src/json.bnf (100%) rename {plugins/json-tests => json/tests}/json-tests.iml (100%) rename {plugins/json-tests => json/tests}/test/com/intellij/json/JsonCompletionTest.java (100%) rename {plugins/json-tests => json/tests}/test/com/intellij/json/JsonFormattingTest.java (100%) rename {plugins/json-tests => json/tests}/test/com/intellij/json/JsonParsingTest.java (100%) rename {plugins/json-tests => json/tests}/testData/completion/InsideArrayElement1.json (100%) rename {plugins/json-tests => json/tests}/testData/completion/InsideArrayElement2.json (100%) rename {plugins/json-tests => json/tests}/testData/completion/InsidePropertyKey1.json (100%) rename {plugins/json-tests => json/tests}/testData/completion/InsidePropertyKey2.json (100%) rename {plugins/json-tests => json/tests}/testData/completion/InsidePropertyValue.json (100%) rename {plugins/json-tests => json/tests}/testData/formatting/BlankLinesStripping.json (100%) rename {plugins/json-tests => json/tests}/testData/formatting/BlankLinesStripping_after.json (100%) rename {plugins/json-tests => json/tests}/testData/formatting/ContainerElementsAlignment.json (100%) rename {plugins/json-tests => json/tests}/testData/formatting/ContainerElementsAlignment_after.json (100%) rename {plugins/json-tests => json/tests}/testData/formatting/SpacesInsertion.json (100%) rename {plugins/json-tests => json/tests}/testData/formatting/SpacesInsertion_after.json (100%) rename {plugins/json-tests => json/tests}/testData/formatting/Wrapping.json (100%) rename {plugins/json-tests => json/tests}/testData/formatting/Wrapping_after.json (100%) rename {plugins/json-tests => json/tests}/testData/psi/Keywords.json (100%) rename {plugins/json-tests => json/tests}/testData/psi/Keywords.txt (100%) rename {plugins/json-tests => json/tests}/testData/psi/NestedArrayLiterals.json (100%) rename {plugins/json-tests => json/tests}/testData/psi/NestedArrayLiterals.txt (100%) rename {plugins/json-tests => json/tests}/testData/psi/NestedObjectLiterals.json (100%) rename {plugins/json-tests => json/tests}/testData/psi/NestedObjectLiterals.txt (100%) rename {plugins/json-tests => json/tests}/testData/psi/TopLevelStringLiteral.json (100%) rename {plugins/json-tests => json/tests}/testData/psi/TopLevelStringLiteral.txt (100%) diff --git a/.idea/modules.xml b/.idea/modules.xml index 94f45924b26e..186cbc39337f 100644 --- a/.idea/modules.xml +++ b/.idea/modules.xml @@ -109,8 +109,8 @@ - - + + diff --git a/plugins/json/gen/com/intellij/json/JsonElementTypes.java b/json/gen/com/intellij/json/JsonElementTypes.java similarity index 100% rename from plugins/json/gen/com/intellij/json/JsonElementTypes.java rename to json/gen/com/intellij/json/JsonElementTypes.java diff --git a/plugins/json/gen/com/intellij/json/JsonLexer.java b/json/gen/com/intellij/json/JsonLexer.java similarity index 100% rename from plugins/json/gen/com/intellij/json/JsonLexer.java rename to json/gen/com/intellij/json/JsonLexer.java diff --git a/plugins/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java similarity index 100% rename from plugins/json/gen/com/intellij/json/JsonParser.java rename to json/gen/com/intellij/json/JsonParser.java diff --git a/plugins/json/gen/com/intellij/json/JsonParserUtil.java b/json/gen/com/intellij/json/JsonParserUtil.java similarity index 100% rename from plugins/json/gen/com/intellij/json/JsonParserUtil.java rename to json/gen/com/intellij/json/JsonParserUtil.java diff --git a/plugins/json/gen/com/intellij/json/_JsonLexer.flex b/json/gen/com/intellij/json/_JsonLexer.flex similarity index 100% rename from plugins/json/gen/com/intellij/json/_JsonLexer.flex rename to json/gen/com/intellij/json/_JsonLexer.flex diff --git a/plugins/json/gen/com/intellij/json/_JsonLexer.java b/json/gen/com/intellij/json/_JsonLexer.java similarity index 100% rename from plugins/json/gen/com/intellij/json/_JsonLexer.java rename to json/gen/com/intellij/json/_JsonLexer.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonArray.java b/json/gen/com/intellij/json/psi/JsonArray.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonArray.java rename to json/gen/com/intellij/json/psi/JsonArray.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonBooleanLiteral.java b/json/gen/com/intellij/json/psi/JsonBooleanLiteral.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonBooleanLiteral.java rename to json/gen/com/intellij/json/psi/JsonBooleanLiteral.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonLiteral.java b/json/gen/com/intellij/json/psi/JsonLiteral.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonLiteral.java rename to json/gen/com/intellij/json/psi/JsonLiteral.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonNullLiteral.java b/json/gen/com/intellij/json/psi/JsonNullLiteral.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonNullLiteral.java rename to json/gen/com/intellij/json/psi/JsonNullLiteral.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonNumberLiteral.java b/json/gen/com/intellij/json/psi/JsonNumberLiteral.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonNumberLiteral.java rename to json/gen/com/intellij/json/psi/JsonNumberLiteral.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonObject.java b/json/gen/com/intellij/json/psi/JsonObject.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonObject.java rename to json/gen/com/intellij/json/psi/JsonObject.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonProperty.java rename to json/gen/com/intellij/json/psi/JsonProperty.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonPropertyName.java b/json/gen/com/intellij/json/psi/JsonPropertyName.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonPropertyName.java rename to json/gen/com/intellij/json/psi/JsonPropertyName.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonStringLiteral.java b/json/gen/com/intellij/json/psi/JsonStringLiteral.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonStringLiteral.java rename to json/gen/com/intellij/json/psi/JsonStringLiteral.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonValue.java b/json/gen/com/intellij/json/psi/JsonValue.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonValue.java rename to json/gen/com/intellij/json/psi/JsonValue.java diff --git a/plugins/json/gen/com/intellij/json/psi/JsonVisitor.java b/json/gen/com/intellij/json/psi/JsonVisitor.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/JsonVisitor.java rename to json/gen/com/intellij/json/psi/JsonVisitor.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java diff --git a/plugins/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java b/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java similarity index 100% rename from plugins/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonValueImpl.java diff --git a/plugins/json/json.iml b/json/json.iml similarity index 100% rename from plugins/json/json.iml rename to json/json.iml diff --git a/plugins/json/src/META-INF/plugin.xml b/json/src/META-INF/plugin.xml similarity index 100% rename from plugins/json/src/META-INF/plugin.xml rename to json/src/META-INF/plugin.xml diff --git a/plugins/json/src/com/intellij/json/JsonBraceMatcher.java b/json/src/com/intellij/json/JsonBraceMatcher.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonBraceMatcher.java rename to json/src/com/intellij/json/JsonBraceMatcher.java diff --git a/plugins/json/src/com/intellij/json/JsonElementType.java b/json/src/com/intellij/json/JsonElementType.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonElementType.java rename to json/src/com/intellij/json/JsonElementType.java diff --git a/plugins/json/src/com/intellij/json/JsonFile.java b/json/src/com/intellij/json/JsonFile.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonFile.java rename to json/src/com/intellij/json/JsonFile.java diff --git a/plugins/json/src/com/intellij/json/JsonFileType.java b/json/src/com/intellij/json/JsonFileType.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonFileType.java rename to json/src/com/intellij/json/JsonFileType.java diff --git a/plugins/json/src/com/intellij/json/JsonFileTypeFactory.java b/json/src/com/intellij/json/JsonFileTypeFactory.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonFileTypeFactory.java rename to json/src/com/intellij/json/JsonFileTypeFactory.java diff --git a/plugins/json/src/com/intellij/json/JsonLanguage.java b/json/src/com/intellij/json/JsonLanguage.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonLanguage.java rename to json/src/com/intellij/json/JsonLanguage.java diff --git a/plugins/json/src/com/intellij/json/JsonParserDefinition.java b/json/src/com/intellij/json/JsonParserDefinition.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonParserDefinition.java rename to json/src/com/intellij/json/JsonParserDefinition.java diff --git a/plugins/json/src/com/intellij/json/JsonQuoteHandler.java b/json/src/com/intellij/json/JsonQuoteHandler.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonQuoteHandler.java rename to json/src/com/intellij/json/JsonQuoteHandler.java diff --git a/plugins/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java b/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java rename to json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java diff --git a/plugins/json/src/com/intellij/json/JsonTokenType.java b/json/src/com/intellij/json/JsonTokenType.java similarity index 100% rename from plugins/json/src/com/intellij/json/JsonTokenType.java rename to json/src/com/intellij/json/JsonTokenType.java diff --git a/plugins/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java b/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java similarity index 100% rename from plugins/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java rename to json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java diff --git a/plugins/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java b/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java similarity index 100% rename from plugins/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java rename to json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java diff --git a/plugins/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java b/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java similarity index 100% rename from plugins/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java rename to json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java diff --git a/plugins/json/src/com/intellij/json/formatter/JsonBlock.java b/json/src/com/intellij/json/formatter/JsonBlock.java similarity index 100% rename from plugins/json/src/com/intellij/json/formatter/JsonBlock.java rename to json/src/com/intellij/json/formatter/JsonBlock.java diff --git a/plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettings.java b/json/src/com/intellij/json/formatter/JsonCodeStyleSettings.java similarity index 100% rename from plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettings.java rename to json/src/com/intellij/json/formatter/JsonCodeStyleSettings.java diff --git a/plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java b/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java similarity index 100% rename from plugins/json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java rename to json/src/com/intellij/json/formatter/JsonCodeStyleSettingsProvider.java diff --git a/plugins/json/src/com/intellij/json/formatter/JsonEnterBetweenBracesHandler.java b/json/src/com/intellij/json/formatter/JsonEnterBetweenBracesHandler.java similarity index 100% rename from plugins/json/src/com/intellij/json/formatter/JsonEnterBetweenBracesHandler.java rename to json/src/com/intellij/json/formatter/JsonEnterBetweenBracesHandler.java diff --git a/plugins/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java b/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java similarity index 100% rename from plugins/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java rename to json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java diff --git a/plugins/json/src/com/intellij/json/formatter/JsonLanguageCodeStyleSettingsProvider.java b/json/src/com/intellij/json/formatter/JsonLanguageCodeStyleSettingsProvider.java similarity index 100% rename from plugins/json/src/com/intellij/json/formatter/JsonLanguageCodeStyleSettingsProvider.java rename to json/src/com/intellij/json/formatter/JsonLanguageCodeStyleSettingsProvider.java diff --git a/plugins/json/src/com/intellij/json/psi/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/JsonPsiImplUtils.java similarity index 100% rename from plugins/json/src/com/intellij/json/psi/JsonPsiImplUtils.java rename to json/src/com/intellij/json/psi/JsonPsiImplUtils.java diff --git a/plugins/json/src/json.bnf b/json/src/json.bnf similarity index 100% rename from plugins/json/src/json.bnf rename to json/src/json.bnf diff --git a/plugins/json-tests/json-tests.iml b/json/tests/json-tests.iml similarity index 100% rename from plugins/json-tests/json-tests.iml rename to json/tests/json-tests.iml diff --git a/plugins/json-tests/test/com/intellij/json/JsonCompletionTest.java b/json/tests/test/com/intellij/json/JsonCompletionTest.java similarity index 100% rename from plugins/json-tests/test/com/intellij/json/JsonCompletionTest.java rename to json/tests/test/com/intellij/json/JsonCompletionTest.java diff --git a/plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java b/json/tests/test/com/intellij/json/JsonFormattingTest.java similarity index 100% rename from plugins/json-tests/test/com/intellij/json/JsonFormattingTest.java rename to json/tests/test/com/intellij/json/JsonFormattingTest.java diff --git a/plugins/json-tests/test/com/intellij/json/JsonParsingTest.java b/json/tests/test/com/intellij/json/JsonParsingTest.java similarity index 100% rename from plugins/json-tests/test/com/intellij/json/JsonParsingTest.java rename to json/tests/test/com/intellij/json/JsonParsingTest.java diff --git a/plugins/json-tests/testData/completion/InsideArrayElement1.json b/json/tests/testData/completion/InsideArrayElement1.json similarity index 100% rename from plugins/json-tests/testData/completion/InsideArrayElement1.json rename to json/tests/testData/completion/InsideArrayElement1.json diff --git a/plugins/json-tests/testData/completion/InsideArrayElement2.json b/json/tests/testData/completion/InsideArrayElement2.json similarity index 100% rename from plugins/json-tests/testData/completion/InsideArrayElement2.json rename to json/tests/testData/completion/InsideArrayElement2.json diff --git a/plugins/json-tests/testData/completion/InsidePropertyKey1.json b/json/tests/testData/completion/InsidePropertyKey1.json similarity index 100% rename from plugins/json-tests/testData/completion/InsidePropertyKey1.json rename to json/tests/testData/completion/InsidePropertyKey1.json diff --git a/plugins/json-tests/testData/completion/InsidePropertyKey2.json b/json/tests/testData/completion/InsidePropertyKey2.json similarity index 100% rename from plugins/json-tests/testData/completion/InsidePropertyKey2.json rename to json/tests/testData/completion/InsidePropertyKey2.json diff --git a/plugins/json-tests/testData/completion/InsidePropertyValue.json b/json/tests/testData/completion/InsidePropertyValue.json similarity index 100% rename from plugins/json-tests/testData/completion/InsidePropertyValue.json rename to json/tests/testData/completion/InsidePropertyValue.json diff --git a/plugins/json-tests/testData/formatting/BlankLinesStripping.json b/json/tests/testData/formatting/BlankLinesStripping.json similarity index 100% rename from plugins/json-tests/testData/formatting/BlankLinesStripping.json rename to json/tests/testData/formatting/BlankLinesStripping.json diff --git a/plugins/json-tests/testData/formatting/BlankLinesStripping_after.json b/json/tests/testData/formatting/BlankLinesStripping_after.json similarity index 100% rename from plugins/json-tests/testData/formatting/BlankLinesStripping_after.json rename to json/tests/testData/formatting/BlankLinesStripping_after.json diff --git a/plugins/json-tests/testData/formatting/ContainerElementsAlignment.json b/json/tests/testData/formatting/ContainerElementsAlignment.json similarity index 100% rename from plugins/json-tests/testData/formatting/ContainerElementsAlignment.json rename to json/tests/testData/formatting/ContainerElementsAlignment.json diff --git a/plugins/json-tests/testData/formatting/ContainerElementsAlignment_after.json b/json/tests/testData/formatting/ContainerElementsAlignment_after.json similarity index 100% rename from plugins/json-tests/testData/formatting/ContainerElementsAlignment_after.json rename to json/tests/testData/formatting/ContainerElementsAlignment_after.json diff --git a/plugins/json-tests/testData/formatting/SpacesInsertion.json b/json/tests/testData/formatting/SpacesInsertion.json similarity index 100% rename from plugins/json-tests/testData/formatting/SpacesInsertion.json rename to json/tests/testData/formatting/SpacesInsertion.json diff --git a/plugins/json-tests/testData/formatting/SpacesInsertion_after.json b/json/tests/testData/formatting/SpacesInsertion_after.json similarity index 100% rename from plugins/json-tests/testData/formatting/SpacesInsertion_after.json rename to json/tests/testData/formatting/SpacesInsertion_after.json diff --git a/plugins/json-tests/testData/formatting/Wrapping.json b/json/tests/testData/formatting/Wrapping.json similarity index 100% rename from plugins/json-tests/testData/formatting/Wrapping.json rename to json/tests/testData/formatting/Wrapping.json diff --git a/plugins/json-tests/testData/formatting/Wrapping_after.json b/json/tests/testData/formatting/Wrapping_after.json similarity index 100% rename from plugins/json-tests/testData/formatting/Wrapping_after.json rename to json/tests/testData/formatting/Wrapping_after.json diff --git a/plugins/json-tests/testData/psi/Keywords.json b/json/tests/testData/psi/Keywords.json similarity index 100% rename from plugins/json-tests/testData/psi/Keywords.json rename to json/tests/testData/psi/Keywords.json diff --git a/plugins/json-tests/testData/psi/Keywords.txt b/json/tests/testData/psi/Keywords.txt similarity index 100% rename from plugins/json-tests/testData/psi/Keywords.txt rename to json/tests/testData/psi/Keywords.txt diff --git a/plugins/json-tests/testData/psi/NestedArrayLiterals.json b/json/tests/testData/psi/NestedArrayLiterals.json similarity index 100% rename from plugins/json-tests/testData/psi/NestedArrayLiterals.json rename to json/tests/testData/psi/NestedArrayLiterals.json diff --git a/plugins/json-tests/testData/psi/NestedArrayLiterals.txt b/json/tests/testData/psi/NestedArrayLiterals.txt similarity index 100% rename from plugins/json-tests/testData/psi/NestedArrayLiterals.txt rename to json/tests/testData/psi/NestedArrayLiterals.txt diff --git a/plugins/json-tests/testData/psi/NestedObjectLiterals.json b/json/tests/testData/psi/NestedObjectLiterals.json similarity index 100% rename from plugins/json-tests/testData/psi/NestedObjectLiterals.json rename to json/tests/testData/psi/NestedObjectLiterals.json diff --git a/plugins/json-tests/testData/psi/NestedObjectLiterals.txt b/json/tests/testData/psi/NestedObjectLiterals.txt similarity index 100% rename from plugins/json-tests/testData/psi/NestedObjectLiterals.txt rename to json/tests/testData/psi/NestedObjectLiterals.txt diff --git a/plugins/json-tests/testData/psi/TopLevelStringLiteral.json b/json/tests/testData/psi/TopLevelStringLiteral.json similarity index 100% rename from plugins/json-tests/testData/psi/TopLevelStringLiteral.json rename to json/tests/testData/psi/TopLevelStringLiteral.json diff --git a/plugins/json-tests/testData/psi/TopLevelStringLiteral.txt b/json/tests/testData/psi/TopLevelStringLiteral.txt similarity index 100% rename from plugins/json-tests/testData/psi/TopLevelStringLiteral.txt rename to json/tests/testData/psi/TopLevelStringLiteral.txt From d82e255be4ef64db2953602640fe96a5a06d28e8 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 19 Aug 2014 16:36:54 +0400 Subject: [PATCH 29/85] Move missing implementation classes from appcode-json to json --- json/gen/com/intellij/json/JsonParser.java | 54 ++++++++-------- .../json/psi/impl/JsonLiteralImpl.java | 6 +- .../json/psi/JsonLiteralManipulator.java | 25 ++++++++ .../intellij/json/psi/JsonPsiChangeUtils.java | 61 +++++++++++++++++++ .../intellij/json/psi/JsonPsiImplUtils.java | 26 ++++++++ .../json/psi/impl/JsonLiteralMixin.java | 33 ++++++++++ json/src/json.bnf | 5 +- 7 files changed, 181 insertions(+), 29 deletions(-) create mode 100644 json/src/com/intellij/json/psi/JsonLiteralManipulator.java create mode 100644 json/src/com/intellij/json/psi/JsonPsiChangeUtils.java create mode 100644 json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index c85f7321d2e7..59bb49f77587 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -73,8 +73,8 @@ public class JsonParser implements PsiParser { public static boolean array(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array")) return false; if (!nextTokenIs(builder_, L_BRACKET)) return false; - boolean result_ = false; - boolean pinned_ = false; + boolean result_; + boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = consumeToken(builder_, L_BRACKET); pinned_ = result_; // pin = 1 @@ -95,7 +95,7 @@ public class JsonParser implements PsiParser { // value static boolean array_element(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_element")) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = value(builder_, level_ + 1); exit_section_(builder_, level_, marker_, null, result_, false, bracket_or_comma_parser_); @@ -106,8 +106,8 @@ public class JsonParser implements PsiParser { // array_element (COMMA array_element)* static boolean array_elements(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_elements")) return false; - boolean result_ = false; - boolean pinned_ = false; + boolean result_; + boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = array_element(builder_, level_ + 1); pinned_ = result_; // pin = 1 @@ -131,8 +131,8 @@ public class JsonParser implements PsiParser { // COMMA array_element private static boolean array_elements_1_0(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_elements_1_0")) return false; - boolean result_ = false; - boolean pinned_ = false; + boolean result_; + boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = consumeToken(builder_, COMMA); pinned_ = result_; // pin = 1 @@ -146,7 +146,7 @@ public class JsonParser implements PsiParser { public static boolean boolean_literal(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "boolean_literal")) return false; if (!nextTokenIs(builder_, "", FALSE, TRUE)) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); result_ = consumeToken(builder_, TRUE); if (!result_) result_ = consumeToken(builder_, FALSE); @@ -158,7 +158,7 @@ public class JsonParser implements PsiParser { // !(R_CURLY|COMMA) static boolean brace_or_comma(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "brace_or_comma")) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_, level_, _NOT_, null); result_ = !brace_or_comma_0(builder_, level_ + 1); exit_section_(builder_, level_, marker_, null, result_, false, null); @@ -168,7 +168,7 @@ public class JsonParser implements PsiParser { // R_CURLY|COMMA private static boolean brace_or_comma_0(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "brace_or_comma_0")) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_); result_ = consumeToken(builder_, R_CURLY); if (!result_) result_ = consumeToken(builder_, COMMA); @@ -180,7 +180,7 @@ public class JsonParser implements PsiParser { // !(R_BRACKET|COMMA) static boolean bracket_or_comma(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "bracket_or_comma")) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_, level_, _NOT_, null); result_ = !bracket_or_comma_0(builder_, level_ + 1); exit_section_(builder_, level_, marker_, null, result_, false, null); @@ -190,7 +190,7 @@ public class JsonParser implements PsiParser { // R_BRACKET|COMMA private static boolean bracket_or_comma_0(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "bracket_or_comma_0")) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_); result_ = consumeToken(builder_, R_BRACKET); if (!result_) result_ = consumeToken(builder_, COMMA); @@ -203,7 +203,7 @@ public class JsonParser implements PsiParser { static boolean json(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "json")) return false; if (!nextTokenIs(builder_, "", L_BRACKET, L_CURLY)) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_); result_ = object(builder_, level_ + 1); if (!result_) result_ = array(builder_, level_ + 1); @@ -215,7 +215,7 @@ public class JsonParser implements PsiParser { // string_literal | number_literal | boolean_literal | null_literal public static boolean literal(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "literal")) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); result_ = string_literal(builder_, level_ + 1); if (!result_) result_ = number_literal(builder_, level_ + 1); @@ -230,7 +230,7 @@ public class JsonParser implements PsiParser { public static boolean null_literal(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "null_literal")) return false; if (!nextTokenIs(builder_, NULL)) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_); result_ = consumeToken(builder_, NULL); exit_section_(builder_, marker_, NULL_LITERAL, result_); @@ -242,7 +242,7 @@ public class JsonParser implements PsiParser { public static boolean number_literal(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "number_literal")) return false; if (!nextTokenIs(builder_, NUMBER)) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_); result_ = consumeToken(builder_, NUMBER); exit_section_(builder_, marker_, NUMBER_LITERAL, result_); @@ -254,8 +254,8 @@ public class JsonParser implements PsiParser { public static boolean object(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object")) return false; if (!nextTokenIs(builder_, L_CURLY)) return false; - boolean result_ = false; - boolean pinned_ = false; + boolean result_; + boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = consumeToken(builder_, L_CURLY); pinned_ = result_; // pin = 1 @@ -277,8 +277,8 @@ public class JsonParser implements PsiParser { static boolean properties(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "properties")) return false; if (!nextTokenIs(builder_, STRING)) return false; - boolean result_ = false; - boolean pinned_ = false; + boolean result_; + boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = property(builder_, level_ + 1); pinned_ = result_; // pin = 1 @@ -302,8 +302,8 @@ public class JsonParser implements PsiParser { // COMMA property private static boolean properties_1_0(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "properties_1_0")) return false; - boolean result_ = false; - boolean pinned_ = false; + boolean result_; + boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = consumeToken(builder_, COMMA); pinned_ = result_; // pin = 1 @@ -316,8 +316,8 @@ public class JsonParser implements PsiParser { // property_name COLON value public static boolean property(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property")) return false; - boolean result_ = false; - boolean pinned_ = false; + boolean result_; + boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, ""); result_ = property_name(builder_, level_ + 1); pinned_ = result_; // pin = 1 @@ -332,7 +332,7 @@ public class JsonParser implements PsiParser { public static boolean property_name(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property_name")) return false; if (!nextTokenIs(builder_, STRING)) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_); result_ = string_literal(builder_, level_ + 1); exit_section_(builder_, marker_, PROPERTY_NAME, result_); @@ -344,7 +344,7 @@ public class JsonParser implements PsiParser { public static boolean string_literal(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "string_literal")) return false; if (!nextTokenIs(builder_, STRING)) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_); result_ = consumeToken(builder_, STRING); exit_section_(builder_, marker_, STRING_LITERAL, result_); @@ -355,7 +355,7 @@ public class JsonParser implements PsiParser { // object | array | literal public static boolean value(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "value")) return false; - boolean result_ = false; + boolean result_; Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); result_ = object(builder_, level_ + 1); if (!result_) result_ = array(builder_, level_ + 1); diff --git a/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java index 54aac5d5ac67..7839c3be27a5 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java @@ -10,7 +10,7 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonLiteralImpl extends JsonValueImpl implements JsonLiteral { +public class JsonLiteralImpl extends JsonLiteralMixin implements JsonLiteral { public JsonLiteralImpl(ASTNode node) { super(node); @@ -21,4 +21,8 @@ public class JsonLiteralImpl extends JsonValueImpl implements JsonLiteral { else super.accept(visitor); } + public void isQuotedString() { + JsonPsiImplUtils.isQuotedString(this); + } + } diff --git a/json/src/com/intellij/json/psi/JsonLiteralManipulator.java b/json/src/com/intellij/json/psi/JsonLiteralManipulator.java new file mode 100644 index 000000000000..6ec36499dd9d --- /dev/null +++ b/json/src/com/intellij/json/psi/JsonLiteralManipulator.java @@ -0,0 +1,25 @@ +package com.intellij.json.psi; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.AbstractElementManipulator; +import com.intellij.psi.PsiFile; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; + +public class JsonLiteralManipulator extends AbstractElementManipulator { + + @Override + public JsonLiteral handleContentChange(@NotNull JsonLiteral element, @NotNull TextRange range, String newContent) throws IncorrectOperationException { + String text = "{\"\":\"" + newContent + "\"}"; + + final PsiFile dummy = JsonPsiChangeUtils.createDummyFile(element, text); + JsonProperty property = PsiTreeUtil.findChildOfType(dummy, JsonProperty.class); + assert property != null; + + JsonValue value = property.getValue(); + assert value instanceof JsonLiteral; + + return (JsonLiteral)element.replace(value); + } +} diff --git a/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java b/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java new file mode 100644 index 000000000000..ae34f258d4ec --- /dev/null +++ b/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java @@ -0,0 +1,61 @@ +package com.intellij.json.psi; + +import com.intellij.json.JsonElementTypes; +import com.intellij.lang.ASTNode; +import com.intellij.lang.Language; +import com.intellij.lang.LanguageParserDefinitions; +import com.intellij.lang.ParserDefinition; +import com.intellij.openapi.project.Project; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; +import com.intellij.psi.TokenType; +import com.intellij.json.JsonFile; +import org.jetbrains.annotations.NotNull; + +public class JsonPsiChangeUtils { + public static void removeCommaSeparatedFromList(final ASTNode myNode, final ASTNode parent) { + ASTNode from = myNode, to = myNode.getTreeNext(); + + boolean seenComma = false; + + ASTNode toCandidate = to; + while (toCandidate != null && toCandidate.getElementType() == TokenType.WHITE_SPACE) { + toCandidate = toCandidate.getTreeNext(); + } + + if (toCandidate != null && toCandidate.getElementType() == JsonElementTypes.COMMA) { + toCandidate = toCandidate.getTreeNext(); + to = toCandidate; + seenComma = true; + + if (to != null && to.getElementType() == TokenType.WHITE_SPACE) { + to = to.getTreeNext(); + } + } + + if (!seenComma) { + ASTNode treePrev = from.getTreePrev(); + + while (treePrev != null && treePrev.getElementType() == TokenType.WHITE_SPACE) { + from = treePrev; + treePrev = treePrev.getTreePrev(); + } + if (treePrev != null && treePrev.getElementType() == JsonElementTypes.COMMA) { + from = treePrev; + } + } + + parent.removeRange(from, to); + } + + @NotNull + public static PsiFile createDummyFile(JsonLiteral element, String text) { + Language language = element.getLanguage(); + ParserDefinition def = LanguageParserDefinitions.INSTANCE.forLanguage(language); + assert def != null; + Project project = element.getProject(); + final PsiFile dummyFile = PsiFileFactory.getInstance(project).createFileFromText("dummy.json", language, text, false, true); + assert dummyFile instanceof JsonFile; + return dummyFile; + } +} diff --git a/json/src/com/intellij/json/psi/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/JsonPsiImplUtils.java index 80cdceebbb6f..f0521f7d06b4 100644 --- a/json/src/com/intellij/json/psi/JsonPsiImplUtils.java +++ b/json/src/com/intellij/json/psi/JsonPsiImplUtils.java @@ -1,11 +1,37 @@ package com.intellij.json.psi; +import com.intellij.json.JsonElementTypes; +import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.Collection; public class JsonPsiImplUtils { @NotNull public static String getName(@NotNull JsonProperty property) { return StringUtil.unquoteString(property.getPropertyName().getText()); } + + public static boolean isQuotedString(@NotNull JsonLiteral literal) { + return literal.getNode().findChildByType(JsonElementTypes.STRING) != null; + } + + public static void delete(@NotNull JsonProperty property) { + final ASTNode myNode = property.getNode(); + JsonPsiChangeUtils.removeCommaSeparatedFromList(myNode, myNode.getTreeParent()); + } + + @Nullable + public static JsonProperty findProperty(@NotNull JsonObject object, @NotNull String name) { + Collection properties = PsiTreeUtil.findChildrenOfType(object, JsonProperty.class); + for (JsonProperty property : properties) { + if (property.getName().equals(name)) { + return property; + } + } + return null; + } } diff --git a/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java b/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java new file mode 100644 index 000000000000..3929b0e2a749 --- /dev/null +++ b/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java @@ -0,0 +1,33 @@ +package com.intellij.json.psi.impl; + +import com.intellij.json.psi.JsonLiteral; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiReference; +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; +import org.jetbrains.annotations.NotNull; + +abstract class JsonLiteralMixin extends JsonValueImpl implements JsonLiteral { + private final Object myRefLock = new Object(); + private volatile PsiReference[] myRefs; + private volatile long myModCount = -1; + + protected JsonLiteralMixin(ASTNode node) { + super(node); + } + + @NotNull + @Override + public PsiReference[] getReferences() { + final long count = getManager().getModificationTracker().getModificationCount(); + if (count != myModCount) { + synchronized (myRefLock) { + if (count != myModCount) { + myRefs = ReferenceProvidersRegistry.getReferencesFromProviders(this); + myModCount = count; + } + } + } + + return myRefs; + } +} diff --git a/json/src/json.bnf b/json/src/json.bnf index 51626b56bc5c..641a5c433cc5 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -67,7 +67,10 @@ number_literal ::= NUMBER boolean_literal ::= TRUE | FALSE null_literal ::= NULL -literal ::= string_literal | number_literal | boolean_literal | null_literal +literal ::= string_literal | number_literal | boolean_literal | null_literal { + methods=[isQuotedString] + mixin="com.intellij.json.psi.impl.JsonLiteralMixin" +} private bracket_or_comma ::= !(R_BRACKET|COMMA) private brace_or_comma ::= !(R_CURLY|COMMA) \ No newline at end of file From dd0146ccbf7c238520e0a1f9de644ee00540622d Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 19 Aug 2014 17:38:06 +0400 Subject: [PATCH 30/85] Make JSON grammars more similar and move extension points to json module * Rename JsonValue (json) to JsonPropertyValue (appcode-json) * Rename JsonParserTypes (appcode-json) to JsonElementTypes (json) * Rename JsonParserDefinitionBase to JsonParserDefinition * Rename AppCode.JSON language ID to JSON in extension points --- .../com/intellij/json/JsonElementTypes.java | 8 ++-- json/gen/com/intellij/json/JsonParser.java | 42 +++++++++---------- json/gen/com/intellij/json/psi/JsonArray.java | 4 +- .../com/intellij/json/psi/JsonLiteral.java | 4 +- .../gen/com/intellij/json/psi/JsonObject.java | 5 ++- .../com/intellij/json/psi/JsonProperty.java | 2 +- ...{JsonValue.java => JsonPropertyValue.java} | 2 +- .../com/intellij/json/psi/JsonVisitor.java | 14 +++---- .../intellij/json/psi/impl/JsonArrayImpl.java | 6 +-- .../json/psi/impl/JsonLiteralImpl.java | 4 +- .../json/psi/impl/JsonObjectImpl.java | 7 +++- .../json/psi/impl/JsonPropertyImpl.java | 4 +- ...ueImpl.java => JsonPropertyValueImpl.java} | 6 +-- json/src/META-INF/plugin.xml | 5 +++ .../breadcrumbs/JsonBreadcrumbsProvider.java | 6 +-- .../intellij/json/formatter/JsonBlock.java | 6 +-- .../json/psi/impl/JsonLiteralMixin.java | 2 +- json/src/json.bnf | 11 +++-- 18 files changed, 78 insertions(+), 60 deletions(-) rename json/gen/com/intellij/json/psi/{JsonValue.java => JsonPropertyValue.java} (77%) rename json/gen/com/intellij/json/psi/impl/{JsonValueImpl.java => JsonPropertyValueImpl.java} (79%) diff --git a/json/gen/com/intellij/json/JsonElementTypes.java b/json/gen/com/intellij/json/JsonElementTypes.java index 019f10dd51ec..bb0600fd06d7 100644 --- a/json/gen/com/intellij/json/JsonElementTypes.java +++ b/json/gen/com/intellij/json/JsonElementTypes.java @@ -16,8 +16,8 @@ public interface JsonElementTypes { IElementType OBJECT = new JsonElementType("OBJECT"); IElementType PROPERTY = new JsonElementType("PROPERTY"); IElementType PROPERTY_NAME = new JsonElementType("PROPERTY_NAME"); + IElementType PROPERTY_VALUE = new JsonElementType("PROPERTY_VALUE"); IElementType STRING_LITERAL = new JsonElementType("STRING_LITERAL"); - IElementType VALUE = new JsonElementType("VALUE"); IElementType COLON = new JsonTokenType(":"); IElementType COMMA = new JsonTokenType(","); @@ -59,12 +59,12 @@ public interface JsonElementTypes { else if (type == PROPERTY_NAME) { return new JsonPropertyNameImpl(node); } + else if (type == PROPERTY_VALUE) { + return new JsonPropertyValueImpl(node); + } else if (type == STRING_LITERAL) { return new JsonStringLiteralImpl(node); } - else if (type == VALUE) { - return new JsonValueImpl(node); - } throw new AssertionError("Unknown element type: " + type); } } diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 59bb49f77587..fbaa347218cc 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -44,12 +44,12 @@ public class JsonParser implements PsiParser { else if (root_ == PROPERTY_NAME) { result_ = property_name(builder_, 0); } + else if (root_ == PROPERTY_VALUE) { + result_ = property_value(builder_, 0); + } else if (root_ == STRING_LITERAL) { result_ = string_literal(builder_, 0); } - else if (root_ == VALUE) { - result_ = value(builder_, 0); - } else { result_ = parse_root_(root_, builder_, 0); } @@ -65,7 +65,7 @@ public class JsonParser implements PsiParser { create_token_set_(BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, NUMBER_LITERAL, STRING_LITERAL), create_token_set_(ARRAY, BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, - NUMBER_LITERAL, OBJECT, STRING_LITERAL, VALUE), + NUMBER_LITERAL, OBJECT, PROPERTY_VALUE, STRING_LITERAL), }; /* ********************************************************** */ @@ -92,12 +92,12 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // value + // property_value static boolean array_element(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_element")) return false; boolean result_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); - result_ = value(builder_, level_ + 1); + result_ = property_value(builder_, level_ + 1); exit_section_(builder_, level_, marker_, null, result_, false, bracket_or_comma_parser_); return result_; } @@ -313,7 +313,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // property_name COLON value + // property_name COLON property_value public static boolean property(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property")) return false; boolean result_; @@ -322,7 +322,7 @@ public class JsonParser implements PsiParser { result_ = property_name(builder_, level_ + 1); pinned_ = result_; // pin = 1 result_ = result_ && report_error_(builder_, consumeToken(builder_, COLON)); - result_ = pinned_ && value(builder_, level_ + 1) && result_; + result_ = pinned_ && property_value(builder_, level_ + 1) && result_; exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, brace_or_comma_parser_); return result_ || pinned_; } @@ -339,6 +339,19 @@ public class JsonParser implements PsiParser { return result_; } + /* ********************************************************** */ + // object | array | literal + public static boolean property_value(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "property_value")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); + result_ = object(builder_, level_ + 1); + if (!result_) result_ = array(builder_, level_ + 1); + if (!result_) result_ = literal(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, PROPERTY_VALUE, result_, false, null); + return result_; + } + /* ********************************************************** */ // STRING public static boolean string_literal(PsiBuilder builder_, int level_) { @@ -351,19 +364,6 @@ public class JsonParser implements PsiParser { return result_; } - /* ********************************************************** */ - // object | array | literal - public static boolean value(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "value")) return false; - boolean result_; - Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); - result_ = object(builder_, level_ + 1); - if (!result_) result_ = array(builder_, level_ + 1); - if (!result_) result_ = literal(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, VALUE, result_, false, null); - return result_; - } - final static Parser brace_or_comma_parser_ = new Parser() { public boolean parse(PsiBuilder builder_, int level_) { return brace_or_comma(builder_, level_ + 1); diff --git a/json/gen/com/intellij/json/psi/JsonArray.java b/json/gen/com/intellij/json/psi/JsonArray.java index a46a8b8ff047..b3a7c4750185 100644 --- a/json/gen/com/intellij/json/psi/JsonArray.java +++ b/json/gen/com/intellij/json/psi/JsonArray.java @@ -5,9 +5,9 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonArray extends JsonValue { +public interface JsonArray extends JsonPropertyValue { @NotNull - List getValueList(); + List getPropertyValueList(); } diff --git a/json/gen/com/intellij/json/psi/JsonLiteral.java b/json/gen/com/intellij/json/psi/JsonLiteral.java index b11833e7d7c0..9a1f35c672e2 100644 --- a/json/gen/com/intellij/json/psi/JsonLiteral.java +++ b/json/gen/com/intellij/json/psi/JsonLiteral.java @@ -5,6 +5,8 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonLiteral extends JsonValue { +public interface JsonLiteral extends JsonPropertyValue { + + boolean isQuotedString(); } diff --git a/json/gen/com/intellij/json/psi/JsonObject.java b/json/gen/com/intellij/json/psi/JsonObject.java index 308b0a6c9c7e..e35e318c6cfd 100644 --- a/json/gen/com/intellij/json/psi/JsonObject.java +++ b/json/gen/com/intellij/json/psi/JsonObject.java @@ -5,9 +5,12 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonObject extends JsonValue { +public interface JsonObject extends JsonPropertyValue { @NotNull List getPropertyList(); + @Nullable + JsonProperty findProperty(String name); + } diff --git a/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java index a62e40046445..f9609b31d9f2 100644 --- a/json/gen/com/intellij/json/psi/JsonProperty.java +++ b/json/gen/com/intellij/json/psi/JsonProperty.java @@ -11,7 +11,7 @@ public interface JsonProperty extends PsiElement { JsonPropertyName getPropertyName(); @Nullable - JsonValue getValue(); + JsonPropertyValue getPropertyValue(); @NotNull String getName(); diff --git a/json/gen/com/intellij/json/psi/JsonValue.java b/json/gen/com/intellij/json/psi/JsonPropertyValue.java similarity index 77% rename from json/gen/com/intellij/json/psi/JsonValue.java rename to json/gen/com/intellij/json/psi/JsonPropertyValue.java index 46995ec879b3..b590975f449e 100644 --- a/json/gen/com/intellij/json/psi/JsonValue.java +++ b/json/gen/com/intellij/json/psi/JsonPropertyValue.java @@ -5,6 +5,6 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonValue extends PsiElement { +public interface JsonPropertyValue extends PsiElement { } diff --git a/json/gen/com/intellij/json/psi/JsonVisitor.java b/json/gen/com/intellij/json/psi/JsonVisitor.java index cdb8755ffbaa..a5c4f10a1ff8 100644 --- a/json/gen/com/intellij/json/psi/JsonVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonVisitor.java @@ -8,7 +8,7 @@ import com.intellij.psi.PsiElement; public class JsonVisitor extends PsiElementVisitor { public void visitArray(@NotNull JsonArray o) { - visitValue(o); + visitPropertyValue(o); } public void visitBooleanLiteral(@NotNull JsonBooleanLiteral o) { @@ -16,7 +16,7 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitLiteral(@NotNull JsonLiteral o) { - visitValue(o); + visitPropertyValue(o); } public void visitNullLiteral(@NotNull JsonNullLiteral o) { @@ -28,7 +28,7 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitObject(@NotNull JsonObject o) { - visitValue(o); + visitPropertyValue(o); } public void visitProperty(@NotNull JsonProperty o) { @@ -39,12 +39,12 @@ public class JsonVisitor extends PsiElementVisitor { visitPsiElement(o); } - public void visitStringLiteral(@NotNull JsonStringLiteral o) { - visitLiteral(o); + public void visitPropertyValue(@NotNull JsonPropertyValue o) { + visitPsiElement(o); } - public void visitValue(@NotNull JsonValue o) { - visitPsiElement(o); + public void visitStringLiteral(@NotNull JsonStringLiteral o) { + visitLiteral(o); } public void visitPsiElement(@NotNull PsiElement o) { diff --git a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java index 54a96032a755..c5b6b8dd86da 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java @@ -10,7 +10,7 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonArrayImpl extends JsonValueImpl implements JsonArray { +public class JsonArrayImpl extends JsonPropertyValueImpl implements JsonArray { public JsonArrayImpl(ASTNode node) { super(node); @@ -23,8 +23,8 @@ public class JsonArrayImpl extends JsonValueImpl implements JsonArray { @Override @NotNull - public List getValueList() { - return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonValue.class); + public List getPropertyValueList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonPropertyValue.class); } } diff --git a/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java index 7839c3be27a5..f56e64767964 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java @@ -21,8 +21,8 @@ public class JsonLiteralImpl extends JsonLiteralMixin implements JsonLiteral { else super.accept(visitor); } - public void isQuotedString() { - JsonPsiImplUtils.isQuotedString(this); + public boolean isQuotedString() { + return JsonPsiImplUtils.isQuotedString(this); } } diff --git a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java index c2e5b3278e8c..482fcdcf9fd5 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java @@ -10,7 +10,7 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonObjectImpl extends JsonValueImpl implements JsonObject { +public class JsonObjectImpl extends JsonPropertyValueImpl implements JsonObject { public JsonObjectImpl(ASTNode node) { super(node); @@ -27,4 +27,9 @@ public class JsonObjectImpl extends JsonValueImpl implements JsonObject { return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonProperty.class); } + @Nullable + public JsonProperty findProperty(String name) { + return JsonPsiImplUtils.findProperty(this, name); + } + } diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java index 5265b1c24605..98425f7964e7 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java @@ -30,8 +30,8 @@ public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProper @Override @Nullable - public JsonValue getValue() { - return findChildByClass(JsonValue.class); + public JsonPropertyValue getPropertyValue() { + return findChildByClass(JsonPropertyValue.class); } @NotNull diff --git a/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyValueImpl.java similarity index 79% rename from json/gen/com/intellij/json/psi/impl/JsonValueImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonPropertyValueImpl.java index 28bcf95a47a6..008f25605669 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyValueImpl.java @@ -11,14 +11,14 @@ import static com.intellij.json.JsonElementTypes.*; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.json.psi.*; -public class JsonValueImpl extends ASTWrapperPsiElement implements JsonValue { +public class JsonPropertyValueImpl extends ASTWrapperPsiElement implements JsonPropertyValue { - public JsonValueImpl(ASTNode node) { + public JsonPropertyValueImpl(ASTNode node) { super(node); } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitValue(this); + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitPropertyValue(this); else super.accept(visitor); } diff --git a/json/src/META-INF/plugin.xml b/json/src/META-INF/plugin.xml index 5f6952c73c6b..848542a62665 100644 --- a/json/src/META-INF/plugin.xml +++ b/json/src/META-INF/plugin.xml @@ -40,5 +40,10 @@ + + + + \ No newline at end of file diff --git a/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java b/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java index e41f316e08bb..f601e5b19d76 100644 --- a/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java +++ b/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java @@ -1,12 +1,12 @@ package com.intellij.json.breadcrumbs; import com.intellij.json.JsonLanguage; +import com.intellij.json.psi.JsonPropertyValue; import com.intellij.lang.Language; import com.intellij.psi.PsiElement; import com.intellij.xml.breadcrumbs.BreadcrumbsInfoProvider; import com.intellij.json.psi.JsonArray; import com.intellij.json.psi.JsonProperty; -import com.intellij.json.psi.JsonValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -35,7 +35,7 @@ public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider { return ((JsonProperty)e).getName(); } else if (isArrayElement(e)) { - List elements = ((JsonArray)e.getParent()).getValueList(); + List elements = ((JsonArray)e.getParent()).getPropertyValueList(); for (int i = 0; i < elements.size(); i++) { if (e == elements.get(i)) { return String.valueOf(i); @@ -56,6 +56,6 @@ public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider { } private static boolean isArrayElement(PsiElement element) { - return element instanceof JsonValue && element.getParent() instanceof JsonArray; + return element instanceof JsonPropertyValue && element.getParent() instanceof JsonArray; } } diff --git a/json/src/com/intellij/json/formatter/JsonBlock.java b/json/src/com/intellij/json/formatter/JsonBlock.java index 69d6a89fb12e..ab5291785891 100644 --- a/json/src/com/intellij/json/formatter/JsonBlock.java +++ b/json/src/com/intellij/json/formatter/JsonBlock.java @@ -2,6 +2,7 @@ package com.intellij.json.formatter; import com.intellij.formatting.*; import com.intellij.json.JsonParserDefinition; +import com.intellij.json.psi.JsonPropertyValue; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; @@ -12,7 +13,6 @@ import com.intellij.psi.tree.TokenSet; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; import com.intellij.json.psi.JsonProperty; -import com.intellij.json.psi.JsonValue; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -100,7 +100,7 @@ public class JsonBlock implements ASTBlock { alignment = myChildAlignment; indent = Indent.getNormalIndent(); } - if (myNode.getElementType() == PROPERTY && childPsiElement instanceof JsonValue) { + if (myNode.getElementType() == PROPERTY && childPsiElement instanceof JsonPropertyValue) { wrap = Wrap.createWrap(WrapType.NORMAL, true); indent = Indent.getNormalIndent(); } @@ -163,7 +163,7 @@ public class JsonBlock implements ASTBlock { return lastChildNode != null && lastChildNode.getElementType() == R_BRACKET; } else if (myPsiElement instanceof JsonProperty) { - return ((JsonProperty)myPsiElement).getValue() != null; + return ((JsonProperty)myPsiElement).getPropertyValue() != null; } return false; } diff --git a/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java b/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java index 3929b0e2a749..b123a2c88486 100644 --- a/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java +++ b/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java @@ -6,7 +6,7 @@ import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; import org.jetbrains.annotations.NotNull; -abstract class JsonLiteralMixin extends JsonValueImpl implements JsonLiteral { +abstract class JsonLiteralMixin extends JsonPropertyImpl implements JsonLiteral { private final Object myRefLock = new Object(); private volatile PsiReference[] myRefs; private volatile long myModCount = -1; diff --git a/json/src/json.bnf b/json/src/json.bnf index 641a5c433cc5..655ed407e2f0 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -37,7 +37,7 @@ TEXT='regexp:\w+' ] - extends("object|array|literal")=value + extends("object|array|literal")=property_value extends("string_literal|number_literal|boolean_literal|null_literal")=literal } @@ -45,9 +45,12 @@ json ::= object | array object ::= L_CURLY [properties] R_CURLY { pin=1 + methods=[ + findProperty + ] } private properties ::= property (COMMA property)* { pin(".*")=1 } -property ::= property_name COLON value { +property ::= property_name COLON property_value { pin = 1 methods=[ getName ] recoverWhile = brace_or_comma @@ -55,12 +58,12 @@ property ::= property_name COLON value { array ::= L_BRACKET [array_elements] R_BRACKET { pin=1 } private array_elements ::= array_element (COMMA array_element)* { pin(".*")=1 } -private array_element ::= value { +private array_element ::= property_value { recoverWhile = bracket_or_comma } property_name ::= string_literal -value ::= object | array | literal +property_value ::= object | array | literal string_literal ::= STRING number_literal ::= NUMBER From 5361bfb1a99c25139938c2886e1c07abeb0f7614 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 19 Aug 2014 21:12:23 +0400 Subject: [PATCH 31/85] Rename JSON grammar rules and PSI elements --- .../com/intellij/json/JsonElementTypes.java | 8 +- json/gen/com/intellij/json/JsonParser.java | 162 +++++++++--------- json/gen/com/intellij/json/psi/JsonArray.java | 4 +- .../com/intellij/json/psi/JsonLiteral.java | 2 +- .../gen/com/intellij/json/psi/JsonObject.java | 2 +- .../com/intellij/json/psi/JsonProperty.java | 8 +- .../intellij/json/psi/JsonPropertyName.java | 2 +- ...{JsonPropertyValue.java => JsonValue.java} | 2 +- .../com/intellij/json/psi/JsonVisitor.java | 14 +- .../intellij/json/psi/impl/JsonArrayImpl.java | 6 +- .../json/psi/impl/JsonObjectImpl.java | 2 +- .../json/psi/impl/JsonPropertyImpl.java | 16 +- .../json/psi/impl/JsonPropertyNameImpl.java | 4 +- ...pertyValueImpl.java => JsonValueImpl.java} | 6 +- .../breadcrumbs/JsonBreadcrumbsProvider.java | 6 +- .../intellij/json/formatter/JsonBlock.java | 6 +- .../intellij/json/psi/JsonPsiImplUtils.java | 2 +- json/src/json.bnf | 36 ++-- .../com/intellij/json/JsonCompletionTest.java | 2 +- .../com/intellij/json/JsonFormattingTest.java | 2 +- .../com/intellij/json/JsonParsingTest.java | 2 +- .../testData/psi/NestedObjectLiterals.txt | 9 +- 22 files changed, 153 insertions(+), 150 deletions(-) rename json/gen/com/intellij/json/psi/{JsonPropertyValue.java => JsonValue.java} (77%) rename json/gen/com/intellij/json/psi/impl/{JsonPropertyValueImpl.java => JsonValueImpl.java} (79%) diff --git a/json/gen/com/intellij/json/JsonElementTypes.java b/json/gen/com/intellij/json/JsonElementTypes.java index bb0600fd06d7..019f10dd51ec 100644 --- a/json/gen/com/intellij/json/JsonElementTypes.java +++ b/json/gen/com/intellij/json/JsonElementTypes.java @@ -16,8 +16,8 @@ public interface JsonElementTypes { IElementType OBJECT = new JsonElementType("OBJECT"); IElementType PROPERTY = new JsonElementType("PROPERTY"); IElementType PROPERTY_NAME = new JsonElementType("PROPERTY_NAME"); - IElementType PROPERTY_VALUE = new JsonElementType("PROPERTY_VALUE"); IElementType STRING_LITERAL = new JsonElementType("STRING_LITERAL"); + IElementType VALUE = new JsonElementType("VALUE"); IElementType COLON = new JsonTokenType(":"); IElementType COMMA = new JsonTokenType(","); @@ -59,12 +59,12 @@ public interface JsonElementTypes { else if (type == PROPERTY_NAME) { return new JsonPropertyNameImpl(node); } - else if (type == PROPERTY_VALUE) { - return new JsonPropertyValueImpl(node); - } else if (type == STRING_LITERAL) { return new JsonStringLiteralImpl(node); } + else if (type == VALUE) { + return new JsonValueImpl(node); + } throw new AssertionError("Unknown element type: " + type); } } diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index fbaa347218cc..30f1f246b0c2 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -44,12 +44,12 @@ public class JsonParser implements PsiParser { else if (root_ == PROPERTY_NAME) { result_ = property_name(builder_, 0); } - else if (root_ == PROPERTY_VALUE) { - result_ = property_value(builder_, 0); - } else if (root_ == STRING_LITERAL) { result_ = string_literal(builder_, 0); } + else if (root_ == VALUE) { + result_ = value(builder_, 0); + } else { result_ = parse_root_(root_, builder_, 0); } @@ -65,11 +65,11 @@ public class JsonParser implements PsiParser { create_token_set_(BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, NUMBER_LITERAL, STRING_LITERAL), create_token_set_(ARRAY, BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, - NUMBER_LITERAL, OBJECT, PROPERTY_VALUE, STRING_LITERAL), + NUMBER_LITERAL, OBJECT, STRING_LITERAL, VALUE), }; /* ********************************************************** */ - // L_BRACKET [array_elements] R_BRACKET + // '[' [array_elements] ']' public static boolean array(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array")) return false; if (!nextTokenIs(builder_, L_BRACKET)) return false; @@ -92,18 +92,18 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // property_value + // value static boolean array_element(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_element")) return false; boolean result_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); - result_ = property_value(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, null, result_, false, bracket_or_comma_parser_); + result_ = value(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, false, not_bracket_or_comma_parser_); return result_; } /* ********************************************************** */ - // array_element (COMMA array_element)* + // array_element (',' array_element)* static boolean array_elements(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_elements")) return false; boolean result_; @@ -116,7 +116,7 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } - // (COMMA array_element)* + // (',' array_element)* private static boolean array_elements_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_elements_1")) return false; int pos_ = current_position_(builder_); @@ -128,7 +128,7 @@ public class JsonParser implements PsiParser { return true; } - // COMMA array_element + // ',' array_element private static boolean array_elements_1_0(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_elements_1_0")) return false; boolean result_; @@ -154,50 +154,6 @@ public class JsonParser implements PsiParser { return result_; } - /* ********************************************************** */ - // !(R_CURLY|COMMA) - static boolean brace_or_comma(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "brace_or_comma")) return false; - boolean result_; - Marker marker_ = enter_section_(builder_, level_, _NOT_, null); - result_ = !brace_or_comma_0(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, null, result_, false, null); - return result_; - } - - // R_CURLY|COMMA - private static boolean brace_or_comma_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "brace_or_comma_0")) return false; - boolean result_; - Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, R_CURLY); - if (!result_) result_ = consumeToken(builder_, COMMA); - exit_section_(builder_, marker_, null, result_); - return result_; - } - - /* ********************************************************** */ - // !(R_BRACKET|COMMA) - static boolean bracket_or_comma(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "bracket_or_comma")) return false; - boolean result_; - Marker marker_ = enter_section_(builder_, level_, _NOT_, null); - result_ = !bracket_or_comma_0(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, null, result_, false, null); - return result_; - } - - // R_BRACKET|COMMA - private static boolean bracket_or_comma_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "bracket_or_comma_0")) return false; - boolean result_; - Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, R_BRACKET); - if (!result_) result_ = consumeToken(builder_, COMMA); - exit_section_(builder_, marker_, null, result_); - return result_; - } - /* ********************************************************** */ // object | array static boolean json(PsiBuilder builder_, int level_) { @@ -225,6 +181,50 @@ public class JsonParser implements PsiParser { return result_; } + /* ********************************************************** */ + // !('}'|',') + static boolean not_brace_or_comma(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "not_brace_or_comma")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_, level_, _NOT_, null); + result_ = !not_brace_or_comma_0(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, false, null); + return result_; + } + + // '}'|',' + private static boolean not_brace_or_comma_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "not_brace_or_comma_0")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, R_CURLY); + if (!result_) result_ = consumeToken(builder_, COMMA); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + /* ********************************************************** */ + // !(']'|',') + static boolean not_bracket_or_comma(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "not_bracket_or_comma")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_, level_, _NOT_, null); + result_ = !not_bracket_or_comma_0(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, false, null); + return result_; + } + + // ']'|',' + private static boolean not_bracket_or_comma_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "not_bracket_or_comma_0")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, R_BRACKET); + if (!result_) result_ = consumeToken(builder_, COMMA); + exit_section_(builder_, marker_, null, result_); + return result_; + } + /* ********************************************************** */ // NULL public static boolean null_literal(PsiBuilder builder_, int level_) { @@ -250,7 +250,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // L_CURLY [properties] R_CURLY + // '{' [properties] '}' public static boolean object(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object")) return false; if (!nextTokenIs(builder_, L_CURLY)) return false; @@ -273,7 +273,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // property (COMMA property)* + // property (',' property)* static boolean properties(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "properties")) return false; if (!nextTokenIs(builder_, STRING)) return false; @@ -287,7 +287,7 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } - // (COMMA property)* + // (',' property)* private static boolean properties_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "properties_1")) return false; int pos_ = current_position_(builder_); @@ -299,7 +299,7 @@ public class JsonParser implements PsiParser { return true; } - // COMMA property + // ',' property private static boolean properties_1_0(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "properties_1_0")) return false; boolean result_; @@ -313,7 +313,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // property_name COLON property_value + // property_name ':' value public static boolean property(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property")) return false; boolean result_; @@ -322,36 +322,23 @@ public class JsonParser implements PsiParser { result_ = property_name(builder_, level_ + 1); pinned_ = result_; // pin = 1 result_ = result_ && report_error_(builder_, consumeToken(builder_, COLON)); - result_ = pinned_ && property_value(builder_, level_ + 1) && result_; - exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, brace_or_comma_parser_); + result_ = pinned_ && value(builder_, level_ + 1) && result_; + exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, not_brace_or_comma_parser_); return result_ || pinned_; } /* ********************************************************** */ - // string_literal + // STRING public static boolean property_name(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property_name")) return false; if (!nextTokenIs(builder_, STRING)) return false; boolean result_; Marker marker_ = enter_section_(builder_); - result_ = string_literal(builder_, level_ + 1); + result_ = consumeToken(builder_, STRING); exit_section_(builder_, marker_, PROPERTY_NAME, result_); return result_; } - /* ********************************************************** */ - // object | array | literal - public static boolean property_value(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "property_value")) return false; - boolean result_; - Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); - result_ = object(builder_, level_ + 1); - if (!result_) result_ = array(builder_, level_ + 1); - if (!result_) result_ = literal(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, PROPERTY_VALUE, result_, false, null); - return result_; - } - /* ********************************************************** */ // STRING public static boolean string_literal(PsiBuilder builder_, int level_) { @@ -364,14 +351,27 @@ public class JsonParser implements PsiParser { return result_; } - final static Parser brace_or_comma_parser_ = new Parser() { + /* ********************************************************** */ + // object | array | literal + public static boolean value(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "value")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); + result_ = object(builder_, level_ + 1); + if (!result_) result_ = array(builder_, level_ + 1); + if (!result_) result_ = literal(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, VALUE, result_, false, null); + return result_; + } + + final static Parser not_brace_or_comma_parser_ = new Parser() { public boolean parse(PsiBuilder builder_, int level_) { - return brace_or_comma(builder_, level_ + 1); + return not_brace_or_comma(builder_, level_ + 1); } }; - final static Parser bracket_or_comma_parser_ = new Parser() { + final static Parser not_bracket_or_comma_parser_ = new Parser() { public boolean parse(PsiBuilder builder_, int level_) { - return bracket_or_comma(builder_, level_ + 1); + return not_bracket_or_comma(builder_, level_ + 1); } }; } diff --git a/json/gen/com/intellij/json/psi/JsonArray.java b/json/gen/com/intellij/json/psi/JsonArray.java index b3a7c4750185..a46a8b8ff047 100644 --- a/json/gen/com/intellij/json/psi/JsonArray.java +++ b/json/gen/com/intellij/json/psi/JsonArray.java @@ -5,9 +5,9 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonArray extends JsonPropertyValue { +public interface JsonArray extends JsonValue { @NotNull - List getPropertyValueList(); + List getValueList(); } diff --git a/json/gen/com/intellij/json/psi/JsonLiteral.java b/json/gen/com/intellij/json/psi/JsonLiteral.java index 9a1f35c672e2..6e0eb7c7c32e 100644 --- a/json/gen/com/intellij/json/psi/JsonLiteral.java +++ b/json/gen/com/intellij/json/psi/JsonLiteral.java @@ -5,7 +5,7 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonLiteral extends JsonPropertyValue { +public interface JsonLiteral extends JsonValue { boolean isQuotedString(); diff --git a/json/gen/com/intellij/json/psi/JsonObject.java b/json/gen/com/intellij/json/psi/JsonObject.java index e35e318c6cfd..139b72b25782 100644 --- a/json/gen/com/intellij/json/psi/JsonObject.java +++ b/json/gen/com/intellij/json/psi/JsonObject.java @@ -5,7 +5,7 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonObject extends JsonPropertyValue { +public interface JsonObject extends JsonValue { @NotNull List getPropertyList(); diff --git a/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java index f9609b31d9f2..305b5719b375 100644 --- a/json/gen/com/intellij/json/psi/JsonProperty.java +++ b/json/gen/com/intellij/json/psi/JsonProperty.java @@ -7,13 +7,13 @@ import com.intellij.psi.PsiElement; public interface JsonProperty extends PsiElement { - @NotNull - JsonPropertyName getPropertyName(); - @Nullable - JsonPropertyValue getPropertyValue(); + JsonValue getValue(); @NotNull String getName(); + @NotNull + JsonPropertyName getNameElement(); + } diff --git a/json/gen/com/intellij/json/psi/JsonPropertyName.java b/json/gen/com/intellij/json/psi/JsonPropertyName.java index 986dfc47e55f..598f257e1900 100644 --- a/json/gen/com/intellij/json/psi/JsonPropertyName.java +++ b/json/gen/com/intellij/json/psi/JsonPropertyName.java @@ -8,6 +8,6 @@ import com.intellij.psi.PsiElement; public interface JsonPropertyName extends PsiElement { @NotNull - JsonStringLiteral getStringLiteral(); + PsiElement getString(); } diff --git a/json/gen/com/intellij/json/psi/JsonPropertyValue.java b/json/gen/com/intellij/json/psi/JsonValue.java similarity index 77% rename from json/gen/com/intellij/json/psi/JsonPropertyValue.java rename to json/gen/com/intellij/json/psi/JsonValue.java index b590975f449e..46995ec879b3 100644 --- a/json/gen/com/intellij/json/psi/JsonPropertyValue.java +++ b/json/gen/com/intellij/json/psi/JsonValue.java @@ -5,6 +5,6 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonPropertyValue extends PsiElement { +public interface JsonValue extends PsiElement { } diff --git a/json/gen/com/intellij/json/psi/JsonVisitor.java b/json/gen/com/intellij/json/psi/JsonVisitor.java index a5c4f10a1ff8..cdb8755ffbaa 100644 --- a/json/gen/com/intellij/json/psi/JsonVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonVisitor.java @@ -8,7 +8,7 @@ import com.intellij.psi.PsiElement; public class JsonVisitor extends PsiElementVisitor { public void visitArray(@NotNull JsonArray o) { - visitPropertyValue(o); + visitValue(o); } public void visitBooleanLiteral(@NotNull JsonBooleanLiteral o) { @@ -16,7 +16,7 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitLiteral(@NotNull JsonLiteral o) { - visitPropertyValue(o); + visitValue(o); } public void visitNullLiteral(@NotNull JsonNullLiteral o) { @@ -28,7 +28,7 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitObject(@NotNull JsonObject o) { - visitPropertyValue(o); + visitValue(o); } public void visitProperty(@NotNull JsonProperty o) { @@ -39,14 +39,14 @@ public class JsonVisitor extends PsiElementVisitor { visitPsiElement(o); } - public void visitPropertyValue(@NotNull JsonPropertyValue o) { - visitPsiElement(o); - } - public void visitStringLiteral(@NotNull JsonStringLiteral o) { visitLiteral(o); } + public void visitValue(@NotNull JsonValue o) { + visitPsiElement(o); + } + public void visitPsiElement(@NotNull PsiElement o) { visitElement(o); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java index c5b6b8dd86da..54a96032a755 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java @@ -10,7 +10,7 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonArrayImpl extends JsonPropertyValueImpl implements JsonArray { +public class JsonArrayImpl extends JsonValueImpl implements JsonArray { public JsonArrayImpl(ASTNode node) { super(node); @@ -23,8 +23,8 @@ public class JsonArrayImpl extends JsonPropertyValueImpl implements JsonArray { @Override @NotNull - public List getPropertyValueList() { - return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonPropertyValue.class); + public List getValueList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonValue.class); } } diff --git a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java index 482fcdcf9fd5..ec3d4844a774 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java @@ -10,7 +10,7 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonObjectImpl extends JsonPropertyValueImpl implements JsonObject { +public class JsonObjectImpl extends JsonValueImpl implements JsonObject { public JsonObjectImpl(ASTNode node) { super(node); diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java index 98425f7964e7..fc8f319a2192 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java @@ -22,16 +22,10 @@ public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProper else super.accept(visitor); } - @Override - @NotNull - public JsonPropertyName getPropertyName() { - return findNotNullChildByClass(JsonPropertyName.class); - } - @Override @Nullable - public JsonPropertyValue getPropertyValue() { - return findChildByClass(JsonPropertyValue.class); + public JsonValue getValue() { + return findChildByClass(JsonValue.class); } @NotNull @@ -39,4 +33,10 @@ public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProper return JsonPsiImplUtils.getName(this); } + @Override + @NotNull + public JsonPropertyName getNameElement() { + return findNotNullChildByClass(JsonPropertyName.class); + } + } diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java index 39f9573ee6c8..0545b3cc2e73 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java @@ -24,8 +24,8 @@ public class JsonPropertyNameImpl extends ASTWrapperPsiElement implements JsonPr @Override @NotNull - public JsonStringLiteral getStringLiteral() { - return findNotNullChildByClass(JsonStringLiteral.class); + public PsiElement getString() { + return findNotNullChildByType(STRING); } } diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyValueImpl.java b/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java similarity index 79% rename from json/gen/com/intellij/json/psi/impl/JsonPropertyValueImpl.java rename to json/gen/com/intellij/json/psi/impl/JsonValueImpl.java index 008f25605669..28bcf95a47a6 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyValueImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java @@ -11,14 +11,14 @@ import static com.intellij.json.JsonElementTypes.*; import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.json.psi.*; -public class JsonPropertyValueImpl extends ASTWrapperPsiElement implements JsonPropertyValue { +public class JsonValueImpl extends ASTWrapperPsiElement implements JsonValue { - public JsonPropertyValueImpl(ASTNode node) { + public JsonValueImpl(ASTNode node) { super(node); } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitPropertyValue(this); + if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitValue(this); else super.accept(visitor); } diff --git a/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java b/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java index f601e5b19d76..4f76b9a3bfba 100644 --- a/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java +++ b/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java @@ -1,7 +1,7 @@ package com.intellij.json.breadcrumbs; import com.intellij.json.JsonLanguage; -import com.intellij.json.psi.JsonPropertyValue; +import com.intellij.json.psi.JsonValue; import com.intellij.lang.Language; import com.intellij.psi.PsiElement; import com.intellij.xml.breadcrumbs.BreadcrumbsInfoProvider; @@ -35,7 +35,7 @@ public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider { return ((JsonProperty)e).getName(); } else if (isArrayElement(e)) { - List elements = ((JsonArray)e.getParent()).getPropertyValueList(); + List elements = ((JsonArray)e.getParent()).getValueList(); for (int i = 0; i < elements.size(); i++) { if (e == elements.get(i)) { return String.valueOf(i); @@ -56,6 +56,6 @@ public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider { } private static boolean isArrayElement(PsiElement element) { - return element instanceof JsonPropertyValue && element.getParent() instanceof JsonArray; + return element instanceof JsonValue && element.getParent() instanceof JsonArray; } } diff --git a/json/src/com/intellij/json/formatter/JsonBlock.java b/json/src/com/intellij/json/formatter/JsonBlock.java index ab5291785891..70b4538d1e50 100644 --- a/json/src/com/intellij/json/formatter/JsonBlock.java +++ b/json/src/com/intellij/json/formatter/JsonBlock.java @@ -2,7 +2,7 @@ package com.intellij.json.formatter; import com.intellij.formatting.*; import com.intellij.json.JsonParserDefinition; -import com.intellij.json.psi.JsonPropertyValue; +import com.intellij.json.psi.JsonValue; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; @@ -100,7 +100,7 @@ public class JsonBlock implements ASTBlock { alignment = myChildAlignment; indent = Indent.getNormalIndent(); } - if (myNode.getElementType() == PROPERTY && childPsiElement instanceof JsonPropertyValue) { + if (myNode.getElementType() == PROPERTY && childPsiElement instanceof JsonValue) { wrap = Wrap.createWrap(WrapType.NORMAL, true); indent = Indent.getNormalIndent(); } @@ -163,7 +163,7 @@ public class JsonBlock implements ASTBlock { return lastChildNode != null && lastChildNode.getElementType() == R_BRACKET; } else if (myPsiElement instanceof JsonProperty) { - return ((JsonProperty)myPsiElement).getPropertyValue() != null; + return ((JsonProperty)myPsiElement).getValue() != null; } return false; } diff --git a/json/src/com/intellij/json/psi/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/JsonPsiImplUtils.java index f0521f7d06b4..50d07624bdec 100644 --- a/json/src/com/intellij/json/psi/JsonPsiImplUtils.java +++ b/json/src/com/intellij/json/psi/JsonPsiImplUtils.java @@ -12,7 +12,7 @@ import java.util.Collection; public class JsonPsiImplUtils { @NotNull public static String getName(@NotNull JsonProperty property) { - return StringUtil.unquoteString(property.getPropertyName().getText()); + return StringUtil.unquoteString(property.getNameElement().getText()); } public static boolean isQuotedString(@NotNull JsonLiteral literal) { diff --git a/json/src/json.bnf b/json/src/json.bnf index 655ed407e2f0..09bb42dc71ab 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -37,33 +37,37 @@ TEXT='regexp:\w+' ] - extends("object|array|literal")=property_value + extends("object|array|literal")=value extends("string_literal|number_literal|boolean_literal|null_literal")=literal } json ::= object | array -object ::= L_CURLY [properties] R_CURLY { +object ::= '{' [properties] '}' { pin=1 methods=[ findProperty ] } -private properties ::= property (COMMA property)* { pin(".*")=1 } -property ::= property_name COLON property_value { + +private properties ::= property (',' property)* { pin(".*")=1 } +property ::= property_name ':' value { pin = 1 - methods=[ getName ] - recoverWhile = brace_or_comma + methods=[ + getName + NameElement="property_name" + ] + recoverWhile = not_brace_or_comma } +property_name ::= STRING -array ::= L_BRACKET [array_elements] R_BRACKET { pin=1 } -private array_elements ::= array_element (COMMA array_element)* { pin(".*")=1 } -private array_element ::= property_value { - recoverWhile = bracket_or_comma +array ::= '[' [array_elements] ']' { + pin=1 +} +private array_elements ::= array_element (',' array_element)* { pin(".*")=1 } +private array_element ::= value { + recoverWhile = not_bracket_or_comma } - -property_name ::= string_literal -property_value ::= object | array | literal string_literal ::= STRING number_literal ::= NUMBER @@ -74,6 +78,8 @@ literal ::= string_literal | number_literal | boolean_literal | null_literal { methods=[isQuotedString] mixin="com.intellij.json.psi.impl.JsonLiteralMixin" } +value ::= object | array | literal -private bracket_or_comma ::= !(R_BRACKET|COMMA) -private brace_or_comma ::= !(R_CURLY|COMMA) \ No newline at end of file +// Recoveries +private not_bracket_or_comma ::= !(']'|',') +private not_brace_or_comma ::= !('}'|',') \ No newline at end of file diff --git a/json/tests/test/com/intellij/json/JsonCompletionTest.java b/json/tests/test/com/intellij/json/JsonCompletionTest.java index 94a1ab744084..1f9727593ce7 100644 --- a/json/tests/test/com/intellij/json/JsonCompletionTest.java +++ b/json/tests/test/com/intellij/json/JsonCompletionTest.java @@ -18,7 +18,7 @@ public class JsonCompletionTest extends CodeInsightFixtureTestCase { } @Override protected String getBasePath() { - return "/plugins/json-tests/testData/completion"; + return "/json/tests/testData/completion"; } diff --git a/json/tests/test/com/intellij/json/JsonFormattingTest.java b/json/tests/test/com/intellij/json/JsonFormattingTest.java index 81b75709e94a..3f3be60c551b 100644 --- a/json/tests/test/com/intellij/json/JsonFormattingTest.java +++ b/json/tests/test/com/intellij/json/JsonFormattingTest.java @@ -26,7 +26,7 @@ public class JsonFormattingTest extends FormatterTestCase { // Why the heck do I specify path to testData in each kind of test differently? @Override protected String getTestDataPath() { - return PlatformTestUtil.getCommunityPath() + "/plugins/json-tests/testData/"; + return PlatformTestUtil.getCommunityPath() + "/json/tests/testData/"; } @Override diff --git a/json/tests/test/com/intellij/json/JsonParsingTest.java b/json/tests/test/com/intellij/json/JsonParsingTest.java index b7d374bdc92f..6c921c075de2 100644 --- a/json/tests/test/com/intellij/json/JsonParsingTest.java +++ b/json/tests/test/com/intellij/json/JsonParsingTest.java @@ -33,6 +33,6 @@ public class JsonParsingTest extends ParsingTestCase { @Override protected String getTestDataPath() { - return PlatformTestUtil.getCommunityPath() + "/plugins/json-tests/testData"; + return PlatformTestUtil.getCommunityPath() + "/json/tests/testData"; } } diff --git a/json/tests/testData/psi/NestedObjectLiterals.txt b/json/tests/testData/psi/NestedObjectLiterals.txt index 4706ab8230ff..824dc0a37c2e 100644 --- a/json/tests/testData/psi/NestedObjectLiterals.txt +++ b/json/tests/testData/psi/NestedObjectLiterals.txt @@ -4,8 +4,7 @@ FILE PsiWhiteSpace(' ') JsonPropertyImpl(PROPERTY) JsonPropertyNameImpl(PROPERTY_NAME) - JsonStringLiteralImpl(STRING_LITERAL) - PsiElement(STRING)('"foo"') + PsiElement(STRING)('"foo"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonObjectImpl(OBJECT) @@ -13,16 +12,14 @@ FILE PsiWhiteSpace(' ') JsonPropertyImpl(PROPERTY) JsonPropertyNameImpl(PROPERTY_NAME) - JsonStringLiteralImpl(STRING_LITERAL) - PsiElement(STRING)('"bar"') + PsiElement(STRING)('"bar"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonObjectImpl(OBJECT) PsiElement({)('{') JsonPropertyImpl(PROPERTY) JsonPropertyNameImpl(PROPERTY_NAME) - JsonStringLiteralImpl(STRING_LITERAL) - PsiElement(STRING)('"baz"') + PsiElement(STRING)('"baz"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonNullLiteralImpl(NULL_LITERAL) From 82851427b488f68333e82a530eb65c31611c33e8 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 19 Aug 2014 21:40:39 +0400 Subject: [PATCH 32/85] Add root JsonElement to PSI hierarchy for JSON --- .../com/intellij/json/psi/JsonProperty.java | 2 +- .../intellij/json/psi/JsonPropertyName.java | 2 +- json/gen/com/intellij/json/psi/JsonValue.java | 2 +- .../com/intellij/json/psi/JsonVisitor.java | 9 ++++---- .../json/psi/impl/JsonPropertyImpl.java | 3 +-- .../json/psi/impl/JsonPropertyNameImpl.java | 3 +-- .../intellij/json/psi/impl/JsonValueImpl.java | 3 +-- .../intellij/json/JsonParserDefinition.java | 1 + .../com/intellij/json/psi/JsonElement.java | 9 ++++++++ .../com/intellij/json/{ => psi}/JsonFile.java | 4 +++- .../intellij/json/psi/JsonPsiChangeUtils.java | 1 - .../json/psi/impl/JsonElementImpl.java | 23 +++++++++++++++++++ json/src/json.bnf | 21 +++++++++-------- json/tests/testData/psi/Keywords.txt | 8 +++---- .../testData/psi/NestedArrayLiterals.txt | 12 +++++----- .../testData/psi/NestedObjectLiterals.txt | 20 ++++++++-------- 16 files changed, 78 insertions(+), 45 deletions(-) create mode 100644 json/src/com/intellij/json/psi/JsonElement.java rename json/src/com/intellij/json/{ => psi}/JsonFile.java (79%) create mode 100644 json/src/com/intellij/json/psi/impl/JsonElementImpl.java diff --git a/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java index 305b5719b375..7eea39f0b52c 100644 --- a/json/gen/com/intellij/json/psi/JsonProperty.java +++ b/json/gen/com/intellij/json/psi/JsonProperty.java @@ -5,7 +5,7 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonProperty extends PsiElement { +public interface JsonProperty extends JsonElement { @Nullable JsonValue getValue(); diff --git a/json/gen/com/intellij/json/psi/JsonPropertyName.java b/json/gen/com/intellij/json/psi/JsonPropertyName.java index 598f257e1900..51435a6598c2 100644 --- a/json/gen/com/intellij/json/psi/JsonPropertyName.java +++ b/json/gen/com/intellij/json/psi/JsonPropertyName.java @@ -5,7 +5,7 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonPropertyName extends PsiElement { +public interface JsonPropertyName extends JsonElement { @NotNull PsiElement getString(); diff --git a/json/gen/com/intellij/json/psi/JsonValue.java b/json/gen/com/intellij/json/psi/JsonValue.java index 46995ec879b3..66c8d38ba844 100644 --- a/json/gen/com/intellij/json/psi/JsonValue.java +++ b/json/gen/com/intellij/json/psi/JsonValue.java @@ -5,6 +5,6 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonValue extends PsiElement { +public interface JsonValue extends JsonElement { } diff --git a/json/gen/com/intellij/json/psi/JsonVisitor.java b/json/gen/com/intellij/json/psi/JsonVisitor.java index cdb8755ffbaa..d97e67b0233d 100644 --- a/json/gen/com/intellij/json/psi/JsonVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonVisitor.java @@ -3,7 +3,6 @@ package com.intellij.json.psi; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiElement; public class JsonVisitor extends PsiElementVisitor { @@ -32,11 +31,11 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitProperty(@NotNull JsonProperty o) { - visitPsiElement(o); + visitElement(o); } public void visitPropertyName(@NotNull JsonPropertyName o) { - visitPsiElement(o); + visitElement(o); } public void visitStringLiteral(@NotNull JsonStringLiteral o) { @@ -44,10 +43,10 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitValue(@NotNull JsonValue o) { - visitPsiElement(o); + visitElement(o); } - public void visitPsiElement(@NotNull PsiElement o) { + public void visitElement(@NotNull JsonElement o) { visitElement(o); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java index fc8f319a2192..67f7de7f4857 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java @@ -8,10 +8,9 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; -import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.json.psi.*; -public class JsonPropertyImpl extends ASTWrapperPsiElement implements JsonProperty { +public class JsonPropertyImpl extends JsonElementImpl implements JsonProperty { public JsonPropertyImpl(ASTNode node) { super(node); diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java index 0545b3cc2e73..98b0ba387372 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java @@ -8,10 +8,9 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; -import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.json.psi.*; -public class JsonPropertyNameImpl extends ASTWrapperPsiElement implements JsonPropertyName { +public class JsonPropertyNameImpl extends JsonElementImpl implements JsonPropertyName { public JsonPropertyNameImpl(ASTNode node) { super(node); diff --git a/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java b/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java index 28bcf95a47a6..4e80c409dacf 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java @@ -8,10 +8,9 @@ import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; -import com.intellij.extapi.psi.ASTWrapperPsiElement; import com.intellij.json.psi.*; -public class JsonValueImpl extends ASTWrapperPsiElement implements JsonValue { +public class JsonValueImpl extends JsonElementImpl implements JsonValue { public JsonValueImpl(ASTNode node) { super(node); diff --git a/json/src/com/intellij/json/JsonParserDefinition.java b/json/src/com/intellij/json/JsonParserDefinition.java index 473a716e00d4..8f88e2625c5e 100644 --- a/json/src/com/intellij/json/JsonParserDefinition.java +++ b/json/src/com/intellij/json/JsonParserDefinition.java @@ -1,5 +1,6 @@ package com.intellij.json; +import com.intellij.json.psi.JsonFile; import com.intellij.lang.ASTNode; import com.intellij.lang.ParserDefinition; import com.intellij.lang.PsiParser; diff --git a/json/src/com/intellij/json/psi/JsonElement.java b/json/src/com/intellij/json/psi/JsonElement.java new file mode 100644 index 000000000000..11f19e920d3e --- /dev/null +++ b/json/src/com/intellij/json/psi/JsonElement.java @@ -0,0 +1,9 @@ +package com.intellij.json.psi; + +import com.intellij.psi.PsiElement; + +/** + * @author Mikhail Golubev + */ +public interface JsonElement extends PsiElement { +} diff --git a/json/src/com/intellij/json/JsonFile.java b/json/src/com/intellij/json/psi/JsonFile.java similarity index 79% rename from json/src/com/intellij/json/JsonFile.java rename to json/src/com/intellij/json/psi/JsonFile.java index e8971563543d..3e6187e7f80d 100644 --- a/json/src/com/intellij/json/JsonFile.java +++ b/json/src/com/intellij/json/psi/JsonFile.java @@ -1,6 +1,8 @@ -package com.intellij.json; +package com.intellij.json.psi; import com.intellij.extapi.psi.PsiFileBase; +import com.intellij.json.JsonFileType; +import com.intellij.json.JsonLanguage; import com.intellij.openapi.fileTypes.FileType; import com.intellij.psi.FileViewProvider; import org.jetbrains.annotations.NotNull; diff --git a/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java b/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java index ae34f258d4ec..341a06997b9e 100644 --- a/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java +++ b/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java @@ -9,7 +9,6 @@ import com.intellij.openapi.project.Project; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiFileFactory; import com.intellij.psi.TokenType; -import com.intellij.json.JsonFile; import org.jetbrains.annotations.NotNull; public class JsonPsiChangeUtils { diff --git a/json/src/com/intellij/json/psi/impl/JsonElementImpl.java b/json/src/com/intellij/json/psi/impl/JsonElementImpl.java new file mode 100644 index 000000000000..e65b4b6803dc --- /dev/null +++ b/json/src/com/intellij/json/psi/impl/JsonElementImpl.java @@ -0,0 +1,23 @@ +package com.intellij.json.psi.impl; + +import com.intellij.extapi.psi.ASTWrapperPsiElement; +import com.intellij.json.psi.JsonElement; +import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.text.StringUtil; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class JsonElementImpl extends ASTWrapperPsiElement implements JsonElement { + + public JsonElementImpl(@NotNull ASTNode node) { + super(node); + } + + @Override + public String toString() { + final String className = getClass().getSimpleName(); + return StringUtil.trimEnd(className, "Impl"); + } +} diff --git a/json/src/json.bnf b/json/src/json.bnf index 09bb42dc71ab..fba28fbcc356 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -1,15 +1,18 @@ { - parserClass='com.intellij.json.JsonParser' - parserUtilClass="com.intellij.json.JsonParserUtil" - psiPackage='com.intellij.json.psi' - psiImplPackage='com.intellij.json.psi.impl' + parserClass = 'com.intellij.json.JsonParser' + parserUtilClass = "com.intellij.json.JsonParserUtil" + psiPackage = 'com.intellij.json.psi' + psiImplPackage = 'com.intellij.json.psi.impl' - elementTypeHolderClass='com.intellij.json.JsonElementTypes' - elementTypeClass='com.intellij.json.JsonElementType' - psiClassPrefix="Json" + elementTypeHolderClass = 'com.intellij.json.JsonElementTypes' + elementTypeClass = 'com.intellij.json.JsonElementType' + psiClassPrefix = "Json" - psiImplUtilClass='com.intellij.json.psi.JsonPsiImplUtils' - tokenTypeClass='com.intellij.json.JsonTokenType' + psiImplUtilClass = 'com.intellij.json.psi.JsonPsiImplUtils' + tokenTypeClass = 'com.intellij.json.JsonTokenType' + + implements = "com.intellij.json.psi.JsonElement" + extends = "com.intellij.json.psi.impl.JsonElementImpl" tokens = [ L_CURLY='{' diff --git a/json/tests/testData/psi/Keywords.txt b/json/tests/testData/psi/Keywords.txt index 3d58b73a66d0..63ea1d274225 100644 --- a/json/tests/testData/psi/Keywords.txt +++ b/json/tests/testData/psi/Keywords.txt @@ -1,14 +1,14 @@ FILE - JsonArrayImpl(ARRAY) + JsonArray PsiElement([)('[') - JsonBooleanLiteralImpl(BOOLEAN_LITERAL) + JsonBooleanLiteral PsiElement(true)('true') PsiElement(,)(',') PsiWhiteSpace(' ') - JsonBooleanLiteralImpl(BOOLEAN_LITERAL) + JsonBooleanLiteral PsiElement(false)('false') PsiElement(,)(',') PsiWhiteSpace(' ') - JsonNullLiteralImpl(NULL_LITERAL) + JsonNullLiteral PsiElement(null)('null') PsiElement(])(']') \ No newline at end of file diff --git a/json/tests/testData/psi/NestedArrayLiterals.txt b/json/tests/testData/psi/NestedArrayLiterals.txt index ac42ee2bad2a..682b67d930cc 100644 --- a/json/tests/testData/psi/NestedArrayLiterals.txt +++ b/json/tests/testData/psi/NestedArrayLiterals.txt @@ -1,19 +1,19 @@ FILE - JsonArrayImpl(ARRAY) + JsonArray PsiElement([)('[') - JsonNumberLiteralImpl(NUMBER_LITERAL) + JsonNumberLiteral PsiElement(NUMBER)('1') PsiElement(,)(',') PsiWhiteSpace(' ') - JsonArrayImpl(ARRAY) + JsonArray PsiElement([)('[') - JsonStringLiteralImpl(STRING_LITERAL) + JsonStringLiteral PsiElement(STRING)('"foo"') PsiElement(,)(',') PsiWhiteSpace(' ') - JsonArrayImpl(ARRAY) + JsonArray PsiElement([)('[') - JsonNullLiteralImpl(NULL_LITERAL) + JsonNullLiteral PsiElement(null)('null') PsiElement(])(']') PsiElement(])(']') diff --git a/json/tests/testData/psi/NestedObjectLiterals.txt b/json/tests/testData/psi/NestedObjectLiterals.txt index 824dc0a37c2e..20c2efaf5a6d 100644 --- a/json/tests/testData/psi/NestedObjectLiterals.txt +++ b/json/tests/testData/psi/NestedObjectLiterals.txt @@ -1,28 +1,28 @@ FILE - JsonObjectImpl(OBJECT) + JsonObject PsiElement({)('{') PsiWhiteSpace(' ') - JsonPropertyImpl(PROPERTY) - JsonPropertyNameImpl(PROPERTY_NAME) + JsonProperty + JsonPropertyName PsiElement(STRING)('"foo"') PsiElement(:)(':') PsiWhiteSpace(' ') - JsonObjectImpl(OBJECT) + JsonObject PsiElement({)('{') PsiWhiteSpace(' ') - JsonPropertyImpl(PROPERTY) - JsonPropertyNameImpl(PROPERTY_NAME) + JsonProperty + JsonPropertyName PsiElement(STRING)('"bar"') PsiElement(:)(':') PsiWhiteSpace(' ') - JsonObjectImpl(OBJECT) + JsonObject PsiElement({)('{') - JsonPropertyImpl(PROPERTY) - JsonPropertyNameImpl(PROPERTY_NAME) + JsonProperty + JsonPropertyName PsiElement(STRING)('"baz"') PsiElement(:)(':') PsiWhiteSpace(' ') - JsonNullLiteralImpl(NULL_LITERAL) + JsonNullLiteral PsiElement(null)('null') PsiElement(})('}') PsiWhiteSpace(' ') From 4a3ff3aff39fcc6e6469049b01a58a4d600b739e Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 20 Aug 2014 15:36:38 +0400 Subject: [PATCH 33/85] Include JSON plugin description to platform --- .../platform-resources/src/META-INF/JsonPlugin.xml | 12 ++---------- resources/src/idea/RichPlatformPlugin.xml | 1 + 2 files changed, 3 insertions(+), 10 deletions(-) rename json/src/META-INF/plugin.xml => platform/platform-resources/src/META-INF/JsonPlugin.xml (82%) diff --git a/json/src/META-INF/plugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml similarity index 82% rename from json/src/META-INF/plugin.xml rename to platform/platform-resources/src/META-INF/JsonPlugin.xml index 848542a62665..4fb05799c686 100644 --- a/json/src/META-INF/plugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -1,14 +1,6 @@ - com.intellij.json - JSON Support - 1.0 - JetBrains - com.intellij.modules.xml - - + @@ -19,7 +11,7 @@ - + diff --git a/resources/src/idea/RichPlatformPlugin.xml b/resources/src/idea/RichPlatformPlugin.xml index 2b1794d236a3..20af27d4c89d 100644 --- a/resources/src/idea/RichPlatformPlugin.xml +++ b/resources/src/idea/RichPlatformPlugin.xml @@ -398,6 +398,7 @@ + From 9f8faafe6d52323ad9afd78c3c0f48fe03f44c8b Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 21 Aug 2014 13:26:49 +0400 Subject: [PATCH 34/85] Split JSON file into interface and implementation --- .../intellij/json/JsonParserDefinition.java | 4 +- json/src/com/intellij/json/psi/JsonFile.java | 30 +++++++------- .../intellij/json/psi/impl/JsonFileImpl.java | 39 +++++++++++++++++++ 3 files changed, 54 insertions(+), 19 deletions(-) create mode 100644 json/src/com/intellij/json/psi/impl/JsonFileImpl.java diff --git a/json/src/com/intellij/json/JsonParserDefinition.java b/json/src/com/intellij/json/JsonParserDefinition.java index 8f88e2625c5e..f243c7a76cc9 100644 --- a/json/src/com/intellij/json/JsonParserDefinition.java +++ b/json/src/com/intellij/json/JsonParserDefinition.java @@ -1,6 +1,6 @@ package com.intellij.json; -import com.intellij.json.psi.JsonFile; +import com.intellij.json.psi.impl.JsonFileImpl; import com.intellij.lang.ASTNode; import com.intellij.lang.ParserDefinition; import com.intellij.lang.PsiParser; @@ -63,7 +63,7 @@ public class JsonParserDefinition implements ParserDefinition { @Override public PsiFile createFile(FileViewProvider fileViewProvider) { - return new JsonFile(fileViewProvider); + return new JsonFileImpl(fileViewProvider); } @Override diff --git a/json/src/com/intellij/json/psi/JsonFile.java b/json/src/com/intellij/json/psi/JsonFile.java index 3e6187e7f80d..6d5bce02010a 100644 --- a/json/src/com/intellij/json/psi/JsonFile.java +++ b/json/src/com/intellij/json/psi/JsonFile.java @@ -1,21 +1,17 @@ package com.intellij.json.psi; -import com.intellij.extapi.psi.PsiFileBase; -import com.intellij.json.JsonFileType; -import com.intellij.json.JsonLanguage; -import com.intellij.openapi.fileTypes.FileType; -import com.intellij.psi.FileViewProvider; -import org.jetbrains.annotations.NotNull; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.Nullable; -public class JsonFile extends PsiFileBase { - - public JsonFile(FileViewProvider fileViewProvider) { - super(fileViewProvider, JsonLanguage.INSTANCE); - } - - @NotNull - @Override - public FileType getFileType() { - return JsonFileType.INSTANCE; - } +/** + * @author Mikhail Golubev + */ +public interface JsonFile extends JsonElement, PsiFile { + /** + * Returns {@link JsonArray} or {@link JsonObject} value according to JSON standard. + * + * @return top-level JSON element if any or {@code null} otherwise + */ + @Nullable + JsonValue getTopLevelValue(); } diff --git a/json/src/com/intellij/json/psi/impl/JsonFileImpl.java b/json/src/com/intellij/json/psi/impl/JsonFileImpl.java new file mode 100644 index 000000000000..3afc0888694c --- /dev/null +++ b/json/src/com/intellij/json/psi/impl/JsonFileImpl.java @@ -0,0 +1,39 @@ +package com.intellij.json.psi.impl; + +import com.intellij.extapi.psi.PsiFileBase; +import com.intellij.json.JsonFileType; +import com.intellij.json.JsonLanguage; +import com.intellij.json.psi.JsonArray; +import com.intellij.json.psi.JsonFile; +import com.intellij.json.psi.JsonObject; +import com.intellij.json.psi.JsonValue; +import com.intellij.openapi.fileTypes.FileType; +import com.intellij.psi.FileViewProvider; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +public class JsonFileImpl extends PsiFileBase implements JsonFile { + + public JsonFileImpl(FileViewProvider fileViewProvider) { + super(fileViewProvider, JsonLanguage.INSTANCE); + } + + @NotNull + @Override + public FileType getFileType() { + return JsonFileType.INSTANCE; + } + + @Nullable + @Override + public JsonValue getTopLevelValue() { + final PsiElement[] children = getChildren(); + for (PsiElement child : children) { + if (child instanceof JsonObject || child instanceof JsonArray) { + return (JsonValue) child; + } + } + return null; + } +} From 6153f6636ed5d7e24f7474d28ee7577194617039 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 21 Aug 2014 15:08:27 +0400 Subject: [PATCH 35/85] Move some of the old JSON parsing tests to new plugin --- json/tests/json-tests.iml | 1 + .../com/intellij/json/JsonCompletionTest.java | 18 +------- .../com/intellij/json/JsonFormattingTest.java | 6 +-- .../com/intellij/json/JsonParsingTest.java | 25 +++++++++++ .../test/com/intellij/json/JsonTestCase.java | 24 ++++++++++ json/tests/testData/psi/Real1.json | 8 ++++ json/tests/testData/psi/Real1.txt | 43 ++++++++++++++++++ json/tests/testData/psi/Real2.json | 3 ++ json/tests/testData/psi/Real2.txt | 16 +++++++ json/tests/testData/psi/Simple1.json | 1 + json/tests/testData/psi/Simple1.txt | 40 +++++++++++++++++ json/tests/testData/psi/Simple2.json | 1 + json/tests/testData/psi/Simple2.txt | 38 ++++++++++++++++ json/tests/testData/psi/Simple3.json | 1 + json/tests/testData/psi/Simple3.txt | 45 +++++++++++++++++++ json/tests/testData/psi/Simple4.json | 1 + json/tests/testData/psi/Simple4.txt | 3 ++ 17 files changed, 254 insertions(+), 20 deletions(-) create mode 100644 json/tests/test/com/intellij/json/JsonTestCase.java create mode 100644 json/tests/testData/psi/Real1.json create mode 100644 json/tests/testData/psi/Real1.txt create mode 100644 json/tests/testData/psi/Real2.json create mode 100644 json/tests/testData/psi/Real2.txt create mode 100644 json/tests/testData/psi/Simple1.json create mode 100644 json/tests/testData/psi/Simple1.txt create mode 100644 json/tests/testData/psi/Simple2.json create mode 100644 json/tests/testData/psi/Simple2.txt create mode 100644 json/tests/testData/psi/Simple3.json create mode 100644 json/tests/testData/psi/Simple3.txt create mode 100644 json/tests/testData/psi/Simple4.json create mode 100644 json/tests/testData/psi/Simple4.txt diff --git a/json/tests/json-tests.iml b/json/tests/json-tests.iml index b399fc32f657..3edce1f127c9 100644 --- a/json/tests/json-tests.iml +++ b/json/tests/json-tests.iml @@ -4,6 +4,7 @@ + diff --git a/json/tests/test/com/intellij/json/JsonCompletionTest.java b/json/tests/test/com/intellij/json/JsonCompletionTest.java index 1f9727593ce7..efde53dcbcfe 100644 --- a/json/tests/test/com/intellij/json/JsonCompletionTest.java +++ b/json/tests/test/com/intellij/json/JsonCompletionTest.java @@ -1,28 +1,14 @@ package com.intellij.json; -import com.intellij.testFramework.IdeaTestCase; -import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; import com.intellij.util.ArrayUtil; /** * @author Mikhail Golubev */ -public class JsonCompletionTest extends CodeInsightFixtureTestCase { +public class JsonCompletionTest extends JsonTestCase { private static final String[] KEYWORDS = new String[]{"true", "false", "null"}; private static final String[] NOTHING = ArrayUtil.EMPTY_STRING_ARRAY; - @Override - public void setUp() throws Exception { - IdeaTestCase.initPlatformPrefix(); - super.setUp(); - } - @Override - protected String getBasePath() { - return "/json/tests/testData/completion"; - } - - - @Override protected boolean isCommunity() { return true; @@ -49,6 +35,6 @@ public class JsonCompletionTest extends CodeInsightFixtureTestCase { } private void doTest(String... variants) { - myFixture.testCompletionVariants(getTestName(false) + ".json", variants); + myFixture.testCompletionVariants("completion/" + getTestName(false) + ".json", variants); } } diff --git a/json/tests/test/com/intellij/json/JsonFormattingTest.java b/json/tests/test/com/intellij/json/JsonFormattingTest.java index 3f3be60c551b..28703b7da7a1 100644 --- a/json/tests/test/com/intellij/json/JsonFormattingTest.java +++ b/json/tests/test/com/intellij/json/JsonFormattingTest.java @@ -2,6 +2,7 @@ package com.intellij.json; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.formatter.FormatterTestCase; import com.intellij.testFramework.IdeaTestCase; import com.intellij.testFramework.PlatformTestUtil; @@ -23,7 +24,6 @@ public class JsonFormattingTest extends FormatterTestCase { return "formatting"; } - // Why the heck do I specify path to testData in each kind of test differently? @Override protected String getTestDataPath() { return PlatformTestUtil.getCommunityPath() + "/json/tests/testData/"; @@ -48,9 +48,7 @@ public class JsonFormattingTest extends FormatterTestCase { public void testWrapping() throws Exception { CodeStyleSettings settings = getSettings(); - int indentSize = settings.getCommonSettings(JsonLanguage.INSTANCE).getIndentOptions().INDENT_SIZE; -// LOG.debug("Intend size for JSON: " + indentSize); - settings.RIGHT_MARGIN = 20; + settings.setRightMargin(JsonLanguage.INSTANCE, 20); doTest(); } diff --git a/json/tests/test/com/intellij/json/JsonParsingTest.java b/json/tests/test/com/intellij/json/JsonParsingTest.java index 6c921c075de2..74eab90632fe 100644 --- a/json/tests/test/com/intellij/json/JsonParsingTest.java +++ b/json/tests/test/com/intellij/json/JsonParsingTest.java @@ -27,6 +27,31 @@ public class JsonParsingTest extends ParsingTestCase { doTest(); } + public void testSimple1() { + doTest(); + } + + public void testSimple2() { + doTest(); + } + + public void testSimple4() { + doTest(); + } + + // TODO: ask about these tests + //public void testSimple3() { + // doTest(); + //} + // + //public void testReal1() { + // doTest(); + //} + // + //public void testReal2() { + // doTest(); + //} + private void doTest() { doTest(true); } diff --git a/json/tests/test/com/intellij/json/JsonTestCase.java b/json/tests/test/com/intellij/json/JsonTestCase.java new file mode 100644 index 000000000000..7807504a2d05 --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonTestCase.java @@ -0,0 +1,24 @@ +package com.intellij.json; + +import com.intellij.testFramework.PlatformTestCase; +import com.intellij.testFramework.TestDataPath; +import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +@TestDataPath("$CONTENT_ROOT/../testData") +public abstract class JsonTestCase extends CodeInsightFixtureTestCase { + @Override + public void setUp() throws Exception { + PlatformTestCase.autodetectPlatformPrefix(); + //IdeaTestCase.initPlatformPrefix(); + super.setUp(); + } + + @NotNull + public String getBasePath() { + return "/json/tests/testData"; + } +} \ No newline at end of file diff --git a/json/tests/testData/psi/Real1.json b/json/tests/testData/psi/Real1.json new file mode 100644 index 000000000000..b8926d999ca4 --- /dev/null +++ b/json/tests/testData/psi/Real1.json @@ -0,0 +1,8 @@ +{ + navigation: [ + { + name: "Demo Applications", + demos: [ "Mail", "Moxie" ] + } + ] +} diff --git a/json/tests/testData/psi/Real1.txt b/json/tests/testData/psi/Real1.txt new file mode 100644 index 000000000000..70cfc8d56be1 --- /dev/null +++ b/json/tests/testData/psi/Real1.txt @@ -0,0 +1,43 @@ +JSFile:Real.json + JSObjectLiteralExpression + PsiElement(JS:LBRACE)('{') + PsiWhiteSpace('\n ') + JSProperty + PsiElement(JS:IDENTIFIER)('navigation') + PsiElement(JS:COLON)(':') + PsiWhiteSpace(' ') + JSArrayLiteralExpression + PsiElement(JS:LBRACKET)('[') + PsiWhiteSpace('\n ') + JSObjectLiteralExpression + PsiElement(JS:LBRACE)('{') + PsiWhiteSpace('\n ') + JSProperty + PsiElement(JS:IDENTIFIER)('name') + PsiElement(JS:COLON)(':') + PsiWhiteSpace(' ') + JSLiteralExpression + PsiElement(JS:STRING_LITERAL)('"Demo Applications"') + PsiElement(JS:COMMA)(',') + PsiWhiteSpace('\n ') + JSProperty + PsiElement(JS:IDENTIFIER)('demos') + PsiElement(JS:COLON)(':') + PsiWhiteSpace(' ') + JSArrayLiteralExpression + PsiElement(JS:LBRACKET)('[') + PsiWhiteSpace(' ') + JSLiteralExpression + PsiElement(JS:STRING_LITERAL)('"Mail"') + PsiElement(JS:COMMA)(',') + PsiWhiteSpace(' ') + JSLiteralExpression + PsiElement(JS:STRING_LITERAL)('"Moxie"') + PsiWhiteSpace(' ') + PsiElement(JS:RBRACKET)(']') + PsiWhiteSpace('\n ') + PsiElement(JS:RBRACE)('}') + PsiWhiteSpace('\n ') + PsiElement(JS:RBRACKET)(']') + PsiWhiteSpace('\n') + PsiElement(JS:RBRACE)('}') \ No newline at end of file diff --git a/json/tests/testData/psi/Real2.json b/json/tests/testData/psi/Real2.json new file mode 100644 index 000000000000..99d381bb2612 --- /dev/null +++ b/json/tests/testData/psi/Real2.json @@ -0,0 +1,3 @@ +{ + /*xxx*/ navigation: "111" // yyy +} diff --git a/json/tests/testData/psi/Real2.txt b/json/tests/testData/psi/Real2.txt new file mode 100644 index 000000000000..063c058e6368 --- /dev/null +++ b/json/tests/testData/psi/Real2.txt @@ -0,0 +1,16 @@ +JSFile:Real2.json + JSObjectLiteralExpression + PsiElement(JS:LBRACE)('{') + PsiWhiteSpace('\n ') + PsiComment(JS:C_STYLE_COMMENT)('/*xxx*/') + PsiWhiteSpace(' ') + JSProperty + PsiElement(JS:IDENTIFIER)('navigation') + PsiElement(JS:COLON)(':') + PsiWhiteSpace(' ') + JSLiteralExpression + PsiElement(JS:STRING_LITERAL)('"111"') + PsiWhiteSpace(' ') + PsiComment(JS:END_OF_LINE_COMMENT)('// yyy') + PsiWhiteSpace('\n') + PsiElement(JS:RBRACE)('}') \ No newline at end of file diff --git a/json/tests/testData/psi/Simple1.json b/json/tests/testData/psi/Simple1.json new file mode 100644 index 000000000000..70afdeb1aa0c --- /dev/null +++ b/json/tests/testData/psi/Simple1.json @@ -0,0 +1 @@ +{ "x": "x value", "y": "y value", "z": "z value", "z2":[] } \ No newline at end of file diff --git a/json/tests/testData/psi/Simple1.txt b/json/tests/testData/psi/Simple1.txt new file mode 100644 index 000000000000..7c975121daac --- /dev/null +++ b/json/tests/testData/psi/Simple1.txt @@ -0,0 +1,40 @@ +FILE + JsonObject + PsiElement({)('{') + PsiWhiteSpace(' ') + JsonProperty + JsonPropertyName + PsiElement(STRING)('"x"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonStringLiteral + PsiElement(STRING)('"x value"') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonProperty + JsonPropertyName + PsiElement(STRING)('"y"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonStringLiteral + PsiElement(STRING)('"y value"') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonProperty + JsonPropertyName + PsiElement(STRING)('"z"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonStringLiteral + PsiElement(STRING)('"z value"') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonProperty + JsonPropertyName + PsiElement(STRING)('"z2"') + PsiElement(:)(':') + JsonArray + PsiElement([)('[') + PsiElement(])(']') + PsiWhiteSpace(' ') + PsiElement(})('}') \ No newline at end of file diff --git a/json/tests/testData/psi/Simple2.json b/json/tests/testData/psi/Simple2.json new file mode 100644 index 000000000000..b78f7d6c255c --- /dev/null +++ b/json/tests/testData/psi/Simple2.json @@ -0,0 +1 @@ +[ "x", 555, null, true, false, "z value", "z2",[] ], \ No newline at end of file diff --git a/json/tests/testData/psi/Simple2.txt b/json/tests/testData/psi/Simple2.txt new file mode 100644 index 000000000000..ad46c1c9f6d3 --- /dev/null +++ b/json/tests/testData/psi/Simple2.txt @@ -0,0 +1,38 @@ +FILE + JsonArray + PsiElement([)('[') + PsiWhiteSpace(' ') + JsonStringLiteral + PsiElement(STRING)('"x"') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonNumberLiteral + PsiElement(NUMBER)('555') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonNullLiteral + PsiElement(null)('null') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonBooleanLiteral + PsiElement(true)('true') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonBooleanLiteral + PsiElement(false)('false') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonStringLiteral + PsiElement(STRING)('"z value"') + PsiElement(,)(',') + PsiWhiteSpace(' ') + JsonStringLiteral + PsiElement(STRING)('"z2"') + PsiElement(,)(',') + JsonArray + PsiElement([)('[') + PsiElement(])(']') + PsiWhiteSpace(' ') + PsiElement(])(']') + PsiErrorElement:',' unexpected + PsiElement(,)(',') \ No newline at end of file diff --git a/json/tests/testData/psi/Simple3.json b/json/tests/testData/psi/Simple3.json new file mode 100644 index 000000000000..41ed9553df48 --- /dev/null +++ b/json/tests/testData/psi/Simple3.json @@ -0,0 +1 @@ +[ ++x, "x value", y + "y value", z, "z value", z2,[ a = b], {z=c} ] \ No newline at end of file diff --git a/json/tests/testData/psi/Simple3.txt b/json/tests/testData/psi/Simple3.txt new file mode 100644 index 000000000000..998f99e78233 --- /dev/null +++ b/json/tests/testData/psi/Simple3.txt @@ -0,0 +1,45 @@ +JSFile:Simple3.json + JSArrayLiteralExpression + PsiElement(JS:LBRACKET)('[') + PsiErrorElement:expression expected + + PsiWhiteSpace(' ') + PsiElement(BAD_CHARACTER)('++') + PsiElement(JS:IDENTIFIER)('x') + PsiElement(JS:COMMA)(',') + PsiWhiteSpace(' ') + PsiElement(JS:STRING_LITERAL)('"x value"') + PsiElement(JS:COMMA)(',') + PsiWhiteSpace(' ') + PsiElement(JS:IDENTIFIER)('y') + PsiWhiteSpace(' ') + PsiElement(BAD_CHARACTER)('+') + PsiWhiteSpace(' ') + PsiElement(JS:STRING_LITERAL)('"y value"') + PsiElement(JS:COMMA)(',') + PsiWhiteSpace(' ') + PsiElement(JS:IDENTIFIER)('z') + PsiElement(JS:COMMA)(',') + PsiWhiteSpace(' ') + PsiElement(JS:STRING_LITERAL)('"z value"') + PsiElement(JS:COMMA)(',') + PsiWhiteSpace(' ') + PsiElement(JS:IDENTIFIER)('z2') + PsiElement(JS:COMMA)(',') + PsiElement(JS:LBRACKET)('[') + PsiWhiteSpace(' ') + PsiElement(JS:IDENTIFIER)('a') + PsiWhiteSpace(' ') + PsiElement(BAD_CHARACTER)('=') + PsiWhiteSpace(' ') + PsiElement(JS:IDENTIFIER)('b') + PsiElement(JS:RBRACKET)(']') + PsiElement(JS:COMMA)(',') + PsiWhiteSpace(' ') + PsiElement(JS:LBRACE)('{') + PsiElement(JS:IDENTIFIER)('z') + PsiElement(BAD_CHARACTER)('=') + PsiElement(JS:IDENTIFIER)('c') + PsiElement(JS:RBRACE)('}') + PsiWhiteSpace(' ') + PsiElement(JS:RBRACKET)(']') \ No newline at end of file diff --git a/json/tests/testData/psi/Simple4.json b/json/tests/testData/psi/Simple4.json new file mode 100644 index 000000000000..f32a5804e292 --- /dev/null +++ b/json/tests/testData/psi/Simple4.json @@ -0,0 +1 @@ +true \ No newline at end of file diff --git a/json/tests/testData/psi/Simple4.txt b/json/tests/testData/psi/Simple4.txt new file mode 100644 index 000000000000..7b2963ed54a0 --- /dev/null +++ b/json/tests/testData/psi/Simple4.txt @@ -0,0 +1,3 @@ +FILE + PsiErrorElement:'[' or '{' expected, got 'true' + PsiElement(true)('true') \ No newline at end of file From 57a0e12f1cfafe155d37151716b490b708b31e3d Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 21 Aug 2014 17:36:52 +0400 Subject: [PATCH 36/85] Exclude redundant PropertyName element from JSON grammar --- .../com/intellij/json/JsonElementTypes.java | 4 --- json/gen/com/intellij/json/JsonParser.java | 25 ++++------------ .../com/intellij/json/psi/JsonProperty.java | 12 +++++--- .../intellij/json/psi/JsonPropertyName.java | 13 -------- .../com/intellij/json/psi/JsonVisitor.java | 11 +++---- .../json/psi/impl/JsonPropertyImpl.java | 18 ++++++----- .../json/psi/impl/JsonPropertyNameImpl.java | 30 ------------------- .../formatter/JsonFormattingBuilderModel.java | 2 +- .../intellij/json/psi/JsonPsiImplUtils.java | 17 ++++++++++- .../json/psi/impl/JsonPropertyMixin.java | 22 ++++++++++++++ json/src/json.bnf | 10 ++++--- .../com/intellij/json/JsonFormattingTest.java | 8 ++++- .../test/com/intellij/json/JsonTestCase.java | 10 ++++++- .../testData/psi/NestedObjectLiterals.txt | 6 ++-- json/tests/testData/psi/Simple1.txt | 8 ++--- 15 files changed, 98 insertions(+), 98 deletions(-) delete mode 100644 json/gen/com/intellij/json/psi/JsonPropertyName.java delete mode 100644 json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java create mode 100644 json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java diff --git a/json/gen/com/intellij/json/JsonElementTypes.java b/json/gen/com/intellij/json/JsonElementTypes.java index 019f10dd51ec..602797280783 100644 --- a/json/gen/com/intellij/json/JsonElementTypes.java +++ b/json/gen/com/intellij/json/JsonElementTypes.java @@ -15,7 +15,6 @@ public interface JsonElementTypes { IElementType NUMBER_LITERAL = new JsonElementType("NUMBER_LITERAL"); IElementType OBJECT = new JsonElementType("OBJECT"); IElementType PROPERTY = new JsonElementType("PROPERTY"); - IElementType PROPERTY_NAME = new JsonElementType("PROPERTY_NAME"); IElementType STRING_LITERAL = new JsonElementType("STRING_LITERAL"); IElementType VALUE = new JsonElementType("VALUE"); @@ -56,9 +55,6 @@ public interface JsonElementTypes { else if (type == PROPERTY) { return new JsonPropertyImpl(node); } - else if (type == PROPERTY_NAME) { - return new JsonPropertyNameImpl(node); - } else if (type == STRING_LITERAL) { return new JsonStringLiteralImpl(node); } diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 30f1f246b0c2..0d8df20539ee 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -41,9 +41,6 @@ public class JsonParser implements PsiParser { else if (root_ == PROPERTY) { result_ = property(builder_, 0); } - else if (root_ == PROPERTY_NAME) { - result_ = property_name(builder_, 0); - } else if (root_ == STRING_LITERAL) { result_ = string_literal(builder_, 0); } @@ -313,32 +310,20 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // property_name ':' value + // string_literal ':' value public static boolean property(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property")) return false; boolean result_; boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, ""); - result_ = property_name(builder_, level_ + 1); - pinned_ = result_; // pin = 1 - result_ = result_ && report_error_(builder_, consumeToken(builder_, COLON)); - result_ = pinned_ && value(builder_, level_ + 1) && result_; + result_ = string_literal(builder_, level_ + 1); + result_ = result_ && consumeToken(builder_, COLON); + pinned_ = result_; // pin = 2 + result_ = result_ && value(builder_, level_ + 1); exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, not_brace_or_comma_parser_); return result_ || pinned_; } - /* ********************************************************** */ - // STRING - public static boolean property_name(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "property_name")) return false; - if (!nextTokenIs(builder_, STRING)) return false; - boolean result_; - Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, STRING); - exit_section_(builder_, marker_, PROPERTY_NAME, result_); - return result_; - } - /* ********************************************************** */ // STRING public static boolean string_literal(PsiBuilder builder_, int level_) { diff --git a/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java index 7eea39f0b52c..b4f3f6bea7e6 100644 --- a/json/gen/com/intellij/json/psi/JsonProperty.java +++ b/json/gen/com/intellij/json/psi/JsonProperty.java @@ -4,16 +4,20 @@ package com.intellij.json.psi; import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNamedElement; -public interface JsonProperty extends JsonElement { +public interface JsonProperty extends PsiNamedElement { - @Nullable - JsonValue getValue(); + @NotNull + List getValueList(); @NotNull String getName(); @NotNull - JsonPropertyName getNameElement(); + JsonStringLiteral getNameElement(); + + @Nullable + JsonValue getValue(); } diff --git a/json/gen/com/intellij/json/psi/JsonPropertyName.java b/json/gen/com/intellij/json/psi/JsonPropertyName.java deleted file mode 100644 index 51435a6598c2..000000000000 --- a/json/gen/com/intellij/json/psi/JsonPropertyName.java +++ /dev/null @@ -1,13 +0,0 @@ -// This is a generated file. Not intended for manual editing. -package com.intellij.json.psi; - -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.psi.PsiElement; - -public interface JsonPropertyName extends JsonElement { - - @NotNull - PsiElement getString(); - -} diff --git a/json/gen/com/intellij/json/psi/JsonVisitor.java b/json/gen/com/intellij/json/psi/JsonVisitor.java index d97e67b0233d..b30a1a345eee 100644 --- a/json/gen/com/intellij/json/psi/JsonVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonVisitor.java @@ -3,6 +3,7 @@ package com.intellij.json.psi; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiNamedElement; public class JsonVisitor extends PsiElementVisitor { @@ -31,11 +32,7 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitProperty(@NotNull JsonProperty o) { - visitElement(o); - } - - public void visitPropertyName(@NotNull JsonPropertyName o) { - visitElement(o); + visitPsiNamedElement(o); } public void visitStringLiteral(@NotNull JsonStringLiteral o) { @@ -46,6 +43,10 @@ public class JsonVisitor extends PsiElementVisitor { visitElement(o); } + public void visitPsiNamedElement(@NotNull PsiNamedElement o) { + visitElement(o); + } + public void visitElement(@NotNull JsonElement o) { visitElement(o); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java index 67f7de7f4857..b559f2164661 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java @@ -10,7 +10,7 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonPropertyImpl extends JsonElementImpl implements JsonProperty { +public class JsonPropertyImpl extends JsonPropertyMixin implements JsonProperty { public JsonPropertyImpl(ASTNode node) { super(node); @@ -22,9 +22,9 @@ public class JsonPropertyImpl extends JsonElementImpl implements JsonProperty { } @Override - @Nullable - public JsonValue getValue() { - return findChildByClass(JsonValue.class); + @NotNull + public List getValueList() { + return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonValue.class); } @NotNull @@ -32,10 +32,14 @@ public class JsonPropertyImpl extends JsonElementImpl implements JsonProperty { return JsonPsiImplUtils.getName(this); } - @Override @NotNull - public JsonPropertyName getNameElement() { - return findNotNullChildByClass(JsonPropertyName.class); + public JsonStringLiteral getNameElement() { + return JsonPsiImplUtils.getNameElement(this); + } + + @Nullable + public JsonValue getValue() { + return JsonPsiImplUtils.getValue(this); } } diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java deleted file mode 100644 index 98b0ba387372..000000000000 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyNameImpl.java +++ /dev/null @@ -1,30 +0,0 @@ -// This is a generated file. Not intended for manual editing. -package com.intellij.json.psi.impl; - -import java.util.List; -import org.jetbrains.annotations.*; -import com.intellij.lang.ASTNode; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.util.PsiTreeUtil; -import static com.intellij.json.JsonElementTypes.*; -import com.intellij.json.psi.*; - -public class JsonPropertyNameImpl extends JsonElementImpl implements JsonPropertyName { - - public JsonPropertyNameImpl(ASTNode node) { - super(node); - } - - public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitPropertyName(this); - else super.accept(visitor); - } - - @Override - @NotNull - public PsiElement getString() { - return findNotNullChildByType(STRING); - } - -} diff --git a/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java b/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java index 041e6095bb04..1074d32fcb61 100644 --- a/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java +++ b/json/src/com/intellij/json/formatter/JsonFormattingBuilderModel.java @@ -27,7 +27,7 @@ public class JsonFormattingBuilderModel implements FormattingModelBuilder { if (LOG.isDebugEnabled()) { LOG.debug("PSI Tree:\n" + DebugUtil.psiToString(element, false)); } - LOG.debug("Right margin: " + settings.RIGHT_MARGIN); + LOG.debug("Right margin: " + settings.getRightMargin(JsonLanguage.INSTANCE)); JsonBlock block = new JsonBlock(null, element.getNode(), settings, null, Indent.getNoneIndent(), null); if (LOG.isDebugEnabled()) { StringBuilder builder = new StringBuilder(); diff --git a/json/src/com/intellij/json/psi/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/JsonPsiImplUtils.java index 50d07624bdec..9d072378e587 100644 --- a/json/src/com/intellij/json/psi/JsonPsiImplUtils.java +++ b/json/src/com/intellij/json/psi/JsonPsiImplUtils.java @@ -3,6 +3,7 @@ package com.intellij.json.psi; import com.intellij.json.JsonElementTypes; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -15,6 +16,20 @@ public class JsonPsiImplUtils { return StringUtil.unquoteString(property.getNameElement().getText()); } + @NotNull + public static JsonStringLiteral getNameElement(@NotNull JsonProperty property) { + return (JsonStringLiteral)property.getFirstChild(); + } + + @Nullable + public static JsonValue getValue(@NotNull JsonProperty property) { + final PsiElement[] children = property.getChildren(); + if (children.length > 2) { + return (JsonValue)property.getLastChild(); + } + return null; + } + public static boolean isQuotedString(@NotNull JsonLiteral literal) { return literal.getNode().findChildByType(JsonElementTypes.STRING) != null; } @@ -26,7 +41,7 @@ public class JsonPsiImplUtils { @Nullable public static JsonProperty findProperty(@NotNull JsonObject object, @NotNull String name) { - Collection properties = PsiTreeUtil.findChildrenOfType(object, JsonProperty.class); + final Collection properties = PsiTreeUtil.findChildrenOfType(object, JsonProperty.class); for (JsonProperty property : properties) { if (property.getName().equals(name)) { return property; diff --git a/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java b/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java new file mode 100644 index 000000000000..b9beaa0e1894 --- /dev/null +++ b/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java @@ -0,0 +1,22 @@ +package com.intellij.json.psi.impl; + +import com.intellij.json.psi.JsonProperty; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +abstract class JsonPropertyMixin extends JsonElementImpl implements JsonProperty { + public JsonPropertyMixin(@NotNull ASTNode node) { + super(node); + } + + @Override + public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException { + throw new IncorrectOperationException(); + } +} diff --git a/json/src/json.bnf b/json/src/json.bnf index fba28fbcc356..81e1948ef6da 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -42,6 +42,7 @@ extends("object|array|literal")=value extends("string_literal|number_literal|boolean_literal|null_literal")=literal + implements("property")="com.intellij.psi.PsiNamedElement" } json ::= object | array @@ -54,15 +55,16 @@ object ::= '{' [properties] '}' { } private properties ::= property (',' property)* { pin(".*")=1 } -property ::= property_name ':' value { - pin = 1 +property ::= string_literal ':' value { + pin = 2 methods=[ getName - NameElement="property_name" + getNameElement + getValue ] + mixin="com.intellij.json.psi.impl.JsonPropertyMixin" recoverWhile = not_brace_or_comma } -property_name ::= STRING array ::= '[' [array_elements] ']' { pin=1 diff --git a/json/tests/test/com/intellij/json/JsonFormattingTest.java b/json/tests/test/com/intellij/json/JsonFormattingTest.java index 28703b7da7a1..07a9728caf54 100644 --- a/json/tests/test/com/intellij/json/JsonFormattingTest.java +++ b/json/tests/test/com/intellij/json/JsonFormattingTest.java @@ -2,15 +2,19 @@ package com.intellij.json; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.codeStyle.CodeStyleSettings; -import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.formatter.FormatterTestCase; import com.intellij.testFramework.IdeaTestCase; import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.testFramework.TestLoggerFactory; /** * @author Mikhail Golubev */ public class JsonFormattingTest extends FormatterTestCase { + static { + Logger.setFactory(TestLoggerFactory.class); + } + private static final Logger LOG = Logger.getInstance(JsonFormattingTest.class); @Override @@ -35,6 +39,8 @@ public class JsonFormattingTest extends FormatterTestCase { } public void testContainerElementsAlignment() throws Exception { + final int indentSize = getSettings(JsonLanguage.INSTANCE).getIndentOptions().INDENT_SIZE; + LOG.debug("Intent size: " + indentSize); doTest(); } diff --git a/json/tests/test/com/intellij/json/JsonTestCase.java b/json/tests/test/com/intellij/json/JsonTestCase.java index 7807504a2d05..5cbaf0e0697c 100644 --- a/json/tests/test/com/intellij/json/JsonTestCase.java +++ b/json/tests/test/com/intellij/json/JsonTestCase.java @@ -1,15 +1,23 @@ package com.intellij.json; +import com.intellij.openapi.diagnostic.Logger; import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.TestDataPath; +import com.intellij.testFramework.TestLoggerFactory; import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; /** * @author Mikhail Golubev */ -@TestDataPath("$CONTENT_ROOT/../testData") +@TestDataPath("$CONTENT_ROOT/testData") public abstract class JsonTestCase extends CodeInsightFixtureTestCase { + static { + Logger.setFactory(TestLoggerFactory.class); + } + + protected static final Logger LOG = Logger.getInstance(JsonTestCase.class); + @Override public void setUp() throws Exception { PlatformTestCase.autodetectPlatformPrefix(); diff --git a/json/tests/testData/psi/NestedObjectLiterals.txt b/json/tests/testData/psi/NestedObjectLiterals.txt index 20c2efaf5a6d..6bd5aaa27dd7 100644 --- a/json/tests/testData/psi/NestedObjectLiterals.txt +++ b/json/tests/testData/psi/NestedObjectLiterals.txt @@ -3,7 +3,7 @@ FILE PsiElement({)('{') PsiWhiteSpace(' ') JsonProperty - JsonPropertyName + JsonStringLiteral PsiElement(STRING)('"foo"') PsiElement(:)(':') PsiWhiteSpace(' ') @@ -11,14 +11,14 @@ FILE PsiElement({)('{') PsiWhiteSpace(' ') JsonProperty - JsonPropertyName + JsonStringLiteral PsiElement(STRING)('"bar"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonObject PsiElement({)('{') JsonProperty - JsonPropertyName + JsonStringLiteral PsiElement(STRING)('"baz"') PsiElement(:)(':') PsiWhiteSpace(' ') diff --git a/json/tests/testData/psi/Simple1.txt b/json/tests/testData/psi/Simple1.txt index 7c975121daac..164c4d74c6ce 100644 --- a/json/tests/testData/psi/Simple1.txt +++ b/json/tests/testData/psi/Simple1.txt @@ -3,7 +3,7 @@ FILE PsiElement({)('{') PsiWhiteSpace(' ') JsonProperty - JsonPropertyName + JsonStringLiteral PsiElement(STRING)('"x"') PsiElement(:)(':') PsiWhiteSpace(' ') @@ -12,7 +12,7 @@ FILE PsiElement(,)(',') PsiWhiteSpace(' ') JsonProperty - JsonPropertyName + JsonStringLiteral PsiElement(STRING)('"y"') PsiElement(:)(':') PsiWhiteSpace(' ') @@ -21,7 +21,7 @@ FILE PsiElement(,)(',') PsiWhiteSpace(' ') JsonProperty - JsonPropertyName + JsonStringLiteral PsiElement(STRING)('"z"') PsiElement(:)(':') PsiWhiteSpace(' ') @@ -30,7 +30,7 @@ FILE PsiElement(,)(',') PsiWhiteSpace(' ') JsonProperty - JsonPropertyName + JsonStringLiteral PsiElement(STRING)('"z2"') PsiElement(:)(':') JsonArray From a94d2c014d51a1e243a85f472a42cfcc03796ebd Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 21 Aug 2014 23:38:03 +0400 Subject: [PATCH 37/85] Fix mixin hierarchy and getKey/getValue implementations --- json/src/com/intellij/json/JsonParserDefinition.java | 11 ++++++++++- json/src/com/intellij/json/formatter/JsonBlock.java | 4 ++-- json/src/com/intellij/json/psi/JsonPsiUtil.java | 10 ++++++++++ .../com/intellij/json/psi/impl/JsonLiteralMixin.java | 2 +- .../json/psi/{ => impl}/JsonPsiImplUtils.java | 10 +++------- json/src/json.bnf | 2 +- 6 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 json/src/com/intellij/json/psi/JsonPsiUtil.java rename json/src/com/intellij/json/psi/{ => impl}/JsonPsiImplUtils.java (86%) diff --git a/json/src/com/intellij/json/JsonParserDefinition.java b/json/src/com/intellij/json/JsonParserDefinition.java index f243c7a76cc9..506072a36551 100644 --- a/json/src/com/intellij/json/JsonParserDefinition.java +++ b/json/src/com/intellij/json/JsonParserDefinition.java @@ -14,11 +14,20 @@ import com.intellij.psi.tree.IFileElementType; import com.intellij.psi.tree.TokenSet; import org.jetbrains.annotations.NotNull; +import static com.intellij.json.JsonElementTypes.*; + public class JsonParserDefinition implements ParserDefinition { public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE); public static final TokenSet STRING_LITERALS = TokenSet.create(JsonElementTypes.STRING); + public static final IFileElementType FILE = new IFileElementType(JsonLanguage.INSTANCE); - public static final TokenSet CONTAINERS = TokenSet.create(JsonElementTypes.ARRAY, JsonElementTypes.OBJECT); + + public static final TokenSet JSON_BRACES = TokenSet.create(L_CURLY, R_CURLY); + public static final TokenSet JSON_BRACKETS = TokenSet.create(L_BRACKET, R_BRACKET); + public static final TokenSet JSON_CONTAINERS = TokenSet.create(OBJECT, ARRAY); + public static final TokenSet JSON_BOOLEANS = TokenSet.create(TRUE, FALSE); + public static final TokenSet JSON_LITERALS = TokenSet.create(STRING_LITERAL, NUMBER_LITERAL, NULL_LITERAL, TRUE, FALSE); + public static final TokenSet JSON_VALUES = TokenSet.orSet(JSON_CONTAINERS, JSON_LITERALS); @NotNull diff --git a/json/src/com/intellij/json/formatter/JsonBlock.java b/json/src/com/intellij/json/formatter/JsonBlock.java index 70b4538d1e50..9a65d2636bb6 100644 --- a/json/src/com/intellij/json/formatter/JsonBlock.java +++ b/json/src/com/intellij/json/formatter/JsonBlock.java @@ -2,6 +2,7 @@ package com.intellij.json.formatter; import com.intellij.formatting.*; import com.intellij.json.JsonParserDefinition; +import com.intellij.json.psi.JsonProperty; import com.intellij.json.psi.JsonValue; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; @@ -12,7 +13,6 @@ import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.Function; import com.intellij.util.containers.ContainerUtil; -import com.intellij.json.psi.JsonProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -178,7 +178,7 @@ public class JsonBlock implements ASTBlock { } private boolean isContainer() { - return JsonParserDefinition.CONTAINERS.contains(myNode.getElementType()); + return JsonParserDefinition.JSON_CONTAINERS.contains(myNode.getElementType()); } } diff --git a/json/src/com/intellij/json/psi/JsonPsiUtil.java b/json/src/com/intellij/json/psi/JsonPsiUtil.java new file mode 100644 index 000000000000..f25bf0501a0d --- /dev/null +++ b/json/src/com/intellij/json/psi/JsonPsiUtil.java @@ -0,0 +1,10 @@ +package com.intellij.json.psi; + +/** + * @author Mikhail Golubev + */ +public class JsonPsiUtil { + private JsonPsiUtil() { + // empty + } +} diff --git a/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java b/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java index b123a2c88486..0338db3e539b 100644 --- a/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java +++ b/json/src/com/intellij/json/psi/impl/JsonLiteralMixin.java @@ -6,7 +6,7 @@ import com.intellij.psi.PsiReference; import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; import org.jetbrains.annotations.NotNull; -abstract class JsonLiteralMixin extends JsonPropertyImpl implements JsonLiteral { +abstract class JsonLiteralMixin extends JsonElementImpl implements JsonLiteral { private final Object myRefLock = new Object(); private volatile PsiReference[] myRefs; private volatile long myModCount = -1; diff --git a/json/src/com/intellij/json/psi/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java similarity index 86% rename from json/src/com/intellij/json/psi/JsonPsiImplUtils.java rename to json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java index 9d072378e587..c2e9e216c374 100644 --- a/json/src/com/intellij/json/psi/JsonPsiImplUtils.java +++ b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java @@ -1,9 +1,9 @@ -package com.intellij.json.psi; +package com.intellij.json.psi.impl; import com.intellij.json.JsonElementTypes; +import com.intellij.json.psi.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -23,11 +23,7 @@ public class JsonPsiImplUtils { @Nullable public static JsonValue getValue(@NotNull JsonProperty property) { - final PsiElement[] children = property.getChildren(); - if (children.length > 2) { - return (JsonValue)property.getLastChild(); - } - return null; + return PsiTreeUtil.getNextSiblingOfType(getNameElement(property), JsonValue.class); } public static boolean isQuotedString(@NotNull JsonLiteral literal) { diff --git a/json/src/json.bnf b/json/src/json.bnf index 81e1948ef6da..faae4aa0dbf8 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -8,7 +8,7 @@ elementTypeClass = 'com.intellij.json.JsonElementType' psiClassPrefix = "Json" - psiImplUtilClass = 'com.intellij.json.psi.JsonPsiImplUtils' + psiImplUtilClass = 'com.intellij.json.psi.impl.JsonPsiImplUtils' tokenTypeClass = 'com.intellij.json.JsonTokenType' implements = "com.intellij.json.psi.JsonElement" From 64221c145247cdb057cbc42dcd082bd0d1dc5d2c Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 22 Aug 2014 00:18:52 +0400 Subject: [PATCH 38/85] Fix JSON formatting --- .../intellij/json/formatter/JsonBlock.java | 26 +++++++++---------- 1 file changed, 13 insertions(+), 13 deletions(-) diff --git a/json/src/com/intellij/json/formatter/JsonBlock.java b/json/src/com/intellij/json/formatter/JsonBlock.java index 9a65d2636bb6..30b3fe744c9c 100644 --- a/json/src/com/intellij/json/formatter/JsonBlock.java +++ b/json/src/com/intellij/json/formatter/JsonBlock.java @@ -1,9 +1,9 @@ package com.intellij.json.formatter; import com.intellij.formatting.*; +import com.intellij.json.JsonElementTypes; import com.intellij.json.JsonParserDefinition; import com.intellij.json.psi.JsonProperty; -import com.intellij.json.psi.JsonValue; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; @@ -18,14 +18,14 @@ import org.jetbrains.annotations.Nullable; import java.util.List; -import static com.intellij.json.JsonElementTypes.*; - /** + * Mostly based on PyBlock implementation. + * * @author Mikhail Golubev */ public class JsonBlock implements ASTBlock { - private static final TokenSet OPEN_BRACES = TokenSet.create(L_BRACKET, L_CURLY); - private static final TokenSet CLOSE_BRACES = TokenSet.create(R_BRACKET, R_CURLY); + private static final TokenSet OPEN_BRACES = TokenSet.create(JsonElementTypes.L_BRACKET, JsonElementTypes.L_CURLY); + private static final TokenSet CLOSE_BRACES = TokenSet.create(JsonElementTypes.R_BRACKET, JsonElementTypes.R_CURLY); private static final TokenSet BRACES = TokenSet.orSet(OPEN_BRACES, CLOSE_BRACES); private JsonBlock myParent; @@ -87,7 +87,7 @@ public class JsonBlock implements ASTBlock { return mySubBlocks; } - private Block makeSubBlock(ASTNode childNode) { + private Block makeSubBlock(@NotNull ASTNode childNode) { IElementType childNodeType = childNode.getElementType(); PsiElement childPsiElement = childNode.getPsi(); @@ -95,12 +95,12 @@ public class JsonBlock implements ASTBlock { Alignment alignment = null; Wrap wrap = null; - if (isContainer() && childNodeType != COMMA && !BRACES.contains(childNodeType)) { + if (isContainer() && childNodeType != JsonElementTypes.COMMA && !BRACES.contains(childNodeType)) { wrap = Wrap.createWrap(WrapType.NORMAL, true); alignment = myChildAlignment; indent = Indent.getNormalIndent(); } - if (myNode.getElementType() == PROPERTY && childPsiElement instanceof JsonValue) { + if (myPsiElement instanceof JsonProperty && childPsiElement == ((JsonProperty)myPsiElement).getValue()) { wrap = Wrap.createWrap(WrapType.NORMAL, true); indent = Indent.getNormalIndent(); } @@ -141,7 +141,7 @@ public class JsonBlock implements ASTBlock { } if (isContainer() && prevChildNode != null) { // correctly indent first element after opening brace - if (OPEN_BRACES.contains(prevChildNode.getElementType()) || prevChildNode.getElementType() == COMMA) { + if (OPEN_BRACES.contains(prevChildNode.getElementType()) || prevChildNode.getElementType() == JsonElementTypes.COMMA) { return new ChildAttributes(Indent.getNormalIndent(), myChildAlignment); } } @@ -156,11 +156,11 @@ public class JsonBlock implements ASTBlock { public boolean isIncomplete() { IElementType nodeType = myNode.getElementType(); ASTNode lastChildNode = myNode.getLastChildNode(); - if (nodeType == OBJECT) { - return lastChildNode != null && lastChildNode.getElementType() == R_CURLY; + if (nodeType == JsonElementTypes.OBJECT) { + return lastChildNode != null && lastChildNode.getElementType() == JsonElementTypes.R_CURLY; } - else if (nodeType == ARRAY) { - return lastChildNode != null && lastChildNode.getElementType() == R_BRACKET; + else if (nodeType == JsonElementTypes.ARRAY) { + return lastChildNode != null && lastChildNode.getElementType() == JsonElementTypes.R_BRACKET; } else if (myPsiElement instanceof JsonProperty) { return ((JsonProperty)myPsiElement).getValue() != null; From 5dbbe9f8000865f6adab48ae1ac44ed99eb6df96 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 22 Aug 2014 00:19:32 +0400 Subject: [PATCH 39/85] Add underlying file name to JsonFile toString() to ease debugging --- .../intellij/json/psi/impl/JsonFileImpl.java | 17 +++++++++-------- json/tests/testData/psi/Keywords.txt | 2 +- json/tests/testData/psi/NestedArrayLiterals.txt | 2 +- .../tests/testData/psi/NestedObjectLiterals.txt | 2 +- json/tests/testData/psi/Simple1.txt | 2 +- json/tests/testData/psi/Simple2.txt | 2 +- json/tests/testData/psi/Simple4.txt | 2 +- .../testData/psi/TopLevelStringLiteral.txt | 2 +- 8 files changed, 16 insertions(+), 15 deletions(-) diff --git a/json/src/com/intellij/json/psi/impl/JsonFileImpl.java b/json/src/com/intellij/json/psi/impl/JsonFileImpl.java index 3afc0888694c..a0e7f2094069 100644 --- a/json/src/com/intellij/json/psi/impl/JsonFileImpl.java +++ b/json/src/com/intellij/json/psi/impl/JsonFileImpl.java @@ -8,8 +8,9 @@ import com.intellij.json.psi.JsonFile; import com.intellij.json.psi.JsonObject; import com.intellij.json.psi.JsonValue; import com.intellij.openapi.fileTypes.FileType; +import com.intellij.openapi.vfs.VirtualFile; import com.intellij.psi.FileViewProvider; -import com.intellij.psi.PsiElement; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -28,12 +29,12 @@ public class JsonFileImpl extends PsiFileBase implements JsonFile { @Nullable @Override public JsonValue getTopLevelValue() { - final PsiElement[] children = getChildren(); - for (PsiElement child : children) { - if (child instanceof JsonObject || child instanceof JsonArray) { - return (JsonValue) child; - } - } - return null; + return PsiTreeUtil.getChildOfAnyType(this, JsonObject.class, JsonArray.class); + } + + @Override + public String toString() { + final VirtualFile virtualFile = getVirtualFile(); + return String.format("JsonFile: " + (virtualFile != null? virtualFile.getName() : "")); } } diff --git a/json/tests/testData/psi/Keywords.txt b/json/tests/testData/psi/Keywords.txt index 63ea1d274225..c032f64c7e0c 100644 --- a/json/tests/testData/psi/Keywords.txt +++ b/json/tests/testData/psi/Keywords.txt @@ -1,4 +1,4 @@ -FILE +JsonFile: Keywords.json JsonArray PsiElement([)('[') JsonBooleanLiteral diff --git a/json/tests/testData/psi/NestedArrayLiterals.txt b/json/tests/testData/psi/NestedArrayLiterals.txt index 682b67d930cc..02cb0359f05b 100644 --- a/json/tests/testData/psi/NestedArrayLiterals.txt +++ b/json/tests/testData/psi/NestedArrayLiterals.txt @@ -1,4 +1,4 @@ -FILE +JsonFile: NestedArrayLiterals.json JsonArray PsiElement([)('[') JsonNumberLiteral diff --git a/json/tests/testData/psi/NestedObjectLiterals.txt b/json/tests/testData/psi/NestedObjectLiterals.txt index 6bd5aaa27dd7..518a0f5c62c6 100644 --- a/json/tests/testData/psi/NestedObjectLiterals.txt +++ b/json/tests/testData/psi/NestedObjectLiterals.txt @@ -1,4 +1,4 @@ -FILE +JsonFile: NestedObjectLiterals.json JsonObject PsiElement({)('{') PsiWhiteSpace(' ') diff --git a/json/tests/testData/psi/Simple1.txt b/json/tests/testData/psi/Simple1.txt index 164c4d74c6ce..9a0725b2ae7b 100644 --- a/json/tests/testData/psi/Simple1.txt +++ b/json/tests/testData/psi/Simple1.txt @@ -1,4 +1,4 @@ -FILE +JsonFile: Simple1.json JsonObject PsiElement({)('{') PsiWhiteSpace(' ') diff --git a/json/tests/testData/psi/Simple2.txt b/json/tests/testData/psi/Simple2.txt index ad46c1c9f6d3..ee1b90a7c9a2 100644 --- a/json/tests/testData/psi/Simple2.txt +++ b/json/tests/testData/psi/Simple2.txt @@ -1,4 +1,4 @@ -FILE +JsonFile: Simple2.json JsonArray PsiElement([)('[') PsiWhiteSpace(' ') diff --git a/json/tests/testData/psi/Simple4.txt b/json/tests/testData/psi/Simple4.txt index 7b2963ed54a0..90eb70f5b1c9 100644 --- a/json/tests/testData/psi/Simple4.txt +++ b/json/tests/testData/psi/Simple4.txt @@ -1,3 +1,3 @@ -FILE +JsonFile: Simple4.json PsiErrorElement:'[' or '{' expected, got 'true' PsiElement(true)('true') \ No newline at end of file diff --git a/json/tests/testData/psi/TopLevelStringLiteral.txt b/json/tests/testData/psi/TopLevelStringLiteral.txt index 6166316f83ff..ceb875da498e 100644 --- a/json/tests/testData/psi/TopLevelStringLiteral.txt +++ b/json/tests/testData/psi/TopLevelStringLiteral.txt @@ -1,3 +1,3 @@ -FILE +JsonFile: TopLevelStringLiteral.json PsiErrorElement:'[' or '{' expected, got '"should not be here"' PsiElement(STRING)('"should not be here"') \ No newline at end of file From b8e225ef655f37136e488af5fbd80b66db5c18d4 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 22 Aug 2014 01:48:55 +0400 Subject: [PATCH 40/85] Add naive implementation of structure view for JSON --- .../com/intellij/json/psi/JsonProperty.java | 2 +- .../com/intellij/json/psi/JsonElement.java | 3 +- .../JsonStructureViewBuilder.java | 33 +++++ .../JsonStructureViewElement.java | 127 ++++++++++++++++++ .../JsonStructureViewFactory.java | 18 +++ json/src/json.bnf | 1 + .../src/META-INF/JsonPlugin.xml | 1 + 7 files changed, 183 insertions(+), 2 deletions(-) create mode 100644 json/src/com/intellij/json/structureView/JsonStructureViewBuilder.java create mode 100644 json/src/com/intellij/json/structureView/JsonStructureViewElement.java create mode 100644 json/src/com/intellij/json/structureView/JsonStructureViewFactory.java diff --git a/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java index b4f3f6bea7e6..95b38f3fd2eb 100644 --- a/json/gen/com/intellij/json/psi/JsonProperty.java +++ b/json/gen/com/intellij/json/psi/JsonProperty.java @@ -6,7 +6,7 @@ import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiNamedElement; -public interface JsonProperty extends PsiNamedElement { +public interface JsonProperty extends JsonElement, PsiNamedElement { @NotNull List getValueList(); diff --git a/json/src/com/intellij/json/psi/JsonElement.java b/json/src/com/intellij/json/psi/JsonElement.java index 11f19e920d3e..f33452553f02 100644 --- a/json/src/com/intellij/json/psi/JsonElement.java +++ b/json/src/com/intellij/json/psi/JsonElement.java @@ -1,9 +1,10 @@ package com.intellij.json.psi; +import com.intellij.psi.NavigatablePsiElement; import com.intellij.psi.PsiElement; /** * @author Mikhail Golubev */ -public interface JsonElement extends PsiElement { +public interface JsonElement extends PsiElement, NavigatablePsiElement { } diff --git a/json/src/com/intellij/json/structureView/JsonStructureViewBuilder.java b/json/src/com/intellij/json/structureView/JsonStructureViewBuilder.java new file mode 100644 index 000000000000..182cd9f10e70 --- /dev/null +++ b/json/src/com/intellij/json/structureView/JsonStructureViewBuilder.java @@ -0,0 +1,33 @@ +package com.intellij.json.structureView; + +import com.intellij.ide.structureView.StructureViewModel; +import com.intellij.ide.structureView.StructureViewModelBase; +import com.intellij.ide.structureView.TreeBasedStructureViewBuilder; +import com.intellij.ide.util.treeView.smartTree.Sorter; +import com.intellij.json.psi.JsonFile; +import com.intellij.json.psi.JsonObject; +import com.intellij.json.psi.JsonProperty; +import com.intellij.openapi.editor.Editor; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * Based on structure view implementation for YAML. + * + * @author Mikhail Golubev + */ +public class JsonStructureViewBuilder extends TreeBasedStructureViewBuilder { + private final JsonFile myJsonFile; + + public JsonStructureViewBuilder(@NotNull JsonFile jsonFile) { + myJsonFile = jsonFile; + } + + @NotNull + @Override + public StructureViewModel createStructureViewModel(@Nullable Editor editor) { + return new StructureViewModelBase(myJsonFile, editor, new JsonStructureViewElement(myJsonFile)) + .withSorters(Sorter.ALPHA_SORTER) + .withSuitableClasses(JsonFile.class, JsonObject.class, JsonProperty.class); + } +} diff --git a/json/src/com/intellij/json/structureView/JsonStructureViewElement.java b/json/src/com/intellij/json/structureView/JsonStructureViewElement.java new file mode 100644 index 000000000000..8b9738776495 --- /dev/null +++ b/json/src/com/intellij/json/structureView/JsonStructureViewElement.java @@ -0,0 +1,127 @@ +package com.intellij.json.structureView; + +import com.intellij.ide.structureView.StructureViewTreeElement; +import com.intellij.ide.util.treeView.smartTree.TreeElement; +import com.intellij.json.psi.JsonElement; +import com.intellij.json.psi.JsonFile; +import com.intellij.json.psi.JsonObject; +import com.intellij.json.psi.JsonProperty; +import com.intellij.navigation.ItemPresentation; +import com.intellij.util.Function; +import com.intellij.util.PlatformIcons; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import javax.swing.*; + +/** + * @author Mikhail Golubev + */ +public class JsonStructureViewElement implements StructureViewTreeElement { + private final JsonElement myElement; + + public JsonStructureViewElement(@NotNull JsonElement element) { + assert element instanceof JsonFile || element instanceof JsonObject || element instanceof JsonProperty; + myElement = element; + } + + @Override + public JsonElement getValue() { + return myElement; + } + + @Override + public void navigate(boolean requestFocus) { + myElement.navigate(requestFocus); + } + + @Override + public boolean canNavigate() { + return myElement.canNavigate(); + } + + @Override + public boolean canNavigateToSource() { + return myElement.canNavigateToSource(); + } + + @NotNull + @Override + public ItemPresentation getPresentation() { + if (myElement instanceof JsonObject) { + return new ItemPresentation() { + @Nullable + @Override + public String getPresentableText() { + return "Object"; + } + + @Nullable + @Override + public String getLocationString() { + return null; + } + + @Nullable + @Override + public Icon getIcon(boolean unused) { + return PlatformIcons.CLASS_ICON; + } + }; + } + else if (myElement instanceof JsonProperty) { + return new ItemPresentation() { + @Nullable + @Override + public String getPresentableText() { + return ((JsonProperty)myElement).getName(); + } + + @Nullable + @Override + public String getLocationString() { + return null; + } + + @Nullable + @Override + public Icon getIcon(boolean unused) { + return PlatformIcons.PROPERTY_ICON; + } + }; + } + else if (myElement instanceof JsonFile) { + //noinspection ConstantConditions + return myElement.getPresentation(); + } + throw new AssertionError("Attempting to create presentation for invalid element: " + myElement); + } + + @NotNull + @Override + public TreeElement[] getChildren() { + if (myElement instanceof JsonFile) { + final JsonFile jsonFile = (JsonFile)myElement; + if (jsonFile.getTopLevelValue() instanceof JsonObject) { + return new TreeElement[]{new JsonStructureViewElement(jsonFile.getTopLevelValue())}; + } + } + else if (myElement instanceof JsonProperty) { + final JsonProperty jsonProperty = (JsonProperty)myElement; + if (jsonProperty.getValue() instanceof JsonObject) { + return new TreeElement[]{new JsonStructureViewElement(jsonProperty.getValue())}; + } + } + else if (myElement instanceof JsonObject) { + final JsonObject jsonObject = (JsonObject)myElement; + return ContainerUtil.map2Array(jsonObject.getPropertyList(), TreeElement.class, new Function() { + @Override + public TreeElement fun(JsonProperty property) { + return new JsonStructureViewElement(property); + } + }); + } + return EMPTY_ARRAY; + } +} diff --git a/json/src/com/intellij/json/structureView/JsonStructureViewFactory.java b/json/src/com/intellij/json/structureView/JsonStructureViewFactory.java new file mode 100644 index 000000000000..f2e325ccae38 --- /dev/null +++ b/json/src/com/intellij/json/structureView/JsonStructureViewFactory.java @@ -0,0 +1,18 @@ +package com.intellij.json.structureView; + +import com.intellij.ide.structureView.StructureViewBuilder; +import com.intellij.json.psi.JsonFile; +import com.intellij.lang.PsiStructureViewFactory; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public class JsonStructureViewFactory implements PsiStructureViewFactory { + @Nullable + @Override + public StructureViewBuilder getStructureViewBuilder(PsiFile psiFile) { + return new JsonStructureViewBuilder(((JsonFile)psiFile)); + } +} diff --git a/json/src/json.bnf b/json/src/json.bnf index faae4aa0dbf8..818a133ba404 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -43,6 +43,7 @@ extends("object|array|literal")=value extends("string_literal|number_literal|boolean_literal|null_literal")=literal implements("property")="com.intellij.psi.PsiNamedElement" + implements("property")="com.intellij.json.psi.JsonElement" } json ::= object | array diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index 4fb05799c686..1a170eae0e51 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -31,6 +31,7 @@ + Date: Fri, 22 Aug 2014 20:03:08 +0400 Subject: [PATCH 41/85] Add folding builder similar to the one used in JavaScript --- .../json/folding/JsonFoldingBuilder.java | 63 +++++++++++++++++++ .../com/intellij/json/JsonCompletionTest.java | 5 -- .../com/intellij/json/JsonFoldingTest.java | 19 ++++++ .../com/intellij/json/JsonParsingTest.java | 2 + .../test/com/intellij/json/JsonTestCase.java | 5 ++ json/tests/testData/folding/ArrayFolding.json | 5 ++ .../tests/testData/folding/ObjectFolding.json | 7 +++ .../src/META-INF/JsonPlugin.xml | 1 + 8 files changed, 102 insertions(+), 5 deletions(-) create mode 100644 json/src/com/intellij/json/folding/JsonFoldingBuilder.java create mode 100644 json/tests/test/com/intellij/json/JsonFoldingTest.java create mode 100644 json/tests/testData/folding/ArrayFolding.json create mode 100644 json/tests/testData/folding/ObjectFolding.json diff --git a/json/src/com/intellij/json/folding/JsonFoldingBuilder.java b/json/src/com/intellij/json/folding/JsonFoldingBuilder.java new file mode 100644 index 000000000000..b785d1c11037 --- /dev/null +++ b/json/src/com/intellij/json/folding/JsonFoldingBuilder.java @@ -0,0 +1,63 @@ +package com.intellij.json.folding; + +import com.intellij.json.JsonElementTypes; +import com.intellij.lang.ASTNode; +import com.intellij.lang.folding.FoldingBuilder; +import com.intellij.lang.folding.FoldingDescriptor; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.project.DumbAware; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author Mikhail Golubev + */ +public class JsonFoldingBuilder implements FoldingBuilder, DumbAware { + @NotNull + @Override + public FoldingDescriptor[] buildFoldRegions(@NotNull ASTNode node, @NotNull Document document) { + final List descriptors = new ArrayList(); + collectDescriptorsRecursively(node, document, descriptors); + return descriptors.toArray(new FoldingDescriptor[descriptors.size()]); + } + + private static void collectDescriptorsRecursively(@NotNull ASTNode node, + @NotNull Document document, + @NotNull List descriptors) { + final IElementType type = node.getElementType(); + if ((type == JsonElementTypes.OBJECT || type == JsonElementTypes.ARRAY) && spanMultipleLines(node, document)) { + descriptors.add(new FoldingDescriptor(node, node.getTextRange())); + } + for (ASTNode child : node.getChildren(null)) { + collectDescriptorsRecursively(child, document, descriptors); + } + } + + @Nullable + @Override + public String getPlaceholderText(@NotNull ASTNode node) { + final IElementType type = node.getElementType(); + if (type == JsonElementTypes.OBJECT) { + return "{...}"; + } + else if (type == JsonElementTypes.ARRAY) { + return "[...]"; + } + return "..."; + } + + @Override + public boolean isCollapsedByDefault(@NotNull ASTNode node) { + return false; + } + + private static boolean spanMultipleLines(@NotNull ASTNode node, @NotNull Document document) { + final TextRange range = node.getTextRange(); + return document.getLineNumber(range.getStartOffset()) < document.getLineNumber(range.getEndOffset()); + } +} diff --git a/json/tests/test/com/intellij/json/JsonCompletionTest.java b/json/tests/test/com/intellij/json/JsonCompletionTest.java index efde53dcbcfe..0a7be0975f9f 100644 --- a/json/tests/test/com/intellij/json/JsonCompletionTest.java +++ b/json/tests/test/com/intellij/json/JsonCompletionTest.java @@ -9,11 +9,6 @@ public class JsonCompletionTest extends JsonTestCase { private static final String[] KEYWORDS = new String[]{"true", "false", "null"}; private static final String[] NOTHING = ArrayUtil.EMPTY_STRING_ARRAY; - @Override - protected boolean isCommunity() { - return true; - } - public void testInsideArrayElement1() throws Exception { doTest(KEYWORDS); } diff --git a/json/tests/test/com/intellij/json/JsonFoldingTest.java b/json/tests/test/com/intellij/json/JsonFoldingTest.java new file mode 100644 index 000000000000..11415369f767 --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonFoldingTest.java @@ -0,0 +1,19 @@ +package com.intellij.json; + +/** + * @author Mikhail Golubev + */ +public class JsonFoldingTest extends JsonTestCase { + private void doTest() { + myFixture.testFolding(getTestDataPath() + "/folding/" + getTestName(false) + ".json"); + } + + + public void testArrayFolding() { + doTest(); + } + + public void testObjectFolding() { + doTest(); + } +} diff --git a/json/tests/test/com/intellij/json/JsonParsingTest.java b/json/tests/test/com/intellij/json/JsonParsingTest.java index 74eab90632fe..5fc7c9902b98 100644 --- a/json/tests/test/com/intellij/json/JsonParsingTest.java +++ b/json/tests/test/com/intellij/json/JsonParsingTest.java @@ -2,10 +2,12 @@ package com.intellij.json; import com.intellij.testFramework.ParsingTestCase; import com.intellij.testFramework.PlatformTestUtil; +import com.intellij.testFramework.TestDataPath; /** * @author Mikhail Golubev */ +@TestDataPath("$CONTENT_ROOT/testData/psi/") public class JsonParsingTest extends ParsingTestCase { public JsonParsingTest() { super("psi", "json", new JsonParserDefinition()); diff --git a/json/tests/test/com/intellij/json/JsonTestCase.java b/json/tests/test/com/intellij/json/JsonTestCase.java index 5cbaf0e0697c..a24de36ef07f 100644 --- a/json/tests/test/com/intellij/json/JsonTestCase.java +++ b/json/tests/test/com/intellij/json/JsonTestCase.java @@ -29,4 +29,9 @@ public abstract class JsonTestCase extends CodeInsightFixtureTestCase { public String getBasePath() { return "/json/tests/testData"; } + + @Override + protected boolean isCommunity() { + return true; + } } \ No newline at end of file diff --git a/json/tests/testData/folding/ArrayFolding.json b/json/tests/testData/folding/ArrayFolding.json new file mode 100644 index 000000000000..7a139ce2ff19 --- /dev/null +++ b/json/tests/testData/folding/ArrayFolding.json @@ -0,0 +1,5 @@ +["foo", + ["inline"], + [1, + 2] + "bar"] \ No newline at end of file diff --git a/json/tests/testData/folding/ObjectFolding.json b/json/tests/testData/folding/ObjectFolding.json new file mode 100644 index 000000000000..f7f489ee690f --- /dev/null +++ b/json/tests/testData/folding/ObjectFolding.json @@ -0,0 +1,7 @@ +{ + "foo": null, + "bar": {"inline": true}, + "baz": { + "nested": true + } +} \ No newline at end of file diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index 1a170eae0e51..a3fc13cfe04a 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -32,6 +32,7 @@ + Date: Mon, 25 Aug 2014 16:09:05 +0400 Subject: [PATCH 42/85] Use SmartEnterProcessorWithFixers for JSON smart enter implementation --- .../smartEnter/JsonSmartEnterProcessor.java | 98 +++++++++++++++++++ .../src/META-INF/JsonPlugin.xml | 1 + 2 files changed, 99 insertions(+) create mode 100644 json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java diff --git a/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java b/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java new file mode 100644 index 000000000000..7d406b2993af --- /dev/null +++ b/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java @@ -0,0 +1,98 @@ +package com.intellij.json.smartEnter; + +import com.intellij.json.JsonElementTypes; +import com.intellij.json.psi.JsonArray; +import com.intellij.json.psi.JsonFile; +import com.intellij.json.psi.JsonProperty; +import com.intellij.json.psi.JsonValue; +import com.intellij.lang.SmartEnterProcessorWithFixers; +import com.intellij.openapi.diagnostic.Logger; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * This processor allows + *
    + *
  • Insert colon after key inside object property
  • + *
  • Insert comma after array element or object property
  • + *
+ * + * @author Mikhail Golubev + */ +public class JsonSmartEnterProcessor extends SmartEnterProcessorWithFixers { + public static final Logger LOG = Logger.getInstance(JsonSmartEnterProcessor.class); + + public JsonSmartEnterProcessor() { + addFixers(new JsonObjectPropertyFixer(), new JsonArrayElementFixer()); + addEnterProcessors(new JsonEnterProcessor()); + } + + @Override + protected void collectAdditionalElements(@NotNull PsiElement element, @NotNull List result) { + // include all parents as well + PsiElement parent = element.getParent(); + while (parent != null && !(parent instanceof JsonFile)) { + result.add(parent); + parent = parent.getParent(); + } + } + + private static boolean terminatedOnCurrentLine(@NotNull Editor editor, @NotNull PsiElement element) { + final Document document = editor.getDocument(); + final int caretOffset = editor.getCaretModel().getCurrentCaret().getOffset(); + final int elementEndOffset = element.getTextRange().getEndOffset(); + if (document.getLineNumber(elementEndOffset) != document.getLineNumber(caretOffset)) { + return false; + } + final PsiElement nextLeaf = PsiTreeUtil.nextLeaf(element); + return nextLeaf == null || (nextLeaf instanceof PsiWhiteSpace && nextLeaf.getText().contains("\n")); + } + + private static boolean isFollowedByComma(@NotNull PsiElement element) { + final PsiElement nextLeaf = PsiTreeUtil.nextVisibleLeaf(element); + return nextLeaf != null && nextLeaf.getNode().getElementType() == JsonElementTypes.COMMA; + } + + private static class JsonArrayElementFixer extends SmartEnterProcessorWithFixers.Fixer{ + @Override + public void apply(@NotNull Editor editor, @NotNull JsonSmartEnterProcessor processor, @NotNull PsiElement element) + throws IncorrectOperationException { + if (element instanceof JsonValue && element.getParent() instanceof JsonArray) { + final JsonValue arrayElement = (JsonValue)element; + if (terminatedOnCurrentLine(editor, arrayElement) && !isFollowedByComma(element)) { + editor.getDocument().insertString(arrayElement.getTextRange().getEndOffset(), ","); + } + } + } + } + + private static class JsonObjectPropertyFixer extends SmartEnterProcessorWithFixers.Fixer { + @Override + public void apply(@NotNull Editor editor, @NotNull JsonSmartEnterProcessor processor, @NotNull PsiElement element) + throws IncorrectOperationException { + if (element instanceof JsonProperty) { + final JsonValue jsonValue = ((JsonProperty)element).getValue(); + // TODO find workaround for grammar in cases like {"foo": 42 "bar": null} (note missing comma) + if (jsonValue != null && terminatedOnCurrentLine(editor, jsonValue) && !isFollowedByComma(jsonValue)) { + editor.getDocument().insertString(jsonValue.getTextRange().getEndOffset(), ","); + } + } + } + } + + private static class JsonEnterProcessor extends SmartEnterProcessorWithFixers.FixEnterProcessor { + @Override + public boolean doEnter(PsiElement atCaret, PsiFile file, @NotNull Editor editor, boolean modified) { + plainEnter(editor); + return true; + } + } +} diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index a3fc13cfe04a..a301d56f91da 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -33,6 +33,7 @@ + Date: Mon, 25 Aug 2014 16:51:27 +0400 Subject: [PATCH 43/85] Remove redundant getValueList from JsonProperty interface --- json/gen/com/intellij/json/psi/JsonProperty.java | 3 --- json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java | 6 ------ json/src/json.bnf | 1 + 3 files changed, 1 insertion(+), 9 deletions(-) diff --git a/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java index 95b38f3fd2eb..86f8867360ca 100644 --- a/json/gen/com/intellij/json/psi/JsonProperty.java +++ b/json/gen/com/intellij/json/psi/JsonProperty.java @@ -8,9 +8,6 @@ import com.intellij.psi.PsiNamedElement; public interface JsonProperty extends JsonElement, PsiNamedElement { - @NotNull - List getValueList(); - @NotNull String getName(); diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java index b559f2164661..cce03924e3d5 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java @@ -21,12 +21,6 @@ public class JsonPropertyImpl extends JsonPropertyMixin implements JsonProperty else super.accept(visitor); } - @Override - @NotNull - public List getValueList() { - return PsiTreeUtil.getChildrenOfTypeAsList(this, JsonValue.class); - } - @NotNull public String getName() { return JsonPsiImplUtils.getName(this); diff --git a/json/src/json.bnf b/json/src/json.bnf index 818a133ba404..6fbc69ccaaa1 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -62,6 +62,7 @@ property ::= string_literal ':' value { getName getNameElement getValue + value="" ] mixin="com.intellij.json.psi.impl.JsonPropertyMixin" recoverWhile = not_brace_or_comma From b17bb2e4a30b7fbdaa7bab24931b704adbaae96b Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 25 Aug 2014 19:19:11 +0400 Subject: [PATCH 44/85] Add auxiliary empty interface to extend PsiNamedElement --- json/gen/com/intellij/json/psi/JsonProperty.java | 3 +-- json/gen/com/intellij/json/psi/JsonVisitor.java | 5 ++--- json/src/com/intellij/json/psi/JsonNamedElement.java | 11 +++++++++++ json/src/json.bnf | 4 ++-- 4 files changed, 16 insertions(+), 7 deletions(-) create mode 100644 json/src/com/intellij/json/psi/JsonNamedElement.java diff --git a/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java index 86f8867360ca..756024ab507d 100644 --- a/json/gen/com/intellij/json/psi/JsonProperty.java +++ b/json/gen/com/intellij/json/psi/JsonProperty.java @@ -4,9 +4,8 @@ package com.intellij.json.psi; import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiNamedElement; -public interface JsonProperty extends JsonElement, PsiNamedElement { +public interface JsonProperty extends JsonNamedElement { @NotNull String getName(); diff --git a/json/gen/com/intellij/json/psi/JsonVisitor.java b/json/gen/com/intellij/json/psi/JsonVisitor.java index b30a1a345eee..8c0c33cb5cc9 100644 --- a/json/gen/com/intellij/json/psi/JsonVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonVisitor.java @@ -3,7 +3,6 @@ package com.intellij.json.psi; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElementVisitor; -import com.intellij.psi.PsiNamedElement; public class JsonVisitor extends PsiElementVisitor { @@ -32,7 +31,7 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitProperty(@NotNull JsonProperty o) { - visitPsiNamedElement(o); + visitNamedElement(o); } public void visitStringLiteral(@NotNull JsonStringLiteral o) { @@ -43,7 +42,7 @@ public class JsonVisitor extends PsiElementVisitor { visitElement(o); } - public void visitPsiNamedElement(@NotNull PsiNamedElement o) { + public void visitNamedElement(@NotNull JsonNamedElement o) { visitElement(o); } diff --git a/json/src/com/intellij/json/psi/JsonNamedElement.java b/json/src/com/intellij/json/psi/JsonNamedElement.java new file mode 100644 index 000000000000..ee65e7186c78 --- /dev/null +++ b/json/src/com/intellij/json/psi/JsonNamedElement.java @@ -0,0 +1,11 @@ +package com.intellij.json.psi; + +import com.intellij.psi.PsiNamedElement; + +/** + * Empty interface as workaround for inability to specify two interfaces in BNF grammar. + * + * @author Mikhail Golubev + */ +public interface JsonNamedElement extends JsonElement, PsiNamedElement{ +} diff --git a/json/src/json.bnf b/json/src/json.bnf index 6fbc69ccaaa1..be09c80c0db3 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -42,8 +42,7 @@ extends("object|array|literal")=value extends("string_literal|number_literal|boolean_literal|null_literal")=literal - implements("property")="com.intellij.psi.PsiNamedElement" - implements("property")="com.intellij.json.psi.JsonElement" + implements("property")="com.intellij.json.psi.JsonNamedElement" } json ::= object | array @@ -62,6 +61,7 @@ property ::= string_literal ':' value { getName getNameElement getValue + // suppress getValueList() accessor value="" ] mixin="com.intellij.json.psi.impl.JsonPropertyMixin" From dc6a62f77a524d39632af8276ad1923d40ef13bd Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 25 Aug 2014 19:47:29 +0400 Subject: [PATCH 45/85] Proper way to handle missing commas in JSON literals (thanks to Sergey Savenko) --- json/gen/com/intellij/json/JsonParser.java | 189 +++++++++--------- .../smartEnter/JsonSmartEnterProcessor.java | 5 +- json/src/json.bnf | 28 +-- 3 files changed, 109 insertions(+), 113 deletions(-) diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 0d8df20539ee..7e54545840d8 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -66,7 +66,7 @@ public class JsonParser implements PsiParser { }; /* ********************************************************** */ - // '[' [array_elements] ']' + // '[' array_element* ']' public static boolean array(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array")) return false; if (!nextTokenIs(builder_, L_BRACKET)) return false; @@ -81,63 +81,53 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } - // [array_elements] + // array_element* private static boolean array_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_1")) return false; - array_elements(builder_, level_ + 1); - return true; - } - - /* ********************************************************** */ - // value - static boolean array_element(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "array_element")) return false; - boolean result_; - Marker marker_ = enter_section_(builder_, level_, _NONE_, null); - result_ = value(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, null, result_, false, not_bracket_or_comma_parser_); - return result_; - } - - /* ********************************************************** */ - // array_element (',' array_element)* - static boolean array_elements(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "array_elements")) return false; - boolean result_; - boolean pinned_; - Marker marker_ = enter_section_(builder_, level_, _NONE_, null); - result_ = array_element(builder_, level_ + 1); - pinned_ = result_; // pin = 1 - result_ = result_ && array_elements_1(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, null, result_, pinned_, null); - return result_ || pinned_; - } - - // (',' array_element)* - private static boolean array_elements_1(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "array_elements_1")) return false; int pos_ = current_position_(builder_); while (true) { - if (!array_elements_1_0(builder_, level_ + 1)) break; - if (!empty_element_parsed_guard_(builder_, "array_elements_1", pos_)) break; + if (!array_element(builder_, level_ + 1)) break; + if (!empty_element_parsed_guard_(builder_, "array_1", pos_)) break; pos_ = current_position_(builder_); } return true; } - // ',' array_element - private static boolean array_elements_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "array_elements_1_0")) return false; + /* ********************************************************** */ + // value (','|&']') + static boolean array_element(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_element")) return false; boolean result_; boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); - result_ = consumeToken(builder_, COMMA); + result_ = value(builder_, level_ + 1); pinned_ = result_; // pin = 1 - result_ = result_ && array_element(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, null, result_, pinned_, null); + result_ = result_ && array_element_1(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, pinned_, not_bracket_or_next_value_parser_); return result_ || pinned_; } + // ','|&']' + private static boolean array_element_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_element_1")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, COMMA); + if (!result_) result_ = array_element_1_1(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // &']' + private static boolean array_element_1_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "array_element_1_1")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_, level_, _AND_, null); + result_ = consumeToken(builder_, R_BRACKET); + exit_section_(builder_, level_, marker_, null, result_, false, null); + return result_; + } + /* ********************************************************** */ // TRUE | FALSE public static boolean boolean_literal(PsiBuilder builder_, int level_) { @@ -179,45 +169,45 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // !('}'|',') - static boolean not_brace_or_comma(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "not_brace_or_comma")) return false; + // !('}'|value) + static boolean not_brace_or_next_value(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "not_brace_or_next_value")) return false; boolean result_; Marker marker_ = enter_section_(builder_, level_, _NOT_, null); - result_ = !not_brace_or_comma_0(builder_, level_ + 1); + result_ = !not_brace_or_next_value_0(builder_, level_ + 1); exit_section_(builder_, level_, marker_, null, result_, false, null); return result_; } - // '}'|',' - private static boolean not_brace_or_comma_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "not_brace_or_comma_0")) return false; + // '}'|value + private static boolean not_brace_or_next_value_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "not_brace_or_next_value_0")) return false; boolean result_; Marker marker_ = enter_section_(builder_); result_ = consumeToken(builder_, R_CURLY); - if (!result_) result_ = consumeToken(builder_, COMMA); + if (!result_) result_ = value(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; } /* ********************************************************** */ - // !(']'|',') - static boolean not_bracket_or_comma(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "not_bracket_or_comma")) return false; + // !(']'|value) + static boolean not_bracket_or_next_value(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "not_bracket_or_next_value")) return false; boolean result_; Marker marker_ = enter_section_(builder_, level_, _NOT_, null); - result_ = !not_bracket_or_comma_0(builder_, level_ + 1); + result_ = !not_bracket_or_next_value_0(builder_, level_ + 1); exit_section_(builder_, level_, marker_, null, result_, false, null); return result_; } - // ']'|',' - private static boolean not_bracket_or_comma_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "not_bracket_or_comma_0")) return false; + // ']'|value + private static boolean not_bracket_or_next_value_0(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "not_bracket_or_next_value_0")) return false; boolean result_; Marker marker_ = enter_section_(builder_); result_ = consumeToken(builder_, R_BRACKET); - if (!result_) result_ = consumeToken(builder_, COMMA); + if (!result_) result_ = value(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; } @@ -247,7 +237,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // '{' [properties] '}' + // '{' object_element* '}' public static boolean object(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object")) return false; if (!nextTokenIs(builder_, L_CURLY)) return false; @@ -262,65 +252,66 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } - // [properties] + // object_element* private static boolean object_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object_1")) return false; - properties(builder_, level_ + 1); - return true; - } - - /* ********************************************************** */ - // property (',' property)* - static boolean properties(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "properties")) return false; - if (!nextTokenIs(builder_, STRING)) return false; - boolean result_; - boolean pinned_; - Marker marker_ = enter_section_(builder_, level_, _NONE_, null); - result_ = property(builder_, level_ + 1); - pinned_ = result_; // pin = 1 - result_ = result_ && properties_1(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, null, result_, pinned_, null); - return result_ || pinned_; - } - - // (',' property)* - private static boolean properties_1(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "properties_1")) return false; int pos_ = current_position_(builder_); while (true) { - if (!properties_1_0(builder_, level_ + 1)) break; - if (!empty_element_parsed_guard_(builder_, "properties_1", pos_)) break; + if (!object_element(builder_, level_ + 1)) break; + if (!empty_element_parsed_guard_(builder_, "object_1", pos_)) break; pos_ = current_position_(builder_); } return true; } - // ',' property - private static boolean properties_1_0(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "properties_1_0")) return false; + /* ********************************************************** */ + // property (','|&'}') + static boolean object_element(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "object_element")) return false; boolean result_; boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, null); - result_ = consumeToken(builder_, COMMA); + result_ = property(builder_, level_ + 1); pinned_ = result_; // pin = 1 - result_ = result_ && property(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, null, result_, pinned_, null); + result_ = result_ && object_element_1(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, pinned_, not_brace_or_next_value_parser_); return result_ || pinned_; } + // ','|&'}' + private static boolean object_element_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "object_element_1")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, COMMA); + if (!result_) result_ = object_element_1_1(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + + // &'}' + private static boolean object_element_1_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "object_element_1_1")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_, level_, _AND_, null); + result_ = consumeToken(builder_, R_CURLY); + exit_section_(builder_, level_, marker_, null, result_, false, null); + return result_; + } + /* ********************************************************** */ // string_literal ':' value public static boolean property(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property")) return false; + if (!nextTokenIs(builder_, STRING)) return false; boolean result_; boolean pinned_; - Marker marker_ = enter_section_(builder_, level_, _NONE_, ""); + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = string_literal(builder_, level_ + 1); - result_ = result_ && consumeToken(builder_, COLON); - pinned_ = result_; // pin = 2 - result_ = result_ && value(builder_, level_ + 1); - exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, not_brace_or_comma_parser_); + pinned_ = result_; // pin = 1 + result_ = result_ && report_error_(builder_, consumeToken(builder_, COLON)); + result_ = pinned_ && value(builder_, level_ + 1) && result_; + exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, null); return result_ || pinned_; } @@ -349,14 +340,14 @@ public class JsonParser implements PsiParser { return result_; } - final static Parser not_brace_or_comma_parser_ = new Parser() { + final static Parser not_brace_or_next_value_parser_ = new Parser() { public boolean parse(PsiBuilder builder_, int level_) { - return not_brace_or_comma(builder_, level_ + 1); + return not_brace_or_next_value(builder_, level_ + 1); } }; - final static Parser not_bracket_or_comma_parser_ = new Parser() { + final static Parser not_bracket_or_next_value_parser_ = new Parser() { public boolean parse(PsiBuilder builder_, int level_) { - return not_bracket_or_comma(builder_, level_ + 1); + return not_bracket_or_next_value(builder_, level_ + 1); } }; } diff --git a/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java b/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java index 7d406b2993af..6c435f13a70d 100644 --- a/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java +++ b/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java @@ -10,6 +10,7 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; import com.intellij.psi.util.PsiTreeUtil; @@ -52,7 +53,8 @@ public class JsonSmartEnterProcessor extends SmartEnterProcessorWithFixers { if (document.getLineNumber(elementEndOffset) != document.getLineNumber(caretOffset)) { return false; } - final PsiElement nextLeaf = PsiTreeUtil.nextLeaf(element); + // Skip empty PsiError elements if comma is missing + PsiElement nextLeaf = PsiTreeUtil.nextLeaf(element, true); return nextLeaf == null || (nextLeaf instanceof PsiWhiteSpace && nextLeaf.getText().contains("\n")); } @@ -80,7 +82,6 @@ public class JsonSmartEnterProcessor extends SmartEnterProcessorWithFixers { throws IncorrectOperationException { if (element instanceof JsonProperty) { final JsonValue jsonValue = ((JsonProperty)element).getValue(); - // TODO find workaround for grammar in cases like {"foo": 42 "bar": null} (note missing comma) if (jsonValue != null && terminatedOnCurrentLine(editor, jsonValue) && !isFollowedByComma(jsonValue)) { editor.getDocument().insertString(jsonValue.getTextRange().getEndOffset(), ","); } diff --git a/json/src/json.bnf b/json/src/json.bnf index be09c80c0db3..a2d1dbc70702 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -47,16 +47,21 @@ json ::= object | array -object ::= '{' [properties] '}' { +object ::= '{' object_element* '}' { pin=1 methods=[ findProperty ] } -private properties ::= property (',' property)* { pin(".*")=1 } -property ::= string_literal ':' value { - pin = 2 +private object_element ::= property (','|&'}') { + recoverWhile = not_brace_or_next_value + pin = 1 +} + +// Hackity-hack to parse array elements and properties even if separating commas are missing, +// TODO: Find out if there is any simpler way to do so in GrammarKit +property ::= string_literal ':' value { methods=[ getName getNameElement @@ -65,16 +70,15 @@ property ::= string_literal ':' value { value="" ] mixin="com.intellij.json.psi.impl.JsonPropertyMixin" - recoverWhile = not_brace_or_comma + pin = 1 } -array ::= '[' [array_elements] ']' { +array ::= '[' array_element* ']' { pin=1 } + +private array_element ::= value (','|&']') { + recoverWhile = not_bracket_or_next_value pin=1 } -private array_elements ::= array_element (',' array_element)* { pin(".*")=1 } -private array_element ::= value { - recoverWhile = not_bracket_or_comma -} string_literal ::= STRING number_literal ::= NUMBER @@ -88,5 +92,5 @@ literal ::= string_literal | number_literal | boolean_literal | null_literal { value ::= object | array | literal // Recoveries -private not_bracket_or_comma ::= !(']'|',') -private not_brace_or_comma ::= !('}'|',') \ No newline at end of file +private not_bracket_or_next_value ::= !(']'|value) +private not_brace_or_next_value ::= !('}'|value) \ No newline at end of file From 040e8b5fe433cf2f57761f349ab43ab48402efc8 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 26 Aug 2014 16:05:05 +0400 Subject: [PATCH 46/85] Smart enter processor for JSON inserts missing colon for properties --- json/gen/com/intellij/json/JsonParser.java | 18 +++++- .../smartEnter/JsonSmartEnterProcessor.java | 57 +++++++++++++------ json/src/json.bnf | 8 +-- .../com/intellij/json/JsonSmartEnterTest.java | 46 +++++++++++++++ .../ColonInsertedAfterPropertyKey.json | 3 + .../ColonInsertedAfterPropertyKey_after.json | 3 + .../CommaInsertedAfterArrayElement.json | 3 + .../CommaInsertedAfterArrayElement_after.json | 4 ++ .../CommaInsertedAfterProperty.json | 3 + ...sertedAfterPropertyWithMultilineValue.json | 7 +++ ...AfterPropertyWithMultilineValue_after.json | 8 +++ .../CommaInsertedAfterProperty_after.json | 4 ++ 12 files changed, 139 insertions(+), 25 deletions(-) create mode 100644 json/tests/test/com/intellij/json/JsonSmartEnterTest.java create mode 100644 json/tests/testData/smartEnter/ColonInsertedAfterPropertyKey.json create mode 100644 json/tests/testData/smartEnter/ColonInsertedAfterPropertyKey_after.json create mode 100644 json/tests/testData/smartEnter/CommaInsertedAfterArrayElement.json create mode 100644 json/tests/testData/smartEnter/CommaInsertedAfterArrayElement_after.json create mode 100644 json/tests/testData/smartEnter/CommaInsertedAfterProperty.json create mode 100644 json/tests/testData/smartEnter/CommaInsertedAfterPropertyWithMultilineValue.json create mode 100644 json/tests/testData/smartEnter/CommaInsertedAfterPropertyWithMultilineValue_after.json create mode 100644 json/tests/testData/smartEnter/CommaInsertedAfterProperty_after.json diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 7e54545840d8..4d3847e13087 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -300,7 +300,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // string_literal ':' value + // string_literal (':' value) public static boolean property(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property")) return false; if (!nextTokenIs(builder_, STRING)) return false; @@ -309,12 +309,24 @@ public class JsonParser implements PsiParser { Marker marker_ = enter_section_(builder_, level_, _NONE_, null); result_ = string_literal(builder_, level_ + 1); pinned_ = result_; // pin = 1 - result_ = result_ && report_error_(builder_, consumeToken(builder_, COLON)); - result_ = pinned_ && value(builder_, level_ + 1) && result_; + result_ = result_ && property_1(builder_, level_ + 1); exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, null); return result_ || pinned_; } + // ':' value + private static boolean property_1(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "property_1")) return false; + boolean result_; + boolean pinned_; + Marker marker_ = enter_section_(builder_, level_, _NONE_, null); + result_ = consumeToken(builder_, COLON); + pinned_ = result_; // pin = 1 + result_ = result_ && value(builder_, level_ + 1); + exit_section_(builder_, level_, marker_, null, result_, pinned_, null); + return result_ || pinned_; + } + /* ********************************************************** */ // STRING public static boolean string_literal(PsiBuilder builder_, int level_) { diff --git a/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java b/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java index 6c435f13a70d..b70b152d9f23 100644 --- a/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java +++ b/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java @@ -1,29 +1,28 @@ package com.intellij.json.smartEnter; -import com.intellij.json.JsonElementTypes; -import com.intellij.json.psi.JsonArray; -import com.intellij.json.psi.JsonFile; -import com.intellij.json.psi.JsonProperty; -import com.intellij.json.psi.JsonValue; +import com.intellij.json.psi.*; import com.intellij.lang.SmartEnterProcessorWithFixers; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiErrorElement; import com.intellij.psi.PsiFile; import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.tree.IElementType; import com.intellij.psi.util.PsiTreeUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NotNull; import java.util.List; +import static com.intellij.json.JsonElementTypes.COLON; +import static com.intellij.json.JsonElementTypes.COMMA; + /** * This processor allows *
    - *
  • Insert colon after key inside object property
  • - *
  • Insert comma after array element or object property
  • + *
  • Insert colon after key inside object property
  • + *
  • Insert comma after array element or object property
  • *
* * @author Mikhail Golubev @@ -31,6 +30,8 @@ import java.util.List; public class JsonSmartEnterProcessor extends SmartEnterProcessorWithFixers { public static final Logger LOG = Logger.getInstance(JsonSmartEnterProcessor.class); + private boolean myShouldAddNewline = false; + public JsonSmartEnterProcessor() { addFixers(new JsonObjectPropertyFixer(), new JsonArrayElementFixer()); addEnterProcessors(new JsonEnterProcessor()); @@ -58,41 +59,61 @@ public class JsonSmartEnterProcessor extends SmartEnterProcessorWithFixers { return nextLeaf == null || (nextLeaf instanceof PsiWhiteSpace && nextLeaf.getText().contains("\n")); } - private static boolean isFollowedByComma(@NotNull PsiElement element) { + private static boolean isFollowedByTerminal(@NotNull PsiElement element, IElementType type) { final PsiElement nextLeaf = PsiTreeUtil.nextVisibleLeaf(element); - return nextLeaf != null && nextLeaf.getNode().getElementType() == JsonElementTypes.COMMA; + return nextLeaf != null && nextLeaf.getNode().getElementType() == type; } - private static class JsonArrayElementFixer extends SmartEnterProcessorWithFixers.Fixer{ + private static class JsonArrayElementFixer extends SmartEnterProcessorWithFixers.Fixer { @Override public void apply(@NotNull Editor editor, @NotNull JsonSmartEnterProcessor processor, @NotNull PsiElement element) throws IncorrectOperationException { if (element instanceof JsonValue && element.getParent() instanceof JsonArray) { final JsonValue arrayElement = (JsonValue)element; - if (terminatedOnCurrentLine(editor, arrayElement) && !isFollowedByComma(element)) { + if (terminatedOnCurrentLine(editor, arrayElement) && !isFollowedByTerminal(element, COMMA)) { editor.getDocument().insertString(arrayElement.getTextRange().getEndOffset(), ","); + processor.myShouldAddNewline = true; } } } } - private static class JsonObjectPropertyFixer extends SmartEnterProcessorWithFixers.Fixer { + private class JsonObjectPropertyFixer extends SmartEnterProcessorWithFixers.Fixer { @Override public void apply(@NotNull Editor editor, @NotNull JsonSmartEnterProcessor processor, @NotNull PsiElement element) throws IncorrectOperationException { if (element instanceof JsonProperty) { - final JsonValue jsonValue = ((JsonProperty)element).getValue(); - if (jsonValue != null && terminatedOnCurrentLine(editor, jsonValue) && !isFollowedByComma(jsonValue)) { - editor.getDocument().insertString(jsonValue.getTextRange().getEndOffset(), ","); + final JsonValue propertyValue = ((JsonProperty)element).getValue(); + if (propertyValue != null) { + if (terminatedOnCurrentLine(editor, propertyValue) && !isFollowedByTerminal(propertyValue, COMMA)) { + editor.getDocument().insertString(propertyValue.getTextRange().getEndOffset(), ","); + processor.myShouldAddNewline = true; + } + } + else { + final JsonStringLiteral propertyKey = ((JsonProperty)element).getNameElement(); + final int keyEndOffset = propertyKey.getTextRange().getEndOffset(); + //processor.myFirstErrorOffset = keyEndOffset; + if (terminatedOnCurrentLine(editor, propertyKey) && !isFollowedByTerminal(propertyKey, COLON)) { + processor.myFirstErrorOffset = keyEndOffset + 2; + editor.getDocument().insertString(keyEndOffset, ": "); + } } } } } - private static class JsonEnterProcessor extends SmartEnterProcessorWithFixers.FixEnterProcessor { + private class JsonEnterProcessor extends SmartEnterProcessorWithFixers.FixEnterProcessor { @Override public boolean doEnter(PsiElement atCaret, PsiFile file, @NotNull Editor editor, boolean modified) { - plainEnter(editor); + if (myShouldAddNewline) { + try { + plainEnter(editor); + } + finally { + myShouldAddNewline = false; + } + } return true; } } diff --git a/json/src/json.bnf b/json/src/json.bnf index a2d1dbc70702..3d0573f3a05b 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -54,14 +54,14 @@ object ::= '{' object_element* '}' { ] } +// Hackity-hack to parse array elements and properties even if separating commas are missing, +// TODO: Find out if there is any simpler way to do so in GrammarKit private object_element ::= property (','|&'}') { recoverWhile = not_brace_or_next_value pin = 1 } -// Hackity-hack to parse array elements and properties even if separating commas are missing, -// TODO: Find out if there is any simpler way to do so in GrammarKit -property ::= string_literal ':' value { +property ::= string_literal (':' value) { methods=[ getName getNameElement @@ -70,7 +70,7 @@ property ::= string_literal ':' value { value="" ] mixin="com.intellij.json.psi.impl.JsonPropertyMixin" - pin = 1 + pin(".*")=1 } array ::= '[' array_element* ']' { pin=1 } diff --git a/json/tests/test/com/intellij/json/JsonSmartEnterTest.java b/json/tests/test/com/intellij/json/JsonSmartEnterTest.java new file mode 100644 index 000000000000..fd6d35b6b78b --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonSmartEnterTest.java @@ -0,0 +1,46 @@ +package com.intellij.json; + +import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessor; +import com.intellij.codeInsight.editorActions.smartEnter.SmartEnterProcessors; +import com.intellij.openapi.application.Result; +import com.intellij.openapi.command.WriteCommandAction; +import com.intellij.openapi.editor.Editor; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author Mikhail Golubev + */ +public class JsonSmartEnterTest extends JsonTestCase { + public void doTest() { + myFixture.configureByFile("smartEnter/" + getTestName(false) + ".json"); + final List processors = SmartEnterProcessors.INSTANCE.forKey(JsonLanguage.INSTANCE); + new WriteCommandAction(myFixture.getProject()) { + @Override + protected void run(@NotNull Result result) throws Throwable { + final Editor editor = myFixture.getEditor(); + for (SmartEnterProcessor processor : processors) { + processor.process(myFixture.getProject(), editor, myFixture.getFile()); + } + } + }.execute(); + myFixture.checkResultByFile("smartEnter/" + getTestName(false) + "_after.json", true); + } + + public void testCommaInsertedAfterArrayElement() { + doTest(); + } + + public void testCommaInsertedAfterProperty() { + doTest(); + } + + public void testCommaInsertedAfterPropertyWithMultilineValue() { + doTest(); + } + + public void testColonInsertedAfterPropertyKey() { + doTest(); + } +} diff --git a/json/tests/testData/smartEnter/ColonInsertedAfterPropertyKey.json b/json/tests/testData/smartEnter/ColonInsertedAfterPropertyKey.json new file mode 100644 index 000000000000..d455652f8c66 --- /dev/null +++ b/json/tests/testData/smartEnter/ColonInsertedAfterPropertyKey.json @@ -0,0 +1,3 @@ +{ + "foo" +} \ No newline at end of file diff --git a/json/tests/testData/smartEnter/ColonInsertedAfterPropertyKey_after.json b/json/tests/testData/smartEnter/ColonInsertedAfterPropertyKey_after.json new file mode 100644 index 000000000000..2e3ee074bff2 --- /dev/null +++ b/json/tests/testData/smartEnter/ColonInsertedAfterPropertyKey_after.json @@ -0,0 +1,3 @@ +{ + "foo": +} \ No newline at end of file diff --git a/json/tests/testData/smartEnter/CommaInsertedAfterArrayElement.json b/json/tests/testData/smartEnter/CommaInsertedAfterArrayElement.json new file mode 100644 index 000000000000..1cb4da384b85 --- /dev/null +++ b/json/tests/testData/smartEnter/CommaInsertedAfterArrayElement.json @@ -0,0 +1,3 @@ +[ + 42 +] \ No newline at end of file diff --git a/json/tests/testData/smartEnter/CommaInsertedAfterArrayElement_after.json b/json/tests/testData/smartEnter/CommaInsertedAfterArrayElement_after.json new file mode 100644 index 000000000000..c3fd82625e27 --- /dev/null +++ b/json/tests/testData/smartEnter/CommaInsertedAfterArrayElement_after.json @@ -0,0 +1,4 @@ +[ + 42, + +] \ No newline at end of file diff --git a/json/tests/testData/smartEnter/CommaInsertedAfterProperty.json b/json/tests/testData/smartEnter/CommaInsertedAfterProperty.json new file mode 100644 index 000000000000..6484206f1ed1 --- /dev/null +++ b/json/tests/testData/smartEnter/CommaInsertedAfterProperty.json @@ -0,0 +1,3 @@ +{ + "foo": 42 +} \ No newline at end of file diff --git a/json/tests/testData/smartEnter/CommaInsertedAfterPropertyWithMultilineValue.json b/json/tests/testData/smartEnter/CommaInsertedAfterPropertyWithMultilineValue.json new file mode 100644 index 000000000000..4f520847d143 --- /dev/null +++ b/json/tests/testData/smartEnter/CommaInsertedAfterPropertyWithMultilineValue.json @@ -0,0 +1,7 @@ +{ + "foo": [ + 1, + 2, + 3 + ] +} \ No newline at end of file diff --git a/json/tests/testData/smartEnter/CommaInsertedAfterPropertyWithMultilineValue_after.json b/json/tests/testData/smartEnter/CommaInsertedAfterPropertyWithMultilineValue_after.json new file mode 100644 index 000000000000..f9a951b655f8 --- /dev/null +++ b/json/tests/testData/smartEnter/CommaInsertedAfterPropertyWithMultilineValue_after.json @@ -0,0 +1,8 @@ +{ + "foo": [ + 1, + 2, + 3 + ], + +} \ No newline at end of file diff --git a/json/tests/testData/smartEnter/CommaInsertedAfterProperty_after.json b/json/tests/testData/smartEnter/CommaInsertedAfterProperty_after.json new file mode 100644 index 000000000000..65f93e6709eb --- /dev/null +++ b/json/tests/testData/smartEnter/CommaInsertedAfterProperty_after.json @@ -0,0 +1,4 @@ +{ + "foo": 42, + +} \ No newline at end of file From 2f6959b75c2154d3cd7d3ae8e945355e11e89e38 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 26 Aug 2014 16:26:21 +0400 Subject: [PATCH 47/85] Simplify JSON breadcrumbs to take into account only property names --- json/src/com/intellij/json/JsonUtil.java | 27 +++++++++++++++ .../breadcrumbs/JsonBreadcrumbsProvider.java | 34 ++++++------------- 2 files changed, 38 insertions(+), 23 deletions(-) create mode 100644 json/src/com/intellij/json/JsonUtil.java diff --git a/json/src/com/intellij/json/JsonUtil.java b/json/src/com/intellij/json/JsonUtil.java new file mode 100644 index 000000000000..e0c93a033f06 --- /dev/null +++ b/json/src/com/intellij/json/JsonUtil.java @@ -0,0 +1,27 @@ +package com.intellij.json; + +import com.intellij.json.psi.JsonArray; +import com.intellij.json.psi.JsonValue; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +@SuppressWarnings("UnusedDeclaration") +public class JsonUtil { + private JsonUtil() { + // empty + } + + + /** + * Checks that PSI element represents item of JSON array. + * + * @param element PSI element to check + * @return whether this PSI element is array element + */ + private static boolean isArrayElement(@NotNull PsiElement element) { + return element instanceof JsonValue && element.getParent() instanceof JsonArray; + } +} diff --git a/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java b/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java index 4f76b9a3bfba..2684bcbe1fb6 100644 --- a/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java +++ b/json/src/com/intellij/json/breadcrumbs/JsonBreadcrumbsProvider.java @@ -1,17 +1,13 @@ package com.intellij.json.breadcrumbs; import com.intellij.json.JsonLanguage; -import com.intellij.json.psi.JsonValue; import com.intellij.lang.Language; import com.intellij.psi.PsiElement; import com.intellij.xml.breadcrumbs.BreadcrumbsInfoProvider; -import com.intellij.json.psi.JsonArray; import com.intellij.json.psi.JsonProperty; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; -import java.util.List; - /** * @author Mikhail Golubev */ @@ -25,24 +21,24 @@ public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider { @Override public boolean acceptElement(@NotNull PsiElement e) { - return isProperty(e) || isArrayElement(e); + return e instanceof JsonProperty; } @NotNull @Override public String getElementInfo(@NotNull PsiElement e) { - if (isProperty(e)) { + if (e instanceof JsonProperty) { return ((JsonProperty)e).getName(); } - else if (isArrayElement(e)) { - List elements = ((JsonArray)e.getParent()).getValueList(); - for (int i = 0; i < elements.size(); i++) { - if (e == elements.get(i)) { - return String.valueOf(i); - } - } - } - throw new AssertionError("Breadcrumbs can be taken only for JsonProperty or JsonArray's element"); + //else if (isArrayElement(e)) { + // List elements = ((JsonArray)e.getParent()).getValueList(); + // for (int i = 0; i < elements.size(); i++) { + // if (e == elements.get(i)) { + // return String.valueOf(i); + // } + // } + //} + throw new AssertionError("Breadcrumbs can be extracted only from JsonProperty elements"); } @Nullable @@ -50,12 +46,4 @@ public class JsonBreadcrumbsProvider extends BreadcrumbsInfoProvider { public String getElementTooltip(@NotNull PsiElement e) { return null; } - - private static boolean isProperty(PsiElement element) { - return element instanceof JsonProperty; - } - - private static boolean isArrayElement(PsiElement element) { - return element instanceof JsonValue && element.getParent() instanceof JsonArray; - } } From 9bb709beb393e1659283f48090bc41f08e4babfe Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 26 Aug 2014 16:54:53 +0400 Subject: [PATCH 48/85] Get rid of JsonNamedElement interface --- json/gen/com/intellij/json/psi/JsonProperty.java | 3 ++- json/gen/com/intellij/json/psi/JsonVisitor.java | 8 +++----- json/src/com/intellij/json/psi/JsonNamedElement.java | 11 ----------- json/src/json.bnf | 5 ++++- 4 files changed, 9 insertions(+), 18 deletions(-) delete mode 100644 json/src/com/intellij/json/psi/JsonNamedElement.java diff --git a/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java index 756024ab507d..86f8867360ca 100644 --- a/json/gen/com/intellij/json/psi/JsonProperty.java +++ b/json/gen/com/intellij/json/psi/JsonProperty.java @@ -4,8 +4,9 @@ package com.intellij.json.psi; import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNamedElement; -public interface JsonProperty extends JsonNamedElement { +public interface JsonProperty extends JsonElement, PsiNamedElement { @NotNull String getName(); diff --git a/json/gen/com/intellij/json/psi/JsonVisitor.java b/json/gen/com/intellij/json/psi/JsonVisitor.java index 8c0c33cb5cc9..aadae923d624 100644 --- a/json/gen/com/intellij/json/psi/JsonVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonVisitor.java @@ -3,6 +3,7 @@ package com.intellij.json.psi; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiNamedElement; public class JsonVisitor extends PsiElementVisitor { @@ -31,7 +32,8 @@ public class JsonVisitor extends PsiElementVisitor { } public void visitProperty(@NotNull JsonProperty o) { - visitNamedElement(o); + visitElement(o); + // visitPsiNamedElement(o); } public void visitStringLiteral(@NotNull JsonStringLiteral o) { @@ -42,10 +44,6 @@ public class JsonVisitor extends PsiElementVisitor { visitElement(o); } - public void visitNamedElement(@NotNull JsonNamedElement o) { - visitElement(o); - } - public void visitElement(@NotNull JsonElement o) { visitElement(o); } diff --git a/json/src/com/intellij/json/psi/JsonNamedElement.java b/json/src/com/intellij/json/psi/JsonNamedElement.java deleted file mode 100644 index ee65e7186c78..000000000000 --- a/json/src/com/intellij/json/psi/JsonNamedElement.java +++ /dev/null @@ -1,11 +0,0 @@ -package com.intellij.json.psi; - -import com.intellij.psi.PsiNamedElement; - -/** - * Empty interface as workaround for inability to specify two interfaces in BNF grammar. - * - * @author Mikhail Golubev - */ -public interface JsonNamedElement extends JsonElement, PsiNamedElement{ -} diff --git a/json/src/json.bnf b/json/src/json.bnf index 3d0573f3a05b..6cdab08b01e9 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -42,7 +42,10 @@ extends("object|array|literal")=value extends("string_literal|number_literal|boolean_literal|null_literal")=literal - implements("property")="com.intellij.json.psi.JsonNamedElement" + implements("property")=[ + "com.intellij.json.psi.JsonElement" + "com.intellij.psi.PsiNamedElement" + ] } json ::= object | array From 33afe64888a2981d0664e7cc870c98dab541cffc Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 3 Sep 2014 18:08:56 +0400 Subject: [PATCH 49/85] Add comments and single quotes string literals to JSON grammar --- .../com/intellij/json/JsonElementTypes.java | 2 + json/gen/com/intellij/json/_JsonLexer.flex | 32 ++-- json/gen/com/intellij/json/_JsonLexer.java | 140 ++++++++++-------- .../intellij/json/JsonParserDefinition.java | 4 +- json/src/json.bnf | 8 +- .../com/intellij/json/JsonParsingTest.java | 9 ++ json/tests/testData/psi/Comments.json | 15 ++ json/tests/testData/psi/Comments.txt | 27 ++++ json/tests/testData/psi/StringLiterals.json | 4 + tools/lexer/jflex-1.4/bin/jflex | 2 +- 10 files changed, 160 insertions(+), 83 deletions(-) create mode 100644 json/tests/testData/psi/Comments.json create mode 100644 json/tests/testData/psi/Comments.txt create mode 100644 json/tests/testData/psi/StringLiterals.json diff --git a/json/gen/com/intellij/json/JsonElementTypes.java b/json/gen/com/intellij/json/JsonElementTypes.java index 602797280783..aa3d749ce7d2 100644 --- a/json/gen/com/intellij/json/JsonElementTypes.java +++ b/json/gen/com/intellij/json/JsonElementTypes.java @@ -18,9 +18,11 @@ public interface JsonElementTypes { IElementType STRING_LITERAL = new JsonElementType("STRING_LITERAL"); IElementType VALUE = new JsonElementType("VALUE"); + IElementType BLOCK_COMMENT = new JsonTokenType("BLOCK_COMMENT"); IElementType COLON = new JsonTokenType(":"); IElementType COMMA = new JsonTokenType(","); IElementType FALSE = new JsonTokenType("false"); + IElementType LINE_COMMENT = new JsonTokenType("LINE_COMMENT"); IElementType L_BRACKET = new JsonTokenType("["); IElementType L_CURLY = new JsonTokenType("{"); IElementType NULL = new JsonTokenType("null"); diff --git a/json/gen/com/intellij/json/_JsonLexer.flex b/json/gen/com/intellij/json/_JsonLexer.flex index 0083719fb629..af5784b60498 100644 --- a/json/gen/com/intellij/json/_JsonLexer.flex +++ b/json/gen/com/intellij/json/_JsonLexer.flex @@ -22,27 +22,31 @@ EOL="\r"|"\n"|"\r\n" LINE_WS=[\ \t\f] WHITE_SPACE=({LINE_WS}|{EOL})+ -STRING=\"([^\\\"\r\n]|\\[^\r\n])*\"? +LINE_COMMENT="//".* +BLOCK_COMMENT="/"\*([^*]|\*+[^*/])*(\*+"/")? +STRING=\"([^\\\"\r\n]|\\[^\r\n])*\"?|'([^\\\"\r\n]|\\[^\r\n])*'? NUMBER=-?[0-9]+(\.[0-9]+([eE][+-]?[0-9]+)?)? TEXT=[a-zA-Z_0-9]+ %% { - {WHITE_SPACE} { return com.intellij.psi.TokenType.WHITE_SPACE; } + {WHITE_SPACE} { return com.intellij.psi.TokenType.WHITE_SPACE; } - "{" { return L_CURLY; } - "}" { return R_CURLY; } - "[" { return L_BRACKET; } - "]" { return R_BRACKET; } - "," { return COMMA; } - ":" { return COLON; } - "true" { return TRUE; } - "false" { return FALSE; } - "null" { return NULL; } + "{" { return L_CURLY; } + "}" { return R_CURLY; } + "[" { return L_BRACKET; } + "]" { return R_BRACKET; } + "," { return COMMA; } + ":" { return COLON; } + "true" { return TRUE; } + "false" { return FALSE; } + "null" { return NULL; } - {STRING} { return STRING; } - {NUMBER} { return NUMBER; } - {TEXT} { return TEXT; } + {LINE_COMMENT} { return LINE_COMMENT; } + {BLOCK_COMMENT} { return BLOCK_COMMENT; } + {STRING} { return STRING; } + {NUMBER} { return NUMBER; } + {TEXT} { return TEXT; } [^] { return com.intellij.psi.TokenType.BAD_CHARACTER; } } diff --git a/json/gen/com/intellij/json/_JsonLexer.java b/json/gen/com/intellij/json/_JsonLexer.java index 1cf42f524aa8..396b5eb6e571 100644 --- a/json/gen/com/intellij/json/_JsonLexer.java +++ b/json/gen/com/intellij/json/_JsonLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 7/15/14 2:07 PM */ +/* The following code was generated by JFlex 1.4.3 on 9/3/14 6:05 PM */ package com.intellij.json; import com.intellij.lexer.*; @@ -9,8 +9,8 @@ import static com.intellij.json.JsonElementTypes.*; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 7/15/14 2:07 PM from the specification file - * /home/east825/develop/repos/IDEA-branch/community/plugins/json/gen/com/intellij/json/_JsonLexer.flex + * on 9/3/14 6:05 PM from the specification file + * /home/east825/develop/repos/IDEA/community/json/gen/com/intellij/json/_JsonLexer.flex */ public class _JsonLexer implements FlexLexer { /** initial size of the lookahead buffer */ @@ -33,11 +33,11 @@ public class _JsonLexer implements FlexLexer { * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = - "\11\0\1\2\1\1\1\0\1\2\1\1\22\0\1\2\1\0\1\3"+ - "\10\0\1\11\1\17\1\5\1\7\1\0\12\6\1\20\6\0\4\12"+ - "\1\10\25\12\1\15\1\4\1\16\1\0\1\12\1\0\1\26\3\12"+ - "\1\24\1\25\5\12\1\27\1\12\1\31\3\12\1\22\1\30\1\21"+ - "\1\23\5\12\1\13\1\0\1\14\uff82\0"; + "\11\0\1\3\1\2\1\0\1\3\1\1\22\0\1\3\1\0\1\6"+ + "\4\0\1\10\2\0\1\5\1\15\1\23\1\11\1\13\1\4\12\12"+ + "\1\24\6\0\4\16\1\14\25\16\1\21\1\7\1\22\1\0\1\16"+ + "\1\0\1\32\3\16\1\30\1\31\5\16\1\33\1\16\1\35\3\16"+ + "\1\26\1\34\1\25\1\27\5\16\1\17\1\0\1\20\uff82\0"; /** * Translates characters to character classes @@ -50,13 +50,14 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\1\0\1\1\1\2\1\3\1\1\1\4\1\5\1\6"+ - "\1\7\1\10\1\11\1\12\1\13\3\5\1\3\1\0"+ - "\1\4\1\0\3\5\1\4\3\5\1\0\1\14\1\5"+ - "\1\15\1\0\1\4\1\16"; + "\1\0\1\1\1\2\1\1\2\3\1\1\1\4\1\5"+ + "\1\6\1\7\1\10\1\11\1\12\1\13\3\5\1\14"+ + "\1\15\1\3\2\0\1\4\1\0\3\5\1\0\1\4"+ + "\3\5\1\15\1\0\1\16\1\5\1\17\1\0\1\4"+ + "\1\20"; private static int [] zzUnpackAction() { - int [] result = new int[34]; + int [] result = new int[41]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -81,14 +82,15 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\32\0\64\0\116\0\150\0\202\0\234\0\32"+ - "\0\32\0\32\0\32\0\32\0\32\0\266\0\320\0\352"+ - "\0\32\0\u0104\0\u011e\0\u0138\0\u0152\0\u016c\0\u0186\0\u01a0"+ - "\0\u01ba\0\u01d4\0\u01ee\0\u0208\0\234\0\u0222\0\234\0\u023c"+ - "\0\u023c\0\234"; + "\0\0\0\36\0\74\0\132\0\170\0\226\0\264\0\322"+ + "\0\360\0\36\0\36\0\36\0\36\0\36\0\36\0\u010e"+ + "\0\u012c\0\u014a\0\u0168\0\u0186\0\36\0\u01a4\0\u01c2\0\u01e0"+ + "\0\u01fe\0\u021c\0\u023a\0\u0258\0\u0276\0\u0294\0\u02b2\0\u02d0"+ + "\0\u02ee\0\36\0\u030c\0\360\0\u032a\0\360\0\u0348\0\u0348"+ + "\0\360"; private static int [] zzUnpackRowMap() { - int [] result = new int[34]; + int [] result = new int[41]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -111,31 +113,34 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_TRANS = zzUnpackTrans(); private static final String ZZ_TRANS_PACKED_0 = - "\1\2\2\3\1\4\1\2\1\5\1\6\1\2\1\7"+ - "\1\2\1\7\1\10\1\11\1\12\1\13\1\14\1\15"+ - "\1\16\3\7\1\17\3\7\1\20\33\0\2\3\27\0"+ - "\1\4\1\0\1\4\1\21\1\22\25\4\6\0\1\23"+ - "\31\0\1\6\1\24\1\7\1\0\1\7\6\0\11\7"+ - "\6\0\1\7\1\0\1\7\1\0\1\7\6\0\11\7"+ - "\6\0\1\7\1\0\1\7\1\0\1\7\6\0\1\7"+ - "\1\25\7\7\6\0\1\7\1\0\1\7\1\0\1\7"+ - "\6\0\5\7\1\26\3\7\6\0\1\7\1\0\1\7"+ - "\1\0\1\7\6\0\2\7\1\27\6\7\1\4\1\0"+ - "\30\4\6\0\1\23\1\24\30\0\1\30\31\0\1\7"+ - "\1\0\1\7\1\0\1\7\6\0\2\7\1\31\6\7"+ - "\6\0\1\7\1\0\1\7\1\0\1\7\6\0\6\7"+ - "\1\32\2\7\6\0\1\7\1\0\1\7\1\0\1\7"+ - "\6\0\6\7\1\33\2\7\6\0\1\30\1\0\1\34"+ - "\13\0\1\34\13\0\1\7\1\0\1\7\1\0\1\7"+ - "\6\0\3\7\1\35\5\7\6\0\1\7\1\0\1\7"+ - "\1\0\1\7\6\0\7\7\1\36\1\7\6\0\1\7"+ - "\1\0\1\7\1\0\1\7\6\0\6\7\1\37\2\7"+ - "\5\0\1\40\1\41\2\0\1\40\26\0\1\7\1\0"+ - "\1\7\1\0\1\7\6\0\3\7\1\42\5\7\6\0"+ - "\1\41\23\0"; + "\1\2\3\3\1\4\1\2\1\5\1\2\1\6\1\7"+ + "\1\10\1\2\1\11\1\2\1\11\1\12\1\13\1\14"+ + "\1\15\1\16\1\17\1\20\3\11\1\21\3\11\1\22"+ + "\37\0\3\3\36\0\1\23\1\24\30\0\1\5\2\0"+ + "\3\5\1\25\1\26\26\5\1\6\2\0\3\6\1\0"+ + "\1\27\26\6\12\0\1\30\35\0\1\10\1\31\1\11"+ + "\1\0\1\11\6\0\11\11\12\0\1\11\1\0\1\11"+ + "\1\0\1\11\6\0\11\11\12\0\1\11\1\0\1\11"+ + "\1\0\1\11\6\0\1\11\1\32\7\11\12\0\1\11"+ + "\1\0\1\11\1\0\1\11\6\0\5\11\1\33\3\11"+ + "\12\0\1\11\1\0\1\11\1\0\1\11\6\0\2\11"+ + "\1\34\6\11\2\23\1\0\33\23\5\24\1\35\30\24"+ + "\1\5\2\0\33\5\1\6\2\0\33\6\12\0\1\30"+ + "\1\31\34\0\1\36\35\0\1\11\1\0\1\11\1\0"+ + "\1\11\6\0\2\11\1\37\6\11\12\0\1\11\1\0"+ + "\1\11\1\0\1\11\6\0\6\11\1\40\2\11\12\0"+ + "\1\11\1\0\1\11\1\0\1\11\6\0\6\11\1\41"+ + "\2\11\4\24\1\42\1\35\30\24\12\0\1\36\1\0"+ + "\1\43\13\0\1\43\17\0\1\11\1\0\1\11\1\0"+ + "\1\11\6\0\3\11\1\44\5\11\12\0\1\11\1\0"+ + "\1\11\1\0\1\11\6\0\7\11\1\45\1\11\12\0"+ + "\1\11\1\0\1\11\1\0\1\11\6\0\6\11\1\46"+ + "\2\11\11\0\1\47\1\50\2\0\1\47\32\0\1\11"+ + "\1\0\1\11\1\0\1\11\6\0\3\11\1\51\5\11"+ + "\12\0\1\50\23\0"; private static int [] zzUnpackTrans() { - int [] result = new int[598]; + int [] result = new int[870]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -176,11 +181,12 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\1\0\1\11\5\1\6\11\3\1\1\11\1\0\1\1"+ - "\1\0\7\1\1\0\3\1\1\0\2\1"; + "\1\0\1\11\7\1\6\11\5\1\1\11\2\0\1\1"+ + "\1\0\3\1\1\0\4\1\1\11\1\0\3\1\1\0"+ + "\2\1"; private static int [] zzUnpackAttribute() { - int [] result = new int[34]; + int [] result = new int[41]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -265,7 +271,7 @@ public class _JsonLexer implements FlexLexer { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ - while (i < 92) { + while (i < 98) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); @@ -478,59 +484,67 @@ public class _JsonLexer implements FlexLexer { case 7: { return R_CURLY; } - case 15: break; + case 17: break; case 6: { return L_CURLY; } - case 16: break; - case 13: + case 18: break; + case 15: { return NULL; } - case 17: break; + case 19: break; case 8: { return L_BRACKET; } - case 18: break; + case 20: break; + case 12: + { return LINE_COMMENT; + } + case 21: break; case 10: { return COMMA; } - case 19: break; + case 22: break; case 2: { return com.intellij.psi.TokenType.WHITE_SPACE; } - case 20: break; + case 23: break; case 5: { return TEXT; } - case 21: break; + case 24: break; case 1: { return com.intellij.psi.TokenType.BAD_CHARACTER; } - case 22: break; - case 12: + case 25: break; + case 14: { return TRUE; } - case 23: break; + case 26: break; case 11: { return COLON; } - case 24: break; + case 27: break; case 3: { return STRING; } - case 25: break; + case 28: break; case 4: { return NUMBER; } - case 26: break; - case 14: + case 29: break; + case 16: { return FALSE; } - case 27: break; + case 30: break; + case 13: + { return BLOCK_COMMENT; + } + case 31: break; case 9: { return R_BRACKET; } - case 28: break; + case 32: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; diff --git a/json/src/com/intellij/json/JsonParserDefinition.java b/json/src/com/intellij/json/JsonParserDefinition.java index 506072a36551..685cdea9e262 100644 --- a/json/src/com/intellij/json/JsonParserDefinition.java +++ b/json/src/com/intellij/json/JsonParserDefinition.java @@ -55,7 +55,7 @@ public class JsonParserDefinition implements ParserDefinition { @NotNull @Override public TokenSet getCommentTokens() { - return TokenSet.EMPTY; + return TokenSet.create(BLOCK_COMMENT, LINE_COMMENT); } @NotNull @@ -67,7 +67,7 @@ public class JsonParserDefinition implements ParserDefinition { @NotNull @Override public PsiElement createElement(ASTNode astNode) { - return JsonElementTypes.Factory.createElement(astNode); + return Factory.createElement(astNode); } @Override diff --git a/json/src/json.bnf b/json/src/json.bnf index 6cdab08b01e9..b4e8b334bb9f 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -19,16 +19,18 @@ R_CURLY='}' L_BRACKET='[' R_BRACKET=']' - + COMMA=',' COLON=':' - // COMMENT='regexp:"//.*|/\*.*?\*/"' + LINE_COMMENT='regexp://.*' + // "/*" ([^*]|\*+[^*/])* (\*+"/")? + BLOCK_COMMENT='regexp:/\*([^*]|\*+[^*/])*(\*+/)?' // else /\*(?:[^*]|\*[^/])*\*+/ // unclosed string literal matches till the line's end // any escape sequences included, illegal escapes are indicated by SyntaxHighlighter // and JsonStringLiteralAnnotator - STRING='regexp:"([^\\"\r\n]|\\[^\r\n])*"?' + STRING="regexp:\"([^\\\"\r\n]|\\[^\r\n])*\"?|'([^\\\"\r\n]|\\[^\r\n])*'?" // STRING='regexp:"([^\\"\r\n]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"?' NUMBER='regexp:-?\d+(\.\d+([eE][+-]?\d+)?)?' diff --git a/json/tests/test/com/intellij/json/JsonParsingTest.java b/json/tests/test/com/intellij/json/JsonParsingTest.java index 5fc7c9902b98..ab48ee1f4ab2 100644 --- a/json/tests/test/com/intellij/json/JsonParsingTest.java +++ b/json/tests/test/com/intellij/json/JsonParsingTest.java @@ -54,6 +54,15 @@ public class JsonParsingTest extends ParsingTestCase { // doTest(); //} + + public void testComments() { + doTest(); + } + + public void testStringLiterals() { + doTest(); + } + private void doTest() { doTest(true); } diff --git a/json/tests/testData/psi/Comments.json b/json/tests/testData/psi/Comments.json new file mode 100644 index 000000000000..60ad9bf4e447 --- /dev/null +++ b/json/tests/testData/psi/Comments.json @@ -0,0 +1,15 @@ +// End of line comment +{ +/**/ +/***/ +/*** */ +/** **/ +/* **/ +/*a*/ /*b*/ +/* C-style block comment */ +/* May span +multiple +lines + */ +} +/* And be incomplete \ No newline at end of file diff --git a/json/tests/testData/psi/Comments.txt b/json/tests/testData/psi/Comments.txt new file mode 100644 index 000000000000..7225a522186e --- /dev/null +++ b/json/tests/testData/psi/Comments.txt @@ -0,0 +1,27 @@ +JsonFile: Comments.json + PsiComment(LINE_COMMENT)('// End of line comment') + PsiWhiteSpace('\n') + JsonObject + PsiElement({)('{') + PsiWhiteSpace('\n') + PsiComment(BLOCK_COMMENT)('/**/') + PsiWhiteSpace('\n') + PsiComment(BLOCK_COMMENT)('/***/') + PsiWhiteSpace('\n') + PsiComment(BLOCK_COMMENT)('/*** */') + PsiWhiteSpace('\n') + PsiComment(BLOCK_COMMENT)('/** **/') + PsiWhiteSpace('\n') + PsiComment(BLOCK_COMMENT)('/* **/') + PsiWhiteSpace('\n') + PsiComment(BLOCK_COMMENT)('/*a*/') + PsiWhiteSpace(' ') + PsiComment(BLOCK_COMMENT)('/*b*/') + PsiWhiteSpace('\n') + PsiComment(BLOCK_COMMENT)('/* C-style block comment */') + PsiWhiteSpace('\n') + PsiComment(BLOCK_COMMENT)('/* May span\nmultiple\nlines\n */') + PsiWhiteSpace('\n') + PsiElement(})('}') + PsiWhiteSpace('\n') + PsiComment(BLOCK_COMMENT)('/* And be incomplete') \ No newline at end of file diff --git a/json/tests/testData/psi/StringLiterals.json b/json/tests/testData/psi/StringLiterals.json new file mode 100644 index 000000000000..e55eaff73c3b --- /dev/null +++ b/json/tests/testData/psi/StringLiterals.json @@ -0,0 +1,4 @@ +{ + 'foo': "bar", + "baz": 'quux' +} \ No newline at end of file diff --git a/tools/lexer/jflex-1.4/bin/jflex b/tools/lexer/jflex-1.4/bin/jflex index d6ad789e2490..65cb93efbbbb 100755 --- a/tools/lexer/jflex-1.4/bin/jflex +++ b/tools/lexer/jflex-1.4/bin/jflex @@ -1,4 +1,4 @@ -#! /bin/bash +#!/bin/bash # # JFlex start script $Revision$ # From 1f6da4996844c7e90bf1fc3f22511f867d90c757 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 3 Sep 2014 20:34:12 +0400 Subject: [PATCH 50/85] Rename JsonVisitor to JsonElementVisitor, add JsonRecursiveElementVisitor --- .../{JsonVisitor.java => JsonElementVisitor.java} | 2 +- .../com/intellij/json/psi/impl/JsonArrayImpl.java | 2 +- .../json/psi/impl/JsonBooleanLiteralImpl.java | 2 +- .../intellij/json/psi/impl/JsonLiteralImpl.java | 2 +- .../json/psi/impl/JsonNullLiteralImpl.java | 2 +- .../json/psi/impl/JsonNumberLiteralImpl.java | 2 +- .../com/intellij/json/psi/impl/JsonObjectImpl.java | 2 +- .../intellij/json/psi/impl/JsonPropertyImpl.java | 2 +- .../json/psi/impl/JsonStringLiteralImpl.java | 2 +- .../com/intellij/json/psi/impl/JsonValueImpl.java | 2 +- .../json/psi/impl/JsonRecursiveVisitor.java | 14 ++++++++++++++ json/src/json.bnf | 1 + 12 files changed, 25 insertions(+), 10 deletions(-) rename json/gen/com/intellij/json/psi/{JsonVisitor.java => JsonElementVisitor.java} (94%) create mode 100644 json/src/com/intellij/json/psi/impl/JsonRecursiveVisitor.java diff --git a/json/gen/com/intellij/json/psi/JsonVisitor.java b/json/gen/com/intellij/json/psi/JsonElementVisitor.java similarity index 94% rename from json/gen/com/intellij/json/psi/JsonVisitor.java rename to json/gen/com/intellij/json/psi/JsonElementVisitor.java index aadae923d624..9bd777e8af17 100644 --- a/json/gen/com/intellij/json/psi/JsonVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonElementVisitor.java @@ -5,7 +5,7 @@ import org.jetbrains.annotations.*; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiNamedElement; -public class JsonVisitor extends PsiElementVisitor { +public class JsonElementVisitor extends PsiElementVisitor { public void visitArray(@NotNull JsonArray o) { visitValue(o); diff --git a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java index 54a96032a755..01d067595e7c 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java @@ -17,7 +17,7 @@ public class JsonArrayImpl extends JsonValueImpl implements JsonArray { } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitArray(this); + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitArray(this); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java index 107879c43c83..3e8d340aab82 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonBooleanLiteralImpl.java @@ -17,7 +17,7 @@ public class JsonBooleanLiteralImpl extends JsonLiteralImpl implements JsonBoole } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitBooleanLiteral(this); + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitBooleanLiteral(this); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java index f56e64767964..da4d688e4873 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonLiteralImpl.java @@ -17,7 +17,7 @@ public class JsonLiteralImpl extends JsonLiteralMixin implements JsonLiteral { } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitLiteral(this); + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitLiteral(this); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java index 78454b01c6e5..c74a4616e5b8 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonNullLiteralImpl.java @@ -17,7 +17,7 @@ public class JsonNullLiteralImpl extends JsonLiteralImpl implements JsonNullLite } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitNullLiteral(this); + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitNullLiteral(this); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java index f4469bca25d6..84fe96bebdaf 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonNumberLiteralImpl.java @@ -17,7 +17,7 @@ public class JsonNumberLiteralImpl extends JsonLiteralImpl implements JsonNumber } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitNumberLiteral(this); + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitNumberLiteral(this); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java index ec3d4844a774..a9365b784e9b 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java @@ -17,7 +17,7 @@ public class JsonObjectImpl extends JsonValueImpl implements JsonObject { } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitObject(this); + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitObject(this); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java index cce03924e3d5..294161da503b 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java @@ -17,7 +17,7 @@ public class JsonPropertyImpl extends JsonPropertyMixin implements JsonProperty } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitProperty(this); + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitProperty(this); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java index e018ce64eb39..5dafe5898b70 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java @@ -17,7 +17,7 @@ public class JsonStringLiteralImpl extends JsonLiteralImpl implements JsonString } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitStringLiteral(this); + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitStringLiteral(this); else super.accept(visitor); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java b/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java index 4e80c409dacf..c8fe9a4682fe 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonValueImpl.java @@ -17,7 +17,7 @@ public class JsonValueImpl extends JsonElementImpl implements JsonValue { } public void accept(@NotNull PsiElementVisitor visitor) { - if (visitor instanceof JsonVisitor) ((JsonVisitor)visitor).visitValue(this); + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitValue(this); else super.accept(visitor); } diff --git a/json/src/com/intellij/json/psi/impl/JsonRecursiveVisitor.java b/json/src/com/intellij/json/psi/impl/JsonRecursiveVisitor.java new file mode 100644 index 000000000000..1c8a17e76f84 --- /dev/null +++ b/json/src/com/intellij/json/psi/impl/JsonRecursiveVisitor.java @@ -0,0 +1,14 @@ +package com.intellij.json.psi.impl; + +import com.intellij.json.psi.JsonElementVisitor; +import com.intellij.psi.PsiElement; + +/** + * @author Mikhail Golubev + */ +public class JsonRecursiveVisitor extends JsonElementVisitor { + + public void visitElement(final PsiElement element) { + element.acceptChildren(this); + } +} diff --git a/json/src/json.bnf b/json/src/json.bnf index b4e8b334bb9f..5ff7beadfa1b 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -7,6 +7,7 @@ elementTypeHolderClass = 'com.intellij.json.JsonElementTypes' elementTypeClass = 'com.intellij.json.JsonElementType' psiClassPrefix = "Json" + psiVisitorName = "JsonElementVisitor" psiImplUtilClass = 'com.intellij.json.psi.impl.JsonPsiImplUtils' tokenTypeClass = 'com.intellij.json.JsonTokenType' From 4b0510638e05f4e672653fa15a34fd02d98c76be Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 3 Sep 2014 21:44:13 +0400 Subject: [PATCH 51/85] Add simple JSON compliance annotator to highlight invalid elements --- .../intellij/json/psi/JsonElementVisitor.java | 3 +- json/src/com/intellij/json/JsonBundle.java | 36 +++++++++++++++++++ .../com/intellij/json/JsonBundle.properties | 8 +++++ .../JsonStandardComplianceAnnotator.java | 32 +++++++++++++++++ .../JsonStringLiteralAnnotator.java | 18 ++++------ .../src/META-INF/JsonPlugin.xml | 1 + 6 files changed, 86 insertions(+), 12 deletions(-) create mode 100644 json/src/com/intellij/json/JsonBundle.java create mode 100644 json/src/com/intellij/json/JsonBundle.properties create mode 100644 json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java diff --git a/json/gen/com/intellij/json/psi/JsonElementVisitor.java b/json/gen/com/intellij/json/psi/JsonElementVisitor.java index 9bd777e8af17..a38376347c50 100644 --- a/json/gen/com/intellij/json/psi/JsonElementVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonElementVisitor.java @@ -1,6 +1,7 @@ // This is a generated file. Not intended for manual editing. package com.intellij.json.psi; +import com.intellij.psi.PsiElement; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElementVisitor; import com.intellij.psi.PsiNamedElement; @@ -45,7 +46,7 @@ public class JsonElementVisitor extends PsiElementVisitor { } public void visitElement(@NotNull JsonElement o) { - visitElement(o); + visitElement((PsiElement)o); } } diff --git a/json/src/com/intellij/json/JsonBundle.java b/json/src/com/intellij/json/JsonBundle.java new file mode 100644 index 000000000000..231acde78d14 --- /dev/null +++ b/json/src/com/intellij/json/JsonBundle.java @@ -0,0 +1,36 @@ +package com.intellij.json; + +import com.intellij.CommonBundle; +import com.intellij.reference.SoftReference; +import org.jetbrains.annotations.NonNls; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.PropertyKey; + +import java.lang.ref.Reference; +import java.util.ResourceBundle; + +/** + * @author Mikhail Golubev + */ +public class JsonBundle { + + private static Reference ourBundle; + @NonNls private static final String BUNDLE = "com.intellij.json.JsonBundle"; + + private JsonBundle() { + // empty + } + + public static String message(@NotNull @PropertyKey(resourceBundle = BUNDLE) String key, @NotNull Object... params) { + return CommonBundle.message(getBundle(), key, params); + } + + private static ResourceBundle getBundle() { + ResourceBundle bundle = SoftReference.dereference(ourBundle); + if (bundle == null) { + bundle = ResourceBundle.getBundle(BUNDLE); + ourBundle = new SoftReference(bundle); + } + return bundle; + } +} diff --git a/json/src/com/intellij/json/JsonBundle.properties b/json/src/com/intellij/json/JsonBundle.properties new file mode 100644 index 000000000000..a802c4d1b34c --- /dev/null +++ b/json/src/com/intellij/json/JsonBundle.properties @@ -0,0 +1,8 @@ +# Annotators + +missing.closing.quote=Missing closing quote +illegal.escape.sequence=Illegal escape sequence +illegal.unicode.escape.sequence=Illegal unicode escape sequence + +compliance.problem.comments=JSON standard does not allow comments +compliance.problem.single.quoted.strings=JSON standard does not allow single quoted strings \ No newline at end of file diff --git a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java new file mode 100644 index 000000000000..04b3bb53cabb --- /dev/null +++ b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java @@ -0,0 +1,32 @@ +package com.intellij.json.codeinsight; + +import com.intellij.json.JsonBundle; +import com.intellij.json.psi.JsonStringLiteral; +import com.intellij.json.psi.impl.JsonRecursiveVisitor; +import com.intellij.lang.annotation.AnnotationHolder; +import com.intellij.lang.annotation.Annotator; +import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class JsonStandardComplianceAnnotator implements Annotator { + @Override + public void annotate(@NotNull final PsiElement element, @NotNull final AnnotationHolder holder) { + new JsonRecursiveVisitor() { + @Override + public void visitComment(PsiComment comment) { + holder.createErrorAnnotation(comment, JsonBundle.message("compliance.problem.comments")); + } + + @Override + public void visitStringLiteral(@NotNull JsonStringLiteral literal) { + if (literal.getText().startsWith("'")) { + holder.createErrorAnnotation(literal, JsonBundle.message("compliance.problem.single.quoted.strings")); + } + } + }.visitElement(element); + } +} diff --git a/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java b/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java index 92c63adfa746..ebb4d597e01c 100644 --- a/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java +++ b/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java @@ -1,12 +1,12 @@ package com.intellij.json.codeinsight; +import com.intellij.json.JsonBundle; +import com.intellij.json.psi.JsonStringLiteral; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.openapi.util.TextRange; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; -import com.intellij.json.psi.JsonStringLiteral; -import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; /** @@ -14,10 +14,6 @@ import org.jetbrains.annotations.NotNull; */ public class JsonStringLiteralAnnotator implements Annotator { - @NonNls public static final String MISSING_CLOSING_QUOTE = "Missing closing quote"; - @NonNls public static final String ILLEGAL_ESCAPE_SEQUENCE = "Illegal escape sequence"; - @NonNls public static final String ILLEGAL_UNICODE_ESCAPE_SEQUENCE = "Illegal unicode escape sequence"; - @Override public void annotate(@NotNull PsiElement element, @NotNull AnnotationHolder holder) { if (element instanceof JsonStringLiteral) { @@ -25,8 +21,8 @@ public class JsonStringLiteralAnnotator implements Annotator { int offset = element.getTextOffset(); int length = text.length(); // Check that string literal closed properly - if (length <= 1 || text.charAt(length - 1) != '\"' || quoteEscaped(text, length - 1)) { - holder.createErrorAnnotation(element.getTextRange(), MISSING_CLOSING_QUOTE); + if (length <= 1 || text.charAt(0) != text.charAt(length - 1) || quoteEscaped(text, length - 1)) { + holder.createErrorAnnotation(element.getTextRange(), JsonBundle.message("missing.closing.quote")); } // Check escape sequences validity int pos = 1; @@ -34,7 +30,7 @@ public class JsonStringLiteralAnnotator implements Annotator { if (text.charAt(pos) == '\\') { if (pos >= length - 1) { TextRange range = new TextRange(offset + pos, offset + pos + 1); - holder.createErrorAnnotation(range, ILLEGAL_ESCAPE_SEQUENCE); + holder.createErrorAnnotation(range, JsonBundle.message("illegal.escape.sequence")); break; } char next = text.charAt(pos + 1); @@ -54,7 +50,7 @@ public class JsonStringLiteralAnnotator implements Annotator { for (; i < pos + 6; i++) { if (i == length || !StringUtil.isHexDigit(text.charAt(i))) { TextRange range = new TextRange(offset + pos, offset + i); - holder.createErrorAnnotation(range, ILLEGAL_UNICODE_ESCAPE_SEQUENCE); + holder.createErrorAnnotation(range, JsonBundle.message("illegal.unicode.escape.sequence")); break; } } @@ -62,7 +58,7 @@ public class JsonStringLiteralAnnotator implements Annotator { break; default: TextRange range = new TextRange(offset + pos, offset + pos + 2); - holder.createErrorAnnotation(range, ILLEGAL_ESCAPE_SEQUENCE); + holder.createErrorAnnotation(range, JsonBundle.message("illegal.escape.sequence")); pos += 2; } } diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index a301d56f91da..faaf4b9ba6d7 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -31,6 +31,7 @@ + From b89ad912610319a13f0601969fec43fc8e50a046 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 3 Sep 2014 22:06:37 +0400 Subject: [PATCH 52/85] Split single and double quoted strings into independent token types --- .../com/intellij/json/JsonElementTypes.java | 3 +- json/gen/com/intellij/json/JsonParser.java | 15 +- json/gen/com/intellij/json/_JsonLexer.flex | 34 +++-- json/gen/com/intellij/json/_JsonLexer.java | 140 +++++++++--------- .../intellij/json/psi/JsonStringLiteral.java | 7 +- .../json/psi/impl/JsonStringLiteralImpl.java | 12 +- .../intellij/json/JsonParserDefinition.java | 2 +- .../json/JsonSyntaxHighlighterFactory.java | 11 +- .../json/psi/impl/JsonPsiImplUtils.java | 5 +- json/src/json.bnf | 5 +- .../com/intellij/json/JsonParsingTest.java | 6 +- .../testData/psi/NestedArrayLiterals.txt | 2 +- .../testData/psi/NestedObjectLiterals.txt | 6 +- json/tests/testData/psi/Simple1.txt | 14 +- json/tests/testData/psi/Simple2.txt | 6 +- .../testData/psi/TopLevelStringLiteral.txt | 2 +- 16 files changed, 148 insertions(+), 122 deletions(-) diff --git a/json/gen/com/intellij/json/JsonElementTypes.java b/json/gen/com/intellij/json/JsonElementTypes.java index aa3d749ce7d2..03c54db68824 100644 --- a/json/gen/com/intellij/json/JsonElementTypes.java +++ b/json/gen/com/intellij/json/JsonElementTypes.java @@ -21,6 +21,7 @@ public interface JsonElementTypes { IElementType BLOCK_COMMENT = new JsonTokenType("BLOCK_COMMENT"); IElementType COLON = new JsonTokenType(":"); IElementType COMMA = new JsonTokenType(","); + IElementType DOUBLE_QUOTED_STRING = new JsonTokenType("DOUBLE_QUOTED_STRING"); IElementType FALSE = new JsonTokenType("false"); IElementType LINE_COMMENT = new JsonTokenType("LINE_COMMENT"); IElementType L_BRACKET = new JsonTokenType("["); @@ -29,7 +30,7 @@ public interface JsonElementTypes { IElementType NUMBER = new JsonTokenType("NUMBER"); IElementType R_BRACKET = new JsonTokenType("]"); IElementType R_CURLY = new JsonTokenType("}"); - IElementType STRING = new JsonTokenType("STRING"); + IElementType SINGLE_QUOTED_STRING = new JsonTokenType("SINGLE_QUOTED_STRING"); IElementType TEXT = new JsonTokenType("TEXT"); IElementType TRUE = new JsonTokenType("true"); diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 4d3847e13087..a184d6b85101 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -303,10 +303,10 @@ public class JsonParser implements PsiParser { // string_literal (':' value) public static boolean property(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property")) return false; - if (!nextTokenIs(builder_, STRING)) return false; + if (!nextTokenIs(builder_, "", DOUBLE_QUOTED_STRING, SINGLE_QUOTED_STRING)) return false; boolean result_; boolean pinned_; - Marker marker_ = enter_section_(builder_, level_, _NONE_, null); + Marker marker_ = enter_section_(builder_, level_, _NONE_, ""); result_ = string_literal(builder_, level_ + 1); pinned_ = result_; // pin = 1 result_ = result_ && property_1(builder_, level_ + 1); @@ -328,14 +328,15 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // STRING + // SINGLE_QUOTED_STRING | DOUBLE_QUOTED_STRING public static boolean string_literal(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "string_literal")) return false; - if (!nextTokenIs(builder_, STRING)) return false; + if (!nextTokenIs(builder_, "", DOUBLE_QUOTED_STRING, SINGLE_QUOTED_STRING)) return false; boolean result_; - Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, STRING); - exit_section_(builder_, marker_, STRING_LITERAL, result_); + Marker marker_ = enter_section_(builder_, level_, _COLLAPSE_, ""); + result_ = consumeToken(builder_, SINGLE_QUOTED_STRING); + if (!result_) result_ = consumeToken(builder_, DOUBLE_QUOTED_STRING); + exit_section_(builder_, level_, marker_, STRING_LITERAL, result_, false, null); return result_; } diff --git a/json/gen/com/intellij/json/_JsonLexer.flex b/json/gen/com/intellij/json/_JsonLexer.flex index af5784b60498..e9a464f1704b 100644 --- a/json/gen/com/intellij/json/_JsonLexer.flex +++ b/json/gen/com/intellij/json/_JsonLexer.flex @@ -24,29 +24,31 @@ WHITE_SPACE=({LINE_WS}|{EOL})+ LINE_COMMENT="//".* BLOCK_COMMENT="/"\*([^*]|\*+[^*/])*(\*+"/")? -STRING=\"([^\\\"\r\n]|\\[^\r\n])*\"?|'([^\\\"\r\n]|\\[^\r\n])*'? +DOUBLE_QUOTED_STRING=\"([^\\\"\r\n]|\\[^\r\n])*\"? +SINGLE_QUOTED_STRING='([^\\'\r\n]|\\[^\r\n])*'? NUMBER=-?[0-9]+(\.[0-9]+([eE][+-]?[0-9]+)?)? TEXT=[a-zA-Z_0-9]+ %% { - {WHITE_SPACE} { return com.intellij.psi.TokenType.WHITE_SPACE; } + {WHITE_SPACE} { return com.intellij.psi.TokenType.WHITE_SPACE; } - "{" { return L_CURLY; } - "}" { return R_CURLY; } - "[" { return L_BRACKET; } - "]" { return R_BRACKET; } - "," { return COMMA; } - ":" { return COLON; } - "true" { return TRUE; } - "false" { return FALSE; } - "null" { return NULL; } + "{" { return L_CURLY; } + "}" { return R_CURLY; } + "[" { return L_BRACKET; } + "]" { return R_BRACKET; } + "," { return COMMA; } + ":" { return COLON; } + "true" { return TRUE; } + "false" { return FALSE; } + "null" { return NULL; } - {LINE_COMMENT} { return LINE_COMMENT; } - {BLOCK_COMMENT} { return BLOCK_COMMENT; } - {STRING} { return STRING; } - {NUMBER} { return NUMBER; } - {TEXT} { return TEXT; } + {LINE_COMMENT} { return LINE_COMMENT; } + {BLOCK_COMMENT} { return BLOCK_COMMENT; } + {DOUBLE_QUOTED_STRING} { return DOUBLE_QUOTED_STRING; } + {SINGLE_QUOTED_STRING} { return SINGLE_QUOTED_STRING; } + {NUMBER} { return NUMBER; } + {TEXT} { return TEXT; } [^] { return com.intellij.psi.TokenType.BAD_CHARACTER; } } diff --git a/json/gen/com/intellij/json/_JsonLexer.java b/json/gen/com/intellij/json/_JsonLexer.java index 396b5eb6e571..d669db593033 100644 --- a/json/gen/com/intellij/json/_JsonLexer.java +++ b/json/gen/com/intellij/json/_JsonLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 9/3/14 6:05 PM */ +/* The following code was generated by JFlex 1.4.3 on 9/3/14 9:55 PM */ package com.intellij.json; import com.intellij.lexer.*; @@ -9,7 +9,7 @@ import static com.intellij.json.JsonElementTypes.*; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 9/3/14 6:05 PM from the specification file + * on 9/3/14 9:55 PM from the specification file * /home/east825/develop/repos/IDEA/community/json/gen/com/intellij/json/_JsonLexer.flex */ public class _JsonLexer implements FlexLexer { @@ -50,14 +50,14 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ACTION = zzUnpackAction(); private static final String ZZ_ACTION_PACKED_0 = - "\1\0\1\1\1\2\1\1\2\3\1\1\1\4\1\5"+ - "\1\6\1\7\1\10\1\11\1\12\1\13\3\5\1\14"+ - "\1\15\1\3\2\0\1\4\1\0\3\5\1\0\1\4"+ - "\3\5\1\15\1\0\1\16\1\5\1\17\1\0\1\4"+ - "\1\20"; + "\1\0\1\1\1\2\1\1\1\3\1\4\1\1\1\5"+ + "\1\6\1\7\1\10\1\11\1\12\1\13\1\14\3\6"+ + "\1\15\1\16\1\3\2\0\1\4\1\5\1\0\3\6"+ + "\1\0\1\5\3\6\1\16\1\0\1\17\1\6\1\20"+ + "\1\0\1\5\1\21"; private static int [] zzUnpackAction() { - int [] result = new int[41]; + int [] result = new int[42]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -84,13 +84,13 @@ public class _JsonLexer implements FlexLexer { private static final String ZZ_ROWMAP_PACKED_0 = "\0\0\0\36\0\74\0\132\0\170\0\226\0\264\0\322"+ "\0\360\0\36\0\36\0\36\0\36\0\36\0\36\0\u010e"+ - "\0\u012c\0\u014a\0\u0168\0\u0186\0\36\0\u01a4\0\u01c2\0\u01e0"+ - "\0\u01fe\0\u021c\0\u023a\0\u0258\0\u0276\0\u0294\0\u02b2\0\u02d0"+ - "\0\u02ee\0\36\0\u030c\0\360\0\u032a\0\360\0\u0348\0\u0348"+ - "\0\360"; + "\0\u012c\0\u014a\0\u0168\0\u0186\0\36\0\u01a4\0\u01c2\0\36"+ + "\0\u01e0\0\u01fe\0\u021c\0\u023a\0\u0258\0\u0276\0\u0294\0\u02b2"+ + "\0\u02d0\0\u02ee\0\36\0\u030c\0\360\0\u032a\0\360\0\u0348"+ + "\0\u0348\0\360"; private static int [] zzUnpackRowMap() { - int [] result = new int[41]; + int [] result = new int[42]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -117,27 +117,27 @@ public class _JsonLexer implements FlexLexer { "\1\10\1\2\1\11\1\2\1\11\1\12\1\13\1\14"+ "\1\15\1\16\1\17\1\20\3\11\1\21\3\11\1\22"+ "\37\0\3\3\36\0\1\23\1\24\30\0\1\5\2\0"+ - "\3\5\1\25\1\26\26\5\1\6\2\0\3\6\1\0"+ - "\1\27\26\6\12\0\1\30\35\0\1\10\1\31\1\11"+ + "\3\5\1\25\1\26\26\5\1\6\2\0\4\6\1\27"+ + "\1\30\25\6\12\0\1\31\35\0\1\10\1\32\1\11"+ "\1\0\1\11\6\0\11\11\12\0\1\11\1\0\1\11"+ "\1\0\1\11\6\0\11\11\12\0\1\11\1\0\1\11"+ - "\1\0\1\11\6\0\1\11\1\32\7\11\12\0\1\11"+ - "\1\0\1\11\1\0\1\11\6\0\5\11\1\33\3\11"+ + "\1\0\1\11\6\0\1\11\1\33\7\11\12\0\1\11"+ + "\1\0\1\11\1\0\1\11\6\0\5\11\1\34\3\11"+ "\12\0\1\11\1\0\1\11\1\0\1\11\6\0\2\11"+ - "\1\34\6\11\2\23\1\0\33\23\5\24\1\35\30\24"+ - "\1\5\2\0\33\5\1\6\2\0\33\6\12\0\1\30"+ - "\1\31\34\0\1\36\35\0\1\11\1\0\1\11\1\0"+ - "\1\11\6\0\2\11\1\37\6\11\12\0\1\11\1\0"+ - "\1\11\1\0\1\11\6\0\6\11\1\40\2\11\12\0"+ - "\1\11\1\0\1\11\1\0\1\11\6\0\6\11\1\41"+ - "\2\11\4\24\1\42\1\35\30\24\12\0\1\36\1\0"+ - "\1\43\13\0\1\43\17\0\1\11\1\0\1\11\1\0"+ - "\1\11\6\0\3\11\1\44\5\11\12\0\1\11\1\0"+ - "\1\11\1\0\1\11\6\0\7\11\1\45\1\11\12\0"+ - "\1\11\1\0\1\11\1\0\1\11\6\0\6\11\1\46"+ - "\2\11\11\0\1\47\1\50\2\0\1\47\32\0\1\11"+ - "\1\0\1\11\1\0\1\11\6\0\3\11\1\51\5\11"+ - "\12\0\1\50\23\0"; + "\1\35\6\11\2\23\1\0\33\23\5\24\1\36\30\24"+ + "\1\5\2\0\33\5\1\6\2\0\33\6\12\0\1\31"+ + "\1\32\34\0\1\37\35\0\1\11\1\0\1\11\1\0"+ + "\1\11\6\0\2\11\1\40\6\11\12\0\1\11\1\0"+ + "\1\11\1\0\1\11\6\0\6\11\1\41\2\11\12\0"+ + "\1\11\1\0\1\11\1\0\1\11\6\0\6\11\1\42"+ + "\2\11\4\24\1\43\1\36\30\24\12\0\1\37\1\0"+ + "\1\44\13\0\1\44\17\0\1\11\1\0\1\11\1\0"+ + "\1\11\6\0\3\11\1\45\5\11\12\0\1\11\1\0"+ + "\1\11\1\0\1\11\6\0\7\11\1\46\1\11\12\0"+ + "\1\11\1\0\1\11\1\0\1\11\6\0\6\11\1\47"+ + "\2\11\11\0\1\50\1\51\2\0\1\50\32\0\1\11"+ + "\1\0\1\11\1\0\1\11\6\0\3\11\1\52\5\11"+ + "\12\0\1\51\23\0"; private static int [] zzUnpackTrans() { int [] result = new int[870]; @@ -181,12 +181,12 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ATTRIBUTE = zzUnpackAttribute(); private static final String ZZ_ATTRIBUTE_PACKED_0 = - "\1\0\1\11\7\1\6\11\5\1\1\11\2\0\1\1"+ - "\1\0\3\1\1\0\4\1\1\11\1\0\3\1\1\0"+ - "\2\1"; + "\1\0\1\11\7\1\6\11\5\1\1\11\2\0\1\11"+ + "\1\1\1\0\3\1\1\0\4\1\1\11\1\0\3\1"+ + "\1\0\2\1"; private static int [] zzUnpackAttribute() { - int [] result = new int[41]; + int [] result = new int[42]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -481,70 +481,74 @@ public class _JsonLexer implements FlexLexer { zzMarkedPos = zzMarkedPosL; switch (zzAction < 0 ? zzAction : ZZ_ACTION[zzAction]) { - case 7: + case 8: { return R_CURLY; } - case 17: break; - case 6: + case 18: break; + case 7: { return L_CURLY; } - case 18: break; - case 15: + case 19: break; + case 16: { return NULL; } - case 19: break; - case 8: + case 20: break; + case 9: { return L_BRACKET; } - case 20: break; - case 12: + case 21: break; + case 13: { return LINE_COMMENT; } - case 21: break; - case 10: + case 22: break; + case 11: { return COMMA; } - case 22: break; + case 23: break; case 2: { return com.intellij.psi.TokenType.WHITE_SPACE; } - case 23: break; - case 5: + case 24: break; + case 6: { return TEXT; } - case 24: break; + case 25: break; + case 3: + { return DOUBLE_QUOTED_STRING; + } + case 26: break; case 1: { return com.intellij.psi.TokenType.BAD_CHARACTER; } - case 25: break; - case 14: + case 27: break; + case 15: { return TRUE; } - case 26: break; - case 11: + case 28: break; + case 12: { return COLON; } - case 27: break; - case 3: - { return STRING; - } - case 28: break; - case 4: - { return NUMBER; - } case 29: break; - case 16: - { return FALSE; + case 4: + { return SINGLE_QUOTED_STRING; } case 30: break; - case 13: - { return BLOCK_COMMENT; + case 5: + { return NUMBER; } case 31: break; - case 9: - { return R_BRACKET; + case 17: + { return FALSE; } case 32: break; + case 14: + { return BLOCK_COMMENT; + } + case 33: break; + case 10: + { return R_BRACKET; + } + case 34: break; default: if (zzInput == YYEOF && zzStartRead == zzCurrentPos) { zzAtEOF = true; diff --git a/json/gen/com/intellij/json/psi/JsonStringLiteral.java b/json/gen/com/intellij/json/psi/JsonStringLiteral.java index b1bc0e89096b..00fb1fde661c 100644 --- a/json/gen/com/intellij/json/psi/JsonStringLiteral.java +++ b/json/gen/com/intellij/json/psi/JsonStringLiteral.java @@ -7,7 +7,10 @@ import com.intellij.psi.PsiElement; public interface JsonStringLiteral extends JsonLiteral { - @NotNull - PsiElement getString(); + @Nullable + PsiElement getDoubleQuotedString(); + + @Nullable + PsiElement getSingleQuotedString(); } diff --git a/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java b/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java index 5dafe5898b70..b704f4eb0784 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonStringLiteralImpl.java @@ -22,9 +22,15 @@ public class JsonStringLiteralImpl extends JsonLiteralImpl implements JsonString } @Override - @NotNull - public PsiElement getString() { - return findNotNullChildByType(STRING); + @Nullable + public PsiElement getDoubleQuotedString() { + return findChildByType(DOUBLE_QUOTED_STRING); + } + + @Override + @Nullable + public PsiElement getSingleQuotedString() { + return findChildByType(SINGLE_QUOTED_STRING); } } diff --git a/json/src/com/intellij/json/JsonParserDefinition.java b/json/src/com/intellij/json/JsonParserDefinition.java index 685cdea9e262..84af9936da4f 100644 --- a/json/src/com/intellij/json/JsonParserDefinition.java +++ b/json/src/com/intellij/json/JsonParserDefinition.java @@ -18,7 +18,7 @@ import static com.intellij.json.JsonElementTypes.*; public class JsonParserDefinition implements ParserDefinition { public static final TokenSet WHITE_SPACES = TokenSet.create(TokenType.WHITE_SPACE); - public static final TokenSet STRING_LITERALS = TokenSet.create(JsonElementTypes.STRING); + public static final TokenSet STRING_LITERALS = TokenSet.create(SINGLE_QUOTED_STRING, DOUBLE_QUOTED_STRING); public static final IFileElementType FILE = new IFileElementType(JsonLanguage.INSTANCE); diff --git a/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java b/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java index a9c29dea68b3..83a5a7e3728a 100644 --- a/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java +++ b/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java @@ -37,9 +37,12 @@ public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { fillMap(ourAttributes, DefaultLanguageHighlighterColors.BRACKETS, L_BRACKET, R_BRACKET); fillMap(ourAttributes, DefaultLanguageHighlighterColors.COMMA, COMMA); fillMap(ourAttributes, DefaultLanguageHighlighterColors.SEMICOLON, COLON); - fillMap(ourAttributes, DefaultLanguageHighlighterColors.STRING, STRING); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.STRING, DOUBLE_QUOTED_STRING); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.STRING, SINGLE_QUOTED_STRING); fillMap(ourAttributes, DefaultLanguageHighlighterColors.NUMBER, NUMBER); fillMap(ourAttributes, DefaultLanguageHighlighterColors.KEYWORD, TRUE, FALSE, NULL); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.LINE_COMMENT, LINE_COMMENT); + fillMap(ourAttributes, DefaultLanguageHighlighterColors.BLOCK_COMMENT, BLOCK_COMMENT); fillMap(ourAttributes, HighlighterColors.TEXT, TEXT); fillMap(ourAttributes, HighlighterColors.BAD_CHARACTER, TokenType.BAD_CHARACTER); @@ -53,8 +56,10 @@ public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { @Override public Lexer getHighlightingLexer() { LayeredLexer layeredLexer = new LayeredLexer(new JsonLexer()); - StringLiteralLexer stringLexer = new StringLiteralLexer('\"', STRING, false, "/", false, false); - layeredLexer.registerSelfStoppingLayer(stringLexer, new IElementType[]{STRING}, IElementType.EMPTY_ARRAY); + layeredLexer.registerSelfStoppingLayer(new StringLiteralLexer('\"', DOUBLE_QUOTED_STRING, false, "/", false, false), + new IElementType[]{DOUBLE_QUOTED_STRING}, IElementType.EMPTY_ARRAY); + layeredLexer.registerSelfStoppingLayer(new StringLiteralLexer('\'', SINGLE_QUOTED_STRING, false, "/", false, false), + new IElementType[]{SINGLE_QUOTED_STRING}, IElementType.EMPTY_ARRAY); return layeredLexer; } diff --git a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java index c2e9e216c374..c4a31218a310 100644 --- a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java +++ b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java @@ -1,9 +1,12 @@ package com.intellij.json.psi.impl; import com.intellij.json.JsonElementTypes; +import com.intellij.json.JsonParserDefinition; +import com.intellij.json.JsonTokenType; import com.intellij.json.psi.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -27,7 +30,7 @@ public class JsonPsiImplUtils { } public static boolean isQuotedString(@NotNull JsonLiteral literal) { - return literal.getNode().findChildByType(JsonElementTypes.STRING) != null; + return literal.getNode().findChildByType(JsonParserDefinition.STRING_LITERALS) != null; } public static void delete(@NotNull JsonProperty property) { diff --git a/json/src/json.bnf b/json/src/json.bnf index 5ff7beadfa1b..d3e95fec1459 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -31,7 +31,8 @@ // unclosed string literal matches till the line's end // any escape sequences included, illegal escapes are indicated by SyntaxHighlighter // and JsonStringLiteralAnnotator - STRING="regexp:\"([^\\\"\r\n]|\\[^\r\n])*\"?|'([^\\\"\r\n]|\\[^\r\n])*'?" + DOUBLE_QUOTED_STRING="regexp:\"([^\\\"\r\n]|\\[^\r\n])*\"?" + SINGLE_QUOTED_STRING="regexp:'([^\\\'\r\n]|\\[^\r\n])*'?" // STRING='regexp:"([^\\"\r\n]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"?' NUMBER='regexp:-?\d+(\.\d+([eE][+-]?\d+)?)?' @@ -86,7 +87,7 @@ private array_element ::= value (','|&']') { pin=1 } -string_literal ::= STRING +string_literal ::= SINGLE_QUOTED_STRING | DOUBLE_QUOTED_STRING number_literal ::= NUMBER boolean_literal ::= TRUE | FALSE null_literal ::= NULL diff --git a/json/tests/test/com/intellij/json/JsonParsingTest.java b/json/tests/test/com/intellij/json/JsonParsingTest.java index ab48ee1f4ab2..84421c784705 100644 --- a/json/tests/test/com/intellij/json/JsonParsingTest.java +++ b/json/tests/test/com/intellij/json/JsonParsingTest.java @@ -17,15 +17,15 @@ public class JsonParsingTest extends ParsingTestCase { doTest(); } - public void testNestedArrayLiterals() throws Exception { + public void testNestedArrayLiterals() { doTest(); } - public void testNestedObjectLiterals() throws Exception { + public void testNestedObjectLiterals() { doTest(); } - public void testTopLevelStringLiteral() throws Exception { + public void testTopLevelStringLiteral() { doTest(); } diff --git a/json/tests/testData/psi/NestedArrayLiterals.txt b/json/tests/testData/psi/NestedArrayLiterals.txt index 02cb0359f05b..a80d62256fa3 100644 --- a/json/tests/testData/psi/NestedArrayLiterals.txt +++ b/json/tests/testData/psi/NestedArrayLiterals.txt @@ -8,7 +8,7 @@ JsonFile: NestedArrayLiterals.json JsonArray PsiElement([)('[') JsonStringLiteral - PsiElement(STRING)('"foo"') + PsiElement(DOUBLE_QUOTED_STRING)('"foo"') PsiElement(,)(',') PsiWhiteSpace(' ') JsonArray diff --git a/json/tests/testData/psi/NestedObjectLiterals.txt b/json/tests/testData/psi/NestedObjectLiterals.txt index 518a0f5c62c6..2cfb189613da 100644 --- a/json/tests/testData/psi/NestedObjectLiterals.txt +++ b/json/tests/testData/psi/NestedObjectLiterals.txt @@ -4,7 +4,7 @@ JsonFile: NestedObjectLiterals.json PsiWhiteSpace(' ') JsonProperty JsonStringLiteral - PsiElement(STRING)('"foo"') + PsiElement(DOUBLE_QUOTED_STRING)('"foo"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonObject @@ -12,14 +12,14 @@ JsonFile: NestedObjectLiterals.json PsiWhiteSpace(' ') JsonProperty JsonStringLiteral - PsiElement(STRING)('"bar"') + PsiElement(DOUBLE_QUOTED_STRING)('"bar"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonObject PsiElement({)('{') JsonProperty JsonStringLiteral - PsiElement(STRING)('"baz"') + PsiElement(DOUBLE_QUOTED_STRING)('"baz"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonNullLiteral diff --git a/json/tests/testData/psi/Simple1.txt b/json/tests/testData/psi/Simple1.txt index 9a0725b2ae7b..5cc6332ebc9e 100644 --- a/json/tests/testData/psi/Simple1.txt +++ b/json/tests/testData/psi/Simple1.txt @@ -4,34 +4,34 @@ JsonFile: Simple1.json PsiWhiteSpace(' ') JsonProperty JsonStringLiteral - PsiElement(STRING)('"x"') + PsiElement(DOUBLE_QUOTED_STRING)('"x"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonStringLiteral - PsiElement(STRING)('"x value"') + PsiElement(DOUBLE_QUOTED_STRING)('"x value"') PsiElement(,)(',') PsiWhiteSpace(' ') JsonProperty JsonStringLiteral - PsiElement(STRING)('"y"') + PsiElement(DOUBLE_QUOTED_STRING)('"y"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonStringLiteral - PsiElement(STRING)('"y value"') + PsiElement(DOUBLE_QUOTED_STRING)('"y value"') PsiElement(,)(',') PsiWhiteSpace(' ') JsonProperty JsonStringLiteral - PsiElement(STRING)('"z"') + PsiElement(DOUBLE_QUOTED_STRING)('"z"') PsiElement(:)(':') PsiWhiteSpace(' ') JsonStringLiteral - PsiElement(STRING)('"z value"') + PsiElement(DOUBLE_QUOTED_STRING)('"z value"') PsiElement(,)(',') PsiWhiteSpace(' ') JsonProperty JsonStringLiteral - PsiElement(STRING)('"z2"') + PsiElement(DOUBLE_QUOTED_STRING)('"z2"') PsiElement(:)(':') JsonArray PsiElement([)('[') diff --git a/json/tests/testData/psi/Simple2.txt b/json/tests/testData/psi/Simple2.txt index ee1b90a7c9a2..593cd869d822 100644 --- a/json/tests/testData/psi/Simple2.txt +++ b/json/tests/testData/psi/Simple2.txt @@ -3,7 +3,7 @@ JsonFile: Simple2.json PsiElement([)('[') PsiWhiteSpace(' ') JsonStringLiteral - PsiElement(STRING)('"x"') + PsiElement(DOUBLE_QUOTED_STRING)('"x"') PsiElement(,)(',') PsiWhiteSpace(' ') JsonNumberLiteral @@ -23,11 +23,11 @@ JsonFile: Simple2.json PsiElement(,)(',') PsiWhiteSpace(' ') JsonStringLiteral - PsiElement(STRING)('"z value"') + PsiElement(DOUBLE_QUOTED_STRING)('"z value"') PsiElement(,)(',') PsiWhiteSpace(' ') JsonStringLiteral - PsiElement(STRING)('"z2"') + PsiElement(DOUBLE_QUOTED_STRING)('"z2"') PsiElement(,)(',') JsonArray PsiElement([)('[') diff --git a/json/tests/testData/psi/TopLevelStringLiteral.txt b/json/tests/testData/psi/TopLevelStringLiteral.txt index ceb875da498e..d067da77f319 100644 --- a/json/tests/testData/psi/TopLevelStringLiteral.txt +++ b/json/tests/testData/psi/TopLevelStringLiteral.txt @@ -1,3 +1,3 @@ JsonFile: TopLevelStringLiteral.json PsiErrorElement:'[' or '{' expected, got '"should not be here"' - PsiElement(STRING)('"should not be here"') \ No newline at end of file + PsiElement(DOUBLE_QUOTED_STRING)('"should not be here"') \ No newline at end of file From b140834a708da84456bc0c0efba419ecc5fd73a6 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 4 Sep 2014 14:42:54 +0400 Subject: [PATCH 53/85] Add tests for highlighting provided by annotators --- .../JsonStandardComplianceAnnotator.java | 6 ++--- .../intellij/json/JsonHighlightingTest.java | 20 +++++++++++++++++ .../testData/highlighting/Compliance.json | 7 ++++++ .../testData/highlighting/StringLiterals.json | 8 +++++++ json/tests/testData/psi/StringLiterals.txt | 22 +++++++++++++++++++ 5 files changed, 60 insertions(+), 3 deletions(-) create mode 100644 json/tests/test/com/intellij/json/JsonHighlightingTest.java create mode 100644 json/tests/testData/highlighting/Compliance.json create mode 100644 json/tests/testData/highlighting/StringLiterals.json create mode 100644 json/tests/testData/psi/StringLiterals.txt diff --git a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java index 04b3bb53cabb..f9d43246fbe8 100644 --- a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java +++ b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java @@ -1,8 +1,8 @@ package com.intellij.json.codeinsight; import com.intellij.json.JsonBundle; +import com.intellij.json.psi.JsonElementVisitor; import com.intellij.json.psi.JsonStringLiteral; -import com.intellij.json.psi.impl.JsonRecursiveVisitor; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.psi.PsiComment; @@ -15,7 +15,7 @@ import org.jetbrains.annotations.NotNull; public class JsonStandardComplianceAnnotator implements Annotator { @Override public void annotate(@NotNull final PsiElement element, @NotNull final AnnotationHolder holder) { - new JsonRecursiveVisitor() { + element.accept(new JsonElementVisitor() { @Override public void visitComment(PsiComment comment) { holder.createErrorAnnotation(comment, JsonBundle.message("compliance.problem.comments")); @@ -27,6 +27,6 @@ public class JsonStandardComplianceAnnotator implements Annotator { holder.createErrorAnnotation(literal, JsonBundle.message("compliance.problem.single.quoted.strings")); } } - }.visitElement(element); + }); } } diff --git a/json/tests/test/com/intellij/json/JsonHighlightingTest.java b/json/tests/test/com/intellij/json/JsonHighlightingTest.java new file mode 100644 index 000000000000..e47de061589b --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonHighlightingTest.java @@ -0,0 +1,20 @@ +package com.intellij.json; + +/** + * @author Mikhail Golubev + */ +public class JsonHighlightingTest extends JsonTestCase { + + private void doTest() { + final String TEST_PATH = "/highlighting/"; + myFixture.testHighlighting(true, true, false, TEST_PATH + getTestName(false) + ".json"); + } + + public void testStringLiterals() { + doTest(); + } + + public void testCompliance() { + doTest(); + } +} diff --git a/json/tests/testData/highlighting/Compliance.json b/json/tests/testData/highlighting/Compliance.json new file mode 100644 index 000000000000..b5ea7ffee41e --- /dev/null +++ b/json/tests/testData/highlighting/Compliance.json @@ -0,0 +1,7 @@ +[ + // Line comment + /* Block + Comment + */ + 'string literal' +] \ No newline at end of file diff --git a/json/tests/testData/highlighting/StringLiterals.json b/json/tests/testData/highlighting/StringLiterals.json new file mode 100644 index 000000000000..c57237c9d2b3 --- /dev/null +++ b/json/tests/testData/highlighting/StringLiterals.json @@ -0,0 +1,8 @@ +[ + "correctly escaped trailing slashes \\\\", + "illegal escape sequence: \q", + "illegal unicode escapes: \uZZZZ", + "illegal unicode escapes: \uBEE", + "unclosed double quoted string , + 'unclosed single quoted string +] \ No newline at end of file diff --git a/json/tests/testData/psi/StringLiterals.txt b/json/tests/testData/psi/StringLiterals.txt new file mode 100644 index 000000000000..7fb01d1ecb87 --- /dev/null +++ b/json/tests/testData/psi/StringLiterals.txt @@ -0,0 +1,22 @@ +JsonFile: StringLiterals.json + JsonObject + PsiElement({)('{') + PsiWhiteSpace('\n ') + JsonProperty + JsonStringLiteral + PsiElement(SINGLE_QUOTED_STRING)(''foo'') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonStringLiteral + PsiElement(DOUBLE_QUOTED_STRING)('"bar"') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + JsonProperty + JsonStringLiteral + PsiElement(DOUBLE_QUOTED_STRING)('"baz"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonStringLiteral + PsiElement(SINGLE_QUOTED_STRING)(''quux'') + PsiWhiteSpace('\n') + PsiElement(})('}') \ No newline at end of file From 8b542f94cb9f1017b69331d14b16a088137c5ffe Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 4 Sep 2014 15:40:46 +0400 Subject: [PATCH 54/85] Rename JsonRecursiveVisitor to JsonRecursiveElementVisitor --- ...onRecursiveVisitor.java => JsonRecursiveElementVisitor.java} | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) rename json/src/com/intellij/json/psi/impl/{JsonRecursiveVisitor.java => JsonRecursiveElementVisitor.java} (78%) diff --git a/json/src/com/intellij/json/psi/impl/JsonRecursiveVisitor.java b/json/src/com/intellij/json/psi/impl/JsonRecursiveElementVisitor.java similarity index 78% rename from json/src/com/intellij/json/psi/impl/JsonRecursiveVisitor.java rename to json/src/com/intellij/json/psi/impl/JsonRecursiveElementVisitor.java index 1c8a17e76f84..902b4a01a3d3 100644 --- a/json/src/com/intellij/json/psi/impl/JsonRecursiveVisitor.java +++ b/json/src/com/intellij/json/psi/impl/JsonRecursiveElementVisitor.java @@ -6,7 +6,7 @@ import com.intellij.psi.PsiElement; /** * @author Mikhail Golubev */ -public class JsonRecursiveVisitor extends JsonElementVisitor { +public class JsonRecursiveElementVisitor extends JsonElementVisitor { public void visitElement(final PsiElement element) { element.acceptChildren(this); From f1048c1ce6734aba918e3f28492e1b5056ee1d27 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 4 Sep 2014 15:50:01 +0400 Subject: [PATCH 55/85] Allow non standard top-level values in JSON files --- json/gen/com/intellij/json/JsonParser.java | 11 ++--------- .../com/intellij/json/JsonBundle.properties | 3 ++- .../JsonStandardComplianceAnnotator.java | 18 +++++++++++++++--- .../intellij/json/psi/impl/JsonFileImpl.java | 4 +--- json/src/json.bnf | 3 ++- .../intellij/json/JsonHighlightingTest.java | 4 ++++ .../highlighting/ComplianceTopLevelValues.json | 1 + 7 files changed, 27 insertions(+), 17 deletions(-) create mode 100644 json/tests/testData/highlighting/ComplianceTopLevelValues.json diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index a184d6b85101..078722c0c9f1 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -142,16 +142,9 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // object | array + // value static boolean json(PsiBuilder builder_, int level_) { - if (!recursion_guard_(builder_, level_, "json")) return false; - if (!nextTokenIs(builder_, "", L_BRACKET, L_CURLY)) return false; - boolean result_; - Marker marker_ = enter_section_(builder_); - result_ = object(builder_, level_ + 1); - if (!result_) result_ = array(builder_, level_ + 1); - exit_section_(builder_, marker_, null, result_); - return result_; + return value(builder_, level_ + 1); } /* ********************************************************** */ diff --git a/json/src/com/intellij/json/JsonBundle.properties b/json/src/com/intellij/json/JsonBundle.properties index a802c4d1b34c..fb3ff2fee718 100644 --- a/json/src/com/intellij/json/JsonBundle.properties +++ b/json/src/com/intellij/json/JsonBundle.properties @@ -5,4 +5,5 @@ illegal.escape.sequence=Illegal escape sequence illegal.unicode.escape.sequence=Illegal unicode escape sequence compliance.problem.comments=JSON standard does not allow comments -compliance.problem.single.quoted.strings=JSON standard does not allow single quoted strings \ No newline at end of file +compliance.problem.single.quoted.strings=JSON standard does not allow single quoted strings +compliance.problem.illegal.top.level.value=JSON standard does not allow not object or array as top-level value \ No newline at end of file diff --git a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java index f9d43246fbe8..d9c4418b2fbb 100644 --- a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java +++ b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java @@ -2,11 +2,14 @@ package com.intellij.json.codeinsight; import com.intellij.json.JsonBundle; import com.intellij.json.psi.JsonElementVisitor; +import com.intellij.json.psi.JsonFile; +import com.intellij.json.psi.JsonLiteral; import com.intellij.json.psi.JsonStringLiteral; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import org.jetbrains.annotations.NotNull; /** @@ -22,9 +25,18 @@ public class JsonStandardComplianceAnnotator implements Annotator { } @Override - public void visitStringLiteral(@NotNull JsonStringLiteral literal) { - if (literal.getText().startsWith("'")) { - holder.createErrorAnnotation(literal, JsonBundle.message("compliance.problem.single.quoted.strings")); + public void visitStringLiteral(@NotNull JsonStringLiteral stringLiteral) { + if (stringLiteral.getText().startsWith("'")) { + holder.createErrorAnnotation(stringLiteral, JsonBundle.message("compliance.problem.single.quoted.strings")); + } + super.visitStringLiteral(stringLiteral); + } + + @Override + public void visitLiteral(@NotNull JsonLiteral literal) { + final PsiFile psiFile = literal.getContainingFile(); + if (psiFile instanceof JsonFile && literal == ((JsonFile)psiFile).getTopLevelValue()) { + holder.createErrorAnnotation(literal, JsonBundle.message("compliance.problem.illegal.top.level.value")); } } }); diff --git a/json/src/com/intellij/json/psi/impl/JsonFileImpl.java b/json/src/com/intellij/json/psi/impl/JsonFileImpl.java index a0e7f2094069..26e7f6399a6f 100644 --- a/json/src/com/intellij/json/psi/impl/JsonFileImpl.java +++ b/json/src/com/intellij/json/psi/impl/JsonFileImpl.java @@ -3,9 +3,7 @@ package com.intellij.json.psi.impl; import com.intellij.extapi.psi.PsiFileBase; import com.intellij.json.JsonFileType; import com.intellij.json.JsonLanguage; -import com.intellij.json.psi.JsonArray; import com.intellij.json.psi.JsonFile; -import com.intellij.json.psi.JsonObject; import com.intellij.json.psi.JsonValue; import com.intellij.openapi.fileTypes.FileType; import com.intellij.openapi.vfs.VirtualFile; @@ -29,7 +27,7 @@ public class JsonFileImpl extends PsiFileBase implements JsonFile { @Nullable @Override public JsonValue getTopLevelValue() { - return PsiTreeUtil.getChildOfAnyType(this, JsonObject.class, JsonArray.class); + return PsiTreeUtil.getChildOfType(this, JsonValue.class); } @Override diff --git a/json/src/json.bnf b/json/src/json.bnf index d3e95fec1459..657f8a9790f4 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -52,7 +52,8 @@ ] } -json ::= object | array +// For compatibility we allow any value at root level (see JsonStandardComplianceAnnotator) +json ::= value object ::= '{' object_element* '}' { pin=1 diff --git a/json/tests/test/com/intellij/json/JsonHighlightingTest.java b/json/tests/test/com/intellij/json/JsonHighlightingTest.java index e47de061589b..7c73af0e5eb1 100644 --- a/json/tests/test/com/intellij/json/JsonHighlightingTest.java +++ b/json/tests/test/com/intellij/json/JsonHighlightingTest.java @@ -17,4 +17,8 @@ public class JsonHighlightingTest extends JsonTestCase { public void testCompliance() { doTest(); } + + public void testComplianceTopLevelValues() { + doTest(); + } } diff --git a/json/tests/testData/highlighting/ComplianceTopLevelValues.json b/json/tests/testData/highlighting/ComplianceTopLevelValues.json new file mode 100644 index 000000000000..cf03490f8a29 --- /dev/null +++ b/json/tests/testData/highlighting/ComplianceTopLevelValues.json @@ -0,0 +1 @@ +null \ No newline at end of file From 937a76cccf0d45ac28bf491e15f6ec683687b433 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 5 Sep 2014 12:48:28 +0400 Subject: [PATCH 56/85] First attempt to integrate new JSON support with old plugin * Move JSONNamesValidator to 'json' module * Add JSON to javascript-openapi dependencies * Old JSON language dialect and file type are now registered for '.json-dialect' file extension --- .../com/intellij/json/JsonNamesValidator.java | 38 +++++++++++++++++++ .../intellij/json/JsonParserDefinition.java | 1 + .../json/psi/impl/JsonPsiImplUtils.java | 5 +-- .../src/META-INF/JsonPlugin.xml | 1 + 4 files changed, 41 insertions(+), 4 deletions(-) create mode 100644 json/src/com/intellij/json/JsonNamesValidator.java diff --git a/json/src/com/intellij/json/JsonNamesValidator.java b/json/src/com/intellij/json/JsonNamesValidator.java new file mode 100644 index 000000000000..98a5bb34f2d4 --- /dev/null +++ b/json/src/com/intellij/json/JsonNamesValidator.java @@ -0,0 +1,38 @@ +/* + * @author max + */ +package com.intellij.json; + +import com.intellij.lang.refactoring.NamesValidator; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; + +public class JsonNamesValidator implements NamesValidator { + + private final JsonLexer myLexer = new JsonLexer(); + + @Override + public synchronized boolean isKeyword(@NotNull String name, Project project) { + myLexer.start(name); + return JsonParserDefinition.JSON_KEYWORDS.contains( myLexer.getTokenType() ) && myLexer.getTokenEnd() == name.length(); + } + @Override + public synchronized boolean isIdentifier(@NotNull String name, final Project project) { + if (!StringUtil.startsWithChar(name,'\'') && !StringUtil.startsWithChar(name,'\"')) { + name = "\"" + name; + } + + if (!StringUtil.endsWithChar(name,'"') && !StringUtil.endsWithChar(name,'\"')) { + name += "\""; + } + + myLexer.start(name); + IElementType type = myLexer.getTokenType(); + + return myLexer.getTokenEnd() == name.length() && (type == JsonElementTypes.DOUBLE_QUOTED_STRING || + type == JsonElementTypes.SINGLE_QUOTED_STRING); + } + +} diff --git a/json/src/com/intellij/json/JsonParserDefinition.java b/json/src/com/intellij/json/JsonParserDefinition.java index 84af9936da4f..6d9f208e09c6 100644 --- a/json/src/com/intellij/json/JsonParserDefinition.java +++ b/json/src/com/intellij/json/JsonParserDefinition.java @@ -26,6 +26,7 @@ public class JsonParserDefinition implements ParserDefinition { public static final TokenSet JSON_BRACKETS = TokenSet.create(L_BRACKET, R_BRACKET); public static final TokenSet JSON_CONTAINERS = TokenSet.create(OBJECT, ARRAY); public static final TokenSet JSON_BOOLEANS = TokenSet.create(TRUE, FALSE); + public static final TokenSet JSON_KEYWORDS = TokenSet.create(TRUE, FALSE, NULL); public static final TokenSet JSON_LITERALS = TokenSet.create(STRING_LITERAL, NUMBER_LITERAL, NULL_LITERAL, TRUE, FALSE); public static final TokenSet JSON_VALUES = TokenSet.orSet(JSON_CONTAINERS, JSON_LITERALS); diff --git a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java index c4a31218a310..2d655ea7daf3 100644 --- a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java +++ b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java @@ -1,12 +1,9 @@ package com.intellij.json.psi.impl; -import com.intellij.json.JsonElementTypes; import com.intellij.json.JsonParserDefinition; -import com.intellij.json.JsonTokenType; import com.intellij.json.psi.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; -import com.intellij.psi.tree.TokenSet; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,7 +13,7 @@ import java.util.Collection; public class JsonPsiImplUtils { @NotNull public static String getName(@NotNull JsonProperty property) { - return StringUtil.unquoteString(property.getNameElement().getText()); + return StringUtil.stripQuotesAroundValue(property.getNameElement().getText()); } @NotNull diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index faaf4b9ba6d7..f750742c6d61 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -35,6 +35,7 @@ + Date: Fri, 5 Sep 2014 17:26:55 +0400 Subject: [PATCH 57/85] Add simple line mover implementation for JSON --- json/src/com/intellij/json/JsonUtil.java | 30 +++-- .../json/editor/lineMover/JsonLineMover.java | 109 ++++++++++++++++++ .../com/intellij/json/psi/JsonPsiUtil.java | 39 +++++++ .../com/intellij/json/JsonCompletionTest.java | 4 + .../com/intellij/json/JsonLineMoverTest.java | 44 +++++++ .../mover/LastArrayElementMovedUp.json | 4 + .../LastArrayElementMovedUp_afterUp.json | 4 + .../mover/LastObjectPropertyMovedUp.json | 4 + .../LastObjectPropertyMovedUp_afterUp.json | 4 + .../mover/PenultArrayElementMovedDown.json | 4 + ...PenultArrayElementMovedDown_afterDown.json | 4 + .../mover/PenultObjectPropertyMovedDown.json | 4 + ...nultObjectPropertyMovedDown_afterDown.json | 4 + .../src/META-INF/JsonPlugin.xml | 5 +- 14 files changed, 251 insertions(+), 12 deletions(-) create mode 100644 json/src/com/intellij/json/editor/lineMover/JsonLineMover.java create mode 100644 json/tests/test/com/intellij/json/JsonLineMoverTest.java create mode 100644 json/tests/testData/mover/LastArrayElementMovedUp.json create mode 100644 json/tests/testData/mover/LastArrayElementMovedUp_afterUp.json create mode 100644 json/tests/testData/mover/LastObjectPropertyMovedUp.json create mode 100644 json/tests/testData/mover/LastObjectPropertyMovedUp_afterUp.json create mode 100644 json/tests/testData/mover/PenultArrayElementMovedDown.json create mode 100644 json/tests/testData/mover/PenultArrayElementMovedDown_afterDown.json create mode 100644 json/tests/testData/mover/PenultObjectPropertyMovedDown.json create mode 100644 json/tests/testData/mover/PenultObjectPropertyMovedDown_afterDown.json diff --git a/json/src/com/intellij/json/JsonUtil.java b/json/src/com/intellij/json/JsonUtil.java index e0c93a033f06..6b8bc98ec809 100644 --- a/json/src/com/intellij/json/JsonUtil.java +++ b/json/src/com/intellij/json/JsonUtil.java @@ -1,27 +1,37 @@ package com.intellij.json; -import com.intellij.json.psi.JsonArray; -import com.intellij.json.psi.JsonValue; -import com.intellij.psi.PsiElement; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; /** * @author Mikhail Golubev */ -@SuppressWarnings("UnusedDeclaration") public class JsonUtil { private JsonUtil() { // empty } - /** - * Checks that PSI element represents item of JSON array. + * Clone of C# "as" operator. + * Checks if expression has correct type and casts it if it has. Returns null otherwise. + * It saves coder from "instanceof / cast" chains. * - * @param element PSI element to check - * @return whether this PSI element is array element + * Copied from PyCharm's {@code PyUtil}. + * + * @param expression expression to check + * @param cls class to cast + * @param class to cast + * @return expression casted to appropriate type (if could be casted). Null otherwise. */ - private static boolean isArrayElement(@NotNull PsiElement element) { - return element instanceof JsonValue && element.getParent() instanceof JsonArray; + @Nullable + @SuppressWarnings("unchecked") + public static T as(@Nullable final Object expression, @NotNull final Class cls) { + if (expression == null) { + return null; + } + if (cls.isAssignableFrom(expression.getClass())) { + return (T)expression; + } + return null; } } diff --git a/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java b/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java new file mode 100644 index 000000000000..d5b0870ffd1f --- /dev/null +++ b/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java @@ -0,0 +1,109 @@ +package com.intellij.json.editor.lineMover; + +import com.intellij.codeInsight.editorActions.moveUpDown.LineMover; +import com.intellij.json.JsonElementTypes; +import com.intellij.json.psi.JsonProperty; +import com.intellij.json.psi.JsonPsiUtil; +import com.intellij.json.psi.JsonValue; +import com.intellij.openapi.editor.Document; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.*; +import com.intellij.psi.impl.source.tree.TreeUtil; +import com.intellij.psi.util.PsiTreeUtil; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public class JsonLineMover extends LineMover { + // Means that we should add comma after element of array/object because of movement + private boolean myShouldAddComma = false; + + @Override + public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) { + myShouldAddComma = false; + + if (!super.checkAvailable(editor, file, info, down)) { + return false; + } + + // TODO Implement proper selection movement + if (editor.getSelectionModel().hasSelection()) { + return false; + } + + final Document document = editor.getDocument(); + final PsiElement targetElement = getFirstElementOnLine(file, document, info.toMove.startLine); + if (targetElement == null) { + info.prohibitMove(); + return false; + } + info.toMove.firstElement = info.toMove.lastElement = targetElement; + final PsiElement destinationElement = getFirstElementOnLine(file, document, info.toMove2.startLine); + info.toMove2.firstElement = info.toMove2.lastElement = destinationElement; + + final PsiElement elementBelow = down ? destinationElement : targetElement; + if (elementBelow != null) { + if (JsonPsiUtil.isArrayElement(elementBelow)) { + if (PsiTreeUtil.getNextSiblingOfType(elementBelow, JsonValue.class) == null && + TreeUtil.findSibling(elementBelow.getNode(), JsonElementTypes.COMMA) == null) { + myShouldAddComma = true; + } + } + else { + final JsonProperty property = PsiTreeUtil.getNonStrictParentOfType(elementBelow, JsonProperty.class); + if (property != null && elementFitsLine(document, property, down? info.toMove2.startLine : info.toMove.startLine)) { + if (PsiTreeUtil.getNextSiblingOfType(property, JsonProperty.class) == null && + TreeUtil.findSibling(property.getNode(), JsonElementTypes.COMMA) == null) { + myShouldAddComma = true; + } + } + } + } + info.indentSource = false; + info.indentTarget = false; + + return true; +} + + @Override + public void beforeMove(@NotNull Editor editor, @NotNull MoveInfo info, boolean down) { + if (myShouldAddComma) { + final Document document = editor.getDocument(); + final PsiElement elementBelow = down ? info.toMove2.firstElement : info.toMove.firstElement; + document.insertString(elementBelow.getTextRange().getEndOffset(), ","); + final PsiElement elementAbove = down ? info.toMove.firstElement : info.toMove2.firstElement; + final int aboveLineEndOffset = document.getLineEndOffset(document.getLineNumber(elementAbove.getTextOffset())); + final String aboveLineEnding = document.getText(new TextRange(aboveLineEndOffset - 1, aboveLineEndOffset)); + if (aboveLineEnding.equals(",")) { + document.deleteString(aboveLineEndOffset - 1, aboveLineEndOffset); + } + final Project project = editor.getProject(); + assert project != null; + PsiDocumentManager.getInstance(project).commitDocument(document); + } + } + + @Nullable + private static PsiElement getFirstElementOnLine(@NotNull PsiFile psiFile, @NotNull Document document, int line) { + + PsiElement anchor = psiFile.findElementAt(getLineStartSafeOffset(document, line)); + while (anchor instanceof PsiWhiteSpace || anchor instanceof PsiComment) { + anchor = anchor.getNextSibling(); + } + if (anchor == null || !elementFitsLine(document, anchor, line)) { + return null; + } + return anchor; + } + + private static boolean elementFitsLine(@NotNull Document document, @NotNull PsiElement element, int line) { + final TextRange range = element.getTextRange(); + final int startLine = document.getLineNumber(range.getStartOffset()); + final int endLine = document.getLineNumber(range.getEndOffset()); + return startLine == line && startLine == endLine; + } +} diff --git a/json/src/com/intellij/json/psi/JsonPsiUtil.java b/json/src/com/intellij/json/psi/JsonPsiUtil.java index f25bf0501a0d..a7aa5414b0e7 100644 --- a/json/src/com/intellij/json/psi/JsonPsiUtil.java +++ b/json/src/com/intellij/json/psi/JsonPsiUtil.java @@ -1,10 +1,49 @@ package com.intellij.json.psi; +import com.intellij.psi.PsiElement; +import org.jetbrains.annotations.NotNull; + /** + * Various helper methods for working with PSI of JSON language. + * * @author Mikhail Golubev */ +@SuppressWarnings("UnusedDeclaration") public class JsonPsiUtil { private JsonPsiUtil() { // empty } + + + /** + * Checks that PSI element represents item of JSON array. + * + * @param element PSI element to check + * @return whether this PSI element is array element + */ + public static boolean isArrayElement(@NotNull PsiElement element) { + return element instanceof JsonValue && element.getParent() instanceof JsonArray; + } + + /** + * Checks that PSI element represents key of JSON property (key-value pair of JSON object) + * + * @param element PSI element to check + * @return whether this PSI element is property key + */ + public static boolean isPropertyKey(@NotNull PsiElement element) { + final PsiElement parent = element.getParent(); + return parent instanceof JsonProperty && element == ((JsonProperty)parent).getNameElement(); + } + + /** + * Checks that PSI element represents value of JSON property (key-value pair of JSON object) + * + * @param element PSI element to check + * @return whether this PSI element is property value + */ + public static boolean isPropertyValue(@NotNull PsiElement element) { + final PsiElement parent = element.getParent(); + return parent instanceof JsonProperty && element == ((JsonProperty)parent).getValue(); + } } diff --git a/json/tests/test/com/intellij/json/JsonCompletionTest.java b/json/tests/test/com/intellij/json/JsonCompletionTest.java index 0a7be0975f9f..9b13e0f4fd8a 100644 --- a/json/tests/test/com/intellij/json/JsonCompletionTest.java +++ b/json/tests/test/com/intellij/json/JsonCompletionTest.java @@ -29,6 +29,10 @@ public class JsonCompletionTest extends JsonTestCase { doTest(KEYWORDS); } + public void testPrefixed() { + doTest("null"); + } + private void doTest(String... variants) { myFixture.testCompletionVariants("completion/" + getTestName(false) + ".json", variants); } diff --git a/json/tests/test/com/intellij/json/JsonLineMoverTest.java b/json/tests/test/com/intellij/json/JsonLineMoverTest.java new file mode 100644 index 000000000000..40c62cab2d0b --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonLineMoverTest.java @@ -0,0 +1,44 @@ +package com.intellij.json; + +import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.fileEditor.FileDocumentManager; + +/** + * @author Mikhail Golubev + */ +public class JsonLineMoverTest extends JsonTestCase { + private void doTest(boolean checkUp, boolean checkDown) { + final String testName = getTestName(false); + + if (checkUp) { + myFixture.configureByFile("mover/" + testName + ".json"); + myFixture.performEditorAction(IdeActions.ACTION_MOVE_STATEMENT_UP_ACTION); + myFixture.checkResultByFile("mover/" + testName + "_afterUp.json", true); + } + + if (checkDown) { + if (checkUp) { + FileDocumentManager.getInstance().reloadFromDisk(myFixture.getDocument(myFixture.getFile())); + } + myFixture.configureByFile("mover/" + testName + ".json"); + myFixture.performEditorAction(IdeActions.ACTION_MOVE_STATEMENT_DOWN_ACTION); + myFixture.checkResultByFile("mover/" + testName + "_afterDown.json", true); + } + } + + public void testLastArrayElementMovedUp() { + doTest(true, false); + } + + public void testPenultArrayElementMovedDown() { + doTest(false, true); + } + + public void testLastObjectPropertyMovedUp() { + doTest(true, false); + } + + public void testPenultObjectPropertyMovedDown() { + doTest(false, true); + } +} diff --git a/json/tests/testData/mover/LastArrayElementMovedUp.json b/json/tests/testData/mover/LastArrayElementMovedUp.json new file mode 100644 index 000000000000..5f8f4d74465b --- /dev/null +++ b/json/tests/testData/mover/LastArrayElementMovedUp.json @@ -0,0 +1,4 @@ +[ + 1, + 2 +] \ No newline at end of file diff --git a/json/tests/testData/mover/LastArrayElementMovedUp_afterUp.json b/json/tests/testData/mover/LastArrayElementMovedUp_afterUp.json new file mode 100644 index 000000000000..9331d492ed88 --- /dev/null +++ b/json/tests/testData/mover/LastArrayElementMovedUp_afterUp.json @@ -0,0 +1,4 @@ +[ + 2, + 1 +] \ No newline at end of file diff --git a/json/tests/testData/mover/LastObjectPropertyMovedUp.json b/json/tests/testData/mover/LastObjectPropertyMovedUp.json new file mode 100644 index 000000000000..d9b302180842 --- /dev/null +++ b/json/tests/testData/mover/LastObjectPropertyMovedUp.json @@ -0,0 +1,4 @@ +{ + "foo": true, + "bar": false +} \ No newline at end of file diff --git a/json/tests/testData/mover/LastObjectPropertyMovedUp_afterUp.json b/json/tests/testData/mover/LastObjectPropertyMovedUp_afterUp.json new file mode 100644 index 000000000000..72202c20b8f6 --- /dev/null +++ b/json/tests/testData/mover/LastObjectPropertyMovedUp_afterUp.json @@ -0,0 +1,4 @@ +{ + "bar": false, + "foo": true +} \ No newline at end of file diff --git a/json/tests/testData/mover/PenultArrayElementMovedDown.json b/json/tests/testData/mover/PenultArrayElementMovedDown.json new file mode 100644 index 000000000000..cca4ea2cbf1e --- /dev/null +++ b/json/tests/testData/mover/PenultArrayElementMovedDown.json @@ -0,0 +1,4 @@ +[ + 1, + 2 +] \ No newline at end of file diff --git a/json/tests/testData/mover/PenultArrayElementMovedDown_afterDown.json b/json/tests/testData/mover/PenultArrayElementMovedDown_afterDown.json new file mode 100644 index 000000000000..741bff81782e --- /dev/null +++ b/json/tests/testData/mover/PenultArrayElementMovedDown_afterDown.json @@ -0,0 +1,4 @@ +[ + 2, + 1 +] \ No newline at end of file diff --git a/json/tests/testData/mover/PenultObjectPropertyMovedDown.json b/json/tests/testData/mover/PenultObjectPropertyMovedDown.json new file mode 100644 index 000000000000..358af0de4161 --- /dev/null +++ b/json/tests/testData/mover/PenultObjectPropertyMovedDown.json @@ -0,0 +1,4 @@ +{ + "bar": false, + "foo": true +} \ No newline at end of file diff --git a/json/tests/testData/mover/PenultObjectPropertyMovedDown_afterDown.json b/json/tests/testData/mover/PenultObjectPropertyMovedDown_afterDown.json new file mode 100644 index 000000000000..95f549f422c4 --- /dev/null +++ b/json/tests/testData/mover/PenultObjectPropertyMovedDown_afterDown.json @@ -0,0 +1,4 @@ +{ + "foo": true, + "bar": false +} \ No newline at end of file diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index f750742c6d61..5cd8451a3ed9 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -33,9 +33,10 @@ - - + + + Date: Fri, 5 Sep 2014 17:27:38 +0400 Subject: [PATCH 58/85] Move smart enter and folding for JSON to 'editor' package --- .../intellij/json/{ => editor}/folding/JsonFoldingBuilder.java | 2 +- .../json/{ => editor}/smartEnter/JsonSmartEnterProcessor.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) rename json/src/com/intellij/json/{ => editor}/folding/JsonFoldingBuilder.java (98%) rename json/src/com/intellij/json/{ => editor}/smartEnter/JsonSmartEnterProcessor.java (99%) diff --git a/json/src/com/intellij/json/folding/JsonFoldingBuilder.java b/json/src/com/intellij/json/editor/folding/JsonFoldingBuilder.java similarity index 98% rename from json/src/com/intellij/json/folding/JsonFoldingBuilder.java rename to json/src/com/intellij/json/editor/folding/JsonFoldingBuilder.java index b785d1c11037..918bdbb6ae38 100644 --- a/json/src/com/intellij/json/folding/JsonFoldingBuilder.java +++ b/json/src/com/intellij/json/editor/folding/JsonFoldingBuilder.java @@ -1,4 +1,4 @@ -package com.intellij.json.folding; +package com.intellij.json.editor.folding; import com.intellij.json.JsonElementTypes; import com.intellij.lang.ASTNode; diff --git a/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java b/json/src/com/intellij/json/editor/smartEnter/JsonSmartEnterProcessor.java similarity index 99% rename from json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java rename to json/src/com/intellij/json/editor/smartEnter/JsonSmartEnterProcessor.java index b70b152d9f23..2200601e1374 100644 --- a/json/src/com/intellij/json/smartEnter/JsonSmartEnterProcessor.java +++ b/json/src/com/intellij/json/editor/smartEnter/JsonSmartEnterProcessor.java @@ -1,4 +1,4 @@ -package com.intellij.json.smartEnter; +package com.intellij.json.editor.smartEnter; import com.intellij.json.psi.*; import com.intellij.lang.SmartEnterProcessorWithFixers; From 6fadfbc77bc61b807fdde4568d148d7455561a5a Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 5 Sep 2014 18:01:32 +0400 Subject: [PATCH 59/85] Add commenter implementation for JSON --- .../intellij/json/editor/JsonCommenter.java | 41 +++++++++++++++++++ .../com/intellij/json/JsonCommenterTest.java | 24 +++++++++++ .../testData/commenter/BlockComment.json | 6 +++ .../commenter/BlockComment_after.json | 6 +++ .../tests/testData/commenter/LineComment.json | 4 ++ .../testData/commenter/LineComment_after.json | 4 ++ .../src/META-INF/JsonPlugin.xml | 1 + 7 files changed, 86 insertions(+) create mode 100644 json/src/com/intellij/json/editor/JsonCommenter.java create mode 100644 json/tests/test/com/intellij/json/JsonCommenterTest.java create mode 100644 json/tests/testData/commenter/BlockComment.json create mode 100644 json/tests/testData/commenter/BlockComment_after.json create mode 100644 json/tests/testData/commenter/LineComment.json create mode 100644 json/tests/testData/commenter/LineComment_after.json diff --git a/json/src/com/intellij/json/editor/JsonCommenter.java b/json/src/com/intellij/json/editor/JsonCommenter.java new file mode 100644 index 000000000000..699f7006f985 --- /dev/null +++ b/json/src/com/intellij/json/editor/JsonCommenter.java @@ -0,0 +1,41 @@ +package com.intellij.json.editor; + +import com.intellij.lang.Commenter; +import org.jetbrains.annotations.Nullable; + +/** + * JSON standard (RFC 4627) doesn't allow comments in documents, but they are added for compatibility with legacy JSON integration. + * + * @author Mikhail Golubev + */ +public class JsonCommenter implements Commenter { + @Nullable + @Override + public String getLineCommentPrefix() { + return "//"; + } + + @Nullable + @Override + public String getBlockCommentPrefix() { + return "/*"; + } + + @Nullable + @Override + public String getBlockCommentSuffix() { + return "*/"; + } + + @Nullable + @Override + public String getCommentedBlockCommentPrefix() { + return null; + } + + @Nullable + @Override + public String getCommentedBlockCommentSuffix() { + return null; + } +} diff --git a/json/tests/test/com/intellij/json/JsonCommenterTest.java b/json/tests/test/com/intellij/json/JsonCommenterTest.java new file mode 100644 index 000000000000..86edf968f61a --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonCommenterTest.java @@ -0,0 +1,24 @@ +package com.intellij.json; + +import com.intellij.openapi.actionSystem.IdeActions; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class JsonCommenterTest extends JsonTestCase { + + private void doTest(@NotNull String actionId) { + myFixture.configureByFile("commenter/" + getTestName(false) + ".json"); + myFixture.performEditorAction(actionId); + myFixture.checkResultByFile("commenter/" + getTestName(false) + "_after.json", true); + } + + public void testLineComment() { + doTest(IdeActions.ACTION_COMMENT_LINE); + } + + public void testBlockComment() { + doTest(IdeActions.ACTION_COMMENT_BLOCK); + } +} diff --git a/json/tests/testData/commenter/BlockComment.json b/json/tests/testData/commenter/BlockComment.json new file mode 100644 index 000000000000..9d99045e4bcf --- /dev/null +++ b/json/tests/testData/commenter/BlockComment.json @@ -0,0 +1,6 @@ +{ + "foo": null, + "bar": { + "baz": [1, 2, 3] + } +} \ No newline at end of file diff --git a/json/tests/testData/commenter/BlockComment_after.json b/json/tests/testData/commenter/BlockComment_after.json new file mode 100644 index 000000000000..f402ecbbf40c --- /dev/null +++ b/json/tests/testData/commenter/BlockComment_after.json @@ -0,0 +1,6 @@ +{ + "foo": null, + "bar": /*{ + "baz": [1, 2, 3] + }*/ +} \ No newline at end of file diff --git a/json/tests/testData/commenter/LineComment.json b/json/tests/testData/commenter/LineComment.json new file mode 100644 index 000000000000..ea08678b24aa --- /dev/null +++ b/json/tests/testData/commenter/LineComment.json @@ -0,0 +1,4 @@ +{ + "foo": true, + "bar": 42 +} \ No newline at end of file diff --git a/json/tests/testData/commenter/LineComment_after.json b/json/tests/testData/commenter/LineComment_after.json new file mode 100644 index 000000000000..ff8bd777f811 --- /dev/null +++ b/json/tests/testData/commenter/LineComment_after.json @@ -0,0 +1,4 @@ +{ +// "foo": true, + "bar": 42 +} \ No newline at end of file diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index 5cd8451a3ed9..5bd60e4a0972 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -37,6 +37,7 @@ + Date: Fri, 5 Sep 2014 18:11:46 +0400 Subject: [PATCH 60/85] Update testData for parsing tests --- json/tests/testData/psi/Simple4.txt | 2 +- json/tests/testData/psi/TopLevelStringLiteral.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/json/tests/testData/psi/Simple4.txt b/json/tests/testData/psi/Simple4.txt index 90eb70f5b1c9..477366a0fcdf 100644 --- a/json/tests/testData/psi/Simple4.txt +++ b/json/tests/testData/psi/Simple4.txt @@ -1,3 +1,3 @@ JsonFile: Simple4.json - PsiErrorElement:'[' or '{' expected, got 'true' + JsonBooleanLiteral PsiElement(true)('true') \ No newline at end of file diff --git a/json/tests/testData/psi/TopLevelStringLiteral.txt b/json/tests/testData/psi/TopLevelStringLiteral.txt index d067da77f319..ed741c1225c6 100644 --- a/json/tests/testData/psi/TopLevelStringLiteral.txt +++ b/json/tests/testData/psi/TopLevelStringLiteral.txt @@ -1,3 +1,3 @@ JsonFile: TopLevelStringLiteral.json - PsiErrorElement:'[' or '{' expected, got '"should not be here"' + JsonStringLiteral PsiElement(DOUBLE_QUOTED_STRING)('"should not be here"') \ No newline at end of file From 2227fb4f49ce9de496d274b48cb521ca154ecd4f Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 8 Sep 2014 20:38:49 +0400 Subject: [PATCH 61/85] Simplify JSON line mover. Add movements of selected consecutive elements of arrays and objects. --- .../json/editor/lineMover/JsonLineMover.java | 97 ++++++++----------- .../com/intellij/json/JsonLineMoverTest.java | 35 +++---- .../mover/ArraySelectionMovedDown.json | 5 + .../ArraySelectionMovedDown_afterDown.json | 5 + .../mover/ObjectSelectionMovedDown.json | 6 ++ .../ObjectSelectionMovedDown_afterDown.json | 6 ++ .../mover/PenultArrayElementMovedDown.json | 4 - ...PenultArrayElementMovedDown_afterDown.json | 4 - .../mover/PenultObjectPropertyMovedDown.json | 4 - ...nultObjectPropertyMovedDown_afterDown.json | 4 - 10 files changed, 77 insertions(+), 93 deletions(-) create mode 100644 json/tests/testData/mover/ArraySelectionMovedDown.json create mode 100644 json/tests/testData/mover/ArraySelectionMovedDown_afterDown.json create mode 100644 json/tests/testData/mover/ObjectSelectionMovedDown.json create mode 100644 json/tests/testData/mover/ObjectSelectionMovedDown_afterDown.json delete mode 100644 json/tests/testData/mover/PenultArrayElementMovedDown.json delete mode 100644 json/tests/testData/mover/PenultArrayElementMovedDown_afterDown.json delete mode 100644 json/tests/testData/mover/PenultObjectPropertyMovedDown.json delete mode 100644 json/tests/testData/mover/PenultObjectPropertyMovedDown_afterDown.json diff --git a/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java b/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java index d5b0870ffd1f..e31e50289bec 100644 --- a/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java +++ b/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java @@ -2,14 +2,15 @@ package com.intellij.json.editor.lineMover; import com.intellij.codeInsight.editorActions.moveUpDown.LineMover; import com.intellij.json.JsonElementTypes; -import com.intellij.json.psi.JsonProperty; -import com.intellij.json.psi.JsonPsiUtil; -import com.intellij.json.psi.JsonValue; +import com.intellij.json.psi.*; import com.intellij.openapi.editor.Document; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.Pair; import com.intellij.openapi.util.TextRange; -import com.intellij.psi.*; +import com.intellij.psi.PsiDocumentManager; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; import com.intellij.psi.impl.source.tree.TreeUtil; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; @@ -19,91 +20,73 @@ import org.jetbrains.annotations.Nullable; * @author Mikhail Golubev */ public class JsonLineMover extends LineMover { - // Means that we should add comma after element of array/object because of movement + private boolean myShouldAddComma = false; @Override public boolean checkAvailable(@NotNull Editor editor, @NotNull PsiFile file, @NotNull MoveInfo info, boolean down) { myShouldAddComma = false; - if (!super.checkAvailable(editor, file, info, down)) { + if (!(file instanceof JsonFile) || !super.checkAvailable(editor, file, info, down)) { return false; } - // TODO Implement proper selection movement - if (editor.getSelectionModel().hasSelection()) { + final Pair movedElementRange = getElementRange(editor, file, info.toMove); + final Pair destElementRange = getElementRange(editor, file, info.toMove2); + + if (!isValidElementRange(movedElementRange) || !isValidElementRange(destElementRange)) { return false; } - final Document document = editor.getDocument(); - final PsiElement targetElement = getFirstElementOnLine(file, document, info.toMove.startLine); - if (targetElement == null) { - info.prohibitMove(); + if (movedElementRange.getFirst().getParent() != destElementRange.getSecond().getParent()) { return false; } - info.toMove.firstElement = info.toMove.lastElement = targetElement; - final PsiElement destinationElement = getFirstElementOnLine(file, document, info.toMove2.startLine); - info.toMove2.firstElement = info.toMove2.lastElement = destinationElement; - final PsiElement elementBelow = down ? destinationElement : targetElement; - if (elementBelow != null) { - if (JsonPsiUtil.isArrayElement(elementBelow)) { - if (PsiTreeUtil.getNextSiblingOfType(elementBelow, JsonValue.class) == null && - TreeUtil.findSibling(elementBelow.getNode(), JsonElementTypes.COMMA) == null) { - myShouldAddComma = true; - } - } - else { - final JsonProperty property = PsiTreeUtil.getNonStrictParentOfType(elementBelow, JsonProperty.class); - if (property != null && elementFitsLine(document, property, down? info.toMove2.startLine : info.toMove.startLine)) { - if (PsiTreeUtil.getNextSiblingOfType(property, JsonProperty.class) == null && - TreeUtil.findSibling(property.getNode(), JsonElementTypes.COMMA) == null) { - myShouldAddComma = true; - } - } + final PsiElement commonParent = movedElementRange.getFirst().getParent(); + final PsiElement lowerRightElement = down ? destElementRange.getSecond() : movedElementRange.getSecond(); + if (commonParent instanceof JsonArray) { + if (PsiTreeUtil.getNextSiblingOfType(lowerRightElement, JsonValue.class) == null && + TreeUtil.findSibling(lowerRightElement.getNode(), JsonElementTypes.COMMA) == null) { + myShouldAddComma = true; } } + else if (commonParent instanceof JsonObject) { + if (PsiTreeUtil.getNextSiblingOfType(lowerRightElement, JsonProperty.class) == null && + TreeUtil.findSibling(lowerRightElement.getNode(), JsonElementTypes.COMMA) == null) { + myShouldAddComma = true; + } + } + info.indentSource = false; info.indentTarget = false; return true; } + + private static boolean isValidElementRange(@Nullable Pair elementRange) { + if (elementRange == null) { + return false; + } + return elementRange.getFirst().getParent() == elementRange.getSecond().getParent(); + } + @Override public void beforeMove(@NotNull Editor editor, @NotNull MoveInfo info, boolean down) { if (myShouldAddComma) { final Document document = editor.getDocument(); - final PsiElement elementBelow = down ? info.toMove2.firstElement : info.toMove.firstElement; - document.insertString(elementBelow.getTextRange().getEndOffset(), ","); - final PsiElement elementAbove = down ? info.toMove.firstElement : info.toMove2.firstElement; - final int aboveLineEndOffset = document.getLineEndOffset(document.getLineNumber(elementAbove.getTextOffset())); - final String aboveLineEnding = document.getText(new TextRange(aboveLineEndOffset - 1, aboveLineEndOffset)); + final int lineBelow = down ? info.toMove2.endLine - 1 : info.toMove.endLine - 1; + document.insertString(document.getLineEndOffset(lineBelow), ","); + + final int lineAbove = down ? info.toMove.endLine - 1 : info.toMove2.endLine - 1; + final int lineAboveEndOffset = document.getLineEndOffset(lineAbove); + final String aboveLineEnding = document.getText(new TextRange(lineAboveEndOffset - 1, lineAboveEndOffset)); if (aboveLineEnding.equals(",")) { - document.deleteString(aboveLineEndOffset - 1, aboveLineEndOffset); + document.deleteString(lineAboveEndOffset - 1, lineAboveEndOffset); } final Project project = editor.getProject(); assert project != null; PsiDocumentManager.getInstance(project).commitDocument(document); } } - - @Nullable - private static PsiElement getFirstElementOnLine(@NotNull PsiFile psiFile, @NotNull Document document, int line) { - - PsiElement anchor = psiFile.findElementAt(getLineStartSafeOffset(document, line)); - while (anchor instanceof PsiWhiteSpace || anchor instanceof PsiComment) { - anchor = anchor.getNextSibling(); - } - if (anchor == null || !elementFitsLine(document, anchor, line)) { - return null; - } - return anchor; - } - - private static boolean elementFitsLine(@NotNull Document document, @NotNull PsiElement element, int line) { - final TextRange range = element.getTextRange(); - final int startLine = document.getLineNumber(range.getStartOffset()); - final int endLine = document.getLineNumber(range.getEndOffset()); - return startLine == line && startLine == endLine; - } } diff --git a/json/tests/test/com/intellij/json/JsonLineMoverTest.java b/json/tests/test/com/intellij/json/JsonLineMoverTest.java index 40c62cab2d0b..76df2e9e6792 100644 --- a/json/tests/test/com/intellij/json/JsonLineMoverTest.java +++ b/json/tests/test/com/intellij/json/JsonLineMoverTest.java @@ -1,44 +1,39 @@ package com.intellij.json; import com.intellij.openapi.actionSystem.IdeActions; -import com.intellij.openapi.fileEditor.FileDocumentManager; /** * @author Mikhail Golubev */ public class JsonLineMoverTest extends JsonTestCase { - private void doTest(boolean checkUp, boolean checkDown) { + private void doTest(boolean down) { final String testName = getTestName(false); - if (checkUp) { - myFixture.configureByFile("mover/" + testName + ".json"); - myFixture.performEditorAction(IdeActions.ACTION_MOVE_STATEMENT_UP_ACTION); - myFixture.checkResultByFile("mover/" + testName + "_afterUp.json", true); - } - - if (checkDown) { - if (checkUp) { - FileDocumentManager.getInstance().reloadFromDisk(myFixture.getDocument(myFixture.getFile())); - } + if (down) { myFixture.configureByFile("mover/" + testName + ".json"); myFixture.performEditorAction(IdeActions.ACTION_MOVE_STATEMENT_DOWN_ACTION); myFixture.checkResultByFile("mover/" + testName + "_afterDown.json", true); } + else { + myFixture.configureByFile("mover/" + testName + ".json"); + myFixture.performEditorAction(IdeActions.ACTION_MOVE_STATEMENT_UP_ACTION); + myFixture.checkResultByFile("mover/" + testName + "_afterUp.json", true); + } } public void testLastArrayElementMovedUp() { - doTest(true, false); - } - - public void testPenultArrayElementMovedDown() { - doTest(false, true); + doTest(false); } public void testLastObjectPropertyMovedUp() { - doTest(true, false); + doTest(false); } - public void testPenultObjectPropertyMovedDown() { - doTest(false, true); + public void testArraySelectionMovedDown() { + doTest(true); + } + + public void testObjectSelectionMovedDown() { + doTest(true); } } diff --git a/json/tests/testData/mover/ArraySelectionMovedDown.json b/json/tests/testData/mover/ArraySelectionMovedDown.json new file mode 100644 index 000000000000..476b56d42dea --- /dev/null +++ b/json/tests/testData/mover/ArraySelectionMovedDown.json @@ -0,0 +1,5 @@ +[ + 1, [2], [true, + false], + null +] \ No newline at end of file diff --git a/json/tests/testData/mover/ArraySelectionMovedDown_afterDown.json b/json/tests/testData/mover/ArraySelectionMovedDown_afterDown.json new file mode 100644 index 000000000000..9db514b06905 --- /dev/null +++ b/json/tests/testData/mover/ArraySelectionMovedDown_afterDown.json @@ -0,0 +1,5 @@ +[ + null, + 1, [2], [true, + false] +] \ No newline at end of file diff --git a/json/tests/testData/mover/ObjectSelectionMovedDown.json b/json/tests/testData/mover/ObjectSelectionMovedDown.json new file mode 100644 index 000000000000..57efbe402072 --- /dev/null +++ b/json/tests/testData/mover/ObjectSelectionMovedDown.json @@ -0,0 +1,6 @@ +{ + "foo": false, "bar": 42, + "baz": [1, 2, + 3], + "quux": null +} \ No newline at end of file diff --git a/json/tests/testData/mover/ObjectSelectionMovedDown_afterDown.json b/json/tests/testData/mover/ObjectSelectionMovedDown_afterDown.json new file mode 100644 index 000000000000..860d3b5d3783 --- /dev/null +++ b/json/tests/testData/mover/ObjectSelectionMovedDown_afterDown.json @@ -0,0 +1,6 @@ +{ + "quux": null, + "foo": false, "bar": 42, + "baz": [1, 2, + 3] +} \ No newline at end of file diff --git a/json/tests/testData/mover/PenultArrayElementMovedDown.json b/json/tests/testData/mover/PenultArrayElementMovedDown.json deleted file mode 100644 index cca4ea2cbf1e..000000000000 --- a/json/tests/testData/mover/PenultArrayElementMovedDown.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - 1, - 2 -] \ No newline at end of file diff --git a/json/tests/testData/mover/PenultArrayElementMovedDown_afterDown.json b/json/tests/testData/mover/PenultArrayElementMovedDown_afterDown.json deleted file mode 100644 index 741bff81782e..000000000000 --- a/json/tests/testData/mover/PenultArrayElementMovedDown_afterDown.json +++ /dev/null @@ -1,4 +0,0 @@ -[ - 2, - 1 -] \ No newline at end of file diff --git a/json/tests/testData/mover/PenultObjectPropertyMovedDown.json b/json/tests/testData/mover/PenultObjectPropertyMovedDown.json deleted file mode 100644 index 358af0de4161..000000000000 --- a/json/tests/testData/mover/PenultObjectPropertyMovedDown.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "bar": false, - "foo": true -} \ No newline at end of file diff --git a/json/tests/testData/mover/PenultObjectPropertyMovedDown_afterDown.json b/json/tests/testData/mover/PenultObjectPropertyMovedDown_afterDown.json deleted file mode 100644 index 95f549f422c4..000000000000 --- a/json/tests/testData/mover/PenultObjectPropertyMovedDown_afterDown.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "foo": true, - "bar": false -} \ No newline at end of file From 9d9cec8c340a382902de4eb906ad58aa638cc53f Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 8 Sep 2014 22:37:50 +0400 Subject: [PATCH 62/85] Fix prefix keyword completion for JSON files --- .../com/intellij/json/JsonElementTypes.java | 6 +- json/gen/com/intellij/json/JsonParser.java | 21 +- json/gen/com/intellij/json/_JsonLexer.flex | 4 +- json/gen/com/intellij/json/_JsonLexer.java | 213 +++++++++++++----- .../intellij/json/psi/JsonElementVisitor.java | 4 + .../json/psi/JsonReferenceExpression.java | 13 ++ .../psi/impl/JsonReferenceExpressionImpl.java | 30 +++ .../com/intellij/json/JsonBundle.properties | 3 +- .../json/JsonSyntaxHighlighterFactory.java | 5 +- .../JsonCompletionContributor.java | 10 +- .../JsonStandardComplianceAnnotator.java | 11 +- json/src/json.bnf | 13 +- .../com/intellij/json/JsonCompletionTest.java | 11 +- .../tests/testData/completion/WithPrefix.json | 3 + 14 files changed, 264 insertions(+), 83 deletions(-) create mode 100644 json/gen/com/intellij/json/psi/JsonReferenceExpression.java create mode 100644 json/gen/com/intellij/json/psi/impl/JsonReferenceExpressionImpl.java create mode 100644 json/tests/testData/completion/WithPrefix.json diff --git a/json/gen/com/intellij/json/JsonElementTypes.java b/json/gen/com/intellij/json/JsonElementTypes.java index 03c54db68824..cbff0ab596f9 100644 --- a/json/gen/com/intellij/json/JsonElementTypes.java +++ b/json/gen/com/intellij/json/JsonElementTypes.java @@ -15,6 +15,7 @@ public interface JsonElementTypes { IElementType NUMBER_LITERAL = new JsonElementType("NUMBER_LITERAL"); IElementType OBJECT = new JsonElementType("OBJECT"); IElementType PROPERTY = new JsonElementType("PROPERTY"); + IElementType REFERENCE_EXPRESSION = new JsonElementType("REFERENCE_EXPRESSION"); IElementType STRING_LITERAL = new JsonElementType("STRING_LITERAL"); IElementType VALUE = new JsonElementType("VALUE"); @@ -23,6 +24,7 @@ public interface JsonElementTypes { IElementType COMMA = new JsonTokenType(","); IElementType DOUBLE_QUOTED_STRING = new JsonTokenType("DOUBLE_QUOTED_STRING"); IElementType FALSE = new JsonTokenType("false"); + IElementType INDENTIFIER = new JsonTokenType("INDENTIFIER"); IElementType LINE_COMMENT = new JsonTokenType("LINE_COMMENT"); IElementType L_BRACKET = new JsonTokenType("["); IElementType L_CURLY = new JsonTokenType("{"); @@ -31,7 +33,6 @@ public interface JsonElementTypes { IElementType R_BRACKET = new JsonTokenType("]"); IElementType R_CURLY = new JsonTokenType("}"); IElementType SINGLE_QUOTED_STRING = new JsonTokenType("SINGLE_QUOTED_STRING"); - IElementType TEXT = new JsonTokenType("TEXT"); IElementType TRUE = new JsonTokenType("true"); class Factory { @@ -58,6 +59,9 @@ public interface JsonElementTypes { else if (type == PROPERTY) { return new JsonPropertyImpl(node); } + else if (type == REFERENCE_EXPRESSION) { + return new JsonReferenceExpressionImpl(node); + } else if (type == STRING_LITERAL) { return new JsonStringLiteralImpl(node); } diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 078722c0c9f1..90a6ca462715 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -41,6 +41,9 @@ public class JsonParser implements PsiParser { else if (root_ == PROPERTY) { result_ = property(builder_, 0); } + else if (root_ == REFERENCE_EXPRESSION) { + result_ = reference_expression(builder_, 0); + } else if (root_ == STRING_LITERAL) { result_ = string_literal(builder_, 0); } @@ -62,7 +65,8 @@ public class JsonParser implements PsiParser { create_token_set_(BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, NUMBER_LITERAL, STRING_LITERAL), create_token_set_(ARRAY, BOOLEAN_LITERAL, LITERAL, NULL_LITERAL, - NUMBER_LITERAL, OBJECT, STRING_LITERAL, VALUE), + NUMBER_LITERAL, OBJECT, REFERENCE_EXPRESSION, STRING_LITERAL, + VALUE), }; /* ********************************************************** */ @@ -320,6 +324,18 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } + /* ********************************************************** */ + // INDENTIFIER + public static boolean reference_expression(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "reference_expression")) return false; + if (!nextTokenIs(builder_, INDENTIFIER)) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = consumeToken(builder_, INDENTIFIER); + exit_section_(builder_, marker_, REFERENCE_EXPRESSION, result_); + return result_; + } + /* ********************************************************** */ // SINGLE_QUOTED_STRING | DOUBLE_QUOTED_STRING public static boolean string_literal(PsiBuilder builder_, int level_) { @@ -334,7 +350,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // object | array | literal + // object | array | literal | reference_expression public static boolean value(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "value")) return false; boolean result_; @@ -342,6 +358,7 @@ public class JsonParser implements PsiParser { result_ = object(builder_, level_ + 1); if (!result_) result_ = array(builder_, level_ + 1); if (!result_) result_ = literal(builder_, level_ + 1); + if (!result_) result_ = reference_expression(builder_, level_ + 1); exit_section_(builder_, level_, marker_, VALUE, result_, false, null); return result_; } diff --git a/json/gen/com/intellij/json/_JsonLexer.flex b/json/gen/com/intellij/json/_JsonLexer.flex index e9a464f1704b..eb11beb9674d 100644 --- a/json/gen/com/intellij/json/_JsonLexer.flex +++ b/json/gen/com/intellij/json/_JsonLexer.flex @@ -27,7 +27,7 @@ BLOCK_COMMENT="/"\*([^*]|\*+[^*/])*(\*+"/")? DOUBLE_QUOTED_STRING=\"([^\\\"\r\n]|\\[^\r\n])*\"? SINGLE_QUOTED_STRING='([^\\'\r\n]|\\[^\r\n])*'? NUMBER=-?[0-9]+(\.[0-9]+([eE][+-]?[0-9]+)?)? -TEXT=[a-zA-Z_0-9]+ +INDENTIFIER=[:jletter:] [:jletterdigit:]* %% { @@ -48,7 +48,7 @@ TEXT=[a-zA-Z_0-9]+ {DOUBLE_QUOTED_STRING} { return DOUBLE_QUOTED_STRING; } {SINGLE_QUOTED_STRING} { return SINGLE_QUOTED_STRING; } {NUMBER} { return NUMBER; } - {TEXT} { return TEXT; } + {INDENTIFIER} { return INDENTIFIER; } [^] { return com.intellij.psi.TokenType.BAD_CHARACTER; } } diff --git a/json/gen/com/intellij/json/_JsonLexer.java b/json/gen/com/intellij/json/_JsonLexer.java index d669db593033..e8eccd6b85f0 100644 --- a/json/gen/com/intellij/json/_JsonLexer.java +++ b/json/gen/com/intellij/json/_JsonLexer.java @@ -1,4 +1,4 @@ -/* The following code was generated by JFlex 1.4.3 on 9/3/14 9:55 PM */ +/* The following code was generated by JFlex 1.4.3 on 9/8/14 10:09 PM */ package com.intellij.json; import com.intellij.lexer.*; @@ -9,7 +9,7 @@ import static com.intellij.json.JsonElementTypes.*; /** * This class is a scanner generated by * JFlex 1.4.3 - * on 9/3/14 9:55 PM from the specification file + * on 9/8/14 10:09 PM from the specification file * /home/east825/develop/repos/IDEA/community/json/gen/com/intellij/json/_JsonLexer.flex */ public class _JsonLexer implements FlexLexer { @@ -33,11 +33,117 @@ public class _JsonLexer implements FlexLexer { * Translates characters to character classes */ private static final String ZZ_CMAP_PACKED = - "\11\0\1\3\1\2\1\0\1\3\1\1\22\0\1\3\1\0\1\6"+ - "\4\0\1\10\2\0\1\5\1\15\1\23\1\11\1\13\1\4\12\12"+ - "\1\24\6\0\4\16\1\14\25\16\1\21\1\7\1\22\1\0\1\16"+ - "\1\0\1\32\3\16\1\30\1\31\5\16\1\33\1\16\1\35\3\16"+ - "\1\26\1\34\1\25\1\27\5\16\1\17\1\0\1\20\uff82\0"; + "\11\17\1\3\1\2\1\0\1\3\1\1\16\17\4\0\1\3\1\0"+ + "\1\6\1\0\1\16\2\0\1\10\2\0\1\5\1\15\1\24\1\11"+ + "\1\13\1\4\12\12\1\25\6\0\4\16\1\14\25\16\1\22\1\7"+ + "\1\23\1\0\1\16\1\0\1\33\3\16\1\31\1\32\5\16\1\34"+ + "\1\16\1\36\3\16\1\27\1\35\1\26\1\30\5\16\1\20\1\0"+ + "\1\21\1\0\41\17\2\0\4\16\4\0\1\16\2\0\1\17\7\0"+ + "\1\16\4\0\1\16\5\0\27\16\1\0\37\16\1\0\u01ca\16\4\0"+ + "\14\16\16\0\5\16\7\0\1\16\1\0\1\16\21\0\160\17\5\16"+ + "\1\0\2\16\2\0\4\16\10\0\1\16\1\0\3\16\1\0\1\16"+ + "\1\0\24\16\1\0\123\16\1\0\213\16\1\0\5\17\2\0\236\16"+ + "\11\0\46\16\2\0\1\16\7\0\47\16\7\0\1\16\1\0\55\17"+ + "\1\0\1\17\1\0\2\17\1\0\2\17\1\0\1\17\10\0\33\16"+ + "\5\0\3\16\15\0\5\17\6\0\1\16\4\0\13\17\5\0\53\16"+ + "\37\17\4\0\2\16\1\17\143\16\1\0\1\16\10\17\1\0\6\17"+ + "\2\16\2\17\1\0\4\17\2\16\12\17\3\16\2\0\1\16\17\0"+ + "\1\17\1\16\1\17\36\16\33\17\2\0\131\16\13\17\1\16\16\0"+ + "\12\17\41\16\11\17\2\16\4\0\1\16\5\0\26\16\4\17\1\16"+ + "\11\17\1\16\3\17\1\16\5\17\22\0\31\16\3\17\104\0\1\16"+ + "\1\0\13\16\67\0\33\17\1\0\4\17\66\16\3\17\1\16\22\17"+ + "\1\16\7\17\12\16\2\17\2\0\12\17\1\0\7\16\1\0\7\16"+ + "\1\0\3\17\1\0\10\16\2\0\2\16\2\0\26\16\1\0\7\16"+ + "\1\0\1\16\3\0\4\16\2\0\1\17\1\16\7\17\2\0\2\17"+ + "\2\0\3\17\1\16\10\0\1\17\4\0\2\16\1\0\3\16\2\17"+ + "\2\0\12\17\4\16\7\0\1\16\5\0\3\17\1\0\6\16\4\0"+ + "\2\16\2\0\26\16\1\0\7\16\1\0\2\16\1\0\2\16\1\0"+ + "\2\16\2\0\1\17\1\0\5\17\4\0\2\17\2\0\3\17\3\0"+ + "\1\17\7\0\4\16\1\0\1\16\7\0\14\17\3\16\1\17\13\0"+ + "\3\17\1\0\11\16\1\0\3\16\1\0\26\16\1\0\7\16\1\0"+ + "\2\16\1\0\5\16\2\0\1\17\1\16\10\17\1\0\3\17\1\0"+ + "\3\17\2\0\1\16\17\0\2\16\2\17\2\0\12\17\1\0\1\16"+ + "\17\0\3\17\1\0\10\16\2\0\2\16\2\0\26\16\1\0\7\16"+ + "\1\0\2\16\1\0\5\16\2\0\1\17\1\16\7\17\2\0\2\17"+ + "\2\0\3\17\10\0\2\17\4\0\2\16\1\0\3\16\2\17\2\0"+ + "\12\17\1\0\1\16\20\0\1\17\1\16\1\0\6\16\3\0\3\16"+ + "\1\0\4\16\3\0\2\16\1\0\1\16\1\0\2\16\3\0\2\16"+ + "\3\0\3\16\3\0\14\16\4\0\5\17\3\0\3\17\1\0\4\17"+ + "\2\0\1\16\6\0\1\17\16\0\12\17\11\0\1\16\7\0\3\17"+ + "\1\0\10\16\1\0\3\16\1\0\27\16\1\0\12\16\1\0\5\16"+ + "\3\0\1\16\7\17\1\0\3\17\1\0\4\17\7\0\2\17\1\0"+ + "\2\16\6\0\2\16\2\17\2\0\12\17\22\0\2\17\1\0\10\16"+ + "\1\0\3\16\1\0\27\16\1\0\12\16\1\0\5\16\2\0\1\17"+ + "\1\16\7\17\1\0\3\17\1\0\4\17\7\0\2\17\7\0\1\16"+ + "\1\0\2\16\2\17\2\0\12\17\1\0\2\16\17\0\2\17\1\0"+ + "\10\16\1\0\3\16\1\0\51\16\2\0\1\16\7\17\1\0\3\17"+ + "\1\0\4\17\1\16\10\0\1\17\10\0\2\16\2\17\2\0\12\17"+ + "\12\0\6\16\2\0\2\17\1\0\22\16\3\0\30\16\1\0\11\16"+ + "\1\0\1\16\2\0\7\16\3\0\1\17\4\0\6\17\1\0\1\17"+ + "\1\0\10\17\22\0\2\17\15\0\60\16\1\17\2\16\7\17\4\0"+ + "\10\16\10\17\1\0\12\17\47\0\2\16\1\0\1\16\2\0\2\16"+ + "\1\0\1\16\2\0\1\16\6\0\4\16\1\0\7\16\1\0\3\16"+ + "\1\0\1\16\1\0\1\16\2\0\2\16\1\0\4\16\1\17\2\16"+ + "\6\17\1\0\2\17\1\16\2\0\5\16\1\0\1\16\1\0\6\17"+ + "\2\0\12\17\2\0\4\16\40\0\1\16\27\0\2\17\6\0\12\17"+ + "\13\0\1\17\1\0\1\17\1\0\1\17\4\0\2\17\10\16\1\0"+ + "\44\16\4\0\24\17\1\0\2\17\5\16\13\17\1\0\44\17\11\0"+ + "\1\17\71\0\53\16\24\17\1\16\12\17\6\0\6\16\4\17\4\16"+ + "\3\17\1\16\3\17\2\16\7\17\3\16\4\17\15\16\14\17\1\16"+ + "\17\17\2\0\46\16\1\0\1\16\5\0\1\16\2\0\53\16\1\0"+ + "\u014d\16\1\0\4\16\2\0\7\16\1\0\1\16\1\0\4\16\2\0"+ + "\51\16\1\0\4\16\2\0\41\16\1\0\4\16\2\0\7\16\1\0"+ + "\1\16\1\0\4\16\2\0\17\16\1\0\71\16\1\0\4\16\2\0"+ + "\103\16\2\0\3\17\40\0\20\16\20\0\125\16\14\0\u026c\16\2\0"+ + "\21\16\1\0\32\16\5\0\113\16\3\0\3\16\17\0\15\16\1\0"+ + "\4\16\3\17\13\0\22\16\3\17\13\0\22\16\2\17\14\0\15\16"+ + "\1\0\3\16\1\0\2\17\14\0\64\16\40\17\3\0\1\16\3\0"+ + "\2\16\1\17\2\0\12\17\41\0\3\17\2\0\12\17\6\0\130\16"+ + "\10\0\51\16\1\17\1\16\5\0\106\16\12\0\35\16\3\0\14\17"+ + "\4\0\14\17\12\0\12\17\36\16\2\0\5\16\13\0\54\16\4\0"+ + "\21\17\7\16\2\17\6\0\12\17\46\0\27\16\5\17\4\0\65\16"+ + "\12\17\1\0\35\17\2\0\13\17\6\0\12\17\15\0\1\16\130\0"+ + "\5\17\57\16\21\17\7\16\4\0\12\17\21\0\11\17\14\0\3\17"+ + "\36\16\15\17\2\16\12\17\54\16\16\17\14\0\44\16\24\17\10\0"+ + "\12\17\3\0\3\16\12\17\44\16\122\0\3\17\1\0\25\17\4\16"+ + "\1\17\4\16\3\17\2\16\11\0\300\16\47\17\25\0\4\17\u0116\16"+ + "\2\0\6\16\2\0\46\16\2\0\6\16\2\0\10\16\1\0\1\16"+ + "\1\0\1\16\1\0\1\16\1\0\37\16\2\0\65\16\1\0\7\16"+ + "\1\0\1\16\3\0\3\16\1\0\7\16\3\0\4\16\2\0\6\16"+ + "\4\0\15\16\5\0\3\16\1\0\7\16\16\0\5\17\32\0\5\17"+ + "\20\0\2\16\23\0\1\16\13\0\5\17\5\0\6\17\1\0\1\16"+ + "\15\0\1\16\20\0\15\16\3\0\33\16\25\0\15\17\4\0\1\17"+ + "\3\0\14\17\21\0\1\16\4\0\1\16\2\0\12\16\1\0\1\16"+ + "\3\0\5\16\6\0\1\16\1\0\1\16\1\0\1\16\1\0\4\16"+ + "\1\0\13\16\2\0\4\16\5\0\5\16\4\0\1\16\21\0\51\16"+ + "\u0a77\0\57\16\1\0\57\16\1\0\205\16\6\0\4\16\3\17\2\16"+ + "\14\0\46\16\1\0\1\16\5\0\1\16\2\0\70\16\7\0\1\16"+ + "\17\0\1\17\27\16\11\0\7\16\1\0\7\16\1\0\7\16\1\0"+ + "\7\16\1\0\7\16\1\0\7\16\1\0\7\16\1\0\7\16\1\0"+ + "\40\17\57\0\1\16\u01d5\0\3\16\31\0\11\16\6\17\1\0\5\16"+ + "\2\0\5\16\4\0\126\16\2\0\2\17\2\0\3\16\1\0\132\16"+ + "\1\0\4\16\5\0\51\16\3\0\136\16\21\0\33\16\65\0\20\16"+ + "\u0200\0\u19b6\16\112\0\u51cd\16\63\0\u048d\16\103\0\56\16\2\0\u010d\16"+ + "\3\0\20\16\12\17\2\16\24\0\57\16\1\17\4\0\12\17\1\0"+ + "\31\16\7\0\1\17\120\16\2\17\45\0\11\16\2\0\147\16\2\0"+ + "\4\16\1\0\4\16\14\0\13\16\115\0\12\16\1\17\3\16\1\17"+ + "\4\16\1\17\27\16\5\17\20\0\1\16\7\0\64\16\14\0\2\17"+ + "\62\16\21\17\13\0\12\17\6\0\22\17\6\16\3\0\1\16\4\0"+ + "\12\17\34\16\10\17\2\0\27\16\15\17\14\0\35\16\3\0\4\17"+ + "\57\16\16\17\16\0\1\16\12\17\46\0\51\16\16\17\11\0\3\16"+ + "\1\17\10\16\2\17\2\0\12\17\6\0\27\16\3\0\1\16\1\17"+ + "\4\0\60\16\1\17\1\16\3\17\2\16\2\17\5\16\2\17\1\16"+ + "\1\17\1\16\30\0\3\16\2\0\13\16\5\17\2\0\3\16\2\17"+ + "\12\0\6\16\2\0\6\16\2\0\6\16\11\0\7\16\1\0\7\16"+ + "\221\0\43\16\10\17\1\0\2\17\2\0\12\17\6\0\u2ba4\16\14\0"+ + "\27\16\4\0\61\16\u2104\0\u016e\16\2\0\152\16\46\0\7\16\14\0"+ + "\5\16\5\0\1\16\1\17\12\16\1\0\15\16\1\0\5\16\1\0"+ + "\1\16\1\0\2\16\1\0\2\16\1\0\154\16\41\0\u016b\16\22\0"+ + "\100\16\2\0\66\16\50\0\15\16\3\0\20\17\20\0\7\17\14\0"+ + "\2\16\30\0\3\16\31\0\1\16\6\0\5\16\1\0\207\16\2\0"+ + "\1\17\4\0\1\16\13\0\12\17\7\0\32\16\4\0\1\16\1\0"+ + "\32\16\13\0\131\16\3\0\6\16\2\0\6\16\2\0\6\16\2\0"+ + "\3\16\3\0\2\16\3\0\2\16\22\0\3\17\4\0"; /** * Translates characters to character classes @@ -52,12 +158,12 @@ public class _JsonLexer implements FlexLexer { private static final String ZZ_ACTION_PACKED_0 = "\1\0\1\1\1\2\1\1\1\3\1\4\1\1\1\5"+ "\1\6\1\7\1\10\1\11\1\12\1\13\1\14\3\6"+ - "\1\15\1\16\1\3\2\0\1\4\1\5\1\0\3\6"+ - "\1\0\1\5\3\6\1\16\1\0\1\17\1\6\1\20"+ - "\1\0\1\5\1\21"; + "\1\15\1\16\1\3\2\0\1\4\1\0\3\6\1\0"+ + "\1\5\3\6\1\16\1\0\1\17\1\6\1\20\1\0"+ + "\1\5\1\21"; private static int [] zzUnpackAction() { - int [] result = new int[42]; + int [] result = new int[41]; int offset = 0; offset = zzUnpackAction(ZZ_ACTION_PACKED_0, offset, result); return result; @@ -82,15 +188,15 @@ public class _JsonLexer implements FlexLexer { private static final int [] ZZ_ROWMAP = zzUnpackRowMap(); private static final String ZZ_ROWMAP_PACKED_0 = - "\0\0\0\36\0\74\0\132\0\170\0\226\0\264\0\322"+ - "\0\360\0\36\0\36\0\36\0\36\0\36\0\36\0\u010e"+ - "\0\u012c\0\u014a\0\u0168\0\u0186\0\36\0\u01a4\0\u01c2\0\36"+ - "\0\u01e0\0\u01fe\0\u021c\0\u023a\0\u0258\0\u0276\0\u0294\0\u02b2"+ - "\0\u02d0\0\u02ee\0\36\0\u030c\0\360\0\u032a\0\360\0\u0348"+ - "\0\u0348\0\360"; + "\0\0\0\37\0\76\0\135\0\174\0\233\0\272\0\331"+ + "\0\370\0\37\0\37\0\37\0\37\0\37\0\37\0\u0117"+ + "\0\u0136\0\u0155\0\u0174\0\u0193\0\37\0\u01b2\0\u01d1\0\37"+ + "\0\u01f0\0\u020f\0\u022e\0\u024d\0\u026c\0\u028b\0\u02aa\0\u02c9"+ + "\0\u02e8\0\37\0\u0307\0\370\0\u0326\0\370\0\u0345\0\u0345"+ + "\0\370"; private static int [] zzUnpackRowMap() { - int [] result = new int[42]; + int [] result = new int[41]; int offset = 0; offset = zzUnpackRowMap(ZZ_ROWMAP_PACKED_0, offset, result); return result; @@ -114,33 +220,32 @@ public class _JsonLexer implements FlexLexer { private static final String ZZ_TRANS_PACKED_0 = "\1\2\3\3\1\4\1\2\1\5\1\2\1\6\1\7"+ - "\1\10\1\2\1\11\1\2\1\11\1\12\1\13\1\14"+ - "\1\15\1\16\1\17\1\20\3\11\1\21\3\11\1\22"+ - "\37\0\3\3\36\0\1\23\1\24\30\0\1\5\2\0"+ - "\3\5\1\25\1\26\26\5\1\6\2\0\4\6\1\27"+ - "\1\30\25\6\12\0\1\31\35\0\1\10\1\32\1\11"+ - "\1\0\1\11\6\0\11\11\12\0\1\11\1\0\1\11"+ - "\1\0\1\11\6\0\11\11\12\0\1\11\1\0\1\11"+ - "\1\0\1\11\6\0\1\11\1\33\7\11\12\0\1\11"+ - "\1\0\1\11\1\0\1\11\6\0\5\11\1\34\3\11"+ - "\12\0\1\11\1\0\1\11\1\0\1\11\6\0\2\11"+ - "\1\35\6\11\2\23\1\0\33\23\5\24\1\36\30\24"+ - "\1\5\2\0\33\5\1\6\2\0\33\6\12\0\1\31"+ - "\1\32\34\0\1\37\35\0\1\11\1\0\1\11\1\0"+ - "\1\11\6\0\2\11\1\40\6\11\12\0\1\11\1\0"+ - "\1\11\1\0\1\11\6\0\6\11\1\41\2\11\12\0"+ - "\1\11\1\0\1\11\1\0\1\11\6\0\6\11\1\42"+ - "\2\11\4\24\1\43\1\36\30\24\12\0\1\37\1\0"+ - "\1\44\13\0\1\44\17\0\1\11\1\0\1\11\1\0"+ - "\1\11\6\0\3\11\1\45\5\11\12\0\1\11\1\0"+ - "\1\11\1\0\1\11\6\0\7\11\1\46\1\11\12\0"+ - "\1\11\1\0\1\11\1\0\1\11\6\0\6\11\1\47"+ - "\2\11\11\0\1\50\1\51\2\0\1\50\32\0\1\11"+ - "\1\0\1\11\1\0\1\11\6\0\3\11\1\52\5\11"+ - "\12\0\1\51\23\0"; + "\1\10\1\2\1\11\1\2\1\11\1\2\1\12\1\13"+ + "\1\14\1\15\1\16\1\17\1\20\3\11\1\21\3\11"+ + "\1\22\40\0\3\3\37\0\1\23\1\24\31\0\1\5"+ + "\2\0\3\5\1\25\1\26\27\5\1\6\2\0\4\6"+ + "\1\27\1\30\26\6\12\0\1\10\36\0\1\10\1\31"+ + "\35\0\1\11\1\0\1\11\1\0\2\11\6\0\11\11"+ + "\12\0\1\11\1\0\1\11\1\0\2\11\6\0\1\11"+ + "\1\32\7\11\12\0\1\11\1\0\1\11\1\0\2\11"+ + "\6\0\5\11\1\33\3\11\12\0\1\11\1\0\1\11"+ + "\1\0\2\11\6\0\2\11\1\34\6\11\2\23\1\0"+ + "\34\23\5\24\1\35\31\24\1\5\2\0\34\5\1\6"+ + "\2\0\34\6\12\0\1\36\36\0\1\11\1\0\1\11"+ + "\1\0\2\11\6\0\2\11\1\37\6\11\12\0\1\11"+ + "\1\0\1\11\1\0\2\11\6\0\6\11\1\40\2\11"+ + "\12\0\1\11\1\0\1\11\1\0\2\11\6\0\6\11"+ + "\1\41\2\11\4\24\1\42\1\35\31\24\12\0\1\36"+ + "\1\0\1\43\14\0\1\43\17\0\1\11\1\0\1\11"+ + "\1\0\2\11\6\0\3\11\1\44\5\11\12\0\1\11"+ + "\1\0\1\11\1\0\2\11\6\0\7\11\1\45\1\11"+ + "\12\0\1\11\1\0\1\11\1\0\2\11\6\0\6\11"+ + "\1\46\2\11\11\0\1\47\1\50\2\0\1\47\33\0"+ + "\1\11\1\0\1\11\1\0\2\11\6\0\3\11\1\51"+ + "\5\11\12\0\1\50\24\0"; private static int [] zzUnpackTrans() { - int [] result = new int[870]; + int [] result = new int[868]; int offset = 0; offset = zzUnpackTrans(ZZ_TRANS_PACKED_0, offset, result); return result; @@ -182,11 +287,11 @@ public class _JsonLexer implements FlexLexer { private static final String ZZ_ATTRIBUTE_PACKED_0 = "\1\0\1\11\7\1\6\11\5\1\1\11\2\0\1\11"+ - "\1\1\1\0\3\1\1\0\4\1\1\11\1\0\3\1"+ - "\1\0\2\1"; + "\1\0\3\1\1\0\4\1\1\11\1\0\3\1\1\0"+ + "\2\1"; private static int [] zzUnpackAttribute() { - int [] result = new int[42]; + int [] result = new int[41]; int offset = 0; offset = zzUnpackAttribute(ZZ_ATTRIBUTE_PACKED_0, offset, result); return result; @@ -271,7 +376,7 @@ public class _JsonLexer implements FlexLexer { char [] map = new char[0x10000]; int i = 0; /* index in packed string */ int j = 0; /* index in unpacked array */ - while (i < 98) { + while (i < 2216) { int count = packed.charAt(i++); char value = packed.charAt(i++); do map[j++] = value; while (--count > 0); @@ -493,25 +598,25 @@ public class _JsonLexer implements FlexLexer { { return NULL; } case 20: break; + case 6: + { return INDENTIFIER; + } + case 21: break; case 9: { return L_BRACKET; } - case 21: break; + case 22: break; case 13: { return LINE_COMMENT; } - case 22: break; + case 23: break; case 11: { return COMMA; } - case 23: break; + case 24: break; case 2: { return com.intellij.psi.TokenType.WHITE_SPACE; } - case 24: break; - case 6: - { return TEXT; - } case 25: break; case 3: { return DOUBLE_QUOTED_STRING; diff --git a/json/gen/com/intellij/json/psi/JsonElementVisitor.java b/json/gen/com/intellij/json/psi/JsonElementVisitor.java index a38376347c50..18f36c61b967 100644 --- a/json/gen/com/intellij/json/psi/JsonElementVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonElementVisitor.java @@ -37,6 +37,10 @@ public class JsonElementVisitor extends PsiElementVisitor { // visitPsiNamedElement(o); } + public void visitReferenceExpression(@NotNull JsonReferenceExpression o) { + visitValue(o); + } + public void visitStringLiteral(@NotNull JsonStringLiteral o) { visitLiteral(o); } diff --git a/json/gen/com/intellij/json/psi/JsonReferenceExpression.java b/json/gen/com/intellij/json/psi/JsonReferenceExpression.java new file mode 100644 index 000000000000..7b0fbb6103af --- /dev/null +++ b/json/gen/com/intellij/json/psi/JsonReferenceExpression.java @@ -0,0 +1,13 @@ +// This is a generated file. Not intended for manual editing. +package com.intellij.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonReferenceExpression extends JsonValue { + + @NotNull + PsiElement getIndentifier(); + +} diff --git a/json/gen/com/intellij/json/psi/impl/JsonReferenceExpressionImpl.java b/json/gen/com/intellij/json/psi/impl/JsonReferenceExpressionImpl.java new file mode 100644 index 000000000000..c4d2ec080b8a --- /dev/null +++ b/json/gen/com/intellij/json/psi/impl/JsonReferenceExpressionImpl.java @@ -0,0 +1,30 @@ +// This is a generated file. Not intended for manual editing. +package com.intellij.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.json.psi.*; + +public class JsonReferenceExpressionImpl extends JsonValueImpl implements JsonReferenceExpression { + + public JsonReferenceExpressionImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitReferenceExpression(this); + else super.accept(visitor); + } + + @Override + @NotNull + public PsiElement getIndentifier() { + return findNotNullChildByType(INDENTIFIER); + } + +} diff --git a/json/src/com/intellij/json/JsonBundle.properties b/json/src/com/intellij/json/JsonBundle.properties index fb3ff2fee718..8c22176c9b09 100644 --- a/json/src/com/intellij/json/JsonBundle.properties +++ b/json/src/com/intellij/json/JsonBundle.properties @@ -6,4 +6,5 @@ illegal.unicode.escape.sequence=Illegal unicode escape sequence compliance.problem.comments=JSON standard does not allow comments compliance.problem.single.quoted.strings=JSON standard does not allow single quoted strings -compliance.problem.illegal.top.level.value=JSON standard does not allow not object or array as top-level value \ No newline at end of file +compliance.problem.illegal.top.level.value=JSON standard does not allow not object or array as top-level value +compliance.problem.identifier=JSON standard does not allow identifiers \ No newline at end of file diff --git a/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java b/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java index 83a5a7e3728a..3fa4584f25d3 100644 --- a/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java +++ b/json/src/com/intellij/json/JsonSyntaxHighlighterFactory.java @@ -19,8 +19,8 @@ import org.jetbrains.annotations.Nullable; import java.util.HashMap; import java.util.Map; -import static com.intellij.psi.StringEscapesTokenTypes.*; import static com.intellij.json.JsonElementTypes.*; +import static com.intellij.psi.StringEscapesTokenTypes.*; public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { @NotNull @@ -43,7 +43,8 @@ public class JsonSyntaxHighlighterFactory extends SyntaxHighlighterFactory { fillMap(ourAttributes, DefaultLanguageHighlighterColors.KEYWORD, TRUE, FALSE, NULL); fillMap(ourAttributes, DefaultLanguageHighlighterColors.LINE_COMMENT, LINE_COMMENT); fillMap(ourAttributes, DefaultLanguageHighlighterColors.BLOCK_COMMENT, BLOCK_COMMENT); - fillMap(ourAttributes, HighlighterColors.TEXT, TEXT); + // TODO may be it's worth to add more sensible highlighting for identifiers + fillMap(ourAttributes, HighlighterColors.TEXT, INDENTIFIER); fillMap(ourAttributes, HighlighterColors.BAD_CHARACTER, TokenType.BAD_CHARACTER); // StringLexer's tokens diff --git a/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java b/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java index aed1217aa036..81d3564f98a0 100644 --- a/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java +++ b/json/src/com/intellij/json/codeinsight/JsonCompletionContributor.java @@ -2,13 +2,13 @@ package com.intellij.json.codeinsight; import com.intellij.codeInsight.completion.*; import com.intellij.codeInsight.lookup.LookupElementBuilder; +import com.intellij.json.psi.JsonArray; +import com.intellij.json.psi.JsonProperty; import com.intellij.openapi.diagnostic.Logger; import com.intellij.patterns.PsiElementPattern; import com.intellij.psi.PsiElement; import com.intellij.psi.impl.DebugUtil; import com.intellij.util.ProcessingContext; -import com.intellij.json.psi.JsonArray; -import com.intellij.json.psi.JsonProperty; import org.jetbrains.annotations.NotNull; import static com.intellij.patterns.PlatformPatterns.psiElement; @@ -18,7 +18,6 @@ import static com.intellij.patterns.PlatformPatterns.psiElement; */ public class JsonCompletionContributor extends CompletionContributor { private static final Logger LOG = Logger.getInstance(JsonCompletionContributor.class); - private static final String COMPLETION_PLACEHOLDER = "\"" + CompletionInitializationContext.DUMMY_IDENTIFIER + "\""; private static final PsiElementPattern.Capture AFTER_COLON_IN_PROPERTY = psiElement() .afterLeaf(":").withSuperParent(2, JsonProperty.class); @@ -37,11 +36,6 @@ public class JsonCompletionContributor extends CompletionContributor { } - @Override - public void beforeCompletion(@NotNull CompletionInitializationContext context) { - context.setDummyIdentifier(COMPLETION_PLACEHOLDER); - } - private static class MyKeywordsCompletionProvider extends CompletionProvider { private static final MyKeywordsCompletionProvider INSTANCE = new MyKeywordsCompletionProvider(); private static final String[] KEYWORDS = new String[]{"null", "true", "false"}; diff --git a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java index d9c4418b2fbb..7afbfa1ffe57 100644 --- a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java +++ b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java @@ -1,10 +1,7 @@ package com.intellij.json.codeinsight; import com.intellij.json.JsonBundle; -import com.intellij.json.psi.JsonElementVisitor; -import com.intellij.json.psi.JsonFile; -import com.intellij.json.psi.JsonLiteral; -import com.intellij.json.psi.JsonStringLiteral; +import com.intellij.json.psi.*; import com.intellij.lang.annotation.AnnotationHolder; import com.intellij.lang.annotation.Annotator; import com.intellij.psi.PsiComment; @@ -39,6 +36,12 @@ public class JsonStandardComplianceAnnotator implements Annotator { holder.createErrorAnnotation(literal, JsonBundle.message("compliance.problem.illegal.top.level.value")); } } + + @Override + public void visitReferenceExpression(@NotNull JsonReferenceExpression reference) { + holder.createErrorAnnotation(reference, JsonBundle.message("compliance.problem.identifier")); + } + }); } } diff --git a/json/src/json.bnf b/json/src/json.bnf index 657f8a9790f4..19e950a6f122 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -39,12 +39,12 @@ TRUE='true' FALSE='false' NULL='null' - // Workaround for highlighting issue - // plays role of IDENTIFIER or NAME token in other languages - TEXT='regexp:\w+' + // Actually not defined in RFC 4627, but may be used for JSON5 and helps with + // auto completion of keywords. + INDENTIFIER='regexp:[:jletter:] [:jletterdigit:]*' ] - extends("object|array|literal")=value + extends("object|array|literal|reference_expression")=value extends("string_literal|number_literal|boolean_literal|null_literal")=literal implements("property")=[ "com.intellij.json.psi.JsonElement" @@ -97,7 +97,10 @@ literal ::= string_literal | number_literal | boolean_literal | null_literal { methods=[isQuotedString] mixin="com.intellij.json.psi.impl.JsonLiteralMixin" } -value ::= object | array | literal + +reference_expression ::= INDENTIFIER + +value ::= object | array | literal | reference_expression // Recoveries private not_bracket_or_next_value ::= !(']'|value) diff --git a/json/tests/test/com/intellij/json/JsonCompletionTest.java b/json/tests/test/com/intellij/json/JsonCompletionTest.java index 9b13e0f4fd8a..1c64efb0fc3d 100644 --- a/json/tests/test/com/intellij/json/JsonCompletionTest.java +++ b/json/tests/test/com/intellij/json/JsonCompletionTest.java @@ -29,11 +29,14 @@ public class JsonCompletionTest extends JsonTestCase { doTest(KEYWORDS); } - public void testPrefixed() { - doTest("null"); - } - private void doTest(String... variants) { myFixture.testCompletionVariants("completion/" + getTestName(false) + ".json", variants); } + + public void testWithPrefix() { + // Before artificial reference expressions were added to grammar, lack of identifier-like tokens + // might lead to problems with keyword completion. + myFixture.configureByFile("completion/" + getTestName(false) + ".json"); + assertNull(myFixture.completeBasic()); + } } diff --git a/json/tests/testData/completion/WithPrefix.json b/json/tests/testData/completion/WithPrefix.json new file mode 100644 index 000000000000..b3d8ddfd0707 --- /dev/null +++ b/json/tests/testData/completion/WithPrefix.json @@ -0,0 +1,3 @@ +{ + "foo": nu +} \ No newline at end of file From a001c287aec15e0d7333cc0ac4545ca8e503413d Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 9 Sep 2014 01:08:42 +0400 Subject: [PATCH 63/85] Make JSON formatting closer to the one used in JavaScript * Array elements and object properties are always placed on their own line (however CHOP_DOWN_IF_LONG strategy may be more suitable). * New lines are inserted after opening and closing braces/brackets if text range of parental literal already contains any line breaks (dependentLFSpacing). --- .../intellij/json/formatter/JsonBlock.java | 28 ++++++++++++++++++- 1 file changed, 27 insertions(+), 1 deletion(-) diff --git a/json/src/com/intellij/json/formatter/JsonBlock.java b/json/src/com/intellij/json/formatter/JsonBlock.java index 30b3fe744c9c..ca00a37956f6 100644 --- a/json/src/com/intellij/json/formatter/JsonBlock.java +++ b/json/src/com/intellij/json/formatter/JsonBlock.java @@ -2,6 +2,7 @@ package com.intellij.json.formatter; import com.intellij.formatting.*; import com.intellij.json.JsonElementTypes; +import com.intellij.json.JsonLanguage; import com.intellij.json.JsonParserDefinition; import com.intellij.json.psi.JsonProperty; import com.intellij.lang.ASTNode; @@ -9,6 +10,8 @@ import com.intellij.openapi.util.TextRange; import com.intellij.psi.PsiElement; import com.intellij.psi.TokenType; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; +import com.intellij.psi.formatter.FormatterUtil; import com.intellij.psi.tree.IElementType; import com.intellij.psi.tree.TokenSet; import com.intellij.util.Function; @@ -18,6 +21,9 @@ import org.jetbrains.annotations.Nullable; import java.util.List; +import static com.intellij.json.JsonParserDefinition.JSON_BRACES; +import static com.intellij.json.JsonParserDefinition.JSON_BRACKETS; + /** * Mostly based on PyBlock implementation. * @@ -96,7 +102,9 @@ public class JsonBlock implements ASTBlock { Wrap wrap = null; if (isContainer() && childNodeType != JsonElementTypes.COMMA && !BRACES.contains(childNodeType)) { - wrap = Wrap.createWrap(WrapType.NORMAL, true); + if (!FormatterUtil.isPrecededBy(childNode, OPEN_BRACES)) { + wrap = Wrap.createWrap(WrapType.ALWAYS, true); + } alignment = myChildAlignment; indent = Indent.getNormalIndent(); } @@ -128,6 +136,24 @@ public class JsonBlock implements ASTBlock { @Nullable @Override public Spacing getSpacing(@Nullable Block child1, @NotNull Block child2) { + final CommonCodeStyleSettings commonSettings = mySettings.getCommonSettings(JsonLanguage.INSTANCE); + final JsonCodeStyleSettings customSettings = mySettings.getCustomSettings(JsonCodeStyleSettings.class); + final IElementType leftChildType = child1 instanceof JsonBlock ? ((JsonBlock)child1).myNode.getElementType() : null; + final IElementType rightChildType = child2 instanceof JsonBlock ? ((JsonBlock)child2).myNode.getElementType() : null; + if (leftChildType != null && rightChildType != null) { + if (JSON_BRACES.contains(leftChildType) ^ JSON_BRACES.contains(rightChildType)) { + final int numSpaces = customSettings.SPACE_WITHIN_BRACES ? 1 : 0; + return Spacing.createDependentLFSpacing(numSpaces, numSpaces, myNode.getTextRange(), + commonSettings.KEEP_LINE_BREAKS, + commonSettings.KEEP_BLANK_LINES_IN_CODE); + } + else if (JSON_BRACKETS.contains(leftChildType) ^ JSON_BRACKETS.contains(rightChildType)) { + final int numSpaces = commonSettings.SPACE_WITHIN_BRACKETS ? 1 : 0; + return Spacing.createDependentLFSpacing(numSpaces, numSpaces, myNode.getTextRange(), + commonSettings.KEEP_LINE_BREAKS, + commonSettings.KEEP_BLANK_LINES_IN_CODE); + } + } return mySpacingBuilder.getSpacing(this, child1, child2); } From cc0a49c455279b3b85b7c95a10e3008674659d89 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 9 Sep 2014 14:22:20 +0400 Subject: [PATCH 64/85] Move existing formatting tests from JavaScript to JSON tests in platform Also do not wrap property values to be comply with JavaScript formatter. --- .../intellij/json/formatter/JsonBlock.java | 5 - .../com/intellij/json/JsonFormattingTest.java | 61 +++++- .../ContainerElementsAlignment_after.json | 5 +- .../testData/formatting/ReformatJSon.json | 1 + .../testData/formatting/ReformatJSon2.json | 1 + .../formatting/ReformatJSon2_after.json | 52 +++++ .../formatting/ReformatJSon_after.json | 29 +++ .../formatting/SpacesInsertion_after.json | 9 +- json/tests/testData/formatting/Web3830.json | 181 +++++++++++++++++ .../testData/formatting/Web3830_after.json | 188 ++++++++++++++++++ .../testData/formatting/Wrapping_after.json | 10 +- 11 files changed, 523 insertions(+), 19 deletions(-) create mode 100644 json/tests/testData/formatting/ReformatJSon.json create mode 100644 json/tests/testData/formatting/ReformatJSon2.json create mode 100644 json/tests/testData/formatting/ReformatJSon2_after.json create mode 100644 json/tests/testData/formatting/ReformatJSon_after.json create mode 100644 json/tests/testData/formatting/Web3830.json create mode 100644 json/tests/testData/formatting/Web3830_after.json diff --git a/json/src/com/intellij/json/formatter/JsonBlock.java b/json/src/com/intellij/json/formatter/JsonBlock.java index ca00a37956f6..ce2960a2f1a0 100644 --- a/json/src/com/intellij/json/formatter/JsonBlock.java +++ b/json/src/com/intellij/json/formatter/JsonBlock.java @@ -95,7 +95,6 @@ public class JsonBlock implements ASTBlock { private Block makeSubBlock(@NotNull ASTNode childNode) { IElementType childNodeType = childNode.getElementType(); - PsiElement childPsiElement = childNode.getPsi(); Indent indent = Indent.getNoneIndent(); Alignment alignment = null; @@ -108,10 +107,6 @@ public class JsonBlock implements ASTBlock { alignment = myChildAlignment; indent = Indent.getNormalIndent(); } - if (myPsiElement instanceof JsonProperty && childPsiElement == ((JsonProperty)myPsiElement).getValue()) { - wrap = Wrap.createWrap(WrapType.NORMAL, true); - indent = Indent.getNormalIndent(); - } return new JsonBlock(this, childNode, mySettings, alignment, indent, wrap); } diff --git a/json/tests/test/com/intellij/json/JsonFormattingTest.java b/json/tests/test/com/intellij/json/JsonFormattingTest.java index 07a9728caf54..289f3f464af4 100644 --- a/json/tests/test/com/intellij/json/JsonFormattingTest.java +++ b/json/tests/test/com/intellij/json/JsonFormattingTest.java @@ -2,6 +2,8 @@ package com.intellij.json; import com.intellij.openapi.diagnostic.Logger; import com.intellij.psi.codeStyle.CodeStyleSettings; +import com.intellij.psi.codeStyle.CodeStyleSettingsManager; +import com.intellij.psi.codeStyle.CommonCodeStyleSettings; import com.intellij.psi.formatter.FormatterTestCase; import com.intellij.testFramework.IdeaTestCase; import com.intellij.testFramework.PlatformTestUtil; @@ -15,14 +17,18 @@ public class JsonFormattingTest extends FormatterTestCase { Logger.setFactory(TestLoggerFactory.class); } - private static final Logger LOG = Logger.getInstance(JsonFormattingTest.class); - @Override protected void setUp() throws Exception { IdeaTestCase.initPlatformPrefix(); super.setUp(); } + @Override + protected String getTestName(boolean ignored) { + // always use uppercase first letter for consistency + return super.getTestName(false); + } + @Override protected String getBasePath() { return "formatting"; @@ -39,8 +45,6 @@ public class JsonFormattingTest extends FormatterTestCase { } public void testContainerElementsAlignment() throws Exception { - final int indentSize = getSettings(JsonLanguage.INSTANCE).getIndentOptions().INDENT_SIZE; - LOG.debug("Intent size: " + indentSize); doTest(); } @@ -53,14 +57,53 @@ public class JsonFormattingTest extends FormatterTestCase { } public void testWrapping() throws Exception { - CodeStyleSettings settings = getSettings(); + final CodeStyleSettings settings = getSettings(); settings.setRightMargin(JsonLanguage.INSTANCE, 20); doTest(); } - @Override - protected String getTestName(boolean ignored) { - // always use uppercase first letter for consistency - return super.getTestName(false); + // Moved from JavaScript + + public void testWeb3830() throws Exception { + final CodeStyleSettings settings = CodeStyleSettingsManager.getInstance(getProject()).getCurrentSettings(); + final CommonCodeStyleSettings.IndentOptions indentOptions = settings.getCommonSettings(JsonLanguage.INSTANCE).getIndentOptions(); + final int indent = indentOptions.INDENT_SIZE; + final boolean useTabs = indentOptions.USE_TAB_CHARACTER; + final int tabSize = indentOptions.TAB_SIZE; + try { + indentOptions.INDENT_SIZE = 8; + indentOptions.USE_TAB_CHARACTER = true; + indentOptions.TAB_SIZE = 8; + doTest(); + } + finally { + indentOptions.INDENT_SIZE = indent; + indentOptions.USE_TAB_CHARACTER = useTabs; + indentOptions.TAB_SIZE = tabSize; + } + } + + public void testReformatJSon() throws Exception { + final CommonCodeStyleSettings.IndentOptions indentOptions = getSettings().getCommonSettings(JsonLanguage.INSTANCE).getIndentOptions(); + final int oldIndentSize = indentOptions.INDENT_SIZE; + try { + indentOptions.INDENT_SIZE = 4; + doTest(); + } + finally { + indentOptions.INDENT_SIZE = oldIndentSize; + } + } + + public void testReformatJSon2() throws Exception { + final CommonCodeStyleSettings.IndentOptions indentOptions = getSettings().getCommonSettings(JsonLanguage.INSTANCE).getIndentOptions(); + final int oldIndentSize = indentOptions.INDENT_SIZE; + try { + indentOptions.INDENT_SIZE = 4; + doTest(); + } + finally { + indentOptions.INDENT_SIZE = oldIndentSize; + } } } diff --git a/json/tests/testData/formatting/ContainerElementsAlignment_after.json b/json/tests/testData/formatting/ContainerElementsAlignment_after.json index 1bc85add7eaa..82d930ff2024 100644 --- a/json/tests/testData/formatting/ContainerElementsAlignment_after.json +++ b/json/tests/testData/formatting/ContainerElementsAlignment_after.json @@ -6,7 +6,10 @@ null ], "object": { - "foo": [1, 2], + "foo": [ + 1, + 2 + ], "bar": true } } \ No newline at end of file diff --git a/json/tests/testData/formatting/ReformatJSon.json b/json/tests/testData/formatting/ReformatJSon.json new file mode 100644 index 000000000000..7d8fefb95541 --- /dev/null +++ b/json/tests/testData/formatting/ReformatJSon.json @@ -0,0 +1 @@ +[[{"id":1,"class":"Train","latitude":47.9329065912321,"longitude":12.041015625,"name":"Train AA","ontime":true},{"id":2,"class":"Train","latitude":47.9862451742621,"longitude":13.436279296875,"name":"Train AA","ontime":false},{"id":3,"class":"Train","latitude":48.0890879988176,"longitude":11.8185424804688,"name":"Train AA","ontime":true}],[]] \ No newline at end of file diff --git a/json/tests/testData/formatting/ReformatJSon2.json b/json/tests/testData/formatting/ReformatJSon2.json new file mode 100644 index 000000000000..1dad0744b0b9 --- /dev/null +++ b/json/tests/testData/formatting/ReformatJSon2.json @@ -0,0 +1 @@ +{ "data":{"id":{"type":"primary","label":"ID"},"destination_id":{"type":"int","label":"Destination","helper":"select","belongs":"destination"},"type_id":{"type":"int","label":"Type","helper":"select","list":"event_types"},"tour_guide_id":{"type":"int","label":"TourGuide","helper":"select","belongs":"tour_guide"},"name":{"type":"text","label":"Title"},"body":{"type":"text","label":"Body","helper":"richedit"},"date":{"type":"int","label":"Date","helper":"datetime"},"created":{"type":"int","label":"Created","helper":"datetime","editable":"false"},"modified":{"type":"int","label":"Modified","helper":"datetime","editable":"false" }}} \ No newline at end of file diff --git a/json/tests/testData/formatting/ReformatJSon2_after.json b/json/tests/testData/formatting/ReformatJSon2_after.json new file mode 100644 index 000000000000..f6ce08672849 --- /dev/null +++ b/json/tests/testData/formatting/ReformatJSon2_after.json @@ -0,0 +1,52 @@ +{ + "data": { + "id": { + "type": "primary", + "label": "ID" + }, + "destination_id": { + "type": "int", + "label": "Destination", + "helper": "select", + "belongs": "destination" + }, + "type_id": { + "type": "int", + "label": "Type", + "helper": "select", + "list": "event_types" + }, + "tour_guide_id": { + "type": "int", + "label": "TourGuide", + "helper": "select", + "belongs": "tour_guide" + }, + "name": { + "type": "text", + "label": "Title" + }, + "body": { + "type": "text", + "label": "Body", + "helper": "richedit" + }, + "date": { + "type": "int", + "label": "Date", + "helper": "datetime" + }, + "created": { + "type": "int", + "label": "Created", + "helper": "datetime", + "editable": "false" + }, + "modified": { + "type": "int", + "label": "Modified", + "helper": "datetime", + "editable": "false" + } + } +} \ No newline at end of file diff --git a/json/tests/testData/formatting/ReformatJSon_after.json b/json/tests/testData/formatting/ReformatJSon_after.json new file mode 100644 index 000000000000..10c0b4fcd31b --- /dev/null +++ b/json/tests/testData/formatting/ReformatJSon_after.json @@ -0,0 +1,29 @@ +[ + [ + { + "id": 1, + "class": "Train", + "latitude": 47.9329065912321, + "longitude": 12.041015625, + "name": "Train AA", + "ontime": true + }, + { + "id": 2, + "class": "Train", + "latitude": 47.9862451742621, + "longitude": 13.436279296875, + "name": "Train AA", + "ontime": false + }, + { + "id": 3, + "class": "Train", + "latitude": 48.0890879988176, + "longitude": 11.8185424804688, + "name": "Train AA", + "ontime": true + } + ], + [] +] \ No newline at end of file diff --git a/json/tests/testData/formatting/SpacesInsertion_after.json b/json/tests/testData/formatting/SpacesInsertion_after.json index f15d71731671..09973711870a 100644 --- a/json/tests/testData/formatting/SpacesInsertion_after.json +++ b/json/tests/testData/formatting/SpacesInsertion_after.json @@ -1 +1,8 @@ -{"foo": [1, 2, "bar"], "baz": null} \ No newline at end of file +{ + "foo": [ + 1, + 2, + "bar" + ], + "baz": null +} \ No newline at end of file diff --git a/json/tests/testData/formatting/Web3830.json b/json/tests/testData/formatting/Web3830.json new file mode 100644 index 000000000000..60751eeb64a1 --- /dev/null +++ b/json/tests/testData/formatting/Web3830.json @@ -0,0 +1,181 @@ +{"version": 2, "guid": "james-quiz-with-one-page", "name": "[James] Quiz with one page", "page": [ + { + "page_type": "TOC", + "sequence_number": 0, + "uid": 1, + "page_number": 1, + "item_element": [ + { + "item_element_type": "TOC_ENTRY", + "toc_entry": { + "link": { + "label": "[James] Quiz with one page", + "ref": "2#james-quiz-with-one-page", + "uri": "", + "new_window_type": "NOT_NEW_WINDOW", + "labelRichText": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "[James] Quiz with one page" + } + } + ] + } + } + } + } + ] + }, + { + "page_type": "QUIZ", + "sequence_number": 1, + "uid": 2, + "page_number": 2, + "item_element": [ + { + "item_element_type": "TOC_OBJECT_ITEM", + "toc_object_item": { + "tocObject": { + "id": "james-quiz-with-one-page", + "label": "[James] Quiz with one page", + "level": 1, + "labelRichText": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "[James] Quiz with one page" + } + } + ] + } + } + } + }, + { + "item_element_type": "FILL_IN_THE_BLANK", + "fill_in_the_blank": { + "ChoiceQuestionElement": { + "id": "fib", + "question_number": 1, + "title": { + "text": "" + }, + "questionText": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "Fill in the Blank" + } + } + ] + }, + { + "rich_text_type": "ELEMENT_BR", + "element_br": {} + }, + { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "___ * ___ = 6" + } + } + ] + } + ], + "id": "stem" + }, + "answer_element": [ + { + "answer_value": "2", + "text": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "2" + } + } + ], + "id": "option1" + }, + "correct": "CORRECT_ANSWER" + }, + { + "answer_value": "3", + "text": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "3" + } + } + ], + "id": "option2" + }, + "correct": "CORRECT_ANSWER" + } + ], + "answer_type": "COURSE_PROVIDED", + "number_tries": 1, + "correct_remediation_element": { + "text": [ + { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "Correct Feedback Text" + } + } + ], + "id": "remediation-correct" + } + ] + }, + "incorrect_remediation_element": { + "text": [ + { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "Incorrect Feedback Text" + } + } + ], + "id": "remediation-incorrect" + } + ] + } + } + } + } + ], + "id": "james-quiz-with-one-page", + "page_subtype": "UNDEFINED" + }, + { + "page_type": "FINISH", + "sequence_number": 6, + "uid": 5, + "page_number": 5 + } +], "toc_page_number": 1, "passing_level": 0.0} \ No newline at end of file diff --git a/json/tests/testData/formatting/Web3830_after.json b/json/tests/testData/formatting/Web3830_after.json new file mode 100644 index 000000000000..1276e3f338f5 --- /dev/null +++ b/json/tests/testData/formatting/Web3830_after.json @@ -0,0 +1,188 @@ +{ + "version": 2, + "guid": "james-quiz-with-one-page", + "name": "[James] Quiz with one page", + "page": [ + { + "page_type": "TOC", + "sequence_number": 0, + "uid": 1, + "page_number": 1, + "item_element": [ + { + "item_element_type": "TOC_ENTRY", + "toc_entry": { + "link": { + "label": "[James] Quiz with one page", + "ref": "2#james-quiz-with-one-page", + "uri": "", + "new_window_type": "NOT_NEW_WINDOW", + "labelRichText": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "[James] Quiz with one page" + } + } + ] + } + } + } + } + ] + }, + { + "page_type": "QUIZ", + "sequence_number": 1, + "uid": 2, + "page_number": 2, + "item_element": [ + { + "item_element_type": "TOC_OBJECT_ITEM", + "toc_object_item": { + "tocObject": { + "id": "james-quiz-with-one-page", + "label": "[James] Quiz with one page", + "level": 1, + "labelRichText": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "[James] Quiz with one page" + } + } + ] + } + } + } + }, + { + "item_element_type": "FILL_IN_THE_BLANK", + "fill_in_the_blank": { + "ChoiceQuestionElement": { + "id": "fib", + "question_number": 1, + "title": { + "text": "" + }, + "questionText": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "Fill in the Blank" + } + } + ] + }, + { + "rich_text_type": "ELEMENT_BR", + "element_br": {} + }, + { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "___ * ___ = 6" + } + } + ] + } + ], + "id": "stem" + }, + "answer_element": [ + { + "answer_value": "2", + "text": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "2" + } + } + ], + "id": "option1" + }, + "correct": "CORRECT_ANSWER" + }, + { + "answer_value": "3", + "text": { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "3" + } + } + ], + "id": "option2" + }, + "correct": "CORRECT_ANSWER" + } + ], + "answer_type": "COURSE_PROVIDED", + "number_tries": 1, + "correct_remediation_element": { + "text": [ + { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "Correct Feedback Text" + } + } + ], + "id": "remediation-correct" + } + ] + }, + "incorrect_remediation_element": { + "text": [ + { + "rich_text_type": "RICH_TEXT", + "richText": [ + { + "rich_text_type": "STR", + "str": { + "text": "Incorrect Feedback Text" + } + } + ], + "id": "remediation-incorrect" + } + ] + } + } + } + } + ], + "id": "james-quiz-with-one-page", + "page_subtype": "UNDEFINED" + }, + { + "page_type": "FINISH", + "sequence_number": 6, + "uid": 5, + "page_number": 5 + } + ], + "toc_page_number": 1, + "passing_level": 0.0 +} \ No newline at end of file diff --git a/json/tests/testData/formatting/Wrapping_after.json b/json/tests/testData/formatting/Wrapping_after.json index d0e8a0201505..f6f41b61f43b 100644 --- a/json/tests/testData/formatting/Wrapping_after.json +++ b/json/tests/testData/formatting/Wrapping_after.json @@ -1,8 +1,12 @@ [ "spam!spam!spam!spam!", "ham!ham!ham!", - 1, 2, 3, 4, 5, 6, + 1, + 2, + 3, + 4, + 5, + 6, 7, - [ - "this line is long too"] + ["this line is long too"] ] \ No newline at end of file From e19e02f23c365e32c06146d11414d1f45678b3f5 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 10 Sep 2014 15:09:30 +0400 Subject: [PATCH 65/85] Structure view for JSON shows only object properties (as done in JavaScript) Also move existing structure view test from JavaScript to JSON --- .../JsonStructureViewBuilder.java | 33 --------- .../JsonStructureViewBuilderFactory.java | 27 ++++++++ .../JsonStructureViewElement.java | 44 +++--------- .../JsonStructureViewFactory.java | 18 ----- .../structureView/JsonStructureViewModel.java | 45 ++++++++++++ .../intellij/json/JsonStructureViewTest.java | 69 +++++++++++++++++++ .../structureView/SimpleStructure.json | 6 ++ .../src/META-INF/JsonPlugin.xml | 2 +- 8 files changed, 157 insertions(+), 87 deletions(-) delete mode 100644 json/src/com/intellij/json/structureView/JsonStructureViewBuilder.java create mode 100644 json/src/com/intellij/json/structureView/JsonStructureViewBuilderFactory.java delete mode 100644 json/src/com/intellij/json/structureView/JsonStructureViewFactory.java create mode 100644 json/src/com/intellij/json/structureView/JsonStructureViewModel.java create mode 100644 json/tests/test/com/intellij/json/JsonStructureViewTest.java create mode 100644 json/tests/testData/structureView/SimpleStructure.json diff --git a/json/src/com/intellij/json/structureView/JsonStructureViewBuilder.java b/json/src/com/intellij/json/structureView/JsonStructureViewBuilder.java deleted file mode 100644 index 182cd9f10e70..000000000000 --- a/json/src/com/intellij/json/structureView/JsonStructureViewBuilder.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.intellij.json.structureView; - -import com.intellij.ide.structureView.StructureViewModel; -import com.intellij.ide.structureView.StructureViewModelBase; -import com.intellij.ide.structureView.TreeBasedStructureViewBuilder; -import com.intellij.ide.util.treeView.smartTree.Sorter; -import com.intellij.json.psi.JsonFile; -import com.intellij.json.psi.JsonObject; -import com.intellij.json.psi.JsonProperty; -import com.intellij.openapi.editor.Editor; -import org.jetbrains.annotations.NotNull; -import org.jetbrains.annotations.Nullable; - -/** - * Based on structure view implementation for YAML. - * - * @author Mikhail Golubev - */ -public class JsonStructureViewBuilder extends TreeBasedStructureViewBuilder { - private final JsonFile myJsonFile; - - public JsonStructureViewBuilder(@NotNull JsonFile jsonFile) { - myJsonFile = jsonFile; - } - - @NotNull - @Override - public StructureViewModel createStructureViewModel(@Nullable Editor editor) { - return new StructureViewModelBase(myJsonFile, editor, new JsonStructureViewElement(myJsonFile)) - .withSorters(Sorter.ALPHA_SORTER) - .withSuitableClasses(JsonFile.class, JsonObject.class, JsonProperty.class); - } -} diff --git a/json/src/com/intellij/json/structureView/JsonStructureViewBuilderFactory.java b/json/src/com/intellij/json/structureView/JsonStructureViewBuilderFactory.java new file mode 100644 index 000000000000..28387d840aa6 --- /dev/null +++ b/json/src/com/intellij/json/structureView/JsonStructureViewBuilderFactory.java @@ -0,0 +1,27 @@ +package com.intellij.json.structureView; + +import com.intellij.ide.structureView.StructureViewBuilder; +import com.intellij.ide.structureView.StructureViewModel; +import com.intellij.ide.structureView.TreeBasedStructureViewBuilder; +import com.intellij.lang.PsiStructureViewFactory; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public class JsonStructureViewBuilderFactory implements PsiStructureViewFactory { + @Nullable + @Override + public StructureViewBuilder getStructureViewBuilder(final PsiFile psiFile) { + return new TreeBasedStructureViewBuilder() { + @NotNull + @Override + public StructureViewModel createStructureViewModel(@Nullable Editor editor) { + return new JsonStructureViewModel(psiFile, editor); + } + }; + } +} diff --git a/json/src/com/intellij/json/structureView/JsonStructureViewElement.java b/json/src/com/intellij/json/structureView/JsonStructureViewElement.java index 8b9738776495..4717694fd945 100644 --- a/json/src/com/intellij/json/structureView/JsonStructureViewElement.java +++ b/json/src/com/intellij/json/structureView/JsonStructureViewElement.java @@ -22,7 +22,7 @@ public class JsonStructureViewElement implements StructureViewTreeElement { private final JsonElement myElement; public JsonStructureViewElement(@NotNull JsonElement element) { - assert element instanceof JsonFile || element instanceof JsonObject || element instanceof JsonProperty; + assert element instanceof JsonFile || element instanceof JsonProperty; myElement = element; } @@ -49,28 +49,7 @@ public class JsonStructureViewElement implements StructureViewTreeElement { @NotNull @Override public ItemPresentation getPresentation() { - if (myElement instanceof JsonObject) { - return new ItemPresentation() { - @Nullable - @Override - public String getPresentableText() { - return "Object"; - } - - @Nullable - @Override - public String getLocationString() { - return null; - } - - @Nullable - @Override - public Icon getIcon(boolean unused) { - return PlatformIcons.CLASS_ICON; - } - }; - } - else if (myElement instanceof JsonProperty) { + if (myElement instanceof JsonProperty) { return new ItemPresentation() { @Nullable @Override @@ -95,27 +74,22 @@ public class JsonStructureViewElement implements StructureViewTreeElement { //noinspection ConstantConditions return myElement.getPresentation(); } - throw new AssertionError("Attempting to create presentation for invalid element: " + myElement); + throw new AssertionError("Attempting to create presentation for illegal element: " + myElement); } @NotNull @Override public TreeElement[] getChildren() { + JsonElement value = null; if (myElement instanceof JsonFile) { - final JsonFile jsonFile = (JsonFile)myElement; - if (jsonFile.getTopLevelValue() instanceof JsonObject) { - return new TreeElement[]{new JsonStructureViewElement(jsonFile.getTopLevelValue())}; - } + value = ((JsonFile)myElement).getTopLevelValue(); } else if (myElement instanceof JsonProperty) { - final JsonProperty jsonProperty = (JsonProperty)myElement; - if (jsonProperty.getValue() instanceof JsonObject) { - return new TreeElement[]{new JsonStructureViewElement(jsonProperty.getValue())}; - } + value = ((JsonProperty)myElement).getValue(); } - else if (myElement instanceof JsonObject) { - final JsonObject jsonObject = (JsonObject)myElement; - return ContainerUtil.map2Array(jsonObject.getPropertyList(), TreeElement.class, new Function() { + if (value instanceof JsonObject) { + final JsonObject object = ((JsonObject)value); + return ContainerUtil.map2Array(object.getPropertyList(), TreeElement.class, new Function() { @Override public TreeElement fun(JsonProperty property) { return new JsonStructureViewElement(property); diff --git a/json/src/com/intellij/json/structureView/JsonStructureViewFactory.java b/json/src/com/intellij/json/structureView/JsonStructureViewFactory.java deleted file mode 100644 index f2e325ccae38..000000000000 --- a/json/src/com/intellij/json/structureView/JsonStructureViewFactory.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.intellij.json.structureView; - -import com.intellij.ide.structureView.StructureViewBuilder; -import com.intellij.json.psi.JsonFile; -import com.intellij.lang.PsiStructureViewFactory; -import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.Nullable; - -/** - * @author Mikhail Golubev - */ -public class JsonStructureViewFactory implements PsiStructureViewFactory { - @Nullable - @Override - public StructureViewBuilder getStructureViewBuilder(PsiFile psiFile) { - return new JsonStructureViewBuilder(((JsonFile)psiFile)); - } -} diff --git a/json/src/com/intellij/json/structureView/JsonStructureViewModel.java b/json/src/com/intellij/json/structureView/JsonStructureViewModel.java new file mode 100644 index 000000000000..dee1afb45960 --- /dev/null +++ b/json/src/com/intellij/json/structureView/JsonStructureViewModel.java @@ -0,0 +1,45 @@ +package com.intellij.json.structureView; + +import com.intellij.ide.structureView.StructureViewModel; +import com.intellij.ide.structureView.StructureViewModelBase; +import com.intellij.ide.structureView.StructureViewTreeElement; +import com.intellij.ide.util.treeView.smartTree.Sorter; +import com.intellij.json.psi.JsonFile; +import com.intellij.json.psi.JsonProperty; +import com.intellij.openapi.editor.Editor; +import com.intellij.psi.PsiFile; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public class JsonStructureViewModel extends StructureViewModelBase implements StructureViewModel.ElementInfoProvider, StructureViewModel.ExpandInfoProvider{ + + public JsonStructureViewModel(@NotNull PsiFile psiFile, @Nullable Editor editor) { + super(psiFile, editor, new JsonStructureViewElement((JsonFile)psiFile)); + withSorters(Sorter.ALPHA_SORTER); + withSuitableClasses(JsonFile.class, JsonProperty.class); + } + + @Override + public boolean isAlwaysShowsPlus(StructureViewTreeElement element) { + return false; + } + + @Override + public boolean isAlwaysLeaf(StructureViewTreeElement element) { + return false; + } + + @Override + public boolean isAutoExpand(@NotNull StructureViewTreeElement element) { + final Object value = element.getValue(); + return value instanceof PsiFile || value instanceof JsonProperty; + } + + @Override + public boolean isSmartExpand() { + return false; + } +} diff --git a/json/tests/test/com/intellij/json/JsonStructureViewTest.java b/json/tests/test/com/intellij/json/JsonStructureViewTest.java new file mode 100644 index 000000000000..e99dd7f51c4c --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonStructureViewTest.java @@ -0,0 +1,69 @@ +package com.intellij.json; + +import com.intellij.ide.structureView.StructureViewBuilder; +import com.intellij.ide.structureView.StructureViewModel; +import com.intellij.ide.structureView.newStructureView.StructureViewComponent; +import com.intellij.ide.util.treeView.smartTree.TreeElement; +import com.intellij.lang.LanguageStructureViewBuilder; +import com.intellij.openapi.fileEditor.FileEditor; +import com.intellij.openapi.fileEditor.FileEditorManager; +import com.intellij.openapi.util.Disposer; +import com.intellij.util.Consumer; +import com.intellij.util.PlatformIcons; + +import static com.intellij.testFramework.PlatformTestUtil.assertTreeEqual; + +/** + * @author Mikhail Golubev + */ +public class JsonStructureViewTest extends JsonTestCase { + + private void doTest(final String expected) { + myFixture.configureByFile("structureView/" + getTestName(false) + ".json"); + myFixture.testStructureView(new Consumer() { + @Override + public void consume(StructureViewComponent component) { + assertTreeEqual(component.getTree(), expected); + } + }); + } + + public void testSimpleStructure() { + doTest("-SimpleStructure.json\n" + + " aaa\n" + + " -bbb\n" + + " ccc\n"); + } + + // Moved from JavaScript + + public void testJsonStructure() { + myFixture.configureByFile("structureView/SimpleStructure.json"); + + final StructureViewBuilder builder = LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(getFile()); + assertNotNull(builder); + StructureViewComponent component = null; + try { + final FileEditor editor = FileEditorManager.getInstance(getProject()).getSelectedEditor(getFile().getVirtualFile()); + component = (StructureViewComponent)builder.createStructureView(editor, myFixture.getProject()); + final StructureViewModel model = component.getTreeModel(); + + TreeElement[] children = model.getRoot().getChildren(); + assertEquals(2, children.length); + assertEquals("aaa", children[0].getPresentation().getPresentableText()); + assertEquals(PlatformIcons.PROPERTY_ICON, children[0].getPresentation().getIcon(false)); + assertEquals("bbb", children[1].getPresentation().getPresentableText()); + assertEquals(PlatformIcons.PROPERTY_ICON, children[1].getPresentation().getIcon(false)); + + children = children[1].getChildren(); + assertEquals(1, children.length); + assertEquals("ccc", children[0].getPresentation().getPresentableText()); + assertEquals(PlatformIcons.PROPERTY_ICON, children[0].getPresentation().getIcon(false)); + } + finally { + if (component != null) { + Disposer.dispose(component); + } + } + } +} diff --git a/json/tests/testData/structureView/SimpleStructure.json b/json/tests/testData/structureView/SimpleStructure.json new file mode 100644 index 000000000000..3bf40b22337b --- /dev/null +++ b/json/tests/testData/structureView/SimpleStructure.json @@ -0,0 +1,6 @@ +{ + "aaa":1, + "bbb":{ + "ccc":2 + } +} \ No newline at end of file diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index 5bd60e4a0972..7460e49f8447 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -32,7 +32,7 @@ - + From 7a5aae32007eaa8013f2065a9eabff2923bd888a Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 10 Sep 2014 22:06:11 +0400 Subject: [PATCH 66/85] Implement "Surround with object literal" functionality for JSON --- .../com/intellij/json/JsonBundle.properties | 4 +- .../json/psi/JsonElementGenerator.java | 58 +++++++++++++ .../surroundWith/JsonSurroundDescriptor.java | 78 +++++++++++++++++ .../JsonWithObjectLiteralSurrounder.java | 87 +++++++++++++++++++ .../intellij/json/JsonSurroundWithTest.java | 37 ++++++++ .../surround/CannotSurroundPropertyKey.json | 3 + .../CannotSurroundPropertyKey_after.json | 3 + .../testData/surround/MultipleProperties.json | 4 + .../surround/MultipleProperties_after.json | 6 ++ .../testData/surround/SingleProperty.json | 3 + .../surround/SingleProperty_after.json | 5 ++ json/tests/testData/surround/SingleValue.json | 1 + .../testData/surround/SingleValue_after.json | 3 + .../src/META-INF/JsonPlugin.xml | 2 + 14 files changed, 293 insertions(+), 1 deletion(-) create mode 100644 json/src/com/intellij/json/psi/JsonElementGenerator.java create mode 100644 json/src/com/intellij/json/surroundWith/JsonSurroundDescriptor.java create mode 100644 json/src/com/intellij/json/surroundWith/JsonWithObjectLiteralSurrounder.java create mode 100644 json/tests/test/com/intellij/json/JsonSurroundWithTest.java create mode 100644 json/tests/testData/surround/CannotSurroundPropertyKey.json create mode 100644 json/tests/testData/surround/CannotSurroundPropertyKey_after.json create mode 100644 json/tests/testData/surround/MultipleProperties.json create mode 100644 json/tests/testData/surround/MultipleProperties_after.json create mode 100644 json/tests/testData/surround/SingleProperty.json create mode 100644 json/tests/testData/surround/SingleProperty_after.json create mode 100644 json/tests/testData/surround/SingleValue.json create mode 100644 json/tests/testData/surround/SingleValue_after.json diff --git a/json/src/com/intellij/json/JsonBundle.properties b/json/src/com/intellij/json/JsonBundle.properties index 8c22176c9b09..a895f2938259 100644 --- a/json/src/com/intellij/json/JsonBundle.properties +++ b/json/src/com/intellij/json/JsonBundle.properties @@ -7,4 +7,6 @@ illegal.unicode.escape.sequence=Illegal unicode escape sequence compliance.problem.comments=JSON standard does not allow comments compliance.problem.single.quoted.strings=JSON standard does not allow single quoted strings compliance.problem.illegal.top.level.value=JSON standard does not allow not object or array as top-level value -compliance.problem.identifier=JSON standard does not allow identifiers \ No newline at end of file +compliance.problem.identifier=JSON standard does not allow identifiers + +surround.with.object.literal.description=object literal \ No newline at end of file diff --git a/json/src/com/intellij/json/psi/JsonElementGenerator.java b/json/src/com/intellij/json/psi/JsonElementGenerator.java new file mode 100644 index 000000000000..5cff3c711a8e --- /dev/null +++ b/json/src/com/intellij/json/psi/JsonElementGenerator.java @@ -0,0 +1,58 @@ +package com.intellij.json.psi; + +import com.intellij.json.JsonFileType; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiFileFactory; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class JsonElementGenerator { + private final Project myProject; + + public JsonElementGenerator(@NotNull Project project) { + myProject = project; + } + + /** + * Create lightweight in-memory {@link com.intellij.json.psi.JsonFile} filled with {@code content}. + * + * @param content content of the file to be created + * @return created file + */ + @NotNull + public PsiFile createDummyFile(@NotNull String content) { + final PsiFileFactory psiFileFactory = PsiFileFactory.getInstance(myProject); + return psiFileFactory.createFileFromText("dummy." + JsonFileType.INSTANCE.getDefaultExtension(), JsonFileType.INSTANCE, content); + } + + /** + * Create JSON value from supplied content. + * + * @param content properly escaped text of JSON value, e.g. Java literal {@code "\"new\\nline\""} if you want to create string literal + * @param type of the JSON value desired + * @return element created from given text + * + * @see {@link com.intellij.json.psi.JsonElementGenerator#createStringLiteral(String)} + */ + @NotNull + public T createValue(@NotNull String content) { + final PsiFile file = createDummyFile("{\"foo\": " + content + "}"); + //noinspection unchecked,ConstantConditions + return (T)((JsonObject)file.getFirstChild()).getPropertyList().get(0).getValue(); + } + + /** + * Create JSON string literal from supplied unescaped content. + * + * @param unescapedContent unescaped content of string literal, e.g. Java literal {@code "new\nline"} (compare with {@link #createValue(String)}). + * @return JSON string literal created from given text + */ + @NotNull + public JsonStringLiteral createStringLiteral(@NotNull String unescapedContent) { + return createValue('"' + StringUtil.escapeStringCharacters(unescapedContent) + '"'); + } +} diff --git a/json/src/com/intellij/json/surroundWith/JsonSurroundDescriptor.java b/json/src/com/intellij/json/surroundWith/JsonSurroundDescriptor.java new file mode 100644 index 000000000000..803b85ac9d48 --- /dev/null +++ b/json/src/com/intellij/json/surroundWith/JsonSurroundDescriptor.java @@ -0,0 +1,78 @@ +package com.intellij.json.surroundWith; + +import com.intellij.json.JsonElementTypes; +import com.intellij.json.psi.JsonElement; +import com.intellij.json.psi.JsonProperty; +import com.intellij.json.psi.JsonValue; +import com.intellij.lang.surroundWith.SurroundDescriptor; +import com.intellij.lang.surroundWith.Surrounder; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiFile; +import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.util.PsiTreeUtil; +import com.intellij.util.containers.ContainerUtil; +import org.jetbrains.annotations.NotNull; + +import java.util.List; + +/** + * @author Mikhail Golubev + */ +public class JsonSurroundDescriptor implements SurroundDescriptor { + private static final Surrounder[] ourSurrounders = new Surrounder[]{ + new JsonWithObjectLiteralSurrounder() + }; + + @NotNull + @Override + public PsiElement[] getElementsToSurround(PsiFile file, int startOffset, int endOffset) { + PsiElement firstElement = file.findElementAt(startOffset); + PsiElement lastElement = file.findElementAt(endOffset - 1); + + // Extend selection beyond possible delimiters + while (firstElement != null && + (firstElement instanceof PsiWhiteSpace || firstElement.getNode().getElementType() == JsonElementTypes.COMMA)) { + firstElement = firstElement.getNextSibling(); + } + while (lastElement != null && + (lastElement instanceof PsiWhiteSpace || lastElement.getNode().getElementType() == JsonElementTypes.COMMA)) { + lastElement = lastElement.getPrevSibling(); + } + if (firstElement != null) { + startOffset = firstElement.getTextRange().getStartOffset(); + } + if (lastElement != null) { + endOffset = lastElement.getTextRange().getEndOffset(); + } + + final JsonElement property = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, JsonProperty.class); + if (property != null) { + final List properties = ContainerUtil.newArrayList(property); + PsiElement nextSibling = property.getNextSibling(); + while (nextSibling != null && nextSibling.getTextRange().getEndOffset() <= endOffset) { + if (nextSibling instanceof JsonProperty) { + properties.add((JsonProperty)nextSibling); + } + nextSibling = nextSibling.getNextSibling(); + } + return properties.toArray(new PsiElement[properties.size()]); + } + + final JsonValue value = PsiTreeUtil.findElementOfClassAtRange(file, startOffset, endOffset, JsonValue.class); + if (value != null) { + return new PsiElement[]{value}; + } + return PsiElement.EMPTY_ARRAY; + } + + @NotNull + @Override + public Surrounder[] getSurrounders() { + return ourSurrounders; + } + + @Override + public boolean isExclusive() { + return false; + } +} diff --git a/json/src/com/intellij/json/surroundWith/JsonWithObjectLiteralSurrounder.java b/json/src/com/intellij/json/surroundWith/JsonWithObjectLiteralSurrounder.java new file mode 100644 index 000000000000..487d7b13d31c --- /dev/null +++ b/json/src/com/intellij/json/surroundWith/JsonWithObjectLiteralSurrounder.java @@ -0,0 +1,87 @@ +package com.intellij.json.surroundWith; + +import com.intellij.json.JsonBundle; +import com.intellij.json.psi.*; +import com.intellij.lang.surroundWith.Surrounder; +import com.intellij.openapi.editor.Editor; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * This surrounder ported from JavaScript allows to wrap single JSON value or several consecutive JSON properties + * in object literal. + *

+ * Examples: + *

    + *
  1. {@code [42]} converts to [{"property": 42}]
  2. + *
  3. + * {
    + *    "foo": 42,
    + *    "bar": false
    + * }
    + * 
    converts to
    + * {
    + *    "property": {
    + *      "foo": 42,
    + *      "bar": false
    + *    }
    + * }
    + * 
  4. + *
+ * + * @author Mikhail Golubev + */ +public class JsonWithObjectLiteralSurrounder implements Surrounder { + @Override + public String getTemplateDescription() { + return JsonBundle.message("surround.with.object.literal.description"); + } + + @Override + public boolean isApplicable(@NotNull PsiElement[] elements) { + return !JsonPsiUtil.isPropertyKey(elements[0]); + } + + @Nullable + @Override + public TextRange surroundElements(@NotNull Project project, + @NotNull Editor editor, + @NotNull PsiElement[] elements) throws IncorrectOperationException { + + if (!isApplicable(elements)) { + return null; + } + + final JsonElementGenerator generator = new JsonElementGenerator(project); + + final PsiElement firstElement = elements[0]; + final JsonElement newNameElement; + if (firstElement instanceof JsonValue) { + assert elements.length == 1 : "Only single JSON value can be wrapped in object literal"; + JsonObject replacement = generator.createValue("{\n\"property\": " + firstElement.getText() + "\n}"); + replacement = (JsonObject)firstElement.replace(replacement); + newNameElement = replacement.getPropertyList().get(0).getNameElement(); + } + else { + assert firstElement instanceof JsonProperty; + final JsonProperty firstProperty = (JsonProperty)elements[0]; + final JsonProperty lastProperty = (JsonProperty)elements[elements.length - 1]; + final TextRange replacedRange = new TextRange(firstProperty.getTextOffset(), lastProperty.getTextRange().getEndOffset()); + final String propertiesText = replacedRange.substring(firstProperty.getContainingFile().getText()); + if (firstProperty != lastProperty) { + final PsiElement parent = firstProperty.getParent(); + parent.deleteChildRange(firstProperty.getNextSibling(), lastProperty); + } + final JsonObject tempJsonObject = generator.createValue("{\"property\": {\n" + propertiesText + "\n}}"); + JsonProperty replacement = tempJsonObject.getPropertyList().get(0); + replacement = (JsonProperty)firstProperty.replace(replacement); + newNameElement = replacement.getNameElement(); + } + final TextRange rangeWithQuotes = newNameElement.getTextRange(); + return new TextRange(rangeWithQuotes.getStartOffset() + 1, rangeWithQuotes.getEndOffset() - 1); + } +} diff --git a/json/tests/test/com/intellij/json/JsonSurroundWithTest.java b/json/tests/test/com/intellij/json/JsonSurroundWithTest.java new file mode 100644 index 000000000000..4c7fec0bb4d5 --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonSurroundWithTest.java @@ -0,0 +1,37 @@ +package com.intellij.json; + +import com.intellij.codeInsight.generation.surroundWith.SurroundWithHandler; +import com.intellij.json.surroundWith.JsonWithObjectLiteralSurrounder; +import com.intellij.openapi.command.WriteCommandAction; + +/** + * @author Mikhail Golubev + */ +public class JsonSurroundWithTest extends JsonTestCase { + private void doTest() { + myFixture.configureByFile("/surround/" + getTestName(false) + ".json"); + new WriteCommandAction.Simple(myFixture.getProject()) { + @Override + protected void run() { + SurroundWithHandler.invoke(myFixture.getProject(), myFixture.getEditor(), myFixture.getFile(), new JsonWithObjectLiteralSurrounder()); + } + }.execute(); + myFixture.checkResultByFile("/surround/" + getTestName(false) + "_after.json", true); + } + + public void testSingleValue() { + doTest(); + } + + public void testSingleProperty() { + doTest(); + } + + public void testMultipleProperties() { + doTest(); + } + + public void testCannotSurroundPropertyKey() { + doTest(); + } +} diff --git a/json/tests/testData/surround/CannotSurroundPropertyKey.json b/json/tests/testData/surround/CannotSurroundPropertyKey.json new file mode 100644 index 000000000000..b98cca877c6a --- /dev/null +++ b/json/tests/testData/surround/CannotSurroundPropertyKey.json @@ -0,0 +1,3 @@ +{ + "foo": false +} \ No newline at end of file diff --git a/json/tests/testData/surround/CannotSurroundPropertyKey_after.json b/json/tests/testData/surround/CannotSurroundPropertyKey_after.json new file mode 100644 index 000000000000..6e101319e899 --- /dev/null +++ b/json/tests/testData/surround/CannotSurroundPropertyKey_after.json @@ -0,0 +1,3 @@ +{ + "foo": false +} \ No newline at end of file diff --git a/json/tests/testData/surround/MultipleProperties.json b/json/tests/testData/surround/MultipleProperties.json new file mode 100644 index 000000000000..7cc748055a5d --- /dev/null +++ b/json/tests/testData/surround/MultipleProperties.json @@ -0,0 +1,4 @@ +{ + "foo": null, + "bar": false +} \ No newline at end of file diff --git a/json/tests/testData/surround/MultipleProperties_after.json b/json/tests/testData/surround/MultipleProperties_after.json new file mode 100644 index 000000000000..b22ff58c5f07 --- /dev/null +++ b/json/tests/testData/surround/MultipleProperties_after.json @@ -0,0 +1,6 @@ +{ + "property": { + "foo": null, + "bar": false + } +} \ No newline at end of file diff --git a/json/tests/testData/surround/SingleProperty.json b/json/tests/testData/surround/SingleProperty.json new file mode 100644 index 000000000000..f9e3dfdb6575 --- /dev/null +++ b/json/tests/testData/surround/SingleProperty.json @@ -0,0 +1,3 @@ +{ + "foo": null +} \ No newline at end of file diff --git a/json/tests/testData/surround/SingleProperty_after.json b/json/tests/testData/surround/SingleProperty_after.json new file mode 100644 index 000000000000..c35cb870d0db --- /dev/null +++ b/json/tests/testData/surround/SingleProperty_after.json @@ -0,0 +1,5 @@ +{ + "property": { + "foo": null + } +} \ No newline at end of file diff --git a/json/tests/testData/surround/SingleValue.json b/json/tests/testData/surround/SingleValue.json new file mode 100644 index 000000000000..500db4a86aa3 --- /dev/null +++ b/json/tests/testData/surround/SingleValue.json @@ -0,0 +1 @@ +[null] \ No newline at end of file diff --git a/json/tests/testData/surround/SingleValue_after.json b/json/tests/testData/surround/SingleValue_after.json new file mode 100644 index 000000000000..963868b0afb7 --- /dev/null +++ b/json/tests/testData/surround/SingleValue_after.json @@ -0,0 +1,3 @@ +{ + "property": [null] +} \ No newline at end of file diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index 7460e49f8447..584e57b82299 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -38,6 +38,8 @@ + + Date: Thu, 11 Sep 2014 13:34:53 +0400 Subject: [PATCH 67/85] JSON folding for object literals behaves similarly to the one in JavaScript --- .../editor/folding/JsonFoldingBuilder.java | 24 +++++++++++++++++++ .../com/intellij/json/JsonFoldingTest.java | 15 ++++++++++++ .../tests/testData/folding/ObjectFolding.json | 4 ++-- .../testData/folding/ObjectLiteral2.json | 4 ++++ .../testData/folding/ObjectLiteral3.json | 3 +++ .../testData/folding/ObjectLiteral4.json | 3 +++ 6 files changed, 51 insertions(+), 2 deletions(-) create mode 100644 json/tests/testData/folding/ObjectLiteral2.json create mode 100644 json/tests/testData/folding/ObjectLiteral3.json create mode 100644 json/tests/testData/folding/ObjectLiteral4.json diff --git a/json/src/com/intellij/json/editor/folding/JsonFoldingBuilder.java b/json/src/com/intellij/json/editor/folding/JsonFoldingBuilder.java index 918bdbb6ae38..fb7a6b6017bd 100644 --- a/json/src/com/intellij/json/editor/folding/JsonFoldingBuilder.java +++ b/json/src/com/intellij/json/editor/folding/JsonFoldingBuilder.java @@ -1,6 +1,10 @@ package com.intellij.json.editor.folding; import com.intellij.json.JsonElementTypes; +import com.intellij.json.psi.JsonLiteral; +import com.intellij.json.psi.JsonObject; +import com.intellij.json.psi.JsonProperty; +import com.intellij.json.psi.JsonValue; import com.intellij.lang.ASTNode; import com.intellij.lang.folding.FoldingBuilder; import com.intellij.lang.folding.FoldingDescriptor; @@ -43,6 +47,26 @@ public class JsonFoldingBuilder implements FoldingBuilder, DumbAware { public String getPlaceholderText(@NotNull ASTNode node) { final IElementType type = node.getElementType(); if (type == JsonElementTypes.OBJECT) { + final JsonObject object = node.getPsi(JsonObject.class); + final List properties = object.getPropertyList(); + JsonProperty candidate = null; + for (JsonProperty property : properties) { + final String name = property.getName(); + final JsonValue value = property.getValue(); + if (value instanceof JsonLiteral) { + if ("id".equals(name) || "name".equals(name)) { + candidate = property; + break; + } + if (candidate == null) { + candidate = property; + } + } + } + if (candidate != null) { + //noinspection ConstantConditions + return "{\"" + candidate.getName() + "\": " + candidate.getValue().getText() + "...}"; + } return "{...}"; } else if (type == JsonElementTypes.ARRAY) { diff --git a/json/tests/test/com/intellij/json/JsonFoldingTest.java b/json/tests/test/com/intellij/json/JsonFoldingTest.java index 11415369f767..702ea2af5498 100644 --- a/json/tests/test/com/intellij/json/JsonFoldingTest.java +++ b/json/tests/test/com/intellij/json/JsonFoldingTest.java @@ -16,4 +16,19 @@ public class JsonFoldingTest extends JsonTestCase { public void testObjectFolding() { doTest(); } + + // Moved from JavaScript + + public void testObjectLiteral2() { + doTest(); + } + + public void testObjectLiteral3() { + doTest(); + } + + public void testObjectLiteral4() { + doTest(); + } + } diff --git a/json/tests/testData/folding/ObjectFolding.json b/json/tests/testData/folding/ObjectFolding.json index f7f489ee690f..42b297d0c658 100644 --- a/json/tests/testData/folding/ObjectFolding.json +++ b/json/tests/testData/folding/ObjectFolding.json @@ -1,7 +1,7 @@ -{ +{ "foo": null, "bar": {"inline": true}, - "baz": { + "baz": { "nested": true } } \ No newline at end of file diff --git a/json/tests/testData/folding/ObjectLiteral2.json b/json/tests/testData/folding/ObjectLiteral2.json new file mode 100644 index 000000000000..735121a3b40a --- /dev/null +++ b/json/tests/testData/folding/ObjectLiteral2.json @@ -0,0 +1,4 @@ +{ + "id": 3, + "value": 3 +} \ No newline at end of file diff --git a/json/tests/testData/folding/ObjectLiteral3.json b/json/tests/testData/folding/ObjectLiteral3.json new file mode 100644 index 000000000000..0b8c58f86631 --- /dev/null +++ b/json/tests/testData/folding/ObjectLiteral3.json @@ -0,0 +1,3 @@ +{ + "value": 3 +} \ No newline at end of file diff --git a/json/tests/testData/folding/ObjectLiteral4.json b/json/tests/testData/folding/ObjectLiteral4.json new file mode 100644 index 000000000000..1f900975755a --- /dev/null +++ b/json/tests/testData/folding/ObjectLiteral4.json @@ -0,0 +1,3 @@ +{ + "value": {"id": 3} +} \ No newline at end of file From fb3bb21cc63d58d4b7ab9ce2538aac747008767a Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 11 Sep 2014 13:46:16 +0400 Subject: [PATCH 68/85] Move 'surround with' test from JavaScript to JSON --- .../test/com/intellij/json/JsonSurroundWithTest.java | 7 +++++++ .../testData/surround/MultipleProperties_after.json | 2 +- json/tests/testData/surround/ObjectLiteral.json | 7 +++++++ json/tests/testData/surround/ObjectLiteral_after.json | 9 +++++++++ json/tests/testData/surround/SingleProperty_after.json | 2 +- json/tests/testData/surround/SingleValue_after.json | 2 +- 6 files changed, 26 insertions(+), 3 deletions(-) create mode 100644 json/tests/testData/surround/ObjectLiteral.json create mode 100644 json/tests/testData/surround/ObjectLiteral_after.json diff --git a/json/tests/test/com/intellij/json/JsonSurroundWithTest.java b/json/tests/test/com/intellij/json/JsonSurroundWithTest.java index 4c7fec0bb4d5..9502ff6e51fc 100644 --- a/json/tests/test/com/intellij/json/JsonSurroundWithTest.java +++ b/json/tests/test/com/intellij/json/JsonSurroundWithTest.java @@ -34,4 +34,11 @@ public class JsonSurroundWithTest extends JsonTestCase { public void testCannotSurroundPropertyKey() { doTest(); } + + // Moved from JavaScript + + + public void testObjectLiteral() { + doTest(); + } } diff --git a/json/tests/testData/surround/MultipleProperties_after.json b/json/tests/testData/surround/MultipleProperties_after.json index b22ff58c5f07..3a16bfb3c7ee 100644 --- a/json/tests/testData/surround/MultipleProperties_after.json +++ b/json/tests/testData/surround/MultipleProperties_after.json @@ -1,5 +1,5 @@ { - "property": { + "property": { "foo": null, "bar": false } diff --git a/json/tests/testData/surround/ObjectLiteral.json b/json/tests/testData/surround/ObjectLiteral.json new file mode 100644 index 000000000000..c00208c2ccee --- /dev/null +++ b/json/tests/testData/surround/ObjectLiteral.json @@ -0,0 +1,7 @@ +{ + "main":{ + "id": 'burndown', + "title": 'Burndown', + "xtype": 'app.widgets.BurndownDiagram' + } +} diff --git a/json/tests/testData/surround/ObjectLiteral_after.json b/json/tests/testData/surround/ObjectLiteral_after.json new file mode 100644 index 000000000000..06903a8e9f03 --- /dev/null +++ b/json/tests/testData/surround/ObjectLiteral_after.json @@ -0,0 +1,9 @@ +{ + "main": { + "property": { + "id": 'burndown', + "title": 'Burndown', + "xtype": 'app.widgets.BurndownDiagram' + } + } +} diff --git a/json/tests/testData/surround/SingleProperty_after.json b/json/tests/testData/surround/SingleProperty_after.json index c35cb870d0db..019436aa8090 100644 --- a/json/tests/testData/surround/SingleProperty_after.json +++ b/json/tests/testData/surround/SingleProperty_after.json @@ -1,5 +1,5 @@ { - "property": { + "property": { "foo": null } } \ No newline at end of file diff --git a/json/tests/testData/surround/SingleValue_after.json b/json/tests/testData/surround/SingleValue_after.json index 963868b0afb7..440c9ce72ee7 100644 --- a/json/tests/testData/surround/SingleValue_after.json +++ b/json/tests/testData/surround/SingleValue_after.json @@ -1,3 +1,3 @@ { - "property": [null] + "property": [null] } \ No newline at end of file From 86b67ffd32ea089518a056696d146569ba63f0ca Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 11 Sep 2014 14:39:25 +0400 Subject: [PATCH 69/85] Move test for WEB-10585 to the rest of JSON test suite --- .../json/editor/lineMover/JsonLineMover.java | 36 +++++++++---------- .../com/intellij/json/JsonLineMoverTest.java | 10 ++++++ .../intellij/json/JsonStructureViewTest.java | 4 +-- .../test/com/intellij/json/JsonTestCase.java | 9 ++--- json/tests/testData/mover/Web_10585.json | 4 +++ .../testData/mover/Web_10585_afterDown.json | 4 +++ .../testData/mover/Web_10585_afterUp.json | 4 +++ 7 files changed, 42 insertions(+), 29 deletions(-) create mode 100644 json/tests/testData/mover/Web_10585.json create mode 100644 json/tests/testData/mover/Web_10585_afterDown.json create mode 100644 json/tests/testData/mover/Web_10585_afterUp.json diff --git a/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java b/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java index e31e50289bec..7c18f8609e91 100644 --- a/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java +++ b/json/src/com/intellij/json/editor/lineMover/JsonLineMover.java @@ -44,31 +44,15 @@ public class JsonLineMover extends LineMover { final PsiElement commonParent = movedElementRange.getFirst().getParent(); final PsiElement lowerRightElement = down ? destElementRange.getSecond() : movedElementRange.getSecond(); - if (commonParent instanceof JsonArray) { - if (PsiTreeUtil.getNextSiblingOfType(lowerRightElement, JsonValue.class) == null && - TreeUtil.findSibling(lowerRightElement.getNode(), JsonElementTypes.COMMA) == null) { + // Destination rightmost element is not closing brace or bracket + if (lowerRightElement instanceof JsonElement) { + if (commonParent instanceof JsonArray && notFollowedByNextElementOrComma(lowerRightElement, JsonValue.class) || + commonParent instanceof JsonObject && notFollowedByNextElementOrComma(lowerRightElement, JsonProperty.class)) { myShouldAddComma = true; } } - else if (commonParent instanceof JsonObject) { - if (PsiTreeUtil.getNextSiblingOfType(lowerRightElement, JsonProperty.class) == null && - TreeUtil.findSibling(lowerRightElement.getNode(), JsonElementTypes.COMMA) == null) { - myShouldAddComma = true; - } - } - - info.indentSource = false; - info.indentTarget = false; return true; -} - - - private static boolean isValidElementRange(@Nullable Pair elementRange) { - if (elementRange == null) { - return false; - } - return elementRange.getFirst().getParent() == elementRange.getSecond().getParent(); } @Override @@ -89,4 +73,16 @@ public class JsonLineMover extends LineMover { PsiDocumentManager.getInstance(project).commitDocument(document); } } + + private static boolean notFollowedByNextElementOrComma(@NotNull PsiElement anchor, @NotNull Class nextElementType) { + return PsiTreeUtil.getNextSiblingOfType(anchor, nextElementType) == null && + TreeUtil.findSibling(anchor.getNode(), JsonElementTypes.COMMA) == null; + } + + private static boolean isValidElementRange(@Nullable Pair elementRange) { + if (elementRange == null) { + return false; + } + return elementRange.getFirst().getParent() == elementRange.getSecond().getParent(); + } } diff --git a/json/tests/test/com/intellij/json/JsonLineMoverTest.java b/json/tests/test/com/intellij/json/JsonLineMoverTest.java index 76df2e9e6792..2babea91e3bb 100644 --- a/json/tests/test/com/intellij/json/JsonLineMoverTest.java +++ b/json/tests/test/com/intellij/json/JsonLineMoverTest.java @@ -1,6 +1,7 @@ package com.intellij.json; import com.intellij.openapi.actionSystem.IdeActions; +import com.intellij.openapi.fileEditor.FileDocumentManager; /** * @author Mikhail Golubev @@ -36,4 +37,13 @@ public class JsonLineMoverTest extends JsonTestCase { public void testObjectSelectionMovedDown() { doTest(true); } + + + // Moved from JavaScript + + public void testWeb_10585() { + doTest(false); + FileDocumentManager.getInstance().reloadFromDisk(myFixture.getDocument(myFixture.getFile())); + doTest(true); + } } diff --git a/json/tests/test/com/intellij/json/JsonStructureViewTest.java b/json/tests/test/com/intellij/json/JsonStructureViewTest.java index e99dd7f51c4c..34d92bfade8a 100644 --- a/json/tests/test/com/intellij/json/JsonStructureViewTest.java +++ b/json/tests/test/com/intellij/json/JsonStructureViewTest.java @@ -40,11 +40,11 @@ public class JsonStructureViewTest extends JsonTestCase { public void testJsonStructure() { myFixture.configureByFile("structureView/SimpleStructure.json"); - final StructureViewBuilder builder = LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(getFile()); + final StructureViewBuilder builder = LanguageStructureViewBuilder.INSTANCE.getStructureViewBuilder(myFixture.getFile()); assertNotNull(builder); StructureViewComponent component = null; try { - final FileEditor editor = FileEditorManager.getInstance(getProject()).getSelectedEditor(getFile().getVirtualFile()); + final FileEditor editor = FileEditorManager.getInstance(getProject()).getSelectedEditor(myFixture.getFile().getVirtualFile()); component = (StructureViewComponent)builder.createStructureView(editor, myFixture.getProject()); final StructureViewModel model = component.getTreeModel(); diff --git a/json/tests/test/com/intellij/json/JsonTestCase.java b/json/tests/test/com/intellij/json/JsonTestCase.java index a24de36ef07f..1a72cd389fa1 100644 --- a/json/tests/test/com/intellij/json/JsonTestCase.java +++ b/json/tests/test/com/intellij/json/JsonTestCase.java @@ -4,14 +4,14 @@ import com.intellij.openapi.diagnostic.Logger; import com.intellij.testFramework.PlatformTestCase; import com.intellij.testFramework.TestDataPath; import com.intellij.testFramework.TestLoggerFactory; -import com.intellij.testFramework.fixtures.CodeInsightFixtureTestCase; +import com.intellij.testFramework.fixtures.LightCodeInsightFixtureTestCase; import org.jetbrains.annotations.NotNull; /** * @author Mikhail Golubev */ @TestDataPath("$CONTENT_ROOT/testData") -public abstract class JsonTestCase extends CodeInsightFixtureTestCase { +public abstract class JsonTestCase extends LightCodeInsightFixtureTestCase { static { Logger.setFactory(TestLoggerFactory.class); } @@ -29,9 +29,4 @@ public abstract class JsonTestCase extends CodeInsightFixtureTestCase { public String getBasePath() { return "/json/tests/testData"; } - - @Override - protected boolean isCommunity() { - return true; - } } \ No newline at end of file diff --git a/json/tests/testData/mover/Web_10585.json b/json/tests/testData/mover/Web_10585.json new file mode 100644 index 000000000000..ed5067667585 --- /dev/null +++ b/json/tests/testData/mover/Web_10585.json @@ -0,0 +1,4 @@ +{ + "name": "foo", + "cycles": 37, +} \ No newline at end of file diff --git a/json/tests/testData/mover/Web_10585_afterDown.json b/json/tests/testData/mover/Web_10585_afterDown.json new file mode 100644 index 000000000000..d74a0f9cd1f7 --- /dev/null +++ b/json/tests/testData/mover/Web_10585_afterDown.json @@ -0,0 +1,4 @@ +{ + "name": "foo", +} +"cycles": 37, diff --git a/json/tests/testData/mover/Web_10585_afterUp.json b/json/tests/testData/mover/Web_10585_afterUp.json new file mode 100644 index 000000000000..2b3b3c4b2e3e --- /dev/null +++ b/json/tests/testData/mover/Web_10585_afterUp.json @@ -0,0 +1,4 @@ +{ + "cycles": 37, + "name": "foo", +} \ No newline at end of file From 64d7fcdef2736ae3bc940024c3f016766b43a6c9 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 11 Sep 2014 16:13:10 +0400 Subject: [PATCH 70/85] Add more tests of parsing various kinds of incomplete JSON --- .../com/intellij/json/JsonParsingTest.java | 50 ++++++++++++------- .../psi/IncompleteObjectProperties.json | 5 ++ .../psi/IncompleteObjectProperties.txt | 27 ++++++++++ .../psi/MissingCommaBetweenArrayElements.json | 4 ++ .../psi/MissingCommaBetweenArrayElements.txt | 13 +++++ .../MissingCommaBetweenObjectProperties.json | 4 ++ .../MissingCommaBetweenObjectProperties.txt | 23 +++++++++ 7 files changed, 108 insertions(+), 18 deletions(-) create mode 100644 json/tests/testData/psi/IncompleteObjectProperties.json create mode 100644 json/tests/testData/psi/IncompleteObjectProperties.txt create mode 100644 json/tests/testData/psi/MissingCommaBetweenArrayElements.json create mode 100644 json/tests/testData/psi/MissingCommaBetweenArrayElements.txt create mode 100644 json/tests/testData/psi/MissingCommaBetweenObjectProperties.json create mode 100644 json/tests/testData/psi/MissingCommaBetweenObjectProperties.txt diff --git a/json/tests/test/com/intellij/json/JsonParsingTest.java b/json/tests/test/com/intellij/json/JsonParsingTest.java index 84421c784705..dc3aebfa575b 100644 --- a/json/tests/test/com/intellij/json/JsonParsingTest.java +++ b/json/tests/test/com/intellij/json/JsonParsingTest.java @@ -13,6 +13,15 @@ public class JsonParsingTest extends ParsingTestCase { super("psi", "json", new JsonParserDefinition()); } + @Override + protected String getTestDataPath() { + return PlatformTestUtil.getCommunityPath() + "/json/tests/testData"; + } + + private void doTest() { + doTest(true); + } + public void testKeywords() throws Exception { doTest(); } @@ -29,6 +38,28 @@ public class JsonParsingTest extends ParsingTestCase { doTest(); } + public void testStringLiterals() { + doTest(); + } + + public void testComments() { + doTest(); + } + + public void testIncompleteObjectProperties() { + doTest(); + } + + public void testMissingCommaBetweenArrayElements() { + doTest(); + } + + public void testMissingCommaBetweenObjectProperties() { + doTest(); + } + + // Moved from JavaScript + public void testSimple1() { doTest(); } @@ -52,23 +83,6 @@ public class JsonParsingTest extends ParsingTestCase { // //public void testReal2() { // doTest(); + //} - - - public void testComments() { - doTest(); - } - - public void testStringLiterals() { - doTest(); - } - - private void doTest() { - doTest(true); - } - - @Override - protected String getTestDataPath() { - return PlatformTestUtil.getCommunityPath() + "/json/tests/testData"; - } } diff --git a/json/tests/testData/psi/IncompleteObjectProperties.json b/json/tests/testData/psi/IncompleteObjectProperties.json new file mode 100644 index 000000000000..9866dcb1264c --- /dev/null +++ b/json/tests/testData/psi/IncompleteObjectProperties.json @@ -0,0 +1,5 @@ +{ + "foo": , + "bar", + "baz" +} \ No newline at end of file diff --git a/json/tests/testData/psi/IncompleteObjectProperties.txt b/json/tests/testData/psi/IncompleteObjectProperties.txt new file mode 100644 index 000000000000..4187382bfd1e --- /dev/null +++ b/json/tests/testData/psi/IncompleteObjectProperties.txt @@ -0,0 +1,27 @@ +JsonFile: IncompleteObjectProperties.json + JsonObject + PsiElement({)('{') + PsiWhiteSpace('\n ') + JsonProperty + JsonStringLiteral + PsiElement(DOUBLE_QUOTED_STRING)('"foo"') + PsiElement(:)(':') + PsiErrorElement: expected, got ',' + + PsiWhiteSpace(' ') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + JsonProperty + JsonStringLiteral + PsiElement(DOUBLE_QUOTED_STRING)('"bar"') + PsiErrorElement:':' expected, got ',' + + PsiElement(,)(',') + PsiWhiteSpace('\n ') + JsonProperty + JsonStringLiteral + PsiElement(DOUBLE_QUOTED_STRING)('"baz"') + PsiErrorElement:':' expected, got '}' + + PsiWhiteSpace('\n') + PsiElement(})('}') \ No newline at end of file diff --git a/json/tests/testData/psi/MissingCommaBetweenArrayElements.json b/json/tests/testData/psi/MissingCommaBetweenArrayElements.json new file mode 100644 index 000000000000..ded015e783ca --- /dev/null +++ b/json/tests/testData/psi/MissingCommaBetweenArrayElements.json @@ -0,0 +1,4 @@ +[ + 42 + null +] \ No newline at end of file diff --git a/json/tests/testData/psi/MissingCommaBetweenArrayElements.txt b/json/tests/testData/psi/MissingCommaBetweenArrayElements.txt new file mode 100644 index 000000000000..c1289d9199e6 --- /dev/null +++ b/json/tests/testData/psi/MissingCommaBetweenArrayElements.txt @@ -0,0 +1,13 @@ +JsonFile: MissingCommaBetweenArrayElements.json + JsonArray + PsiElement([)('[') + PsiWhiteSpace('\n ') + JsonNumberLiteral + PsiElement(NUMBER)('42') + PsiErrorElement:',' or ']' expected, got 'null' + + PsiWhiteSpace('\n ') + JsonNullLiteral + PsiElement(null)('null') + PsiWhiteSpace('\n') + PsiElement(])(']') \ No newline at end of file diff --git a/json/tests/testData/psi/MissingCommaBetweenObjectProperties.json b/json/tests/testData/psi/MissingCommaBetweenObjectProperties.json new file mode 100644 index 000000000000..ff7451a67df5 --- /dev/null +++ b/json/tests/testData/psi/MissingCommaBetweenObjectProperties.json @@ -0,0 +1,4 @@ +{ + "foo": 42 + "bar": null +} \ No newline at end of file diff --git a/json/tests/testData/psi/MissingCommaBetweenObjectProperties.txt b/json/tests/testData/psi/MissingCommaBetweenObjectProperties.txt new file mode 100644 index 000000000000..dcd15c72a05a --- /dev/null +++ b/json/tests/testData/psi/MissingCommaBetweenObjectProperties.txt @@ -0,0 +1,23 @@ +JsonFile: MissingCommaBetweenObjectProperties.json + JsonObject + PsiElement({)('{') + PsiWhiteSpace('\n ') + JsonProperty + JsonStringLiteral + PsiElement(DOUBLE_QUOTED_STRING)('"foo"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonNumberLiteral + PsiElement(NUMBER)('42') + PsiErrorElement:',' or '}' expected, got '"bar"' + + PsiWhiteSpace('\n ') + JsonProperty + JsonStringLiteral + PsiElement(DOUBLE_QUOTED_STRING)('"bar"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonNullLiteral + PsiElement(null)('null') + PsiWhiteSpace('\n') + PsiElement(})('}') \ No newline at end of file From f7dac28085b9911da79496b160758d200b132bfa Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 11 Sep 2014 16:23:26 +0400 Subject: [PATCH 71/85] Change JSON grammar to allow usage of any literals and identifiers as property keys --- json/gen/com/intellij/json/JsonParser.java | 17 +++++-- .../com/intellij/json/psi/JsonProperty.java | 2 +- .../json/psi/impl/JsonPropertyImpl.java | 2 +- .../smartEnter/JsonSmartEnterProcessor.java | 7 ++- .../json/psi/JsonElementGenerator.java | 2 +- .../json/psi/impl/JsonPsiImplUtils.java | 14 +++++- json/src/json.bnf | 4 +- .../com/intellij/json/JsonParsingTest.java | 4 ++ .../psi/NonStandardPropertyKeyValues.json | 7 +++ .../psi/NonStandardPropertyKeyValues.txt | 49 +++++++++++++++++++ 10 files changed, 97 insertions(+), 11 deletions(-) create mode 100644 json/tests/testData/psi/NonStandardPropertyKeyValues.json create mode 100644 json/tests/testData/psi/NonStandardPropertyKeyValues.txt diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 90a6ca462715..930394b911a9 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -297,14 +297,13 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // string_literal (':' value) + // property_name (':' value) public static boolean property(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "property")) return false; - if (!nextTokenIs(builder_, "", DOUBLE_QUOTED_STRING, SINGLE_QUOTED_STRING)) return false; boolean result_; boolean pinned_; Marker marker_ = enter_section_(builder_, level_, _NONE_, ""); - result_ = string_literal(builder_, level_ + 1); + result_ = property_name(builder_, level_ + 1); pinned_ = result_; // pin = 1 result_ = result_ && property_1(builder_, level_ + 1); exit_section_(builder_, level_, marker_, PROPERTY, result_, pinned_, null); @@ -324,6 +323,18 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } + /* ********************************************************** */ + // literal | reference_expression + static boolean property_name(PsiBuilder builder_, int level_) { + if (!recursion_guard_(builder_, level_, "property_name")) return false; + boolean result_; + Marker marker_ = enter_section_(builder_); + result_ = literal(builder_, level_ + 1); + if (!result_) result_ = reference_expression(builder_, level_ + 1); + exit_section_(builder_, marker_, null, result_); + return result_; + } + /* ********************************************************** */ // INDENTIFIER public static boolean reference_expression(PsiBuilder builder_, int level_) { diff --git a/json/gen/com/intellij/json/psi/JsonProperty.java b/json/gen/com/intellij/json/psi/JsonProperty.java index 86f8867360ca..2f59e0c022ed 100644 --- a/json/gen/com/intellij/json/psi/JsonProperty.java +++ b/json/gen/com/intellij/json/psi/JsonProperty.java @@ -12,7 +12,7 @@ public interface JsonProperty extends JsonElement, PsiNamedElement { String getName(); @NotNull - JsonStringLiteral getNameElement(); + JsonValue getNameElement(); @Nullable JsonValue getValue(); diff --git a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java index 294161da503b..b371f66af8db 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonPropertyImpl.java @@ -27,7 +27,7 @@ public class JsonPropertyImpl extends JsonPropertyMixin implements JsonProperty } @NotNull - public JsonStringLiteral getNameElement() { + public JsonValue getNameElement() { return JsonPsiImplUtils.getNameElement(this); } diff --git a/json/src/com/intellij/json/editor/smartEnter/JsonSmartEnterProcessor.java b/json/src/com/intellij/json/editor/smartEnter/JsonSmartEnterProcessor.java index 2200601e1374..ed695d7425fc 100644 --- a/json/src/com/intellij/json/editor/smartEnter/JsonSmartEnterProcessor.java +++ b/json/src/com/intellij/json/editor/smartEnter/JsonSmartEnterProcessor.java @@ -1,6 +1,9 @@ package com.intellij.json.editor.smartEnter; -import com.intellij.json.psi.*; +import com.intellij.json.psi.JsonArray; +import com.intellij.json.psi.JsonFile; +import com.intellij.json.psi.JsonProperty; +import com.intellij.json.psi.JsonValue; import com.intellij.lang.SmartEnterProcessorWithFixers; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Document; @@ -91,7 +94,7 @@ public class JsonSmartEnterProcessor extends SmartEnterProcessorWithFixers { } } else { - final JsonStringLiteral propertyKey = ((JsonProperty)element).getNameElement(); + final JsonValue propertyKey = ((JsonProperty)element).getNameElement(); final int keyEndOffset = propertyKey.getTextRange().getEndOffset(); //processor.myFirstErrorOffset = keyEndOffset; if (terminatedOnCurrentLine(editor, propertyKey) && !isFollowedByTerminal(propertyKey, COLON)) { diff --git a/json/src/com/intellij/json/psi/JsonElementGenerator.java b/json/src/com/intellij/json/psi/JsonElementGenerator.java index 5cff3c711a8e..4e242c4f9f9b 100644 --- a/json/src/com/intellij/json/psi/JsonElementGenerator.java +++ b/json/src/com/intellij/json/psi/JsonElementGenerator.java @@ -36,7 +36,7 @@ public class JsonElementGenerator { * @param type of the JSON value desired * @return element created from given text * - * @see {@link com.intellij.json.psi.JsonElementGenerator#createStringLiteral(String)} + * @see #createStringLiteral(String) */ @NotNull public T createValue(@NotNull String content) { diff --git a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java index 2d655ea7daf3..d02eda5fd7a7 100644 --- a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java +++ b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java @@ -4,6 +4,7 @@ import com.intellij.json.JsonParserDefinition; import com.intellij.json.psi.*; import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiElement; import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; @@ -16,9 +17,18 @@ public class JsonPsiImplUtils { return StringUtil.stripQuotesAroundValue(property.getNameElement().getText()); } + /** + * Actually only JSON string literal should be accepted as valid name of property according to standard, + * but for compatibility with JavaScript integration any JSON literals as well as identifiers (unquoted words) + * are possible and highlighted as error later. + * + * @see com.intellij.json.codeinsight.JsonStandardComplianceAnnotator + */ @NotNull - public static JsonStringLiteral getNameElement(@NotNull JsonProperty property) { - return (JsonStringLiteral)property.getFirstChild(); + public static JsonValue getNameElement(@NotNull JsonProperty property) { + final PsiElement firstChild = property.getFirstChild(); + assert firstChild instanceof JsonLiteral || firstChild instanceof JsonReferenceExpression; + return (JsonValue)firstChild; } @Nullable diff --git a/json/src/json.bnf b/json/src/json.bnf index 19e950a6f122..1ab75ffbf074 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -69,7 +69,7 @@ private object_element ::= property (','|&'}') { pin = 1 } -property ::= string_literal (':' value) { +property ::= property_name (':' value) { methods=[ getName getNameElement @@ -81,6 +81,8 @@ property ::= string_literal (':' value) { pin(".*")=1 } +private property_name ::= literal | reference_expression + array ::= '[' array_element* ']' { pin=1 } private array_element ::= value (','|&']') { diff --git a/json/tests/test/com/intellij/json/JsonParsingTest.java b/json/tests/test/com/intellij/json/JsonParsingTest.java index dc3aebfa575b..4fe0fef17049 100644 --- a/json/tests/test/com/intellij/json/JsonParsingTest.java +++ b/json/tests/test/com/intellij/json/JsonParsingTest.java @@ -58,6 +58,10 @@ public class JsonParsingTest extends ParsingTestCase { doTest(); } + public void testNonStandardPropertyKeyValues() { + doTest(); + } + // Moved from JavaScript public void testSimple1() { diff --git a/json/tests/testData/psi/NonStandardPropertyKeyValues.json b/json/tests/testData/psi/NonStandardPropertyKeyValues.json new file mode 100644 index 000000000000..20ce603be5d1 --- /dev/null +++ b/json/tests/testData/psi/NonStandardPropertyKeyValues.json @@ -0,0 +1,7 @@ +{ + 42: null, + null: null, + false: null, + true: null, + identifier: null +} \ No newline at end of file diff --git a/json/tests/testData/psi/NonStandardPropertyKeyValues.txt b/json/tests/testData/psi/NonStandardPropertyKeyValues.txt new file mode 100644 index 000000000000..1d5d1f4ba986 --- /dev/null +++ b/json/tests/testData/psi/NonStandardPropertyKeyValues.txt @@ -0,0 +1,49 @@ +JsonFile: NonStandardPropertyKeyValues.json + JsonObject + PsiElement({)('{') + PsiWhiteSpace('\n ') + JsonProperty + JsonNumberLiteral + PsiElement(NUMBER)('42') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonNullLiteral + PsiElement(null)('null') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + JsonProperty + JsonNullLiteral + PsiElement(null)('null') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonNullLiteral + PsiElement(null)('null') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + JsonProperty + JsonBooleanLiteral + PsiElement(false)('false') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonNullLiteral + PsiElement(null)('null') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + JsonProperty + JsonBooleanLiteral + PsiElement(true)('true') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonNullLiteral + PsiElement(null)('null') + PsiElement(,)(',') + PsiWhiteSpace('\n ') + JsonProperty + JsonReferenceExpression + PsiElement(INDENTIFIER)('identifier') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonNullLiteral + PsiElement(null)('null') + PsiWhiteSpace('\n') + PsiElement(})('}') \ No newline at end of file From 93abb59764c210b4770ab832c57903a46da66663 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 11 Sep 2014 16:36:54 +0400 Subject: [PATCH 72/85] Move remaining JSON completion tests from JavaScript to platform --- .../com/intellij/json/JsonCompletionTest.java | 33 ++++++++++++------- json/tests/testData/completion/Keywords.json | 1 + .../tests/testData/completion/Keywords_2.json | 1 + .../testData/completion/Keywords_2_after.json | 1 + .../testData/completion/Keywords_after.json | 1 + .../tests/testData/completion/WithPrefix.json | 3 -- 6 files changed, 26 insertions(+), 14 deletions(-) create mode 100644 json/tests/testData/completion/Keywords.json create mode 100644 json/tests/testData/completion/Keywords_2.json create mode 100644 json/tests/testData/completion/Keywords_2_after.json create mode 100644 json/tests/testData/completion/Keywords_after.json delete mode 100644 json/tests/testData/completion/WithPrefix.json diff --git a/json/tests/test/com/intellij/json/JsonCompletionTest.java b/json/tests/test/com/intellij/json/JsonCompletionTest.java index 1c64efb0fc3d..a0fa049d1a6c 100644 --- a/json/tests/test/com/intellij/json/JsonCompletionTest.java +++ b/json/tests/test/com/intellij/json/JsonCompletionTest.java @@ -1,20 +1,32 @@ package com.intellij.json; +import com.intellij.codeInsight.lookup.LookupElement; import com.intellij.util.ArrayUtil; /** * @author Mikhail Golubev */ public class JsonCompletionTest extends JsonTestCase { - private static final String[] KEYWORDS = new String[]{"true", "false", "null"}; + private static final String[] ALL_KEYWORDS = new String[]{"true", "false", "null"}; private static final String[] NOTHING = ArrayUtil.EMPTY_STRING_ARRAY; + private void doTest(String... variants) { + myFixture.testCompletionVariants("completion/" + getTestName(false) + ".json", variants); + } + + private void doTestSingleVariant() { + myFixture.configureByFile("completion/" + getTestName(false) + ".json"); + final LookupElement[] variants = myFixture.completeBasic(); + assertNull(variants); + myFixture.checkResultByFile("completion/" + getTestName(false) + "_after.json" ); + } + public void testInsideArrayElement1() throws Exception { - doTest(KEYWORDS); + doTest(ALL_KEYWORDS); } public void testInsideArrayElement2() throws Exception { - doTest(KEYWORDS); + doTest(ALL_KEYWORDS); } public void testInsidePropertyKey1() throws Exception { @@ -26,17 +38,16 @@ public class JsonCompletionTest extends JsonTestCase { } public void testInsidePropertyValue() throws Exception { - doTest(KEYWORDS); + doTest(ALL_KEYWORDS); } - private void doTest(String... variants) { - myFixture.testCompletionVariants("completion/" + getTestName(false) + ".json", variants); + // Moved from JavaScript + + public void testKeywords() { + doTestSingleVariant(); } - public void testWithPrefix() { - // Before artificial reference expressions were added to grammar, lack of identifier-like tokens - // might lead to problems with keyword completion. - myFixture.configureByFile("completion/" + getTestName(false) + ".json"); - assertNull(myFixture.completeBasic()); + public void testKeywords_2() { + doTestSingleVariant(); } } diff --git a/json/tests/testData/completion/Keywords.json b/json/tests/testData/completion/Keywords.json new file mode 100644 index 000000000000..73155ebe0d9b --- /dev/null +++ b/json/tests/testData/completion/Keywords.json @@ -0,0 +1 @@ +[nu] \ No newline at end of file diff --git a/json/tests/testData/completion/Keywords_2.json b/json/tests/testData/completion/Keywords_2.json new file mode 100644 index 000000000000..0435563c4c43 --- /dev/null +++ b/json/tests/testData/completion/Keywords_2.json @@ -0,0 +1 @@ +{aaa:nu} \ No newline at end of file diff --git a/json/tests/testData/completion/Keywords_2_after.json b/json/tests/testData/completion/Keywords_2_after.json new file mode 100644 index 000000000000..e8aa019bf4c8 --- /dev/null +++ b/json/tests/testData/completion/Keywords_2_after.json @@ -0,0 +1 @@ +{aaa:null} \ No newline at end of file diff --git a/json/tests/testData/completion/Keywords_after.json b/json/tests/testData/completion/Keywords_after.json new file mode 100644 index 000000000000..8dfaa79e6723 --- /dev/null +++ b/json/tests/testData/completion/Keywords_after.json @@ -0,0 +1 @@ +[null] \ No newline at end of file diff --git a/json/tests/testData/completion/WithPrefix.json b/json/tests/testData/completion/WithPrefix.json deleted file mode 100644 index b3d8ddfd0707..000000000000 --- a/json/tests/testData/completion/WithPrefix.json +++ /dev/null @@ -1,3 +0,0 @@ -{ - "foo": nu -} \ No newline at end of file From c13c748730fbbaf53bf6bb71b2e2738350cb14ec Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 11 Sep 2014 18:45:37 +0400 Subject: [PATCH 73/85] Adjust JSON grammar to detect trailing comma in object and array literals --- json/gen/com/intellij/json/JsonParser.java | 14 +++++------ .../gen/com/intellij/json/JsonParserUtil.java | 9 ------- .../com/intellij/json/psi/JsonParserUtil.java | 25 +++++++++++++++++++ json/src/json.bnf | 7 +++--- 4 files changed, 36 insertions(+), 19 deletions(-) delete mode 100644 json/gen/com/intellij/json/JsonParserUtil.java create mode 100644 json/src/com/intellij/json/psi/JsonParserUtil.java diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 930394b911a9..22200bb66999 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -5,7 +5,7 @@ import com.intellij.lang.PsiBuilder; import com.intellij.lang.PsiBuilder.Marker; import com.intellij.openapi.diagnostic.Logger; import static com.intellij.json.JsonElementTypes.*; -import static com.intellij.json.JsonParserUtil.*; +import static com.intellij.json.psi.JsonParserUtil.*; import com.intellij.psi.tree.IElementType; import com.intellij.lang.ASTNode; import com.intellij.psi.tree.TokenSet; @@ -98,7 +98,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // value (','|&']') + // value (<>|&']') static boolean array_element(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_element")) return false; boolean result_; @@ -111,12 +111,12 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } - // ','|&']' + // <>|&']' private static boolean array_element_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_element_1")) return false; boolean result_; Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, COMMA); + result_ = notTrailingComma(builder_, level_ + 1); if (!result_) result_ = array_element_1_1(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; @@ -262,7 +262,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // property (','|&'}') + // property (<>|&'}') static boolean object_element(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object_element")) return false; boolean result_; @@ -275,12 +275,12 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } - // ','|&'}' + // <>|&'}' private static boolean object_element_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object_element_1")) return false; boolean result_; Marker marker_ = enter_section_(builder_); - result_ = consumeToken(builder_, COMMA); + result_ = notTrailingComma(builder_, level_ + 1); if (!result_) result_ = object_element_1_1(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; diff --git a/json/gen/com/intellij/json/JsonParserUtil.java b/json/gen/com/intellij/json/JsonParserUtil.java deleted file mode 100644 index a2e6ef5aad93..000000000000 --- a/json/gen/com/intellij/json/JsonParserUtil.java +++ /dev/null @@ -1,9 +0,0 @@ -package com.intellij.json; - -import com.intellij.lang.parser.GeneratedParserUtilBase; - -/** - * @author Mikhail Golubev - */ -public class JsonParserUtil extends GeneratedParserUtilBase { -} diff --git a/json/src/com/intellij/json/psi/JsonParserUtil.java b/json/src/com/intellij/json/psi/JsonParserUtil.java new file mode 100644 index 000000000000..d0f5f4674776 --- /dev/null +++ b/json/src/com/intellij/json/psi/JsonParserUtil.java @@ -0,0 +1,25 @@ +package com.intellij.json.psi; + +import com.intellij.json.JsonElementTypes; +import com.intellij.lang.PsiBuilder; +import com.intellij.lang.parser.GeneratedParserUtilBase; +import com.intellij.psi.tree.IElementType; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class JsonParserUtil extends GeneratedParserUtilBase { + + public static boolean notTrailingComma(@NotNull PsiBuilder builder, int level) { + if (builder.getTokenType() != JsonElementTypes.COMMA) { + return false; + } + final IElementType afterComma = builder.lookAhead(1); + if (afterComma == JsonElementTypes.R_BRACKET || afterComma == JsonElementTypes.R_CURLY) { + builder.error("trailing comma"); + } + builder.advanceLexer(); + return true; + } +} diff --git a/json/src/json.bnf b/json/src/json.bnf index 1ab75ffbf074..458f4b2d4c46 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -1,6 +1,6 @@ { parserClass = 'com.intellij.json.JsonParser' - parserUtilClass = "com.intellij.json.JsonParserUtil" + parserUtilClass = "com.intellij.json.psi.JsonParserUtil" psiPackage = 'com.intellij.json.psi' psiImplPackage = 'com.intellij.json.psi.impl' @@ -64,7 +64,7 @@ object ::= '{' object_element* '}' { // Hackity-hack to parse array elements and properties even if separating commas are missing, // TODO: Find out if there is any simpler way to do so in GrammarKit -private object_element ::= property (','|&'}') { +private object_element ::= property (<>|&'}') { recoverWhile = not_brace_or_next_value pin = 1 } @@ -85,7 +85,8 @@ private property_name ::= literal | reference_expression array ::= '[' array_element* ']' { pin=1 } -private array_element ::= value (','|&']') { +// Using rule value ((','!']')|&']') to detect trailing comma gives meaningless message: "',' or ']' expected, got ','" +private array_element ::= value (<>|&']') { recoverWhile = not_bracket_or_next_value pin=1 } From 7a01f0d9ba397a6325fe00e4c91d06dca7220624 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Thu, 11 Sep 2014 20:27:58 +0400 Subject: [PATCH 74/85] Move JSON validation checks to dedicated inspection --- json/json.iml | 1 + .../JsonStandardCompliance.html | 6 + .../com/intellij/json/JsonBundle.properties | 23 ++-- .../JsonStandardComplianceAnnotator.java | 47 -------- .../JsonStandardComplianceInspection.java | 106 ++++++++++++++++++ .../JsonStringLiteralAnnotator.java | 8 +- .../json/psi/impl/JsonPsiImplUtils.java | 2 +- .../JsonWithObjectLiteralSurrounder.java | 2 +- .../src/META-INF/JsonPlugin.xml | 6 +- 9 files changed, 138 insertions(+), 63 deletions(-) create mode 100644 json/resources/inspectionDescriptions/JsonStandardCompliance.html delete mode 100644 json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java create mode 100644 json/src/com/intellij/json/codeinsight/JsonStandardComplianceInspection.java diff --git a/json/json.iml b/json/json.iml index d58b456b56c2..aaaf40c50ffd 100644 --- a/json/json.iml +++ b/json/json.iml @@ -5,6 +5,7 @@ + diff --git a/json/resources/inspectionDescriptions/JsonStandardCompliance.html b/json/resources/inspectionDescriptions/JsonStandardCompliance.html new file mode 100644 index 000000000000..9627ff1e0faf --- /dev/null +++ b/json/resources/inspectionDescriptions/JsonStandardCompliance.html @@ -0,0 +1,6 @@ + + +This inspection checks that *.json files comply with JSON specification (RFC-4627).
+
+ + \ No newline at end of file diff --git a/json/src/com/intellij/json/JsonBundle.properties b/json/src/com/intellij/json/JsonBundle.properties index a895f2938259..e5ac50e0c100 100644 --- a/json/src/com/intellij/json/JsonBundle.properties +++ b/json/src/com/intellij/json/JsonBundle.properties @@ -1,12 +1,17 @@ -# Annotators +msg.missing.closing.quote=Missing closing quote +msg.illegal.escape.sequence=Illegal escape sequence +msg.illegal.unicode.escape.sequence=Illegal unicode escape sequence -missing.closing.quote=Missing closing quote -illegal.escape.sequence=Illegal escape sequence -illegal.unicode.escape.sequence=Illegal unicode escape sequence +msg.compliance.problem.comments=JSON standard does not allow comments +msg.compliance.problem.single.quoted.strings=JSON standard does not allow single quoted strings +msg.compliance.problem.illegal.top.level.value=JSON standard allows only object or array as top-level value +msg.compliance.problem.identifier=JSON standard does not allow identifiers +msg.compliance.problem.illegal.property.key=JSON standard allows only double quoted string as property key -compliance.problem.comments=JSON standard does not allow comments -compliance.problem.single.quoted.strings=JSON standard does not allow single quoted strings -compliance.problem.illegal.top.level.value=JSON standard does not allow not object or array as top-level value -compliance.problem.identifier=JSON standard does not allow identifiers -surround.with.object.literal.description=object literal \ No newline at end of file +name.json.inspection.group=JSON +name.standard.compliance.inspection=Compliance with JSON standard +name.add.double.quotes.quickfix=Wrap with double quotes +name.surround.with.object.literal=object literal + +option.warn.about.comments.name=Warn about comments in JSON diff --git a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java deleted file mode 100644 index 7afbfa1ffe57..000000000000 --- a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceAnnotator.java +++ /dev/null @@ -1,47 +0,0 @@ -package com.intellij.json.codeinsight; - -import com.intellij.json.JsonBundle; -import com.intellij.json.psi.*; -import com.intellij.lang.annotation.AnnotationHolder; -import com.intellij.lang.annotation.Annotator; -import com.intellij.psi.PsiComment; -import com.intellij.psi.PsiElement; -import com.intellij.psi.PsiFile; -import org.jetbrains.annotations.NotNull; - -/** - * @author Mikhail Golubev - */ -public class JsonStandardComplianceAnnotator implements Annotator { - @Override - public void annotate(@NotNull final PsiElement element, @NotNull final AnnotationHolder holder) { - element.accept(new JsonElementVisitor() { - @Override - public void visitComment(PsiComment comment) { - holder.createErrorAnnotation(comment, JsonBundle.message("compliance.problem.comments")); - } - - @Override - public void visitStringLiteral(@NotNull JsonStringLiteral stringLiteral) { - if (stringLiteral.getText().startsWith("'")) { - holder.createErrorAnnotation(stringLiteral, JsonBundle.message("compliance.problem.single.quoted.strings")); - } - super.visitStringLiteral(stringLiteral); - } - - @Override - public void visitLiteral(@NotNull JsonLiteral literal) { - final PsiFile psiFile = literal.getContainingFile(); - if (psiFile instanceof JsonFile && literal == ((JsonFile)psiFile).getTopLevelValue()) { - holder.createErrorAnnotation(literal, JsonBundle.message("compliance.problem.illegal.top.level.value")); - } - } - - @Override - public void visitReferenceExpression(@NotNull JsonReferenceExpression reference) { - holder.createErrorAnnotation(reference, JsonBundle.message("compliance.problem.identifier")); - } - - }); - } -} diff --git a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceInspection.java b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceInspection.java new file mode 100644 index 000000000000..09b01c5307be --- /dev/null +++ b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceInspection.java @@ -0,0 +1,106 @@ +package com.intellij.json.codeinsight; + +import com.intellij.codeHighlighting.HighlightDisplayLevel; +import com.intellij.codeInspection.*; +import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; +import com.intellij.json.JsonBundle; +import com.intellij.json.psi.*; +import com.intellij.openapi.project.Project; +import com.intellij.openapi.util.text.StringUtil; +import com.intellij.psi.PsiComment; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import org.jetbrains.annotations.NotNull; + +import javax.swing.*; + +/** + * Compliance checks include + *
    + *
  • Usage of line and block commentaries
  • + *
  • Usage of single quoted strings
  • + *
  • Usage of identifiers (unqouted words)
  • + *
  • Not double quoted string literal is used as property key
  • + *
+ * + * @author Mikhail Golubev + */ +public class JsonStandardComplianceInspection extends LocalInspectionTool { + public boolean myWarnAboutComments = true; + + @NotNull + public String getDisplayName() { + return JsonBundle.message("name.standard.compliance.inspection"); + } + + @NotNull + @Override + public HighlightDisplayLevel getDefaultLevel() { + return HighlightDisplayLevel.ERROR; + } + + @NotNull + @Override + public PsiElementVisitor buildVisitor(@NotNull final ProblemsHolder holder, boolean isOnTheFly) { + return new JsonElementVisitor() { + @Override + public void visitComment(PsiComment comment) { + if (myWarnAboutComments) { + holder.registerProblem(comment, JsonBundle.message("msg.compliance.problem.comments"), ProblemHighlightType.WEAK_WARNING); + } + } + + @Override + public void visitStringLiteral(@NotNull JsonStringLiteral stringLiteral) { + if (stringLiteral.getText().startsWith("'")) { + holder.registerProblem(stringLiteral, JsonBundle.message("msg.compliance.problem.single.quoted.strings"), new AddDoubleQuotesFix()); + } + super.visitStringLiteral(stringLiteral); + } + + @Override + public void visitLiteral(@NotNull JsonLiteral literal) { + if (literal.getParent() instanceof JsonFile) { + holder.registerProblem(literal, JsonBundle.message("msg.compliance.problem.illegal.top.level.value")); + } + if (JsonPsiUtil.isPropertyKey(literal) && !(literal.getText().startsWith("\""))) { + holder.registerProblem(literal, JsonBundle.message("msg.compliance.problem.illegal.property.key"), new AddDoubleQuotesFix()); + } + } + + @Override + public void visitReferenceExpression(@NotNull JsonReferenceExpression reference) { + holder.registerProblem(reference, JsonBundle.message("msg.compliance.problem.identifier"), new AddDoubleQuotesFix()); + } + }; + } + + @Override + public JComponent createOptionsPanel() { + final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this); + optionsPanel.addCheckbox(JsonBundle.message("option.warn.about.comments.name"), "myWarnAboutComments"); + return optionsPanel; + } + + private static class AddDoubleQuotesFix implements LocalQuickFix { + @NotNull + @Override + public String getName() { + return JsonBundle.message("name.add.double.quotes.quickfix"); + } + + @NotNull + @Override + public String getFamilyName() { + return getName(); + } + + @Override + public void applyFix(@NotNull Project project, @NotNull ProblemDescriptor descriptor) { + final PsiElement element = descriptor.getPsiElement(); + assert element instanceof JsonLiteral || element instanceof JsonReferenceExpression; + final String content = StringUtil.stripQuotesAroundValue(element.getText()); + element.replace(new JsonElementGenerator(project).createStringLiteral(content)); + } + } +} diff --git a/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java b/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java index ebb4d597e01c..a61758cd1867 100644 --- a/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java +++ b/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java @@ -22,7 +22,7 @@ public class JsonStringLiteralAnnotator implements Annotator { int length = text.length(); // Check that string literal closed properly if (length <= 1 || text.charAt(0) != text.charAt(length - 1) || quoteEscaped(text, length - 1)) { - holder.createErrorAnnotation(element.getTextRange(), JsonBundle.message("missing.closing.quote")); + holder.createErrorAnnotation(element.getTextRange(), JsonBundle.message("msg.missing.closing.quote")); } // Check escape sequences validity int pos = 1; @@ -30,7 +30,7 @@ public class JsonStringLiteralAnnotator implements Annotator { if (text.charAt(pos) == '\\') { if (pos >= length - 1) { TextRange range = new TextRange(offset + pos, offset + pos + 1); - holder.createErrorAnnotation(range, JsonBundle.message("illegal.escape.sequence")); + holder.createErrorAnnotation(range, JsonBundle.message("msg.illegal.escape.sequence")); break; } char next = text.charAt(pos + 1); @@ -50,7 +50,7 @@ public class JsonStringLiteralAnnotator implements Annotator { for (; i < pos + 6; i++) { if (i == length || !StringUtil.isHexDigit(text.charAt(i))) { TextRange range = new TextRange(offset + pos, offset + i); - holder.createErrorAnnotation(range, JsonBundle.message("illegal.unicode.escape.sequence")); + holder.createErrorAnnotation(range, JsonBundle.message("msg.illegal.unicode.escape.sequence")); break; } } @@ -58,7 +58,7 @@ public class JsonStringLiteralAnnotator implements Annotator { break; default: TextRange range = new TextRange(offset + pos, offset + pos + 2); - holder.createErrorAnnotation(range, JsonBundle.message("illegal.escape.sequence")); + holder.createErrorAnnotation(range, JsonBundle.message("msg.illegal.escape.sequence")); pos += 2; } } diff --git a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java index d02eda5fd7a7..2a7f2e67f589 100644 --- a/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java +++ b/json/src/com/intellij/json/psi/impl/JsonPsiImplUtils.java @@ -22,7 +22,7 @@ public class JsonPsiImplUtils { * but for compatibility with JavaScript integration any JSON literals as well as identifiers (unquoted words) * are possible and highlighted as error later. * - * @see com.intellij.json.codeinsight.JsonStandardComplianceAnnotator + * @see com.intellij.json.codeinsight.JsonStandardComplianceInspection */ @NotNull public static JsonValue getNameElement(@NotNull JsonProperty property) { diff --git a/json/src/com/intellij/json/surroundWith/JsonWithObjectLiteralSurrounder.java b/json/src/com/intellij/json/surroundWith/JsonWithObjectLiteralSurrounder.java index 487d7b13d31c..9f0a804c9c04 100644 --- a/json/src/com/intellij/json/surroundWith/JsonWithObjectLiteralSurrounder.java +++ b/json/src/com/intellij/json/surroundWith/JsonWithObjectLiteralSurrounder.java @@ -38,7 +38,7 @@ import org.jetbrains.annotations.Nullable; public class JsonWithObjectLiteralSurrounder implements Surrounder { @Override public String getTemplateDescription() { - return JsonBundle.message("surround.with.object.literal.description"); + return JsonBundle.message("name.surround.with.object.literal"); } @Override diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index 584e57b82299..3a22d6e7aed5 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -14,6 +14,8 @@ + com.intellij.json.JsonBundle + @@ -31,7 +33,6 @@ - @@ -40,6 +41,9 @@ + Date: Fri, 12 Sep 2014 21:34:00 +0400 Subject: [PATCH 75/85] Move highlighting tests from JavaScript to JSON Semantic highlighting of property keys is not supported for now however. --- .../com/intellij/json/JsonBundle.properties | 2 +- .../intellij/json/JsonHighlightingTest.java | 41 +++++++++++++-- .../com/intellij/json/JsonQuickFixTest.java | 52 +++++++++++++++++++ .../testData/highlighting/Compliance.json | 7 --- .../highlighting/ComplianceProblems.json | 12 +++++ .../ComplianceProblemsTopLevelValue.json | 1 + .../ComplianceTopLevelValues.json | 1 - json/tests/testData/highlighting/JSON.json | 12 +++++ .../highlighting/JSON_with_comment.json | 4 ++ .../highlighting/SemanticHighlighting.json | 3 ++ .../testData/highlighting/StringLiterals.json | 4 +- json/tests/testData/quickfix/JSON2.json | 1 + json/tests/testData/quickfix/JSON2_after.json | 1 + json/tests/testData/quickfix/JSON3.json | 1 + json/tests/testData/quickfix/JSON3_after.json | 1 + 15 files changed, 128 insertions(+), 15 deletions(-) create mode 100644 json/tests/test/com/intellij/json/JsonQuickFixTest.java delete mode 100644 json/tests/testData/highlighting/Compliance.json create mode 100644 json/tests/testData/highlighting/ComplianceProblems.json create mode 100644 json/tests/testData/highlighting/ComplianceProblemsTopLevelValue.json delete mode 100644 json/tests/testData/highlighting/ComplianceTopLevelValues.json create mode 100644 json/tests/testData/highlighting/JSON.json create mode 100644 json/tests/testData/highlighting/JSON_with_comment.json create mode 100644 json/tests/testData/highlighting/SemanticHighlighting.json create mode 100644 json/tests/testData/quickfix/JSON2.json create mode 100644 json/tests/testData/quickfix/JSON2_after.json create mode 100644 json/tests/testData/quickfix/JSON3.json create mode 100644 json/tests/testData/quickfix/JSON3_after.json diff --git a/json/src/com/intellij/json/JsonBundle.properties b/json/src/com/intellij/json/JsonBundle.properties index e5ac50e0c100..4da0e2fdc607 100644 --- a/json/src/com/intellij/json/JsonBundle.properties +++ b/json/src/com/intellij/json/JsonBundle.properties @@ -2,7 +2,7 @@ msg.missing.closing.quote=Missing closing quote msg.illegal.escape.sequence=Illegal escape sequence msg.illegal.unicode.escape.sequence=Illegal unicode escape sequence -msg.compliance.problem.comments=JSON standard does not allow comments +msg.compliance.problem.comments=JSON standard does not allow comments. Use JSMin or similar tool to remove comments before parsing. msg.compliance.problem.single.quoted.strings=JSON standard does not allow single quoted strings msg.compliance.problem.illegal.top.level.value=JSON standard allows only object or array as top-level value msg.compliance.problem.identifier=JSON standard does not allow identifiers diff --git a/json/tests/test/com/intellij/json/JsonHighlightingTest.java b/json/tests/test/com/intellij/json/JsonHighlightingTest.java index 7c73af0e5eb1..8114d83f4db6 100644 --- a/json/tests/test/com/intellij/json/JsonHighlightingTest.java +++ b/json/tests/test/com/intellij/json/JsonHighlightingTest.java @@ -1,24 +1,57 @@ package com.intellij.json; +import com.intellij.json.codeinsight.JsonStandardComplianceInspection; + /** * @author Mikhail Golubev */ public class JsonHighlightingTest extends JsonTestCase { private void doTest() { - final String TEST_PATH = "/highlighting/"; - myFixture.testHighlighting(true, true, false, TEST_PATH + getTestName(false) + ".json"); + doTestHighlighting(true, true, true); + } + + private long doTestHighlighting(boolean checkInfo, boolean checkWeakWarning, boolean checkWarning) { + return myFixture.testHighlighting(checkWarning, checkInfo, checkWeakWarning, "/highlighting/" + getTestName(false) + ".json"); + } + + private void enableStandardComplianceInspection(boolean checkComments) { + final JsonStandardComplianceInspection inspection = new JsonStandardComplianceInspection(); + inspection.myWarnAboutComments = checkComments; + myFixture.enableInspections(inspection); } public void testStringLiterals() { doTest(); } - public void testCompliance() { + public void testComplianceProblemsTopLevelValue() { + enableStandardComplianceInspection(true); doTest(); } - public void testComplianceTopLevelValues() { + public void testComplianceProblems() { + enableStandardComplianceInspection(true); doTest(); } + + // Moved from JavaScript + + public void testJSON_with_comment() throws Exception { + enableStandardComplianceInspection(false); + doTest(); + } + + public void testJSON() throws Exception { + enableStandardComplianceInspection(true); + doTest(); + } + + // TODO: JSON semantic highlighting? + /* + public void testSemanticHighlighting() throws Exception { + doTest(); + } + */ + } diff --git a/json/tests/test/com/intellij/json/JsonQuickFixTest.java b/json/tests/test/com/intellij/json/JsonQuickFixTest.java new file mode 100644 index 000000000000..8a80967b4da7 --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonQuickFixTest.java @@ -0,0 +1,52 @@ +package com.intellij.json; + +import com.intellij.codeInsight.intention.IntentionAction; +import com.intellij.codeInspection.LocalInspectionTool; +import com.intellij.json.codeinsight.JsonStandardComplianceInspection; +import org.jetbrains.annotations.NotNull; + +/** + * @author Mikhail Golubev + */ +public class JsonQuickFixTest extends JsonTestCase { + + protected void doTest(@NotNull Class inspectionClass, @NotNull String hint) { + final String testFileName = "quickfix/" + getTestName(false); + myFixture.enableInspections(inspectionClass); + myFixture.configureByFile(testFileName + ".json"); + myFixture.checkHighlighting(true, false, false); + final IntentionAction intentionAction = myFixture.getAvailableIntention(hint); + assertNotNull(intentionAction); + myFixture.launchAction(intentionAction); + myFixture.checkResultByFile(testFileName + "_after.json", true); + } + + public void testWrapInDoubleQuotes() { + checkWrapInDoubleQuotes("{null: false}", "{\"null\": false}"); + checkWrapInDoubleQuotes("{true: false}", "{\"true\": false}"); + checkWrapInDoubleQuotes("{42: false}", "{\"42\": false}"); + checkWrapInDoubleQuotes("{foo: false}", "{\"foo\": false}"); + checkWrapInDoubleQuotes("{'foo': false}", "{\"foo\": false}"); + checkWrapInDoubleQuotes("{\"foo\": bar}", "{\"foo\": \"bar\"}"); + checkWrapInDoubleQuotes("{\"foo\": 'bar'}", "{\"foo\": \"bar\"}"); + } + + private void checkWrapInDoubleQuotes(@NotNull String before, @NotNull String after) { + myFixture.configureByText(JsonFileType.INSTANCE, before); + myFixture.enableInspections(JsonStandardComplianceInspection.class); + final IntentionAction intentionAction = myFixture.getAvailableIntention(JsonBundle.message("name.add.double.quotes.quickfix")); + assertNotNull(intentionAction); + myFixture.launchAction(intentionAction); + myFixture.checkResult(after); + } + + // Moved from JavaScript + + public void testJSON2() { + doTest(JsonStandardComplianceInspection.class, JsonBundle.message("name.add.double.quotes.quickfix")); + } + + public void testJSON3() { + doTest(JsonStandardComplianceInspection.class, JsonBundle.message("name.add.double.quotes.quickfix")); + } +} diff --git a/json/tests/testData/highlighting/Compliance.json b/json/tests/testData/highlighting/Compliance.json deleted file mode 100644 index b5ea7ffee41e..000000000000 --- a/json/tests/testData/highlighting/Compliance.json +++ /dev/null @@ -1,7 +0,0 @@ -[ - // Line comment - /* Block - Comment - */ - 'string literal' -] \ No newline at end of file diff --git a/json/tests/testData/highlighting/ComplianceProblems.json b/json/tests/testData/highlighting/ComplianceProblems.json new file mode 100644 index 000000000000..8b4aa17e55b8 --- /dev/null +++ b/json/tests/testData/highlighting/ComplianceProblems.json @@ -0,0 +1,12 @@ +{ + /* Property key checks */ + "key1": null, + 'key2': null, + key3: null, + 42: null, + + // Property value checks + "key4": "foo", + "key5": 'foo', + "key6": foo +} \ No newline at end of file diff --git a/json/tests/testData/highlighting/ComplianceProblemsTopLevelValue.json b/json/tests/testData/highlighting/ComplianceProblemsTopLevelValue.json new file mode 100644 index 000000000000..211a7b597d5d --- /dev/null +++ b/json/tests/testData/highlighting/ComplianceProblemsTopLevelValue.json @@ -0,0 +1 @@ +null \ No newline at end of file diff --git a/json/tests/testData/highlighting/ComplianceTopLevelValues.json b/json/tests/testData/highlighting/ComplianceTopLevelValues.json deleted file mode 100644 index cf03490f8a29..000000000000 --- a/json/tests/testData/highlighting/ComplianceTopLevelValues.json +++ /dev/null @@ -1 +0,0 @@ -null \ No newline at end of file diff --git a/json/tests/testData/highlighting/JSON.json b/json/tests/testData/highlighting/JSON.json new file mode 100644 index 000000000000..709e80ba1311 --- /dev/null +++ b/json/tests/testData/highlighting/JSON.json @@ -0,0 +1,12 @@ +{ "bindings": [ + {"ircEvent": undefined}, + {'ircEvent' :123}, + /*comment*/ + {ircEvent: "PRIVMSG", "method": "randomURI", + "regex": 'test' + }, + ], +/** some comment */ +"foo": 1, +"lastComma": {"a":"b",} +} diff --git a/json/tests/testData/highlighting/JSON_with_comment.json b/json/tests/testData/highlighting/JSON_with_comment.json new file mode 100644 index 000000000000..7cca61f3d904 --- /dev/null +++ b/json/tests/testData/highlighting/JSON_with_comment.json @@ -0,0 +1,4 @@ +{ + // simple comment + "test" : 1 +} diff --git a/json/tests/testData/highlighting/SemanticHighlighting.json b/json/tests/testData/highlighting/SemanticHighlighting.json new file mode 100644 index 000000000000..66d55b3eec1d --- /dev/null +++ b/json/tests/testData/highlighting/SemanticHighlighting.json @@ -0,0 +1,3 @@ +{ + "aaa":123 +} \ No newline at end of file diff --git a/json/tests/testData/highlighting/StringLiterals.json b/json/tests/testData/highlighting/StringLiterals.json index c57237c9d2b3..d673d66f14d5 100644 --- a/json/tests/testData/highlighting/StringLiterals.json +++ b/json/tests/testData/highlighting/StringLiterals.json @@ -3,6 +3,6 @@ "illegal escape sequence: \q", "illegal unicode escapes: \uZZZZ", "illegal unicode escapes: \uBEE", - "unclosed double quoted string , - 'unclosed single quoted string + "unclosed double quoted string , + 'unclosed single quoted string ] \ No newline at end of file diff --git a/json/tests/testData/quickfix/JSON2.json b/json/tests/testData/quickfix/JSON2.json new file mode 100644 index 000000000000..d97d8c5d229b --- /dev/null +++ b/json/tests/testData/quickfix/JSON2.json @@ -0,0 +1 @@ +{aaa: 222} \ No newline at end of file diff --git a/json/tests/testData/quickfix/JSON2_after.json b/json/tests/testData/quickfix/JSON2_after.json new file mode 100644 index 000000000000..0e66cf666c01 --- /dev/null +++ b/json/tests/testData/quickfix/JSON2_after.json @@ -0,0 +1 @@ +{"aaa": 222} \ No newline at end of file diff --git a/json/tests/testData/quickfix/JSON3.json b/json/tests/testData/quickfix/JSON3.json new file mode 100644 index 000000000000..d3e8cce2fec2 --- /dev/null +++ b/json/tests/testData/quickfix/JSON3.json @@ -0,0 +1 @@ +{"aaa": bbb} \ No newline at end of file diff --git a/json/tests/testData/quickfix/JSON3_after.json b/json/tests/testData/quickfix/JSON3_after.json new file mode 100644 index 000000000000..618b0ca4238f --- /dev/null +++ b/json/tests/testData/quickfix/JSON3_after.json @@ -0,0 +1 @@ +{"aaa": "bbb"} \ No newline at end of file From b20cb95d6797aadd3d4adf978f82c430efdaf6cb Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Fri, 12 Sep 2014 22:36:07 +0400 Subject: [PATCH 76/85] Trailing commas in JSON arrays and objects are detected by annotator not parser Also JsonArray and JsonObject extent JsonContainer interface now. --- json/gen/com/intellij/json/JsonParser.java | 12 +++---- json/gen/com/intellij/json/psi/JsonArray.java | 2 +- .../com/intellij/json/psi/JsonContainer.java | 10 ++++++ .../intellij/json/psi/JsonElementVisitor.java | 8 +++-- .../gen/com/intellij/json/psi/JsonObject.java | 2 +- .../intellij/json/psi/impl/JsonArrayImpl.java | 2 +- .../json/psi/impl/JsonContainerImpl.java | 24 +++++++++++++ .../json/psi/impl/JsonObjectImpl.java | 2 +- .../com/intellij/json/JsonBundle.properties | 1 + .../intellij/json/JsonParserDefinition.java | 3 +- .../JsonStandardComplianceInspection.java | 35 +++++++++++++++++++ json/src/json.bnf | 10 +++--- .../com/intellij/json/JsonParsingTest.java | 6 +++- .../highlighting/ComplianceProblems.json | 4 ++- .../testData/highlighting/StringLiterals.json | 2 +- ...lues.json => NonStandardPropertyKeys.json} | 0 ...Values.txt => NonStandardPropertyKeys.txt} | 2 +- json/tests/testData/psi/TrailingCommas.json | 3 ++ json/tests/testData/psi/TrailingCommas.txt | 18 ++++++++++ 19 files changed, 125 insertions(+), 21 deletions(-) create mode 100644 json/gen/com/intellij/json/psi/JsonContainer.java create mode 100644 json/gen/com/intellij/json/psi/impl/JsonContainerImpl.java rename json/tests/testData/psi/{NonStandardPropertyKeyValues.json => NonStandardPropertyKeys.json} (100%) rename json/tests/testData/psi/{NonStandardPropertyKeyValues.txt => NonStandardPropertyKeys.txt} (96%) create mode 100644 json/tests/testData/psi/TrailingCommas.json create mode 100644 json/tests/testData/psi/TrailingCommas.txt diff --git a/json/gen/com/intellij/json/JsonParser.java b/json/gen/com/intellij/json/JsonParser.java index 22200bb66999..954a71a7dfc2 100644 --- a/json/gen/com/intellij/json/JsonParser.java +++ b/json/gen/com/intellij/json/JsonParser.java @@ -98,7 +98,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // value (<>|&']') + // value (','|&']') static boolean array_element(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_element")) return false; boolean result_; @@ -111,12 +111,12 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } - // <>|&']' + // ','|&']' private static boolean array_element_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "array_element_1")) return false; boolean result_; Marker marker_ = enter_section_(builder_); - result_ = notTrailingComma(builder_, level_ + 1); + result_ = consumeToken(builder_, COMMA); if (!result_) result_ = array_element_1_1(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; @@ -262,7 +262,7 @@ public class JsonParser implements PsiParser { } /* ********************************************************** */ - // property (<>|&'}') + // property (','|&'}') static boolean object_element(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object_element")) return false; boolean result_; @@ -275,12 +275,12 @@ public class JsonParser implements PsiParser { return result_ || pinned_; } - // <>|&'}' + // ','|&'}' private static boolean object_element_1(PsiBuilder builder_, int level_) { if (!recursion_guard_(builder_, level_, "object_element_1")) return false; boolean result_; Marker marker_ = enter_section_(builder_); - result_ = notTrailingComma(builder_, level_ + 1); + result_ = consumeToken(builder_, COMMA); if (!result_) result_ = object_element_1_1(builder_, level_ + 1); exit_section_(builder_, marker_, null, result_); return result_; diff --git a/json/gen/com/intellij/json/psi/JsonArray.java b/json/gen/com/intellij/json/psi/JsonArray.java index a46a8b8ff047..868b1fbf8bff 100644 --- a/json/gen/com/intellij/json/psi/JsonArray.java +++ b/json/gen/com/intellij/json/psi/JsonArray.java @@ -5,7 +5,7 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonArray extends JsonValue { +public interface JsonArray extends JsonContainer { @NotNull List getValueList(); diff --git a/json/gen/com/intellij/json/psi/JsonContainer.java b/json/gen/com/intellij/json/psi/JsonContainer.java new file mode 100644 index 000000000000..a69c0a8bf683 --- /dev/null +++ b/json/gen/com/intellij/json/psi/JsonContainer.java @@ -0,0 +1,10 @@ +// This is a generated file. Not intended for manual editing. +package com.intellij.json.psi; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.psi.PsiElement; + +public interface JsonContainer extends JsonValue { + +} diff --git a/json/gen/com/intellij/json/psi/JsonElementVisitor.java b/json/gen/com/intellij/json/psi/JsonElementVisitor.java index 18f36c61b967..c027a3bfcddf 100644 --- a/json/gen/com/intellij/json/psi/JsonElementVisitor.java +++ b/json/gen/com/intellij/json/psi/JsonElementVisitor.java @@ -9,13 +9,17 @@ import com.intellij.psi.PsiNamedElement; public class JsonElementVisitor extends PsiElementVisitor { public void visitArray(@NotNull JsonArray o) { - visitValue(o); + visitContainer(o); } public void visitBooleanLiteral(@NotNull JsonBooleanLiteral o) { visitLiteral(o); } + public void visitContainer(@NotNull JsonContainer o) { + visitValue(o); + } + public void visitLiteral(@NotNull JsonLiteral o) { visitValue(o); } @@ -29,7 +33,7 @@ public class JsonElementVisitor extends PsiElementVisitor { } public void visitObject(@NotNull JsonObject o) { - visitValue(o); + visitContainer(o); } public void visitProperty(@NotNull JsonProperty o) { diff --git a/json/gen/com/intellij/json/psi/JsonObject.java b/json/gen/com/intellij/json/psi/JsonObject.java index 139b72b25782..0f01d14651e1 100644 --- a/json/gen/com/intellij/json/psi/JsonObject.java +++ b/json/gen/com/intellij/json/psi/JsonObject.java @@ -5,7 +5,7 @@ import java.util.List; import org.jetbrains.annotations.*; import com.intellij.psi.PsiElement; -public interface JsonObject extends JsonValue { +public interface JsonObject extends JsonContainer { @NotNull List getPropertyList(); diff --git a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java index 01d067595e7c..9dadae1c0e4d 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonArrayImpl.java @@ -10,7 +10,7 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonArrayImpl extends JsonValueImpl implements JsonArray { +public class JsonArrayImpl extends JsonContainerImpl implements JsonArray { public JsonArrayImpl(ASTNode node) { super(node); diff --git a/json/gen/com/intellij/json/psi/impl/JsonContainerImpl.java b/json/gen/com/intellij/json/psi/impl/JsonContainerImpl.java new file mode 100644 index 000000000000..765b2c06a107 --- /dev/null +++ b/json/gen/com/intellij/json/psi/impl/JsonContainerImpl.java @@ -0,0 +1,24 @@ +// This is a generated file. Not intended for manual editing. +package com.intellij.json.psi.impl; + +import java.util.List; +import org.jetbrains.annotations.*; +import com.intellij.lang.ASTNode; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.util.PsiTreeUtil; +import static com.intellij.json.JsonElementTypes.*; +import com.intellij.json.psi.*; + +public class JsonContainerImpl extends JsonValueImpl implements JsonContainer { + + public JsonContainerImpl(ASTNode node) { + super(node); + } + + public void accept(@NotNull PsiElementVisitor visitor) { + if (visitor instanceof JsonElementVisitor) ((JsonElementVisitor)visitor).visitContainer(this); + else super.accept(visitor); + } + +} diff --git a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java index a9365b784e9b..1e239de1cc16 100644 --- a/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java +++ b/json/gen/com/intellij/json/psi/impl/JsonObjectImpl.java @@ -10,7 +10,7 @@ import com.intellij.psi.util.PsiTreeUtil; import static com.intellij.json.JsonElementTypes.*; import com.intellij.json.psi.*; -public class JsonObjectImpl extends JsonValueImpl implements JsonObject { +public class JsonObjectImpl extends JsonContainerImpl implements JsonObject { public JsonObjectImpl(ASTNode node) { super(node); diff --git a/json/src/com/intellij/json/JsonBundle.properties b/json/src/com/intellij/json/JsonBundle.properties index 4da0e2fdc607..426a506ff5a4 100644 --- a/json/src/com/intellij/json/JsonBundle.properties +++ b/json/src/com/intellij/json/JsonBundle.properties @@ -7,6 +7,7 @@ msg.compliance.problem.single.quoted.strings=JSON standard does not allow single msg.compliance.problem.illegal.top.level.value=JSON standard allows only object or array as top-level value msg.compliance.problem.identifier=JSON standard does not allow identifiers msg.compliance.problem.illegal.property.key=JSON standard allows only double quoted string as property key +msg.compliance.problem.trailing.comma=JSON standard does not allow trailing comma name.json.inspection.group=JSON diff --git a/json/src/com/intellij/json/JsonParserDefinition.java b/json/src/com/intellij/json/JsonParserDefinition.java index 6d9f208e09c6..2eca5d3d2119 100644 --- a/json/src/com/intellij/json/JsonParserDefinition.java +++ b/json/src/com/intellij/json/JsonParserDefinition.java @@ -29,6 +29,7 @@ public class JsonParserDefinition implements ParserDefinition { public static final TokenSet JSON_KEYWORDS = TokenSet.create(TRUE, FALSE, NULL); public static final TokenSet JSON_LITERALS = TokenSet.create(STRING_LITERAL, NUMBER_LITERAL, NULL_LITERAL, TRUE, FALSE); public static final TokenSet JSON_VALUES = TokenSet.orSet(JSON_CONTAINERS, JSON_LITERALS); + public static final TokenSet JSON_COMMENTARIES = TokenSet.create(BLOCK_COMMENT, LINE_COMMENT); @NotNull @@ -56,7 +57,7 @@ public class JsonParserDefinition implements ParserDefinition { @NotNull @Override public TokenSet getCommentTokens() { - return TokenSet.create(BLOCK_COMMENT, LINE_COMMENT); + return JSON_COMMENTARIES; } @NotNull diff --git a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceInspection.java b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceInspection.java index 09b01c5307be..0124c48fa7fe 100644 --- a/json/src/com/intellij/json/codeinsight/JsonStandardComplianceInspection.java +++ b/json/src/com/intellij/json/codeinsight/JsonStandardComplianceInspection.java @@ -4,13 +4,18 @@ import com.intellij.codeHighlighting.HighlightDisplayLevel; import com.intellij.codeInspection.*; import com.intellij.codeInspection.ui.MultipleCheckboxOptionsPanel; import com.intellij.json.JsonBundle; +import com.intellij.json.JsonElementTypes; import com.intellij.json.psi.*; import com.intellij.openapi.project.Project; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiComment; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiElementVisitor; +import com.intellij.psi.PsiWhiteSpace; +import com.intellij.psi.tree.IElementType; +import com.intellij.psi.util.PsiTreeUtil; import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; import javax.swing.*; @@ -72,9 +77,39 @@ public class JsonStandardComplianceInspection extends LocalInspectionTool { public void visitReferenceExpression(@NotNull JsonReferenceExpression reference) { holder.registerProblem(reference, JsonBundle.message("msg.compliance.problem.identifier"), new AddDoubleQuotesFix()); } + + @Override + public void visitArray(@NotNull JsonArray array) { + final PsiElement trailingComma = findTrailingComma(array, JsonElementTypes.R_BRACKET); + if (trailingComma != null) { + holder.registerProblem(trailingComma, JsonBundle.message("msg.compliance.problem.trailing.comma")); + } + } + + @Override + public void visitObject(@NotNull JsonObject object) { + final PsiElement trailingComma = findTrailingComma(object, JsonElementTypes.R_CURLY); + if (trailingComma != null) { + holder.registerProblem(trailingComma, JsonBundle.message("msg.compliance.problem.trailing.comma")); + } + } }; } + @Nullable + private static PsiElement findTrailingComma(@NotNull JsonContainer container, @NotNull IElementType ending) { + final PsiElement lastChild = container.getLastChild(); + if (lastChild.getNode().getElementType() != ending) { + return null; + } + final PsiElement beforeEnding = PsiTreeUtil.skipSiblingsBackward(lastChild, PsiComment.class, PsiWhiteSpace.class); + if (beforeEnding != null && beforeEnding.getNode().getElementType() == JsonElementTypes.COMMA) { + return beforeEnding; + } + return null; + } + + @Override public JComponent createOptionsPanel() { final MultipleCheckboxOptionsPanel optionsPanel = new MultipleCheckboxOptionsPanel(this); diff --git a/json/src/json.bnf b/json/src/json.bnf index 458f4b2d4c46..1f36efc907c2 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -44,7 +44,8 @@ INDENTIFIER='regexp:[:jletter:] [:jletterdigit:]*' ] - extends("object|array|literal|reference_expression")=value + extends("container|literal|reference_expression")=value + extends("array|object")=container extends("string_literal|number_literal|boolean_literal|null_literal")=literal implements("property")=[ "com.intellij.json.psi.JsonElement" @@ -64,7 +65,7 @@ object ::= '{' object_element* '}' { // Hackity-hack to parse array elements and properties even if separating commas are missing, // TODO: Find out if there is any simpler way to do so in GrammarKit -private object_element ::= property (<>|&'}') { +private object_element ::= property (','|&'}') { recoverWhile = not_brace_or_next_value pin = 1 } @@ -85,8 +86,7 @@ private property_name ::= literal | reference_expression array ::= '[' array_element* ']' { pin=1 } -// Using rule value ((','!']')|&']') to detect trailing comma gives meaningless message: "',' or ']' expected, got ','" -private array_element ::= value (<>|&']') { +private array_element ::= value (','|&']') { recoverWhile = not_bracket_or_next_value pin=1 } @@ -101,6 +101,8 @@ literal ::= string_literal | number_literal | boolean_literal | null_literal { mixin="com.intellij.json.psi.impl.JsonLiteralMixin" } +fake container ::= object | literal + reference_expression ::= INDENTIFIER value ::= object | array | literal | reference_expression diff --git a/json/tests/test/com/intellij/json/JsonParsingTest.java b/json/tests/test/com/intellij/json/JsonParsingTest.java index 4fe0fef17049..ee07a9437a4a 100644 --- a/json/tests/test/com/intellij/json/JsonParsingTest.java +++ b/json/tests/test/com/intellij/json/JsonParsingTest.java @@ -58,7 +58,11 @@ public class JsonParsingTest extends ParsingTestCase { doTest(); } - public void testNonStandardPropertyKeyValues() { + public void testNonStandardPropertyKeys() { + doTest(); + } + + public void testTrailingCommas() { doTest(); } diff --git a/json/tests/testData/highlighting/ComplianceProblems.json b/json/tests/testData/highlighting/ComplianceProblems.json index 8b4aa17e55b8..1511f50b369e 100644 --- a/json/tests/testData/highlighting/ComplianceProblems.json +++ b/json/tests/testData/highlighting/ComplianceProblems.json @@ -8,5 +8,7 @@ // Property value checks "key4": "foo", "key5": 'foo', - "key6": foo + "key6": foo, + "key7": [42,], + "key8": false, } \ No newline at end of file diff --git a/json/tests/testData/highlighting/StringLiterals.json b/json/tests/testData/highlighting/StringLiterals.json index d673d66f14d5..b901624d93a5 100644 --- a/json/tests/testData/highlighting/StringLiterals.json +++ b/json/tests/testData/highlighting/StringLiterals.json @@ -3,6 +3,6 @@ "illegal escape sequence: \q", "illegal unicode escapes: \uZZZZ", "illegal unicode escapes: \uBEE", - "unclosed double quoted string , + "unclosed double quoted string , 'unclosed single quoted string ] \ No newline at end of file diff --git a/json/tests/testData/psi/NonStandardPropertyKeyValues.json b/json/tests/testData/psi/NonStandardPropertyKeys.json similarity index 100% rename from json/tests/testData/psi/NonStandardPropertyKeyValues.json rename to json/tests/testData/psi/NonStandardPropertyKeys.json diff --git a/json/tests/testData/psi/NonStandardPropertyKeyValues.txt b/json/tests/testData/psi/NonStandardPropertyKeys.txt similarity index 96% rename from json/tests/testData/psi/NonStandardPropertyKeyValues.txt rename to json/tests/testData/psi/NonStandardPropertyKeys.txt index 1d5d1f4ba986..dd862090033e 100644 --- a/json/tests/testData/psi/NonStandardPropertyKeyValues.txt +++ b/json/tests/testData/psi/NonStandardPropertyKeys.txt @@ -1,4 +1,4 @@ -JsonFile: NonStandardPropertyKeyValues.json +JsonFile: NonStandardPropertyKeys.json JsonObject PsiElement({)('{') PsiWhiteSpace('\n ') diff --git a/json/tests/testData/psi/TrailingCommas.json b/json/tests/testData/psi/TrailingCommas.json new file mode 100644 index 000000000000..93828866fd5f --- /dev/null +++ b/json/tests/testData/psi/TrailingCommas.json @@ -0,0 +1,3 @@ +{ + "foo": [42,], +} \ No newline at end of file diff --git a/json/tests/testData/psi/TrailingCommas.txt b/json/tests/testData/psi/TrailingCommas.txt new file mode 100644 index 000000000000..402eda96976d --- /dev/null +++ b/json/tests/testData/psi/TrailingCommas.txt @@ -0,0 +1,18 @@ +JsonFile: TrailingCommas.json + JsonObject + PsiElement({)('{') + PsiWhiteSpace('\n ') + JsonProperty + JsonStringLiteral + PsiElement(DOUBLE_QUOTED_STRING)('"foo"') + PsiElement(:)(':') + PsiWhiteSpace(' ') + JsonArray + PsiElement([)('[') + JsonNumberLiteral + PsiElement(NUMBER)('42') + PsiElement(,)(',') + PsiElement(])(']') + PsiElement(,)(',') + PsiWhiteSpace('\n') + PsiElement(})('}') \ No newline at end of file From a36a9d41d8707a0ff1a902403cfd0cc4cd0a8874 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Mon, 15 Sep 2014 20:59:10 +0400 Subject: [PATCH 77/85] Implement renaming for JSON properties. Move designated tests from JavaScript --- .../findUsages/JsonFindUsagesProvider.java | 54 +++++++++++++ .../json/findUsages/JsonWordScanner.java | 19 +++++ .../psi/impl/JsonNamePropertyReference.java | 80 +++++++++++++++++++ .../json/psi/impl/JsonPropertyMixin.java | 12 ++- .../com/intellij/json/JsonRenameTest.java | 28 +++++++ .../testData/rename/DuplicateProperties.json | 4 + .../rename/DuplicatePropertiesQuotedName.json | 4 + .../DuplicatePropertiesQuotedName_after.json | 4 + .../rename/DuplicateProperties_after.json | 4 + .../rename/PropertyNameRequiresEscaping.json | 3 + .../PropertyNameRequiresEscaping_after.json | 3 + .../src/META-INF/JsonPlugin.xml | 10 ++- 12 files changed, 222 insertions(+), 3 deletions(-) create mode 100644 json/src/com/intellij/json/findUsages/JsonFindUsagesProvider.java create mode 100644 json/src/com/intellij/json/findUsages/JsonWordScanner.java create mode 100644 json/src/com/intellij/json/psi/impl/JsonNamePropertyReference.java create mode 100644 json/tests/test/com/intellij/json/JsonRenameTest.java create mode 100644 json/tests/testData/rename/DuplicateProperties.json create mode 100644 json/tests/testData/rename/DuplicatePropertiesQuotedName.json create mode 100644 json/tests/testData/rename/DuplicatePropertiesQuotedName_after.json create mode 100644 json/tests/testData/rename/DuplicateProperties_after.json create mode 100644 json/tests/testData/rename/PropertyNameRequiresEscaping.json create mode 100644 json/tests/testData/rename/PropertyNameRequiresEscaping_after.json diff --git a/json/src/com/intellij/json/findUsages/JsonFindUsagesProvider.java b/json/src/com/intellij/json/findUsages/JsonFindUsagesProvider.java new file mode 100644 index 000000000000..fb7dfd3c26fa --- /dev/null +++ b/json/src/com/intellij/json/findUsages/JsonFindUsagesProvider.java @@ -0,0 +1,54 @@ +package com.intellij.json.findUsages; + +import com.intellij.json.psi.JsonProperty; +import com.intellij.lang.HelpID; +import com.intellij.lang.cacheBuilder.WordsScanner; +import com.intellij.lang.findUsages.FindUsagesProvider; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiNamedElement; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public class JsonFindUsagesProvider implements FindUsagesProvider { + @Nullable + @Override + public WordsScanner getWordsScanner() { + return new JsonWordScanner(); + } + + @Override + public boolean canFindUsagesFor(@NotNull PsiElement psiElement) { + return psiElement instanceof PsiNamedElement; + } + + @Nullable + @Override + public String getHelpId(@NotNull PsiElement psiElement) { + return HelpID.FIND_OTHER_USAGES; + } + + @NotNull + @Override + public String getType(@NotNull PsiElement element) { + if (element instanceof JsonProperty) { + return "property"; + } + return ""; + } + + @NotNull + @Override + public String getDescriptiveName(@NotNull PsiElement element) { + final String name = element instanceof PsiNamedElement ? ((PsiNamedElement)element).getName() : null; + return name != null ? name : ""; + } + + @NotNull + @Override + public String getNodeText(@NotNull PsiElement element, boolean useFullName) { + return getDescriptiveName(element); + } +} diff --git a/json/src/com/intellij/json/findUsages/JsonWordScanner.java b/json/src/com/intellij/json/findUsages/JsonWordScanner.java new file mode 100644 index 000000000000..2291d16a4c06 --- /dev/null +++ b/json/src/com/intellij/json/findUsages/JsonWordScanner.java @@ -0,0 +1,19 @@ +package com.intellij.json.findUsages; + +import com.intellij.json.JsonElementTypes; +import com.intellij.json.JsonLexer; +import com.intellij.lang.cacheBuilder.DefaultWordsScanner; +import com.intellij.psi.tree.TokenSet; + +import static com.intellij.json.JsonParserDefinition.JSON_COMMENTARIES; +import static com.intellij.json.JsonParserDefinition.JSON_LITERALS; + +/** + * @author Mikhail Golubev + */ +public class JsonWordScanner extends DefaultWordsScanner { + public JsonWordScanner() { + super(new JsonLexer(), TokenSet.create(JsonElementTypes.INDENTIFIER), JSON_COMMENTARIES, JSON_LITERALS); + setMayHaveFileRefsInLiterals(true); + } +} diff --git a/json/src/com/intellij/json/psi/impl/JsonNamePropertyReference.java b/json/src/com/intellij/json/psi/impl/JsonNamePropertyReference.java new file mode 100644 index 000000000000..c74fb652b0a5 --- /dev/null +++ b/json/src/com/intellij/json/psi/impl/JsonNamePropertyReference.java @@ -0,0 +1,80 @@ +package com.intellij.json.psi.impl; + +import com.intellij.json.psi.JsonProperty; +import com.intellij.json.psi.JsonValue; +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; +import com.intellij.util.ArrayUtil; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; +import org.jetbrains.annotations.Nullable; + +/** + * @author Mikhail Golubev + */ +public class JsonNamePropertyReference implements PsiReference { + private final JsonProperty myProperty; + + public JsonNamePropertyReference(@NotNull JsonProperty property) { + myProperty = property; + } + + @Override + public PsiElement getElement() { + return myProperty; + } + + @Override + public TextRange getRangeInElement() { + final JsonValue nameElement = myProperty.getNameElement(); + final String nameText = nameElement.getText(); + final int startOffset = nameText.startsWith("\"") || nameText.startsWith("'")? 1 : 0; + final int endOffset = nameText.length() > 1 && (nameText.endsWith("\"") || nameText.endsWith("'")) ? -1 : 0; + return new TextRange(nameElement.getStartOffsetInParent() + startOffset, + nameElement.getStartOffsetInParent() + nameElement.getTextLength() + endOffset); + } + + @Nullable + @Override + public PsiElement resolve() { + return myProperty; + } + + @NotNull + @Override + public String getCanonicalText() { + return myProperty.getName(); + } + + @Override + public PsiElement handleElementRename(String newElementName) throws IncorrectOperationException { + return myProperty.setName(newElementName); + } + + @Override + public PsiElement bindToElement(@NotNull PsiElement element) throws IncorrectOperationException { + return null; + } + + @Override + public boolean isReferenceTo(PsiElement element) { + if (!(element instanceof JsonProperty)) { + return false; + } + final JsonProperty otherProperty = (JsonProperty)element; + final PsiElement selfResolve = resolve(); + return otherProperty.getName().equals(getCanonicalText()) && selfResolve != otherProperty; + } + + @NotNull + @Override + public Object[] getVariants() { + return ArrayUtil.EMPTY_OBJECT_ARRAY; + } + + @Override + public boolean isSoft() { + return true; + } +} diff --git a/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java b/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java index b9beaa0e1894..ba34dd44ec51 100644 --- a/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java +++ b/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java @@ -1,8 +1,11 @@ package com.intellij.json.psi.impl; +import com.intellij.json.psi.JsonElementGenerator; import com.intellij.json.psi.JsonProperty; import com.intellij.lang.ASTNode; +import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; +import com.intellij.psi.PsiReference; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -17,6 +20,13 @@ abstract class JsonPropertyMixin extends JsonElementImpl implements JsonProperty @Override public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException { - throw new IncorrectOperationException(); + final JsonElementGenerator generator = new JsonElementGenerator(getProject()); + // Strip only both quotes in case user wants some exotic name like key' + return getNameElement().replace(generator.createStringLiteral(StringUtil.unquoteString(name))); + } + + @Override + public PsiReference getReference() { + return new JsonNamePropertyReference(this); } } diff --git a/json/tests/test/com/intellij/json/JsonRenameTest.java b/json/tests/test/com/intellij/json/JsonRenameTest.java new file mode 100644 index 000000000000..76b5eea0043f --- /dev/null +++ b/json/tests/test/com/intellij/json/JsonRenameTest.java @@ -0,0 +1,28 @@ +package com.intellij.json; + +/** + * @author Mikhail Golubev + */ +public class JsonRenameTest extends JsonTestCase { + + private void doTest(final String newName) { + myFixture.configureByFile("rename/" + getTestName(false) + ".json"); + myFixture.renameElementAtCaret(newName); + myFixture.checkResultByFile("rename/" + getTestName(false) + "_after.json"); + } + + public void testPropertyNameRequiresEscaping() { + doTest("\"/\\\b\f\n\r\t\0\u001B'"); + } + + // Moved from JavaScript + + public void testDuplicateProperties() { + doTest("aaa2"); + } + + public void testDuplicatePropertiesQuotedName() { + doTest("\"aaa2\""); + } + +} diff --git a/json/tests/testData/rename/DuplicateProperties.json b/json/tests/testData/rename/DuplicateProperties.json new file mode 100644 index 000000000000..2cfba34c01f9 --- /dev/null +++ b/json/tests/testData/rename/DuplicateProperties.json @@ -0,0 +1,4 @@ +{ + "aaa":1, + "aaa":2 +} \ No newline at end of file diff --git a/json/tests/testData/rename/DuplicatePropertiesQuotedName.json b/json/tests/testData/rename/DuplicatePropertiesQuotedName.json new file mode 100644 index 000000000000..2cfba34c01f9 --- /dev/null +++ b/json/tests/testData/rename/DuplicatePropertiesQuotedName.json @@ -0,0 +1,4 @@ +{ + "aaa":1, + "aaa":2 +} \ No newline at end of file diff --git a/json/tests/testData/rename/DuplicatePropertiesQuotedName_after.json b/json/tests/testData/rename/DuplicatePropertiesQuotedName_after.json new file mode 100644 index 000000000000..ab37e1f5cfe6 --- /dev/null +++ b/json/tests/testData/rename/DuplicatePropertiesQuotedName_after.json @@ -0,0 +1,4 @@ +{ + "aaa2":1, + "aaa2":2 +} \ No newline at end of file diff --git a/json/tests/testData/rename/DuplicateProperties_after.json b/json/tests/testData/rename/DuplicateProperties_after.json new file mode 100644 index 000000000000..ab37e1f5cfe6 --- /dev/null +++ b/json/tests/testData/rename/DuplicateProperties_after.json @@ -0,0 +1,4 @@ +{ + "aaa2":1, + "aaa2":2 +} \ No newline at end of file diff --git a/json/tests/testData/rename/PropertyNameRequiresEscaping.json b/json/tests/testData/rename/PropertyNameRequiresEscaping.json new file mode 100644 index 000000000000..bc5b44aeb2c1 --- /dev/null +++ b/json/tests/testData/rename/PropertyNameRequiresEscaping.json @@ -0,0 +1,3 @@ +{ + "foo": null +} \ No newline at end of file diff --git a/json/tests/testData/rename/PropertyNameRequiresEscaping_after.json b/json/tests/testData/rename/PropertyNameRequiresEscaping_after.json new file mode 100644 index 000000000000..255382ffb0c3 --- /dev/null +++ b/json/tests/testData/rename/PropertyNameRequiresEscaping_after.json @@ -0,0 +1,3 @@ +{ + "\"/\\\b\f\n\r\t\u0000\u001B'": null +} \ No newline at end of file diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index 3a22d6e7aed5..73accfe0f8a1 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -32,19 +32,25 @@ - - + + + + + + + + From 2618053c443da95008c57acf12e8eab50e4ce802 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Tue, 16 Sep 2014 19:27:47 +0400 Subject: [PATCH 78/85] Reference contributor to enable find usages inside JSON from JavaScript --- .../json/psi/JsonLiteralManipulator.java | 25 --------------- .../intellij/json/psi/JsonPsiChangeUtils.java | 18 ----------- .../psi/JsonStringLiteralManipulator.java | 32 +++++++++++++++++++ .../json/psi/impl/JsonPropertyMixin.java | 14 ++++++-- ...ce.java => JsonPropertyNameReference.java} | 13 ++++---- .../src/META-INF/JsonPlugin.xml | 9 ++---- 6 files changed, 52 insertions(+), 59 deletions(-) delete mode 100644 json/src/com/intellij/json/psi/JsonLiteralManipulator.java create mode 100644 json/src/com/intellij/json/psi/JsonStringLiteralManipulator.java rename json/src/com/intellij/json/psi/impl/{JsonNamePropertyReference.java => JsonPropertyNameReference.java} (75%) diff --git a/json/src/com/intellij/json/psi/JsonLiteralManipulator.java b/json/src/com/intellij/json/psi/JsonLiteralManipulator.java deleted file mode 100644 index 6ec36499dd9d..000000000000 --- a/json/src/com/intellij/json/psi/JsonLiteralManipulator.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.intellij.json.psi; - -import com.intellij.openapi.util.TextRange; -import com.intellij.psi.AbstractElementManipulator; -import com.intellij.psi.PsiFile; -import com.intellij.psi.util.PsiTreeUtil; -import com.intellij.util.IncorrectOperationException; -import org.jetbrains.annotations.NotNull; - -public class JsonLiteralManipulator extends AbstractElementManipulator { - - @Override - public JsonLiteral handleContentChange(@NotNull JsonLiteral element, @NotNull TextRange range, String newContent) throws IncorrectOperationException { - String text = "{\"\":\"" + newContent + "\"}"; - - final PsiFile dummy = JsonPsiChangeUtils.createDummyFile(element, text); - JsonProperty property = PsiTreeUtil.findChildOfType(dummy, JsonProperty.class); - assert property != null; - - JsonValue value = property.getValue(); - assert value instanceof JsonLiteral; - - return (JsonLiteral)element.replace(value); - } -} diff --git a/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java b/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java index 341a06997b9e..4c4a9385c742 100644 --- a/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java +++ b/json/src/com/intellij/json/psi/JsonPsiChangeUtils.java @@ -2,14 +2,7 @@ package com.intellij.json.psi; import com.intellij.json.JsonElementTypes; import com.intellij.lang.ASTNode; -import com.intellij.lang.Language; -import com.intellij.lang.LanguageParserDefinitions; -import com.intellij.lang.ParserDefinition; -import com.intellij.openapi.project.Project; -import com.intellij.psi.PsiFile; -import com.intellij.psi.PsiFileFactory; import com.intellij.psi.TokenType; -import org.jetbrains.annotations.NotNull; public class JsonPsiChangeUtils { public static void removeCommaSeparatedFromList(final ASTNode myNode, final ASTNode parent) { @@ -46,15 +39,4 @@ public class JsonPsiChangeUtils { parent.removeRange(from, to); } - - @NotNull - public static PsiFile createDummyFile(JsonLiteral element, String text) { - Language language = element.getLanguage(); - ParserDefinition def = LanguageParserDefinitions.INSTANCE.forLanguage(language); - assert def != null; - Project project = element.getProject(); - final PsiFile dummyFile = PsiFileFactory.getInstance(project).createFileFromText("dummy.json", language, text, false, true); - assert dummyFile instanceof JsonFile; - return dummyFile; - } } diff --git a/json/src/com/intellij/json/psi/JsonStringLiteralManipulator.java b/json/src/com/intellij/json/psi/JsonStringLiteralManipulator.java new file mode 100644 index 000000000000..fb3865b84f9b --- /dev/null +++ b/json/src/com/intellij/json/psi/JsonStringLiteralManipulator.java @@ -0,0 +1,32 @@ +package com.intellij.json.psi; + +import com.intellij.openapi.util.TextRange; +import com.intellij.psi.AbstractElementManipulator; +import com.intellij.util.IncorrectOperationException; +import org.jetbrains.annotations.NotNull; + +public class JsonStringLiteralManipulator extends AbstractElementManipulator { + + @Override + public JsonStringLiteral handleContentChange(@NotNull JsonStringLiteral element, @NotNull TextRange range, String newContent) + throws IncorrectOperationException { + assert new TextRange(0, element.getTextLength()).contains(range); + + final String originalContent = element.getText(); + final TextRange withoutQuotes = getRangeInElement(element); + final JsonElementGenerator generator = new JsonElementGenerator(element.getProject()); + final String replacement = originalContent.substring(withoutQuotes.getStartOffset(), range.getStartOffset()) + + newContent + + originalContent.substring(range.getEndOffset(), withoutQuotes.getEndOffset()); + return generator.createStringLiteral(replacement); + } + + @NotNull + @Override + public TextRange getRangeInElement(@NotNull JsonStringLiteral element) { + final String content = element.getText(); + final int startOffset = content.startsWith("'") || content.startsWith("\"") ? 1 : 0; + final int endOffset = content.length() > 0 && (content.endsWith("'") || content.endsWith("\"")) ? -1 : 0; + return new TextRange(startOffset, content.length() + endOffset); + } +} diff --git a/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java b/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java index ba34dd44ec51..8f0d2db7495e 100644 --- a/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java +++ b/json/src/com/intellij/json/psi/impl/JsonPropertyMixin.java @@ -6,6 +6,8 @@ import com.intellij.lang.ASTNode; import com.intellij.openapi.util.text.StringUtil; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; +import com.intellij.psi.impl.source.resolve.reference.ReferenceProvidersRegistry; +import com.intellij.util.ArrayUtil; import com.intellij.util.IncorrectOperationException; import org.jetbrains.annotations.NonNls; import org.jetbrains.annotations.NotNull; @@ -22,11 +24,19 @@ abstract class JsonPropertyMixin extends JsonElementImpl implements JsonProperty public PsiElement setName(@NonNls @NotNull String name) throws IncorrectOperationException { final JsonElementGenerator generator = new JsonElementGenerator(getProject()); // Strip only both quotes in case user wants some exotic name like key' - return getNameElement().replace(generator.createStringLiteral(StringUtil.unquoteString(name))); + getNameElement().replace(generator.createStringLiteral(StringUtil.unquoteString(name))); + return this; } @Override public PsiReference getReference() { - return new JsonNamePropertyReference(this); + return new JsonPropertyNameReference(this); + } + + @NotNull + @Override + public PsiReference[] getReferences() { + final PsiReference[] fromProviders = ReferenceProvidersRegistry.getReferencesFromProviders(this); + return ArrayUtil.prepend(new JsonPropertyNameReference(this), fromProviders); } } diff --git a/json/src/com/intellij/json/psi/impl/JsonNamePropertyReference.java b/json/src/com/intellij/json/psi/impl/JsonPropertyNameReference.java similarity index 75% rename from json/src/com/intellij/json/psi/impl/JsonNamePropertyReference.java rename to json/src/com/intellij/json/psi/impl/JsonPropertyNameReference.java index c74fb652b0a5..950db8e5afbd 100644 --- a/json/src/com/intellij/json/psi/impl/JsonNamePropertyReference.java +++ b/json/src/com/intellij/json/psi/impl/JsonPropertyNameReference.java @@ -3,6 +3,7 @@ package com.intellij.json.psi.impl; import com.intellij.json.psi.JsonProperty; import com.intellij.json.psi.JsonValue; import com.intellij.openapi.util.TextRange; +import com.intellij.psi.ElementManipulators; import com.intellij.psi.PsiElement; import com.intellij.psi.PsiReference; import com.intellij.util.ArrayUtil; @@ -13,10 +14,10 @@ import org.jetbrains.annotations.Nullable; /** * @author Mikhail Golubev */ -public class JsonNamePropertyReference implements PsiReference { +public class JsonPropertyNameReference implements PsiReference { private final JsonProperty myProperty; - public JsonNamePropertyReference(@NotNull JsonProperty property) { + public JsonPropertyNameReference(@NotNull JsonProperty property) { myProperty = property; } @@ -28,11 +29,8 @@ public class JsonNamePropertyReference implements PsiReference { @Override public TextRange getRangeInElement() { final JsonValue nameElement = myProperty.getNameElement(); - final String nameText = nameElement.getText(); - final int startOffset = nameText.startsWith("\"") || nameText.startsWith("'")? 1 : 0; - final int endOffset = nameText.length() > 1 && (nameText.endsWith("\"") || nameText.endsWith("'")) ? -1 : 0; - return new TextRange(nameElement.getStartOffsetInParent() + startOffset, - nameElement.getStartOffsetInParent() + nameElement.getTextLength() + endOffset); + // Either value of string with quotes stripped or element's text as is + return ElementManipulators.getValueTextRange(nameElement); } @Nullable @@ -62,6 +60,7 @@ public class JsonNamePropertyReference implements PsiReference { if (!(element instanceof JsonProperty)) { return false; } + // May reference to the property with the same name for compatibility with JavaScript JSON support final JsonProperty otherProperty = (JsonProperty)element; final PsiElement selfResolve = resolve(); return otherProperty.getName().equals(getCanonicalText()) && selfResolve != otherProperty; diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index 73accfe0f8a1..abb8bae4e7f4 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -49,12 +49,7 @@ groupKey="name.json.inspection.group" enabledByDefault="true" level="ERROR" implementationClass="com.intellij.json.codeinsight.JsonStandardComplianceInspection"/> - - - - - - +
\ No newline at end of file From 347004fa50e528ff280367d3cea7aca72367cb78 Mon Sep 17 00:00:00 2001 From: "Vladislav.Soroka" Date: Wed, 17 Sep 2014 11:32:45 +0400 Subject: [PATCH 79/85] external system: ProjectResolverClass jar path calculation fixed --- .../service/RemoteExternalSystemCommunicationManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemCommunicationManager.java b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemCommunicationManager.java index e17d2443da61..83d2359ff498 100644 --- a/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemCommunicationManager.java +++ b/platform/external-system-impl/src/com/intellij/openapi/externalSystem/service/RemoteExternalSystemCommunicationManager.java @@ -159,7 +159,7 @@ public class RemoteExternalSystemCommunicationManager implements ExternalSystemC if (externalSystemId != null) { ExternalSystemManager manager = ExternalSystemApiUtil.getManager(externalSystemId); if (manager != null) { - params.getClassPath().add(PathUtil.getJarPathForClass(manager.getProjectResolverClass().getClass())); + params.getClassPath().add(PathUtil.getJarPathForClass(manager.getProjectResolverClass())); params.getProgramParametersList().add(manager.getProjectResolverClass().getName()); params.getProgramParametersList().add(manager.getTaskManagerClass().getName()); manager.enhanceRemoteProcessing(params); From e8f8eb948670f3b9d9094971e0266084a098a964 Mon Sep 17 00:00:00 2001 From: Yaroslav Lepenkin Date: Wed, 17 Sep 2014 12:18:13 +0400 Subject: [PATCH 80/85] [AutoDetectIndent] allow to detect indent and tab usage in small files, set tab usage to false when indent detected --- .../codeStyle/autodetect/IndentOptionsDetectorImpl.java | 9 ++++++--- .../codeStyle/autodetect/smallFileWithIndent8.java | 6 ++++++ .../testData/codeStyle/autodetect/smallFileWithTabs.java | 5 +++++ .../intellij/psi/autodetect/IndentAutoDetectionTest.java | 8 ++++++++ 4 files changed, 25 insertions(+), 3 deletions(-) create mode 100644 platform/platform-tests/testData/codeStyle/autodetect/smallFileWithIndent8.java create mode 100644 platform/platform-tests/testData/codeStyle/autodetect/smallFileWithTabs.java diff --git a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetectorImpl.java b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetectorImpl.java index f4972cda633c..b5d5d40ce190 100644 --- a/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetectorImpl.java +++ b/platform/lang-impl/src/com/intellij/psi/codeStyle/autodetect/IndentOptionsDetectorImpl.java @@ -31,7 +31,6 @@ public class IndentOptionsDetectorImpl implements IndentOptionsDetector { private static Logger LOG = Logger.getInstance("#com.intellij.psi.codeStyle.CommonCodeStyleSettings.IndentOptionsDetector"); private static final double RATE_THRESHOLD = 0.8; - private static final int MIN_LINES_THRESHOLD = 20; private static final int MAX_INDENT_TO_DETECT = 8; private final PsiFile myFile; @@ -68,10 +67,14 @@ public class IndentOptionsDetectorImpl implements IndentOptionsDetector { LOG.info("Detected tab usage in" + myFile); } } - else if (linesWithWhiteSpaceIndent > MIN_LINES_THRESHOLD) { + else { + if (indentOptions.USE_TAB_CHARACTER) { + indentOptions.USE_TAB_CHARACTER = false; + LOG.info("No tab usage detected " + myFile); + } + int newIndentSize = getPositiveIndentSize(stats); if (newIndentSize > 0) { - indentOptions.USE_TAB_CHARACTER = false; if (indentOptions.INDENT_SIZE != newIndentSize) { indentOptions.INDENT_SIZE = newIndentSize; LOG.info("Detected indent size: " + newIndentSize + " for file " + myFile); diff --git a/platform/platform-tests/testData/codeStyle/autodetect/smallFileWithIndent8.java b/platform/platform-tests/testData/codeStyle/autodetect/smallFileWithIndent8.java new file mode 100644 index 000000000000..e20d0ffce1b7 --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/autodetect/smallFileWithIndent8.java @@ -0,0 +1,6 @@ +public void Test { + + public void run() { + } + +} \ No newline at end of file diff --git a/platform/platform-tests/testData/codeStyle/autodetect/smallFileWithTabs.java b/platform/platform-tests/testData/codeStyle/autodetect/smallFileWithTabs.java new file mode 100644 index 000000000000..574df5794fdf --- /dev/null +++ b/platform/platform-tests/testData/codeStyle/autodetect/smallFileWithTabs.java @@ -0,0 +1,5 @@ +public void TabTest { + + public void run() {} + +} \ No newline at end of file diff --git a/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java b/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java index 2ff3ede87117..d22db1104340 100644 --- a/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java +++ b/platform/platform-tests/testSrc/com/intellij/psi/autodetect/IndentAutoDetectionTest.java @@ -62,6 +62,14 @@ public class IndentAutoDetectionTest extends LightPlatformCodeInsightTestCase { doTestMaxUsedIndent(2); } + public void testSmallFileWithIndent8() { + doTestMaxUsedIndent(8); + } + + public void testSmallFileWithTabs() { + doTestTabsUsed(); + } + public void testSpacesToNumbers() throws Exception { String text = " i\n" + " a\n" + From 53fc44ed6171439ccf99233ff3335f27610ac11c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Tue, 16 Sep 2014 20:58:51 +0400 Subject: [PATCH 81/85] updates: hide area with non-informative message (IDEA-129860) --- .../openapi/updateSettings/impl/AbstractUpdateDialog.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java index 9fba509bf356..7d5456dd53b3 100644 --- a/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java +++ b/platform/platform-impl/src/com/intellij/openapi/updateSettings/impl/AbstractUpdateDialog.java @@ -113,7 +113,7 @@ public abstract class AbstractUpdateDialog extends DialogWrapper { UIUtil.getCssFontDeclaration(UIUtil.getLabelFont(), fontColor, null, null) + "" + "" + - messageBody + + (myEnableLink ? messageBody : "") + ""; area.setBackground(UIUtil.getPanelBackground()); From 304dbaf1dd2d688544c0f943c9a64b3ef31f101c Mon Sep 17 00:00:00 2001 From: Anna Kozlova Date: Wed, 17 Sep 2014 10:34:42 +0400 Subject: [PATCH 82/85] do not copy container's annotations during generations (IDEA-129828) --- ...reateConstructorParameterFromFieldFix.java | 9 +++--- .../GenerateConstructorHandler.java | 4 +-- .../impl/FieldFromParameterUtils.java | 12 +++---- .../InheritanceToDelegationProcessor.java | 8 ++--- .../codeInsight/NullableNotNullManager.java | 31 ++++++++++++++++++- .../com/intellij/psi/util/PropertyUtil.java | 17 +++++----- .../lang/psi/util/GroovyPropertyUtils.java | 8 ++--- 7 files changed, 58 insertions(+), 31 deletions(-) diff --git a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java index 14e7478ad025..12cf5d8aae2f 100644 --- a/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java +++ b/java/java-impl/src/com/intellij/codeInsight/daemon/impl/quickfix/CreateConstructorParameterFromFieldFix.java @@ -326,7 +326,7 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction { if (parameter == null) { continue; } - notNull(project, field, parameter); + notNull(field, parameter); cleanupElements.add(parameter); final PsiElement assignmentStatement = AssignFieldFromParameterAction.addFieldAssignmentStatement(project, field, parameter, editor); if (assignmentStatement != null) { @@ -338,11 +338,10 @@ public class CreateConstructorParameterFromFieldFix implements IntentionAction { return created; } - private static void notNull(Project project, PsiField field, PsiParameter parameter) { - final String notNull = NullableNotNullManager.getInstance(field.getProject()).getNotNull(field); + private static void notNull(PsiField field, PsiParameter parameter) { + final PsiAnnotation notNull = NullableNotNullManager.getInstance(field.getProject()).copyNotNullAnnotation(field); if (notNull != null) { - final PsiAnnotation annotation = JavaPsiFacade.getElementFactory(project).createAnnotationFromText("@" + notNull, field); - parameter.getModifierList().addBefore(annotation, null); + parameter.getModifierList().addBefore(notNull, null); } } diff --git a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java index 7b36bdc33c9d..7990c5872b16 100644 --- a/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java +++ b/java/java-impl/src/com/intellij/codeInsight/generation/GenerateConstructorHandler.java @@ -265,9 +265,9 @@ public class GenerateConstructorHandler extends GenerateMembersHandlerBase { PsiParameter parm = factory.createParameter(parmName, field.getType(), aClass); final NullableNotNullManager nullableManager = NullableNotNullManager.getInstance(field.getProject()); - final String notNull = nullableManager.getNotNull(field); + final PsiAnnotation notNull = nullableManager.copyNotNullAnnotation(field); if (notNull != null) { - parm.getModifierList().addAfter(factory.createAnnotationFromText("@" + notNull, field), null); + parm.getModifierList().addAfter(notNull, null); } constructor.getParameterList().add(parm); diff --git a/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java b/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java index 37fb882e5e66..27ca12630905 100644 --- a/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java +++ b/java/java-impl/src/com/intellij/codeInsight/intention/impl/FieldFromParameterUtils.java @@ -187,14 +187,14 @@ public final class FieldFromParameterUtils { modifierList.setModifierProperty(PsiModifier.FINAL, isFinal); final NullableNotNullManager manager = NullableNotNullManager.getInstance(project); - final PsiAnnotation nullable = manager.getNullableAnnotation(parameter, false); - if (nullable != null && !manager.isContainerAnnotation(nullable)) { - modifierList.addAfter(factory.createAnnotationFromText("@" + nullable.getQualifiedName(), field), null); + final PsiAnnotation nullable = manager.copyNullableAnnotation(parameter); + if (nullable != null) { + modifierList.addAfter(nullable, null); } else if (isFinal) { - final PsiAnnotation notNull = manager.getNotNullAnnotation(parameter, false); - if (notNull != null && !manager.isContainerAnnotation(notNull)) { - modifierList.addAfter(factory.createAnnotationFromText("@" + notNull.getQualifiedName(), field), null); + final PsiAnnotation notNull = manager.copyNotNullAnnotation(parameter); + if (notNull != null) { + modifierList.addAfter(notNull, null); } } diff --git a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java index 6c74e8a60193..f75eb25cb4c5 100644 --- a/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java +++ b/java/java-impl/src/com/intellij/refactoring/inheritanceToDelegation/InheritanceToDelegationProcessor.java @@ -518,14 +518,14 @@ public class InheritanceToDelegationProcessor extends BaseRefactoringProcessor { final PsiModifierList modifierList = methodToAdd.getModifierList(); final NullableNotNullManager manager = NullableNotNullManager.getInstance(myProject); modifierList.setModifierProperty(PsiModifier.ABSTRACT, false); - final String nullable = manager.getNullable(method); + final PsiAnnotation nullable = manager.copyNullableAnnotation(method); if (nullable != null) { - modifierList.addAfter(myFactory.createAnnotationFromText("@" + nullable, methodToAdd), null); + modifierList.addAfter(nullable, null); } else { - final String notNull = manager.getNotNull(method); + final PsiAnnotation notNull = manager.copyNotNullAnnotation(method); if (notNull != null) { - modifierList.addAfter(myFactory.createAnnotationFromText("@" + notNull, methodToAdd), null); + modifierList.addAfter(notNull, null); } } diff --git a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java index 0f19a245ff18..00d76638cc97 100644 --- a/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java +++ b/java/java-psi-api/src/com/intellij/codeInsight/NullableNotNullManager.java @@ -95,13 +95,25 @@ public class NullableNotNullManager implements PersistentStateComponent public String getDefaultNullable() { return myDefaultNullable; } - + @Nullable public String getNullable(@NotNull PsiModifierListOwner owner) { PsiAnnotation annotation = getNullableAnnotation(owner, false); return annotation == null ? null : annotation.getQualifiedName(); } + private String checkContainer(PsiAnnotation annotation, boolean acceptContainer) { + if (annotation == null) { + return null; + } + else { + if (!acceptContainer && isContainerAnnotation(annotation)) { + return null; + } + return annotation.getQualifiedName(); + } + } + @Nullable public PsiAnnotation getNullableAnnotation(@NotNull PsiModifierListOwner owner, boolean checkBases) { return findNullabilityAnnotation(owner, checkBases, true); @@ -127,6 +139,23 @@ public class NullableNotNullManager implements PersistentStateComponent return findNullabilityAnnotation(owner, checkBases, false); } + public PsiAnnotation copyNotNullAnnotation(PsiModifierListOwner owner) { + return copyAnnotation(owner, getNotNullAnnotation(owner, false)); + } + + public PsiAnnotation copyNullableAnnotation(PsiModifierListOwner owner) { + return copyAnnotation(owner, getNullableAnnotation(owner, false)); + } + + private PsiAnnotation copyAnnotation(PsiModifierListOwner owner, + PsiAnnotation annotation) { + final String notNull = checkContainer(annotation, false); + if (notNull != null) { + return JavaPsiFacade.getElementFactory(owner.getProject()).createAnnotationFromText("@" + notNull, owner); + } + return null; + } + @Nullable public String getNotNull(@NotNull PsiModifierListOwner owner) { PsiAnnotation annotation = getNotNullAnnotation(owner, false); diff --git a/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java b/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java index 5a50bc8ea4ae..4b7de701c325 100644 --- a/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java +++ b/java/java-psi-api/src/com/intellij/psi/util/PropertyUtil.java @@ -413,7 +413,7 @@ public class PropertyUtil { PsiUtil.setModifierProperty(getMethod, PsiModifier.STATIC, true); } - annotateWithNullableStuff(field, factory, getMethod); + annotateWithNullableStuff(field, getMethod); PsiCodeBlock body = factory.createCodeBlockFromText("{\nreturn " + name + ";\n}", null); getMethod.getBody().replace(body); @@ -466,7 +466,7 @@ public class PropertyUtil { String parameterName = codeStyleManager.propertyNameToVariableName(propertyName, VariableKind.PARAMETER); PsiParameter param = factory.createParameter(parameterName, field.getType()); - annotateWithNullableStuff(field, factory, param); + annotateWithNullableStuff(field, param); setMethod.getParameterList().add(param); PsiUtil.setModifierProperty(setMethod, PsiModifier.PUBLIC, true); @@ -506,27 +506,26 @@ public class PropertyUtil { } private static void annotateWithNullableStuff(final PsiModifierListOwner field, - final PsiElementFactory factory, final PsiModifierListOwner listOwner) throws IncorrectOperationException { final NullableNotNullManager manager = NullableNotNullManager.getInstance(field.getProject()); - final String notNull = manager.getNotNull(field); + final PsiAnnotation notNull = manager.copyNotNullAnnotation(field); if (notNull != null) { - annotate(factory, listOwner, notNull); + annotate(listOwner, notNull); } else { - final String nullable = manager.getNullable(field); + final PsiAnnotation nullable = manager.copyNullableAnnotation(field); if (nullable != null) { - annotate(factory, listOwner, nullable); + annotate(listOwner, nullable); } } } - private static void annotate(final PsiElementFactory factory, final PsiModifierListOwner listOwner, final String annotationQName) + private static void annotate(final PsiModifierListOwner listOwner, final PsiAnnotation annotation) throws IncorrectOperationException { final PsiModifierList modifierList = listOwner.getModifierList(); LOG.assertTrue(modifierList != null); - modifierList.addAfter(factory.createAnnotationFromText("@" + annotationQName, listOwner), null); + modifierList.addAfter(annotation, null); } public static String suggestPropertyName(@NotNull PsiField field) { diff --git a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java index 15765bbd1a15..48bee8fe3807 100644 --- a/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java +++ b/plugins/groovy/groovy-psi/src/org/jetbrains/plugins/groovy/lang/psi/util/GroovyPropertyUtils.java @@ -557,12 +557,12 @@ public class GroovyPropertyUtils { private static void annotateWithNullableStuff(final PsiModifierListOwner field, final PsiModifierListOwner listOwner) throws IncorrectOperationException { final NullableNotNullManager manager = NullableNotNullManager.getInstance(field.getProject()); - final String notNull = manager.getNotNull(field); + final PsiAnnotation notNull = manager.copyNotNullAnnotation(field); if (notNull != null) { annotate(listOwner, notNull); } else { - final String nullable = manager.getNullable(field); + final PsiAnnotation nullable = manager.copyNullableAnnotation(field); if (nullable != null) { annotate(listOwner, nullable); } @@ -577,11 +577,11 @@ public class GroovyPropertyUtils { } } - private static void annotate(final PsiModifierListOwner listOwner, final String annotationQName) + private static void annotate(final PsiModifierListOwner listOwner, final PsiAnnotation annotation) throws IncorrectOperationException { final PsiModifierList modifierList = listOwner.getModifierList(); LOG.assertTrue(modifierList != null); - modifierList.addAnnotation(annotationQName); + modifierList.addAnnotation(annotation.getQualifiedName()); } From f6f78d20270c514d24f3d18488109072814ed192 Mon Sep 17 00:00:00 2001 From: "Egor.Ushakov" Date: Wed, 17 Sep 2014 13:07:30 +0400 Subject: [PATCH 83/85] IDEA-129861 Show a failure popup for Quick Expression Evaluation, instead of nothing --- .../xdebugger/impl/evaluate/quick/XValueHint.java | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java index 37b641e1042e..e959bd87c711 100644 --- a/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java +++ b/platform/xdebugger-impl/src/com/intellij/xdebugger/impl/evaluate/quick/XValueHint.java @@ -15,6 +15,7 @@ */ package com.intellij.xdebugger.impl.evaluate.quick; +import com.intellij.codeInsight.hint.HintManager; import com.intellij.codeInsight.hint.HintUtil; import com.intellij.execution.console.LanguageConsoleImpl; import com.intellij.execution.console.LanguageConsoleView; @@ -24,6 +25,7 @@ import com.intellij.openapi.Disposable; import com.intellij.openapi.actionSystem.ActionManager; import com.intellij.openapi.actionSystem.AnActionEvent; import com.intellij.openapi.actionSystem.ShortcutSet; +import com.intellij.openapi.application.ApplicationManager; import com.intellij.openapi.diagnostic.Logger; import com.intellij.openapi.editor.Editor; import com.intellij.openapi.fileEditor.FileDocumentManager; @@ -204,6 +206,15 @@ public class XValueHint extends AbstractValueHint { @Override public void errorOccurred(@NotNull final String errorMessage) { + ApplicationManager.getApplication().invokeLater(new Runnable() { + @Override + public void run() { + HintManager.getInstance().showErrorHint(getEditor(), errorMessage, getCurrentRange().getStartOffset(), + getCurrentRange().getEndOffset(), HintManager.ABOVE, + HintManager.HIDE_BY_ESCAPE | HintManager.HIDE_BY_TEXT_CHANGE, + 0); + } + }); LOG.debug("Cannot evaluate '" + myExpression + "':" + errorMessage); } }, myExpressionPosition); From ac2363264f57bdb33fdb0b9a1008d7d732078818 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 17 Sep 2014 10:54:41 +0400 Subject: [PATCH 84/85] proper fix for IDEA-129066 (solving a general issue with scrolling on folding) this removes a regression introduced by fix in commit 2f164b2 for IDEA-117756, that issue is now fixed in a different way --- .../execution/impl/ConsoleViewImpl.java | 3 --- .../openapi/editor/impl/FoldingModelImpl.java | 22 +++++++------------ .../editor/impl/ScrollingModelImpl.java | 2 +- .../editor/impl/VisibleEditorsTracker.java | 2 +- 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java index ae5cfe829f6c..c20c8195ac56 100644 --- a/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java +++ b/platform/lang-impl/src/com/intellij/execution/impl/ConsoleViewImpl.java @@ -1085,9 +1085,6 @@ public class ConsoleViewImpl extends JPanel implements ConsoleView, ObservableCo }; if (immediately) { model.runBatchFoldingOperation(operation); - if (isCaretAtLastLine()) { - EditorUtil.scrollToTheEnd(myEditor); - } } else { model.runBatchFoldingOperationDoNotCollapseCaret(operation); diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java index b92970425e99..15946220c5fe 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/FoldingModelImpl.java @@ -64,7 +64,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList private int mySavedCaretX; private int mySavedCaretY; - private int mySavedCaretPositionBeforeBatchFolding; + private int mySavedCaretShift; private boolean myCaretPositionSaved; private final MultiMap myGroups = new MultiMap(); private boolean myDocumentChangeProcessed = true; @@ -205,7 +205,8 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList myDoNotCollapseCaret |= dontCollapseCaret; boolean oldBatchFlag = myIsBatchFoldingProcessing; if (!oldBatchFlag) { - mySavedCaretPositionBeforeBatchFolding = myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line); + ((ScrollingModelImpl)myEditor.getScrollingModel()).finishAnimation(); + mySavedCaretShift = myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line) - myEditor.getScrollingModel().getVerticalScrollOffset(); } myIsBatchFoldingProcessing = true; @@ -236,7 +237,7 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList * Should be called from inside batch operation runnable. */ public void flushCaretShift() { - mySavedCaretPositionBeforeBatchFolding = -1; + mySavedCaretShift = -1; } @Override @@ -429,18 +430,11 @@ public class FoldingModelImpl implements FoldingModelEx, PrioritizedDocumentList myEditor.getSelectionModel().setSelection(selectionStart, selectionEnd); } - if (mySavedCaretPositionBeforeBatchFolding >= 0) { - final int offset = myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line) - mySavedCaretPositionBeforeBatchFolding; + if (mySavedCaretShift > 0) { final ScrollingModel scrollingModel = myEditor.getScrollingModel(); - scrollingModel.runActionOnScrollingFinished(new Runnable() { - @Override - public void run() { - scrollingModel.disableAnimation(); - int pos = scrollingModel.getVerticalScrollOffset(); - scrollingModel.scrollVertically(pos + offset); - scrollingModel.enableAnimation(); - } - }); + scrollingModel.disableAnimation(); + scrollingModel.scrollVertically(myEditor.visibleLineToY(myEditor.getCaretModel().getVisualPosition().line) - mySavedCaretShift); + scrollingModel.enableAnimation(); } } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java index 2942bafcc7d5..029d6742b4e8 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/ScrollingModelImpl.java @@ -376,7 +376,7 @@ public class ScrollingModelImpl implements ScrollingModelEx { LOG.assertTrue(success); } - public void commandStarted() { + public void finishAnimation() { cancelAnimatedScrolling(true); } diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/VisibleEditorsTracker.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/VisibleEditorsTracker.java index bacbf42ec614..5cbdb35b3eaf 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/VisibleEditorsTracker.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/VisibleEditorsTracker.java @@ -54,7 +54,7 @@ public class VisibleEditorsTracker extends CommandAdapter { myEditorsVisibleOnCommandStart.add(editor); } - ((ScrollingModelImpl)editor.getScrollingModel()).commandStarted(); + ((ScrollingModelImpl)editor.getScrollingModel()).finishAnimation(); myCurrentCommandStart = System.currentTimeMillis(); } } From fd12a9b5298a054260d864b0fa675839b5721364 Mon Sep 17 00:00:00 2001 From: Dmitry Batrak Date: Wed, 17 Sep 2014 13:03:43 +0400 Subject: [PATCH 85/85] set correct line number area width at editor creation to avoid unneeded extra soft wrap recalculation this also fixes the issue with navigation to a file element ending up with target element beyond editor viewable area (as navigation vertical offset was calculated after first soft wrap recalculation, not taking line number area width into account) --- .../intellij/openapi/editor/impl/EditorImpl.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java index 37fd93bc601a..00ed3d054e9e 100644 --- a/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java +++ b/platform/platform-impl/src/com/intellij/openapi/editor/impl/EditorImpl.java @@ -307,6 +307,13 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi private CaretImpl myPrimaryCaret; + private final TIntFunction myLineNumberAreaWidthFunction = new TIntFunction() { + @Override + public int execute(int lineNumber) { + return getFontMetrics(Font.PLAIN).stringWidth(Integer.toString(lineNumber + 2)) + 6; + } + }; + static { ourCaretBlinkingCommand.start(); } @@ -510,6 +517,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi setFontSize(UISettings.getInstance().PRESENTATION_MODE_FONT_SIZE); } + myGutterComponent.setLineNumberAreaWidth(myLineNumberAreaWidthFunction); myGutterComponent.updateSize(); Dimension preferredSize = getPreferredSize(); myEditorComponent.setSize(preferredSize); @@ -1810,12 +1818,7 @@ public final class EditorImpl extends UserDataHolderBase implements EditorEx, Hi } myPreferredSize = dim; - myGutterComponent.setLineNumberAreaWidth(new TIntFunction() { - @Override - public int execute(int lineNumber) { - return getFontMetrics(Font.PLAIN).stringWidth(Integer.toString(lineNumber + 2)) + 6; - } - }); + myGutterComponent.setLineNumberAreaWidth(myLineNumberAreaWidthFunction); myGutterComponent.updateSize(); myEditorComponent.setSize(dim);