From 9a10039da5c8510206be575514331cfa71aa6db5 Mon Sep 17 00:00:00 2001 From: Mikhail Golubev Date: Wed, 8 Oct 2014 16:35:19 +0400 Subject: [PATCH] WEB-13600 Match incomplete exponents of numeric literals in JSON lexer Corresponding syntax error is reported later using existing annotator for JSON literals. --- json/gen/com/intellij/json/_JsonLexer.flex | 2 +- json/gen/com/intellij/json/_JsonLexer.java | 45 +++++++++---------- .../com/intellij/json/JsonBundle.properties | 1 + ...notator.java => JsonLiteralAnnotator.java} | 12 ++++- json/src/json.bnf | 2 +- .../intellij/json/JsonHighlightingTest.java | 5 +++ ...leteFloatingPointLiteralsWithExponent.json | 7 +++ json/tests/testData/psi/NumberLiterals.txt | 12 +---- .../src/META-INF/JsonPlugin.xml | 2 +- 9 files changed, 50 insertions(+), 38 deletions(-) rename json/src/com/intellij/json/codeinsight/{JsonStringLiteralAnnotator.java => JsonLiteralAnnotator.java} (82%) create mode 100644 json/tests/testData/highlighting/IncompleteFloatingPointLiteralsWithExponent.json diff --git a/json/gen/com/intellij/json/_JsonLexer.flex b/json/gen/com/intellij/json/_JsonLexer.flex index c59f27dbcbf0..7bcfc6015e1e 100644 --- a/json/gen/com/intellij/json/_JsonLexer.flex +++ b/json/gen/com/intellij/json/_JsonLexer.flex @@ -26,7 +26,7 @@ LINE_COMMENT="//".* BLOCK_COMMENT="/"\*([^*]|\*+[^*/])*(\*+"/")? DOUBLE_QUOTED_STRING=\"([^\\\"\r\n]|\\[^\r\n])*\"? SINGLE_QUOTED_STRING='([^\\'\r\n]|\\[^\r\n])*'? -NUMBER=-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]+)? +NUMBER=-?(0|[1-9][0-9]*)(\.[0-9]+)?([eE][+-]?[0-9]*)? INDENTIFIER=[:jletter:] [:jletterdigit:]* %% diff --git a/json/gen/com/intellij/json/_JsonLexer.java b/json/gen/com/intellij/json/_JsonLexer.java index 3f341b1c2c15..0f0c24fdcac8 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 10/1/14 5:02 PM */ +/* The following code was generated by JFlex 1.4.3 on 10/8/14 3:56 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 10/1/14 5:02 PM from the specification file + * on 10/8/14 3:56 PM from the specification file * /home/east825/develop/repos/IDEA/community/json/gen/com/intellij/json/_JsonLexer.flex */ public class _JsonLexer implements FlexLexer { @@ -158,12 +158,11 @@ 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\2\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\2\0\3\6\1\0"+ - "\1\5\1\0\1\5\3\6\1\16\1\17\1\6\1\20"+ - "\1\21"; + "\1\15\1\16\1\3\2\0\1\4\1\0\1\5\3\6"+ + "\1\0\2\5\3\6\1\16\1\17\1\6\1\20\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; @@ -192,11 +191,11 @@ public class _JsonLexer implements FlexLexer { "\0\u0100\0\u0120\0\40\0\40\0\40\0\40\0\40\0\40"+ "\0\u0140\0\u0160\0\u0180\0\u01a0\0\u01c0\0\40\0\u01e0\0\u0200"+ "\0\40\0\u0220\0\u0240\0\u0260\0\u0280\0\u02a0\0\u02c0\0\u02e0"+ - "\0\u0300\0\u0300\0\u0320\0\u0340\0\u0360\0\40\0\u0120\0\u0380"+ - "\0\u0120\0\u0120"; + "\0\u0300\0\u0320\0\u0340\0\u0360\0\40\0\u0120\0\u0380\0\u0120"+ + "\0\u0120"; 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; @@ -232,18 +231,18 @@ public class _JsonLexer implements FlexLexer { "\1\0\2\12\6\0\5\12\1\35\3\12\12\0\2\12"+ "\1\0\1\12\1\0\2\12\6\0\2\12\1\36\6\12"+ "\2\24\1\0\35\24\5\25\1\37\32\25\1\5\2\0"+ - "\35\5\1\6\2\0\35\6\12\0\2\40\35\0\1\41"+ - "\2\42\2\0\1\41\33\0\2\12\1\0\1\12\1\0"+ - "\2\12\6\0\2\12\1\43\6\12\12\0\2\12\1\0"+ - "\1\12\1\0\2\12\6\0\6\12\1\44\2\12\12\0"+ - "\2\12\1\0\1\12\1\0\2\12\6\0\6\12\1\45"+ - "\2\12\4\25\1\46\1\37\32\25\12\0\2\40\1\0"+ - "\1\33\14\0\1\33\17\0\2\42\36\0\2\12\1\0"+ - "\1\12\1\0\2\12\6\0\3\12\1\47\5\12\12\0"+ - "\2\12\1\0\1\12\1\0\2\12\6\0\7\12\1\50"+ - "\1\12\12\0\2\12\1\0\1\12\1\0\2\12\6\0"+ - "\6\12\1\51\2\12\12\0\2\12\1\0\1\12\1\0"+ - "\2\12\6\0\3\12\1\52\5\12"; + "\35\5\1\6\2\0\35\6\12\0\2\40\35\0\3\41"+ + "\2\0\1\41\33\0\2\12\1\0\1\12\1\0\2\12"+ + "\6\0\2\12\1\42\6\12\12\0\2\12\1\0\1\12"+ + "\1\0\2\12\6\0\6\12\1\43\2\12\12\0\2\12"+ + "\1\0\1\12\1\0\2\12\6\0\6\12\1\44\2\12"+ + "\4\25\1\45\1\37\32\25\12\0\2\40\1\0\1\33"+ + "\14\0\1\33\17\0\2\41\36\0\2\12\1\0\1\12"+ + "\1\0\2\12\6\0\3\12\1\46\5\12\12\0\2\12"+ + "\1\0\1\12\1\0\2\12\6\0\7\12\1\47\1\12"+ + "\12\0\2\12\1\0\1\12\1\0\2\12\6\0\6\12"+ + "\1\50\2\12\12\0\2\12\1\0\1\12\1\0\2\12"+ + "\6\0\3\12\1\51\5\12"; private static int [] zzUnpackTrans() { int [] result = new int[928]; @@ -288,10 +287,10 @@ public class _JsonLexer implements FlexLexer { private static final String ZZ_ATTRIBUTE_PACKED_0 = "\1\0\1\11\10\1\6\11\5\1\1\11\2\0\1\11"+ - "\2\0\3\1\1\0\1\1\1\0\4\1\1\11\4\1"; + "\1\0\4\1\1\0\5\1\1\11\4\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; diff --git a/json/src/com/intellij/json/JsonBundle.properties b/json/src/com/intellij/json/JsonBundle.properties index 1537845b49e5..ac1d5bdcf1eb 100644 --- a/json/src/com/intellij/json/JsonBundle.properties +++ b/json/src/com/intellij/json/JsonBundle.properties @@ -1,6 +1,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.illegal.floating.point.literal=Illegal floating point literal 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 diff --git a/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java b/json/src/com/intellij/json/codeinsight/JsonLiteralAnnotator.java similarity index 82% rename from json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java rename to json/src/com/intellij/json/codeinsight/JsonLiteralAnnotator.java index e83d2b8a1268..335bb12c0e48 100644 --- a/json/src/com/intellij/json/codeinsight/JsonStringLiteralAnnotator.java +++ b/json/src/com/intellij/json/codeinsight/JsonLiteralAnnotator.java @@ -1,6 +1,7 @@ package com.intellij.json.codeinsight; import com.intellij.json.JsonBundle; +import com.intellij.json.psi.JsonNumberLiteral; import com.intellij.json.psi.JsonPsiUtil; import com.intellij.json.psi.JsonStringLiteral; import com.intellij.lang.annotation.AnnotationHolder; @@ -18,8 +19,9 @@ import java.util.regex.Pattern; /** * @author Mikhail Golubev */ -public class JsonStringLiteralAnnotator implements Annotator { +public class JsonLiteralAnnotator implements Annotator { private static final Pattern VALID_ESCAPE = Pattern.compile("\\\\([\"\\\\/bfnrt]|u[0-9a-fA-F]{4})"); + private static final Pattern VALID_NUMBER_LITERAL = Pattern.compile("-?(0|[1-9][0-9]*)(\\.[0-9]+)?([eE][+-]?[0-9]+)?"); private static boolean debug = ApplicationManager.getApplication().isUnitTestMode(); @@ -34,9 +36,10 @@ public class JsonStringLiteralAnnotator implements Annotator { } final String text = element.getText(); final int length = text.length(); + // Check that string literal is closed properly if (length <= 1 || text.charAt(0) != text.charAt(length - 1) || quoteEscaped(text, length - 1)) { - holder.createErrorAnnotation(element.getTextRange(), JsonBundle.message("msg.missing.closing.quote")); + holder.createErrorAnnotation(element, JsonBundle.message("msg.missing.closing.quote")); } // Check escapes @@ -54,6 +57,11 @@ public class JsonStringLiteralAnnotator implements Annotator { } } } + else if (element instanceof JsonNumberLiteral) { + if (!VALID_NUMBER_LITERAL.matcher(element.getText()).matches()) { + holder.createErrorAnnotation(element, JsonBundle.message("msg.illegal.floating.point.literal")); + } + } } private static boolean quoteEscaped(String text, int quotePos) { diff --git a/json/src/json.bnf b/json/src/json.bnf index fe8b0fa85c1f..d85b0231e0f4 100644 --- a/json/src/json.bnf +++ b/json/src/json.bnf @@ -35,7 +35,7 @@ SINGLE_QUOTED_STRING="regexp:'([^\\\'\r\n]|\\[^\r\n])*'?" // STRING='regexp:"([^\\"\r\n]|\\([\\"/bfnrt]|u[a-fA-F0-9]{4}))*"?' - NUMBER='regexp:-?(0|[1-9]\d*)(\.\d+)?([eE][+-]?\d+)?' + NUMBER='regexp:-?(0|[1-9]\d*)(\.\d+)?([eE][+-]?\d*)?' TRUE='true' FALSE='false' NULL='null' diff --git a/json/tests/test/com/intellij/json/JsonHighlightingTest.java b/json/tests/test/com/intellij/json/JsonHighlightingTest.java index 6494a1d7cd34..55669514cf2d 100644 --- a/json/tests/test/com/intellij/json/JsonHighlightingTest.java +++ b/json/tests/test/com/intellij/json/JsonHighlightingTest.java @@ -35,6 +35,11 @@ public class JsonHighlightingTest extends JsonTestCase { doTestHighlighting(false, true, true); } + // WEB-13600 + public void testIncompleteFloatingPointLiteralsWithExponent() { + doTestHighlighting(false, false, false); + } + // Moved from JavaScript public void testJSON_with_comment() throws Exception { diff --git a/json/tests/testData/highlighting/IncompleteFloatingPointLiteralsWithExponent.json b/json/tests/testData/highlighting/IncompleteFloatingPointLiteralsWithExponent.json new file mode 100644 index 000000000000..f954b6a0db01 --- /dev/null +++ b/json/tests/testData/highlighting/IncompleteFloatingPointLiteralsWithExponent.json @@ -0,0 +1,7 @@ +[ + 1.2e, + 1.2e+, + 1.2E-, + 1.2e+1, + 1.2E-1 +] \ No newline at end of file diff --git a/json/tests/testData/psi/NumberLiterals.txt b/json/tests/testData/psi/NumberLiterals.txt index a4c9366f8e77..592f006f3ef5 100644 --- a/json/tests/testData/psi/NumberLiterals.txt +++ b/json/tests/testData/psi/NumberLiterals.txt @@ -63,11 +63,7 @@ JsonFile: NumberLiterals.json PsiElement(,)(',') PsiWhiteSpace('\n\n ') JsonNumberLiteral - PsiElement(NUMBER)('1') - PsiErrorElement:',' or ']' expected, got 'e' - - JsonReferenceExpression - PsiElement(INDENTIFIER)('e') + PsiElement(NUMBER)('1e') PsiElement(,)(',') PsiWhiteSpace('\n ') JsonReferenceExpression @@ -135,11 +131,7 @@ JsonFile: NumberLiterals.json PsiElement(,)(',') PsiWhiteSpace('\n ') JsonNumberLiteral - PsiElement(NUMBER)('1.2') - PsiErrorElement:',' or ']' expected, got 'e' - - JsonReferenceExpression - PsiElement(INDENTIFIER)('e') + PsiElement(NUMBER)('1.2e') PsiElement(,)(',') PsiWhiteSpace('\n ') PsiErrorElement:'.' unexpected diff --git a/platform/platform-resources/src/META-INF/JsonPlugin.xml b/platform/platform-resources/src/META-INF/JsonPlugin.xml index 0604be44c8ed..b693b3fb247f 100644 --- a/platform/platform-resources/src/META-INF/JsonPlugin.xml +++ b/platform/platform-resources/src/META-INF/JsonPlugin.xml @@ -44,7 +44,7 @@ - +