refactor(ast,parser): use u32 for node spans

The next PR will fix the jargon where Node = Span.

relates to #9
This commit is contained in:
Boshen 2023-02-21 14:26:11 +08:00
parent 39a05030d7
commit a733856536
20 changed files with 260 additions and 237 deletions

1
Cargo.lock generated
View file

@ -537,6 +537,7 @@ version = "0.0.0"
dependencies = [
"bitflags",
"compact_str",
"miette",
"num-bigint",
"ordered-float",
"oxc_allocator",

View file

@ -17,6 +17,7 @@ compact_str = { workspace = true, features = ["serde"] }
thiserror = { workspace = true }
serde = { workspace = true, features = ["derive"] }
serde_json = { workspace = true, optional = true }
miette = { workspace = true }
num-bigint = "0.4.3"
ryu-js = "0.2.2"

View file

@ -3,29 +3,40 @@ use std::{
ops::Range,
};
use miette::{SourceOffset, SourceSpan};
use serde::Serialize;
#[allow(clippy::wildcard_imports)]
use crate::ast::*;
pub type Span = Range<usize>;
pub type Span = Range<u32>;
#[derive(Debug, Default, Clone, Copy, Serialize, PartialEq, Eq)]
pub struct Node {
pub start: usize,
pub end: usize,
pub start: u32,
pub end: u32,
}
impl Node {
#[must_use]
#[inline]
pub const fn new(start: usize, end: usize) -> Self {
pub const fn new(start: u32, end: u32) -> Self {
Self { start, end }
}
#[must_use]
pub const fn range(&self) -> Span {
self.start..self.end
(self.start)..(self.end)
}
#[must_use]
pub const fn len(&self) -> u32 {
self.end - self.start
}
#[must_use]
pub const fn is_empty(&self) -> bool {
self.len() == 0
}
}
@ -36,6 +47,12 @@ impl Hash for Node {
}
}
impl From<Node> for SourceSpan {
fn from(val: Node) -> Self {
Self::new(SourceOffset::from(val.start as usize), SourceOffset::from(val.len() as usize))
}
}
pub trait GetNode {
#[must_use]
fn node(&self) -> Node;

View file

@ -2,7 +2,7 @@
use std::{cell::RefCell, ops::Deref, rc::Rc};
use oxc_ast::{Atom, Span};
use oxc_ast::{Atom, Node};
use thiserror::Error;
pub type Result<T> = std::result::Result<T, Diagnostic>;
@ -30,120 +30,120 @@ impl Diagnostics {
pub enum Diagnostic {
#[error("This file panicked")]
#[diagnostic()]
Panic(#[label("")] Span),
Panic(#[label("")] Node),
#[error("Flow is not supported")]
#[diagnostic()]
Flow(#[label("")] Span),
Flow(#[label("")] Node),
/* Lexer */
#[error("Syntax Error")]
#[diagnostic()]
UnexpectedToken(#[label("Unexpected Token")] Span),
UnexpectedToken(#[label("Unexpected Token")] Node),
#[error("Syntax Error")]
#[diagnostic()]
ExpectToken(&'static str, &'static str, #[label("Expect `{0}` here, but found `{1}`")] Span),
ExpectToken(&'static str, &'static str, #[label("Expect `{0}` here, but found `{1}`")] Node),
#[error("Invalid escape sequence")]
InvalidEscapeSequence(#[label("Invalid escape sequence")] Span),
InvalidEscapeSequence(#[label("Invalid escape sequence")] Node),
#[error("Invalid escape sequence")]
NonOctalDecimalEscapeSequence(#[label("\\8 and \\9 are not allowed in strict mode")] Span),
NonOctalDecimalEscapeSequence(#[label("\\8 and \\9 are not allowed in strict mode")] Node),
#[error("Invalid Unicode escape sequence")]
UnicodeEscapeSequence(#[label("Invalid Unicode escape sequence")] Span),
UnicodeEscapeSequence(#[label("Invalid Unicode escape sequence")] Node),
#[error("Invalid Character `{0}`")]
InvalidCharacter(char, #[label("Invalid Character `{0}`")] Span),
InvalidCharacter(char, #[label("Invalid Character `{0}`")] Node),
#[error("Invalid characters after number")]
InvalidNumberEnd(#[label("Invalid characters after number")] Span),
InvalidNumberEnd(#[label("Invalid characters after number")] Node),
#[error("Unterminated multiLine comment")]
UnterminatedMultiLineComment(#[label("Unterminated multiLine comment")] Span),
UnterminatedMultiLineComment(#[label("Unterminated multiLine comment")] Node),
#[error("Unterminated string")]
UnterminatedString(#[label("Unterminated string")] Span),
UnterminatedString(#[label("Unterminated string")] Node),
#[error("Unexpected flag {0} in regular expression literal")]
RegExpFlag(char, #[label("Unexpected flag {0} in regular expression literal")] Span),
RegExpFlag(char, #[label("Unexpected flag {0} in regular expression literal")] Node),
#[error("Flag {0} is mentioned twice in regular expression literal")]
RegExpFlagTwice(
char,
#[label("Flag {0} is mentioned twice in regular expression literal")] Span,
#[label("Flag {0} is mentioned twice in regular expression literal")] Node,
),
#[error("The 'u' and 'v' regular expression flags cannot be enabled at the same time")]
RegExpFlagUAndV(
#[label("The 'u' and 'v' regular expression flags cannot be enabled at the same time")]
Span,
Node,
),
#[error("Unexpected end of file")]
UnexpectedEnd(#[label("Unexpected end of file")] Span),
UnexpectedEnd(#[label("Unexpected end of file")] Node),
#[error("Unterminated regular expression")]
UnterminatedRegExp(#[label("Unterminated regular expression")] Span),
UnterminatedRegExp(#[label("Unterminated regular expression")] Node),
#[error("Invalid Number")]
InvalidNumber(&'static str, #[label("{0}")] Span),
InvalidNumber(&'static str, #[label("{0}")] Node),
#[error("Keywords cannot contain escape characters")]
#[diagnostic()]
EscapedKeyword(#[label("keyword cannot contain escape characters")] Span),
EscapedKeyword(#[label("keyword cannot contain escape characters")] Node),
/* Syntax Errors */
#[error("Automatic Semicolon Insertion")]
#[diagnostic(help("Try insert a semicolon here"))]
AutoSemicolonInsertion(
#[label("Expected a semicolon or an implicit semicolon after a statement, but found none")]
Span,
Node,
),
#[error("Octal literals are not allowed in strict mode")]
#[diagnostic(help("for octal literals use the '0o' prefix instead"))]
LegacyOctal(
#[label("'0'-prefixed octal literals and octal escape sequences are deprecated")] Span,
#[label("'0'-prefixed octal literals and octal escape sequences are deprecated")] Node,
),
#[error("Decimals with leading zeros are not allowed in strict mode")]
#[diagnostic(help("remove the leading zero"))]
LeadingZeroDecimal(#[label("Decimals with leading zeros are not allowed in strict mode")] Span),
LeadingZeroDecimal(#[label("Decimals with leading zeros are not allowed in strict mode")] Node),
#[error("Line terminator not permitted before arrow")]
#[diagnostic()]
LineterminatorBeforeArrow(#[label("Line terminator not permitted before arrow")] Span),
LineterminatorBeforeArrow(#[label("Line terminator not permitted before arrow")] Node),
#[error("Unexpected new.target expression")]
#[diagnostic(help(
"new.target is only allowed in constructors and functions invoked using thew `new` operator"
))]
NewTarget(#[label("new.target expression is not allowed here")] Span),
NewTarget(#[label("new.target expression is not allowed here")] Node),
#[error("The only valid meta property for new is new.target")]
#[diagnostic()]
NewTargetProperty(#[label("The only valid meta property for new is new.target")] Span),
NewTargetProperty(#[label("The only valid meta property for new is new.target")] Node),
#[error("Unexpected import.meta expression")]
#[diagnostic(help("import.meta is only allowed in module code"))]
ImportMeta(#[label("import.meta expression is not allowed here")] Span),
ImportMeta(#[label("import.meta expression is not allowed here")] Node),
#[error("The only valid meta property for import is import.meta")]
#[diagnostic()]
ImportMetaProperty(#[label("The only valid meta property for import is import.meta")] Span),
ImportMetaProperty(#[label("The only valid meta property for import is import.meta")] Node),
#[error("Illegal break statement")]
#[diagnostic(help(
"A `break` statement can only be used within an enclosing iteration or switch statement."
))]
InvalidBreak(#[label("break statement is not allowed here")] Span),
InvalidBreak(#[label("break statement is not allowed here")] Node),
#[error("Illegal continue statement: no surrounding iteration statement")]
#[diagnostic(help(
"A `continue` statement can only be used within an enclosing `for`, `while` or `do while` "
))]
InvalidContinue(#[label("continue statement is not allowed here")] Span),
InvalidContinue(#[label("continue statement is not allowed here")] Node),
#[error(
"A `{0}` statement can only jump to a label of an enclosing `for`, `while` or `do while` statement."
@ -151,349 +151,349 @@ pub enum Diagnostic {
#[diagnostic()]
InvalidLabelNonIteration(
&'static str,
#[label("This is an non-iteration statement")] Span,
#[label("for this label")] Span,
#[label("This is an non-iteration statement")] Node,
#[label("for this label")] Node,
),
#[error("Use of undefined label")]
#[diagnostic()]
InvalidLabelTarget(#[label("This label is used, but not defined")] Span),
InvalidLabelTarget(#[label("This label is used, but not defined")] Node),
#[error("Jump target cannot cross function boundary.")]
#[diagnostic()]
InvalidLabelJumpTarget(#[label("Jump target cannot cross function boundary.")] Span),
InvalidLabelJumpTarget(#[label("Jump target cannot cross function boundary.")] Node),
#[error("Unexpected '{0}' strict mode")]
#[diagnostic()]
UnexpectedIdentifierAssign(Atom, #[label("Cannot assign to '{0}' in strict mode")] Span),
UnexpectedIdentifierAssign(Atom, #[label("Cannot assign to '{0}' in strict mode")] Node),
#[error("Invalid left-hand side in assignment")]
#[diagnostic()]
UnexpectedLhsAssign(#[label("Invalid left-hand side in assignment")] Span),
UnexpectedLhsAssign(#[label("Invalid left-hand side in assignment")] Node),
#[error("The keyword '{0}' is reserved")]
#[diagnostic()]
ReservedKeyword(Atom, #[label("{0} is reserved")] Span),
ReservedKeyword(Atom, #[label("{0} is reserved")] Node),
#[error("Identifier `{0}` has already been declared")]
#[diagnostic()]
Redeclaration(
Atom,
#[label("`{0}` has already been declared here")] Span,
#[label("It can not be redeclared here")] Span,
#[label("`{0}` has already been declared here")] Node,
#[label("It can not be redeclared here")] Node,
),
#[error("{0} is disallowed as a lexically bound name")]
#[diagnostic()]
DisallowedLexicalName(Atom, #[label("{0} is disallowed as a lexically bound name")] Span),
DisallowedLexicalName(Atom, #[label("{0} is disallowed as a lexically bound name")] Node),
#[error("`let` cannot be declared as a variable name inside of a `{0}` declaration")]
#[diagnostic()]
InvalidLetDeclaration(String, #[label("Rename the let identifier here")] Span),
InvalidLetDeclaration(String, #[label("Rename the let identifier here")] Node),
#[error("Missing initializer in destructuring declaration")]
#[diagnostic()]
InvalidDestrucuringDeclaration(
#[label("Missing initializer in destructuring declaration")] Span,
#[label("Missing initializer in destructuring declaration")] Node,
),
#[error("Missing initializer in const declaration")]
#[diagnostic()]
MissinginitializerInConst(#[label("const declaration need an initializer")] Span),
MissinginitializerInConst(#[label("const declaration need an initializer")] Node),
#[error("Functions cannot be labelled")]
#[diagnostic(help("This is not allowed in strict mode starting with ECMAScript 2015."))]
FunctionsCannotBeLabelled(#[label("Functions cannot be labelled")] Span),
FunctionsCannotBeLabelled(#[label("Functions cannot be labelled")] Node),
#[error("Cannot use {0} outside a method")]
MethodCode(&'static str, #[label("Cannot use {0} outside a method")] Span),
MethodCode(&'static str, #[label("Cannot use {0} outside a method")] Node),
#[error("Cannot use {0} outside a module")]
#[diagnostic()]
ModuleCode(&'static str, #[label("Cannot use {0} outside a module")] Span),
ModuleCode(&'static str, #[label("Cannot use {0} outside a module")] Node),
#[error("Lexical declaration cannot appear in a single-statement context")]
#[diagnostic(help("Wrap this declaration in a block statement"))]
LexicalDeclarationSingleStatement(#[label("Lexical declaration is not allowed here")] Span),
LexicalDeclarationSingleStatement(#[label("Lexical declaration is not allowed here")] Node),
#[error("Invalid function declaration")]
#[diagnostic(help(
"In strict mode code, functions can only be declared at top level or inside a block"
))]
FunctionDeclarationStrict(#[label("function declaration is not allowed here")] Span),
FunctionDeclarationStrict(#[label("function declaration is not allowed here")] Node),
#[error("Async functions can only be declared at the top level or inside a block")]
#[diagnostic()]
AsyncFunctionDeclaration(
#[label("Async functions can only be declared at the top level or inside a block")] Span,
#[label("Async functions can only be declared at the top level or inside a block")] Node,
),
#[error("Generators can only be declared at the top level or inside a block")]
#[diagnostic()]
GeneratorFunctionDeclaration(
#[label("Generators can only be declared at the top level or inside a block")] Span,
#[label("Generators can only be declared at the top level or inside a block")] Node,
),
#[error("Invalid function declaration")]
#[diagnostic(help(
"In non-strict mode code, functions can only be declared at top level, inside a block, or as the body of an if statement"
))]
FunctionDeclarationNonStrict(#[label("function declaration is not allowed here")] Span),
FunctionDeclarationNonStrict(#[label("function declaration is not allowed here")] Node),
#[error("`await` is only allowed within async functions and at the top levels of modules")]
#[diagnostic()]
AwaitExpression(
#[label("`await` is only allowed within async functions and at the top levels of modules")]
Span,
Node,
),
#[error("A 'yield' expression is only allowed in a generator body.")]
#[diagnostic()]
YieldExpression(#[label("A 'yield' expression is only allowed in a generator body.")] Span),
YieldExpression(#[label("A 'yield' expression is only allowed in a generator body.")] Node),
#[error("Invalid class declaration")]
#[diagnostic()]
ClassDeclaration(#[label("Classes can only be declared at top level or inside a block")] Span),
ClassDeclaration(#[label("Classes can only be declared at top level or inside a block")] Node),
#[error("Rest element must be last element")]
#[diagnostic()]
RestElement(#[label("Rest element must be last element")] Span),
RestElement(#[label("Rest element must be last element")] Node),
#[error("Spread must be last element")]
#[diagnostic()]
SpreadLastElement(#[label("Spread must be last element")] Span),
SpreadLastElement(#[label("Spread must be last element")] Node),
#[error("Unexpected trailing comma after rest element")]
#[diagnostic()]
RestElementTraillingComma(#[label("Unexpected trailing comma after rest element")] Span),
RestElementTraillingComma(#[label("Unexpected trailing comma after rest element")] Node),
#[error("Invalid rest argument")]
#[diagnostic(help("Expected identifier in rest argument"))]
InvalidRestArgument(#[label("Invalid rest argument")] Span),
InvalidRestArgument(#[label("Invalid rest argument")] Node),
#[error("Invalid parenthesized parameter")]
#[diagnostic(help("remove the parentheses"))]
InvalidParenthesizedParameter(#[label("Invliad parenthesized parameter")] Span),
InvalidParenthesizedParameter(#[label("Invliad parenthesized parameter")] Node),
#[error("Invalid parenthesized pattern")]
#[diagnostic()]
InvalidParenthesizedPattern(#[label("Invliad parenthesized pattern")] Span),
InvalidParenthesizedPattern(#[label("Invliad parenthesized pattern")] Node),
#[error("Invalid assignment")]
#[diagnostic()]
InvalidAssignment(#[label("Cannot assign to this expression")] Span),
InvalidAssignment(#[label("Cannot assign to this expression")] Node),
#[error("Optional chaining cannot appear in the callee of new expressions")]
#[diagnostic()]
NewOptionalChain(
#[label("Optional chaining cannot appear in the callee of new expressions")] Span,
#[label("Optional chaining cannot appear in the callee of new expressions")] Node,
),
#[error("The left-hand side of a `for...of` statement may not be `async`")]
#[diagnostic()]
ForLoopAsyncOf(
#[label("The left-hand side of a `for...of` statement may not be `async`")] Span,
#[label("The left-hand side of a `for...of` statement may not be `async`")] Node,
),
#[error("await can only be used in conjunction with `for...of` statements")]
#[diagnostic()]
ForAwait(#[label("await can only be used in conjunction with `for...of` statements")] Span),
ForAwait(#[label("await can only be used in conjunction with `for...of` statements")] Node),
#[error("Cannot use new with dynamic import")]
#[diagnostic()]
NewDynamicImport(#[label("Cannot use new with dynamic import")] Span),
NewDynamicImport(#[label("Cannot use new with dynamic import")] Node),
#[error("'{0}' declaration can only be used at the top level of a module")]
#[diagnostic()]
TopLevel(&'static str, #[label("'{0}' declaration can only appear at the top level")] Span),
TopLevel(&'static str, #[label("'{0}' declaration can only appear at the top level")] Node),
#[error("Duplicated export '{0}'")]
#[diagnostic()]
DuplicateExport(
Atom,
#[label("Export has already been declared here")] Span,
#[label("It cannot be redeclared here")] Span,
#[label("Export has already been declared here")] Node,
#[label("It cannot be redeclared here")] Node,
),
#[error("Unexpected private field")]
#[diagnostic(help(
"Private names are only allowed in property accesses (`obj.#field`) or in `in` expressions (`#field in obj`)."
))]
UnexpectedPrivateIdentifier(#[label("Unexpected private field")] Span),
UnexpectedPrivateIdentifier(#[label("Unexpected private field")] Node),
#[error("Classes can't have an element named '#constructor'")]
#[diagnostic()]
PrivateNameConstructor(#[label("Classes can't have an element named '#constructor'")] Span),
PrivateNameConstructor(#[label("Classes can't have an element named '#constructor'")] Node),
#[error("Private field '{0}' must be declared in an enclosing class")]
#[diagnostic()]
PrivateFieldUndeclared(
Atom,
#[label("Private field '{0}' must be declared in an enclosing class")] Span,
#[label("Private field '{0}' must be declared in an enclosing class")] Node,
),
#[error("Unexpected private identifier")]
#[diagnostic()]
PrivateNotInClass(
Atom,
#[label("Private identifier '#{0}' is not allowed outside class bodies")] Span,
#[label("Private identifier '#{0}' is not allowed outside class bodies")] Node,
),
#[error("Classes may not have a static property named prototype")]
#[diagnostic()]
StaticPrototype(#[label("Classes may not have a static property named prototype")] Span),
StaticPrototype(#[label("Classes may not have a static property named prototype")] Node),
#[error("Constructor can't have get/set modifier")]
#[diagnostic()]
ConstructorGetterSetter(#[label("Constructor can't have get/set modifier")] Span),
ConstructorGetterSetter(#[label("Constructor can't have get/set modifier")] Node),
#[error("Constructor can't be an async method")]
#[diagnostic()]
ConstructorAsync(#[label("Constructor can't be an async method")] Span),
ConstructorAsync(#[label("Constructor can't be an async method")] Node),
#[error("Cannot use `{0}` as an identifier in an async context")]
#[diagnostic()]
IdentifierAsync(&'static str, #[label("{0} cannot be used here")] Span),
IdentifierAsync(&'static str, #[label("{0} cannot be used here")] Node),
#[error("Cannot use `{0}` as an identifier in a generator context")]
#[diagnostic()]
IdentifierGenerator(&'static str, #[label("{0} cannot be used here")] Span),
IdentifierGenerator(&'static str, #[label("{0} cannot be used here")] Node),
#[error("Constructor can't be a generator")]
#[diagnostic()]
ConstructorGenerator(#[label("Constructor can't be a generator")] Span),
ConstructorGenerator(#[label("Constructor can't be a generator")] Node),
#[error("Classes can't have a field named 'constructor'")]
#[diagnostic()]
FieldConstructor(#[label("Classes can't have a field named 'constructor'")] Span),
FieldConstructor(#[label("Classes can't have a field named 'constructor'")] Node),
#[error("Multiple constructor implementations are not allowed.")]
#[diagnostic()]
DuplicateConstructor(
#[label("constructor has already been declared here")] Span,
#[label("it cannot be redeclared here")] Span,
#[label("constructor has already been declared here")] Node,
#[label("it cannot be redeclared here")] Node,
),
#[error("An export name cannot include a unicode lone surrogate")]
#[diagnostic()]
ExportLoneSurrogate(#[label("An export name cannot include a unicode lone surrogate")] Span),
ExportLoneSurrogate(#[label("An export name cannot include a unicode lone surrogate")] Node),
#[error("A string literal cannot be used as an exported binding without `from`")]
#[diagnostic(help("Did you mean `export {{ '{0}' as '{1}' }} from 'some-module'`?"))]
ExportNamedString(
Atom,
Atom,
#[label("A string literal cannot be used as an exported binding without `from`")] Span,
#[label("A string literal cannot be used as an exported binding without `from`")] Node,
),
#[error("Bad escape sequence in untagged template literal")]
#[diagnostic()]
TemplateLiteral(#[label("Bad escape sequence in untagged template literal")] Span),
TemplateLiteral(#[label("Bad escape sequence in untagged template literal")] Node),
#[error("Delete of an unqualified identifier in strict mode.")]
#[diagnostic()]
DeleteOfUnqualified(#[label("Delete of an unqualified identifier in strict mode")] Span),
DeleteOfUnqualified(#[label("Delete of an unqualified identifier in strict mode")] Node),
#[error("'with' statements are not allowed")]
#[diagnostic()]
WithStatement(#[label("'with' statements are not allowed")] Span),
WithStatement(#[label("'with' statements are not allowed")] Node),
#[error("Private fields can not be deleted")]
#[diagnostic()]
DeletePrivateField(#[label("Private fields can not be deleted")] Span),
DeletePrivateField(#[label("Private fields can not be deleted")] Node),
#[error("Empty parenthesized expression")]
#[diagnostic()]
EmptyParenthesizedExpression(#[label("Expected an expression here")] Span),
EmptyParenthesizedExpression(#[label("Expected an expression here")] Node),
#[error("Undefined export")]
#[diagnostic()]
UndefinedExport(Atom, #[label("Export '{0}' is not defined")] Span),
UndefinedExport(Atom, #[label("Export '{0}' is not defined")] Node),
#[error("Logical expressions and coalesce expressions cannot be mixed")]
#[diagnostic(help("Wrap either expression by parentheses"))]
MixedCoalesce(#[label("Logical expressions and coalesce expressions cannot be mixed")] Span),
MixedCoalesce(#[label("Logical expressions and coalesce expressions cannot be mixed")] Node),
#[error("'Unexpected `{0}`")]
#[diagnostic()]
UnexpectedKeyword(&'static str, #[label("'{0}' keyword is unexpected here")] Span),
UnexpectedKeyword(&'static str, #[label("'{0}' keyword is unexpected here")] Node),
#[error("{0} loop variable declaration may not have an initializer")]
#[diagnostic()]
UnexpectedInitializerInForLoopHead(
&'static str,
#[label("{0} loop variable declaration may not have an initializer")] Span,
#[label("{0} loop variable declaration may not have an initializer")] Node,
),
#[error("Only a single declaration is allowed in a `for...{0}` statement")]
#[diagnostic()]
MultipleDeclarationInForLoopHead(
&'static str,
#[label("Only a single declaration is allowed in a `for...{0}` statement")] Span,
#[label("Only a single declaration is allowed in a `for...{0}` statement")] Node,
),
#[error("Illegal newline after {0}")]
#[diagnostic()]
IllegalNewline(
&'static str,
#[label("{0} starts here")] Span,
#[label("A newline is not expected here")] Span,
#[label("{0} starts here")] Node,
#[label("A newline is not expected here")] Node,
),
#[error("Duplicate parameter name not allowed in this context")]
#[diagnostic()]
DuplicateParameter(#[label("Duplicate parameter name not allowed in this context")] Span),
DuplicateParameter(#[label("Duplicate parameter name not allowed in this context")] Node),
#[error("Illegal 'use strict' directive in function with non-simple parameter list")]
#[diagnostic()]
IllegalUseStrict(
#[label("Illegal 'use strict' directive in function with non-simple parameter list")] Span,
#[label("Illegal 'use strict' directive in function with non-simple parameter list")] Node,
),
#[error("'arguments' is not allowed in {0}")]
#[diagnostic()]
UnexpectedArguments(&'static str, #[label("'arguments' is not allowed in {0}")] Span),
UnexpectedArguments(&'static str, #[label("'arguments' is not allowed in {0}")] Node),
#[error("Unexpected {0} expression")]
#[diagnostic()]
UnexpectedExpression(&'static str, #[label("Unexpected {0} expression")] Span),
UnexpectedExpression(&'static str, #[label("Unexpected {0} expression")] Node),
#[error("Unexpected exponentiation expression")]
#[diagnostic(help("Wrap {0} expression in parentheses to enforce operator precedence"))]
UnexpectedExponential(&'static str, #[label("Unexpected exponentiation expression")] Span),
UnexpectedExponential(&'static str, #[label("Unexpected exponentiation expression")] Node),
#[error("Tagged template expressions are not permitted in an optional chain")]
#[diagnostic()]
OptionalChainTaggedTemplate(
#[label("Tagged template expressions are not permitted in an optional chain")] Span,
#[label("Tagged template expressions are not permitted in an optional chain")] Node,
),
#[error("A 'get' accessor must not have any formal parameters.")]
#[diagnostic()]
GetterParameters(#[label("A 'get' accessor must not have any formal parameters.")] Span),
GetterParameters(#[label("A 'get' accessor must not have any formal parameters.")] Node),
#[error("A 'set' accessor must have exactly one parameter.")]
#[diagnostic()]
SetterParameters(#[label("A 'set' accessor must have exactly one parameter.")] Span),
SetterParameters(#[label("A 'set' accessor must have exactly one parameter.")] Node),
#[error("A 'set' accessor function argument must not be a rest parameter")]
#[diagnostic()]
SetterParametersRestPattern(
#[label("A 'set' accessor function argument must not be a rest parameter")] Span,
#[label("A 'set' accessor function argument must not be a rest parameter")] Node,
),
#[error("{0} expression not allowed in formal parameter")]
#[diagnostic()]
AwaitOrYieldInParameter(
&'static str,
#[label("{0} expression not allowed in formal parameter")] Span,
#[label("{0} expression not allowed in formal parameter")] Node,
),
#[error("Invalid assignment in object literal")]
#[diagnostic(help(
"Did you mean to use a ':'? An '=' can only follow a property name when the containing object literal is part of a destructuring pattern."
))]
CoverInitializedNameError(#[label("Assignment is not allowed here")] Span),
CoverInitializedNameError(#[label("Assignment is not allowed here")] Node),
#[error("Super calls are not permitted outside constructors or in nested functions inside constructors.
")]
@ -502,7 +502,7 @@ pub enum Diagnostic {
#[label(
"Super calls are not permitted outside constructors or in nested functions inside constructors."
)]
Span,
Node,
),
#[error("'super' can only be referenced in members of derived classes or object literal expressions.
@ -511,98 +511,98 @@ pub enum Diagnostic {
UnexpectedSuperReference(
#[label("'super' can only be referenced in members of derived classes or object literal expressions.
")]
Span,
Node,
),
#[error("'super' can only be used with function calls or in property accesses")]
#[diagnostic(help("replace with `super()` or `super.prop` or `super[prop]`"))]
UnexpectedSuper(
#[label("'super' can only be used with function calls or in property accesses ")] Span,
#[label("'super' can only be used with function calls or in property accesses ")] Node,
),
#[error("'super' can only be referenced in a derived class.")]
#[diagnostic(help("either remove this super, or extend the class"))]
SuperWithoutDerivedClass(
#[label("'super' can only be referenced in a derived class.")] Span,
#[label("class does not have `extends`")] Span,
#[label("'super' can only be referenced in a derived class.")] Node,
#[label("class does not have `extends`")] Node,
),
#[error("Private fields cannot be accessed on super")]
#[diagnostic()]
SuperPrivate(#[label("Private fields cannot be accessed on super")] Span),
SuperPrivate(#[label("Private fields cannot be accessed on super")] Node),
#[error("Expected function name")]
#[diagnostic(help("Function name is required in function declaration or named export"))]
ExpectFunctionName(#[label("Function name is required here")] Span),
ExpectFunctionName(#[label("Function name is required here")] Node),
#[error("Missing catch or finally clause")]
#[diagnostic()]
ExpectCatchFinally(#[label("Expected `catch` or `finally` here")] Span),
ExpectCatchFinally(#[label("Expected `catch` or `finally` here")] Node),
#[error("Cannot assign to '{0}' because it is a {1}")]
#[diagnostic()]
CannotAssignTo(
Atom,
&'static str,
#[label("Cannot assign to '{0}' because this is a {1}")] Span,
#[label("Cannot assign to '{0}' because this is a {1}")] Node,
),
#[error("A rest parameter cannot have an initializer")]
#[diagnostic()]
ARestParameterCannotHaveAnInitializer(
#[label("A rest parameter cannot have an initializer")] Span,
#[label("A rest parameter cannot have an initializer")] Node,
),
/* TypeScript */
#[error("TS1015: Parameter cannot have question mark and initializer")]
#[diagnostic()]
ParameterCannotHaveQuestionMarkAndInitializer(
#[label("Parameter cannot have question mark and initializer")] Span,
#[label("Parameter cannot have question mark and initializer")] Node,
),
#[error("TS1047: A rest parameter cannot be optional")]
#[diagnostic()]
ARestParameterCannotBeOptional(#[label("A rest parameter cannot be optional")] Span),
ARestParameterCannotBeOptional(#[label("A rest parameter cannot be optional")] Node),
#[error("TS1095: A 'set' accessor cannot have a return type annotation")]
#[diagnostic()]
ASetAccessorCannotHaveAReturnTypeAnnotation(
#[label("A 'set' accessor cannot have a return type annotation")] Span,
#[label("A 'set' accessor cannot have a return type annotation")] Node,
),
#[error("TS1098: Type parameter list cannot be empty")]
#[diagnostic()]
TypeParameterListCannotBeEmpty(#[label("Type parameter list cannot be empty")] Span),
TypeParameterListCannotBeEmpty(#[label("Type parameter list cannot be empty")] Node),
#[error("TS1099: Type argument list cannot be empty")]
#[diagnostic()]
TypeArgumentListCannotBeEmpty(#[label("Type argument list cannot be empty")] Span),
TypeArgumentListCannotBeEmpty(#[label("Type argument list cannot be empty")] Node),
#[error("TS1108: A 'return' statement can only be used within a function body")]
#[diagnostic()]
ReturnStatementOnlyInFunctionBody(
#[label("A 'return' statement can only be used within a function body.")] Span,
#[label("A 'return' statement can only be used within a function body.")] Node,
),
#[error("TS1164: Computed property names are not allowed in enums")]
#[diagnostic()]
ComputedPropertyNamesAreNotAllowedInEnums(
#[label("Computed property names are not allowed in enums")] Span,
#[label("Computed property names are not allowed in enums")] Node,
),
#[error("TS1313: The body of an 'if' statement cannot be the empty statement")]
#[diagnostic()]
TheBodyOfAnIfStatementCannotBeTheEmptyStatement(
#[label("The body of an 'if' statement cannot be the empty statement")] Span,
#[label("The body of an 'if' statement cannot be the empty statement")] Node,
),
#[error("TS1317: A parameter property cannot be declared using a rest parameter")]
#[diagnostic()]
AParameterPropertyCannotBeDeclaredUsingARestParameter(
#[label("A parameter property cannot be declared using a rest parameter")] Span,
#[label("A parameter property cannot be declared using a rest parameter")] Node,
),
#[error("TS2452: An enum member cannot have a numeric name")]
#[diagnostic()]
AnEnumMemberCannotHaveANumericName(#[label("An enum member cannot have a numeric name")] Span),
AnEnumMemberCannotHaveANumericName(#[label("An enum member cannot have a numeric name")] Node),
}

View file

@ -9,7 +9,7 @@ use crate::Parser;
pub struct ParserCheckpoint<'a> {
lexer: LexerCheckpoint<'a>,
cur_token: Token,
prev_node_end: usize,
prev_node_end: u32,
errors_pos: usize,
}
@ -42,7 +42,8 @@ impl<'a> Parser<'a> {
/// Get current source text
#[must_use]
pub fn cur_src(&self) -> &'a str {
unsafe { self.source.get_unchecked(self.cur_token().range()) }
let range = self.cur_token().node().range();
unsafe { self.source.get_unchecked(range.start as usize..range.end as usize) }
}
/// Get current atom
@ -100,8 +101,8 @@ impl<'a> Parser<'a> {
// in IdentifierName hence such escapes cannot be used to write an Identifier
// whose code point sequence is the same as a ReservedWord.
if self.cur_token().escaped && kind.is_all_keyword() {
let range = self.cur_token().range();
self.error(Diagnostic::EscapedKeyword(range));
let node = self.cur_token().node();
self.error(Diagnostic::EscapedKeyword(node));
}
self.prev_token_end = self.token.end;
self.token = self.lexer.next_token();
@ -139,8 +140,8 @@ impl<'a> Parser<'a> {
/// # Errors
pub fn asi(&mut self) -> Result<()> {
if !self.can_insert_semicolon() {
let range = self.prev_token_end..self.cur_token().start;
return Err(Diagnostic::AutoSemicolonInsertion(range));
let node = Node::new(self.prev_token_end, self.cur_token().start);
return Err(Diagnostic::AutoSemicolonInsertion(node));
}
if self.at(Kind::Semicolon) {
self.advance(Kind::Semicolon);
@ -169,17 +170,17 @@ impl<'a> Parser<'a> {
}
#[must_use]
pub const fn current_range(&self) -> std::ops::Range<usize> {
pub const fn current_range(&self) -> Node {
let cur_token = self.cur_token();
match self.cur_kind() {
Kind::Eof => {
if self.prev_token_end < cur_token.end {
self.prev_token_end..self.prev_token_end
Node::new(self.prev_token_end, self.prev_token_end)
} else {
self.prev_token_end - 1..self.prev_token_end
Node::new(self.prev_token_end - 1, self.prev_token_end)
}
}
_ => cur_token.range(),
_ => cur_token.node(),
}
}

View file

@ -57,9 +57,9 @@ impl<'a> Parser<'a> {
if self.at(Kind::Comma) {
let error = if self.peek_at(Kind::RBrack) {
Diagnostic::RestElementTraillingComma(self.cur_token().range())
Diagnostic::RestElementTraillingComma(self.cur_token().node())
} else {
Diagnostic::RestElement(node.range())
Diagnostic::RestElement(node)
};
self.error(error);
}

View file

@ -18,7 +18,10 @@ impl<'a> Parser<'a> {
let decl = self.parse_class_declaration(/* declare */ false)?;
if stmt_ctx.is_single_statement() {
self.error(Diagnostic::ClassDeclaration(decl.node.start..decl.body.node.start));
self.error(Diagnostic::ClassDeclaration(Node::new(
decl.node.start,
decl.body.node.start,
)));
}
Ok(self.ast.class_declaration(decl))
@ -238,7 +241,7 @@ impl<'a> Parser<'a> {
if let PropertyKey::PrivateIdentifier(private_ident) = &key {
if private_ident.name == "constructor" {
self.error(Diagnostic::PrivateNameConstructor(private_ident.node.range()));
self.error(Diagnostic::PrivateNameConstructor(private_ident.node));
}
}
@ -264,17 +267,17 @@ impl<'a> Parser<'a> {
)?;
if let Some((name, node)) = definition.prop_name() {
if r#static && name == "prototype" {
self.error(Diagnostic::StaticPrototype(node.range()));
self.error(Diagnostic::StaticPrototype(node));
}
if !r#static && name == "constructor" {
if kind == MethodDefinitionKind::Get || kind == MethodDefinitionKind::Set {
self.error(Diagnostic::ConstructorGetterSetter(node.range()));
self.error(Diagnostic::ConstructorGetterSetter(node));
}
if r#async {
self.error(Diagnostic::ConstructorAsync(node.range()));
self.error(Diagnostic::ConstructorAsync(node));
}
if generator {
self.error(Diagnostic::ConstructorGenerator(node.range()));
self.error(Diagnostic::ConstructorGenerator(node));
}
}
}
@ -295,10 +298,10 @@ impl<'a> Parser<'a> {
)?;
if let Some((name, node)) = definition.prop_name() {
if name == "constructor" {
self.error(Diagnostic::FieldConstructor(node.range()));
self.error(Diagnostic::FieldConstructor(node));
}
if r#static && name == "prototype" {
self.error(Diagnostic::StaticPrototype(node.range()));
self.error(Diagnostic::StaticPrototype(node));
}
}
Ok(definition)
@ -344,17 +347,17 @@ impl<'a> Parser<'a> {
let value = self.parse_method(r#async, generator)?;
if kind == MethodDefinitionKind::Get && !value.params.is_empty() {
self.error(Diagnostic::GetterParameters(value.params.node.range()));
self.error(Diagnostic::GetterParameters(value.params.node));
}
if kind == MethodDefinitionKind::Set {
if value.params.items.len() != 1 {
self.error(Diagnostic::SetterParameters(value.params.node.range()));
self.error(Diagnostic::SetterParameters(value.params.node));
}
if value.params.items.len() == 1 {
if let BindingPatternKind::RestElement(elem) = &value.params.items[0].pattern.kind {
self.error(Diagnostic::SetterParametersRestPattern(elem.node.range()));
self.error(Diagnostic::SetterParametersRestPattern(elem.node));
}
}
}

View file

@ -92,10 +92,10 @@ impl<'a> Parser<'a> {
// BindingPattern[?Yield, ?Await] Initializer[?In, ?Yield, ?Await]
// the grammar forbids `let []`, `let {}`
if !matches!(id.kind, BindingPatternKind::BindingIdentifier(_)) {
self.error(Diagnostic::InvalidDestrucuringDeclaration(id.node().range()));
self.error(Diagnostic::InvalidDestrucuringDeclaration(id.node()));
} else if kind == VariableDeclarationKind::Const && !self.ctx.has_ambient() {
// It is a Syntax Error if Initializer is not present and IsConstantDeclaration of the LexicalDeclaration containing this LexicalBinding is true.
self.error(Diagnostic::MissinginitializerInConst(id.node().range()));
self.error(Diagnostic::MissinginitializerInConst(id.node()));
}
}

View file

@ -191,7 +191,7 @@ impl<'a> Parser<'a> {
expressions.remove(0)
} else {
if expressions.is_empty() {
self.error(Diagnostic::EmptyParenthesizedExpression(list.node.range()));
self.error(Diagnostic::EmptyParenthesizedExpression(list.node));
}
self.ast.sequence_expression(list.node, expressions)
};
@ -376,7 +376,7 @@ impl<'a> Parser<'a> {
// It is a Syntax Error if any source text is matched by this production.
// https://tc39.es/ecma262/#sec-left-hand-side-expressions-static-semantics-early-errors
if in_optional_chain {
self.error(Diagnostic::OptionalChainTaggedTemplate(quasi.node.range()));
self.error(Diagnostic::OptionalChainTaggedTemplate(quasi.node));
}
Ok(self.ast.tagged_template_expression(node, lhs, quasi, type_parameters))
}
@ -384,7 +384,7 @@ impl<'a> Parser<'a> {
pub fn parse_template_element(&mut self, tagged: bool) -> TemplateElement {
let node = self.start_node();
let cur_kind = self.cur_kind();
let end_offset = match cur_kind {
let end_offset: u32 = match cur_kind {
Kind::TemplateHead | Kind::TemplateMiddle => 2,
Kind::NoSubstitutionTemplate | Kind::TemplateTail => 1,
_ => unreachable!(),
@ -393,7 +393,7 @@ impl<'a> Parser<'a> {
// cooked = None when template literal has invalid escape sequence
let cooked = self.cur_atom().map(Clone::clone);
let raw = &self.cur_src()[1..self.cur_src().len() - end_offset];
let raw = &self.cur_src()[1..self.cur_src().len() - end_offset as usize];
let raw = Atom::from(if cooked.is_some() && raw.contains('\r') {
self.ast.new_str(raw.replace("\r\n", "\n").replace('\r', "\n").as_str())
} else {
@ -407,7 +407,7 @@ impl<'a> Parser<'a> {
node.end -= end_offset;
if !tagged && cooked.is_none() {
self.error(Diagnostic::TemplateLiteral(node.range()));
self.error(Diagnostic::TemplateLiteral(node));
}
let tail = matches!(cur_kind, Kind::TemplateTail | Kind::NoSubstitutionTemplate);
@ -475,7 +475,7 @@ impl<'a> Parser<'a> {
// SuperCall:
// super ( Arguments )
if !matches!(self.cur_kind(), Kind::Dot | Kind::LBrack | Kind::LParen) {
self.error(Diagnostic::UnexpectedSuper(node.range()));
self.error(Diagnostic::UnexpectedSuper(node));
}
self.ast.super_(node)
@ -605,13 +605,13 @@ impl<'a> Parser<'a> {
};
if matches!(callee, Expression::ImportExpression(_)) {
self.error(Diagnostic::NewDynamicImport(self.end_node(rhs_node).range()));
self.error(Diagnostic::NewDynamicImport(self.end_node(rhs_node)));
}
let node = self.end_node(node);
if optional {
self.error(Diagnostic::NewOptionalChain(node.range()));
self.error(Diagnostic::NewOptionalChain(node));
}
Ok(self.ast.new_expression(node, callee, arguments, type_parameter))

View file

@ -155,13 +155,15 @@ impl<'a> Parser<'a> {
let decl = self.parse_function_impl(func_kind)?;
if stmt_ctx.is_single_statement() {
if decl.r#async {
self.error(Diagnostic::AsyncFunctionDeclaration(
decl.node.start..decl.params.node.end,
));
self.error(Diagnostic::AsyncFunctionDeclaration(Node::new(
decl.node.start,
decl.params.node.end,
)));
} else if decl.generator {
self.error(Diagnostic::GeneratorFunctionDeclaration(
decl.node.start..decl.params.node.end,
));
self.error(Diagnostic::GeneratorFunctionDeclaration(Node::new(
decl.node.start,
decl.params.node.end,
)));
}
}
@ -318,7 +320,7 @@ impl<'a> Parser<'a> {
self.ctx = ctx;
if kind.is_id_required() && id.is_none() {
self.error(Diagnostic::ExpectFunctionName(self.cur_token().range()));
self.error(Diagnostic::ExpectFunctionName(self.cur_token().node()));
}
id
@ -431,7 +433,7 @@ impl<'a> Parser<'a> {
self.ctx = self.ctx.and_await(has_await);
if self.cur_token().is_on_new_line {
self.error(Diagnostic::LineterminatorBeforeArrow(self.cur_token().range()));
self.error(Diagnostic::LineterminatorBeforeArrow(self.cur_token().node()));
}
self.expect(Kind::Arrow)?;

View file

@ -45,7 +45,7 @@ impl<'a> CoverGrammar<'a, Expression<'a>> for SimpleAssignmentTarget<'a> {
let node = expr.node;
match expr.unbox().expression {
Expression::ObjectExpression(_) | Expression::ArrayExpression(_) => {
Err(Diagnostic::InvalidAssignment(node.range()))
Err(Diagnostic::InvalidAssignment(node))
}
expr => SimpleAssignmentTarget::cover(expr, p),
}
@ -55,7 +55,7 @@ impl<'a> CoverGrammar<'a, Expression<'a>> for SimpleAssignmentTarget<'a> {
Ok(SimpleAssignmentTarget::TSNonNullExpression(expr))
}
Expression::TSTypeAssertion(expr) => Ok(SimpleAssignmentTarget::TSTypeAssertion(expr)),
expr => Err(Diagnostic::InvalidAssignment(expr.node().range())),
expr => Err(Diagnostic::InvalidAssignment(expr.node())),
}
}
}
@ -77,10 +77,10 @@ impl<'a> CoverGrammar<'a, ArrayExpression<'a>> for ArrayAssignmentTarget<'a> {
if i == len - 1 {
rest = Some(AssignmentTarget::cover(elem.unbox().argument, p)?);
if let Some(node) = expr.trailing_comma {
p.error(Diagnostic::RestElementTraillingComma(node.range()));
p.error(Diagnostic::RestElementTraillingComma(node));
}
} else {
return Err(Diagnostic::SpreadLastElement(elem.node.range()));
return Err(Diagnostic::SpreadLastElement(elem.node));
}
}
}
@ -135,7 +135,7 @@ impl<'a> CoverGrammar<'a, ObjectExpression<'a>> for ObjectAssignmentTarget<'a> {
if i == len - 1 {
rest = Some(AssignmentTarget::cover(spread.unbox().argument, p)?);
} else {
return Err(Diagnostic::SpreadLastElement(spread.node.range()));
return Err(Diagnostic::SpreadLastElement(spread.node));
}
}
}
@ -166,7 +166,7 @@ impl<'a> CoverGrammar<'a, Property<'a>> for AssignmentTargetProperty<'a> {
let binding = match property.value {
PropertyValue::Expression(expr) => AssignmentTargetMaybeDefault::cover(expr, p)?,
PropertyValue::Pattern(_) => {
return Err(Diagnostic::InvalidAssignment(property.value.node().range()));
return Err(Diagnostic::InvalidAssignment(property.value.node()));
}
};
let target = AssignmentTargetPropertyProperty {

View file

@ -65,7 +65,7 @@ impl<'a> SeparatedList<'a> for ObjectPatternProperties<'a> {
let rest_element = p.parse_rest_element()?;
if !matches!(rest_element.argument.kind, BindingPatternKind::BindingIdentifier(_)) {
p.error(Diagnostic::InvalidRestArgument(rest_element.node.range()));
p.error(Diagnostic::InvalidRestArgument(rest_element.node));
}
ObjectPatternProperty::RestElement(rest_element)
@ -291,7 +291,7 @@ impl<'a> SeparatedList<'a> for AssertEntries<'a> {
};
if let Some(old_node) = self.keys.get(&key.as_atom()) {
p.error(Diagnostic::Redeclaration(key.as_atom(), old_node.range(), key.node().range()));
p.error(Diagnostic::Redeclaration(key.as_atom(), *old_node, key.node()));
} else {
self.keys.insert(key.as_atom(), key.node());
}
@ -396,8 +396,8 @@ impl<'a> ClassElements<'a> {
{
p.error(Diagnostic::Redeclaration(
private_ident.name.clone(),
existed.node.range(),
private_ident.node.range(),
existed.node,
private_ident.node,
));
}
}

View file

@ -255,7 +255,7 @@ impl<'a> Parser<'a> {
self.error(Diagnostic::ExportNamedString(
literal.value.clone(),
specifier.local.name().clone(),
literal.node.range(),
literal.node,
));
}
}
@ -384,7 +384,7 @@ impl<'a> Parser<'a> {
// ModuleExportName : StringLiteral
// It is a Syntax Error if IsStringWellFormedUnicode(the SV of StringLiteral) is false.
if !literal.is_string_well_formed_unicode() {
self.error(Diagnostic::ExportLoneSurrogate(literal.node.range()));
self.error(Diagnostic::ExportLoneSurrogate(literal.node));
};
Ok(ModuleExportName::StringLiteral(literal))
}

View file

@ -216,7 +216,7 @@ impl<'a> Parser<'a> {
let method = self.parse_method(false, false)?;
if !method.params.is_empty() {
self.error(Diagnostic::GetterParameters(method.params.node.range()));
self.error(Diagnostic::GetterParameters(method.params.node));
}
let value = PropertyValue::Expression(self.ast.function_expression(method));
@ -240,12 +240,12 @@ impl<'a> Parser<'a> {
let method = self.parse_method(false, false)?;
if method.params.items.len() != 1 {
self.error(Diagnostic::SetterParameters(method.params.node.range()));
self.error(Diagnostic::SetterParameters(method.params.node));
}
if method.params.items.len() == 1 {
if let BindingPatternKind::RestElement(elem) = &method.params.items[0].pattern.kind {
self.error(Diagnostic::SetterParametersRestPattern(elem.node.range()));
self.error(Diagnostic::SetterParametersRestPattern(elem.node));
}
}

View file

@ -50,7 +50,8 @@ impl<'a> Parser<'a> {
if expecting_diretives {
if let Statement::ExpressionStatement(expr) = &stmt {
if let Expression::StringLiteral(string) = &expr.expression {
let src = &self.source[string.node.start + 1..string.node.end - 1];
let src = &self.source
[string.node.start as usize + 1..string.node.end as usize - 1];
let directive =
self.ast.directive(expr.node, (*string).clone(), src);
directives.push(directive);
@ -192,7 +193,7 @@ impl<'a> Parser<'a> {
))?;
if stmt_ctx.is_single_statement() && decl.kind.is_lexical() {
self.error(Diagnostic::LexicalDeclarationSingleStatement(decl.node.range()));
self.error(Diagnostic::LexicalDeclarationSingleStatement(decl.node));
}
Ok(Statement::Declaration(Declaration::VariableDeclaration(decl)))
@ -297,18 +298,15 @@ impl<'a> Parser<'a> {
// for (a.b in ...), for ([a] in ..), for ({a} in ..)
if self.at(Kind::In) || self.at(Kind::Of) {
let target = AssignmentTarget::cover(init_expression, self)
.map_err(|_| Diagnostic::UnexpectedToken(self.end_node(expression_node).range()))?;
.map_err(|_| Diagnostic::UnexpectedToken(self.end_node(expression_node)))?;
let for_stmt_left = ForStatementLeft::AssignmentTarget(target);
if !r#await && is_async_of {
self.error(Diagnostic::ForLoopAsyncOf(self.end_node(expression_node).range()));
self.error(Diagnostic::ForLoopAsyncOf(self.end_node(expression_node)));
}
if is_let_of {
self.error(Diagnostic::UnexpectedKeyword(
"let",
self.end_node(expression_node).range(),
));
self.error(Diagnostic::UnexpectedKeyword("let", self.end_node(expression_node)));
}
return self.parse_for_in_or_of_loop(node, r#await, for_stmt_left);
@ -330,7 +328,7 @@ impl<'a> Parser<'a> {
self.expect(Kind::RParen)?;
if r#await {
self.error(Diagnostic::ForAwait(self.end_node(node).range()));
self.error(Diagnostic::ForAwait(self.end_node(node)));
}
let body = self.parse_statement_list_item(StatementContext::For)?;
@ -354,7 +352,7 @@ impl<'a> Parser<'a> {
self.expect(Kind::RParen)?;
if r#await && is_for_in {
self.error(Diagnostic::ForAwait(self.end_node(node).range()));
self.error(Diagnostic::ForAwait(self.end_node(node)));
}
let body = self.parse_statement_list_item(StatementContext::For)?;
@ -454,8 +452,8 @@ impl<'a> Parser<'a> {
if self.cur_token().is_on_new_line {
self.error(Diagnostic::IllegalNewline(
"throw",
self.end_node(node).range(),
self.cur_token().range(),
self.end_node(node),
self.cur_token().node(),
));
}
let argument = self.parse_expression()?;
@ -474,8 +472,7 @@ impl<'a> Parser<'a> {
let finalizer = self.eat(Kind::Finally).then(|| self.parse_block()).transpose()?;
#[allow(clippy::range_plus_one)]
let range = self.prev_token_end..self.prev_token_end + 1;
let range = Node::new(self.prev_token_end, self.prev_token_end + 1);
if handler.is_none() && finalizer.is_none() {
self.error(Diagnostic::ExpectCatchFinally(range));
}

View file

@ -21,7 +21,7 @@ use constants::{
pub use kind::Kind;
use number::{parse_big_int, parse_float, parse_int};
use oxc_allocator::{Allocator, String};
use oxc_ast::{Atom, SourceType, Span};
use oxc_ast::{Atom, Node, SourceType};
use oxc_diagnostics::{Diagnostic, Diagnostics};
use simd::{SkipMultilineComment, SkipWhitespace};
use string_builder::AutoCow;
@ -205,7 +205,7 @@ impl<'a> Lexer<'a> {
}
/// Expand the current token for `JSXIdentifier`
pub fn next_jsx_identifier(&mut self, prev_len: usize) -> Token {
pub fn next_jsx_identifier(&mut self, prev_len: u32) -> Token {
let kind = self.read_jsx_identifier(prev_len);
self.lookahead.clear();
self.finish_next(kind)
@ -219,7 +219,7 @@ impl<'a> Lexer<'a> {
_ => unreachable!(),
};
self.current.token.start = self.offset() - offset;
self.current.chars = self.source[self.current.token.start + 1..].chars();
self.current.chars = self.source[self.current.token.start as usize + 1..].chars();
let kind = Kind::LAngle;
self.lookahead.clear();
self.finish_next(kind)
@ -234,7 +234,7 @@ impl<'a> Lexer<'a> {
_ => unreachable!(),
};
self.current.token.start = self.offset() - offset;
self.current.chars = self.source[self.current.token.start + 1..].chars();
self.current.chars = self.source[self.current.token.start as usize + 1..].chars();
let kind = Kind::RAngle;
self.lookahead.clear();
self.finish_next(kind)
@ -247,13 +247,14 @@ impl<'a> Lexer<'a> {
/// Get the length offset from the source, in UTF-8 bytes
#[inline]
fn offset(&self) -> usize {
self.source.len() - self.current.chars.as_str().len()
#[allow(clippy::cast_possible_truncation)]
fn offset(&self) -> u32 {
(self.source.len() - self.current.chars.as_str().len()) as u32
}
/// Get the current unterminated token range
fn unterminated_range(&self) -> Span {
self.current.token.start..self.offset()
fn unterminated_range(&self) -> Node {
Node::new(self.current.token.start, self.offset())
}
/// Peek the next char without advancing the position
@ -279,9 +280,9 @@ impl<'a> Lexer<'a> {
matched
}
fn current_offset(&self) -> std::ops::Range<usize> {
fn current_offset(&self) -> Node {
let offset = self.offset();
offset..offset
Node::new(offset, offset)
}
/// Return `IllegalCharacter` Error or `UnexpectedEnd` if EOF
@ -316,7 +317,10 @@ impl<'a> Lexer<'a> {
match value {
Ok(value) => self.current.token.value = value,
Err(err) => {
self.error(Diagnostic::InvalidNumber(err, self.current.token.start..self.offset()));
self.error(Diagnostic::InvalidNumber(
err,
Node::new(self.current.token.start, self.offset()),
));
self.current.token.value = TokenValue::Number(std::f64::NAN);
}
};
@ -710,11 +714,11 @@ impl<'a> Lexer<'a> {
self.identifier_unicode_escape_sequence(&mut builder, true);
}
Some(c) => {
self.error(Diagnostic::InvalidCharacter(c, start..self.offset() - 1));
self.error(Diagnostic::InvalidCharacter(c, Node::new(start, self.offset() - 1)));
return Kind::Undetermined;
}
None => {
self.error(Diagnostic::UnexpectedEnd(start..self.offset() - 1));
self.error(Diagnostic::UnexpectedEnd(Node::new(start, self.offset() - 1)));
return Kind::Undetermined;
}
}
@ -931,7 +935,7 @@ impl<'a> Lexer<'a> {
break;
}
}
self.error(Diagnostic::InvalidNumberEnd(offset..self.offset()));
self.error(Diagnostic::InvalidNumberEnd(Node::new(offset, self.offset())));
Kind::Undetermined
}
@ -958,7 +962,7 @@ impl<'a> Lexer<'a> {
let mut is_valid_escape_sequence = true;
self.read_string_escape_sequence(text, false, &mut is_valid_escape_sequence);
if !is_valid_escape_sequence {
let range = start..self.offset();
let range = Node::new(start, self.offset());
self.error(Diagnostic::InvalidEscapeSequence(range));
}
}
@ -1080,8 +1084,8 @@ impl<'a> Lexer<'a> {
/// `IdentifierStart`
/// `JSXIdentifier` `IdentifierPart`
/// `JSXIdentifier` [no `WhiteSpace` or Comment here] -
fn read_jsx_identifier(&mut self, prev_len: usize) -> Kind {
let prev_str = &self.source[prev_len..self.offset()];
fn read_jsx_identifier(&mut self, prev_len: u32) -> Kind {
let prev_str = &self.source[prev_len as usize..self.offset() as usize];
let mut builder = AutoCow::new(self);
loop {
@ -1185,7 +1189,7 @@ impl<'a> Lexer<'a> {
) {
let start = self.offset();
if self.current.chars.next() != Some('u') {
let range = start..self.offset();
let range = Node::new(start, self.offset());
self.error(Diagnostic::UnicodeEscapeSequence(range));
return;
}
@ -1196,7 +1200,7 @@ impl<'a> Lexer<'a> {
};
let Some(value) = value else {
let range = start..self.offset();
let range = Node::new(start,self.offset());
self.error(Diagnostic::UnicodeEscapeSequence(range));
return;
};
@ -1204,7 +1208,7 @@ impl<'a> Lexer<'a> {
// For Identifiers, surrogate pair is an invalid grammar, e.g. `var \uD800\uDEA7`.
let ch = match value {
SurrogatePair::Astral(..) | SurrogatePair::HighLow(..) => {
let range = start..self.offset();
let range = Node::new(start, self.offset());
self.error(Diagnostic::UnicodeEscapeSequence(range));
return;
}
@ -1212,7 +1216,7 @@ impl<'a> Lexer<'a> {
if let Ok(ch) = char::try_from(code_point) {
ch
} else {
let range = start..self.offset();
let range = Node::new(start, self.offset());
self.error(Diagnostic::UnicodeEscapeSequence(range));
return;
}

View file

@ -1,9 +1,7 @@
//! Token
use std::ops::Range;
use num_bigint::BigUint;
use oxc_ast::Atom;
use oxc_ast::{Atom, Node};
use super::kind::Kind;
@ -13,10 +11,10 @@ pub struct Token {
pub kind: Kind,
/// Start offset in source
pub start: usize,
pub start: u32,
/// End offset in source
pub end: usize,
pub end: u32,
/// Indicates the token is on a newline
pub is_on_new_line: bool,
@ -29,8 +27,8 @@ pub struct Token {
impl Token {
#[must_use]
pub const fn range(&self) -> Range<usize> {
self.start..self.end
pub const fn node(&self) -> Node {
Node::new(self.start, self.end)
}
}

View file

@ -46,7 +46,7 @@ pub struct Parser<'a> {
token: Token,
/// The end range of the previous token
prev_token_end: usize,
prev_token_end: u32,
/// Parser state
state: ParserState<'a>,
@ -102,6 +102,7 @@ impl<'a> Parser<'a> {
ParserReturn { program, errors: self.errors.borrow().clone() }
}
#[allow(clippy::cast_possible_truncation)]
fn parse_program(&mut self) -> Result<Program<'a>> {
// initialize cur_token and prev_token by moving onto the first token
self.bump_any();
@ -109,7 +110,7 @@ impl<'a> Parser<'a> {
let (directives, statements) =
self.parse_directives_and_statements(/* is_top_level */ true)?;
let node = Node::new(0, self.source.len());
let node = Node::new(0, self.source.len() as u32);
Ok(self.ast.program(node, directives, statements, self.source_type))
}
@ -119,7 +120,7 @@ impl<'a> Parser<'a> {
if self.source_type.is_javascript()
&& (self.source.starts_with("// @flow") || self.source.starts_with("/* @flow */"))
{
return Some(Diagnostic::Flow(0..8));
return Some(Diagnostic::Flow(Node::new(0, 8)));
}
None
}

View file

@ -5,7 +5,7 @@ use oxc_ast::ast::Decorator;
#[derive(Default)]
pub struct ParserState<'a> {
pub not_parenthesized_arrow: HashSet<usize>,
pub not_parenthesized_arrow: HashSet<u32>,
pub decorators: Option<Vec<'a, Decorator<'a>>>,
}

View file

@ -877,7 +877,7 @@ impl<'a> Parser<'a> {
self.bump(Kind::Comma);
self.bump(Kind::Semicolon);
if !params.is_empty() {
self.error(Diagnostic::GetterParameters(params.node.range()));
self.error(Diagnostic::GetterParameters(params.node));
}
Ok(self.ast.ts_method_signature(
self.end_node(node),
@ -900,12 +900,10 @@ impl<'a> Parser<'a> {
self.bump(Kind::Comma);
self.bump(Kind::Semicolon);
if params.items.len() != 1 {
self.error(Diagnostic::SetterParameters(params.node.range()));
self.error(Diagnostic::SetterParameters(params.node));
}
if let Some(return_type) = return_type.as_ref() {
self.error(Diagnostic::ASetAccessorCannotHaveAReturnTypeAnnotation(
return_type.node.range(),
));
self.error(Diagnostic::ASetAccessorCannotHaveAReturnTypeAnnotation(return_type.node));
}
Ok(self.ast.ts_method_signature(
self.end_node(node),