From a1d33d023ac7bf019b010c071ae5fdb974eb0926 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=EA=B0=95=EB=8F=99=EC=9C=A4?= Date: Sat, 25 Jul 2020 20:26:04 +0900 Subject: [PATCH] Improve ux using swc as a rust library (#893) swc_ecma_parser: - Improve parser's error reporting story - Replace `Session`, `Handler`, `Emitter` with Parser.take_errors() - Expose `Error` - Remove useless lifetime parameters --- .travis.yml | 2 +- CONTRIBUTING.md | 1 - ecmascript/codegen/Cargo.toml | 4 +- ecmascript/codegen/benches/bench.rs | 20 +- ecmascript/codegen/benches/with_parse.rs | 19 +- ecmascript/codegen/src/tests.rs | 21 +- ecmascript/codegen/tests/test262.rs | 22 +- ecmascript/parser/Cargo.toml | 2 +- ecmascript/parser/benches/lexer.rs | 6 +- ecmascript/parser/benches/parser.rs | 8 +- ecmascript/parser/examples/lexer.rs | 15 +- ecmascript/parser/examples/typescript.rs | 15 +- ecmascript/parser/src/error.rs | 66 ++--- ecmascript/parser/src/lexer/mod.rs | 10 +- ecmascript/parser/src/lexer/number.rs | 8 +- ecmascript/parser/src/lexer/state.rs | 16 +- ecmascript/parser/src/lexer/tests.rs | 6 +- ecmascript/parser/src/lexer/util.rs | 18 +- ecmascript/parser/src/lib.rs | 35 ++- ecmascript/parser/src/parser/class_and_fn.rs | 88 +++---- ecmascript/parser/src/parser/expr.rs | 68 +++-- ecmascript/parser/src/parser/expr/ops.rs | 34 +-- ecmascript/parser/src/parser/expr/tests.rs | 42 +--- ecmascript/parser/src/parser/expr/verifier.rs | 4 +- ecmascript/parser/src/parser/ident.rs | 26 +- ecmascript/parser/src/parser/input.rs | 33 ++- ecmascript/parser/src/parser/jsx.rs | 33 ++- ecmascript/parser/src/parser/jsx/tests.rs | 6 +- ecmascript/parser/src/parser/macros.rs | 40 ++- ecmascript/parser/src/parser/mod.rs | 103 ++++---- ecmascript/parser/src/parser/object.rs | 20 +- ecmascript/parser/src/parser/pat.rs | 44 ++-- ecmascript/parser/src/parser/stmt.rs | 237 +++++------------- .../parser/src/parser/stmt/module_item.rs | 22 +- ecmascript/parser/src/parser/typescript.rs | 227 ++++++++--------- ecmascript/parser/src/parser/util.rs | 54 ++-- ecmascript/parser/tests/common/mod.rs | 51 +++- ecmascript/parser/tests/jsx.rs | 18 +- .../input.js.stderr | 12 +- .../fail/1aefe47e20eb91fa.module.js.stderr | 12 +- .../fail/2d1410e37ecc3647.js.stderr | 12 +- .../fail/37cb7557997d4fd6.js.stderr | 12 +- .../fail/37e9fb0470e7ec3d.js.stderr | 12 +- .../fail/48dee14b7a3a3767.module.js.stderr | 6 - .../fail/58707e130fe451a8.js.stderr | 12 +- .../fail/6ac4f95d48362a35.js.stderr | 12 +- .../fail/7562c2148b3f455c.js.stderr | 12 +- .../fail/85ee036d67974729.js.stderr | 12 +- .../fail/983987033f0e1170.js.stderr | 12 +- .../fail/a7be138dfd29025e.js.stderr | 12 +- .../fail/c45a4b00a2a24c2b.js.stderr | 12 +- .../fail/c91a41d48af2ef00.js.stderr | 6 - .../fail/ca3dd7ea0b4626dd.js.stderr | 12 +- .../fail/d17d3aebb6a3cf43.js.stderr | 12 +- .../fail/e3a388ec11e4d061.js.stderr | 12 +- .../fail/e4963d9605864d9a.js.stderr | 12 +- .../fail/f0ff9ff5dab859aa.js.stderr | 12 +- .../fail/fe233d87f280ed04.js.stderr | 12 +- ecmascript/parser/tests/test262.rs | 30 ++- .../typescript-errors/class/input.ts.stderr | 12 +- ecmascript/parser/tests/typescript.rs | 31 ++- ecmascript/preset_env/benches/polyfills.rs | 18 +- ecmascript/preset_env/tests/test.rs | 21 +- ecmascript/transforms/Cargo.toml | 8 +- ecmascript/transforms/benches/base.rs | 73 +++--- ecmascript/transforms/benches/basic.rs | 19 +- ecmascript/transforms/benches/compat.rs | 15 +- ecmascript/transforms/src/const_modules.rs | 15 +- ecmascript/transforms/src/helpers.rs | 13 +- ecmascript/transforms/src/hygiene/tests.rs | 4 +- .../transforms/src/modules/umd/config.rs | 21 +- ecmascript/transforms/src/react/jsx.rs | 37 ++- ecmascript/transforms/src/tests.rs | 49 ++-- ecmascript/transforms/tests/common/mod.rs | 43 ++-- ecmascript/transforms/tests/fixer_test262.rs | 40 ++- ecmascript/utils/Cargo.toml | 4 +- ecmascript/utils/src/lib.rs | 1 + ecmascript/utils/src/options.rs | 12 +- spack/src/bundler/helpers/mod.rs | 11 +- src/config.rs | 18 +- src/lib.rs | 44 ++-- tests/serde.rs | 15 +- 82 files changed, 997 insertions(+), 1229 deletions(-) diff --git a/.travis.yml b/.travis.yml index 09e83d9882c..3beb8c144b3 100644 --- a/.travis.yml +++ b/.travis.yml @@ -37,7 +37,7 @@ install: - npm install - npm install browserslist regenerator - npm install -g jest - - RUST_BACKTRACE=0 cargo test --no-run --color always --all --all-features + - travis_wait 50 RUST_BACKTRACE=0 cargo test --no-run --color always --all --all-features script: # - RUST_BACKTRACE=0 cargo check --color always --all --all-targets diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 4b01b6f438c..1b78300c97b 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -95,7 +95,6 @@ After cloning the project there are a few steps required to get the project runn 3. Setup some environment variables which is required for tests. ```bash - export RUST_MIN_STACK=16777216 export RUSTFLAGS='--cfg procmacro2_semver_exempt' export RUST_BACKTRACE=full export PATH="$PATH:$PWD/ecmascript/transforms/node_modules/.bin" diff --git a/ecmascript/codegen/Cargo.toml b/ecmascript/codegen/Cargo.toml index 5343701cde8..f422125b3db 100644 --- a/ecmascript/codegen/Cargo.toml +++ b/ecmascript/codegen/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swc_ecma_codegen" -version = "0.26.0" +version = "0.27.0" authors = ["강동윤 "] license = "Apache-2.0/MIT" repository = "https://github.com/swc-project/swc.git" @@ -19,5 +19,5 @@ sourcemap = "6" num-bigint = { version = "0.2", features = ["serde"] } [dev-dependencies] -swc_ecma_parser = { version = "0.28", path ="../parser" } +swc_ecma_parser = { version = "0.29", path ="../parser" } testing = { version = "0.7", path ="../../testing" } diff --git a/ecmascript/codegen/benches/bench.rs b/ecmascript/codegen/benches/bench.rs index 9f483c827f2..7247b9c2f68 100644 --- a/ecmascript/codegen/benches/bench.rs +++ b/ecmascript/codegen/benches/bench.rs @@ -5,7 +5,7 @@ extern crate test; use std::hint::black_box; use swc_common::FileName; use swc_ecma_codegen::{self, Emitter}; -use swc_ecma_parser::{Parser, Session, SourceFileInput, Syntax}; +use swc_ecma_parser::{Parser, SourceFileInput, Syntax}; use test::Bencher; const COLORS_JS: &str = r#" @@ -86,23 +86,19 @@ fn bench_emitter(b: &mut Bencher, s: &str) { b.bytes = s.len() as _; let _ = ::testing::run_test(true, |cm, handler| { - let session = Session { handler: &handler }; - let fm = cm.new_source_file(FileName::Anon, s.into()); - let mut parser = Parser::new( - session, - Syntax::default(), - SourceFileInput::from(&*fm), - None, - ); + let mut parser = Parser::new(Syntax::default(), SourceFileInput::from(&*fm), None); + let mut src_map_buf = vec![]; let module = parser .parse_module() - .map_err(|mut e| { - e.emit(); - }) + .map_err(|e| e.into_diagnostic(handler).emit()) .unwrap(); + for err in parser.take_errors() { + err.into_diagnostic(handler).emit(); + } + b.iter(|| { let mut buf = vec![]; { diff --git a/ecmascript/codegen/benches/with_parse.rs b/ecmascript/codegen/benches/with_parse.rs index d7e55c0fe28..0305b32244e 100644 --- a/ecmascript/codegen/benches/with_parse.rs +++ b/ecmascript/codegen/benches/with_parse.rs @@ -5,7 +5,7 @@ extern crate test; use std::hint::black_box; use swc_common::FileName; use swc_ecma_codegen::{self, Emitter}; -use swc_ecma_parser::{Parser, Session, SourceFileInput, Syntax}; +use swc_ecma_parser::{Parser, SourceFileInput, Syntax}; use test::Bencher; const COLORS_JS: &str = r#" @@ -86,24 +86,19 @@ fn bench_emitter(b: &mut Bencher, s: &str) { b.bytes = s.len() as _; let _ = ::testing::run_test(true, |cm, handler| { - let session = Session { handler: &handler }; - b.iter(|| { let fm = cm.new_source_file(FileName::Anon, s.into()); - let mut parser = Parser::new( - session, - Syntax::default(), - SourceFileInput::from(&*fm), - None, - ); + let mut parser = Parser::new(Syntax::default(), SourceFileInput::from(&*fm), None); let mut src_map_buf = vec![]; let module = parser .parse_module() - .map_err(|mut e| { - e.emit(); - }) + .map_err(|e| e.into_diagnostic(handler).emit()) .unwrap(); + for err in parser.take_errors() { + err.into_diagnostic(handler).emit(); + } + let mut buf = vec![]; { let handlers = Box::new(MyHandlers); diff --git a/ecmascript/codegen/src/tests.rs b/ecmascript/codegen/src/tests.rs index adcc64866eb..6fd170686c2 100644 --- a/ecmascript/codegen/src/tests.rs +++ b/ecmascript/codegen/src/tests.rs @@ -1,4 +1,4 @@ -use self::swc_ecma_parser::{EsConfig, Parser, Session, SourceFileInput, Syntax}; +use self::swc_ecma_parser::{EsConfig, Parser, SourceFileInput, Syntax}; use super::*; use crate::config::Config; use std::{ @@ -58,15 +58,16 @@ fn parse_then_emit(from: &str, cfg: Config, syntax: Syntax) -> String { let comments = Default::default(); let res = { - let mut parser = Parser::new( - Session { handler: &handler }, - syntax, - SourceFileInput::from(&*src), - Some(&comments), - ); - parser.parse_module().map_err(|mut e| { - e.emit(); - })? + let mut parser = Parser::new(syntax, SourceFileInput::from(&*src), Some(&comments)); + let res = parser + .parse_module() + .map_err(|e| e.into_diagnostic(handler).emit()); + + for err in parser.take_errors() { + err.into_diagnostic(handler).emit() + } + + res? }; let out = Builder { cfg, cm, comments }.text(from, |e| e.emit_module(&res).unwrap()); diff --git a/ecmascript/codegen/tests/test262.rs b/ecmascript/codegen/tests/test262.rs index d27c5412a25..e3a79b051f0 100644 --- a/ecmascript/codegen/tests/test262.rs +++ b/ecmascript/codegen/tests/test262.rs @@ -11,7 +11,7 @@ use std::{ }; use swc_common::comments::Comments; use swc_ecma_codegen::{self, Emitter}; -use swc_ecma_parser::{lexer::Lexer, Parser, Session, SourceFileInput, Syntax}; +use swc_ecma_parser::{lexer::Lexer, Parser, SourceFileInput, Syntax}; use test::{ test_main, DynTestFn, Options, ShouldPanic::No, TestDesc, TestDescAndFn, TestName, TestType, }; @@ -150,14 +150,12 @@ fn error_tests(tests: &mut Vec) -> Result<(), io::Error> { let comments = Comments::default(); let handlers = Box::new(MyHandlers); let lexer = Lexer::new( - Session { handler: &handler }, Syntax::default(), Default::default(), (&*src).into(), Some(&comments), ); - let mut parser: Parser<'_, Lexer<'_, SourceFileInput<'_>>> = - Parser::new_from(Session { handler: &handler }, lexer); + let mut parser: Parser> = Parser::new_from(lexer); { let mut emitter = Emitter { @@ -173,15 +171,19 @@ fn error_tests(tests: &mut Vec) -> Result<(), io::Error> { // Parse source if module { emitter - .emit_module(&parser.parse_module().map_err(|mut e| { - e.emit(); - })?) + .emit_module( + &parser + .parse_module() + .map_err(|e| e.into_diagnostic(handler).emit())?, + ) .unwrap(); } else { emitter - .emit_script(&parser.parse_script().map_err(|mut e| { - e.emit(); - })?) + .emit_script( + &parser + .parse_script() + .map_err(|e| e.into_diagnostic(handler).emit())?, + ) .unwrap(); } } diff --git a/ecmascript/parser/Cargo.toml b/ecmascript/parser/Cargo.toml index 9bbe9843ef7..7501bbb5dbb 100644 --- a/ecmascript/parser/Cargo.toml +++ b/ecmascript/parser/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "swc_ecma_parser" -version = "0.28.0" +version = "0.29.0" authors = ["강동윤 "] license = "Apache-2.0/MIT" repository = "https://github.com/swc-project/swc.git" diff --git a/ecmascript/parser/benches/lexer.rs b/ecmascript/parser/benches/lexer.rs index 90a26ca68b4..37e49fa15da 100644 --- a/ecmascript/parser/benches/lexer.rs +++ b/ecmascript/parser/benches/lexer.rs @@ -4,7 +4,7 @@ extern crate test; use std::hint::black_box; use swc_common::FileName; -use swc_ecma_parser::{lexer::Lexer, Session, SourceFileInput, Syntax}; +use swc_ecma_parser::{lexer::Lexer, SourceFileInput, Syntax}; use test::Bencher; #[bench] @@ -75,13 +75,11 @@ fn yui(b: &mut Bencher) { fn bench_module(b: &mut Bencher, syntax: Syntax, src: &'static str) { b.bytes = src.len() as _; - let _ = ::testing::run_test(false, |cm, handler| { - let session = Session { handler: &handler }; + let _ = ::testing::run_test(false, |cm, _| { let fm = cm.new_source_file(FileName::Anon, src.into()); b.iter(|| { let lexer = Lexer::new( - session, syntax, Default::default(), SourceFileInput::from(&*fm), diff --git a/ecmascript/parser/benches/parser.rs b/ecmascript/parser/benches/parser.rs index 9f7a24711d1..65e534acd77 100644 --- a/ecmascript/parser/benches/parser.rs +++ b/ecmascript/parser/benches/parser.rs @@ -3,7 +3,7 @@ extern crate test; use swc_common::FileName; -use swc_ecma_parser::{lexer::Lexer, Parser, Session, SourceFileInput, Syntax}; +use swc_ecma_parser::{lexer::Lexer, Parser, SourceFileInput, Syntax}; use test::Bencher; #[bench] @@ -156,20 +156,18 @@ fn large(b: &mut Bencher) { fn bench_module(b: &mut Bencher, syntax: Syntax, src: &'static str) { b.bytes = src.len() as _; - let _ = ::testing::run_test(false, |cm, handler| { - let session = Session { handler: &handler }; + let _ = ::testing::run_test(false, |cm, _| { let fm = cm.new_source_file(FileName::Anon, src.into()); b.iter(|| { let _ = test::black_box({ let lexer = Lexer::new( - session, syntax, Default::default(), SourceFileInput::from(&*fm), None, ); - let mut parser = Parser::new_from(session, lexer); + let mut parser = Parser::new_from(lexer); parser.parse_module() }); }); diff --git a/ecmascript/parser/examples/lexer.rs b/ecmascript/parser/examples/lexer.rs index c999b95b671..fb98aebf8f9 100644 --- a/ecmascript/parser/examples/lexer.rs +++ b/ecmascript/parser/examples/lexer.rs @@ -4,15 +4,13 @@ use swc_common::{ errors::{ColorConfig, Handler}, FileName, SourceMap, }; -use swc_ecma_parser::{lexer::Lexer, Capturing, Parser, Session, SourceFileInput, Syntax}; +use swc_ecma_parser::{lexer::Lexer, Capturing, Parser, SourceFileInput, Syntax}; fn main() { swc_common::GLOBALS.set(&swc_common::Globals::new(), || { let cm: Arc = Default::default(); let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(cm.clone())); - let session = Session { handler: &handler }; - // Real usage // let fm = cm // .load_file(Path::new("test.js")) @@ -24,7 +22,6 @@ fn main() { ); let lexer = Lexer::new( - session, Syntax::Es(Default::default()), Default::default(), SourceFileInput::from(&*fm), @@ -33,13 +30,15 @@ fn main() { let capturing = Capturing::new(lexer); - let mut parser = Parser::new_from(session, capturing); + let mut parser = Parser::new_from(capturing); + + for e in parser.take_errors() { + e.into_diagnostic(&handler).emit(); + } let _module = parser .parse_module() - .map_err(|mut e| { - e.emit(); - }) + .map_err(|e| e.into_diagnostic(&handler).emit()) .expect("Failed to parse module."); println!("Tokens: {:?}", parser.input().take()); diff --git a/ecmascript/parser/examples/typescript.rs b/ecmascript/parser/examples/typescript.rs index 05efd6dff06..4c7597ddebe 100644 --- a/ecmascript/parser/examples/typescript.rs +++ b/ecmascript/parser/examples/typescript.rs @@ -5,15 +5,13 @@ use swc_common::{ errors::{ColorConfig, Handler}, FileName, SourceMap, }; -use swc_ecma_parser::{lexer::Lexer, Capturing, Parser, Session, SourceFileInput, Syntax}; +use swc_ecma_parser::{lexer::Lexer, Capturing, Parser, SourceFileInput, Syntax}; fn main() { swc_common::GLOBALS.set(&swc_common::Globals::new(), || { let cm: Arc = Default::default(); let handler = Handler::with_tty_emitter(ColorConfig::Auto, true, false, Some(cm.clone())); - let session = Session { handler: &handler }; - // Real usage // let fm = cm // .load_file(Path::new("test.js")) @@ -25,7 +23,6 @@ fn main() { ); let lexer = Lexer::new( - session, Syntax::Typescript(Default::default()), Default::default(), SourceFileInput::from(&*fm), @@ -34,13 +31,15 @@ fn main() { let capturing = Capturing::new(lexer); - let mut parser = Parser::new_from(session, capturing); + let mut parser = Parser::new_from(capturing); + + for e in parser.take_errors() { + e.into_diagnostic(&handler).emit(); + } let _module = parser .parse_typescript_module() - .map_err(|mut e| { - e.emit(); - }) + .map_err(|e| e.into_diagnostic(&handler).emit()) .expect("Failed to parse module."); println!("Tokens: {:?}", parser.input().take()); diff --git a/ecmascript/parser/src/error.rs b/ecmascript/parser/src/error.rs index 63e495e7632..ac915439734 100644 --- a/ecmascript/parser/src/error.rs +++ b/ecmascript/parser/src/error.rs @@ -2,50 +2,23 @@ use self::SyntaxError::*; use crate::token::Token; -use std::{ - borrow::Cow, - fmt::{self, Debug, Formatter}, -}; +use std::{borrow::Cow, fmt::Debug}; use swc_atoms::JsWord; use swc_common::{ errors::{DiagnosticBuilder, Handler}, Span, }; -#[derive(Copy, Clone)] -pub(crate) struct Eof<'a> { - pub last: Span, - pub handler: &'a Handler, -} - -impl<'a> From> for DiagnosticBuilder<'a> { - fn from(Eof { handler, last }: Eof<'a>) -> Self { - let mut db = handler.struct_err("Unexpected eof"); - db.set_span(last); - db - } -} - -impl<'a> Debug for Eof<'a> { - fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { - Debug::fmt("", f) - } -} - -pub(crate) struct ErrorToDiag<'a> { - pub handler: &'a Handler, - pub span: Span, - pub error: SyntaxError, -} - #[derive(Debug, Clone, PartialEq)] pub struct Error { pub span: Span, - pub error: SyntaxError, + pub error: Box, } #[derive(Debug, Clone, PartialEq)] +#[non_exhaustive] pub enum SyntaxError { + Eof, TopLevelAwait, LegacyDecimal, @@ -217,20 +190,10 @@ pub enum SyntaxError { TS2703, } -impl<'a> From> for Error { +impl Error { #[cold] - fn from(e: ErrorToDiag<'a>) -> Self { - Error { - span: e.span, - error: e.error, - } - } -} - -impl<'a> From> for DiagnosticBuilder<'a> { - #[cold] - fn from(e: ErrorToDiag<'a>) -> Self { - let msg: Cow<'static, _> = match e.error { + pub fn into_diagnostic(self, handler: &Handler) -> DiagnosticBuilder { + let msg: Cow<'static, _> = match *self.error { TopLevelAwait => "top level await requires target to es2017 or higher and \ topLevelAwait:true for ecmascript" .into(), @@ -380,14 +343,16 @@ impl<'a> From> for DiagnosticBuilder<'a> { TS1110 => "type expected".into(), TS1141 => "literal in an import type should be string literal".into(), + Eof => "Unexpected eof".into(), + // TODO: - _ => format!("{:?}", e.error).into(), + _ => format!("{:?}", self.error).into(), }; - let mut db = e.handler.struct_err(&msg); - db.set_span(e.span); + let mut db = handler.struct_err(&msg); + db.set_span(self.span); - match e.error { + match *self.error { ExpectedSemiForExprStmt { expr } => { db.span_note( expr, @@ -403,3 +368,8 @@ impl<'a> From> for DiagnosticBuilder<'a> { db } } + +#[test] +fn size_of_error() { + assert_eq!(std::mem::size_of::(), 16); +} diff --git a/ecmascript/parser/src/lexer/mod.rs b/ecmascript/parser/src/lexer/mod.rs index 661d2f0e118..f019a5eecaf 100644 --- a/ecmascript/parser/src/lexer/mod.rs +++ b/ecmascript/parser/src/lexer/mod.rs @@ -12,11 +12,11 @@ use self::{state::State, util::*}; use crate::{ error::{Error, SyntaxError}, token::*, - Context, JscTarget, Session, Syntax, + Context, JscTarget, Syntax, }; use either::Either::{Left, Right}; use smallvec::{smallvec, SmallVec}; -use std::{char, iter::FusedIterator, mem::take}; +use std::{cell::RefCell, char, iter::FusedIterator, mem::take, rc::Rc}; use swc_atoms::{js_word, JsWord}; use swc_common::{ comments::{Comment, Comments}, @@ -95,7 +95,6 @@ impl FusedIterator for CharIter {} #[derive(Clone)] pub struct Lexer<'a, I: Input> { - session: Session<'a>, comments: Option<&'a Comments>, leading_comments_buffer: Option>, pub(crate) ctx: Context, @@ -104,6 +103,8 @@ pub struct Lexer<'a, I: Input> { pub(crate) syntax: Syntax, pub(crate) target: JscTarget, + errors: Rc>>, + buf: String, } @@ -111,14 +112,12 @@ impl FusedIterator for Lexer<'_, I> {} impl<'a, I: Input> Lexer<'a, I> { pub fn new( - session: Session<'a>, syntax: Syntax, target: JscTarget, input: I, comments: Option<&'a Comments>, ) -> Self { Lexer { - session, leading_comments_buffer: if comments.is_some() { Some(Default::default()) } else { @@ -130,6 +129,7 @@ impl<'a, I: Input> Lexer<'a, I> { ctx: Default::default(), syntax, target, + errors: Default::default(), buf: String::with_capacity(16), } } diff --git a/ecmascript/parser/src/lexer/number.rs b/ecmascript/parser/src/lexer/number.rs index 404777f59f2..2090fab4661 100644 --- a/ecmascript/parser/src/lexer/number.rs +++ b/ecmascript/parser/src/lexer/number.rs @@ -444,9 +444,8 @@ mod tests { where F: FnOnce(&mut Lexer<'_, SourceFileInput<'_>>) -> Ret, { - crate::with_test_sess(s, |sess, fm| { + crate::with_test_sess(s, |handler, fm| { let mut l = Lexer::new( - sess, Syntax::Es(EsConfig { num_sep: true, ..Default::default() @@ -576,9 +575,8 @@ mod tests { }); let vec = panic::catch_unwind(|| { - crate::with_test_sess(case, |mut sess, input| { - let mut l = - Lexer::new(sess, Syntax::default(), Default::default(), input, None); + crate::with_test_sess(case, |handler, input| { + let mut l = Lexer::new(Syntax::default(), Default::default(), input, None); l.ctx.strict = strict; Ok(l.map(|ts| ts.token).collect::>()) }) diff --git a/ecmascript/parser/src/lexer/state.rs b/ecmascript/parser/src/lexer/state.rs index dab8a40e9c7..e5f36a81c8b 100644 --- a/ecmascript/parser/src/lexer/state.rs +++ b/ecmascript/parser/src/lexer/state.rs @@ -1,8 +1,8 @@ use super::{Context, Input, Lexer}; -use crate::{input::Tokens, lexer::util::CharExt, token::*, JscTarget, Syntax}; +use crate::{error::Error, input::Tokens, lexer::util::CharExt, token::*, JscTarget, Syntax}; use enum_kind::Kind; use log::trace; -use std::mem; +use std::{mem, mem::take}; use swc_common::BytePos; /// State of lexer. @@ -129,6 +129,14 @@ impl Tokens for Lexer<'_, I> { fn set_token_context(&mut self, c: TokenContexts) { self.state.context = c; } + + fn add_error(&self, error: Error) { + self.errors.borrow_mut().push(error); + } + + fn take_errors(&mut self) -> Vec { + take(&mut self.errors.borrow_mut()) + } } impl<'a, I: Input> Iterator for Lexer<'a, I> { @@ -613,8 +621,8 @@ pub(crate) fn with_lexer( where F: FnOnce(&mut Lexer<'_, crate::lexer::input::SourceFileInput<'_>>) -> Result, { - crate::with_test_sess(s, |sess, fm| { - let mut l = Lexer::new(sess, syntax, Default::default(), fm, None); + crate::with_test_sess(s, |handler, fm| { + let mut l = Lexer::new(syntax, Default::default(), fm, None); let res = f(&mut l); let c = vec![TokenContext::BraceStmt]; diff --git a/ecmascript/parser/src/lexer/tests.rs b/ecmascript/parser/src/lexer/tests.rs index 4276b827906..29d2e7d0d00 100644 --- a/ecmascript/parser/src/lexer/tests.rs +++ b/ecmascript/parser/src/lexer/tests.rs @@ -130,7 +130,7 @@ fn module_legacy_decimal() { lex_module(Syntax::default(), "08"), vec![Token::Error(Error { span: make_span(sp(0..2)), - error: SyntaxError::LegacyDecimal, + error: Box::new(SyntaxError::LegacyDecimal), }) .span(0..2) .lb(),] @@ -143,7 +143,7 @@ fn module_legacy_comment_1() { lex_module(Syntax::default(), ""), vec![Token::Error(Error { span: make_span(sp(0..3)), - error: SyntaxError::LegacyCommentInModule, + error: Box::new(SyntaxError::LegacyCommentInModule), }) .span(0..3) .lb(),] diff --git a/ecmascript/parser/src/lexer/util.rs b/ecmascript/parser/src/lexer/util.rs index de026dce15b..577f0ffcdf0 100644 --- a/ecmascript/parser/src/lexer/util.rs +++ b/ecmascript/parser/src/lexer/util.rs @@ -6,11 +6,10 @@ //! //! [babylon/util/identifier.js]:https://github.com/babel/babel/blob/master/packages/babylon/src/util/identifier.js use super::{input::Input, Char, LexResult, Lexer}; -use crate::error::{ErrorToDiag, SyntaxError}; +use crate::error::{Error, SyntaxError}; use std::char; use swc_common::{ comments::{Comment, CommentKind}, - errors::DiagnosticBuilder, BytePos, Span, SpanData, SyntaxContext, }; use unicode_xid::UnicodeXID; @@ -99,12 +98,10 @@ impl<'a, I: Input> Lexer<'a, I> { #[cold] pub(super) fn error_span(&mut self, span: Span, kind: SyntaxError) -> LexResult { - let err = ErrorToDiag { - handler: self.session.handler, + Err(Error { span, - error: kind, - }; - Err(err.into()) + error: Box::new(kind), + }) } #[cold] @@ -115,12 +112,11 @@ impl<'a, I: Input> Lexer<'a, I> { #[cold] pub(super) fn emit_error_span(&mut self, span: Span, kind: SyntaxError) { - let err = ErrorToDiag { - handler: self.session.handler, + let err = Error { span, - error: kind, + error: Box::new(kind), }; - DiagnosticBuilder::from(err).emit(); + self.errors.borrow_mut().push(err); } /// Skip comments or whitespaces. diff --git a/ecmascript/parser/src/lib.rs b/ecmascript/parser/src/lib.rs index 47ba42448fe..16093f283c9 100644 --- a/ecmascript/parser/src/lib.rs +++ b/ecmascript/parser/src/lib.rs @@ -45,43 +45,43 @@ //! errors::{ColorConfig, Handler}, //! FileName, FilePathMapping, SourceMap, //! }; -//! use swc_ecma_parser::{lexer::Lexer, Parser, Session, SourceFileInput, Syntax}; +//! use swc_ecma_parser::{lexer::Lexer, Parser, SourceFileInput, Syntax}; //! //! fn main() { //! swc_common::GLOBALS.set(&swc_common::Globals::new(), || { //! let cm: Arc = Default::default(); //! let handler = //! Handler::with_tty_emitter(ColorConfig::Auto, true, false, -//! Some(cm.clone())); -//! -//! let session = Session { handler: &handler }; +//! Some(cm.clone())); //! //! // Real usage //! // let fm = cm //! // .load_file(Path::new("test.js")) //! // .expect("failed to load test.js"); -//! -//! //! let fm = cm.new_source_file( //! FileName::Custom("test.js".into()), //! "function foo() {}".into(), //! ); //! let lexer = Lexer::new( -//! session, +//! // We want to parse ecmascript //! Syntax::Es(Default::default()), -//! Default::default(), +//! // JscTarget defaults to es5 +//! Default::default(), //! SourceFileInput::from(&*fm), //! None, //! ); //! -//! let mut parser = Parser::new_from(session, lexer); +//! let mut parser = Parser::new_from(lexer); //! +//! for e in parser.take_errors() { +//! e.into_diagnostic(&handler).emit(); +//! } //! //! let _module = parser //! .parse_module() //! .map_err(|mut e| { -//! e.emit(); -//! () +//! // Unrecoverable fatal error occurred +//! e.into_diagnostic(&handler).emit() //! }) //! .expect("failed to parser module"); //! }); @@ -100,11 +100,11 @@ pub use self::{ parser::*, }; use serde::{Deserialize, Serialize}; -use swc_common::{errors::Handler, Span, SpanData}; +use swc_common::{Span, SpanData}; #[macro_use] mod macros; -mod error; +pub mod error; pub mod lexer; mod parser; pub mod token; @@ -427,22 +427,17 @@ pub struct Context { in_case_cond: bool, } -#[derive(Clone, Copy)] -pub struct Session<'a> { - pub handler: &'a Handler, -} - #[cfg(test)] fn with_test_sess(src: &str, f: F) -> Result where - F: FnOnce(Session<'_>, SourceFileInput<'_>) -> Result, + F: FnOnce(&swc_common::errors::Handler, SourceFileInput<'_>) -> Result, { use swc_common::FileName; ::testing::run_test(false, |cm, handler| { let fm = cm.new_source_file(FileName::Real("testing".into()), src.into()); - f(Session { handler: &handler }, (&*fm).into()) + f(handler, (&*fm).into()) }) } diff --git a/ecmascript/parser/src/parser/class_and_fn.rs b/ecmascript/parser/src/parser/class_and_fn.rs index c8ce6b47490..17144068cc3 100644 --- a/ecmascript/parser/src/parser/class_and_fn.rs +++ b/ecmascript/parser/src/parser/class_and_fn.rs @@ -7,32 +7,32 @@ use swc_ecma_parser_macros::parser; #[parser] /// Parser for function expression and function declaration. -impl<'a, I: Tokens> Parser<'a, I> { - pub(super) fn parse_async_fn_expr(&mut self) -> PResult<'a, Box> { +impl<'a, I: Tokens> Parser { + pub(super) fn parse_async_fn_expr(&mut self) -> PResult> { let start = cur_pos!(); expect!("async"); self.parse_fn(Some(start), vec![]) } /// Parse function expression - pub(super) fn parse_fn_expr(&mut self) -> PResult<'a, Box> { + pub(super) fn parse_fn_expr(&mut self) -> PResult> { self.parse_fn(None, vec![]) } - pub(super) fn parse_async_fn_decl(&mut self, decorators: Vec) -> PResult<'a, Decl> { + pub(super) fn parse_async_fn_decl(&mut self, decorators: Vec) -> PResult { let start = cur_pos!(); expect!("async"); self.parse_fn(Some(start), decorators) } - pub(super) fn parse_fn_decl(&mut self, decorators: Vec) -> PResult<'a, Decl> { + pub(super) fn parse_fn_decl(&mut self, decorators: Vec) -> PResult { self.parse_fn(None, decorators) } pub(super) fn parse_default_async_fn( &mut self, decorators: Vec, - ) -> PResult<'a, ExportDefaultDecl> { + ) -> PResult { let start = cur_pos!(); expect!("async"); self.parse_fn(Some(start), decorators) @@ -41,7 +41,7 @@ impl<'a, I: Tokens> Parser<'a, I> { pub(super) fn parse_default_fn( &mut self, decorators: Vec, - ) -> PResult<'a, ExportDefaultDecl> { + ) -> PResult { self.parse_fn(None, decorators) } @@ -50,7 +50,7 @@ impl<'a, I: Tokens> Parser<'a, I> { start: BytePos, class_start: BytePos, decorators: Vec, - ) -> PResult<'a, Decl> { + ) -> PResult { self.parse_class(start, class_start, decorators) } @@ -58,7 +58,7 @@ impl<'a, I: Tokens> Parser<'a, I> { &mut self, start: BytePos, decorators: Vec, - ) -> PResult<'a, Box> { + ) -> PResult> { self.parse_class(start, start, decorators) } @@ -67,7 +67,7 @@ impl<'a, I: Tokens> Parser<'a, I> { start: BytePos, class_start: BytePos, decorators: Vec, - ) -> PResult<'a, ExportDefaultDecl> { + ) -> PResult { self.parse_class(start, class_start, decorators) } @@ -76,10 +76,10 @@ impl<'a, I: Tokens> Parser<'a, I> { start: BytePos, class_start: BytePos, decorators: Vec, - ) -> PResult<'a, T> + ) -> PResult where T: OutputType, - Self: MaybeOptionalIdentParser<'a, T::Ident>, + Self: MaybeOptionalIdentParser, { self.strict_mode().parse_with(|p| { expect!("class"); @@ -181,7 +181,7 @@ impl<'a, I: Tokens> Parser<'a, I> { }) } - pub(super) fn parse_decorators(&mut self, allow_export: bool) -> PResult<'a, Vec> { + pub(super) fn parse_decorators(&mut self, allow_export: bool) -> PResult> { if !self.syntax().decorators() { return Ok(vec![]); } @@ -211,7 +211,7 @@ impl<'a, I: Tokens> Parser<'a, I> { Ok(decorators) } - fn parse_decorator(&mut self) -> PResult<'a, Decorator> { + fn parse_decorator(&mut self) -> PResult { let start = cur_pos!(); assert_and_bump!('@'); @@ -251,7 +251,7 @@ impl<'a, I: Tokens> Parser<'a, I> { }) } - fn parse_maybe_decorator_args(&mut self, expr: Box) -> PResult<'a, Box> { + fn parse_maybe_decorator_args(&mut self, expr: Box) -> PResult> { let type_args = if self.input.syntax().typescript() && is!('<') { Some(self.parse_ts_type_args()?) } else { @@ -271,7 +271,7 @@ impl<'a, I: Tokens> Parser<'a, I> { }))) } - fn parse_class_body(&mut self) -> PResult<'a, Vec> { + fn parse_class_body(&mut self) -> PResult> { let mut elems = vec![]; while !eof!() && !is!('}') { if eat_exact!(';') { @@ -287,7 +287,7 @@ impl<'a, I: Tokens> Parser<'a, I> { Ok(elems) } - pub(super) fn parse_access_modifier(&mut self) -> PResult<'a, Option> { + pub(super) fn parse_access_modifier(&mut self) -> PResult> { Ok(self .parse_ts_modifier(&["public", "protected", "private"])? .map(|s| match s { @@ -298,7 +298,7 @@ impl<'a, I: Tokens> Parser<'a, I> { })) } - fn parse_class_member(&mut self) -> PResult<'a, ClassMember> { + fn parse_class_member(&mut self) -> PResult { let start = cur_pos!(); let decorators = self.parse_decorators(false)?; @@ -425,7 +425,7 @@ impl<'a, I: Tokens> Parser<'a, I> { accessibility: Option, static_token: Option, decorators: Vec, - ) -> PResult<'a, ClassMember> { + ) -> PResult { let is_static = static_token.is_some(); let modifier = self.parse_ts_modifier(&["abstract", "readonly"])?; let modifier_span = if let Some(..) = modifier { @@ -728,7 +728,7 @@ impl<'a, I: Tokens> Parser<'a, I> { is_optional: bool, readonly: bool, is_abstract: bool, - ) -> PResult<'a, ClassMember> { + ) -> PResult { if !self.input.syntax().class_props() { syntax_error!(span!(start), SyntaxError::ClassProperty) } @@ -803,11 +803,11 @@ impl<'a, I: Tokens> Parser<'a, I> { }) } - fn is_class_method(&mut self) -> PResult<'a, bool> { + fn is_class_method(&mut self) -> PResult { Ok(is!('(') || (self.input.syntax().typescript() && is!('<'))) } - fn is_class_property(&mut self) -> PResult<'a, bool> { + fn is_class_property(&mut self) -> PResult { Ok((self.input.syntax().typescript() && is_one_of!('!', ':')) || is_one_of!('=', ';', '}')) } @@ -815,10 +815,10 @@ impl<'a, I: Tokens> Parser<'a, I> { &mut self, start_of_async: Option, decorators: Vec, - ) -> PResult<'a, T> + ) -> PResult where T: OutputType, - Self: MaybeOptionalIdentParser<'a, T::Ident>, + Self: MaybeOptionalIdentParser, T::Ident: Spanned, { let start = start_of_async.unwrap_or(cur_pos!()); @@ -890,9 +890,9 @@ impl<'a, I: Tokens> Parser<'a, I> { parse_args: F, is_async: bool, is_generator: bool, - ) -> PResult<'a, Function> + ) -> PResult where - F: FnOnce(&mut Self) -> PResult<'a, Vec>, + F: FnOnce(&mut Self) -> PResult>, { // let prev_in_generator = self.ctx().in_generator; let ctx = Context { @@ -959,7 +959,7 @@ impl<'a, I: Tokens> Parser<'a, I> { }) } - fn parse_class_prop_name(&mut self) -> PResult<'a, Either> { + fn parse_class_prop_name(&mut self) -> PResult> { if is!('#') { self.parse_private_name().map(Either::Left) } else { @@ -967,9 +967,9 @@ impl<'a, I: Tokens> Parser<'a, I> { } } - pub(super) fn parse_fn_body(&mut self, is_async: bool, is_generator: bool) -> PResult<'a, T> + pub(super) fn parse_fn_body(&mut self, is_async: bool, is_generator: bool) -> PResult where - Self: FnBodyParser<'a, T>, + Self: FnBodyParser, { if self.ctx().in_declare && self.syntax().typescript() && is!('{') { // self.emit_err( @@ -995,7 +995,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } } -impl<'a, I: Tokens> Parser<'a, I> { +impl<'a, I: Tokens> Parser { fn make_method( &mut self, parse_args: F, @@ -1011,9 +1011,9 @@ impl<'a, I: Tokens> Parser<'a, I> { is_async, is_generator, }: MakeMethodArgs, - ) -> PResult<'a, ClassMember> + ) -> PResult where - F: FnOnce(&mut Self) -> PResult<'a, Vec>, + F: FnOnce(&mut Self) -> PResult>, { let is_static = static_token.is_some(); let ctx = Context { @@ -1178,13 +1178,13 @@ impl OutputType for Decl { } } -pub(super) trait FnBodyParser<'a, Body> { - fn parse_fn_body_inner(&mut self) -> PResult<'a, Body>; +pub(super) trait FnBodyParser { + fn parse_fn_body_inner(&mut self) -> PResult; } #[parser] -impl<'a, I: Tokens> FnBodyParser<'a, BlockStmtOrExpr> for Parser<'a, I> { - fn parse_fn_body_inner(&mut self) -> PResult<'a, BlockStmtOrExpr> { +impl FnBodyParser for Parser { + fn parse_fn_body_inner(&mut self) -> PResult { if is!('{') { self.parse_block(false).map(BlockStmtOrExpr::BlockStmt) } else { @@ -1194,8 +1194,8 @@ impl<'a, I: Tokens> FnBodyParser<'a, BlockStmtOrExpr> for Parser<'a, I> { } #[parser] -impl<'a, I: Tokens> FnBodyParser<'a, Option> for Parser<'a, I> { - fn parse_fn_body_inner(&mut self) -> PResult<'a, Option> { +impl FnBodyParser> for Parser { + fn parse_fn_body_inner(&mut self) -> PResult> { // allow omitting body and allow placing `{` on next line if self.input.syntax().typescript() && !is!('{') && eat!(';') { return Ok(None); @@ -1248,19 +1248,11 @@ mod tests { use swc_ecma_visit::assert_eq_ignore_span; fn lhs(s: &'static str) -> Box { - test_parser(s, Syntax::default(), |p| { - p.parse_lhs_expr().map_err(|mut e| { - e.emit(); - }) - }) + test_parser(s, Syntax::default(), |p| p.parse_lhs_expr()) } fn expr(s: &'static str) -> Box { - test_parser(s, Syntax::default(), |p| { - p.parse_expr().map_err(|mut e| { - e.emit(); - }) - }) + test_parser(s, Syntax::default(), |p| p.parse_expr()) } #[test] diff --git a/ecmascript/parser/src/parser/expr.rs b/ecmascript/parser/src/parser/expr.rs index 7365793ef4a..9d0830d8c82 100644 --- a/ecmascript/parser/src/parser/expr.rs +++ b/ecmascript/parser/src/parser/expr.rs @@ -10,8 +10,8 @@ mod tests; mod verifier; #[parser] -impl<'a, I: Tokens> Parser<'a, I> { - pub fn parse_expr(&mut self) -> PResult<'a, Box> { +impl<'a, I: Tokens> Parser { + pub fn parse_expr(&mut self) -> PResult> { trace_cur!(parse_expr); let expr = self.parse_assignment_expr()?; @@ -33,7 +33,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } ///`parseMaybeAssign` (overrided) - pub(super) fn parse_assignment_expr(&mut self) -> PResult<'a, Box> { + pub(super) fn parse_assignment_expr(&mut self) -> PResult> { trace_cur!(parse_assignment_expr); if self.input.syntax().typescript() { @@ -97,7 +97,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// operators like `+=`. /// /// `parseMaybeAssign` - fn parse_assignment_expr_base(&mut self) -> PResult<'a, Box> { + fn parse_assignment_expr_base(&mut self) -> PResult> { trace_cur!(parse_assignment_expr_base); if self.ctx().in_generator && is!("yield") { @@ -126,11 +126,7 @@ impl<'a, I: Tokens> Parser<'a, I> { self.finish_assignment_expr(start, cond) } - fn finish_assignment_expr( - &mut self, - start: BytePos, - cond: Box, - ) -> PResult<'a, Box> { + fn finish_assignment_expr(&mut self, start: BytePos, cond: Box) -> PResult> { trace_cur!(finish_assignment_expr); match cur!(false) { @@ -177,7 +173,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } /// Spec: 'ConditionalExpression' - fn parse_cond_expr(&mut self) -> PResult<'a, Box> { + fn parse_cond_expr(&mut self) -> PResult> { trace_cur!(parse_cond_expr); let start = cur_pos!(); @@ -212,7 +208,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// Parse a primary expression or arrow function #[allow(clippy::cognitive_complexity)] - pub(super) fn parse_primary_expr(&mut self) -> PResult<'a, Box> { + pub(super) fn parse_primary_expr(&mut self) -> PResult> { trace_cur!(parse_primary_expr); let _ = cur!(false); @@ -384,7 +380,7 @@ impl<'a, I: Tokens> Parser<'a, I> { unexpected!() } - fn parse_array_lit(&mut self) -> PResult<'a, Box> { + fn parse_array_lit(&mut self) -> PResult> { trace_cur!(parse_array_lit); let start = cur_pos!(); @@ -414,12 +410,12 @@ impl<'a, I: Tokens> Parser<'a, I> { Ok(Box::new(Expr::Array(ArrayLit { span, elems }))) } - fn parse_member_expr(&mut self) -> PResult<'a, Box> { + fn parse_member_expr(&mut self) -> PResult> { self.parse_member_expr_or_new_expr(false) } /// `parseImportMetaProperty` - pub(super) fn parse_import_meta_prop(&mut self, import: Ident) -> PResult<'a, MetaPropExpr> { + pub(super) fn parse_import_meta_prop(&mut self, import: Ident) -> PResult { let start = cur_pos!(); let meta = import; @@ -436,7 +432,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } /// `is_new_expr`: true iff we are parsing production 'NewExpression'. - fn parse_member_expr_or_new_expr(&mut self, is_new_expr: bool) -> PResult<'a, Box> { + fn parse_member_expr_or_new_expr(&mut self, is_new_expr: bool) -> PResult> { trace_cur!(parse_member_expr_or_new_expr); let start = cur_pos!(); @@ -510,14 +506,14 @@ impl<'a, I: Tokens> Parser<'a, I> { /// Parse `NewExpresion`. /// This includes `MemberExpression`. - pub(super) fn parse_new_expr(&mut self) -> PResult<'a, Box> { + pub(super) fn parse_new_expr(&mut self) -> PResult> { trace_cur!(parse_new_expr); self.parse_member_expr_or_new_expr(true) } /// Parse `Arguments[Yield, Await]` - pub(super) fn parse_args(&mut self, is_dynamic_import: bool) -> PResult<'a, Vec> { + pub(super) fn parse_args(&mut self, is_dynamic_import: bool) -> PResult> { trace_cur!(parse_args); let start = cur_pos!(); @@ -550,7 +546,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// AssignmentExpression[+In, ?Yield, ?Await] /// ...AssignmentExpression[+In, ?Yield, ?Await] - pub(super) fn parse_expr_or_spread(&mut self) -> PResult<'a, ExprOrSpread> { + pub(super) fn parse_expr_or_spread(&mut self) -> PResult { trace_cur!(parse_expr_or_spread); let start = cur_pos!(); @@ -571,7 +567,7 @@ impl<'a, I: Tokens> Parser<'a, I> { &mut self, can_be_arrow: bool, async_span: Option, - ) -> PResult<'a, Box> { + ) -> PResult> { trace_cur!(parse_paren_expr_or_arrow_fn); let expr_start = async_span.map(|x| x.lo()).unwrap_or(cur_pos!()); @@ -676,7 +672,7 @@ impl<'a, I: Tokens> Parser<'a, I> { let expr_or_spreads = paren_items .into_iter() - .map(|item| -> PResult<'a, _> { + .map(|item| -> PResult<_> { match item { PatOrExprOrSpread::ExprOrSpread(e) => Ok(e), _ => syntax_error!(item.span(), SyntaxError::InvalidExpr), @@ -755,7 +751,7 @@ impl<'a, I: Tokens> Parser<'a, I> { fn parse_tpl_elements( &mut self, is_tagged: bool, - ) -> PResult<'a, (Vec>, Vec)> { + ) -> PResult<(Vec>, Vec)> { trace_cur!(parse_tpl_elements); let mut exprs = vec![]; @@ -780,7 +776,7 @@ impl<'a, I: Tokens> Parser<'a, I> { &mut self, tag: Box, type_params: Option, - ) -> PResult<'a, TaggedTpl> { + ) -> PResult { let tagged_tpl_start = tag.span().lo(); trace_cur!(parse_tagged_tpl); @@ -800,7 +796,7 @@ impl<'a, I: Tokens> Parser<'a, I> { }) } - pub(super) fn parse_tpl(&mut self) -> PResult<'a, Tpl> { + pub(super) fn parse_tpl(&mut self) -> PResult { trace_cur!(parse_tpl); let start = cur_pos!(); @@ -818,7 +814,7 @@ impl<'a, I: Tokens> Parser<'a, I> { }) } - fn parse_tpl_element(&mut self, is_tagged: bool) -> PResult<'a, TplElement> { + fn parse_tpl_element(&mut self, is_tagged: bool) -> PResult { let start = cur_pos!(); let (raw, cooked) = match *cur!(true)? { @@ -853,7 +849,7 @@ impl<'a, I: Tokens> Parser<'a, I> { }) } - fn parse_subscripts(&mut self, mut obj: ExprOrSuper, no_call: bool) -> PResult<'a, Box> { + fn parse_subscripts(&mut self, mut obj: ExprOrSuper, no_call: bool) -> PResult> { loop { obj = match self.parse_subscript(obj, no_call)? { (expr, false) => return Ok(expr), @@ -864,11 +860,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// returned bool is true if this method should be called again. #[allow(clippy::cognitive_complexity)] - fn parse_subscript( - &mut self, - obj: ExprOrSuper, - no_call: bool, - ) -> PResult<'a, (Box, bool)> { + fn parse_subscript(&mut self, obj: ExprOrSuper, no_call: bool) -> PResult<(Box, bool)> { let _ = cur!(false); let start = obj.span().lo(); @@ -1048,7 +1040,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } } /// Parse call, dot, and `[]`-subscript expressions. - pub(super) fn parse_lhs_expr(&mut self) -> PResult<'a, Box> { + pub(super) fn parse_lhs_expr(&mut self) -> PResult> { let start = cur_pos!(); // parse jsx @@ -1149,12 +1141,12 @@ impl<'a, I: Tokens> Parser<'a, I> { Ok(callee) } - pub(super) fn parse_expr_or_pat(&mut self) -> PResult<'a, Box> { + pub(super) fn parse_expr_or_pat(&mut self) -> PResult> { self.parse_expr() } #[allow(clippy::cognitive_complexity)] - pub(super) fn parse_args_or_pats(&mut self) -> PResult<'a, Vec> { + pub(super) fn parse_args_or_pats(&mut self) -> PResult> { trace_cur!(parse_args_or_pats); expect!('('); @@ -1426,8 +1418,8 @@ pub(in crate::parser) enum PatOrExprOrSpread { /// simple leaf methods. #[parser] -impl<'a, I: Tokens> Parser<'a, I> { - fn parse_yield_expr(&mut self) -> PResult<'a, Box> { +impl<'a, I: Tokens> Parser { + fn parse_yield_expr(&mut self) -> PResult> { let start = cur_pos!(); assert_and_bump!("yield"); @@ -1462,7 +1454,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } } - fn at_possible_async(&mut self, expr: &Expr) -> PResult<'a, bool> { + fn at_possible_async(&mut self, expr: &Expr) -> PResult { // TODO(kdy1): !this.state.containsEsc && Ok(self.state.potential_arrow_start == Some(expr.span().lo()) @@ -1476,7 +1468,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } /// 12.2.5 Array Initializer - pub(super) fn parse_lit(&mut self) -> PResult<'a, Lit> { + pub(super) fn parse_lit(&mut self) -> PResult { let start = cur_pos!(); let v = match *cur!(true)? { @@ -1523,7 +1515,7 @@ impl<'a, I: Tokens> Parser<'a, I> { &mut self, start: BytePos, import_ident: Ident, - ) -> PResult<'a, Box> { + ) -> PResult> { if !self.input.syntax().dynamic_import() { syntax_error!(span!(start), SyntaxError::DynamicImport); } diff --git a/ecmascript/parser/src/parser/expr/ops.rs b/ecmascript/parser/src/parser/expr/ops.rs index 2c8c40df153..1f8e66e717f 100644 --- a/ecmascript/parser/src/parser/expr/ops.rs +++ b/ecmascript/parser/src/parser/expr/ops.rs @@ -5,14 +5,14 @@ use log::trace; use swc_common::Spanned; #[parser] -impl<'a, I: Tokens> Parser<'a, I> { +impl<'a, I: Tokens> Parser { /// Name from spec: 'LogicalORExpression' - pub(super) fn parse_bin_expr(&mut self) -> PResult<'a, Box> { + pub(super) fn parse_bin_expr(&mut self) -> PResult> { let ctx = self.ctx(); let left = match self.parse_unary_expr() { Ok(v) => v, - Err(mut err) => { + Err(err) => { match { let is_err_token = match self.input.cur() { Some(&Token::Error(..)) => true, @@ -28,22 +28,14 @@ impl<'a, I: Tokens> Parser<'a, I> { } } { &Word(Word::Keyword(Keyword::In)) if ctx.include_in_expr => { - err.cancel(); - self.emit_err(self.input.cur_span(), SyntaxError::TS1109); - Box::new(Expr::Invalid(Invalid { - span: err.span.primary_span().unwrap(), - })) + Box::new(Expr::Invalid(Invalid { span: err.span })) } &Word(Word::Keyword(Keyword::InstanceOf)) | &Token::BinOp(..) => { - err.cancel(); - self.emit_err(self.input.cur_span(), SyntaxError::TS1109); - Box::new(Expr::Invalid(Invalid { - span: err.span.primary_span().unwrap(), - })) + Box::new(Expr::Invalid(Invalid { span: err.span })) } _ => return Err(err), } @@ -65,7 +57,7 @@ impl<'a, I: Tokens> Parser<'a, I> { &mut self, left: Box, min_prec: u8, - ) -> PResult<'a, Box> { + ) -> PResult> { const PREC_OF_IN: u8 = 7; if self.input.syntax().typescript() @@ -213,7 +205,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// Parse unary expression and update expression. /// /// spec: 'UnaryExpression' - pub(in crate::parser) fn parse_unary_expr(&mut self) -> PResult<'a, Box> { + pub(in crate::parser) fn parse_unary_expr(&mut self) -> PResult> { let start = cur_pos!(); if !self.input.syntax().jsx() && self.input.syntax().typescript() && eat!('<') { @@ -267,8 +259,8 @@ impl<'a, I: Tokens> Parser<'a, I> { let arg_start = cur_pos!() - BytePos(1); let arg = match self.parse_unary_expr() { Ok(expr) => expr, - Err(mut err) => { - err.emit(); + Err(err) => { + self.emit_error(err); Box::new(Expr::Invalid(Invalid { span: Span::new(arg_start, arg_start, Default::default()), })) @@ -338,7 +330,7 @@ impl<'a, I: Tokens> Parser<'a, I> { Ok(expr) } - pub(crate) fn parse_await_expr(&mut self) -> PResult<'a, Box> { + pub(crate) fn parse_await_expr(&mut self) -> PResult> { let start = cur_pos!(); assert_and_bump!("await"); @@ -369,11 +361,7 @@ mod tests { use swc_ecma_visit::assert_eq_ignore_span; fn bin(s: &'static str) -> Box { - test_parser(s, Syntax::default(), |p| { - p.parse_bin_expr().map_err(|mut e| { - e.emit(); - }) - }) + test_parser(s, Syntax::default(), |p| p.parse_bin_expr()) } #[test] diff --git a/ecmascript/parser/src/parser/expr/tests.rs b/ecmascript/parser/src/parser/expr/tests.rs index 1871c342730..d314213ffce 100644 --- a/ecmascript/parser/src/parser/expr/tests.rs +++ b/ecmascript/parser/src/parser/expr/tests.rs @@ -15,39 +15,23 @@ fn syntax() -> Syntax { } fn lhs(s: &'static str) -> Box { - test_parser(s, syntax(), |p| { - p.parse_lhs_expr().map_err(|mut e| { - e.emit(); - }) - }) + test_parser(s, syntax(), |p| p.parse_lhs_expr()) } fn new_expr(s: &'static str) -> Box { - test_parser(s, syntax(), |p| { - p.parse_new_expr().map_err(|mut e| { - e.emit(); - }) - }) + test_parser(s, syntax(), |p| p.parse_new_expr()) } fn member_expr(s: &'static str) -> Box { - test_parser(s, syntax(), |p| { - p.parse_member_expr().map_err(|mut e| { - e.emit(); - }) - }) + test_parser(s, syntax(), |p| p.parse_member_expr()) } fn expr(s: &'static str) -> Box { test_parser(s, syntax(), |p| { - p.parse_stmt(true) - .map(|stmt| match stmt { - Stmt::Expr(expr) => expr.expr, - _ => unreachable!(), - }) - .map_err(|mut e| { - e.emit(); - }) + p.parse_stmt(true).map(|stmt| match stmt { + Stmt::Expr(expr) => expr.expr, + _ => unreachable!(), + }) }) } @@ -353,11 +337,7 @@ fn issue_328() { dynamic_import: true, ..Default::default() }), - |p| { - p.parse_stmt(true).map_err(|mut e| { - e.emit(); - }) - } + |p| { p.parse_stmt(true) } ), Stmt::Expr(ExprStmt { span, @@ -383,11 +363,7 @@ fn issue_337() { test_parser( "const foo = 'bar' in bas ? 'beep' : 'boop';", Default::default(), - |p| { - p.parse_module().map_err(|mut e| { - e.emit(); - }) - }, + |p| p.parse_module(), ); } diff --git a/ecmascript/parser/src/parser/expr/verifier.rs b/ecmascript/parser/src/parser/expr/verifier.rs index d0416bf86da..fc55a3d9d68 100644 --- a/ecmascript/parser/src/parser/expr/verifier.rs +++ b/ecmascript/parser/src/parser/expr/verifier.rs @@ -2,8 +2,8 @@ use super::*; use swc_common::{Span, Spanned, DUMMY_SP}; use swc_ecma_visit::{Node, Visit, VisitWith}; -impl<'a, I: Tokens> Parser<'a, I> { - pub(in crate::parser) fn verify_expr(&self, expr: Box) -> PResult<'a, Box> { +impl<'a, I: Tokens> Parser { + pub(in crate::parser) fn verify_expr(&mut self, expr: Box) -> PResult> { let mut v = Verifier { errors: vec![] }; v.visit_expr(&expr, &Invalid { span: DUMMY_SP } as _); diff --git a/ecmascript/parser/src/parser/ident.rs b/ecmascript/parser/src/parser/ident.rs index f70f089bc79..5832be982a6 100644 --- a/ecmascript/parser/src/parser/ident.rs +++ b/ecmascript/parser/src/parser/ident.rs @@ -6,8 +6,8 @@ use swc_atoms::js_word; use swc_ecma_parser_macros::parser; #[parser] -impl<'a, I: Tokens> Parser<'a, I> { - pub(super) fn parse_maybe_private_name(&mut self) -> PResult<'a, Either> { +impl<'a, I: Tokens> Parser { + pub(super) fn parse_maybe_private_name(&mut self) -> PResult> { let start = cur_pos!(); let is_private = is!('#'); @@ -18,7 +18,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } } - pub(super) fn parse_private_name(&mut self) -> PResult<'a, PrivateName> { + pub(super) fn parse_private_name(&mut self) -> PResult { let start = cur_pos!(); assert_and_bump!('#'); @@ -35,14 +35,14 @@ impl<'a, I: Tokens> Parser<'a, I> { } /// IdentifierReference - pub(super) fn parse_ident_ref(&mut self) -> PResult<'a, Ident> { + pub(super) fn parse_ident_ref(&mut self) -> PResult { let ctx = self.ctx(); self.parse_ident(!ctx.in_generator, !ctx.in_async) } /// LabelIdentifier - pub(super) fn parse_label_ident(&mut self) -> PResult<'a, Ident> { + pub(super) fn parse_label_ident(&mut self) -> PResult { let ctx = self.ctx(); self.parse_ident(!ctx.in_generator, !ctx.in_async) @@ -50,7 +50,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// Use this when spec says "IdentifierName". /// This allows idents like `catch`. - pub(super) fn parse_ident_name(&mut self) -> PResult<'a, Ident> { + pub(super) fn parse_ident_name(&mut self) -> PResult { let start = cur_pos!(); let w = match cur!(true) { @@ -67,7 +67,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// Identifier /// /// In strict mode, "yield" is SyntaxError if matched. - pub(super) fn parse_ident(&mut self, incl_yield: bool, incl_await: bool) -> PResult<'a, Ident> { + pub(super) fn parse_ident(&mut self, incl_yield: bool, incl_await: bool) -> PResult { trace_cur!(parse_ident); let start = cur_pos!(); @@ -144,16 +144,16 @@ impl<'a, I: Tokens> Parser<'a, I> { } } -pub(super) trait MaybeOptionalIdentParser<'a, Ident> { - fn parse_maybe_opt_binding_ident(&mut self) -> PResult<'a, Ident>; +pub(super) trait MaybeOptionalIdentParser { + fn parse_maybe_opt_binding_ident(&mut self) -> PResult; } -impl<'a, I: Tokens> MaybeOptionalIdentParser<'a, Ident> for Parser<'a, I> { - fn parse_maybe_opt_binding_ident(&mut self) -> PResult<'a, Ident> { +impl MaybeOptionalIdentParser for Parser { + fn parse_maybe_opt_binding_ident(&mut self) -> PResult { self.parse_binding_ident() } } -impl<'a, I: Tokens> MaybeOptionalIdentParser<'a, Option> for Parser<'a, I> { - fn parse_maybe_opt_binding_ident(&mut self) -> PResult<'a, Option> { +impl MaybeOptionalIdentParser> for Parser { + fn parse_maybe_opt_binding_ident(&mut self) -> PResult> { self.parse_opt_binding_ident() } } diff --git a/ecmascript/parser/src/parser/input.rs b/ecmascript/parser/src/parser/input.rs index 335a091935f..2090331462c 100644 --- a/ecmascript/parser/src/parser/input.rs +++ b/ecmascript/parser/src/parser/input.rs @@ -1,11 +1,12 @@ use super::Parser; use crate::{ + error::Error, lexer::{self}, token::*, Context, JscTarget, Syntax, }; use lexer::TokenContexts; -use std::{cell::RefCell, mem, rc::Rc}; +use std::{cell::RefCell, mem, mem::take, rc::Rc}; use swc_common::{BytePos, Span, SpanData, DUMMY_SP}; pub trait Tokens: Clone + Iterator { @@ -18,6 +19,13 @@ pub trait Tokens: Clone + Iterator { fn token_context(&self) -> &lexer::TokenContexts; fn token_context_mut(&mut self) -> &mut lexer::TokenContexts; fn set_token_context(&mut self, _c: lexer::TokenContexts); + + /// Implementors should use Rc>>. + /// + /// It is required because parser should backtrack while parsing typescript + /// code. + fn add_error(&self, error: Error); + fn take_errors(&mut self) -> Vec; } #[derive(Clone)] @@ -27,6 +35,7 @@ pub struct TokensInput { syntax: Syntax, target: JscTarget, token_ctx: TokenContexts, + errors: Rc>>, } impl TokensInput { @@ -37,6 +46,7 @@ impl TokensInput { syntax, target, token_ctx: Default::default(), + errors: Default::default(), } } } @@ -78,6 +88,14 @@ impl Tokens for TokensInput { fn set_token_context(&mut self, c: TokenContexts) { self.token_ctx = c; } + + fn add_error(&self, error: Error) { + self.errors.borrow_mut().push(error); + } + + fn take_errors(&mut self) -> Vec { + take(&mut self.errors.borrow_mut()) + } } /// Note: Lexer need access to parser's context to lex correctly. @@ -168,6 +186,14 @@ impl Tokens for Capturing { fn set_token_context(&mut self, c: TokenContexts) { self.inner.set_token_context(c) } + + fn add_error(&self, error: Error) { + self.inner.add_error(error); + } + + fn take_errors(&mut self) -> Vec { + self.inner.take_errors() + } } /// This struct is responsible for managing current token and peeked token. @@ -181,10 +207,13 @@ pub(super) struct Buffer { next: Option, } -impl Parser<'_, I> { +impl Parser { pub fn input(&mut self) -> &mut I { &mut self.input.iter } + pub(crate) fn input_ref(&self) -> &I { + &self.input.iter + } } impl Buffer { diff --git a/ecmascript/parser/src/parser/jsx.rs b/ecmascript/parser/src/parser/jsx.rs index 34c9f78158d..2d1b8361843 100644 --- a/ecmascript/parser/src/parser/jsx.rs +++ b/ecmascript/parser/src/parser/jsx.rs @@ -7,9 +7,9 @@ use swc_common::{Span, Spanned, SyntaxContext}; mod tests; #[parser] -impl<'a, I: Tokens> Parser<'a, I> { +impl<'a, I: Tokens> Parser { /// Parse next token as JSX identifier - pub(super) fn parse_jsx_ident(&mut self) -> PResult<'a, Ident> { + pub(super) fn parse_jsx_ident(&mut self) -> PResult { debug_assert!(self.input.syntax().jsx()); let ctx = self.ctx(); @@ -27,7 +27,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } /// Parse namespaced identifier. - pub(super) fn parse_jsx_namespaced_name(&mut self) -> PResult<'a, JSXAttrName> { + pub(super) fn parse_jsx_namespaced_name(&mut self) -> PResult { debug_assert!(self.input.syntax().jsx()); let ns = self.parse_jsx_ident()?; @@ -44,7 +44,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// Parses element name in any form - namespaced, member or single /// identifier. - pub(super) fn parse_jsx_element_name(&mut self) -> PResult<'a, JSXElementName> { + pub(super) fn parse_jsx_element_name(&mut self) -> PResult { debug_assert!(self.input.syntax().jsx()); let start_pos = cur_pos!(); @@ -70,7 +70,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// Parses any type of JSX attribute value. /// /// TODO(kdy1): Change return type to JSXAttrValue - pub(super) fn parse_jsx_attr_value(&mut self) -> PResult<'a, JSXAttrValue> { + pub(super) fn parse_jsx_attr_value(&mut self) -> PResult { debug_assert!(self.input.syntax().jsx()); let start = cur_pos!(); @@ -105,7 +105,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// JSXEmptyExpression is unique type since it doesn't actually parse /// anything, and so it should start at the end of last read token (left /// brace) and finish at the beginning of the next one (right brace). - pub(super) fn parse_jsx_empty_expr(&mut self) -> PResult<'a, JSXEmptyExpr> { + pub(super) fn parse_jsx_empty_expr(&mut self) -> PResult { debug_assert!(self.input.syntax().jsx()); let start = cur_pos!(); @@ -115,7 +115,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } /// Parse JSX spread child - pub(super) fn parse_jsx_spread_child(&mut self) -> PResult<'a, JSXSpreadChild> { + pub(super) fn parse_jsx_spread_child(&mut self) -> PResult { debug_assert!(self.input.syntax().jsx()); let start = cur_pos!(); expect!('{'); @@ -130,10 +130,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } /// Parses JSX expression enclosed into curly brackets. - pub(super) fn parse_jsx_expr_container( - &mut self, - start: BytePos, - ) -> PResult<'a, JSXExprContainer> { + pub(super) fn parse_jsx_expr_container(&mut self, start: BytePos) -> PResult { debug_assert!(self.input.syntax().jsx()); let start = cur_pos!(); @@ -151,7 +148,7 @@ impl<'a, I: Tokens> Parser<'a, I> { } /// Parses following JSX attribute name-value pair. - pub(super) fn parse_jsx_attr(&mut self) -> PResult<'a, JSXAttrOrSpread> { + pub(super) fn parse_jsx_attr(&mut self) -> PResult { debug_assert!(self.input.syntax().jsx()); let start = cur_pos!(); @@ -183,7 +180,7 @@ impl<'a, I: Tokens> Parser<'a, I> { pub(super) fn parse_jsx_opening_element_at( &mut self, start: BytePos, - ) -> PResult<'a, Either> { + ) -> PResult> { debug_assert!(self.input.syntax().jsx()); if eat!(JSXTagEnd) { @@ -200,7 +197,7 @@ impl<'a, I: Tokens> Parser<'a, I> { &mut self, start: BytePos, name: JSXElementName, - ) -> PResult<'a, JSXOpeningElement> { + ) -> PResult { debug_assert!(self.input.syntax().jsx()); let type_args = if self.input.syntax().typescript() && is!('<') { @@ -235,7 +232,7 @@ impl<'a, I: Tokens> Parser<'a, I> { fn parse_jsx_closing_element_at( &mut self, start: BytePos, - ) -> PResult<'a, Either> { + ) -> PResult> { debug_assert!(self.input.syntax().jsx()); if eat!(JSXTagEnd) { @@ -257,7 +254,7 @@ impl<'a, I: Tokens> Parser<'a, I> { pub(super) fn parse_jsx_element_at( &mut self, start_pos: BytePos, - ) -> PResult<'a, Either> { + ) -> PResult> { debug_assert!(self.input.syntax().jsx()); let _ = cur!(true); @@ -374,7 +371,7 @@ impl<'a, I: Tokens> Parser<'a, I> { /// Parses entire JSX element from current position. /// /// babel: `jsxParseElement` - pub(super) fn parse_jsx_element(&mut self) -> PResult<'a, Either> { + pub(super) fn parse_jsx_element(&mut self) -> PResult> { debug_assert!(self.input.syntax().jsx()); debug_assert!({ match *cur!(true)? { @@ -388,7 +385,7 @@ impl<'a, I: Tokens> Parser<'a, I> { self.parse_jsx_element_at(start_pos) } - pub(super) fn parse_jsx_text(&mut self) -> PResult<'a, JSXText> { + pub(super) fn parse_jsx_text(&mut self) -> PResult { debug_assert!(self.input.syntax().jsx()); debug_assert!({ match cur!(false) { diff --git a/ecmascript/parser/src/parser/jsx/tests.rs b/ecmascript/parser/src/parser/jsx/tests.rs index 7bebef6653b..a284eedcb28 100644 --- a/ecmascript/parser/src/parser/jsx/tests.rs +++ b/ecmascript/parser/src/parser/jsx/tests.rs @@ -10,11 +10,7 @@ fn jsx(src: &'static str) -> Box { jsx: true, ..Default::default() }), - |p| { - p.parse_expr().map_err(|mut e| { - e.emit(); - }) - }, + |p| p.parse_expr(), ) } diff --git a/ecmascript/parser/src/parser/macros.rs b/ecmascript/parser/src/parser/macros.rs index 1406f1b0947..51dfa40c835 100644 --- a/ecmascript/parser/src/parser/macros.rs +++ b/ecmascript/parser/src/parser/macros.rs @@ -192,12 +192,10 @@ macro_rules! cur { if is_err_token { match $p.input.bump() { $crate::token::Token::Error(e) => { - let err = - ::swc_common::errors::DiagnosticBuilder::from($crate::error::ErrorToDiag { - handler: &$p.session.handler, - span: e.span, - error: e.error, - }); + let err = crate::error::Error { + span: e.span, + error: e.error, + }; return Err(err.into()); } _ => unreachable!(), @@ -208,15 +206,15 @@ macro_rules! cur { Some(c) => Ok(c), None => { if $required { - let err = ::swc_common::errors::DiagnosticBuilder::from($crate::error::Eof { - last, - handler: &$p.session.handler, - }); + let err = crate::error::Error { + span: last, + error: Box::new(crate::error::SyntaxError::Eof), + }; return Err(err.into()); } - Err($crate::error::Eof { - last, - handler: &$p.session.handler, + Err(crate::error::Error { + span: last, + error: Box::new(crate::error::SyntaxError::Eof), }) } } @@ -237,11 +235,10 @@ Current token is {:?}", match $p.input.peek() { Some(c) => Ok(c), None => { - let err = ::swc_common::errors::DiagnosticBuilder::from($crate::error::Eof { - //TODO: Use whole span - last, - handler: &$p.session.handler, - }); + let err = crate::error::Error { + span: last, + error: Box::new(crate::error::SyntaxError::Eof), + }; Err(err) } } @@ -312,11 +309,10 @@ macro_rules! span { macro_rules! make_error { ($p:expr, $span:expr, $err:expr) => {{ - ::swc_common::errors::DiagnosticBuilder::from($crate::error::ErrorToDiag { - handler: $p.session.handler, + crate::error::Error { span: $span, - error: $err, - }) + error: Box::new($err), + } }}; } diff --git a/ecmascript/parser/src/parser/mod.rs b/ecmascript/parser/src/parser/mod.rs index 677186ada39..58121c818d9 100644 --- a/ecmascript/parser/src/parser/mod.rs +++ b/ecmascript/parser/src/parser/mod.rs @@ -3,18 +3,19 @@ pub use self::input::{Capturing, Tokens, TokensInput}; use self::{input::Buffer, util::ParseObject}; use crate::{ - error::{ErrorToDiag, SyntaxError}, + error::SyntaxError, lexer::Lexer, token::{Token, Word}, - Context, JscTarget, Session, Syntax, + Context, JscTarget, Syntax, }; use std::ops::{Deref, DerefMut}; use swc_atoms::JsWord; -use swc_common::{comments::Comments, errors::DiagnosticBuilder, input::Input, BytePos, Span}; +use swc_common::{comments::Comments, input::Input, BytePos, Span}; use swc_ecma_ast::*; use swc_ecma_parser_macros::parser; #[cfg(test)] extern crate test; +use crate::error::Error; #[cfg(test)] use test::Bencher; @@ -32,14 +33,13 @@ mod typescript; mod util; /// When error occurs, error is emitted and parser returns Err(()). -pub type PResult<'a, T> = Result>; +pub type PResult = Result; /// EcmaScript parser. #[derive(Clone)] -pub struct Parser<'a, I: Tokens> { +pub struct Parser { /// [false] while backtracking emit_err: bool, - session: Session<'a>, state: State, input: Buffer, } @@ -51,37 +51,31 @@ struct State { potential_arrow_start: Option, } -impl<'a, I: Input> Parser<'a, Lexer<'a, I>> { - // #[deprecated(since = "0.12.3", note = "Please use new_from instead")] - pub fn new( - session: Session<'a>, - syntax: Syntax, - input: I, - comments: Option<&'a Comments>, - ) -> Self { - Self::new_from( - session, - Lexer::new(session, syntax, Default::default(), input, comments), - ) +impl<'a, I: Input> Parser> { + pub fn new(syntax: Syntax, input: I, comments: Option<&'a Comments>) -> Self { + Self::new_from(Lexer::new(syntax, Default::default(), input, comments)) } } #[parser] -impl<'a, I: Tokens> Parser<'a, I> { - pub fn new_from(session: Session<'a>, input: I) -> Self { +impl Parser { + pub fn new_from(input: I) -> Self { Parser { emit_err: true, - session, input: Buffer::new(input), state: Default::default(), } } + pub fn take_errors(&mut self) -> Vec { + self.input().take_errors() + } + pub(crate) fn target(&self) -> JscTarget { self.input.target() } - pub fn parse_script(&mut self) -> PResult<'a, Script> { + pub fn parse_script(&mut self) -> PResult