feat(es/parser): Allow parsing files with missing close braces (#4187)

This commit is contained in:
David Sherret 2022-03-30 16:31:24 -04:00 committed by GitHub
parent b67c104877
commit cffe5ca58e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 134 additions and 13 deletions

View File

@ -157,7 +157,16 @@ impl<'a, I: Tokens> Parser<I> {
..p.ctx()
})
.parse_class_body()?;
expect!(p, '}');
if p.input.cur().is_none() {
let eof_text = p.input.dump_cur();
p.emit_err(
p.input.cur_span(),
SyntaxError::Expected(&Token::RBrace, eof_text),
);
} else {
expect!(p, '}');
}
let end = last_pos!(p);
Ok((

View File

@ -16,7 +16,7 @@ impl<'a, I: Tokens> Parser<I> {
&mut self,
mut allow_directives: bool,
top_level: bool,
end: Option<&Token>,
end: Option<&'static Token>,
) -> PResult<Vec<Type>>
where
Self: StmtLikeParser<'a, Type>,
@ -28,8 +28,17 @@ impl<'a, I: Tokens> Parser<I> {
let stmts = Arena::new();
while {
let c = cur!(self, false).ok();
c != end
if self.input.cur().is_none() && end.is_some() {
let eof_text = self.input.dump_cur();
self.emit_err(
self.input.cur_span(),
SyntaxError::Expected(end.unwrap(), eof_text),
);
false
} else {
let c = cur!(self, false).ok();
c != end
}
} {
let stmt = self.parse_stmt_like(true, top_level)?;
if allow_directives {
@ -54,7 +63,7 @@ impl<'a, I: Tokens> Parser<I> {
stmts.alloc(stmt);
}
if end.is_some() {
if self.input.cur().is_some() && end.is_some() {
bump!(self);
}

View File

@ -0,0 +1,3 @@
class Test {
method() {}

View File

@ -0,0 +1,84 @@
x Module
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:1:1]
1 | ,-> class Test {
2 | |
3 | `-> method() {}
`----
x ModuleItem
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:1:1]
1 | ,-> class Test {
2 | |
3 | `-> method() {}
`----
x Stmt
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:1:1]
1 | ,-> class Test {
2 | |
3 | `-> method() {}
`----
x Decl
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:1:1]
1 | ,-> class Test {
2 | |
3 | `-> method() {}
`----
x ClassDecl
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:1:1]
1 | ,-> class Test {
2 | |
3 | `-> method() {}
`----
x Ident
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:1:1]
1 | class Test {
: ^^^^
`----
x Class
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:1:1]
1 | ,-> class Test {
2 | |
3 | `-> method() {}
`----
x ClassMember
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:3:3]
3 | method() {}
: ^^^^^^^^^^^
`----
x ClassMethod
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:3:3]
3 | method() {}
: ^^^^^^^^^^^
`----
x PropName
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:3:3]
3 | method() {}
: ^^^^^^
`----
x Ident
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:3:3]
3 | method() {}
: ^^^^^^
`----
x Function
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:3:3]
3 | method() {}
: ^^^^^^^^^^^
`----
x BlockStmt
,-[$DIR/tests/span/js/decl/class-no-close-brace.js:3:3]
3 | method() {}
: ^^
`----

View File

@ -1,6 +1,6 @@
x Unexpected eof
x Expected '}', got '<eof>'
,-[$DIR/tests/test262-parser/fail/021fb596db81e6d0.js:1:1]
1 | {
: ^
: ^
`----

View File

@ -1,6 +1,6 @@
x Unexpected eof
x Expected '}', got '<eof>'
,-[$DIR/tests/test262-parser/fail/4d579849c75cfef9.js:4:1]
4 | {
: ^
: ^
`----

View File

@ -1,6 +1,6 @@
x Unexpected eof
x Expected '}', got '<eof>'
,-[$DIR/tests/test262-parser/fail/50efa1f220e37136.js:1:1]
1 | { ; ;
: ^
: ^
`----

View File

@ -1,6 +1,6 @@
x Unexpected eof
x Expected '}', got '<eof>'
,-[$DIR/tests/test262-parser/fail/77fe5a8d6ae33dd1.js:1:1]
1 | function t() { ; ;
: ^
: ^
`----

View File

@ -0,0 +1,2 @@
const t = () => {
console.log(5);

View File

@ -0,0 +1,6 @@
x Expected '}', got '<eof>'
,-[$DIR/tests/typescript-errors/arrow-function/missing-closing-brace/input.ts:2:3]
2 | console.log(5);
: ^
`----

View File

@ -0,0 +1,2 @@
class Class {
prop: string;

View File

@ -0,0 +1,6 @@
x Expected '}', got '<eof>'
,-[$DIR/tests/typescript-errors/class/missing-closing-brace/input.ts:2:3]
2 | prop: string;
: ^
`----