-
Notifications
You must be signed in to change notification settings - Fork 12.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Improve Recovery of Unterminated Regular Expressions #58289
Changes from 1 commit
ff858bc
c7b65ac
a7621e0
f1aa06f
978e195
5c75b2d
76acd92
e67692a
0247ea8
11ad5f5
77235de
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
graphemecluster marked this conversation as resolved.
Show resolved
Hide resolved
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
import * as ts from "../_namespaces/ts"; | ||
|
||
describe("unittests:: regExpParserRecovery", () => { | ||
const testCases = [ | ||
"/", | ||
"/[]", | ||
"/{}", | ||
"/()", | ||
"/foo", | ||
"/foo[]", | ||
"/foo{}", | ||
"/foo()", | ||
"/[]foo", | ||
"/{}foo", | ||
"/()foo", | ||
"/{[]}", | ||
"/([])", | ||
"/[)}({]", | ||
"/({[)}]})", | ||
"/\\[", | ||
"/\\{", | ||
"/\\(", | ||
"/[\\[]", | ||
"/(\\[)", | ||
"/{\\[}", | ||
"/[\\(]", | ||
"/(\\()", | ||
"/{\\(}", | ||
"/[\\{]", | ||
"/(\\{)", | ||
"/{\\{}", | ||
"/\\{(\\[\\([{])", | ||
"/\\]", | ||
"/\\}", | ||
"/\\)", | ||
"/[\\]]", | ||
"/(\\])", | ||
"/{\\]}", | ||
"/[\\)]", | ||
"/(\\))", | ||
"/{\\)}", | ||
"/[\\}]", | ||
"/(\\})", | ||
"/{\\}}", | ||
"/({[\\]})]})", | ||
]; | ||
const whiteSpaceSequences = [ | ||
"", | ||
" ", | ||
"\t\v\r\n", | ||
"\u3000\u2028", | ||
]; | ||
it("stops parsing unterminated regexes at correct position", () => { | ||
graphemecluster marked this conversation as resolved.
Show resolved
Hide resolved
|
||
ts.forEach(testCases, testCase => { | ||
ts.forEach(whiteSpaceSequences, whiteSpaces => { | ||
const testCaseWithWhiteSpaces = testCase + whiteSpaces; | ||
const sources = [ | ||
`const regex = ${testCaseWithWhiteSpaces};`, | ||
`(${testCaseWithWhiteSpaces});`, | ||
`([${testCaseWithWhiteSpaces}]);`, | ||
`({prop: ${testCaseWithWhiteSpaces}});`, | ||
`({prop: ([(${testCaseWithWhiteSpaces})])});`, | ||
`({[(${testCaseWithWhiteSpaces}).source]: 42});`, | ||
]; | ||
ts.forEach(sources, source => { | ||
const { parseDiagnostics } = ts.createLanguageServiceSourceFile( | ||
/*fileName*/ "", | ||
ts.ScriptSnapshot.fromString(source), | ||
ts.ScriptTarget.Latest, | ||
/*version*/ "0", | ||
/*setNodeParents*/ false, | ||
); | ||
const diagnostic = ts.find(parseDiagnostics, ({ code }) => code === ts.Diagnostics.Unterminated_regular_expression_literal.code); | ||
assert(diagnostic, "There should be an 'Unterminated regular expression literal.' error"); | ||
assert.equal(diagnostic.start, source.indexOf("/"), "Diagnostic should start at where the regex starts"); | ||
assert.equal(diagnostic.length, testCase.length, "Diagnostic should end at where the regex ends"); | ||
}); | ||
}); | ||
}); | ||
}); | ||
}); |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,10 @@ | ||
parser645086_1.ts(1,13): error TS1005: ',' expected. | ||
parser645086_1.ts(1,14): error TS1134: Variable declaration expected. | ||
parser645086_1.ts(1,15): error TS1161: Unterminated regular expression literal. | ||
|
||
|
||
==== parser645086_1.ts (3 errors) ==== | ||
==== parser645086_1.ts (2 errors) ==== | ||
var v = /[]/]/ | ||
~ | ||
!!! error TS1005: ',' expected. | ||
~ | ||
!!! error TS1134: Variable declaration expected. | ||
|
||
!!! error TS1161: Unterminated regular expression literal. | ||
!!! error TS1134: Variable declaration expected. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,13 +1,10 @@ | ||
parser645086_2.ts(1,14): error TS1005: ',' expected. | ||
parser645086_2.ts(1,15): error TS1134: Variable declaration expected. | ||
parser645086_2.ts(1,16): error TS1161: Unterminated regular expression literal. | ||
|
||
|
||
==== parser645086_2.ts (3 errors) ==== | ||
==== parser645086_2.ts (2 errors) ==== | ||
var v = /[^]/]/ | ||
~ | ||
!!! error TS1005: ',' expected. | ||
~ | ||
!!! error TS1134: Variable declaration expected. | ||
|
||
!!! error TS1161: Unterminated regular expression literal. | ||
!!! error TS1134: Variable declaration expected. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
parserMissingToken2.ts(1,2): error TS1161: Unterminated regular expression literal. | ||
parserMissingToken2.ts(1,1): error TS1161: Unterminated regular expression literal. | ||
|
||
|
||
==== parserMissingToken2.ts (1 errors) ==== | ||
/ b; | ||
~~~ | ||
!!! error TS1161: Unterminated regular expression literal. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -4,4 +4,4 @@ | |
/ b; | ||
|
||
//// [parserMissingToken2.js] | ||
/ b;; | ||
/ b; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,6 @@ | |
|
||
=== parserMissingToken2.ts === | ||
/ b; | ||
>/ b; : RegExp | ||
> : ^^^^^^ | ||
>/ b : RegExp | ||
> : ^^^^^^ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,10 +1,10 @@ | ||
parserRegularExpressionDivideAmbiguity4.ts(1,1): error TS2304: Cannot find name 'foo'. | ||
parserRegularExpressionDivideAmbiguity4.ts(1,6): error TS1161: Unterminated regular expression literal. | ||
parserRegularExpressionDivideAmbiguity4.ts(1,5): error TS1161: Unterminated regular expression literal. | ||
|
||
|
||
==== parserRegularExpressionDivideAmbiguity4.ts (2 errors) ==== | ||
foo(/notregexp); | ||
~~~ | ||
!!! error TS2304: Cannot find name 'foo'. | ||
~~~~~~~~~~ | ||
!!! error TS1161: Unterminated regular expression literal. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -10,7 +10,7 @@ file.tsx(11,1): error TS2362: The left-hand side of an arithmetic operation must | |
file.tsx(11,8): error TS1003: Identifier expected. | ||
file.tsx(11,9): error TS2304: Cannot find name 'data'. | ||
file.tsx(11,13): error TS1005: ';' expected. | ||
file.tsx(11,20): error TS1161: Unterminated regular expression literal. | ||
file.tsx(11,19): error TS1161: Unterminated regular expression literal. | ||
|
||
|
||
==== file.tsx (13 errors) ==== | ||
|
@@ -49,5 +49,5 @@ file.tsx(11,20): error TS1161: Unterminated regular expression literal. | |
!!! error TS2304: Cannot find name 'data'. | ||
~ | ||
!!! error TS1005: ';' expected. | ||
~~ | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Should we include angle brackets (in addition to parens and braces) to the logic? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. With respect to treating them as unterminated? I don't think that's necessary. Also, Annex B does not treat There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I'm not too terribly concerned about this case, to be honest. Parsing falls off the rails here because of malformed JSX, not a malformed RegExp. |
||
!!! error TS1161: Unterminated regular expression literal. |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -22,4 +22,4 @@ data = { 32: } / > ; | |
{ | ||
32; | ||
} | ||
/>;; | ||
/>; |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -56,6 +56,6 @@ declare module JSX { | |
> : ^^^ | ||
>32 : 32 | ||
> : ^^ | ||
>/>; : RegExp | ||
> : ^^^^^^ | ||
>/> : RegExp | ||
> : ^^^^^^ | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,7 @@ | ||
unterminatedRegexAtEndOfSource1.ts(1,10): error TS1161: Unterminated regular expression literal. | ||
unterminatedRegexAtEndOfSource1.ts(1,9): error TS1161: Unterminated regular expression literal. | ||
|
||
|
||
==== unterminatedRegexAtEndOfSource1.ts (1 errors) ==== | ||
var a = / | ||
~ | ||
!!! error TS1161: Unterminated regular expression literal. |
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I know this is bad. Are there any solutions that does not affect pressing enter? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is eliminated for readability