WEB-13600 Match incomplete exponents of numeric literals in JSON lexer

Corresponding syntax error is reported later using existing annotator for JSON literals.
This commit is contained in:
Mikhail Golubev
2014-10-09 12:42:03 +04:00
parent 69d7a5db7c
commit 9a10039da5
9 changed files with 50 additions and 38 deletions
+1 -1
View File
@@ -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:]*
%%
+22 -23
View File
@@ -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
* <a href="http://www.jflex.de/">JFlex</a> 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
* <tt>/home/east825/develop/repos/IDEA/community/json/gen/com/intellij/json/_JsonLexer.flex</tt>
*/
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;
@@ -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
@@ -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) {
+1 -1
View File
@@ -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'
@@ -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 {
@@ -0,0 +1,7 @@
[
<error descr="Illegal floating point literal">1.2e</error>,
<error descr="Illegal floating point literal">1.2e+</error>,
<error descr="Illegal floating point literal">1.2E-</error>,
1.2e+1,
1.2E-1
]
+2 -10
View File
@@ -63,11 +63,7 @@ JsonFile: NumberLiterals.json
PsiElement(,)(',')
PsiWhiteSpace('\n\n ')
JsonNumberLiteral
PsiElement(NUMBER)('1')
PsiErrorElement:',' or ']' expected, got 'e'
<empty list>
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'
<empty list>
JsonReferenceExpression
PsiElement(INDENTIFIER)('e')
PsiElement(NUMBER)('1.2e')
PsiElement(,)(',')
PsiWhiteSpace('\n ')
PsiErrorElement:'.' unexpected
@@ -44,7 +44,7 @@
<basicWordSelectionFilter implementation="com.intellij.json.editor.selection.JsonBasicWordSelectionFilter"/>
<!-- Annotators -->
<annotator language="JSON" implementationClass="com.intellij.json.codeinsight.JsonStringLiteralAnnotator"/>
<annotator language="JSON" implementationClass="com.intellij.json.codeinsight.JsonLiteralAnnotator"/>
<!-- Inspections -->
<localInspection language="JSON" groupPath="JSON" shortName="JsonStandardCompliance" key="name.standard.compliance.inspection"