diff --git a/Cargo.lock b/Cargo.lock index 946c6dfffd2c1..eafbb80428a22 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -198,6 +198,15 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37b2a672a2cb129a2e41c10b1224bb368f9f37a2b16b612598138befd7b37eb5" +[[package]] +name = "castaway" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8a17ed5635fc8536268e5d4de1e22e81ac34419e5f052d4d51f4e01dcc263fcc" +dependencies = [ + "rustversion", +] + [[package]] name = "cc" version = "1.0.83" @@ -297,6 +306,20 @@ dependencies = [ "windows-sys 0.48.0", ] +[[package]] +name = "compact_str" +version = "0.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f86b9c4c00838774a6d902ef931eff7470720c51d90c2e32cfe15dc304737b3f" +dependencies = [ + "castaway", + "cfg-if", + "itoa", + "ryu", + "serde", + "static_assertions", +] + [[package]] name = "console" version = "0.15.8" @@ -1645,6 +1668,7 @@ dependencies = [ name = "oxc_span" version = "0.8.0" dependencies = [ + "compact_str", "inlinable_string", "miette", "serde", @@ -2150,6 +2174,12 @@ dependencies = [ "untrusted", ] +[[package]] +name = "rustversion" +version = "1.0.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" + [[package]] name = "ryu" version = "1.0.16" diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index d79cfd88bc3c1..3f3abc2fea023 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -22,8 +22,8 @@ pub struct Program<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub source_type: SourceType, - pub directives: Vec<'a, Directive>, - pub hashbang: Option, + pub directives: Vec<'a, Directive<'a>>, + pub hashbang: Option>, pub body: Vec<'a, Statement<'a>>, } @@ -47,14 +47,14 @@ pub enum Expression<'a> { BooleanLiteral(Box<'a, BooleanLiteral>), NullLiteral(Box<'a, NullLiteral>), NumericLiteral(Box<'a, NumericLiteral<'a>>), - BigintLiteral(Box<'a, BigintLiteral>), - RegExpLiteral(Box<'a, RegExpLiteral>), - StringLiteral(Box<'a, StringLiteral>), + BigintLiteral(Box<'a, BigintLiteral<'a>>), + RegExpLiteral(Box<'a, RegExpLiteral<'a>>), + StringLiteral(Box<'a, StringLiteral<'a>>), TemplateLiteral(Box<'a, TemplateLiteral<'a>>), - Identifier(Box<'a, IdentifierReference>), + Identifier(Box<'a, IdentifierReference<'a>>), - MetaProperty(Box<'a, MetaProperty>), + MetaProperty(Box<'a, MetaProperty<'a>>), Super(Box<'a, Super>), ArrayExpression(Box<'a, ArrayExpression<'a>>), @@ -301,14 +301,14 @@ impl<'a> Expression<'a> { #[derive(Debug, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct IdentifierName { +pub struct IdentifierName<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub name: Atom, + pub name: Atom<'a>, } -impl IdentifierName { - pub fn new(span: Span, name: Atom) -> Self { +impl<'a> IdentifierName<'a> { + pub fn new(span: Span, name: Atom<'a>) -> Self { Self { span, name } } } @@ -317,23 +317,23 @@ impl IdentifierName { #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "camelCase"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct IdentifierReference { +pub struct IdentifierReference<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub name: Atom, + pub name: Atom<'a>, pub reference_id: Cell>, pub reference_flag: ReferenceFlag, } -impl Hash for IdentifierReference { +impl<'a> Hash for IdentifierReference<'a> { fn hash(&self, state: &mut H) { self.span.hash(state); self.name.hash(state); } } -impl IdentifierReference { - pub fn new(span: Span, name: Atom) -> Self { +impl<'a> IdentifierReference<'a> { + pub fn new(span: Span, name: Atom<'a>) -> Self { Self { span, name, reference_id: Cell::default(), reference_flag: ReferenceFlag::default() } } } @@ -342,22 +342,22 @@ impl IdentifierReference { #[derive(Debug, Clone)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "camelCase"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct BindingIdentifier { +pub struct BindingIdentifier<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub name: Atom, + pub name: Atom<'a>, pub symbol_id: Cell>, } -impl Hash for BindingIdentifier { +impl<'a> Hash for BindingIdentifier<'a> { fn hash(&self, state: &mut H) { self.span.hash(state); self.name.hash(state); } } -impl BindingIdentifier { - pub fn new(span: Span, name: Atom) -> Self { +impl<'a> BindingIdentifier<'a> { + pub fn new(span: Span, name: Atom<'a>) -> Self { Self { span, name, symbol_id: Cell::default() } } } @@ -366,10 +366,10 @@ impl BindingIdentifier { #[derive(Debug, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct LabelIdentifier { +pub struct LabelIdentifier<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub name: Atom, + pub name: Atom<'a>, } /// This Expression @@ -457,13 +457,13 @@ pub struct ObjectProperty<'a> { #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum PropertyKey<'a> { - Identifier(Box<'a, IdentifierName>), - PrivateIdentifier(Box<'a, PrivateIdentifier>), + Identifier(Box<'a, IdentifierName<'a>>), + PrivateIdentifier(Box<'a, PrivateIdentifier<'a>>), Expression(Expression<'a>), } impl<'a> PropertyKey<'a> { - pub fn static_name(&self) -> Option { + pub fn static_name(&self) -> Option> { match self { Self::Identifier(ident) => Some(ident.name.clone()), Self::PrivateIdentifier(_) => None, @@ -493,14 +493,14 @@ impl<'a> PropertyKey<'a> { matches!(self, Self::PrivateIdentifier(_)) } - pub fn private_name(&self) -> Option { + pub fn private_name(&self) -> Option> { match self { Self::PrivateIdentifier(ident) => Some(ident.name.clone()), _ => None, } } - pub fn name(&self) -> Option { + pub fn name(&self) -> Option> { if self.is_private_identifier() { self.private_name() } else { @@ -541,7 +541,7 @@ pub enum PropertyKind { pub struct TemplateLiteral<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub quasis: Vec<'a, TemplateElement>, + pub quasis: Vec<'a, TemplateElement<'a>>, pub expressions: Vec<'a, Expression<'a>>, } @@ -551,7 +551,7 @@ impl<'a> TemplateLiteral<'a> { } /// Get single quasi from `template` - pub fn quasi(&self) -> Option<&Atom> { + pub fn quasi(&self) -> Option<&Atom<'a>> { self.quasis.first().and_then(|quasi| quasi.value.cooked.as_ref()) } } @@ -570,27 +570,27 @@ pub struct TaggedTemplateExpression<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct TemplateElement { +pub struct TemplateElement<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub tail: bool, - pub value: TemplateElementValue, + pub value: TemplateElementValue<'a>, } /// See [template-strings-cooked-vs-raw](https://exploringjs.com/impatient-js/ch_template-literals.html#template-strings-cooked-vs-raw) #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct TemplateElementValue { +pub struct TemplateElementValue<'a> { /// A raw interpretation where backslashes do not have special meaning. /// For example, \t produces two characters – a backslash and a t. /// This interpretation of the template strings is stored in property .raw of the first argument (an Array). - pub raw: Atom, + pub raw: Atom<'a>, /// A cooked interpretation where backslashes have special meaning. /// For example, \t produces a tab character. /// This interpretation of the template strings is stored as an Array in the first argument. /// cooked = None when template literal has invalid escape sequence - pub cooked: Option, + pub cooked: Option>, } /// @@ -708,7 +708,7 @@ pub struct StaticMemberExpression<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub object: Expression<'a>, - pub property: IdentifierName, + pub property: IdentifierName<'a>, pub optional: bool, // for optional chaining } @@ -720,7 +720,7 @@ pub struct PrivateFieldExpression<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub object: Expression<'a>, - pub field: PrivateIdentifier, + pub field: PrivateIdentifier<'a>, pub optional: bool, // for optional chaining } @@ -794,11 +794,11 @@ pub struct NewExpression<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct MetaProperty { +pub struct MetaProperty<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub meta: IdentifierName, - pub property: IdentifierName, + pub meta: IdentifierName<'a>, + pub property: IdentifierName<'a>, } /// Spread Element @@ -868,7 +868,7 @@ pub struct BinaryExpression<'a> { pub struct PrivateInExpression<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub left: PrivateIdentifier, + pub left: PrivateIdentifier<'a>, pub operator: BinaryOperator, // BinaryOperator::In pub right: Expression<'a>, } @@ -939,7 +939,7 @@ impl<'a> AssignmentTarget<'a> { #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum SimpleAssignmentTarget<'a> { - AssignmentTargetIdentifier(Box<'a, IdentifierReference>), + AssignmentTargetIdentifier(Box<'a, IdentifierReference<'a>>), MemberAssignmentTarget(Box<'a, MemberExpression<'a>>), TSAsExpression(Box<'a, TSAsExpression<'a>>), TSSatisfiesExpression(Box<'a, TSSatisfiesExpression<'a>>), @@ -1058,7 +1058,7 @@ pub enum AssignmentTargetProperty<'a> { pub struct AssignmentTargetPropertyIdentifier<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub binding: IdentifierReference, + pub binding: IdentifierReference<'a>, pub init: Option>, } @@ -1135,8 +1135,8 @@ pub struct ParenthesizedExpression<'a> { pub enum Statement<'a> { // Statements BlockStatement(Box<'a, BlockStatement<'a>>), - BreakStatement(Box<'a, BreakStatement>), - ContinueStatement(Box<'a, ContinueStatement>), + BreakStatement(Box<'a, BreakStatement<'a>>), + ContinueStatement(Box<'a, ContinueStatement<'a>>), DebuggerStatement(Box<'a, DebuggerStatement>), DoWhileStatement(Box<'a, DoWhileStatement<'a>>), EmptyStatement(Box<'a, EmptyStatement>), @@ -1174,24 +1174,24 @@ impl<'a> Statement<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct Directive { +pub struct Directive<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub expression: StringLiteral, + pub expression: StringLiteral<'a>, /// A Use Strict Directive is an ExpressionStatement in a Directive Prologue whose StringLiteral is either of the exact code point sequences "use strict" or 'use strict'. /// A Use Strict Directive may not contain an EscapeSequence or LineContinuation. /// - pub directive: Atom, + pub directive: Atom<'a>, } /// Hashbang #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct Hashbang { +pub struct Hashbang<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub value: Atom, + pub value: Atom<'a>, } /// Block Statement @@ -1463,20 +1463,20 @@ impl<'a> ForStatementLeft<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct ContinueStatement { +pub struct ContinueStatement<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub label: Option, + pub label: Option>, } /// Break Statement #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct BreakStatement { +pub struct BreakStatement<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub label: Option, + pub label: Option>, } /// Return Statement @@ -1534,7 +1534,7 @@ impl<'a> SwitchCase<'a> { pub struct LabeledStatement<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub label: LabelIdentifier, + pub label: LabelIdentifier<'a>, pub body: Statement<'a>, } @@ -1601,7 +1601,7 @@ impl<'a> BindingPattern<'a> { #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum BindingPatternKind<'a> { /// `const a = 1` - BindingIdentifier(Box<'a, BindingIdentifier>), + BindingIdentifier(Box<'a, BindingIdentifier<'a>>), /// `const {a} = 1` ObjectPattern(Box<'a, ObjectPattern<'a>>), /// `const [a] = 1` @@ -1705,7 +1705,7 @@ pub struct Function<'a> { pub r#type: FunctionType, #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub id: Option, + pub id: Option>, pub generator: bool, pub r#async: bool, /// Declaring `this` in a Function @@ -1834,7 +1834,7 @@ impl<'a> FormalParameters<'a> { pub struct FunctionBody<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub directives: Vec<'a, Directive>, + pub directives: Vec<'a, Directive<'a>>, pub statements: Vec<'a, Statement<'a>>, } @@ -1893,7 +1893,7 @@ pub struct Class<'a> { pub r#type: ClassType, #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub id: Option, + pub id: Option>, pub super_class: Option>, pub body: Box<'a, ClassBody<'a>>, pub type_parameters: Option>>, @@ -2126,14 +2126,14 @@ impl MethodDefinitionKind { #[derive(Debug, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct PrivateIdentifier { +pub struct PrivateIdentifier<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub name: Atom, + pub name: Atom<'a>, } -impl PrivateIdentifier { - pub fn new(span: Span, name: Atom) -> Self { +impl<'a> PrivateIdentifier<'a> { + pub fn new(span: Span, name: Atom<'a>) -> Self { Self { span, name } } } @@ -2165,7 +2165,7 @@ pub enum ModuleDeclaration<'a> { /// export = 5; TSExportAssignment(Box<'a, TSExportAssignment<'a>>), /// export as namespace React; - TSNamespaceExportDeclaration(Box<'a, TSNamespaceExportDeclaration>), + TSNamespaceExportDeclaration(Box<'a, TSNamespaceExportDeclaration<'a>>), } impl<'a> ModuleDeclaration<'a> { @@ -2188,7 +2188,7 @@ impl<'a> ModuleDeclaration<'a> { matches!(self, Self::ExportDefaultDeclaration(_)) } - pub fn source(&self) -> Option<&StringLiteral> { + pub fn source(&self) -> Option<&StringLiteral<'a>> { match self { Self::ImportDeclaration(decl) => Some(&decl.source), Self::ExportAllDeclaration(decl) => Some(&decl.source), @@ -2230,8 +2230,8 @@ pub struct ImportDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, /// `None` for `import 'foo'`, `Some([])` for `import {} from 'foo'` - pub specifiers: Option>, - pub source: StringLiteral, + pub specifiers: Option>>, + pub source: StringLiteral<'a>, /// Some(vec![]) for empty assertion pub with_clause: Option>, /// `import type { foo } from 'bar'` @@ -2241,14 +2241,14 @@ pub struct ImportDeclaration<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub enum ImportDeclarationSpecifier { +pub enum ImportDeclarationSpecifier<'a> { /// import {imported} from "source" /// import {imported as local} from "source" - ImportSpecifier(ImportSpecifier), + ImportSpecifier(ImportSpecifier<'a>), /// import local from "source" - ImportDefaultSpecifier(ImportDefaultSpecifier), + ImportDefaultSpecifier(ImportDefaultSpecifier<'a>), /// import * as local from "source" - ImportNamespaceSpecifier(ImportNamespaceSpecifier), + ImportNamespaceSpecifier(ImportNamespaceSpecifier<'a>), } // import {imported} from "source" @@ -2256,11 +2256,11 @@ pub enum ImportDeclarationSpecifier { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "camelCase"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct ImportSpecifier { +pub struct ImportSpecifier<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub imported: ModuleExportName, - pub local: BindingIdentifier, + pub imported: ModuleExportName<'a>, + pub local: BindingIdentifier<'a>, pub import_kind: ImportOrExportKind, } @@ -2268,20 +2268,20 @@ pub struct ImportSpecifier { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct ImportDefaultSpecifier { +pub struct ImportDefaultSpecifier<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub local: BindingIdentifier, + pub local: BindingIdentifier<'a>, } // import * as local from "source" #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct ImportNamespaceSpecifier { +pub struct ImportNamespaceSpecifier<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub local: BindingIdentifier, + pub local: BindingIdentifier<'a>, } #[derive(Debug, Hash)] @@ -2290,30 +2290,30 @@ pub struct ImportNamespaceSpecifier { pub struct WithClause<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub attributes_keyword: IdentifierName, // `with` or `assert` - pub with_entries: Vec<'a, ImportAttribute>, + pub attributes_keyword: IdentifierName<'a>, // `with` or `assert` + pub with_entries: Vec<'a, ImportAttribute<'a>>, } #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct ImportAttribute { +pub struct ImportAttribute<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub key: ImportAttributeKey, - pub value: StringLiteral, + pub key: ImportAttributeKey<'a>, + pub value: StringLiteral<'a>, } #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub enum ImportAttributeKey { - Identifier(IdentifierName), - StringLiteral(StringLiteral), +pub enum ImportAttributeKey<'a> { + Identifier(IdentifierName<'a>), + StringLiteral(StringLiteral<'a>), } -impl ImportAttributeKey { - pub fn as_atom(&self) -> Atom { +impl<'a> ImportAttributeKey<'a> { + pub fn as_atom(&self) -> Atom<'a> { match self { Self::Identifier(identifier) => identifier.name.clone(), Self::StringLiteral(literal) => literal.value.clone(), @@ -2328,8 +2328,8 @@ pub struct ExportNamedDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub declaration: Option>, - pub specifiers: Vec<'a, ExportSpecifier>, - pub source: Option, + pub specifiers: Vec<'a, ExportSpecifier<'a>>, + pub source: Option>, /// `export type { foo }` pub export_kind: ImportOrExportKind, } @@ -2352,7 +2352,7 @@ pub struct ExportDefaultDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub declaration: ExportDefaultDeclarationKind<'a>, - pub exported: ModuleExportName, // `default` + pub exported: ModuleExportName<'a>, // `default` } impl<'a> ExportDefaultDeclaration<'a> { @@ -2367,8 +2367,8 @@ impl<'a> ExportDefaultDeclaration<'a> { pub struct ExportAllDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub exported: Option, - pub source: StringLiteral, + pub exported: Option>, + pub source: StringLiteral<'a>, pub with_clause: Option>, // Some(vec![]) for empty assertion pub export_kind: ImportOrExportKind, // `export type *` } @@ -2382,16 +2382,16 @@ impl<'a> ExportAllDeclaration<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct ExportSpecifier { +pub struct ExportSpecifier<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub local: ModuleExportName, - pub exported: ModuleExportName, + pub local: ModuleExportName<'a>, + pub exported: ModuleExportName<'a>, pub export_kind: ImportOrExportKind, // `export type *` } -impl ExportSpecifier { - pub fn new(span: Span, local: ModuleExportName, exported: ModuleExportName) -> Self { +impl<'a> ExportSpecifier<'a> { + pub fn new(span: Span, local: ModuleExportName<'a>, exported: ModuleExportName<'a>) -> Self { Self { span, local, exported, export_kind: ImportOrExportKind::Value } } } @@ -2437,12 +2437,12 @@ impl<'a> ExportDefaultDeclarationKind<'a> { #[derive(Debug, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub enum ModuleExportName { - Identifier(IdentifierName), - StringLiteral(StringLiteral), +pub enum ModuleExportName<'a> { + Identifier(IdentifierName<'a>), + StringLiteral(StringLiteral<'a>), } -impl fmt::Display for ModuleExportName { +impl<'a> fmt::Display for ModuleExportName<'a> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let s = match self { Self::Identifier(identifier) => identifier.name.to_string(), @@ -2452,8 +2452,8 @@ impl fmt::Display for ModuleExportName { } } -impl ModuleExportName { - pub fn name(&self) -> &Atom { +impl<'a> ModuleExportName<'a> { + pub fn name(&self) -> &Atom<'a> { match self { Self::Identifier(identifier) => &identifier.name, Self::StringLiteral(literal) => &literal.value, diff --git a/crates/oxc_ast/src/ast/jsx.rs b/crates/oxc_ast/src/ast/jsx.rs index 907570c2d6d01..9f27c3b121b6b 100644 --- a/crates/oxc_ast/src/ast/jsx.rs +++ b/crates/oxc_ast/src/ast/jsx.rs @@ -79,9 +79,9 @@ pub struct JSXClosingFragment { #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum JSXElementName<'a> { /// `` - Identifier(JSXIdentifier), + Identifier(JSXIdentifier<'a>), /// `` - NamespacedName(Box<'a, JSXNamespacedName>), + NamespacedName(Box<'a, JSXNamespacedName<'a>>), /// `` MemberExpression(Box<'a, JSXMemberExpression<'a>>), } @@ -90,14 +90,14 @@ pub enum JSXElementName<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct JSXNamespacedName { +pub struct JSXNamespacedName<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub namespace: JSXIdentifier, - pub property: JSXIdentifier, + pub namespace: JSXIdentifier<'a>, + pub property: JSXIdentifier<'a>, } -impl std::fmt::Display for JSXNamespacedName { +impl<'a> std::fmt::Display for JSXNamespacedName<'a> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{}:{}", self.namespace.name, self.property.name) } @@ -111,7 +111,7 @@ pub struct JSXMemberExpression<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub object: JSXMemberExpressionObject<'a>, - pub property: JSXIdentifier, + pub property: JSXIdentifier<'a>, } impl<'a> JSXMemberExpression<'a> { @@ -127,7 +127,7 @@ impl<'a> JSXMemberExpression<'a> { #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum JSXMemberExpressionObject<'a> { - Identifier(JSXIdentifier), + Identifier(JSXIdentifier<'a>), MemberExpression(Box<'a, JSXMemberExpression<'a>>), } @@ -199,8 +199,8 @@ pub struct JSXSpreadAttribute<'a> { #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum JSXAttributeName<'a> { - Identifier(JSXIdentifier), - NamespacedName(Box<'a, JSXNamespacedName>), + Identifier(JSXIdentifier<'a>), + NamespacedName(Box<'a, JSXNamespacedName<'a>>), } /// JSX Attribute Value @@ -208,7 +208,7 @@ pub enum JSXAttributeName<'a> { #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum JSXAttributeValue<'a> { - StringLiteral(StringLiteral), + StringLiteral(StringLiteral<'a>), ExpressionContainer(JSXExpressionContainer<'a>), Element(Box<'a, JSXElement<'a>>), Fragment(Box<'a, JSXFragment<'a>>), @@ -217,10 +217,10 @@ pub enum JSXAttributeValue<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct JSXIdentifier { +pub struct JSXIdentifier<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub name: Atom, + pub name: Atom<'a>, } // 1.4 JSX Children @@ -230,7 +230,7 @@ pub struct JSXIdentifier { #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum JSXChild<'a> { - Text(JSXText), + Text(JSXText<'a>), Element(Box<'a, JSXElement<'a>>), Fragment(Box<'a, JSXFragment<'a>>), ExpressionContainer(JSXExpressionContainer<'a>), @@ -249,8 +249,8 @@ pub struct JSXSpreadChild<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct JSXText { +pub struct JSXText<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub value: Atom, + pub value: Atom<'a>, } diff --git a/crates/oxc_ast/src/ast/literal.rs b/crates/oxc_ast/src/ast/literal.rs index 02a5618ff964c..ce906703a9a21 100644 --- a/crates/oxc_ast/src/ast/literal.rs +++ b/crates/oxc_ast/src/ast/literal.rs @@ -109,15 +109,15 @@ impl<'a> Hash for NumericLiteral<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct BigintLiteral { +pub struct BigintLiteral<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub raw: Atom, + pub raw: Atom<'a>, #[cfg_attr(feature = "serde", serde(skip))] pub base: BigintBase, } -impl BigintLiteral { +impl<'a> BigintLiteral<'a> { pub fn is_zero(&self) -> bool { self.raw == "0n" } @@ -126,24 +126,24 @@ impl BigintLiteral { #[derive(Debug, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct RegExpLiteral { +pub struct RegExpLiteral<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, // valid regex is printed as {} // invalid regex is printed as null, which we can't implement yet pub value: EmptyObject, - pub regex: RegExp, + pub regex: RegExp<'a>, } #[derive(Debug, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct RegExp { - pub pattern: Atom, +pub struct RegExp<'a> { + pub pattern: Atom<'a>, pub flags: RegExpFlags, } -impl fmt::Display for RegExp { +impl<'a> fmt::Display for RegExp<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { write!(f, "/{}/{}", self.pattern, self.flags) } @@ -238,14 +238,14 @@ pub struct EmptyObject; #[derive(Debug, Clone, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct StringLiteral { +pub struct StringLiteral<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub value: Atom, + pub value: Atom<'a>, } -impl StringLiteral { - pub fn new(span: Span, value: Atom) -> Self { +impl<'a> StringLiteral<'a> { + pub fn new(span: Span, value: Atom<'a>) -> Self { Self { span, value } } diff --git a/crates/oxc_ast/src/ast/ts.rs b/crates/oxc_ast/src/ast/ts.rs index 13498854ae04e..7e63713bc2717 100644 --- a/crates/oxc_ast/src/ast/ts.rs +++ b/crates/oxc_ast/src/ast/ts.rs @@ -27,7 +27,7 @@ export interface TSAbstractMethodDefinition extends Omit { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub this: IdentifierName, + pub this: IdentifierName<'a>, pub type_annotation: Option>>, } @@ -40,7 +40,7 @@ pub struct TSThisParameter<'a> { pub struct TSEnumDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub id: BindingIdentifier, + pub id: BindingIdentifier<'a>, pub members: Vec<'a, TSEnumMember<'a>>, /// Valid Modifiers: `const`, `export`, `declare` pub modifiers: Modifiers<'a>, @@ -60,8 +60,8 @@ pub struct TSEnumMember<'a> { #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum TSEnumMemberName<'a> { - Identifier(IdentifierName), - StringLiteral(StringLiteral), + Identifier(IdentifierName<'a>), + StringLiteral(StringLiteral<'a>), // Invalid Grammar `enum E { [computed] }` ComputedPropertyName(Expression<'a>), // Invalid Grammar `enum E { 1 }` @@ -93,9 +93,9 @@ pub enum TSLiteral<'a> { BooleanLiteral(Box<'a, BooleanLiteral>), NullLiteral(Box<'a, NullLiteral>), NumericLiteral(Box<'a, NumericLiteral<'a>>), - BigintLiteral(Box<'a, BigintLiteral>), - RegExpLiteral(Box<'a, RegExpLiteral>), - StringLiteral(Box<'a, StringLiteral>), + BigintLiteral(Box<'a, BigintLiteral<'a>>), + RegExpLiteral(Box<'a, RegExpLiteral<'a>>), + StringLiteral(Box<'a, StringLiteral<'a>>), TemplateLiteral(Box<'a, TemplateLiteral<'a>>), UnaryExpression(Box<'a, UnaryExpression<'a>>), } @@ -254,7 +254,7 @@ pub struct TSNamedTupleMember<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub element_type: TSType<'a>, - pub label: IdentifierName, + pub label: IdentifierName<'a>, pub optional: bool, } @@ -410,12 +410,12 @@ pub struct TSTypeReference<'a> { #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum TSTypeName<'a> { - IdentifierReference(Box<'a, IdentifierReference>), + IdentifierReference(Box<'a, IdentifierReference<'a>>), QualifiedName(Box<'a, TSQualifiedName<'a>>), } impl<'a> TSTypeName<'a> { - pub fn get_first_name(name: &TSTypeName) -> IdentifierReference { + pub fn get_first_name(name: &TSTypeName<'a>) -> IdentifierReference<'a> { match name { TSTypeName::IdentifierReference(name) => (*name).clone(), TSTypeName::QualifiedName(name) => TSTypeName::get_first_name(&name.left), @@ -456,7 +456,7 @@ pub struct TSQualifiedName<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, pub left: TSTypeName<'a>, - pub right: IdentifierName, + pub right: IdentifierName<'a>, } #[derive(Debug, Hash)] @@ -474,7 +474,7 @@ pub struct TSTypeParameterInstantiation<'a> { pub struct TSTypeParameter<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub name: BindingIdentifier, + pub name: BindingIdentifier<'a>, pub constraint: Option>, pub default: Option>, pub r#in: bool, @@ -497,7 +497,7 @@ pub struct TSTypeParameterDeclaration<'a> { pub struct TSTypeAliasDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub id: BindingIdentifier, + pub id: BindingIdentifier<'a>, pub type_annotation: TSType<'a>, pub type_parameters: Option>>, /// Valid Modifiers: `declare`, `export` @@ -546,7 +546,7 @@ pub struct TSClassImplements<'a> { pub struct TSInterfaceDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub id: BindingIdentifier, + pub id: BindingIdentifier<'a>, pub body: Box<'a, TSInterfaceBody<'a>>, pub type_parameters: Option>>, pub extends: Option>>>, @@ -651,7 +651,7 @@ pub struct TSConstructSignatureDeclaration<'a> { pub struct TSIndexSignatureName<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub name: Atom, + pub name: Atom<'a>, pub type_annotation: Box<'a, TSTypeAnnotation<'a>>, } @@ -671,7 +671,7 @@ pub struct TSInterfaceHeritage<'a> { pub struct TSTypePredicate<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub parameter_name: TSTypePredicateName, + pub parameter_name: TSTypePredicateName<'a>, pub asserts: bool, pub type_annotation: Option>>, } @@ -679,8 +679,8 @@ pub struct TSTypePredicate<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged, rename_all = "camelCase"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub enum TSTypePredicateName { - Identifier(IdentifierName), +pub enum TSTypePredicateName<'a> { + Identifier(IdentifierName<'a>), This(TSThisType), } @@ -690,7 +690,7 @@ pub enum TSTypePredicateName { pub struct TSModuleDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub id: TSModuleDeclarationName, + pub id: TSModuleDeclarationName<'a>, pub body: TSModuleDeclarationBody<'a>, /// The keyword used to define this module declaration /// ```text @@ -718,13 +718,13 @@ pub enum TSModuleDeclarationKind { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(untagged))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub enum TSModuleDeclarationName { - Identifier(IdentifierName), - StringLiteral(StringLiteral), +pub enum TSModuleDeclarationName<'a> { + Identifier(IdentifierName<'a>), + StringLiteral(StringLiteral<'a>), } -impl TSModuleDeclarationName { - pub fn name(&self) -> &Atom { +impl<'a> TSModuleDeclarationName<'a> { + pub fn name(&self) -> &Atom<'a> { match self { Self::Identifier(ident) => &ident.name, Self::StringLiteral(lit) => &lit.value, @@ -805,16 +805,16 @@ pub struct TSImportAttributes<'a> { pub struct TSImportAttribute<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub name: TSImportAttributeName, + pub name: TSImportAttributeName<'a>, pub value: Expression<'a>, } #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(rename_all = "camelCase"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub enum TSImportAttributeName { - Identifier(IdentifierName), - StringLiteral(StringLiteral), +pub enum TSImportAttributeName<'a> { + Identifier(IdentifierName<'a>), + StringLiteral(StringLiteral<'a>), } #[derive(Debug, Hash)] @@ -872,7 +872,7 @@ pub enum TSMappedTypeModifierOperator { pub struct TSTemplateLiteralType<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub quasis: Vec<'a, TemplateElement>, + pub quasis: Vec<'a, TemplateElement<'a>>, pub types: Vec<'a, TSType<'a>>, } @@ -912,7 +912,7 @@ pub struct TSTypeAssertion<'a> { pub struct TSImportEqualsDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub id: BindingIdentifier, + pub id: BindingIdentifier<'a>, pub module_reference: Box<'a, TSModuleReference<'a>>, pub is_export: bool, pub import_kind: ImportOrExportKind, @@ -923,16 +923,16 @@ pub struct TSImportEqualsDeclaration<'a> { #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub enum TSModuleReference<'a> { TypeName(TSTypeName<'a>), - ExternalModuleReference(TSExternalModuleReference), + ExternalModuleReference(TSExternalModuleReference<'a>), } #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "camelCase"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct TSExternalModuleReference { +pub struct TSExternalModuleReference<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub expression: StringLiteral, + pub expression: StringLiteral<'a>, } #[derive(Debug, Hash)] @@ -1030,10 +1030,10 @@ pub struct TSExportAssignment<'a> { #[derive(Debug, Hash)] #[cfg_attr(feature = "serde", derive(Serialize), serde(tag = "type", rename_all = "camelCase"))] #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] -pub struct TSNamespaceExportDeclaration { +pub struct TSNamespaceExportDeclaration<'a> { #[cfg_attr(feature = "serde", serde(flatten))] pub span: Span, - pub id: IdentifierName, + pub id: IdentifierName<'a>, } #[derive(Debug, Hash)] diff --git a/crates/oxc_ast/src/ast_builder.rs b/crates/oxc_ast/src/ast_builder.rs index 42f5933890f76..7ae07e81481c9 100644 --- a/crates/oxc_ast/src/ast_builder.rs +++ b/crates/oxc_ast/src/ast_builder.rs @@ -56,6 +56,11 @@ impl<'a> AstBuilder<'a> { String::from_str_in(value, self.allocator).into_bump_str() } + #[inline] + pub fn new_atom(&self, value: &str) -> Atom<'a> { + Atom::from(String::from_str_in(value, self.allocator).into_bump_str()) + } + pub fn copy(&self, src: &T) -> T { // SAFETY: // This should be safe as long as `src` is an reference from the allocator. @@ -104,7 +109,7 @@ impl<'a> AstBuilder<'a> { span: Span, source_type: SourceType, directives: Vec<'a, Directive>, - hashbang: Option, + hashbang: Option>, body: Vec<'a, Statement<'a>>, ) -> Program<'a> { Program { span, source_type, directives, hashbang, body } @@ -135,7 +140,7 @@ impl<'a> AstBuilder<'a> { BooleanLiteral { span, value } } - pub fn bigint_literal(&self, span: Span, raw: Atom, base: BigintBase) -> BigintLiteral { + pub fn bigint_literal(&self, span: Span, raw: Atom<'a>, base: BigintBase) -> BigintLiteral<'a> { BigintLiteral { span, raw, base } } @@ -152,12 +157,16 @@ impl<'a> AstBuilder<'a> { &self, span: Span, tail: bool, - value: TemplateElementValue, - ) -> TemplateElement { + value: TemplateElementValue<'a>, + ) -> TemplateElement<'a> { TemplateElement { span, tail, value } } - pub fn template_element_value(&self, raw: Atom, cooked: Option) -> TemplateElementValue { + pub fn template_element_value( + &self, + raw: Atom<'a>, + cooked: Option>, + ) -> TemplateElementValue<'a> { TemplateElementValue { raw, cooked } } @@ -166,11 +175,11 @@ impl<'a> AstBuilder<'a> { span: Span, pattern: &'a str, flags: RegExpFlags, - ) -> RegExpLiteral { + ) -> RegExpLiteral<'a> { RegExpLiteral { span, value: EmptyObject, regex: RegExp { pattern: pattern.into(), flags } } } - pub fn literal_string_expression(&self, literal: StringLiteral) -> Expression<'a> { + pub fn literal_string_expression(&self, literal: StringLiteral<'a>) -> Expression<'a> { Expression::StringLiteral(self.alloc(literal)) } @@ -182,7 +191,7 @@ impl<'a> AstBuilder<'a> { Expression::NullLiteral(self.alloc(literal)) } - pub fn literal_regexp_expression(&self, literal: RegExpLiteral) -> Expression<'a> { + pub fn literal_regexp_expression(&self, literal: RegExpLiteral<'a>) -> Expression<'a> { Expression::RegExpLiteral(self.alloc(literal)) } @@ -190,7 +199,7 @@ impl<'a> AstBuilder<'a> { Expression::NumericLiteral(self.alloc(literal)) } - pub fn literal_bigint_expression(&self, literal: BigintLiteral) -> Expression<'a> { + pub fn literal_bigint_expression(&self, literal: BigintLiteral<'a>) -> Expression<'a> { Expression::BigintLiteral(self.alloc(literal)) } @@ -198,17 +207,25 @@ impl<'a> AstBuilder<'a> { Expression::TemplateLiteral(self.alloc(literal)) } - pub fn identifier_reference_expression(&self, ident: IdentifierReference) -> Expression<'a> { + pub fn identifier_reference_expression( + &self, + ident: IdentifierReference<'a>, + ) -> Expression<'a> { Expression::Identifier(self.alloc(ident)) } /* ---------- Statements ---------- */ - pub fn directive(&self, span: Span, expression: StringLiteral, directive: Atom) -> Directive { + pub fn directive( + &self, + span: Span, + expression: StringLiteral<'a>, + directive: Atom<'a>, + ) -> Directive<'a> { Directive { span, expression, directive } } - pub fn hashbang(&self, span: Span, value: Atom) -> Hashbang { + pub fn hashbang(&self, span: Span, value: Atom<'a>) -> Hashbang<'a> { Hashbang { span, value } } @@ -222,11 +239,15 @@ impl<'a> AstBuilder<'a> { ) } - pub fn break_statement(&self, span: Span, label: Option) -> Statement<'a> { + pub fn break_statement(&self, span: Span, label: Option>) -> Statement<'a> { Statement::BreakStatement(self.alloc(BreakStatement { span, label })) } - pub fn continue_statement(&self, span: Span, label: Option) -> Statement<'a> { + pub fn continue_statement( + &self, + span: Span, + label: Option>, + ) -> Statement<'a> { Statement::ContinueStatement(self.alloc(ContinueStatement { span, label })) } @@ -309,7 +330,7 @@ impl<'a> AstBuilder<'a> { pub fn labeled_statement( &self, span: Span, - label: LabelIdentifier, + label: LabelIdentifier<'a>, body: Statement<'a>, ) -> Statement<'a> { Statement::LabeledStatement(self.alloc(LabeledStatement { span, label, body })) @@ -387,8 +408,8 @@ impl<'a> AstBuilder<'a> { pub fn meta_property( &self, span: Span, - meta: IdentifierName, - property: IdentifierName, + meta: IdentifierName<'a>, + property: IdentifierName<'a>, ) -> Expression<'a> { Expression::MetaProperty(self.alloc(MetaProperty { span, meta, property })) } @@ -449,7 +470,7 @@ impl<'a> AstBuilder<'a> { pub fn simple_assignment_target_identifier( &self, - ident: IdentifierReference, + ident: IdentifierReference<'a>, ) -> AssignmentTarget<'a> { AssignmentTarget::SimpleAssignmentTarget( SimpleAssignmentTarget::AssignmentTargetIdentifier(self.alloc(ident)), @@ -575,7 +596,7 @@ impl<'a> AstBuilder<'a> { &self, span: Span, object: Expression<'a>, - property: IdentifierName, + property: IdentifierName<'a>, optional: bool, // for optional chaining ) -> MemberExpression<'a> { MemberExpression::StaticMemberExpression(StaticMemberExpression { @@ -590,7 +611,7 @@ impl<'a> AstBuilder<'a> { &self, span: Span, object: Expression<'a>, - property: IdentifierName, + property: IdentifierName<'a>, optional: bool, // for optional chaining ) -> Expression<'a> { self.member_expression(self.static_member(span, object, property, optional)) @@ -600,7 +621,7 @@ impl<'a> AstBuilder<'a> { &self, span: Span, object: Expression<'a>, - field: PrivateIdentifier, + field: PrivateIdentifier<'a>, optional: bool, ) -> MemberExpression<'a> { MemberExpression::PrivateFieldExpression(PrivateFieldExpression { @@ -614,7 +635,7 @@ impl<'a> AstBuilder<'a> { pub fn private_in_expression( &self, span: Span, - left: PrivateIdentifier, + left: PrivateIdentifier<'a>, right: Expression<'a>, ) -> Expression<'a> { Expression::PrivateInExpression(self.alloc(PrivateInExpression { @@ -629,7 +650,7 @@ impl<'a> AstBuilder<'a> { &self, span: Span, object: Expression<'a>, - field: PrivateIdentifier, + field: PrivateIdentifier<'a>, optional: bool, ) -> Expression<'a> { self.member_expression(self.private_field(span, object, field, optional)) @@ -783,7 +804,7 @@ impl<'a> AstBuilder<'a> { pub fn ts_this_parameter( &self, span: Span, - this: IdentifierName, + this: IdentifierName<'a>, type_annotation: Option>>, ) -> TSThisParameter<'a> { TSThisParameter { span, this, type_annotation } @@ -793,7 +814,7 @@ impl<'a> AstBuilder<'a> { &self, r#type: FunctionType, span: Span, - id: Option, + id: Option>, generator: bool, r#async: bool, this_param: Option>, @@ -833,7 +854,7 @@ impl<'a> AstBuilder<'a> { &self, r#type: ClassType, span: Span, - id: Option, + id: Option>, super_class: Option>, body: Box<'a, ClassBody<'a>>, type_parameters: Option>>, @@ -979,7 +1000,7 @@ impl<'a> AstBuilder<'a> { pub fn binding_pattern_identifier( &self, - identifier: BindingIdentifier, + identifier: BindingIdentifier<'a>, ) -> BindingPatternKind<'a> { BindingPatternKind::BindingIdentifier(self.alloc(identifier)) } @@ -1043,7 +1064,7 @@ impl<'a> AstBuilder<'a> { self.alloc(BindingRestElement { span, argument }) } - pub fn property_key_identifier(&self, ident: IdentifierName) -> PropertyKey<'a> { + pub fn property_key_identifier(&self, ident: IdentifierName<'a>) -> PropertyKey<'a> { PropertyKey::Identifier(self.alloc(ident)) } @@ -1061,7 +1082,7 @@ impl<'a> AstBuilder<'a> { &self, span: Span, specifiers: Option>, - source: StringLiteral, + source: StringLiteral<'a>, with_clause: Option>, import_kind: ImportOrExportKind, ) -> Box<'a, ImportDeclaration<'a>> { @@ -1071,8 +1092,8 @@ impl<'a> AstBuilder<'a> { pub fn export_all_declaration( &self, span: Span, - exported: Option, - source: StringLiteral, + exported: Option>, + source: StringLiteral<'a>, with_clause: Option>, export_kind: ImportOrExportKind, ) -> Box<'a, ExportAllDeclaration<'a>> { @@ -1083,7 +1104,7 @@ impl<'a> AstBuilder<'a> { &self, span: Span, declaration: ExportDefaultDeclarationKind<'a>, - exported: ModuleExportName, + exported: ModuleExportName<'a>, ) -> Box<'a, ExportDefaultDeclaration<'a>> { self.alloc(ExportDefaultDeclaration { span, declaration, exported }) } @@ -1093,7 +1114,7 @@ impl<'a> AstBuilder<'a> { span: Span, declaration: Option>, specifiers: Vec<'a, ExportSpecifier>, - source: Option, + source: Option>, export_kind: ImportOrExportKind, ) -> Box<'a, ExportNamedDeclaration<'a>> { self.alloc(ExportNamedDeclaration { span, declaration, specifiers, source, export_kind }) @@ -1150,9 +1171,9 @@ impl<'a> AstBuilder<'a> { pub fn jsx_namespaced_name( &self, span: Span, - namespace: JSXIdentifier, - property: JSXIdentifier, - ) -> Box<'a, JSXNamespacedName> { + namespace: JSXIdentifier<'a>, + property: JSXIdentifier<'a>, + ) -> Box<'a, JSXNamespacedName<'a>> { self.alloc(JSXNamespacedName { span, namespace, property }) } @@ -1160,7 +1181,7 @@ impl<'a> AstBuilder<'a> { &self, span: Span, object: JSXMemberExpressionObject<'a>, - property: JSXIdentifier, + property: JSXIdentifier<'a>, ) -> Box<'a, JSXMemberExpression<'a>> { self.alloc(JSXMemberExpression { span, object, property }) } @@ -1198,11 +1219,11 @@ impl<'a> AstBuilder<'a> { self.alloc(JSXSpreadAttribute { span, argument }) } - pub fn jsx_identifier(&self, span: Span, name: Atom) -> JSXIdentifier { + pub fn jsx_identifier(&self, span: Span, name: Atom<'a>) -> JSXIdentifier<'a> { JSXIdentifier { span, name } } - pub fn jsx_text(&self, span: Span, value: Atom) -> JSXText { + pub fn jsx_text(&self, span: Span, value: Atom<'a>) -> JSXText<'a> { JSXText { span, value } } @@ -1210,7 +1231,7 @@ impl<'a> AstBuilder<'a> { pub fn ts_module_declaration( &self, span: Span, - id: TSModuleDeclarationName, + id: TSModuleDeclarationName<'a>, body: TSModuleDeclarationBody<'a>, kind: TSModuleDeclarationKind, modifiers: Modifiers<'a>, @@ -1297,7 +1318,7 @@ impl<'a> AstBuilder<'a> { pub fn ts_type_parameter( &self, span: Span, - name: BindingIdentifier, + name: BindingIdentifier<'a>, constraint: Option>, default: Option>, r#in: bool, @@ -1482,7 +1503,7 @@ impl<'a> AstBuilder<'a> { pub fn ts_import_equals_declaration( &self, span: Span, - id: BindingIdentifier, + id: BindingIdentifier<'a>, module_reference: TSModuleReference<'a>, is_export: bool, import_kind: ImportOrExportKind, @@ -1499,7 +1520,7 @@ impl<'a> AstBuilder<'a> { pub fn ts_interface_declaration( &self, span: Span, - id: BindingIdentifier, + id: BindingIdentifier<'a>, body: Box<'a, TSInterfaceBody<'a>>, type_parameters: Option>>, extends: Option>>>, @@ -1518,7 +1539,7 @@ impl<'a> AstBuilder<'a> { pub fn ts_type_alias_declaration( &self, span: Span, - id: BindingIdentifier, + id: BindingIdentifier<'a>, type_annotation: TSType<'a>, type_parameters: Option>>, modifiers: Modifiers<'a>, @@ -1535,7 +1556,7 @@ impl<'a> AstBuilder<'a> { pub fn ts_enum_declaration( &self, span: Span, - id: BindingIdentifier, + id: BindingIdentifier<'a>, members: Vec<'a, TSEnumMember<'a>>, modifiers: Modifiers<'a>, ) -> Declaration<'a> { @@ -1606,7 +1627,7 @@ impl<'a> AstBuilder<'a> { pub fn ts_template_literal_type( &self, span: Span, - quasis: Vec<'a, TemplateElement>, + quasis: Vec<'a, TemplateElement<'a>>, types: Vec<'a, TSType<'a>>, ) -> TSType<'a> { TSType::TSTemplateLiteralType(self.alloc(TSTemplateLiteralType { span, quasis, types })) @@ -1721,7 +1742,7 @@ impl<'a> AstBuilder<'a> { pub fn ts_type_predicate( &self, span: Span, - parameter_name: TSTypePredicateName, + parameter_name: TSTypePredicateName<'a>, asserts: bool, type_annotation: Option>>, ) -> TSType<'a> { diff --git a/crates/oxc_ast/src/ast_kind.rs b/crates/oxc_ast/src/ast_kind.rs index a6da6a4120b10..7da604967bed7 100644 --- a/crates/oxc_ast/src/ast_kind.rs +++ b/crates/oxc_ast/src/ast_kind.rs @@ -7,12 +7,12 @@ use crate::ast::*; #[derive(Debug, Clone, Copy)] pub enum AstKind<'a> { Program(&'a Program<'a>), - Directive(&'a Directive), - Hashbang(&'a Hashbang), + Directive(&'a Directive<'a>), + Hashbang(&'a Hashbang<'a>), BlockStatement(&'a BlockStatement<'a>), - BreakStatement(&'a BreakStatement), - ContinueStatement(&'a ContinueStatement), + BreakStatement(&'a BreakStatement<'a>), + ContinueStatement(&'a ContinueStatement<'a>), DebuggerStatement(&'a DebuggerStatement), DoWhileStatement(&'a DoWhileStatement<'a>), EmptyStatement(&'a EmptyStatement), @@ -39,21 +39,21 @@ pub enum AstKind<'a> { UsingDeclaration(&'a UsingDeclaration<'a>), - IdentifierName(&'a IdentifierName), - IdentifierReference(&'a IdentifierReference), - BindingIdentifier(&'a BindingIdentifier), - LabelIdentifier(&'a LabelIdentifier), - PrivateIdentifier(&'a PrivateIdentifier), + IdentifierName(&'a IdentifierName<'a>), + IdentifierReference(&'a IdentifierReference<'a>), + BindingIdentifier(&'a BindingIdentifier<'a>), + LabelIdentifier(&'a LabelIdentifier<'a>), + PrivateIdentifier(&'a PrivateIdentifier<'a>), NumericLiteral(&'a NumericLiteral<'a>), - StringLiteral(&'a StringLiteral), + StringLiteral(&'a StringLiteral<'a>), BooleanLiteral(&'a BooleanLiteral), NullLiteral(&'a NullLiteral), - BigintLiteral(&'a BigintLiteral), - RegExpLiteral(&'a RegExpLiteral), + BigintLiteral(&'a BigintLiteral<'a>), + RegExpLiteral(&'a RegExpLiteral<'a>), TemplateLiteral(&'a TemplateLiteral<'a>), - MetaProperty(&'a MetaProperty), + MetaProperty(&'a MetaProperty<'a>), Super(&'a Super), ArrayExpression(&'a ArrayExpression<'a>), @@ -110,9 +110,9 @@ pub enum AstKind<'a> { ModuleDeclaration(&'a ModuleDeclaration<'a>), ImportDeclaration(&'a ImportDeclaration<'a>), - ImportSpecifier(&'a ImportSpecifier), - ImportDefaultSpecifier(&'a ImportDefaultSpecifier), - ImportNamespaceSpecifier(&'a ImportNamespaceSpecifier), + ImportSpecifier(&'a ImportSpecifier<'a>), + ImportDefaultSpecifier(&'a ImportDefaultSpecifier<'a>), + ImportNamespaceSpecifier(&'a ImportNamespaceSpecifier<'a>), ExportDefaultDeclaration(&'a ExportDefaultDeclaration<'a>), ExportNamedDeclaration(&'a ExportNamedDeclaration<'a>), ExportAllDeclaration(&'a ExportAllDeclaration<'a>), @@ -127,11 +127,11 @@ pub enum AstKind<'a> { JSXExpressionContainer(&'a JSXExpressionContainer<'a>), JSXAttributeItem(&'a JSXAttributeItem<'a>), JSXSpreadAttribute(&'a JSXSpreadAttribute<'a>), - JSXText(&'a JSXText), - JSXIdentifier(&'a JSXIdentifier), + JSXText(&'a JSXText<'a>), + JSXIdentifier(&'a JSXIdentifier<'a>), JSXMemberExpression(&'a JSXMemberExpression<'a>), JSXMemberExpressionObject(&'a JSXMemberExpressionObject<'a>), - JSXNamespacedName(&'a JSXNamespacedName), + JSXNamespacedName(&'a JSXNamespacedName<'a>), // TypeScript TSModuleBlock(&'a TSModuleBlock<'a>), @@ -159,7 +159,7 @@ pub enum AstKind<'a> { TSImportEqualsDeclaration(&'a TSImportEqualsDeclaration<'a>), TSTypeName(&'a TSTypeName<'a>), - TSExternalModuleReference(&'a TSExternalModuleReference), + TSExternalModuleReference(&'a TSExternalModuleReference<'a>), TSQualifiedName(&'a TSQualifiedName<'a>), TSInterfaceDeclaration(&'a TSInterfaceDeclaration<'a>), @@ -245,7 +245,7 @@ impl<'a> AstKind<'a> { matches!(self, Self::Function(_) | Self::ArrowFunctionExpression(_)) } - pub fn identifier_name(self) -> Option { + pub fn identifier_name(self) -> Option> { match self { Self::BindingIdentifier(ident) => Some(ident.name.clone()), Self::IdentifierReference(ident) => Some(ident.name.clone()), diff --git a/crates/oxc_ast/src/span.rs b/crates/oxc_ast/src/span.rs index 5e4859d43e61d..fe8a8a5cb01fb 100644 --- a/crates/oxc_ast/src/span.rs +++ b/crates/oxc_ast/src/span.rs @@ -76,7 +76,7 @@ impl<'a> GetSpan for Expression<'a> { } } -impl GetSpan for Directive { +impl<'a> GetSpan for Directive<'a> { fn span(&self) -> Span { self.span } @@ -144,7 +144,7 @@ impl<'a> GetSpan for MemberExpression<'a> { } } -impl GetSpan for ImportAttributeKey { +impl<'a> GetSpan for ImportAttributeKey<'a> { fn span(&self) -> Span { match self { Self::Identifier(identifier) => identifier.span, @@ -153,7 +153,7 @@ impl GetSpan for ImportAttributeKey { } } -impl GetSpan for ModuleExportName { +impl<'a> GetSpan for ModuleExportName<'a> { fn span(&self) -> Span { match self { Self::Identifier(identifier) => identifier.span, @@ -191,7 +191,7 @@ impl<'a> GetSpan for Declaration<'a> { } } -impl GetSpan for TSModuleDeclarationName { +impl<'a> GetSpan for TSModuleDeclarationName<'a> { fn span(&self) -> Span { match self { Self::Identifier(ident) => ident.span, @@ -365,7 +365,7 @@ impl<'a> GetSpan for ExportDefaultDeclarationKind<'a> { } } -impl GetSpan for ImportDeclarationSpecifier { +impl<'a> GetSpan for ImportDeclarationSpecifier<'a> { fn span(&self) -> Span { match self { Self::ImportSpecifier(specifier) => specifier.span, diff --git a/crates/oxc_ast/src/syntax_directed_operations/bound_names.rs b/crates/oxc_ast/src/syntax_directed_operations/bound_names.rs index 35a3a0ba61346..180a889f82d78 100644 --- a/crates/oxc_ast/src/syntax_directed_operations/bound_names.rs +++ b/crates/oxc_ast/src/syntax_directed_operations/bound_names.rs @@ -1,16 +1,16 @@ use crate::ast::*; /// [`BoundName`](https://tc39.es/ecma262/#sec-static-semantics-boundnames) -pub trait BoundName { - fn bound_name(&self, f: &mut F); +pub trait BoundName<'a> { + fn bound_name)>(&self, f: &mut F); } -pub trait BoundNames { - fn bound_names(&self, f: &mut F); +pub trait BoundNames<'a> { + fn bound_names)>(&self, f: &mut F); } -impl<'a> BoundNames for BindingPattern<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for BindingPattern<'a> { + fn bound_names)>(&self, f: &mut F) { match &self.kind { BindingPatternKind::BindingIdentifier(ident) => ident.bound_names(f), BindingPatternKind::ArrayPattern(array) => array.bound_names(f), @@ -20,14 +20,14 @@ impl<'a> BoundNames for BindingPattern<'a> { } } -impl BoundNames for BindingIdentifier { +impl<'a> BoundNames<'a> for BindingIdentifier<'a> { fn bound_names(&self, f: &mut F) { f(self); } } -impl<'a> BoundNames for ArrayPattern<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for ArrayPattern<'a> { + fn bound_names)>(&self, f: &mut F) { for elem in self.elements.iter().flatten() { elem.bound_names(f); } @@ -37,8 +37,8 @@ impl<'a> BoundNames for ArrayPattern<'a> { } } -impl<'a> BoundNames for ObjectPattern<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for ObjectPattern<'a> { + fn bound_names)>(&self, f: &mut F) { for p in &self.properties { p.value.bound_names(f); } @@ -48,20 +48,20 @@ impl<'a> BoundNames for ObjectPattern<'a> { } } -impl<'a> BoundNames for AssignmentPattern<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for AssignmentPattern<'a> { + fn bound_names)>(&self, f: &mut F) { self.left.bound_names(f); } } -impl<'a> BoundNames for BindingRestElement<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for BindingRestElement<'a> { + fn bound_names)>(&self, f: &mut F) { self.argument.bound_names(f); } } -impl<'a> BoundNames for FormalParameters<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for FormalParameters<'a> { + fn bound_names)>(&self, f: &mut F) { for item in &self.items { item.bound_names(f); } @@ -71,8 +71,8 @@ impl<'a> BoundNames for FormalParameters<'a> { } } -impl<'a> BoundNames for Declaration<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for Declaration<'a> { + fn bound_names)>(&self, f: &mut F) { match self { Declaration::VariableDeclaration(decl) => decl.bound_names(f), Declaration::FunctionDeclaration(func) => func.bound_names(f), @@ -82,66 +82,66 @@ impl<'a> BoundNames for Declaration<'a> { } } -impl<'a> BoundNames for VariableDeclaration<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for VariableDeclaration<'a> { + fn bound_names)>(&self, f: &mut F) { for declarator in &self.declarations { declarator.id.bound_names(f); } } } -impl<'a> BoundNames for UsingDeclaration<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for UsingDeclaration<'a> { + fn bound_names)>(&self, f: &mut F) { for declarator in &self.declarations { declarator.id.bound_names(f); } } } -impl<'a> BoundName for Function<'a> { - fn bound_name(&self, f: &mut F) { +impl<'a> BoundName<'a> for Function<'a> { + fn bound_name)>(&self, f: &mut F) { if let Some(ident) = &self.id { f(ident); } } } -impl<'a> BoundNames for Function<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for Function<'a> { + fn bound_names)>(&self, f: &mut F) { self.bound_name(f); } } -impl<'a> BoundName for Class<'a> { - fn bound_name(&self, f: &mut F) { +impl<'a> BoundName<'a> for Class<'a> { + fn bound_name)>(&self, f: &mut F) { if let Some(ident) = &self.id { f(ident); } } } -impl<'a> BoundNames for Class<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for Class<'a> { + fn bound_names)>(&self, f: &mut F) { self.bound_name(f); } } -impl<'a> BoundNames for FormalParameter<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for FormalParameter<'a> { + fn bound_names)>(&self, f: &mut F) { self.pattern.bound_names(f); } } -impl<'a> BoundNames for ModuleDeclaration<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for ModuleDeclaration<'a> { + fn bound_names)>(&self, f: &mut F) { if let ModuleDeclaration::ImportDeclaration(decl) = &self { decl.bound_names(f); } } } -impl<'a> BoundNames for ImportDeclaration<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for ImportDeclaration<'a> { + fn bound_names)>(&self, f: &mut F) { if let Some(specifiers) = &self.specifiers { for specifier in specifiers { match specifier { @@ -160,8 +160,8 @@ impl<'a> BoundNames for ImportDeclaration<'a> { } } -impl<'a> BoundNames for ExportNamedDeclaration<'a> { - fn bound_names(&self, f: &mut F) { +impl<'a> BoundNames<'a> for ExportNamedDeclaration<'a> { + fn bound_names)>(&self, f: &mut F) { if let Some(decl) = &self.declaration { decl.bound_names(f); } diff --git a/crates/oxc_ast/src/syntax_directed_operations/gather_node_parts.rs b/crates/oxc_ast/src/syntax_directed_operations/gather_node_parts.rs index a727f8d22532b..49e5b358f8feb 100644 --- a/crates/oxc_ast/src/syntax_directed_operations/gather_node_parts.rs +++ b/crates/oxc_ast/src/syntax_directed_operations/gather_node_parts.rs @@ -2,12 +2,12 @@ use crate::ast::*; use oxc_span::Atom; // TODO: -pub trait GatherNodeParts { - fn gather(&self, f: &mut F); +pub trait GatherNodeParts<'a> { + fn gather)>(&self, f: &mut F); } -impl<'a> GatherNodeParts for Expression<'a> { - fn gather(&self, f: &mut F) { +impl<'a> GatherNodeParts<'a> for Expression<'a> { + fn gather)>(&self, f: &mut F) { match self { Self::Identifier(ident) => f(ident.name.clone()), Self::MemberExpression(expr) => expr.gather(f), @@ -19,8 +19,8 @@ impl<'a> GatherNodeParts for Expression<'a> { } } -impl<'a> GatherNodeParts for MemberExpression<'a> { - fn gather(&self, f: &mut F) { +impl<'a> GatherNodeParts<'a> for MemberExpression<'a> { + fn gather)>(&self, f: &mut F) { match self { MemberExpression::ComputedMemberExpression(expr) => { expr.object.gather(f); @@ -38,8 +38,8 @@ impl<'a> GatherNodeParts for MemberExpression<'a> { } } -impl<'a> GatherNodeParts for AssignmentTarget<'a> { - fn gather(&self, f: &mut F) { +impl<'a> GatherNodeParts<'a> for AssignmentTarget<'a> { + fn gather)>(&self, f: &mut F) { match self { AssignmentTarget::SimpleAssignmentTarget(t) => t.gather(f), AssignmentTarget::AssignmentTargetPattern(_) => {} @@ -47,8 +47,8 @@ impl<'a> GatherNodeParts for AssignmentTarget<'a> { } } -impl<'a> GatherNodeParts for SimpleAssignmentTarget<'a> { - fn gather(&self, f: &mut F) { +impl<'a> GatherNodeParts<'a> for SimpleAssignmentTarget<'a> { + fn gather)>(&self, f: &mut F) { match self { Self::AssignmentTargetIdentifier(ident) => ident.gather(f), Self::MemberAssignmentTarget(expr) => expr.gather(f), @@ -57,26 +57,26 @@ impl<'a> GatherNodeParts for SimpleAssignmentTarget<'a> { } } -impl GatherNodeParts for IdentifierReference { - fn gather(&self, f: &mut F) { +impl<'a> GatherNodeParts<'a> for IdentifierReference<'a> { + fn gather)>(&self, f: &mut F) { f(self.name.clone()); } } -impl GatherNodeParts for IdentifierName { - fn gather(&self, f: &mut F) { +impl<'a> GatherNodeParts<'a> for IdentifierName<'a> { + fn gather)>(&self, f: &mut F) { f(self.name.clone()); } } -impl GatherNodeParts for PrivateIdentifier { - fn gather(&self, f: &mut F) { +impl<'a> GatherNodeParts<'a> for PrivateIdentifier<'a> { + fn gather)>(&self, f: &mut F) { f(self.name.clone()); } } -impl GatherNodeParts for StringLiteral { - fn gather(&self, f: &mut F) { +impl<'a> GatherNodeParts<'a> for StringLiteral<'a> { + fn gather)>(&self, f: &mut F) { f(self.value.clone()); } } diff --git a/crates/oxc_ast/src/visit.rs b/crates/oxc_ast/src/visit.rs index 43dc880ada4c5..a592eca10414c 100644 --- a/crates/oxc_ast/src/visit.rs +++ b/crates/oxc_ast/src/visit.rs @@ -90,7 +90,7 @@ pub trait Visit<'a>: Sized { self.leave_scope(); } - fn visit_break_statement(&mut self, stmt: &BreakStatement) { + fn visit_break_statement(&mut self, stmt: &BreakStatement<'a>) { let kind = AstKind::BreakStatement(self.alloc(stmt)); self.enter_node(kind); if let Some(break_target) = &stmt.label { @@ -99,7 +99,7 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_continue_statement(&mut self, stmt: &ContinueStatement) { + fn visit_continue_statement(&mut self, stmt: &ContinueStatement<'a>) { let kind = AstKind::ContinueStatement(self.alloc(stmt)); self.enter_node(kind); if let Some(continue_target) = &stmt.label { @@ -323,7 +323,7 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_directive(&mut self, directive: &Directive) { + fn visit_directive(&mut self, directive: &Directive<'a>) { let kind = AstKind::Directive(self.alloc(directive)); self.enter_node(kind); self.visit_string_literal(&directive.expression); @@ -605,7 +605,7 @@ pub trait Visit<'a>: Sized { } } - fn visit_meta_property(&mut self, meta: &MetaProperty) { + fn visit_meta_property(&mut self, meta: &MetaProperty<'a>) { let kind = AstKind::MetaProperty(self.alloc(meta)); self.enter_node(kind); self.leave_node(kind); @@ -1053,7 +1053,7 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_jsx_identifier(&mut self, ident: &JSXIdentifier) { + fn visit_jsx_identifier(&mut self, ident: &JSXIdentifier<'a>) { let kind = AstKind::JSXIdentifier(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); @@ -1079,7 +1079,7 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_jsx_namespaced_name(&mut self, name: &JSXNamespacedName) { + fn visit_jsx_namespaced_name(&mut self, name: &JSXNamespacedName<'a>) { let kind = AstKind::JSXNamespacedName(self.alloc(name)); self.enter_node(kind); self.visit_jsx_identifier(&name.namespace); @@ -1157,7 +1157,7 @@ pub trait Visit<'a>: Sized { self.visit_expression(&child.expression); } - fn visit_jsx_text(&mut self, child: &JSXText) { + fn visit_jsx_text(&mut self, child: &JSXText<'a>) { let kind = AstKind::JSXText(self.alloc(child)); self.enter_node(kind); self.leave_node(kind); @@ -1179,7 +1179,7 @@ pub trait Visit<'a>: Sized { } } - fn visit_binding_identifier(&mut self, ident: &BindingIdentifier) { + fn visit_binding_identifier(&mut self, ident: &BindingIdentifier<'a>) { let kind = AstKind::BindingIdentifier(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); @@ -1231,25 +1231,25 @@ pub trait Visit<'a>: Sized { /* ---------- Identifier ---------- */ - fn visit_identifier_reference(&mut self, ident: &IdentifierReference) { + fn visit_identifier_reference(&mut self, ident: &IdentifierReference<'a>) { let kind = AstKind::IdentifierReference(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); } - fn visit_private_identifier(&mut self, ident: &PrivateIdentifier) { + fn visit_private_identifier(&mut self, ident: &PrivateIdentifier<'a>) { let kind = AstKind::PrivateIdentifier(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); } - fn visit_label_identifier(&mut self, ident: &LabelIdentifier) { + fn visit_label_identifier(&mut self, ident: &LabelIdentifier<'a>) { let kind = AstKind::LabelIdentifier(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); } - fn visit_identifier_name(&mut self, ident: &IdentifierName) { + fn visit_identifier_name(&mut self, ident: &IdentifierName<'a>) { let kind = AstKind::IdentifierName(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); @@ -1275,13 +1275,13 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_bigint_literal(&mut self, lit: &BigintLiteral) { + fn visit_bigint_literal(&mut self, lit: &BigintLiteral<'a>) { let kind = AstKind::BigintLiteral(self.alloc(lit)); self.enter_node(kind); self.leave_node(kind); } - fn visit_string_literal(&mut self, lit: &StringLiteral) { + fn visit_string_literal(&mut self, lit: &StringLiteral<'a>) { let kind = AstKind::StringLiteral(self.alloc(lit)); self.enter_node(kind); self.leave_node(kind); @@ -1299,7 +1299,7 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_reg_expr_literal(&mut self, lit: &RegExpLiteral) { + fn visit_reg_expr_literal(&mut self, lit: &RegExpLiteral<'a>) { let kind = AstKind::RegExpLiteral(self.alloc(lit)); self.enter_node(kind); self.leave_node(kind); @@ -1346,7 +1346,7 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_import_declaration_specifier(&mut self, specifier: &ImportDeclarationSpecifier) { + fn visit_import_declaration_specifier(&mut self, specifier: &ImportDeclarationSpecifier<'a>) { match &specifier { ImportDeclarationSpecifier::ImportSpecifier(specifier) => { self.visit_import_specifier(specifier); @@ -1360,7 +1360,7 @@ pub trait Visit<'a>: Sized { } } - fn visit_import_specifier(&mut self, specifier: &ImportSpecifier) { + fn visit_import_specifier(&mut self, specifier: &ImportSpecifier<'a>) { let kind = AstKind::ImportSpecifier(self.alloc(specifier)); self.enter_node(kind); // TODO: imported @@ -1368,14 +1368,14 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_import_default_specifier(&mut self, specifier: &ImportDefaultSpecifier) { + fn visit_import_default_specifier(&mut self, specifier: &ImportDefaultSpecifier<'a>) { let kind = AstKind::ImportDefaultSpecifier(self.alloc(specifier)); self.enter_node(kind); self.visit_binding_identifier(&specifier.local); self.leave_node(kind); } - fn visit_import_name_specifier(&mut self, specifier: &ImportNamespaceSpecifier) { + fn visit_import_name_specifier(&mut self, specifier: &ImportNamespaceSpecifier<'a>) { let kind = AstKind::ImportNamespaceSpecifier(self.alloc(specifier)); self.enter_node(kind); self.visit_binding_identifier(&specifier.local); @@ -1490,7 +1490,7 @@ pub trait Visit<'a>: Sized { self.leave_node(kind); } - fn visit_ts_external_module_reference(&mut self, reference: &TSExternalModuleReference) { + fn visit_ts_external_module_reference(&mut self, reference: &TSExternalModuleReference<'a>) { let kind = AstKind::TSExternalModuleReference(self.alloc(reference)); self.enter_node(kind); self.visit_string_literal(&reference.expression); diff --git a/crates/oxc_ast/src/visit_mut.rs b/crates/oxc_ast/src/visit_mut.rs index 22678ccb0fced..fa41384f46927 100644 --- a/crates/oxc_ast/src/visit_mut.rs +++ b/crates/oxc_ast/src/visit_mut.rs @@ -87,7 +87,7 @@ pub trait VisitMut<'a>: Sized { self.leave_scope(); } - fn visit_break_statement(&mut self, stmt: &mut BreakStatement) { + fn visit_break_statement(&mut self, stmt: &mut BreakStatement<'a>) { let kind = AstKind::BreakStatement(self.alloc(stmt)); self.enter_node(kind); if let Some(break_target) = &mut stmt.label { @@ -96,7 +96,7 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_continue_statement(&mut self, stmt: &mut ContinueStatement) { + fn visit_continue_statement(&mut self, stmt: &mut ContinueStatement<'a>) { let kind = AstKind::ContinueStatement(self.alloc(stmt)); self.enter_node(kind); if let Some(continue_target) = &mut stmt.label { @@ -320,7 +320,7 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_directive(&mut self, directive: &mut Directive) { + fn visit_directive(&mut self, directive: &mut Directive<'a>) { let kind = AstKind::Directive(self.alloc(directive)); self.enter_node(kind); self.visit_string_literal(&mut directive.expression); @@ -595,7 +595,7 @@ pub trait VisitMut<'a>: Sized { } } - fn visit_meta_property(&mut self, meta: &mut MetaProperty) { + fn visit_meta_property(&mut self, meta: &mut MetaProperty<'a>) { let kind = AstKind::MetaProperty(self.alloc(meta)); self.enter_node(kind); self.leave_node(kind); @@ -1052,7 +1052,7 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_jsx_identifier(&mut self, ident: &mut JSXIdentifier) { + fn visit_jsx_identifier(&mut self, ident: &mut JSXIdentifier<'a>) { let kind = AstKind::JSXIdentifier(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); @@ -1078,7 +1078,7 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_jsx_namespaced_name(&mut self, name: &mut JSXNamespacedName) { + fn visit_jsx_namespaced_name(&mut self, name: &mut JSXNamespacedName<'a>) { let kind = AstKind::JSXNamespacedName(self.alloc(name)); self.enter_node(kind); self.visit_jsx_identifier(&mut name.namespace); @@ -1156,13 +1156,13 @@ pub trait VisitMut<'a>: Sized { self.visit_expression(&mut child.expression); } - fn visit_jsx_text(&mut self, child: &JSXText) { + fn visit_jsx_text(&mut self, child: &JSXText<'a>) { let kind = AstKind::JSXText(self.alloc(child)); self.enter_node(kind); self.leave_node(kind); } - /* ---------- Pattern ---------- */ + /*<'a> ---------- Pattern ---------- */ fn visit_binding_pattern(&mut self, pat: &mut BindingPattern<'a>) { match &mut pat.kind { @@ -1178,7 +1178,7 @@ pub trait VisitMut<'a>: Sized { } } - fn visit_binding_identifier(&mut self, ident: &mut BindingIdentifier) { + fn visit_binding_identifier(&mut self, ident: &mut BindingIdentifier<'a>) { let kind = AstKind::BindingIdentifier(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); @@ -1230,25 +1230,25 @@ pub trait VisitMut<'a>: Sized { /* ---------- Identifier ---------- */ - fn visit_identifier_reference(&mut self, ident: &mut IdentifierReference) { + fn visit_identifier_reference(&mut self, ident: &mut IdentifierReference<'a>) { let kind = AstKind::IdentifierReference(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); } - fn visit_private_identifier(&mut self, ident: &mut PrivateIdentifier) { + fn visit_private_identifier(&mut self, ident: &mut PrivateIdentifier<'a>) { let kind = AstKind::PrivateIdentifier(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); } - fn visit_label_identifier(&mut self, ident: &mut LabelIdentifier) { + fn visit_label_identifier(&mut self, ident: &mut LabelIdentifier<'a>) { let kind = AstKind::LabelIdentifier(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); } - fn visit_identifier_name(&mut self, ident: &mut IdentifierName) { + fn visit_identifier_name(&mut self, ident: &mut IdentifierName<'a>) { let kind = AstKind::IdentifierName(self.alloc(ident)); self.enter_node(kind); self.leave_node(kind); @@ -1274,13 +1274,13 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_bigint_literal(&mut self, lit: &mut BigintLiteral) { + fn visit_bigint_literal(&mut self, lit: &mut BigintLiteral<'a>) { let kind = AstKind::BigintLiteral(self.alloc(lit)); self.enter_node(kind); self.leave_node(kind); } - fn visit_string_literal(&mut self, lit: &mut StringLiteral) { + fn visit_string_literal(&mut self, lit: &mut StringLiteral<'a>) { let kind = AstKind::StringLiteral(self.alloc(lit)); self.enter_node(kind); self.leave_node(kind); @@ -1298,7 +1298,7 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_reg_expr_literal(&mut self, lit: &mut RegExpLiteral) { + fn visit_reg_expr_literal(&mut self, lit: &mut RegExpLiteral<'a>) { let kind = AstKind::RegExpLiteral(self.alloc(lit)); self.enter_node(kind); self.leave_node(kind); @@ -1345,7 +1345,10 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_import_declaration_specifier(&mut self, specifier: &mut ImportDeclarationSpecifier) { + fn visit_import_declaration_specifier( + &mut self, + specifier: &mut ImportDeclarationSpecifier<'a>, + ) { match specifier { ImportDeclarationSpecifier::ImportSpecifier(specifier) => { self.visit_import_specifier(specifier); @@ -1359,7 +1362,7 @@ pub trait VisitMut<'a>: Sized { } } - fn visit_import_specifier(&mut self, specifier: &mut ImportSpecifier) { + fn visit_import_specifier(&mut self, specifier: &mut ImportSpecifier<'a>) { let kind = AstKind::ImportSpecifier(self.alloc(specifier)); self.enter_node(kind); // TODO: imported @@ -1367,14 +1370,14 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_import_default_specifier(&mut self, specifier: &mut ImportDefaultSpecifier) { + fn visit_import_default_specifier(&mut self, specifier: &mut ImportDefaultSpecifier<'a>) { let kind = AstKind::ImportDefaultSpecifier(self.alloc(specifier)); self.enter_node(kind); self.visit_binding_identifier(&mut specifier.local); self.leave_node(kind); } - fn visit_import_name_specifier(&mut self, specifier: &mut ImportNamespaceSpecifier) { + fn visit_import_name_specifier(&mut self, specifier: &mut ImportNamespaceSpecifier<'a>) { let kind = AstKind::ImportNamespaceSpecifier(self.alloc(specifier)); self.enter_node(kind); self.visit_binding_identifier(&mut specifier.local); @@ -1488,7 +1491,10 @@ pub trait VisitMut<'a>: Sized { self.leave_node(kind); } - fn visit_ts_external_module_reference(&mut self, reference: &mut TSExternalModuleReference) { + fn visit_ts_external_module_reference( + &mut self, + reference: &mut TSExternalModuleReference<'a>, + ) { let kind = AstKind::TSExternalModuleReference(self.alloc(reference)); self.enter_node(kind); self.visit_string_literal(&mut reference.expression); diff --git a/crates/oxc_codegen/src/gen.rs b/crates/oxc_codegen/src/gen.rs index 9800627cc0577..a67e4ec167837 100644 --- a/crates/oxc_codegen/src/gen.rs +++ b/crates/oxc_codegen/src/gen.rs @@ -60,14 +60,14 @@ fn print_directives_and_statements( ); } -impl Gen for Hashbang { +impl<'a, const MINIFY: bool> Gen for Hashbang<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { p.print_str(b"#!"); p.print_str(self.value.as_bytes()); } } -impl Gen for Directive { +impl<'a, const MINIFY: bool> Gen for Directive<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { // A Use Strict Directive may not contain an EscapeSequence or LineContinuation. // So here should print original `directive` value, the `expression` value is escaped str. @@ -344,7 +344,7 @@ impl Gen for EmptyStatement { } } -impl Gen for ContinueStatement { +impl<'a, const MINIFY: bool> Gen for ContinueStatement<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { p.print_indent(); p.print_str(b"continue"); @@ -356,7 +356,7 @@ impl Gen for ContinueStatement { } } -impl Gen for BreakStatement { +impl<'a, const MINIFY: bool> Gen for BreakStatement<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { p.print_indent(); p.print_str(b"break"); @@ -797,7 +797,7 @@ impl<'a, const MINIFY: bool> Gen for WithClause<'a> { } } -impl Gen for ImportAttribute { +impl<'a, const MINIFY: bool> Gen for ImportAttribute<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { match &self.key { ImportAttributeKey::Identifier(identifier) => { @@ -838,7 +838,7 @@ impl<'a, const MINIFY: bool> Gen for ExportNamedDeclaration<'a> { } } -impl Gen for ExportSpecifier { +impl<'a, const MINIFY: bool> Gen for ExportSpecifier<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { self.local.gen(p, ctx); if self.local.name() != self.exported.name() { @@ -848,7 +848,7 @@ impl Gen for ExportSpecifier { } } -impl Gen for ModuleExportName { +impl<'a, const MINIFY: bool> Gen for ModuleExportName<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { match self { Self::Identifier(identifier) => { @@ -977,7 +977,7 @@ impl<'a, const MINIFY: bool> GenExpr for TSAsExpression<'a> { } } } -impl Gen for IdentifierReference { +impl<'a, const MINIFY: bool> Gen for IdentifierReference<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { // if let Some(mangler) = &p.mangler { // if let Some(reference_id) = self.reference_id.get() { @@ -991,19 +991,19 @@ impl Gen for IdentifierReference { } } -impl Gen for IdentifierName { +impl<'a, const MINIFY: bool> Gen for IdentifierName<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { p.print_str(self.name.as_bytes()); } } -impl Gen for BindingIdentifier { +impl<'a, const MINIFY: bool> Gen for BindingIdentifier<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { p.print_symbol(self.symbol_id.get(), &self.name); } } -impl Gen for LabelIdentifier { +impl<'a, const MINIFY: bool> Gen for LabelIdentifier<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { p.print_str(self.name.as_bytes()); } @@ -1130,7 +1130,7 @@ fn print_non_negative_float(value: f64, _p: &Codegen<{ MINIF result } -impl Gen for BigintLiteral { +impl<'a, const MINIFY: bool> Gen for BigintLiteral<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { if self.raw.contains('_') { p.print_str(self.raw.replace('_', "").as_bytes()); @@ -1140,7 +1140,7 @@ impl Gen for BigintLiteral { } } -impl Gen for RegExpLiteral { +impl<'a, const MINIFY: bool> Gen for RegExpLiteral<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { let last = p.peek_nth(0); // Avoid forming a single-line comment or "(s: &str, quote: char, p: &mut Codegen< } } -impl Gen for StringLiteral { +impl<'a, const MINIFY: bool> Gen for StringLiteral<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { let s = self.value.as_str(); p.wrap_quote(s, |p, quote| { @@ -1920,7 +1920,7 @@ impl<'a, const MINIFY: bool> GenExpr for NewExpression<'a> { } } -impl Gen for MetaProperty { +impl<'a, const MINIFY: bool> Gen for MetaProperty<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { self.meta.gen(p, ctx); p.print(b'.'); @@ -1988,7 +1988,7 @@ impl<'a, const MINIFY: bool> Gen for ClassElement<'a> { } } -impl Gen for JSXIdentifier { +impl<'a, const MINIFY: bool> Gen for JSXIdentifier<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { p.print_str(self.name.as_bytes()); } @@ -2021,7 +2021,7 @@ impl<'a, const MINIFY: bool> Gen for JSXElementName<'a> { } } -impl Gen for JSXNamespacedName { +impl<'a, const MINIFY: bool> Gen for JSXNamespacedName<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, ctx: Context) { self.namespace.gen(p, ctx); p.print(b':'); @@ -2145,7 +2145,7 @@ impl Gen for JSXClosingFragment { } } -impl Gen for JSXText { +impl<'a, const MINIFY: bool> Gen for JSXText<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { p.print_str(self.value.as_bytes()); } @@ -2306,7 +2306,7 @@ impl<'a, const MINIFY: bool> Gen for AccessorProperty<'a> { } } -impl Gen for PrivateIdentifier { +impl<'a, const MINIFY: bool> Gen for PrivateIdentifier<'a> { fn gen(&self, p: &mut Codegen<{ MINIFY }>, _ctx: Context) { p.print(b'#'); p.print_str(self.name.as_bytes()); diff --git a/crates/oxc_js_regex/src/ast.rs b/crates/oxc_js_regex/src/ast.rs index 6690c5f7386fc..ca3700687edfb 100644 --- a/crates/oxc_js_regex/src/ast.rs +++ b/crates/oxc_js_regex/src/ast.rs @@ -1,7 +1,7 @@ //! [`@eslint-community/regexpp`](https://github.com/eslint-community/regexpp/blob/2e8f1af992fb12eae46a446253e8fa3f6cede92a/src/ast.ts) use oxc_allocator::{Box, Vec}; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; /// The type which includes all nodes. #[derive(Debug)] @@ -120,7 +120,7 @@ pub struct Group<'a> { #[derive(Debug)] pub struct CapturingGroup<'a> { pub span: Span, - pub name: Option, + pub name: Option, pub alternatives: Vec<'a, Alternative<'a>>, pub references: Vec<'a, Backreference<'a>>, } @@ -267,8 +267,8 @@ pub enum UnicodePropertyCharacterSet<'a> { #[derive(Debug)] pub struct CharacterUnicodePropertyCharacterSet { pub span: Span, - pub key: Atom, - pub value: Option, + pub key: CompactString, + pub value: Option, pub negate: bool, } @@ -276,7 +276,7 @@ pub struct CharacterUnicodePropertyCharacterSet { #[derive(Debug)] pub struct StringsUnicodePropertyCharacterSet { pub span: Span, - pub key: Atom, + pub key: CompactString, } /// The expression character class. @@ -360,7 +360,7 @@ pub struct Character { #[derive(Debug)] pub enum BackreferenceRef { Number(i32), - Atom(Atom), + CompactString(CompactString), } /// The backreference. diff --git a/crates/oxc_linter/src/rules/deepscan/bad_array_method_on_arguments.rs b/crates/oxc_linter/src/rules/deepscan/bad_array_method_on_arguments.rs index 1ae3192bb654f..48b5b7c10fde1 100644 --- a/crates/oxc_linter/src/rules/deepscan/bad_array_method_on_arguments.rs +++ b/crates/oxc_linter/src/rules/deepscan/bad_array_method_on_arguments.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -19,7 +19,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; "The 'arguments' object does not have '{0}()' method. If an array method was intended, consider converting the 'arguments' object to an array or using ES6 rest parameter instead." ) )] -struct BadArrayMethodOnArgumentsDiagnostic(Atom, #[label] pub Span); +struct BadArrayMethodOnArgumentsDiagnostic(CompactString, #[label] pub Span); /// `https://deepscan.io/docs/rules/bad-array-method-on-arguments` #[derive(Debug, Default, Clone)] @@ -61,7 +61,7 @@ impl Rule for BadArrayMethodOnArguments { MemberExpression::StaticMemberExpression(expr) => { if ARRAY_METHODS.binary_search(&expr.property.name.as_str()).is_ok() { ctx.diagnostic(BadArrayMethodOnArgumentsDiagnostic( - expr.property.name.clone(), + expr.property.name.to_compact_string(), expr.span, )); } @@ -71,7 +71,7 @@ impl Rule for BadArrayMethodOnArguments { Expression::StringLiteral(name) => { if ARRAY_METHODS.binary_search(&name.value.as_str()).is_ok() { ctx.diagnostic(BadArrayMethodOnArgumentsDiagnostic( - name.value.clone(), + name.value.to_compact_string(), expr.span, )); } @@ -86,7 +86,7 @@ impl Rule for BadArrayMethodOnArguments { { if ARRAY_METHODS.binary_search(&name).is_ok() { ctx.diagnostic(BadArrayMethodOnArgumentsDiagnostic( - Atom::from(name), + CompactString::from(name), expr.span, )); } diff --git a/crates/oxc_linter/src/rules/deepscan/number_arg_out_of_range.rs b/crates/oxc_linter/src/rules/deepscan/number_arg_out_of_range.rs index a734767a3c2cb..1bc14fc8b7a2b 100644 --- a/crates/oxc_linter/src/rules/deepscan/number_arg_out_of_range.rs +++ b/crates/oxc_linter/src/rules/deepscan/number_arg_out_of_range.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -17,7 +17,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; severity(warning), help("The first argument of 'Number.prototype.{0}' should be a number between {1} and {2}") )] -struct NumberArgOutOfRangeDiagnostic(Atom, usize, usize, #[label] pub Span); +struct NumberArgOutOfRangeDiagnostic(CompactString, usize, usize, #[label] pub Span); /// `https://deepscan.io/docs/rules/number-arg-out-of-range` #[derive(Debug, Default, Clone)] @@ -52,19 +52,19 @@ impl Rule for NumberArgOutOfRange { match member.static_property_name() { Some(name @ "toString") => { if !(2.0_f64..=36.0_f64).contains(&value) { - let name = Atom::from(name); + let name = CompactString::from(name); ctx.diagnostic(NumberArgOutOfRangeDiagnostic(name, 2, 36, expr.span)); } } Some(name @ ("toFixed" | "toExponential")) => { if !(0.0_f64..=20.0_f64).contains(&value) { - let name = Atom::from(name); + let name = CompactString::from(name); ctx.diagnostic(NumberArgOutOfRangeDiagnostic(name, 0, 20, expr.span)); } } Some(name @ "toPrecision") => { if !(1.0_f64..=21.0_f64).contains(&value) { - let name = Atom::from(name); + let name = CompactString::from(name); ctx.diagnostic(NumberArgOutOfRangeDiagnostic(name, 1, 21, expr.span)); } } diff --git a/crates/oxc_linter/src/rules/eslint/array_callback_return/mod.rs b/crates/oxc_linter/src/rules/eslint/array_callback_return/mod.rs index cc652f94a058f..9d97f545fc075 100644 --- a/crates/oxc_linter/src/rules/eslint/array_callback_return/mod.rs +++ b/crates/oxc_linter/src/rules/eslint/array_callback_return/mod.rs @@ -9,7 +9,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{CompactString, GetSpan, Span}; use phf::phf_set; use serde_json::Value; @@ -28,14 +28,14 @@ enum ArrayCallbackReturnDiagnostic { severity(warning), help("Array method {0:?} needs to have valid return on all code paths") )] - ExpectReturn(Atom, #[label] Span), + ExpectReturn(CompactString, #[label] Span), #[error("eslint(array-callback-return): Unexpected return for array method {0}")] #[diagnostic( severity(warning), help("Array method {0} expects no useless return from the function") )] - ExpectNoReturn(Atom, #[label] Span), + ExpectNoReturn(CompactString, #[label] Span), } #[derive(Debug, Default, Clone)] @@ -243,10 +243,10 @@ const TARGET_METHODS: phf::Set<&'static str> = phf_set! { "toSorted", }; -fn full_array_method_name(array_method: &'static str) -> Atom { +fn full_array_method_name(array_method: &'static str) -> CompactString { match array_method { - "from" => Atom::from("Array.from"), - s => Atom::from(format!("Array.prototype.{s}")), + "from" => CompactString::from("Array.from"), + s => CompactString::from(format!("Array.prototype.{s}")), } } diff --git a/crates/oxc_linter/src/rules/eslint/no_class_assign.rs b/crates/oxc_linter/src/rules/eslint/no_class_assign.rs index 58d52cfee9622..6e5a94b5f4671 100644 --- a/crates/oxc_linter/src/rules/eslint/no_class_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_class_assign.rs @@ -4,7 +4,7 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::SymbolId; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule}; @@ -12,7 +12,7 @@ use crate::{context::LintContext, rule::Rule}; #[error("eslint(no-class-assign): Unexpected re-assignment of class {0}")] #[diagnostic(severity(warning))] struct NoClassAssignDiagnostic( - Atom, + CompactString, #[label("{0} is declared as class here")] pub Span, #[label("{0} is re-assigned here")] pub Span, ); @@ -45,7 +45,7 @@ impl Rule for NoClassAssign { for reference in symbol_table.get_resolved_references(symbol_id) { if reference.is_write() { ctx.diagnostic(NoClassAssignDiagnostic( - symbol_table.get_name(symbol_id).clone(), + symbol_table.get_name(symbol_id).into(), symbol_table.get_span(symbol_id), reference.span(), )); diff --git a/crates/oxc_linter/src/rules/eslint/no_const_assign.rs b/crates/oxc_linter/src/rules/eslint/no_const_assign.rs index 9c04e628af9ec..8de3f7e7200aa 100644 --- a/crates/oxc_linter/src/rules/eslint/no_const_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_const_assign.rs @@ -4,7 +4,7 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::SymbolId; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule}; @@ -12,7 +12,7 @@ use crate::{context::LintContext, rule::Rule}; #[error("eslint(no-const-assign): Unexpected re-assignment of const variable {0}")] #[diagnostic(severity(warning))] struct NoConstAssignDiagnostic( - Atom, + CompactString, #[label("{0} is declared here as const")] pub Span, #[label("{0} is re-assigned here")] pub Span, ); @@ -44,7 +44,7 @@ impl Rule for NoConstAssign { for reference in symbol_table.get_resolved_references(symbol_id) { if reference.is_write() { ctx.diagnostic(NoConstAssignDiagnostic( - symbol_table.get_name(symbol_id).clone(), + symbol_table.get_name(symbol_id).into(), symbol_table.get_span(symbol_id), reference.span(), )); diff --git a/crates/oxc_linter/src/rules/eslint/no_control_regex.rs b/crates/oxc_linter/src/rules/eslint/no_control_regex.rs index 4b1b0c754a731..8a9427f9fb520 100644 --- a/crates/oxc_linter/src/rules/eslint/no_control_regex.rs +++ b/crates/oxc_linter/src/rules/eslint/no_control_regex.rs @@ -8,7 +8,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{Atom, CompactString, GetSpan, Span}; use regex::{Matches, Regex}; use crate::{ast_util::extract_regex_flags, context::LintContext, rule::Rule, AstNode}; @@ -19,7 +19,7 @@ use crate::{ast_util::extract_regex_flags, context::LintContext, rule::Rule, Ast severity(warning), help("Unexpected control character(s) in regular expression: \"{0}\"") )] -struct NoControlRegexDiagnostic(Atom, #[label] pub Span); +struct NoControlRegexDiagnostic(CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct NoControlRegex; @@ -72,7 +72,7 @@ impl Rule for NoControlRegex { if let Some(RegexPatternData { pattern, flags, span }) = regex_pattern(node) { let mut violations: Vec<&str> = Vec::new(); - for matched_ctl_pattern in control_patterns(pattern) { + for matched_ctl_pattern in control_patterns(pattern.as_str()) { let ctl = matched_ctl_pattern.as_str(); // check for an even number of backslashes, since these will @@ -144,7 +144,7 @@ impl Rule for NoControlRegex { struct RegexPatternData<'a> { /// A regex pattern, either from a literal (`/foo/`) a RegExp constructor /// (`new RegExp("foo")`), or a RegExp function call (`RegExp("foo")) - pattern: &'a Atom, + pattern: &'a Atom<'a>, /// Regex flags, if found. It's possible for this to be `Some` but have /// no flags. /// @@ -236,14 +236,14 @@ fn regex_pattern<'a>(node: &AstNode<'a>) -> Option> { } } -fn control_patterns(pattern: &Atom) -> Matches<'static, '_> { +fn control_patterns(pattern: &str) -> Matches<'static, '_> { lazy_static! { static ref CTL_PAT: Regex = Regex::new( r"([\x00-\x1f]|(?:\\x\w{2})|(?:\\u\w{4})|(?:\\u\{\w{1,4}\}))" // r"((?:\\x\w{2}))" ).unwrap(); } - CTL_PAT.find_iter(pattern.as_str()) + CTL_PAT.find_iter(pattern) } #[cfg(test)] diff --git a/crates/oxc_linter/src/rules/eslint/no_dupe_class_members.rs b/crates/oxc_linter/src/rules/eslint/no_dupe_class_members.rs index e4504ccf4ed80..e5fafef49731e 100644 --- a/crates/oxc_linter/src/rules/eslint/no_dupe_class_members.rs +++ b/crates/oxc_linter/src/rules/eslint/no_dupe_class_members.rs @@ -3,7 +3,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use rustc_hash::FxHashMap; use crate::{context::LintContext, rule::Rule}; @@ -17,7 +17,7 @@ use crate::{context::LintContext, rule::Rule}; ) )] struct NoDupeClassMembersDiagnostic( - Atom, /*Class member name */ + CompactString, /*Class member name */ #[label("{0:?} is previously declared here")] pub Span, #[label("{0:?} is re-declared here")] pub Span, ); diff --git a/crates/oxc_linter/src/rules/eslint/no_func_assign.rs b/crates/oxc_linter/src/rules/eslint/no_func_assign.rs index 112761a00c1fd..d9cb52ac8d3ee 100644 --- a/crates/oxc_linter/src/rules/eslint/no_func_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_func_assign.rs @@ -5,14 +5,14 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::SymbolId; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule}; #[derive(Debug, Error, Diagnostic)] #[error("eslint(no-func-assign): '{0}' is a function.")] #[diagnostic(severity(warning))] -struct NoFuncAssignDiagnostic(Atom, #[label("{0} is re-assigned here")] pub Span); +struct NoFuncAssignDiagnostic(CompactString, #[label("{0} is re-assigned here")] pub Span); #[derive(Debug, Default, Clone)] pub struct NoFuncAssign; @@ -42,7 +42,7 @@ impl Rule for NoFuncAssign { for reference in symbol_table.get_resolved_references(symbol_id) { if reference.is_write() { ctx.diagnostic(NoFuncAssignDiagnostic( - symbol_table.get_name(symbol_id).clone(), + symbol_table.get_name(symbol_id).into(), reference.span(), )); } diff --git a/crates/oxc_linter/src/rules/eslint/no_global_assign.rs b/crates/oxc_linter/src/rules/eslint/no_global_assign.rs index 0875f9ba531a7..1fc492f9fad3a 100644 --- a/crates/oxc_linter/src/rules/eslint/no_global_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_global_assign.rs @@ -3,7 +3,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule}; @@ -11,7 +11,7 @@ use crate::{context::LintContext, rule::Rule}; #[error("eslint(no-global-assign): Read-only global '{0}' should not be modified.")] #[diagnostic(severity(warning))] struct NoGlobalAssignDiagnostic( - Atom, + CompactString, #[label("Read-only global '{0}' should not be modified.")] pub Span, ); @@ -20,7 +20,7 @@ pub struct NoGlobalAssign(Box); #[derive(Debug, Default, Clone)] pub struct NoGlobalAssignConfig { - excludes: Vec, + excludes: Vec, } impl std::ops::Deref for NoGlobalAssign { @@ -58,8 +58,8 @@ impl Rule for NoGlobalAssign { .iter() .map(serde_json::Value::as_str) .filter(std::option::Option::is_some) - .map(|x| Atom::from(x.unwrap().to_string())) - .collect::>(), + .map(|x| CompactString::from(x.unwrap())) + .collect::>(), })) } diff --git a/crates/oxc_linter/src/rules/eslint/no_new_wrappers.rs b/crates/oxc_linter/src/rules/eslint/no_new_wrappers.rs index fe8c54cb1cbc4..f0c40f5aee16a 100644 --- a/crates/oxc_linter/src/rules/eslint/no_new_wrappers.rs +++ b/crates/oxc_linter/src/rules/eslint/no_new_wrappers.rs @@ -4,7 +4,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -16,7 +16,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; severity(warning), help("do not use {0} as a constructor, consider removing the new operator.") )] -struct NoNewWrappersDiagnostic(Atom, #[label] pub Span); +struct NoNewWrappersDiagnostic(CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct NoNewWrappers; @@ -47,7 +47,7 @@ impl Rule for NoNewWrappers { if (ident.name == "String" || ident.name == "Number" || ident.name == "Boolean") && ctx.semantic().is_reference_to_global_variable(ident) { - ctx.diagnostic(NoNewWrappersDiagnostic(ident.name.clone(), expr.span)); + ctx.diagnostic(NoNewWrappersDiagnostic(ident.name.to_compact_string(), expr.span)); } } } diff --git a/crates/oxc_linter/src/rules/eslint/no_obj_calls.rs b/crates/oxc_linter/src/rules/eslint/no_obj_calls.rs index 8d11df56f6e3d..71f1cc7bd4c10 100644 --- a/crates/oxc_linter/src/rules/eslint/no_obj_calls.rs +++ b/crates/oxc_linter/src/rules/eslint/no_obj_calls.rs @@ -8,7 +8,7 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::{AstNode, ScopeId}; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule}; @@ -18,7 +18,7 @@ const NON_CALLABLE_GLOBALS: [&str; 5] = ["Atomics", "Intl", "JSON", "Math", "Ref #[derive(Debug, Error, Diagnostic)] #[error("eslint(no-obj-calls): Disallow calling some global objects as functions")] #[diagnostic(severity(warning), help("{0} is not a function."))] -struct NoObjCallsDiagnostic(Atom, #[label] pub Span); +struct NoObjCallsDiagnostic(CompactString, #[label] pub Span); #[derive(Debug, Clone, PartialEq, Eq)] pub struct NoObjCalls; @@ -46,8 +46,8 @@ declare_oxc_lint! { /// let json = JSON(); /// let newJson = new JSON(); /// - /// let atomics = Atomics(); - /// let newAtomics = new Atomics(); + /// let atomics = CompactStringics(); + /// let newCompactStringics = new CompactStringics(); /// /// let intl = Intl(); /// let newIntl = new Intl(); @@ -58,32 +58,34 @@ declare_oxc_lint! { /// // Good /// let area = r => 2 * Math.PI * r * r; /// let object = JSON.parse("{}"); - /// let first = Atomics.load(sharedArray, 0); + /// let first = CompactStringics.load(sharedArray, 0); /// let segmenterFrom = Intl.Segmenter("fr", { granularity: "word" }); /// ``` NoObjCalls, correctness, } -fn is_global_obj(str: &Atom) -> bool { - NON_CALLABLE_GLOBALS.iter().any(|&n| str == &n) +fn is_global_obj(s: &str) -> bool { + NON_CALLABLE_GLOBALS.contains(&s) } -fn global_this_member(expr: &oxc_allocator::Box<'_, MemberExpression<'_>>) -> Option { +fn global_this_member<'a>( + expr: &'a oxc_allocator::Box<'_, MemberExpression<'_>>, +) -> Option<&'a str> { if expr.object().is_specific_id(GLOBAL_THIS) { - expr.static_property_name().map(std::convert::Into::into) + expr.static_property_name() } else { None } } fn resolve_global_binding<'a, 'b: 'a>( - ident: &oxc_allocator::Box<'a, IdentifierReference>, + ident: &'a oxc_allocator::Box<'a, IdentifierReference<'a>>, scope_id: ScopeId, ctx: &LintContext<'a>, -) -> Option { +) -> Option<&'a str> { if ctx.semantic().is_reference_to_global_variable(ident) { - Some(ident.name.clone()) + Some(ident.name.as_str()) } else { let scope = ctx.scopes(); let nodes = ctx.nodes(); @@ -102,7 +104,7 @@ fn resolve_global_binding<'a, 'b: 'a>( match decl.kind() { AstKind::VariableDeclarator(parent_decl) => { if !parent_decl.id.kind.is_binding_identifier() { - return Some(ident.name.clone()); + return Some(ident.name.as_str()); } match &parent_decl.init { // handles "let a = JSON; let b = a; a();" @@ -138,8 +140,8 @@ impl Rule for NoObjCalls { if let Some(top_level_reference) = resolve_global_binding(ident, node.scope_id(), ctx) { - if is_global_obj(&top_level_reference) { - ctx.diagnostic(NoObjCallsDiagnostic(ident.name.clone(), span)); + if is_global_obj(top_level_reference) { + ctx.diagnostic(NoObjCallsDiagnostic(ident.name.to_compact_string(), span)); } } } @@ -147,8 +149,8 @@ impl Rule for NoObjCalls { Expression::MemberExpression(expr) => { // handle new globalThis.Math(), globalThis.Math(), etc if let Some(global_member) = global_this_member(expr) { - if is_global_obj(&global_member) { - ctx.diagnostic(NoObjCallsDiagnostic(global_member, span)); + if is_global_obj(global_member) { + ctx.diagnostic(NoObjCallsDiagnostic(global_member.into(), span)); } } } @@ -169,7 +171,7 @@ fn test() { ("let m = foo.Math();", None), ("JSON.parse(\"{}\")", None), ("Math.PI * 2 * (r * r)", None), - ("bar.Atomic(foo)", None), + ("bar.Atomics(foo)", None), // reference test cases ( "let j = JSON; diff --git a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs index 3dabdb453577c..e3930e82de523 100644 --- a/crates/oxc_linter/src/rules/eslint/no_redeclare.rs +++ b/crates/oxc_linter/src/rules/eslint/no_redeclare.rs @@ -8,7 +8,7 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::VariableInfo; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule}; @@ -16,7 +16,7 @@ use crate::{context::LintContext, rule::Rule}; #[error("eslint(no-redeclare): '{0}' is already defined.")] #[diagnostic(severity(warning))] struct NoRedeclareDiagnostic( - Atom, + CompactString, #[label("'{0}' is already defined.")] pub Span, #[label("It can not be redeclare here.")] pub Span, ); @@ -25,7 +25,7 @@ struct NoRedeclareDiagnostic( #[error("eslint(no-redeclare): '{0}' is already defined as a built-in global variable.")] #[diagnostic(severity(warning))] struct NoRedeclareAsBuiltiInDiagnostic( - Atom, + CompactString, #[label("'{0}' is already defined as a built-in global variable.")] pub Span, ); @@ -33,7 +33,7 @@ struct NoRedeclareAsBuiltiInDiagnostic( #[error("eslint(no-redeclare): '{0}' is already defined by a variable declaration.")] #[diagnostic(severity(warning))] struct NoRedeclareBySyntaxDiagnostic( - Atom, + CompactString, #[label("'{0}' is already defined by a variable declaration.")] pub Span, #[label("It cannot be redeclared here.")] pub Span, ); @@ -81,14 +81,14 @@ impl Rule for NoRedeclare { match ctx.nodes().kind(decl) { AstKind::VariableDeclarator(var) => { if let BindingPatternKind::BindingIdentifier(ident) = &var.id.kind { - if *symbol_table.get_name(variable.symbol_id) == ident.name { + if symbol_table.get_name(variable.symbol_id) == ident.name.as_str() { self.report_diagnostic(ctx, variable, ident); } } } AstKind::FormalParameter(param) => { if let BindingPatternKind::BindingIdentifier(ident) = ¶m.pattern.kind { - if *symbol_table.get_name(variable.symbol_id) == ident.name { + if symbol_table.get_name(variable.symbol_id) == ident.name.as_str() { self.report_diagnostic(ctx, variable, ident); } } @@ -107,9 +107,16 @@ impl NoRedeclare { ident: &BindingIdentifier, ) { if self.built_in_globals && ctx.env_contains_var(&ident.name) { - ctx.diagnostic(NoRedeclareAsBuiltiInDiagnostic(ident.name.clone(), ident.span)); + ctx.diagnostic(NoRedeclareAsBuiltiInDiagnostic( + ident.name.to_compact_string(), + ident.span, + )); } else if variable.span != ident.span { - ctx.diagnostic(NoRedeclareDiagnostic(ident.name.clone(), ident.span, variable.span)); + ctx.diagnostic(NoRedeclareDiagnostic( + ident.name.to_compact_string(), + ident.span, + variable.span, + )); } } } diff --git a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs index 8252334f4b9d6..89e73a0d3eb99 100644 --- a/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs +++ b/crates/oxc_linter/src/rules/eslint/no_shadow_restricted_names.rs @@ -7,14 +7,14 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{Atom, CompactString, Span}; use crate::{context::LintContext, globals::PRE_DEFINE_VAR, rule::Rule}; #[derive(Debug, Error, Diagnostic)] #[error("eslint(no-shadow-restricted-names): Shadowing of global properties such as 'undefined' is not allowed.")] #[diagnostic(severity(warning), help("Shadowing of global properties '{0}'."))] -struct NoShadowRestrictedNamesDiagnostic(Atom, #[label] pub Span); +struct NoShadowRestrictedNamesDiagnostic(CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct NoShadowRestrictedNames; @@ -41,7 +41,7 @@ declare_oxc_lint!( correctness ); -fn binding_pattern_is_global_obj(pat: &BindingPattern) -> Option<(Atom, Span)> { +fn binding_pattern_is_global_obj<'a>(pat: &BindingPattern<'a>) -> Option<(Atom<'a>, Span)> { match &pat.kind { oxc_ast::ast::BindingPatternKind::BindingIdentifier(boxed_bind_identifier) => { if PRE_DEFINE_VAR.contains_key(boxed_bind_identifier.name.as_str()) { @@ -79,9 +79,9 @@ fn binding_pattern_is_global_obj(pat: &BindingPattern) -> Option<(Atom, Span)> { } #[inline] -fn check_and_diagnostic(atom: Atom, span: Span, ctx: &LintContext) { - if PRE_DEFINE_VAR.contains_key(atom.as_str()) { - ctx.diagnostic(NoShadowRestrictedNamesDiagnostic(atom, span)); +fn check_and_diagnostic(s: &str, span: Span, ctx: &LintContext) { + if PRE_DEFINE_VAR.contains_key(s) { + ctx.diagnostic(NoShadowRestrictedNamesDiagnostic(s.into(), span)); } } @@ -94,7 +94,10 @@ impl Rule for NoShadowRestrictedNames { AstKind::VariableDeclarator(decl) => { if let Some((atom, span)) = binding_pattern_is_global_obj(&decl.id) { if atom.as_str() != "undefined" || decl.init.is_some() { - ctx.diagnostic(NoShadowRestrictedNamesDiagnostic(atom, span)); + ctx.diagnostic(NoShadowRestrictedNamesDiagnostic( + atom.to_compact_string(), + span, + )); } else { nearest_span = Some(span); } @@ -109,7 +112,7 @@ impl Rule for NoShadowRestrictedNames { ) if ati.name == "undefined" => { if let Some(span) = nearest_span { ctx.diagnostic(NoShadowRestrictedNamesDiagnostic( - ati.name.clone(), + ati.name.to_compact_string(), span, )); } @@ -120,23 +123,29 @@ impl Rule for NoShadowRestrictedNames { } AstKind::Function(function) => { if let Some(bind_ident) = function.id.as_ref() { - check_and_diagnostic(bind_ident.name.clone(), bind_ident.span, ctx); + check_and_diagnostic(bind_ident.name.as_str(), bind_ident.span, ctx); } } AstKind::FormalParameter(param) => { if let Some(value) = binding_pattern_is_global_obj(¶m.pattern) { - ctx.diagnostic(NoShadowRestrictedNamesDiagnostic(value.0, value.1)); + ctx.diagnostic(NoShadowRestrictedNamesDiagnostic( + value.0.to_compact_string(), + value.1, + )); } } AstKind::Class(class_decl) => { if let Some(bind_ident) = class_decl.id.as_ref() { - check_and_diagnostic(bind_ident.name.clone(), bind_ident.span, ctx); + check_and_diagnostic(bind_ident.name.as_str(), bind_ident.span, ctx); } } AstKind::CatchClause(catch_clause) => { if let Some(param) = catch_clause.param.as_ref() { if let Some(value) = binding_pattern_is_global_obj(param) { - ctx.diagnostic(NoShadowRestrictedNamesDiagnostic(value.0, value.1)); + ctx.diagnostic(NoShadowRestrictedNamesDiagnostic( + value.0.to_compact_string(), + value.1, + )); } } } diff --git a/crates/oxc_linter/src/rules/eslint/no_undef.rs b/crates/oxc_linter/src/rules/eslint/no_undef.rs index a801132250e6b..575e5222dae02 100644 --- a/crates/oxc_linter/src/rules/eslint/no_undef.rs +++ b/crates/oxc_linter/src/rules/eslint/no_undef.rs @@ -4,7 +4,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use oxc_syntax::operator::UnaryOperator; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -12,7 +12,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; #[derive(Debug, Error, Diagnostic)] #[error("eslint(no-undef): Disallow the use of undeclared variables")] #[diagnostic(severity(warning), help("'{0}' is not defined."))] -struct NoUndefDiagnostic(Atom, #[label] pub Span); +struct NoUndefDiagnostic(CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct NoUndef { diff --git a/crates/oxc_linter/src/rules/eslint/no_unused_labels.rs b/crates/oxc_linter/src/rules/eslint/no_unused_labels.rs index 9e61e366ad1fe..6adc012aa91dc 100644 --- a/crates/oxc_linter/src/rules/eslint/no_unused_labels.rs +++ b/crates/oxc_linter/src/rules/eslint/no_unused_labels.rs @@ -4,14 +4,14 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, fixer::Fix, rule::Rule}; #[derive(Debug, Error, Diagnostic)] #[error("eslint(no-unused-labels): Disallow unused labels")] #[diagnostic(severity(warning), help("'{0}:' is defined but never used."))] -struct NoUnusedLabelsDiagnostic(Atom, #[label] pub Span); +struct NoUnusedLabelsDiagnostic(CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct NoUnusedLabels; @@ -51,7 +51,7 @@ impl Rule for NoUnusedLabels { // TODO: Ignore fix where comments exist between label and statement // e.g. A: /* Comment */ function foo(){} ctx.diagnostic_with_fix( - NoUnusedLabelsDiagnostic(stmt.label.name.clone(), stmt.label.span), + NoUnusedLabelsDiagnostic(stmt.label.name.to_compact_string(), stmt.label.span), || Fix::delete(stmt.label.span), ); } diff --git a/crates/oxc_linter/src/rules/eslint/no_unused_private_class_members.rs b/crates/oxc_linter/src/rules/eslint/no_unused_private_class_members.rs index 68f64fa660c0d..359ca2a08f3fc 100644 --- a/crates/oxc_linter/src/rules/eslint/no_unused_private_class_members.rs +++ b/crates/oxc_linter/src/rules/eslint/no_unused_private_class_members.rs @@ -6,7 +6,7 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::{AstNode, AstNodeId, AstNodes}; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use oxc_syntax::class::ElementKind; use crate::{context::LintContext, rule::Rule}; @@ -14,7 +14,7 @@ use crate::{context::LintContext, rule::Rule}; #[derive(Debug, Error, Diagnostic)] #[error("eslint(no-unused-private-class-members): '{0}' is defined but never used.")] #[diagnostic(severity(warning))] -struct NoUnusedPrivateClassMembersDiagnostic(Atom, #[label] pub Span); +struct NoUnusedPrivateClassMembersDiagnostic(CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct NoUnusedPrivateClassMembers; @@ -179,7 +179,7 @@ fn test() { }", r"class C { #usedMember; - + foo() { bar(this.#usedMember += 1); } @@ -192,11 +192,11 @@ fn test() { }", r"class C { #usedInOuterClass; - + foo() { return class {}; } - + bar() { return this.#usedInOuterClass; } @@ -205,7 +205,7 @@ fn test() { #usedInForInLoop; method() { for (const bar in this.#usedInForInLoop) { - + } } }", @@ -213,7 +213,7 @@ fn test() { #usedInForOfLoop; method() { for (const bar of this.#usedInForOfLoop) { - + } } }", @@ -237,7 +237,7 @@ fn test() { }", r"class C { #usedInObjectAssignment; - + method() { ({ [this.#usedInObjectAssignment]: a } = foo); } @@ -330,18 +330,18 @@ fn test() { }", r"class C { #usedOnlyInIncrement; - + foo() { this.#usedOnlyInIncrement++; } }", r"class C { #unusedInOuterClass; - + foo() { return class { #unusedInOuterClass; - + bar() { return this.#unusedInOuterClass; } @@ -350,21 +350,21 @@ fn test() { }", r"class C { #unusedOnlyInSecondNestedClass; - + foo() { return class { #unusedOnlyInSecondNestedClass; - + bar() { return this.#unusedOnlyInSecondNestedClass; } }; } - + baz() { return this.#unusedOnlyInSecondNestedClass; } - + bar() { return class { #unusedOnlyInSecondNestedClass; @@ -390,7 +390,7 @@ fn test() { #unusedForInLoop; method() { for (this.#unusedForInLoop in bar) { - + } } }", @@ -398,7 +398,7 @@ fn test() { #unusedForOfLoop; method() { for (this.#unusedForOfLoop of bar) { - + } } }", @@ -428,15 +428,15 @@ fn test() { }", r"class C { #usedOnlyInTheSecondInnerClass; - + method(a) { return class { #usedOnlyInTheSecondInnerClass; - + method2(b) { foo = b.#usedOnlyInTheSecondInnerClass; } - + method3(b) { foo = b.#usedOnlyInTheSecondInnerClass; } diff --git a/crates/oxc_linter/src/rules/import/export.rs b/crates/oxc_linter/src/rules/import/export.rs index fabe27333057e..8dce203041e97 100644 --- a/crates/oxc_linter/src/rules/import/export.rs +++ b/crates/oxc_linter/src/rules/import/export.rs @@ -6,7 +6,7 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::ModuleRecord; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use rustc_hash::{FxHashMap, FxHashSet}; use crate::{context::LintContext, rule::Rule}; @@ -15,10 +15,10 @@ use crate::{context::LintContext, rule::Rule}; enum ExportDiagnostic { #[error("eslint-plugin-import(export): Multiple exports of name '{1}'.")] #[diagnostic(severity(warning))] - MultipleNamedExport(#[label] Span, Atom), + MultipleNamedExport(#[label] Span, CompactString), #[error("eslint-plugin-import(export): No named exports found in module '{1}'")] #[diagnostic(severity(warning))] - NoNamedExport(#[label] Span, Atom), + NoNamedExport(#[label] Span, CompactString), } /// @@ -84,7 +84,7 @@ impl Rule for Export { fn walk_exported_recursive( module_record: &ModuleRecord, - result: &mut FxHashSet, + result: &mut FxHashSet, visited: &mut FxHashSet, ) { let path = &module_record.resolved_absolute_path; diff --git a/crates/oxc_linter/src/rules/import/namespace.rs b/crates/oxc_linter/src/rules/import/namespace.rs index 338c665072a35..5f66578ff238f 100644 --- a/crates/oxc_linter/src/rules/import/namespace.rs +++ b/crates/oxc_linter/src/rules/import/namespace.rs @@ -3,14 +3,14 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule}; #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-import(namespace): ")] #[diagnostic(severity(warning), help(""))] -struct NamespaceDiagnostic(Atom, #[label] pub Span); +struct NamespaceDiagnostic(CompactString, #[label] pub Span); /// #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/import/no_amd.rs b/crates/oxc_linter/src/rules/import/no_amd.rs index 3a93d21774c18..4feccd800dcd3 100644 --- a/crates/oxc_linter/src/rules/import/no_amd.rs +++ b/crates/oxc_linter/src/rules/import/no_amd.rs @@ -5,14 +5,14 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-import(no-amd): Do not use AMD `require` and `define` calls.")] #[diagnostic(severity(warning), help("Expected imports instead of AMD {1}()"))] -struct NoAmdDiagnostic(#[label] pub Span, Atom); +struct NoAmdDiagnostic(#[label] pub Span, CompactString); #[derive(Debug, Default, Clone)] pub struct NoAmd; @@ -54,7 +54,10 @@ impl Rule for NoAmd { if let Argument::Expression(Expression::ArrayExpression(_)) = call_expr.arguments[0] { - ctx.diagnostic(NoAmdDiagnostic(identifier.span, identifier.name.clone())); + ctx.diagnostic(NoAmdDiagnostic( + identifier.span, + identifier.name.to_compact_string(), + )); } } } diff --git a/crates/oxc_linter/src/rules/import/no_cycle.rs b/crates/oxc_linter/src/rules/import/no_cycle.rs index 11e1211738112..1b994cc49569b 100644 --- a/crates/oxc_linter/src/rules/import/no_cycle.rs +++ b/crates/oxc_linter/src/rules/import/no_cycle.rs @@ -11,7 +11,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use oxc_syntax::module_record::ModuleRecord; use crate::{context::LintContext, rule::Rule}; @@ -120,7 +120,7 @@ impl Rule for NoCycle { #[derive(Debug, Default)] struct State { traversed: HashSet, - stack: Vec<(Atom, PathBuf)>, + stack: Vec<(CompactString, PathBuf)>, } impl NoCycle { diff --git a/crates/oxc_linter/src/rules/import/no_deprecated.rs b/crates/oxc_linter/src/rules/import/no_deprecated.rs index 0a4a758d90995..01a0aeba5b0a5 100644 --- a/crates/oxc_linter/src/rules/import/no_deprecated.rs +++ b/crates/oxc_linter/src/rules/import/no_deprecated.rs @@ -3,14 +3,14 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule}; #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-import(namespace): ")] #[diagnostic(severity(warning), help(""))] -struct NoDeprecatedDiagnostic(Atom, #[label] pub Span); +struct NoDeprecatedDiagnostic(CompactString, #[label] pub Span); /// #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs b/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs index e6da200595f04..a1a42a24a6e9c 100644 --- a/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs +++ b/crates/oxc_linter/src/rules/import/no_named_as_default_member.rs @@ -12,7 +12,7 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::SymbolId; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use oxc_syntax::module_record::ImportImportName; use crate::{context::LintContext, rule::Rule}; @@ -58,7 +58,7 @@ impl Rule for NoNamedAsDefaultMember { fn run_once(&self, ctx: &LintContext<'_>) { let module_record = ctx.semantic().module_record(); - let mut has_members_map: HashMap, Atom)> = + let mut has_members_map: HashMap, CompactString)> = HashMap::default(); for import_entry in &module_record.import_entries { let ImportImportName::Default(_) = import_entry.import_name else { @@ -73,7 +73,7 @@ impl Rule for NoNamedAsDefaultMember { if !remote_module_record_ref.exported_bindings.is_empty() { has_members_map.insert( ctx.symbols().get_symbol_id_from_span(&import_entry.local_name.span()).unwrap(), - (remote_module_record_ref, import_entry.module_request.name().to_owned()), + (remote_module_record_ref, import_entry.module_request.name().clone()), ); } } @@ -82,7 +82,7 @@ impl Rule for NoNamedAsDefaultMember { return; }; let get_external_module_name_if_has_entry = - |ident: &IdentifierReference, entry_name: &Atom| { + |ident: &IdentifierReference, entry_name: &str| { get_symbol_id_from_ident(ctx, ident) .and_then(|symbol_id| has_members_map.get(&symbol_id)) .and_then(|it| { @@ -101,9 +101,7 @@ impl Rule for NoNamedAsDefaultMember { let Some(prop_str) = member_expr.static_property_name() else { return; }; - if let Some(module_name) = - get_external_module_name_if_has_entry(ident, &Atom::from(prop_str)) - { + if let Some(module_name) = get_external_module_name_if_has_entry(ident, prop_str) { ctx.diagnostic(NoNamedAsDefaultMemberDignostic( match member_expr { MemberExpression::ComputedMemberExpression(it) => it.span, diff --git a/crates/oxc_linter/src/rules/import/no_unused_modules.rs b/crates/oxc_linter/src/rules/import/no_unused_modules.rs index d558a430ef16c..d5b77a4b3a146 100644 --- a/crates/oxc_linter/src/rules/import/no_unused_modules.rs +++ b/crates/oxc_linter/src/rules/import/no_unused_modules.rs @@ -3,14 +3,14 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule}; #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-import(namespace): ")] #[diagnostic(severity(warning), help(""))] -struct NoUnusedModulesDiagnostic(Atom, #[label] pub Span); +struct NoUnusedModulesDiagnostic(CompactString, #[label] pub Span); /// #[derive(Debug, Default, Clone)] diff --git a/crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rs b/crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rs index d1cfc86209109..77de4d93045ee 100644 --- a/crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rs +++ b/crates/oxc_linter/src/rules/jest/no_confusing_set_timeout.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::{AstNode, AstNodeId, ReferenceId}; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{GetSpan, Span}; use crate::{ context::LintContext, @@ -236,7 +236,7 @@ fn is_jest_fn_call<'a>( parse_jest_fn_call(call_expr, possible_jest_node, ctx).is_some() } -fn is_jest_call(name: &Atom) -> bool { +fn is_jest_call(name: &str) -> bool { // handle "jest" | "Jest" | "JEST" | "JEst" to "jest", For example: // // import { jest as Jest } from "@jest/globals"; diff --git a/crates/oxc_linter/src/rules/jest/no_identical_title.rs b/crates/oxc_linter/src/rules/jest/no_identical_title.rs index dc5149983ba96..1fa2a6b16b087 100644 --- a/crates/oxc_linter/src/rules/jest/no_identical_title.rs +++ b/crates/oxc_linter/src/rules/jest/no_identical_title.rs @@ -120,7 +120,7 @@ fn filter_and_process_jest_result<'a>( call_expr: &'a CallExpression<'a>, possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>, -) -> Option<(Span, &'a Atom, JestFnKind, AstNodeId)> { +) -> Option<(Span, &'a Atom<'a>, JestFnKind, AstNodeId)> { let Some(result) = parse_general_jest_fn_call(call_expr, possible_jest_node, ctx) else { return None; }; diff --git a/crates/oxc_linter/src/rules/jest/no_test_prefixes.rs b/crates/oxc_linter/src/rules/jest/no_test_prefixes.rs index a625f6802ebba..01438d6e72de0 100644 --- a/crates/oxc_linter/src/rules/jest/no_test_prefixes.rs +++ b/crates/oxc_linter/src/rules/jest/no_test_prefixes.rs @@ -4,7 +4,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{CompactString, GetSpan, Span}; use crate::{ context::LintContext, @@ -19,7 +19,7 @@ use crate::{ #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-jest(no-test-prefixes): Use {0:?} instead.")] #[diagnostic(severity(warning))] -struct NoTestPrefixesDiagnostic(Atom, #[label] pub Span); +struct NoTestPrefixesDiagnostic(CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct NoTestPrefixes; @@ -91,7 +91,7 @@ fn run<'a>(possible_jest_node: &PossibleJestNode<'a, '_>, ctx: &LintContext<'a>) }); } -fn get_preferred_node_names(jest_fn_call: &ParsedGeneralJestFnCall) -> Atom { +fn get_preferred_node_names(jest_fn_call: &ParsedGeneralJestFnCall) -> CompactString { let ParsedGeneralJestFnCall { members, name, .. } = jest_fn_call; let preferred_modifier = if name.starts_with('f') { "only" } else { "skip" }; @@ -103,9 +103,9 @@ fn get_preferred_node_names(jest_fn_call: &ParsedGeneralJestFnCall) -> Atom { let name_slice = &name[1..]; if member_names.is_empty() { - Atom::from(format!("{name_slice}.{preferred_modifier}")) + CompactString::from(format!("{name_slice}.{preferred_modifier}")) } else { - Atom::from(format!("{name_slice}.{preferred_modifier}.{member_names}")) + CompactString::from(format!("{name_slice}.{preferred_modifier}.{member_names}")) } } diff --git a/crates/oxc_linter/src/rules/jest/valid_expect.rs b/crates/oxc_linter/src/rules/jest/valid_expect.rs index 8db7eff959d3e..c9ea7d7503bd7 100644 --- a/crates/oxc_linter/src/rules/jest/valid_expect.rs +++ b/crates/oxc_linter/src/rules/jest/valid_expect.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{CompactString, GetSpan, Span}; use crate::{ context::LintContext, @@ -21,7 +21,7 @@ use crate::{ #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-jest(valid-expect): {0:?}")] #[diagnostic(severity(warning), help("{1:?}"))] -struct ValidExpectDiagnostic(pub Atom, pub &'static str, #[label] pub Span); +struct ValidExpectDiagnostic(CompactString, &'static str, #[label] Span); #[derive(Debug, Default, Clone)] pub struct ValidExpect(Box); @@ -142,7 +142,7 @@ impl ValidExpect { let Some(Expression::CallExpression(call_expr)) = jest_fn_call.head.parent else { return }; if call_expr.arguments.len() < self.min_args { - let error = Atom::from(format!( + let error = CompactString::from(format!( "Expect takes at most {} argument{} ", self.min_args, if self.min_args > 1 { "s" } else { "" } @@ -152,7 +152,7 @@ impl ValidExpect { return; } if call_expr.arguments.len() > self.max_args { - let error = Atom::from(format!( + let error = CompactString::from(format!( "Expect requires at least {} argument{} ", self.max_args, if self.max_args > 1 { "s" } else { "" } @@ -360,24 +360,26 @@ enum Message { } impl Message { - fn details(self) -> (Atom, &'static str) { + fn details(self) -> (CompactString, &'static str) { match self { Self::MatcherNotFound => ( - Atom::from("Expect must have a corresponding matcher call."), + CompactString::from("Expect must have a corresponding matcher call."), "Did you forget add a matcher(e.g. `toBe`, `toBeDefined`)", ), Self::MatcherNotCalled => ( - Atom::from("Matchers must be called to assert."), + CompactString::from("Matchers must be called to assert."), "You need call your matcher, e.g. `expect(true).toBe(true)`.", ), - Self::ModifierUnknown => { - (Atom::from("Expect has an unknown modifier."), "Is it a spelling mistake?") - } - Self::AsyncMustBeAwaited => { - (Atom::from("Async assertions must be awaited."), "Add `await` to your assertion.") - } + Self::ModifierUnknown => ( + CompactString::from("Expect has an unknown modifier."), + "Is it a spelling mistake?", + ), + Self::AsyncMustBeAwaited => ( + CompactString::from("Async assertions must be awaited."), + "Add `await` to your assertion.", + ), Self::PromisesWithAsyncAssertionsMustBeAwaited => ( - Atom::from("Promises which return async assertions must be awaited."), + CompactString::from("Promises which return async assertions must be awaited."), "Add `await` to your assertion.", ), } diff --git a/crates/oxc_linter/src/rules/jest/valid_title.rs b/crates/oxc_linter/src/rules/jest/valid_title.rs index f11719775ea21..204cb77696d2e 100644 --- a/crates/oxc_linter/src/rules/jest/valid_title.rs +++ b/crates/oxc_linter/src/rules/jest/valid_title.rs @@ -9,7 +9,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{CompactString, GetSpan, Span}; use regex::Regex; use crate::{ @@ -24,7 +24,7 @@ use crate::{ #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-jest(valid-title): {0:?}")] #[diagnostic(severity(warning), help("{1:?}"))] -struct ValidTitleDiagnostic(Atom, &'static str, #[label] pub Span); +struct ValidTitleDiagnostic(CompactString, &'static str, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct ValidTitle(Box); @@ -293,7 +293,7 @@ fn validate_title( if let Some(matched) = disallowed_words_reg.find(title) { let error = format!("{} is not allowed in test title", matched.as_str()); ctx.diagnostic(ValidTitleDiagnostic( - Atom::from(error), + CompactString::from(error), "It is included in the `disallowedWords` of your config file, try to remove it from your title", span, )); @@ -325,8 +325,8 @@ fn validate_title( if !regex.is_match(title) { let raw_pattern = regex.as_str(); let message = message.as_ref().map_or_else( - || Atom::from(format!("{un_prefixed_name} should match {raw_pattern}")), - |message| Atom::from(message.as_str()), + || CompactString::from(format!("{un_prefixed_name} should match {raw_pattern}")), + |message| CompactString::from(message.as_str()), ); ctx.diagnostic(ValidTitleDiagnostic( message, @@ -340,8 +340,12 @@ fn validate_title( if regex.is_match(title) { let raw_pattern = regex.as_str(); let message = message.as_ref().map_or_else( - || Atom::from(format!("{un_prefixed_name} should not match {raw_pattern}")), - |message| Atom::from(message.as_str()), + || { + CompactString::from(format!( + "{un_prefixed_name} should not match {raw_pattern}" + )) + }, + |message| CompactString::from(message.as_str()), ); ctx.diagnostic(ValidTitleDiagnostic( @@ -382,7 +386,7 @@ impl Message { } fn diagnostic(&self, ctx: &LintContext, span: Span) { let (error, help) = self.detail(); - ctx.diagnostic(ValidTitleDiagnostic(Atom::from(error), help, span)); + ctx.diagnostic(ValidTitleDiagnostic(CompactString::from(error), help, span)); } } diff --git a/crates/oxc_linter/src/rules/oxc/only_used_in_recursion.rs b/crates/oxc_linter/src/rules/oxc/only_used_in_recursion.rs index 395a16bdd7a22..5884d1a12dbba 100644 --- a/crates/oxc_linter/src/rules/oxc/only_used_in_recursion.rs +++ b/crates/oxc_linter/src/rules/oxc/only_used_in_recursion.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{CompactString, GetSpan, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -19,7 +19,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; "Remove the argument and its usage. Alternatively, use the argument in the function body." ) )] -struct OnlyUsedInRecursionDiagnostic(#[label] pub Span, pub Atom); +struct OnlyUsedInRecursionDiagnostic(#[label] pub Span, pub CompactString); #[derive(Debug, Default, Clone)] pub struct OnlyUsedInRecursion; @@ -79,7 +79,10 @@ impl Rule for OnlyUsedInRecursion { let BindingPatternKind::BindingIdentifier(arg) = &arg.pattern.kind else { continue }; if is_argument_only_used_in_recursion(function_id, arg, arg_index, ctx) { - ctx.diagnostic(OnlyUsedInRecursionDiagnostic(arg.span, arg.name.clone())); + ctx.diagnostic(OnlyUsedInRecursionDiagnostic( + arg.span, + arg.name.to_compact_string(), + )); } } } diff --git a/crates/oxc_linter/src/rules/react/jsx_no_duplicate_props.rs b/crates/oxc_linter/src/rules/react/jsx_no_duplicate_props.rs index 2384fc1916dd0..0b4857b21506d 100644 --- a/crates/oxc_linter/src/rules/react/jsx_no_duplicate_props.rs +++ b/crates/oxc_linter/src/rules/react/jsx_no_duplicate_props.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{Atom, CompactString, Span}; use rustc_hash::FxHashMap; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -20,7 +20,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; severity(warning), help("Remove one of the props, or rename them so each prop is distinct.") )] -struct JsxNoDuplicatePropsDiagnostic(Atom, #[label] pub Span, #[label] pub Span); +struct JsxNoDuplicatePropsDiagnostic(CompactString, #[label] pub Span, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct JsxNoDuplicateProps; @@ -63,7 +63,7 @@ impl Rule for JsxNoDuplicateProps { if let Some(old_span) = props.insert(ident.name.clone(), ident.span) { ctx.diagnostic(JsxNoDuplicatePropsDiagnostic( - ident.name.clone(), + ident.name.to_compact_string(), old_span, ident.span, )); diff --git a/crates/oxc_linter/src/rules/react/jsx_no_undef.rs b/crates/oxc_linter/src/rules/react/jsx_no_undef.rs index 5317323a77e9a..296c38e428969 100644 --- a/crates/oxc_linter/src/rules/react/jsx_no_undef.rs +++ b/crates/oxc_linter/src/rules/react/jsx_no_undef.rs @@ -10,14 +10,14 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-react(jsx-no-undef): Disallow undeclared variables in JSX")] #[diagnostic(severity(warning), help("'{0}' is not defined."))] -struct JsxNoUndefDiagnostic(Atom, #[label] pub Span); +struct JsxNoUndefDiagnostic(CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct JsxNoUndef; @@ -69,7 +69,7 @@ impl Rule for JsxNoUndef { return; } } - ctx.diagnostic(JsxNoUndefDiagnostic(ident.name.clone(), ident.span)); + ctx.diagnostic(JsxNoUndefDiagnostic(ident.name.to_compact_string(), ident.span)); } } } diff --git a/crates/oxc_linter/src/rules/typescript/adjacent_overload_signatures.rs b/crates/oxc_linter/src/rules/typescript/adjacent_overload_signatures.rs index 9b55eae217b86..0a6217432c7d8 100644 --- a/crates/oxc_linter/src/rules/typescript/adjacent_overload_signatures.rs +++ b/crates/oxc_linter/src/rules/typescript/adjacent_overload_signatures.rs @@ -10,7 +10,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{CompactString, GetSpan, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -19,7 +19,11 @@ use crate::{context::LintContext, rule::Rule, AstNode}; "typescript-eslint(adjacent-overload-signatures): All {0:?} signatures should be adjacent." )] #[diagnostic(severity(warning))] -struct AdjacentOverloadSignaturesDiagnostic(Atom, #[label] pub Option, #[label] pub Span); +struct AdjacentOverloadSignaturesDiagnostic( + CompactString, + #[label] pub Option, + #[label] pub Span, +); #[derive(Debug, Default, Clone)] pub struct AdjacentOverloadSignatures; @@ -100,7 +104,7 @@ fn get_kind_from_key(key: &PropertyKey) -> MethodKind { #[derive(Debug)] struct Method { - name: Atom, + name: CompactString, r#static: bool, call_signature: bool, kind: MethodKind, @@ -126,7 +130,7 @@ impl GetMethod for ClassElement<'_> { fn get_method(&self) -> Option { match self { ClassElement::MethodDefinition(def) => def.key.static_name().map(|name| Method { - name, + name: name.to_compact_string(), r#static: def.r#static, call_signature: false, kind: get_kind_from_key(&def.key), @@ -141,21 +145,21 @@ impl GetMethod for TSSignature<'_> { fn get_method(&self) -> Option { match self { TSSignature::TSMethodSignature(sig) => sig.key.static_name().map(|name| Method { - name, + name: name.to_compact_string(), r#static: false, call_signature: false, kind: get_kind_from_key(&sig.key), span: sig.key.span(), }), TSSignature::TSCallSignatureDeclaration(sig) => Some(Method { - name: Atom::from("call"), + name: CompactString::from("call"), r#static: false, call_signature: true, kind: MethodKind::Normal, span: sig.span, }), TSSignature::TSConstructSignatureDeclaration(decl) => Some(Method { - name: Atom::from("new"), + name: CompactString::from("new"), r#static: false, call_signature: false, kind: MethodKind::Normal, @@ -179,7 +183,7 @@ impl GetMethod for ModuleDeclaration<'_> { FunctionType::FunctionDeclaration | FunctionType::TSDeclareFunction ) { func_decl.id.as_ref().map(|id| Method { - name: id.name.clone(), + name: id.name.to_compact_string(), r#static: false, call_signature: false, kind: MethodKind::Normal, @@ -195,7 +199,7 @@ impl GetMethod for ModuleDeclaration<'_> { ModuleDeclaration::ExportNamedDeclaration(named_decl) => { if let Some(Declaration::FunctionDeclaration(func_decl)) = &named_decl.declaration { return func_decl.id.as_ref().map(|id| Method { - name: id.name.clone(), + name: id.name.to_compact_string(), r#static: false, call_signature: false, kind: MethodKind::Normal, @@ -218,7 +222,7 @@ impl GetMethod for Declaration<'_> { FunctionType::FunctionDeclaration | FunctionType::TSDeclareFunction ) { func_decl.id.as_ref().map(|id| Method { - name: id.name.clone(), + name: id.name.to_compact_string(), r#static: false, call_signature: false, kind: MethodKind::Normal, @@ -253,7 +257,7 @@ fn check_and_report(methods: &Vec>, ctx: &LintContext<'_>) { if index.is_some() && !method.is_same_method(last_method) { let name = if method.r#static { - Atom::from(format!("static {0}", method.name)) + CompactString::from(format!("static {0}", method.name)) } else { method.name.clone() }; diff --git a/crates/oxc_linter/src/rules/typescript/ban_types.rs b/crates/oxc_linter/src/rules/typescript/ban_types.rs index cf1740a23da4f..b044615296d11 100644 --- a/crates/oxc_linter/src/rules/typescript/ban_types.rs +++ b/crates/oxc_linter/src/rules/typescript/ban_types.rs @@ -4,7 +4,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -12,7 +12,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; pub enum BanTypesDiagnostic { #[error("typescript-eslint(ban-types): Do not use {0:?} as a type. Use \"{1}\" instead")] #[diagnostic(severity(warning))] - Type(Atom, String, #[label] Span), + Type(CompactString, String, #[label] Span), #[error("typescript-eslint(ban-types): Prefer explicitly define the object shape")] #[diagnostic(severity(warning), help("This type means \"any non-nullish value\", which is slightly better than 'unknown', but it's still a broad type"))] @@ -63,7 +63,7 @@ impl Rule for BanTypes { match name.as_str() { "String" | "Boolean" | "Number" | "Symbol" | "BigInt" => { ctx.diagnostic(BanTypesDiagnostic::Type( - name.clone(), + name.to_compact_string(), name.to_lowercase(), typ.span, )); diff --git a/crates/oxc_linter/src/rules/typescript/no_this_alias.rs b/crates/oxc_linter/src/rules/typescript/no_this_alias.rs index ae2296548108f..dce2cbc053efb 100644 --- a/crates/oxc_linter/src/rules/typescript/no_this_alias.rs +++ b/crates/oxc_linter/src/rules/typescript/no_this_alias.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{CompactString, GetSpan, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -37,7 +37,7 @@ pub struct NoThisAlias(Box); #[derive(Debug, Clone)] pub struct NoThisAliasConfig { allow_destructuring: bool, - allow_names: Vec, + allow_names: Vec, } impl std::ops::Deref for NoThisAlias { @@ -83,8 +83,8 @@ impl Rule for NoThisAlias { .iter() .map(serde_json::Value::as_str) .filter(std::option::Option::is_some) - .map(|x| Atom::from(x.unwrap().to_string())) - .collect::>(); + .map(|x| CompactString::from(x.unwrap())) + .collect::>(); Self(Box::new(NoThisAliasConfig { allow_destructuring: obj @@ -114,7 +114,7 @@ impl Rule for NoThisAlias { } if let BindingPatternKind::BindingIdentifier(identifier) = &decl.id.kind { - if !self.allow_names.contains(&identifier.name) { + if !self.allow_names.iter().any(|s| s.as_str() == identifier.name.as_str()) { ctx.diagnostic(NoThisAliasDiagnostic(identifier.span)); } @@ -135,14 +135,18 @@ impl Rule for NoThisAlias { } AssignmentTarget::SimpleAssignmentTarget(pat) => match pat { SimpleAssignmentTarget::AssignmentTargetIdentifier(id) => { - if !self.allow_names.contains(&id.name) { + if !self.allow_names.iter().any(|s| s.as_str() == id.name.as_str()) { ctx.diagnostic(NoThisAliasDiagnostic(id.span)); } } _ => { if let Some(expr) = pat.get_expression() { if let Some(id) = expr.get_identifier_reference() { - if !self.allow_names.contains(&id.name) { + if !self + .allow_names + .iter() + .any(|s| s.as_str() == id.name.as_str()) + { ctx.diagnostic(NoThisAliasDiagnostic(id.span)); } } diff --git a/crates/oxc_linter/src/rules/typescript/no_unnecessary_type_constraint.rs b/crates/oxc_linter/src/rules/typescript/no_unnecessary_type_constraint.rs index 1e6704d338eee..b48bf44cb456a 100644 --- a/crates/oxc_linter/src/rules/typescript/no_unnecessary_type_constraint.rs +++ b/crates/oxc_linter/src/rules/typescript/no_unnecessary_type_constraint.rs @@ -4,7 +4,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -14,7 +14,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; )] #[diagnostic(severity(warning), help("Remove the unnecessary {1:?} constraint"))] struct NoUnnecessaryTypeConstraintDiagnostic( - Atom, + CompactString, &'static str, #[label] pub Span, #[label] pub Span, @@ -60,7 +60,7 @@ impl Rule for NoUnnecessaryTypeConstraint { _ => continue, }; ctx.diagnostic(NoUnnecessaryTypeConstraintDiagnostic( - param.name.name.clone(), + param.name.name.to_compact_string(), value, param.name.span, ty_span, diff --git a/crates/oxc_linter/src/rules/unicorn/catch_error_name.rs b/crates/oxc_linter/src/rules/unicorn/catch_error_name.rs index 92cb5c511dac1..b416320d05ddb 100644 --- a/crates/oxc_linter/src/rules/unicorn/catch_error_name.rs +++ b/crates/oxc_linter/src/rules/unicorn/catch_error_name.rs @@ -8,22 +8,22 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::SymbolId; -use oxc_span::{Atom, Span}; +use oxc_span::{Atom, CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-unicorn(catch-error-name): The catch parameter {0:?} should be named {1:?}")] #[diagnostic(severity(warning))] -struct CatchErrorNameDiagnostic(Atom, Atom, #[label] pub Span); +struct CatchErrorNameDiagnostic(CompactString, CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct CatchErrorName(Box); #[derive(Debug, Clone)] pub struct CatchErrorNameConfig { - ignore: Vec, - name: Atom, + ignore: Vec, + name: CompactString, } impl std::ops::Deref for CatchErrorName { @@ -36,7 +36,7 @@ impl std::ops::Deref for CatchErrorName { impl Default for CatchErrorNameConfig { fn default() -> Self { - Self { ignore: vec![], name: Atom::new_inline("error") } + Self { ignore: vec![], name: CompactString::new_inline("error") } } } @@ -69,10 +69,10 @@ impl Rule for CatchErrorName { .iter() .map(serde_json::Value::as_str) .filter(std::option::Option::is_some) - .map(|x| Atom::from(x.unwrap().to_string())) - .collect::>(); + .map(|x| CompactString::from(x.unwrap())) + .collect::>(); - let allowed_name = Atom::from( + let allowed_name = CompactString::from( value .get(0) .and_then(|v| v.get("name")) @@ -96,7 +96,7 @@ impl Rule for CatchErrorName { if binding_ident.name.starts_with('_') { if symbol_has_references(binding_ident.symbol_id.get(), ctx) { ctx.diagnostic(CatchErrorNameDiagnostic( - binding_ident.name.clone(), + binding_ident.name.to_compact_string(), self.name.clone(), binding_ident.span, )); @@ -105,7 +105,7 @@ impl Rule for CatchErrorName { } ctx.diagnostic(CatchErrorNameDiagnostic( - binding_ident.name.clone(), + binding_ident.name.to_compact_string(), self.name.clone(), binding_ident.span, )); @@ -137,7 +137,7 @@ impl Rule for CatchErrorName { impl CatchErrorName { fn is_name_allowed(&self, name: &Atom) -> bool { - self.name == name || self.ignore.contains(name) + self.name == name || self.ignore.iter().any(|s| s.as_str() == name.as_str()) } fn check_function_arguments( &self, @@ -158,7 +158,7 @@ impl CatchErrorName { if v.name.starts_with('_') { if symbol_has_references(v.symbol_id.get(), ctx) { ctx.diagnostic(CatchErrorNameDiagnostic( - v.name.clone(), + v.name.to_compact_string(), self.name.clone(), v.span, )); @@ -168,7 +168,7 @@ impl CatchErrorName { } return Some(CatchErrorNameDiagnostic( - v.name.clone(), + v.name.to_compact_string(), self.name.clone(), v.span, )); @@ -186,7 +186,7 @@ impl CatchErrorName { if binding_ident.name.starts_with('_') { if symbol_has_references(binding_ident.symbol_id.get(), ctx) { ctx.diagnostic(CatchErrorNameDiagnostic( - binding_ident.name.clone(), + binding_ident.name.to_compact_string(), self.name.clone(), binding_ident.span, )); @@ -196,7 +196,7 @@ impl CatchErrorName { } return Some(CatchErrorNameDiagnostic( - binding_ident.name.clone(), + binding_ident.name.to_compact_string(), self.name.clone(), binding_ident.span, )); diff --git a/crates/oxc_linter/src/rules/unicorn/error_message.rs b/crates/oxc_linter/src/rules/unicorn/error_message.rs index f49ec5d2b0133..0da4b5e3ec837 100644 --- a/crates/oxc_linter/src/rules/unicorn/error_message.rs +++ b/crates/oxc_linter/src/rules/unicorn/error_message.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::Error, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -15,7 +15,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; #[diagnostic(severity(warning))] pub enum ErrorMessageDiagnostic { #[error("eslint-plugin-unicorn(error-message): Pass a message to the {0:1} constructor.")] - MissingMessage(Atom, #[label] Span), + MissingMessage(CompactString, #[label] Span), #[error("eslint-plugin-unicorn(error-message): Error message should not be an empty string.")] EmptyMessage(#[label] Span), #[error("eslint-plugin-unicorn(error-message): Error message should be a string.")] @@ -88,7 +88,7 @@ impl Rule for ErrorMessage { Some(v) => v, None => { return ctx.diagnostic(ErrorMessageDiagnostic::MissingMessage( - constructor_name.clone(), + constructor_name.to_compact_string(), span, )) } diff --git a/crates/oxc_linter/src/rules/unicorn/explicit_length_check.rs b/crates/oxc_linter/src/rules/unicorn/explicit_length_check.rs index 4654d1a68c5e2..bbd098c2bcea8 100644 --- a/crates/oxc_linter/src/rules/unicorn/explicit_length_check.rs +++ b/crates/oxc_linter/src/rules/unicorn/explicit_length_check.rs @@ -10,7 +10,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use oxc_syntax::operator::{BinaryOperator, LogicalOperator}; use crate::{ @@ -24,12 +24,12 @@ use crate::{ enum ExplicitLengthCheckDiagnostic { #[error("eslint-plugin-unicorn(explicit-length-check): Use `.{1} {2}` when checking {1} is not zero.")] #[diagnostic(severity(warning))] - NoneZero(#[label] Span, Atom, Atom, #[help] Option), + NoneZero(#[label] Span, CompactString, CompactString, #[help] Option), #[error( "eslint-plugin-unicorn(explicit-length-check): Use `.{1} {2}` when checking {1} is zero." )] #[diagnostic(severity(warning))] - Zero(#[label] Span, Atom, Atom, #[help] Option), + Zero(#[label] Span, CompactString, CompactString, #[help] Option), } #[derive(Debug, Default, Clone)] enum NonZero { @@ -218,7 +218,7 @@ impl ExplicitLengthCheck { let diagnostic = if is_zero_length_check { ExplicitLengthCheckDiagnostic::Zero( span, - property.clone(), + property.to_compact_string(), check_code.into(), if auto_fix { None @@ -229,7 +229,7 @@ impl ExplicitLengthCheck { } else { ExplicitLengthCheckDiagnostic::NoneZero( span, - property.clone(), + property.to_compact_string(), check_code.into(), if auto_fix { None diff --git a/crates/oxc_linter/src/rules/unicorn/no_this_assignment.rs b/crates/oxc_linter/src/rules/unicorn/no_this_assignment.rs index 4c7d0de5a36b4..76044f4993c69 100644 --- a/crates/oxc_linter/src/rules/unicorn/no_this_assignment.rs +++ b/crates/oxc_linter/src/rules/unicorn/no_this_assignment.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -17,7 +17,7 @@ use crate::{context::LintContext, rule::Rule, AstNode}; severity(warning), help("Reference `this` directly instead of assigning it to a variable.") )] -struct NoThisAssignmentDiagnostic(#[label] pub Span, Atom); +struct NoThisAssignmentDiagnostic(#[label] pub Span, CompactString); #[derive(Debug, Default, Clone)] pub struct NoThisAssignment; @@ -78,7 +78,7 @@ impl Rule for NoThisAssignment { ctx.diagnostic(NoThisAssignmentDiagnostic( variable_decl.span, - binding_ident.name.clone(), + binding_ident.name.to_compact_string(), )); } AstKind::AssignmentExpression(assignment_expr) => { @@ -103,7 +103,7 @@ impl Rule for NoThisAssignment { ctx.diagnostic(NoThisAssignmentDiagnostic( assignment_expr.span, - ident.name.clone(), + ident.name.to_compact_string(), )); } _ => {} diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_date_now.rs b/crates/oxc_linter/src/rules/unicorn/prefer_date_now.rs index 213ee54ab3a14..2f95b9c64d270 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_date_now.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_date_now.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{CompactString, GetSpan, Span}; use oxc_syntax::operator::{AssignmentOperator, BinaryOperator, UnaryOperator}; use crate::{context::LintContext, rule::Rule, AstNode}; @@ -21,7 +21,7 @@ enum PreferDateNowDiagnostic { #[error("eslint-plugin-unicorn(prefer-date-now): Prefer `Date.now()` over `new Date().{1}()`")] #[diagnostic(severity(warning), help("Change to `Date.now()`."))] - PreferDateNowOverMethods(#[label] Span, Atom), + PreferDateNowOverMethods(#[label] Span, CompactString), #[error( "eslint-plugin-unicorn(prefer-date-now): Prefer `Date.now()` over `Number(new Date())`" diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_modern_dom_apis.rs b/crates/oxc_linter/src/rules/unicorn/prefer_modern_dom_apis.rs index cf4512f560ed5..c73dd41863e8d 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_modern_dom_apis.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_modern_dom_apis.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use phf::phf_map; use crate::{ast_util::is_method_call, context::LintContext, rule::Rule, AstNode}; @@ -15,7 +15,7 @@ use crate::{ast_util::is_method_call, context::LintContext, rule::Rule, AstNode} #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-unicorn(prefer-modern-dom-apis): Prefer using `{0}` over `{1}`.")] #[diagnostic(severity(warning))] -struct PreferModernDomApisDiagnostic(pub &'static str, Atom, #[label] pub Span); +struct PreferModernDomApisDiagnostic(pub &'static str, CompactString, #[label] pub Span); #[derive(Debug, Default, Clone)] pub struct PreferModernDomApis; @@ -91,7 +91,7 @@ impl Rule for PreferModernDomApis { if let Some(preferred_method) = DISALLOWED_METHODS.get(method) { ctx.diagnostic(PreferModernDomApisDiagnostic( preferred_method, - Atom::from(method), + CompactString::from(method), member_expr.property.span, )); @@ -111,7 +111,7 @@ impl Rule for PreferModernDomApis { if lit.value == position { ctx.diagnostic(PreferModernDomApisDiagnostic( replacer, - Atom::from(method), + CompactString::from(method), member_expr.property.span, )); } diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_native_coercion_functions.rs b/crates/oxc_linter/src/rules/unicorn/prefer_native_coercion_functions.rs index 1c889904ae63d..90ddae059d709 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_native_coercion_functions.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_native_coercion_functions.rs @@ -144,7 +144,7 @@ fn check_function( None } -fn get_returned_ident<'a>(stmt: &'a Statement, is_arrow: bool) -> Option<&'a Atom> { +fn get_returned_ident<'a>(stmt: &'a Statement, is_arrow: bool) -> Option<&'a Atom<'a>> { if is_arrow { if let Statement::ExpressionStatement(expr_stmt) = &stmt { return expr_stmt diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_node_protocol.rs b/crates/oxc_linter/src/rules/unicorn/prefer_node_protocol.rs index e9f3a40941328..4afc1dcb29dd7 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_node_protocol.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_node_protocol.rs @@ -77,14 +77,14 @@ impl Rule for PreferNodeProtocol { fn get_static_require_arg<'a>( ctx: &LintContext<'a>, call: &CallExpression<'a>, -) -> Option<(Atom, Span)> { +) -> Option<(Atom<'a>, Span)> { let Expression::Identifier(ref id) = call.callee else { return None }; match call.arguments.as_slice() { [Argument::Expression(Expression::StringLiteral(str))] if id.name == "require" => ctx .semantic() .scopes() .root_unresolved_references() - .contains_key(&id.name) + .contains_key(id.name.as_str()) .then(|| (str.value.clone(), str.span)), _ => None, } diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_string_replace_all.rs b/crates/oxc_linter/src/rules/unicorn/prefer_string_replace_all.rs index d3b40321fe11d..f5aba5697304e 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_string_replace_all.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_string_replace_all.rs @@ -7,7 +7,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{ast_util::extract_regex_flags, context::LintContext, rule::Rule, AstNode}; @@ -15,7 +15,7 @@ use crate::{ast_util::extract_regex_flags, context::LintContext, rule::Rule, Ast enum PreferStringReplaceAllDiagnostic { #[error("eslint-plugin-unicorn(prefer-string-replace-all): This pattern can be replaced with `{1}`.")] #[diagnostic(severity(warning))] - StringLiteral(#[label] Span, Atom), + StringLiteral(#[label] Span, CompactString), #[error("eslint-plugin-unicorn(prefer-string-replace-all): Prefer `String#replaceAll()` over `String#replace()` when using a regex with the global flag.")] #[diagnostic(severity(warning))] UseReplaceAll(#[label] Span), @@ -99,7 +99,7 @@ fn is_reg_exp_with_global_flag<'a>(expr: &'a Expression<'a>) -> bool { false } -fn get_pattern_replacement<'a>(expr: &'a Expression<'a>) -> Option { +fn get_pattern_replacement<'a>(expr: &'a Expression<'a>) -> Option { let Expression::RegExpLiteral(reg_exp_literal) = expr else { return None }; if !reg_exp_literal.regex.flags.contains(RegExpFlags::G) { @@ -110,7 +110,7 @@ fn get_pattern_replacement<'a>(expr: &'a Expression<'a>) -> Option { return None; } - Some(reg_exp_literal.regex.pattern.clone()) + Some(reg_exp_literal.regex.pattern.to_compact_string()) } fn is_simple_string(str: &str) -> bool { diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_string_slice.rs b/crates/oxc_linter/src/rules/unicorn/prefer_string_slice.rs index 0c3b8ec575317..6a933dcaaa69a 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_string_slice.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_string_slice.rs @@ -4,14 +4,14 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-unicorn(prefer-string-slice): Prefer String#slice() over String#{1}()")] #[diagnostic(severity(warning))] -struct PreferStringSliceDiagnostic(#[label] pub Span, Atom); +struct PreferStringSliceDiagnostic(#[label] pub Span, CompactString); #[derive(Debug, Default, Clone)] pub struct PreferStringSlice; @@ -50,7 +50,7 @@ impl Rule for PreferStringSlice { _ => return, }; - ctx.diagnostic(PreferStringSliceDiagnostic(span, name.clone())); + ctx.diagnostic(PreferStringSliceDiagnostic(span, name.to_compact_string())); } } diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_string_trim_start_end.rs b/crates/oxc_linter/src/rules/unicorn/prefer_string_trim_start_end.rs index f36bb79726f48..be551cae301ad 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_string_trim_start_end.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_string_trim_start_end.rs @@ -4,14 +4,14 @@ use oxc_diagnostics::{ thiserror::{self, Error}, }; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-unicorn(prefer-string-trim-start-end): Prefer `{1}` over `{2}`")] #[diagnostic(severity(warning), help("Replace with `{1}`"))] -struct PreferStringTrimStartEndDiagnostic(#[label] pub Span, Atom, &'static str); +struct PreferStringTrimStartEndDiagnostic(#[label] pub Span, CompactString, &'static str); #[derive(Debug, Default, Clone)] pub struct PreferStringTrimStartEnd; @@ -67,7 +67,7 @@ impl Rule for PreferStringTrimStartEnd { ctx.diagnostic(PreferStringTrimStartEndDiagnostic( span, - name.clone(), + name.to_compact_string(), get_replacement(name.as_str()), )); } diff --git a/crates/oxc_linter/src/rules/unicorn/text_encoding_identifier_case.rs b/crates/oxc_linter/src/rules/unicorn/text_encoding_identifier_case.rs index 6c0df06596895..c18f287c46ce7 100644 --- a/crates/oxc_linter/src/rules/unicorn/text_encoding_identifier_case.rs +++ b/crates/oxc_linter/src/rules/unicorn/text_encoding_identifier_case.rs @@ -8,14 +8,14 @@ use oxc_diagnostics::{ }; use oxc_macros::declare_oxc_lint; use oxc_semantic::AstNodeId; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; use crate::{context::LintContext, rule::Rule, AstNode}; #[derive(Debug, Error, Diagnostic)] #[error("eslint-plugin-unicorn(text-encoding-identifier-case): Prefer `{1}` over `{2}`.")] #[diagnostic(severity(warning))] -struct TextEncodingIdentifierCaseDiagnostic(#[label] pub Span, pub &'static str, pub Atom); +struct TextEncodingIdentifierCaseDiagnostic(#[label] pub Span, pub &'static str, pub CompactString); #[derive(Debug, Default, Clone)] pub struct TextEncodingIdentifierCase; @@ -52,36 +52,37 @@ declare_oxc_lint!( impl Rule for TextEncodingIdentifierCase { fn run<'a>(&self, node: &AstNode<'a>, ctx: &LintContext<'a>) { - let (str, span) = match node.kind() { + let (s, span) = match node.kind() { AstKind::StringLiteral(string_lit) => (&string_lit.value, string_lit.span), AstKind::JSXText(jsx_text) => (&jsx_text.value, jsx_text.span), _ => { return; } }; + let s = s.as_str(); - if str.as_str() == "utf-8" && is_jsx_meta_elem_with_charset_attr(node.id(), ctx) { + if s == "utf-8" && is_jsx_meta_elem_with_charset_attr(node.id(), ctx) { return; } - let Some(replacement) = get_replacement(str) else { + let Some(replacement) = get_replacement(s) else { return; }; - if replacement == str.as_str() { + if replacement == s { return; } - ctx.diagnostic(TextEncodingIdentifierCaseDiagnostic(span, replacement, str.clone())); + ctx.diagnostic(TextEncodingIdentifierCaseDiagnostic(span, replacement, s.into())); } } -fn get_replacement(node: &Atom) -> Option<&'static str> { - if !matches!(node.as_str().len(), 4 | 5) { +fn get_replacement(node: &str) -> Option<&'static str> { + if !matches!(node.len(), 4 | 5) { return None; } - let node_lower = node.as_str().to_ascii_lowercase(); + let node_lower = node.to_ascii_lowercase(); if node_lower == "utf-8" || node_lower == "utf8" { return Some("utf8"); diff --git a/crates/oxc_linter/src/snapshots/no_unused_private_class_members.snap b/crates/oxc_linter/src/snapshots/no_unused_private_class_members.snap index f75c764e3b9e6..47f1c964c10f1 100644 --- a/crates/oxc_linter/src/snapshots/no_unused_private_class_members.snap +++ b/crates/oxc_linter/src/snapshots/no_unused_private_class_members.snap @@ -63,7 +63,7 @@ expression: no_unused_private_class_members 1 │ class C { 2 │ #usedOnlyInIncrement; · ──────────────────── - 3 │ + 3 │ ╰──── ⚠ eslint(no-unused-private-class-members): 'unusedInOuterClass' is defined but never used. @@ -71,7 +71,7 @@ expression: no_unused_private_class_members 1 │ class C { 2 │ #unusedInOuterClass; · ─────────────────── - 3 │ + 3 │ ╰──── ⚠ eslint(no-unused-private-class-members): 'unusedOnlyInSecondNestedClass' is defined but never used. @@ -159,5 +159,5 @@ expression: no_unused_private_class_members 1 │ class C { 2 │ #usedOnlyInTheSecondInnerClass; · ────────────────────────────── - 3 │ + 3 │ ╰──── diff --git a/crates/oxc_linter/src/utils/jest.rs b/crates/oxc_linter/src/utils/jest.rs index 258d46b04b247..9a91e3deb872d 100644 --- a/crates/oxc_linter/src/utils/jest.rs +++ b/crates/oxc_linter/src/utils/jest.rs @@ -134,7 +134,7 @@ pub fn parse_expect_jest_fn_call<'a>( pub struct PossibleJestNode<'a, 'b> { pub node: &'b AstNode<'a>, - pub original: Option<&'a Atom>, // if this node is imported from 'jest/globals', this field will be Some(original_name), otherwise None + pub original: Option<&'a Atom<'a>>, // if this node is imported from 'jest/globals', this field will be Some(original_name), otherwise None } /// Collect all possible Jest fn Call Expression, @@ -193,7 +193,7 @@ pub fn collect_possible_jest_call_node<'a, 'b>( fn collect_ids_referenced_to_import<'a, 'b>( ctx: &'b LintContext<'a>, -) -> Vec<(ReferenceId, Option<&'a Atom>)> { +) -> Vec<(ReferenceId, Option<&'a Atom<'a>>)> { ctx.symbols() .resolved_references .iter_enumerated() @@ -220,14 +220,17 @@ fn collect_ids_referenced_to_import<'a, 'b>( None }) .flatten() - .collect::)>>() + .collect::>)>>() } /// Find name in the Import Declaration, not use name because of lifetime not long enough. -fn find_original_name<'a>(import_decl: &'a ImportDeclaration<'a>, name: &Atom) -> Option<&'a Atom> { +fn find_original_name<'a>( + import_decl: &'a ImportDeclaration<'a>, + name: &str, +) -> Option<&'a Atom<'a>> { import_decl.specifiers.iter().flatten().find_map(|specifier| match specifier { ImportDeclarationSpecifier::ImportSpecifier(import_specifier) => { - if import_specifier.local.name.as_str() == name.as_str() { + if import_specifier.local.name.as_str() == name { return Some(import_specifier.imported.name()); } None diff --git a/crates/oxc_linter/src/utils/jest/parse_jest_fn.rs b/crates/oxc_linter/src/utils/jest/parse_jest_fn.rs index b29feab0d23e9..72030387952e3 100644 --- a/crates/oxc_linter/src/utils/jest/parse_jest_fn.rs +++ b/crates/oxc_linter/src/utils/jest/parse_jest_fn.rs @@ -271,13 +271,13 @@ fn is_valid_jest_call(members: &[Cow]) -> bool { fn resolve_to_jest_fn<'a>( call_expr: &'a CallExpression<'a>, - original: Option<&'a Atom>, + original: Option<&'a Atom<'a>>, ) -> Option> { let ident = resolve_first_ident(&call_expr.callee)?; Some(ResolvedJestFn { local: &ident.name, original }) } -fn resolve_first_ident<'a>(expr: &'a Expression) -> Option<&'a IdentifierReference> { +fn resolve_first_ident<'a>(expr: &'a Expression<'a>) -> Option<&'a IdentifierReference<'a>> { match expr { Expression::Identifier(ident) => Some(ident), Expression::MemberExpression(member_expr) => resolve_first_ident(member_expr.object()), @@ -333,8 +333,8 @@ impl<'a> ParsedExpectFnCall<'a> { } struct ResolvedJestFn<'a> { - pub local: &'a Atom, - pub original: Option<&'a Atom>, + pub local: &'a Atom<'a>, + pub original: Option<&'a Atom<'a>>, } #[derive(Clone, Copy, Debug)] @@ -388,7 +388,7 @@ impl<'a> KnownMemberExpressionProperty<'a> { pub enum MemberExpressionElement<'a> { Expression(&'a Expression<'a>), - IdentName(&'a IdentifierName), + IdentName(&'a IdentifierName<'a>), } impl<'a> MemberExpressionElement<'a> { diff --git a/crates/oxc_linter/src/utils/nextjs.rs b/crates/oxc_linter/src/utils/nextjs.rs index e3e26cceec40a..dc4a1e978eb57 100644 --- a/crates/oxc_linter/src/utils/nextjs.rs +++ b/crates/oxc_linter/src/utils/nextjs.rs @@ -1,4 +1,4 @@ -use oxc_span::Atom; +use oxc_span::CompactString; use crate::LintContext; @@ -11,7 +11,7 @@ pub fn is_document_page(file_path: &str) -> bool { page.starts_with("/_document") || page.starts_with("\\_document") } -pub fn get_next_script_import_local_name<'a>(ctx: &'a LintContext) -> Option<&'a Atom> { +pub fn get_next_script_import_local_name<'a>(ctx: &'a LintContext) -> Option<&'a CompactString> { ctx.semantic().module_record().import_entries.iter().find_map(|entry| { if entry.module_request.name().as_str() == "next/script" { Some(entry.local_name.name()) diff --git a/crates/oxc_minifier/src/mangler/mod.rs b/crates/oxc_minifier/src/mangler/mod.rs index 154c440916896..c6892292b1f4a 100644 --- a/crates/oxc_minifier/src/mangler/mod.rs +++ b/crates/oxc_minifier/src/mangler/mod.rs @@ -13,11 +13,11 @@ pub struct Mangler { } impl Mangler { - pub fn get_symbol_name(&self, symbol_id: SymbolId) -> &Atom { + pub fn get_symbol_name(&self, symbol_id: SymbolId) -> &str { self.symbol_table.get_name(symbol_id) } - pub fn get_reference_name(&self, reference_id: ReferenceId) -> Option<&Atom> { + pub fn get_reference_name(&self, reference_id: ReferenceId) -> Option<&str> { let symbol_id = self.symbol_table.get_reference(reference_id).symbol_id()?; Some(self.symbol_table.get_name(symbol_id)) } @@ -171,7 +171,7 @@ impl ManglerBuilder { // rename the variables for (symbol_to_rename, new_name) in symbols_to_rename_with_new_names { for symbol_id in &symbol_to_rename.symbol_ids { - symbol_table.set_name(*symbol_id, new_name.clone()); + symbol_table.set_name(*symbol_id, new_name.to_compact_string()); } } } diff --git a/crates/oxc_parser/src/js/expression.rs b/crates/oxc_parser/src/js/expression.rs index 0a1cbc0e0d218..fc356ec101176 100644 --- a/crates/oxc_parser/src/js/expression.rs +++ b/crates/oxc_parser/src/js/expression.rs @@ -50,7 +50,7 @@ impl<'a> ParserImpl<'a> { Ok(self.ast.identifier_reference_expression(ident)) } - pub(crate) fn parse_identifier_reference(&mut self) -> Result { + pub(crate) fn parse_identifier_reference(&mut self) -> Result> { // allow `await` and `yield`, let semantic analysis report error if !self.cur_kind().is_identifier_reference(false, false) { return Err(self.unexpected()); @@ -61,7 +61,7 @@ impl<'a> ParserImpl<'a> { } /// `BindingIdentifier` : Identifier - pub(crate) fn parse_binding_identifier(&mut self) -> Result { + pub(crate) fn parse_binding_identifier(&mut self) -> Result> { if !self.cur_kind().is_binding_identifier() { return Err(self.unexpected()); } @@ -70,7 +70,7 @@ impl<'a> ParserImpl<'a> { Ok(BindingIdentifier { span, name, symbol_id: Cell::default() }) } - pub(crate) fn parse_label_identifier(&mut self) -> Result { + pub(crate) fn parse_label_identifier(&mut self) -> Result> { if !self.cur_kind().is_label_identifier(self.ctx.has_yield(), self.ctx.has_await()) { return Err(self.unexpected()); } @@ -79,7 +79,7 @@ impl<'a> ParserImpl<'a> { Ok(LabelIdentifier { span, name }) } - pub(crate) fn parse_identifier_name(&mut self) -> Result { + pub(crate) fn parse_identifier_name(&mut self) -> Result> { if !self.cur_kind().is_identifier_name() { return Err(self.unexpected()); } @@ -88,12 +88,12 @@ impl<'a> ParserImpl<'a> { } /// Parse keyword kind as identifier - pub(crate) fn parse_keyword_identifier(&mut self, kind: Kind) -> IdentifierName { + pub(crate) fn parse_keyword_identifier(&mut self, kind: Kind) -> IdentifierName<'a> { let (span, name) = self.parse_identifier_kind(kind); IdentifierName { span, name } } - pub(crate) fn parse_identifier_kind(&mut self, kind: Kind) -> (Span, Atom) { + pub(crate) fn parse_identifier_kind(&mut self, kind: Kind) -> (Span, Atom<'a>) { let span = self.start_span(); let name = self.cur_string(); self.bump_remap(kind); @@ -115,7 +115,7 @@ impl<'a> ParserImpl<'a> { /// `PrivateIdentifier` :: /// # `IdentifierName` /// # Panics - pub(crate) fn parse_private_identifier(&mut self) -> PrivateIdentifier { + pub(crate) fn parse_private_identifier(&mut self) -> PrivateIdentifier<'a> { let span = self.start_span(); let name = Atom::from(self.cur_string()); self.bump_any(); @@ -299,7 +299,7 @@ impl<'a> ParserImpl<'a> { Ok(NumericLiteral::new(self.end_span(span), value, src, base)) } - pub(crate) fn parse_literal_bigint(&mut self) -> Result { + pub(crate) fn parse_literal_bigint(&mut self) -> Result> { let span = self.start_span(); let base = match self.cur_kind() { Kind::Decimal => BigintBase::Decimal, @@ -317,7 +317,7 @@ impl<'a> ParserImpl<'a> { Ok(self.ast.bigint_literal(self.end_span(span), Atom::from(raw), base)) } - pub(crate) fn parse_literal_regexp(&mut self) -> RegExpLiteral { + pub(crate) fn parse_literal_regexp(&mut self) -> RegExpLiteral<'a> { let span = self.start_span(); // split out pattern @@ -329,7 +329,7 @@ impl<'a> ParserImpl<'a> { self.ast.reg_exp_literal(self.end_span(span), pattern, flags) } - pub(crate) fn parse_literal_string(&mut self) -> Result { + pub(crate) fn parse_literal_string(&mut self) -> Result> { if !self.at(Kind::Str) { return Err(self.unexpected()); } @@ -427,7 +427,7 @@ impl<'a> ParserImpl<'a> { Ok(self.ast.tagged_template_expression(span, lhs, quasi, type_parameters)) } - pub(crate) fn parse_template_element(&mut self, tagged: bool) -> TemplateElement { + pub(crate) fn parse_template_element(&mut self, tagged: bool) -> TemplateElement<'a> { let span = self.start_span(); let cur_kind = self.cur_kind(); let end_offset: u32 = match cur_kind { @@ -467,7 +467,11 @@ impl<'a> ParserImpl<'a> { } /// Section 13.3 Meta Property - fn parse_meta_property(&mut self, span: Span, meta: IdentifierName) -> Result> { + fn parse_meta_property( + &mut self, + span: Span, + meta: IdentifierName<'a>, + ) -> Result> { self.bump_any(); // bump `.` let property = match self.cur_kind() { Kind::Meta => self.parse_keyword_identifier(Kind::Meta), diff --git a/crates/oxc_parser/src/js/function.rs b/crates/oxc_parser/src/js/function.rs index 737b34cea64fe..bdca5c77e3006 100644 --- a/crates/oxc_parser/src/js/function.rs +++ b/crates/oxc_parser/src/js/function.rs @@ -80,7 +80,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_function( &mut self, span: Span, - id: Option, + id: Option>, r#async: bool, generator: bool, func_kind: FunctionKind, @@ -329,7 +329,7 @@ impl<'a> ParserImpl<'a> { kind: FunctionKind, r#async: bool, generator: bool, - ) -> Option { + ) -> Option> { let ctx = self.ctx; if kind.is_expression() { self.ctx = self.ctx.and_await(r#async).and_yield(generator); diff --git a/crates/oxc_parser/src/js/list.rs b/crates/oxc_parser/src/js/list.rs index 70c88aad9d7d1..55b548fe0ed1b 100644 --- a/crates/oxc_parser/src/js/list.rs +++ b/crates/oxc_parser/src/js/list.rs @@ -5,7 +5,7 @@ use oxc_diagnostics::{ thiserror::{self, Error}, Result, }; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{Atom, CompactString, GetSpan, Span}; use rustc_hash::FxHashMap; use crate::{ @@ -19,7 +19,7 @@ use crate::{ #[error("Identifier `{0}` has already been declared")] #[diagnostic()] struct Redeclaration( - pub Atom, + pub CompactString, #[label("`{0}` has already been declared here")] pub Span, #[label("It can not be redeclared here")] pub Span, ); @@ -290,8 +290,8 @@ impl<'a> SeparatedList<'a> for FormalParameterList<'a> { /// [Assert Entries](https://tc39.es/proposal-import-assertions) pub struct AssertEntries<'a> { - pub elements: Vec<'a, ImportAttribute>, - keys: FxHashMap, + pub elements: Vec<'a, ImportAttribute<'a>>, + keys: FxHashMap, Span>, } impl<'a> SeparatedList<'a> for AssertEntries<'a> { @@ -315,7 +315,7 @@ impl<'a> SeparatedList<'a> for AssertEntries<'a> { }; if let Some(old_span) = self.keys.get(&key.as_atom()) { - p.error(Redeclaration(key.as_atom(), *old_span, key.span())); + p.error(Redeclaration(key.as_atom().into_compact_string(), *old_span, key.span())); } else { self.keys.insert(key.as_atom(), key.span()); } @@ -329,7 +329,7 @@ impl<'a> SeparatedList<'a> for AssertEntries<'a> { } pub struct ExportNamedSpecifiers<'a> { - pub elements: Vec<'a, ExportSpecifier>, + pub elements: Vec<'a, ExportSpecifier<'a>>, } impl<'a> SeparatedList<'a> for ExportNamedSpecifiers<'a> { @@ -443,7 +443,7 @@ impl<'a> NormalList<'a> for SwitchCases<'a> { } pub struct ImportSpecifierList<'a> { - pub import_specifiers: Vec<'a, ImportDeclarationSpecifier>, + pub import_specifiers: Vec<'a, ImportDeclarationSpecifier<'a>>, } impl<'a> SeparatedList<'a> for ImportSpecifierList<'a> { diff --git a/crates/oxc_parser/src/js/module.rs b/crates/oxc_parser/src/js/module.rs index ce820d2dfb85f..2213294db88b4 100644 --- a/crates/oxc_parser/src/js/module.rs +++ b/crates/oxc_parser/src/js/module.rs @@ -73,7 +73,7 @@ impl<'a> ParserImpl<'a> { // Full Syntax: fn parse_import_declaration_specifiers( &mut self, - ) -> Result> { + ) -> Result>> { let mut specifiers = self.ast.new_vec(); // import defaultExport from "module-name"; if self.cur_kind().is_binding_identifier() { @@ -104,7 +104,7 @@ impl<'a> ParserImpl<'a> { } // import default from "module-name" - fn parse_import_default_specifier(&mut self) -> Result { + fn parse_import_default_specifier(&mut self) -> Result> { let span = self.start_span(); let local = self.parse_binding_identifier()?; Ok(ImportDeclarationSpecifier::ImportDefaultSpecifier(ImportDefaultSpecifier { @@ -114,7 +114,7 @@ impl<'a> ParserImpl<'a> { } // import * as name from "module-name" - fn parse_import_namespace_specifier(&mut self) -> Result { + fn parse_import_namespace_specifier(&mut self) -> Result> { let span = self.start_span(); self.bump_any(); // advance `*` self.expect(Kind::As)?; @@ -126,7 +126,7 @@ impl<'a> ParserImpl<'a> { } // import { export1 , export2 as alias2 , [...] } from "module-name"; - fn parse_import_specifiers(&mut self) -> Result> { + fn parse_import_specifiers(&mut self) -> Result>> { let ctx = self.ctx; self.ctx = Context::default(); let specifiers = ImportSpecifierList::parse(self)?.import_specifiers; @@ -167,7 +167,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_ts_export_namespace( &mut self, - ) -> Result> { + ) -> Result>> { let span = self.start_span(); self.expect(Kind::As)?; self.expect(Kind::Namespace)?; @@ -377,7 +377,7 @@ impl<'a> ParserImpl<'a> { // ImportSpecifier : // ImportedBinding // ModuleExportName as ImportedBinding - pub(crate) fn parse_import_specifier(&mut self) -> Result { + pub(crate) fn parse_import_specifier(&mut self) -> Result> { let specifier_span = self.start_span(); let peek_kind = self.peek_kind(); let mut import_kind = ImportOrExportKind::Value; @@ -414,7 +414,7 @@ impl<'a> ParserImpl<'a> { // ModuleExportName : // IdentifierName // StringLiteral - pub(crate) fn parse_module_export_name(&mut self) -> Result { + pub(crate) fn parse_module_export_name(&mut self) -> Result> { match self.cur_kind() { Kind::Str => { let literal = self.parse_literal_string()?; diff --git a/crates/oxc_parser/src/js/statement.rs b/crates/oxc_parser/src/js/statement.rs index 10838d1b070e2..dd6745ed183be 100644 --- a/crates/oxc_parser/src/js/statement.rs +++ b/crates/oxc_parser/src/js/statement.rs @@ -14,7 +14,7 @@ impl<'a> ParserImpl<'a> { // Section 12 // The InputElementHashbangOrRegExp goal is used at the start of a Script // or Module. - pub(crate) fn parse_hashbang(&mut self) -> Option { + pub(crate) fn parse_hashbang(&mut self) -> Option> { if self.cur_kind() == Kind::HashbangComment { let span = self.start_span(); self.bump_any(); @@ -33,7 +33,7 @@ impl<'a> ParserImpl<'a> { pub(crate) fn parse_directives_and_statements( &mut self, is_top_level: bool, - ) -> Result<(Vec<'a, Directive>, Vec<'a, Statement<'a>>)> { + ) -> Result<(Vec<'a, Directive<'a>>, Vec<'a, Statement<'a>>)> { let mut directives = self.ast.new_vec(); let mut statements = self.ast.new_vec(); diff --git a/crates/oxc_parser/src/jsx/mod.rs b/crates/oxc_parser/src/jsx/mod.rs index 5ab9d1a4289fe..502650c958f75 100644 --- a/crates/oxc_parser/src/jsx/mod.rs +++ b/crates/oxc_parser/src/jsx/mod.rs @@ -153,7 +153,7 @@ impl<'a> ParserImpl<'a> { fn parse_jsx_member_expression( &mut self, span: Span, - object: JSXIdentifier, + object: JSXIdentifier<'a>, ) -> Result>> { let mut span = span; let mut object = JSXMemberExpressionObject::Identifier(object); @@ -353,7 +353,7 @@ impl<'a> ParserImpl<'a> { /// `IdentifierStart` /// `JSXIdentifier` `IdentifierPart` /// `JSXIdentifier` [no `WhiteSpace` or Comment here] - - fn parse_jsx_identifier(&mut self) -> Result { + fn parse_jsx_identifier(&mut self) -> Result> { let span = self.start_span(); if !self.at(Kind::Ident) && !self.cur_kind().is_all_keyword() { return Err(self.unexpected()); @@ -366,7 +366,7 @@ impl<'a> ParserImpl<'a> { Ok(self.ast.jsx_identifier(span, name.into())) } - fn parse_jsx_text(&mut self) -> JSXText { + fn parse_jsx_text(&mut self) -> JSXText<'a> { let span = self.start_span(); let value = Atom::from(self.cur_string()); self.bump_any(); diff --git a/crates/oxc_prettier/src/format/block.rs b/crates/oxc_prettier/src/format/block.rs index 9d56bd043fcf9..3f1bd1f5b6ce3 100644 --- a/crates/oxc_prettier/src/format/block.rs +++ b/crates/oxc_prettier/src/format/block.rs @@ -9,7 +9,7 @@ use crate::{ pub(super) fn print_block<'a>( p: &mut Prettier<'a>, stmts: &[Statement<'a>], - directives: Option<&[Directive]>, + directives: Option<&[Directive<'a>]>, ) -> Doc<'a> { let mut parts = p.vec(); parts.push(ss!("{")); @@ -52,7 +52,7 @@ pub(super) fn print_block<'a>( pub(super) fn print_block_body<'a>( p: &mut Prettier<'a>, stmts: &[Statement<'a>], - directives: Option<&[Directive]>, + directives: Option<&[Directive<'a>]>, remove_last_statement_hardline: bool, is_root: bool, ) -> Option> { diff --git a/crates/oxc_prettier/src/format/mod.rs b/crates/oxc_prettier/src/format/mod.rs index 8153d381a5772..206d92a0ee3a5 100644 --- a/crates/oxc_prettier/src/format/mod.rs +++ b/crates/oxc_prettier/src/format/mod.rs @@ -79,13 +79,13 @@ impl<'a> Format<'a> for Program<'a> { } } -impl<'a> Format<'a> for Hashbang { +impl<'a> Format<'a> for Hashbang<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { Doc::Str(self.span.source_text(p.source_text)) } } -impl<'a> Format<'a> for Directive { +impl<'a> Format<'a> for Directive<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { let mut parts = p.vec(); parts.push(Doc::Str(string::print_string( @@ -332,7 +332,7 @@ impl<'a> Format<'a> for DoWhileStatement<'a> { } } -impl<'a> Format<'a> for ContinueStatement { +impl<'a> Format<'a> for ContinueStatement<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { let mut parts = p.vec(); parts.push(ss!("continue")); @@ -346,7 +346,7 @@ impl<'a> Format<'a> for ContinueStatement { } } -impl<'a> Format<'a> for BreakStatement { +impl<'a> Format<'a> for BreakStatement<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { let mut parts = p.vec(); parts.push(ss!("break")); @@ -970,7 +970,7 @@ impl<'a> Format<'a> for TSTypeName<'a> { } } -impl<'a> Format<'a> for TSExternalModuleReference { +impl<'a> Format<'a> for TSExternalModuleReference<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { array!(p, ss!("require("), format!(p, self.expression), ss!(")")) } @@ -1058,7 +1058,7 @@ impl<'a> Format<'a> for ImportDeclaration<'a> { } } -impl<'a> Format<'a> for ImportDeclarationSpecifier { +impl<'a> Format<'a> for ImportDeclarationSpecifier<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { match self { Self::ImportSpecifier(specifier) => specifier.format(p), @@ -1068,7 +1068,7 @@ impl<'a> Format<'a> for ImportDeclarationSpecifier { } } -impl<'a> Format<'a> for ImportSpecifier { +impl<'a> Format<'a> for ImportSpecifier<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { if self.imported.span() == self.local.span { self.local.format(p) @@ -1078,25 +1078,25 @@ impl<'a> Format<'a> for ImportSpecifier { } } -impl<'a> Format<'a> for ImportDefaultSpecifier { +impl<'a> Format<'a> for ImportDefaultSpecifier<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { self.local.format(p) } } -impl<'a> Format<'a> for ImportNamespaceSpecifier { +impl<'a> Format<'a> for ImportNamespaceSpecifier<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { array!(p, ss!("* as "), self.local.format(p)) } } -impl<'a> Format<'a> for Option> { +impl<'a> Format<'a> for Option>> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { line!() } } -impl<'a> Format<'a> for ImportAttribute { +impl<'a> Format<'a> for ImportAttribute<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { line!() } @@ -1126,13 +1126,13 @@ impl<'a> Format<'a> for TSExportAssignment<'a> { } } -impl<'a> Format<'a> for TSNamespaceExportDeclaration { +impl<'a> Format<'a> for TSNamespaceExportDeclaration<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { line!() } } -impl<'a> Format<'a> for ExportSpecifier { +impl<'a> Format<'a> for ExportSpecifier<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { if self.exported.span() == self.local.span() { self.local.format(p) @@ -1142,7 +1142,7 @@ impl<'a> Format<'a> for ExportSpecifier { } } -impl<'a> Format<'a> for ModuleExportName { +impl<'a> Format<'a> for ModuleExportName<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { match self { Self::Identifier(ident) => ident.format(p), @@ -1227,25 +1227,25 @@ impl<'a> Format<'a> for Expression<'a> { } } -impl<'a> Format<'a> for IdentifierReference { +impl<'a> Format<'a> for IdentifierReference<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { wrap!(p, self, IdentifierReference, { p.str(self.name.as_str()) }) } } -impl<'a> Format<'a> for IdentifierName { +impl<'a> Format<'a> for IdentifierName<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { p.str(self.name.as_str()) } } -impl<'a> Format<'a> for BindingIdentifier { +impl<'a> Format<'a> for BindingIdentifier<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { wrap!(p, self, BindingIdentifier, { p.str(self.name.as_str()) }) } } -impl<'a> Format<'a> for LabelIdentifier { +impl<'a> Format<'a> for LabelIdentifier<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { p.str(self.name.as_str()) } @@ -1336,7 +1336,7 @@ impl<'a> Format<'a> for NumericLiteral<'a> { } } -impl<'a> Format<'a> for BigintLiteral { +impl<'a> Format<'a> for BigintLiteral<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { let text = self.span.source_text(p.source_text); // Perf: avoid a memory allocation from `to_ascii_lowercase`. @@ -1348,7 +1348,7 @@ impl<'a> Format<'a> for BigintLiteral { } } -impl<'a> Format<'a> for RegExpLiteral { +impl<'a> Format<'a> for RegExpLiteral<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { let mut parts = p.vec(); parts.push(ss!("/")); @@ -1359,7 +1359,7 @@ impl<'a> Format<'a> for RegExpLiteral { } } -impl<'a> Format<'a> for StringLiteral { +impl<'a> Format<'a> for StringLiteral<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { wrap!(p, self, StringLiteral, { let raw = &p.source_text[(self.span.start + 1) as usize..(self.span.end - 1) as usize]; @@ -1871,7 +1871,7 @@ impl<'a> Format<'a> for TemplateLiteral<'a> { } } -impl<'a> Format<'a> for TemplateElement { +impl<'a> Format<'a> for TemplateElement<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { // TODO: `replaceEndOfLine` p.str(self.value.raw.as_str()) @@ -1941,7 +1941,7 @@ impl<'a> Format<'a> for NewExpression<'a> { } } -impl<'a> Format<'a> for MetaProperty { +impl<'a> Format<'a> for MetaProperty<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { array![p, format!(p, self.meta), ss!("."), format!(p, self.property)] } @@ -1973,7 +1973,7 @@ impl<'a> Format<'a> for ClassElement<'a> { } } -impl<'a> Format<'a> for JSXIdentifier { +impl<'a> Format<'a> for JSXIdentifier<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { line!() } @@ -1997,7 +1997,7 @@ impl<'a> Format<'a> for JSXElementName<'a> { } } -impl<'a> Format<'a> for JSXNamespacedName { +impl<'a> Format<'a> for JSXNamespacedName<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { line!() } @@ -2081,7 +2081,7 @@ impl<'a> Format<'a> for JSXClosingFragment { } } -impl<'a> Format<'a> for JSXText { +impl<'a> Format<'a> for JSXText<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { line!() } @@ -2133,7 +2133,7 @@ impl<'a> Format<'a> for AccessorProperty<'a> { } } -impl<'a> Format<'a> for PrivateIdentifier { +impl<'a> Format<'a> for PrivateIdentifier<'a> { fn format(&self, p: &mut Prettier<'a>) -> Doc<'a> { let mut parts = p.vec(); parts.push(ss!("#")); diff --git a/crates/oxc_prettier/src/format/template_literal.rs b/crates/oxc_prettier/src/format/template_literal.rs index fc4efa144f895..a0e09cac56813 100644 --- a/crates/oxc_prettier/src/format/template_literal.rs +++ b/crates/oxc_prettier/src/format/template_literal.rs @@ -13,7 +13,7 @@ pub enum TemplateLiteralPrinter<'a, 'b> { } impl<'a, 'b> TemplateLiteralPrinter<'a, 'b> { - fn quasis(&self) -> &[TemplateElement] { + fn quasis(&self) -> &[TemplateElement<'a>] { match self { Self::TemplateLiteral(template_literal) => &template_literal.quasis, Self::TSTemplateLiteralType(template_literal) => &template_literal.quasis, @@ -31,9 +31,9 @@ impl<'a, 'b> TemplateLiteralPrinter<'a, 'b> { } } -pub(super) fn print_template_literal<'a>( +pub(super) fn print_template_literal<'a, 'b>( p: &mut Prettier<'a>, - template_literal: &TemplateLiteralPrinter<'a, '_>, + template_literal: &'b TemplateLiteralPrinter<'a, 'b>, ) -> Doc<'a> { let mut parts = p.vec(); parts.push(ss!("`")); diff --git a/crates/oxc_semantic/src/binder.rs b/crates/oxc_semantic/src/binder.rs index 04ecdd7f85971..42f0321da8427 100644 --- a/crates/oxc_semantic/src/binder.rs +++ b/crates/oxc_semantic/src/binder.rs @@ -68,7 +68,7 @@ impl<'a> Binder for VariableDeclarator<'a> { builder.declare_symbol_on_scope(span, name, current_scope_id, includes, excludes); ident.symbol_id.set(Some(symbol_id)); for scope_id in &var_scope_ids { - builder.scope.add_binding(*scope_id, name.clone(), symbol_id); + builder.scope.add_binding(*scope_id, name.to_compact_string(), symbol_id); } }); } @@ -280,19 +280,19 @@ fn declare_symbol_for_import_specifier(ident: &BindingIdentifier, builder: &mut ident.symbol_id.set(Some(symbol_id)); } -impl Binder for ImportSpecifier { +impl<'a> Binder for ImportSpecifier<'a> { fn bind(&self, builder: &mut SemanticBuilder) { declare_symbol_for_import_specifier(&self.local, builder); } } -impl Binder for ImportDefaultSpecifier { +impl<'a> Binder for ImportDefaultSpecifier<'a> { fn bind(&self, builder: &mut SemanticBuilder) { declare_symbol_for_import_specifier(&self.local, builder); } } -impl Binder for ImportNamespaceSpecifier { +impl<'a> Binder for ImportNamespaceSpecifier<'a> { fn bind(&self, builder: &mut SemanticBuilder) { declare_symbol_for_import_specifier(&self.local, builder); } diff --git a/crates/oxc_semantic/src/builder.rs b/crates/oxc_semantic/src/builder.rs index 15d1fba9d017d..0b0e88824d688 100644 --- a/crates/oxc_semantic/src/builder.rs +++ b/crates/oxc_semantic/src/builder.rs @@ -5,7 +5,7 @@ use std::{cell::RefCell, path::PathBuf, rc::Rc, sync::Arc}; #[allow(clippy::wildcard_imports)] use oxc_ast::{ast::*, AstKind, Trivias, TriviasMap, Visit}; use oxc_diagnostics::Error; -use oxc_span::{Atom, SourceType, Span}; +use oxc_span::{Atom, CompactString, SourceType, Span}; use oxc_syntax::{ module_record::{ExportLocalName, ModuleRecord}, operator::AssignmentOperator, @@ -263,7 +263,7 @@ impl<'a> SemanticBuilder<'a> { let includes = includes | self.current_symbol_flags; let symbol_id = self.symbols.create_symbol(span, name.clone(), includes, scope_id); self.symbols.add_declaration(self.current_node_id); - self.scope.add_binding(scope_id, name.clone(), symbol_id); + self.scope.add_binding(scope_id, name.to_compact_string(), symbol_id); symbol_id } @@ -288,7 +288,7 @@ impl<'a> SemanticBuilder<'a> { let symbol_id = self.scope.get_binding(scope_id, name)?; if report_error && self.symbols.get_flag(symbol_id).intersects(excludes) { let symbol_span = self.symbols.get_span(symbol_id); - self.error(Redeclaration(name.clone(), symbol_span, span)); + self.error(Redeclaration(name.to_compact_string(), symbol_span, span)); } Some(symbol_id) } @@ -296,7 +296,11 @@ impl<'a> SemanticBuilder<'a> { pub fn declare_reference(&mut self, reference: Reference) -> ReferenceId { let reference_name = reference.name().clone(); let reference_id = self.symbols.create_reference(reference); - self.scope.add_unresolved_reference(self.current_scope_id, reference_name, reference_id); + self.scope.add_unresolved_reference( + self.current_scope_id, + CompactString::new(reference_name), + reference_id, + ); reference_id } @@ -312,7 +316,7 @@ impl<'a> SemanticBuilder<'a> { let symbol_id = self.symbols.create_symbol(span, name.clone(), includes, self.current_scope_id); self.symbols.add_declaration(self.current_node_id); - self.scope.get_bindings_mut(scope_id).insert(name.clone(), symbol_id); + self.scope.get_bindings_mut(scope_id).insert(name.to_compact_string(), symbol_id); symbol_id } @@ -321,7 +325,7 @@ impl<'a> SemanticBuilder<'a> { .scope .unresolved_references_mut(self.current_scope_id) .drain() - .collect::)>>(); + .collect::)>>(); let parent_scope_id = self.scope.get_parent_id(self.current_scope_id).unwrap_or(self.current_scope_id); @@ -465,7 +469,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { self.leave_scope(); } - fn visit_break_statement(&mut self, stmt: &BreakStatement) { + fn visit_break_statement(&mut self, stmt: &BreakStatement<'a>) { let kind = AstKind::BreakStatement(self.alloc(stmt)); self.enter_node(kind); @@ -517,7 +521,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { self.leave_node(kind); } - fn visit_continue_statement(&mut self, stmt: &ContinueStatement) { + fn visit_continue_statement(&mut self, stmt: &ContinueStatement<'a>) { let kind = AstKind::ContinueStatement(self.alloc(stmt)); self.enter_node(kind); @@ -1041,7 +1045,7 @@ impl<'a> Visit<'a> for SemanticBuilder<'a> { self.visit_label_identifier(&stmt.label); /* cfg */ - self.cfg.next_label = Some(stmt.label.name.clone()); + self.cfg.next_label = Some(stmt.label.name.to_compact_string()); /* cfg */ self.visit_statement(&stmt.body); @@ -1714,7 +1718,7 @@ impl<'a> SemanticBuilder<'a> { let symbol_id = self .scope .get_bindings(self.current_scope_id) - .get(module_declaration.id.name()); + .get(module_declaration.id.name().as_str()); self.namespace_stack.push(*symbol_id.unwrap()); self.in_type_definition = true; } @@ -1851,7 +1855,8 @@ impl<'a> SemanticBuilder<'a> { fn reference_identifier(&mut self, ident: &IdentifierReference) { let flag = self.resolve_reference_usages(); - let reference = Reference::new(ident.span, ident.name.clone(), self.current_node_id, flag); + let reference = + Reference::new(ident.span, ident.name.to_compact_string(), self.current_node_id, flag); let reference_id = self.declare_reference(reference); ident.reference_id.set(Some(reference_id)); } @@ -1883,7 +1888,7 @@ impl<'a> SemanticBuilder<'a> { } { let reference = Reference::new( ident.span, - ident.name.clone(), + ident.name.to_compact_string(), self.current_node_id, ReferenceFlag::read(), ); diff --git a/crates/oxc_semantic/src/checker/javascript.rs b/crates/oxc_semantic/src/checker/javascript.rs index c83592b11cff1..bd300749f0171 100644 --- a/crates/oxc_semantic/src/checker/javascript.rs +++ b/crates/oxc_semantic/src/checker/javascript.rs @@ -8,7 +8,7 @@ use oxc_diagnostics::{ miette::{self, Diagnostic}, thiserror::{self, Error}, }; -use oxc_span::{Atom, GetSpan, ModuleKind, Span}; +use oxc_span::{Atom, CompactString, GetSpan, ModuleKind, Span}; use oxc_syntax::{ module_record::ExportLocalName, operator::{AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator}, @@ -145,13 +145,13 @@ fn check_module_record(ctx: &SemanticBuilder<'_>) { #[derive(Debug, Error, Diagnostic)] #[error("Export '{0}' is not defined")] #[diagnostic()] - struct UndefinedExport(Atom, #[label] Span); + struct UndefinedExport(CompactString, #[label] Span); #[derive(Debug, Error, Diagnostic)] #[error("Duplicated export '{0}'")] #[diagnostic()] struct DuplicateExport( - Atom, + CompactString, #[label("Export has already been declared here")] Span, #[label("It cannot be redeclared here")] Span, ); @@ -172,7 +172,9 @@ fn check_module_record(ctx: &SemanticBuilder<'_>) { ExportLocalName::Name(name_span) => Some(name_span), _ => None, }) - .filter(|name_span| ctx.scope.get_binding(ctx.current_scope_id, name_span.name()).is_none()) + .filter(|name_span| { + ctx.scope.get_binding(ctx.current_scope_id, name_span.name().as_ref()).is_none() + }) .for_each(|name_span| { ctx.error(UndefinedExport(name_span.name().clone(), name_span.span())); }); @@ -205,7 +207,7 @@ struct ClassStaticBlockAwait(#[label] Span); #[derive(Debug, Error, Diagnostic)] #[error("The keyword '{0}' is reserved")] #[diagnostic()] -struct ReservedKeyword(Atom, #[label] Span); +struct ReservedKeyword(CompactString, #[label] Span); pub const STRICT_MODE_NAMES: Set<&'static str> = phf_set! { "implements", @@ -227,7 +229,7 @@ fn check_identifier<'a>(name: &Atom, span: Span, node: &AstNode<'a>, ctx: &Seman if *name == "await" { // It is a Syntax Error if the goal symbol of the syntactic grammar is Module and the StringValue of IdentifierName is "await". if ctx.source_type.is_module() { - return ctx.error(ReservedKeyword(name.clone(), span)); + return ctx.error(ReservedKeyword(name.to_compact_string(), span)); } // It is a Syntax Error if ClassStaticBlockStatementList Contains await is true. if ctx.scope.get_flags(node.scope_id()).is_class_static_block() { @@ -237,14 +239,14 @@ fn check_identifier<'a>(name: &Atom, span: Span, node: &AstNode<'a>, ctx: &Seman // It is a Syntax Error if this phrase is contained in strict mode code and the StringValue of IdentifierName is: "implements", "interface", "let", "package", "private", "protected", "public", "static", or "yield". if ctx.strict_mode() && STRICT_MODE_NAMES.contains(name.as_str()) { - ctx.error(ReservedKeyword(name.clone(), span)); + ctx.error(ReservedKeyword(name.to_compact_string(), span)); } } #[derive(Debug, Error, Diagnostic)] #[error("Cannot assign to '{0}' in strict mode")] #[diagnostic()] -struct UnexpectedIdentifierAssign(Atom, #[label] Span); +struct UnexpectedIdentifierAssign(CompactString, #[label] Span); fn check_binding_identifier<'a>( ident: &BindingIdentifier, @@ -254,7 +256,7 @@ fn check_binding_identifier<'a>( let strict_mode = ctx.strict_mode(); // It is a Diagnostic if the StringValue of a BindingIdentifier is "eval" or "arguments" within strict mode code. if strict_mode && matches!(ident.name.as_str(), "eval" | "arguments") { - return ctx.error(UnexpectedIdentifierAssign(ident.name.clone(), ident.span)); + return ctx.error(UnexpectedIdentifierAssign(ident.name.to_compact_string(), ident.span)); } // LexicalDeclaration : LetOrConst BindingList ; @@ -296,7 +298,10 @@ fn check_identifier_reference<'a>( for node_id in ctx.nodes.ancestors(node.id()).skip(1) { match ctx.nodes.kind(node_id) { AstKind::AssignmentTarget(_) | AstKind::SimpleAssignmentTarget(_) => { - return ctx.error(UnexpectedIdentifierAssign(ident.name.clone(), ident.span)); + return ctx.error(UnexpectedIdentifierAssign( + ident.name.to_compact_string(), + ident.span, + )); } AstKind::MemberExpression(_) => break, _ => {} @@ -331,8 +336,8 @@ fn check_private_identifier_outside_class(ident: &PrivateIdentifier, ctx: &Seman #[derive(Debug, Error, Diagnostic)] #[error("Private identifier '#{0}' is not allowed outside class bodies")] #[diagnostic()] - struct PrivateNotInClass(Atom, #[label] Span); - ctx.error(PrivateNotInClass(ident.name.clone(), ident.span)); + struct PrivateNotInClass(CompactString, #[label] Span); + ctx.error(PrivateNotInClass(ident.name.to_compact_string(), ident.span)); } } @@ -349,7 +354,7 @@ fn check_private_identifier(ctx: &SemanticBuilder<'_>) { #[derive(Debug, Error, Diagnostic)] #[error("Private field '{0}' must be declared in an enclosing class")] #[diagnostic()] - struct PrivateFieldUndeclared(Atom, #[label] Span); + struct PrivateFieldUndeclared(CompactString, #[label] Span); ctx.error(PrivateFieldUndeclared(reference.name.clone(), reference.span)); } }); @@ -444,7 +449,7 @@ fn check_directive(directive: &Directive, ctx: &SemanticBuilder<'_>) { if matches!(ctx.nodes.kind(ctx.scope.get_node_id(ctx.current_scope_id)), AstKind::Function(Function { params, .. }) - | AstKind::ArrowFunctionExpression(ArrowFunctionExpression { params, .. }) + | AstKind::ArrowFunctionExpression(ArrowFunctionExpression { params, .. }) if !params.is_simple_parameter_list()) { ctx.error(IllegalUseStrict(directive.span)); diff --git a/crates/oxc_semantic/src/checker/typescript.rs b/crates/oxc_semantic/src/checker/typescript.rs index 4b38d582f8e6c..44955285456d5 100644 --- a/crates/oxc_semantic/src/checker/typescript.rs +++ b/crates/oxc_semantic/src/checker/typescript.rs @@ -89,11 +89,11 @@ fn check_formal_parameters(params: &FormalParameters, ctx: &SemanticBuilder<'_>) } } -fn check_duplicate_bound_names(bound_names: &T, ctx: &SemanticBuilder<'_>) { - let mut idents: FxHashMap = FxHashMap::default(); +fn check_duplicate_bound_names<'a, T: BoundNames<'a>>(bound_names: &T, ctx: &SemanticBuilder<'_>) { + let mut idents: FxHashMap, Span> = FxHashMap::default(); bound_names.bound_names(&mut |ident| { if let Some(old_span) = idents.insert(ident.name.clone(), ident.span) { - ctx.error(Redeclaration(ident.name.clone(), old_span, ident.span)); + ctx.error(Redeclaration(ident.name.to_compact_string(), old_span, ident.span)); } }); } diff --git a/crates/oxc_semantic/src/class/builder.rs b/crates/oxc_semantic/src/class/builder.rs index 55d82ec8a8210..c9cd6e9d4d3ea 100644 --- a/crates/oxc_semantic/src/class/builder.rs +++ b/crates/oxc_semantic/src/class/builder.rs @@ -65,7 +65,7 @@ impl ClassTableBuilder { self.classes.add_element( class_id, Element::new( - name, + name.to_compact_string(), property.key.span(), property.r#static, is_private, @@ -86,7 +86,7 @@ impl ClassTableBuilder { self.classes.add_element( class_id, Element::new( - name, + name.to_compact_string(), property.key.span(), property.r#static, is_private, @@ -112,7 +112,7 @@ impl ClassTableBuilder { let reference = PrivateIdentifierReference::new( current_node_id, - ident.name.clone(), + ident.name.to_compact_string(), ident.span, element_ids, ); @@ -134,7 +134,7 @@ impl ClassTableBuilder { self.classes.add_element( class_id, Element::new( - name, + name.to_compact_string(), method.key.span(), method.r#static, is_private, diff --git a/crates/oxc_semantic/src/class/table.rs b/crates/oxc_semantic/src/class/table.rs index f167c7ae80bf3..e9a6fe65a3f86 100644 --- a/crates/oxc_semantic/src/class/table.rs +++ b/crates/oxc_semantic/src/class/table.rs @@ -1,5 +1,5 @@ use oxc_index::IndexVec; -use oxc_span::{Atom, Span}; +use oxc_span::{Atom, CompactString, Span}; use oxc_syntax::class::{ClassId, ElementId, ElementKind}; use rustc_hash::FxHashMap; @@ -7,7 +7,7 @@ use crate::node::AstNodeId; #[derive(Debug)] pub struct Element { - pub name: Atom, + pub name: CompactString, pub span: Span, pub is_private: bool, pub r#static: bool, @@ -16,7 +16,7 @@ pub struct Element { impl Element { pub fn new( - name: Atom, + name: CompactString, span: Span, r#static: bool, is_private: bool, @@ -29,13 +29,18 @@ impl Element { #[derive(Debug)] pub struct PrivateIdentifierReference { pub id: AstNodeId, - pub name: Atom, + pub name: CompactString, pub span: Span, pub element_ids: Vec, } impl PrivateIdentifierReference { - pub fn new(id: AstNodeId, name: Atom, span: Span, element_ids: Vec) -> Self { + pub fn new( + id: AstNodeId, + name: CompactString, + span: Span, + element_ids: Vec, + ) -> Self { Self { id, name, span, element_ids } } } @@ -93,8 +98,8 @@ impl ClassTable { element_ids } - pub fn has_private_definition(&self, class_id: ClassId, name: &Atom) -> bool { - self.elements[class_id].iter().any(|p| p.is_private && p.name == *name) + pub fn has_private_definition(&self, class_id: ClassId, name: &str) -> bool { + self.elements[class_id].iter().any(|p| p.is_private && p.name == name) } pub fn declare_class(&mut self, parent_id: Option, ast_node_id: AstNodeId) -> ClassId { diff --git a/crates/oxc_semantic/src/control_flow.rs b/crates/oxc_semantic/src/control_flow.rs index 8a612a3af6544..309b42019e735 100644 --- a/crates/oxc_semantic/src/control_flow.rs +++ b/crates/oxc_semantic/src/control_flow.rs @@ -1,4 +1,4 @@ -use oxc_span::Atom; +use oxc_span::CompactString; use oxc_syntax::operator::{ AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator, }; @@ -14,8 +14,8 @@ pub enum Register { #[derive(Debug, Clone)] pub enum ObjectPropertyAccessBy { - PrivateProperty(Atom), - Property(Atom), + PrivateProperty(CompactString), + Property(CompactString), Expression(Register), } @@ -139,8 +139,8 @@ pub struct ControlFlowGraph { pub basic_blocks_with_continues: Vec>, // node indexes of the basic blocks of switch case conditions pub switch_case_conditions: Vec>, - pub next_label: Option, - pub label_to_ast_node_ix: Vec<(Atom, AstNodeId)>, + pub next_label: Option, + pub label_to_ast_node_ix: Vec<(CompactString, AstNodeId)>, pub ast_node_to_break_continue: Vec<(AstNodeId, usize, Option)>, pub after_throw_block: Option, } diff --git a/crates/oxc_semantic/src/diagnostics.rs b/crates/oxc_semantic/src/diagnostics.rs index a853310e02f25..c8d50b87152eb 100644 --- a/crates/oxc_semantic/src/diagnostics.rs +++ b/crates/oxc_semantic/src/diagnostics.rs @@ -2,13 +2,13 @@ use oxc_diagnostics::{ miette::{self, Diagnostic}, thiserror::{self, Error}, }; -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; #[derive(Debug, Error, Diagnostic)] #[error("Identifier `{0}` has already been declared")] #[diagnostic()] pub struct Redeclaration( - pub Atom, + pub CompactString, #[label("`{0}` has already been declared here")] pub Span, #[label("It can not be redeclared here")] pub Span, ); diff --git a/crates/oxc_semantic/src/lib.rs b/crates/oxc_semantic/src/lib.rs index 7ef6b78af2fb9..a04a8cf595da9 100644 --- a/crates/oxc_semantic/src/lib.rs +++ b/crates/oxc_semantic/src/lib.rs @@ -127,7 +127,7 @@ impl<'a> Semantic<'a> { let AstKind::IdentifierReference(id) = reference_node.kind() else { return false; }; - self.scopes().root_unresolved_references().contains_key(&id.name) + self.scopes().root_unresolved_references().contains_key(id.name.as_str()) } /// Find which scope a symbol is declared in @@ -145,7 +145,7 @@ impl<'a> Semantic<'a> { } pub fn is_reference_to_global_variable(&self, ident: &IdentifierReference) -> bool { - self.scopes().root_unresolved_references().contains_key(&ident.name) + self.scopes().root_unresolved_references().contains_key(ident.name.as_str()) } pub fn redeclare_variables(&self) -> &Vec { @@ -212,7 +212,7 @@ mod tests { let top_level_a = semantic .scopes() .iter_bindings() - .find(|(_scope_id, _symbol_id, name)| name == &Atom::from("Fn")) + .find(|(_scope_id, _symbol_id, name)| name.as_str() == "Fn") .unwrap(); assert_eq!(semantic.symbols.get_scope_id(top_level_a.1), top_level_a.0); } diff --git a/crates/oxc_semantic/src/module_record/builder.rs b/crates/oxc_semantic/src/module_record/builder.rs index 6869c33d45909..d66981d89f570 100644 --- a/crates/oxc_semantic/src/module_record/builder.rs +++ b/crates/oxc_semantic/src/module_record/builder.rs @@ -2,7 +2,7 @@ use std::path::PathBuf; #[allow(clippy::wildcard_imports)] use oxc_ast::{ast::*, syntax_directed_operations::BoundNames}; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{CompactString, GetSpan, Span}; #[allow(clippy::wildcard_imports)] use oxc_syntax::module_record::*; @@ -71,7 +71,7 @@ impl ModuleRecordBuilder { self.module_record.star_export_entries.push(entry); } - fn add_export_binding(&mut self, name: Atom, span: Span) { + fn add_export_binding(&mut self, name: CompactString, span: Span) { if let Some(old_node) = self.module_record.exported_bindings.insert(name.clone(), span) { self.module_record.exported_bindings_duplicated.push(NameSpan::new(name, old_node)); } @@ -179,24 +179,33 @@ impl ModuleRecordBuilder { if decl.import_kind.is_type() { return; } - let module_request = NameSpan::new(decl.source.value.clone(), decl.source.span); + let module_request = NameSpan::new(decl.source.value.to_compact_string(), decl.source.span); if let Some(specifiers) = &decl.specifiers { for specifier in specifiers { let (import_name, local_name) = match specifier { ImportDeclarationSpecifier::ImportSpecifier(specifier) => ( ImportImportName::Name(NameSpan::new( - specifier.imported.name().clone(), + specifier.imported.name().to_compact_string(), specifier.imported.span(), )), - NameSpan::new(specifier.local.name.clone(), specifier.local.span), + NameSpan::new( + specifier.local.name.to_compact_string(), + specifier.local.span, + ), ), ImportDeclarationSpecifier::ImportNamespaceSpecifier(specifier) => ( ImportImportName::NamespaceObject, - NameSpan::new(specifier.local.name.clone(), specifier.local.span), + NameSpan::new( + specifier.local.name.to_compact_string(), + specifier.local.span, + ), ), ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => ( ImportImportName::Default(specifier.span), - NameSpan::new(specifier.local.name.clone(), specifier.local.span), + NameSpan::new( + specifier.local.name.to_compact_string(), + specifier.local.span, + ), ), }; self.add_import_entry(ImportEntry { @@ -210,7 +219,7 @@ impl ModuleRecordBuilder { } fn visit_export_all_declaration(&mut self, decl: &ExportAllDeclaration) { - let module_request = NameSpan::new(decl.source.value.clone(), decl.source.span); + let module_request = NameSpan::new(decl.source.value.to_compact_string(), decl.source.span); let export_entry = ExportEntry { module_request: Some(module_request.clone()), import_name: decl @@ -219,7 +228,7 @@ impl ModuleRecordBuilder { .map_or(ExportImportName::AllButDefault, |_| ExportImportName::All), export_name: decl.exported.as_ref().map_or(ExportExportName::Null, |exported_name| { ExportExportName::Name(NameSpan::new( - exported_name.name().clone(), + exported_name.name().to_compact_string(), exported_name.span(), )) }), @@ -227,7 +236,7 @@ impl ModuleRecordBuilder { }; self.add_export_entry(export_entry); if let Some(exported_name) = &decl.exported { - self.add_export_binding(exported_name.name().clone(), exported_name.span()); + self.add_export_binding(exported_name.name().to_compact_string(), exported_name.span()); } self.add_module_request(&module_request); } @@ -251,7 +260,9 @@ impl ModuleRecordBuilder { export_name: ExportExportName::Default(exported_name.span()), local_name: id.as_ref().map_or_else( || ExportLocalName::Default(exported_name.span()), - |ident| ExportLocalName::Name(NameSpan::new(ident.name.clone(), ident.span)), + |ident| { + ExportLocalName::Name(NameSpan::new(ident.name.to_compact_string(), ident.span)) + }, ), span: decl.declaration.span(), ..ExportEntry::default() @@ -268,8 +279,10 @@ impl ModuleRecordBuilder { return; } - let module_request = - decl.source.as_ref().map(|source| NameSpan::new(source.value.clone(), source.span)); + let module_request = decl + .source + .as_ref() + .map(|source| NameSpan::new(source.value.to_compact_string(), source.span)); if let Some(module_request) = &module_request { self.add_module_request(module_request); @@ -277,10 +290,14 @@ impl ModuleRecordBuilder { if let Some(decl) = &decl.declaration { decl.bound_names(&mut |ident| { - let export_name = - ExportExportName::Name(NameSpan::new(ident.name.clone(), ident.span)); - let local_name = - ExportLocalName::Name(NameSpan::new(ident.name.clone(), ident.span)); + let export_name = ExportExportName::Name(NameSpan::new( + ident.name.to_compact_string(), + ident.span, + )); + let local_name = ExportLocalName::Name(NameSpan::new( + ident.name.to_compact_string(), + ident.span, + )); let export_entry = ExportEntry { span: decl.span(), module_request: module_request.clone(), @@ -289,18 +306,18 @@ impl ModuleRecordBuilder { local_name, }; self.add_export_entry(export_entry); - self.add_export_binding(ident.name.clone(), ident.span); + self.add_export_binding(ident.name.to_compact_string(), ident.span); }); } for specifier in &decl.specifiers { let export_name = ExportExportName::Name(NameSpan::new( - specifier.exported.name().clone(), + specifier.exported.name().to_compact_string(), specifier.exported.span(), )); let import_name = if module_request.is_some() { ExportImportName::Name(NameSpan::new( - specifier.local.name().clone(), + specifier.local.name().to_compact_string(), specifier.local.span(), )) } else { @@ -310,7 +327,7 @@ impl ModuleRecordBuilder { ExportLocalName::Null } else { ExportLocalName::Name(NameSpan::new( - specifier.local.name().clone(), + specifier.local.name().to_compact_string(), specifier.local.span(), )) }; @@ -322,7 +339,10 @@ impl ModuleRecordBuilder { local_name, }; self.add_export_entry(export_entry); - self.add_export_binding(specifier.exported.name().clone(), specifier.exported.span()); + self.add_export_binding( + specifier.exported.name().to_compact_string(), + specifier.exported.span(), + ); } } @@ -359,7 +379,7 @@ impl ModuleRecordBuilder { if let Some(Argument::Expression(Expression::StringLiteral(module))) = call.arguments.first() { - let module_request = NameSpan::new(module.value.clone(), module.span); + let module_request = NameSpan::new(module.value.to_compact_string(), module.span); self.add_module_request(&module_request); } } diff --git a/crates/oxc_semantic/src/reference.rs b/crates/oxc_semantic/src/reference.rs index 709eb320d28a5..6fa1dff90f290 100644 --- a/crates/oxc_semantic/src/reference.rs +++ b/crates/oxc_semantic/src/reference.rs @@ -1,4 +1,4 @@ -use oxc_span::{Atom, Span}; +use oxc_span::{CompactString, Span}; #[cfg(feature = "serde")] use serde::Serialize; @@ -12,7 +12,7 @@ pub use oxc_syntax::reference::{ReferenceFlag, ReferenceId}; pub struct Reference { span: Span, /// The name of the identifier that was referred to - name: Atom, + name: CompactString, node_id: AstNodeId, symbol_id: Option, /// Describes how this referenced is used by other AST nodes. References can @@ -21,7 +21,7 @@ pub struct Reference { } impl Reference { - pub fn new(span: Span, name: Atom, node_id: AstNodeId, flag: ReferenceFlag) -> Self { + pub fn new(span: Span, name: CompactString, node_id: AstNodeId, flag: ReferenceFlag) -> Self { Self { span, name, node_id, symbol_id: None, flag } } @@ -29,7 +29,7 @@ impl Reference { self.span } - pub fn name(&self) -> &Atom { + pub fn name(&self) -> &CompactString { &self.name } diff --git a/crates/oxc_semantic/src/scope.rs b/crates/oxc_semantic/src/scope.rs index 9ce819968225e..13959d85109d0 100644 --- a/crates/oxc_semantic/src/scope.rs +++ b/crates/oxc_semantic/src/scope.rs @@ -3,7 +3,7 @@ use std::hash::BuildHasherDefault; use indexmap::IndexMap; use oxc_ast::{ast::Expression, syntax_directed_operations::GatherNodeParts}; use oxc_index::IndexVec; -use oxc_span::Atom; +use oxc_span::CompactString; pub use oxc_syntax::scope::{ScopeFlags, ScopeId}; use rustc_hash::{FxHashMap, FxHasher}; @@ -11,8 +11,8 @@ use crate::{reference::ReferenceId, symbol::SymbolId, AstNodeId}; type FxIndexMap = IndexMap>; -type Bindings = FxIndexMap; -type UnresolvedReferences = FxHashMap>; +type Bindings = FxIndexMap; +type UnresolvedReferences = FxHashMap>; /// Scope Tree /// @@ -100,15 +100,15 @@ impl ScopeTree { } /// Get a variable binding by name that was declared in the top-level scope - pub fn get_root_binding(&self, name: &Atom) -> Option { + pub fn get_root_binding(&self, name: &str) -> Option { self.get_binding(self.root_scope_id(), name) } - pub fn has_binding(&self, scope_id: ScopeId, name: &Atom) -> bool { + pub fn has_binding(&self, scope_id: ScopeId, name: &str) -> bool { self.bindings[scope_id].get(name).is_some() } - pub fn get_binding(&self, scope_id: ScopeId, name: &Atom) -> Option { + pub fn get_binding(&self, scope_id: ScopeId, name: &str) -> Option { self.bindings[scope_id].get(name).copied() } @@ -120,9 +120,11 @@ impl ScopeTree { self.node_ids[&scope_id] } - pub fn iter_bindings(&self) -> impl Iterator + '_ { + pub fn iter_bindings( + &self, + ) -> impl Iterator + '_ { self.bindings.iter_enumerated().flat_map(|(scope_id, bindings)| { - bindings.iter().map(move |(name, symbol_id)| (scope_id, *symbol_id, name.clone())) + bindings.iter().map(move |(name, symbol_id)| (scope_id, *symbol_id, name)) }) } @@ -147,14 +149,14 @@ impl ScopeTree { self.node_ids.insert(scope_id, node_id); } - pub fn add_binding(&mut self, scope_id: ScopeId, name: Atom, symbol_id: SymbolId) { + pub fn add_binding(&mut self, scope_id: ScopeId, name: CompactString, symbol_id: SymbolId) { self.bindings[scope_id].insert(name, symbol_id); } pub(crate) fn add_unresolved_reference( &mut self, scope_id: ScopeId, - name: Atom, + name: CompactString, reference_id: ReferenceId, ) { self.unresolved_references[scope_id].entry(name).or_default().push(reference_id); @@ -163,7 +165,7 @@ impl ScopeTree { pub(crate) fn extend_unresolved_reference( &mut self, scope_id: ScopeId, - name: Atom, + name: CompactString, reference_ids: Vec, ) { self.unresolved_references[scope_id].entry(name).or_default().extend(reference_ids); @@ -178,7 +180,7 @@ impl ScopeTree { // TODO: // - pub fn generate_uid_based_on_node(&self, expr: &Expression) -> Atom { + pub fn generate_uid_based_on_node(&self, expr: &Expression) -> CompactString { let mut parts = std::vec::Vec::with_capacity(1); expr.gather(&mut |part| parts.push(part)); let name = parts.join("$"); @@ -187,7 +189,7 @@ impl ScopeTree { } // - pub fn generate_uid(&self, name: &str) -> Atom { + pub fn generate_uid(&self, name: &str) -> CompactString { for i in 0.. { let name = Self::internal_generate_uid(name, i); if !self.has_binding(ScopeId::new(0), &name) { @@ -198,7 +200,7 @@ impl ScopeTree { } // - fn internal_generate_uid(name: &str, i: i32) -> Atom { - Atom::from(if i > 1 { format!("_{name}{i}") } else { format!("_{name}") }) + fn internal_generate_uid(name: &str, i: i32) -> CompactString { + CompactString::from(if i > 1 { format!("_{name}{i}") } else { format!("_{name}") }) } } diff --git a/crates/oxc_semantic/src/symbol.rs b/crates/oxc_semantic/src/symbol.rs index 0836aa9af1b3f..3f44b8a7d8a14 100644 --- a/crates/oxc_semantic/src/symbol.rs +++ b/crates/oxc_semantic/src/symbol.rs @@ -1,6 +1,6 @@ use oxc_ast::ast::Expression; use oxc_index::IndexVec; -use oxc_span::{Atom, Span}; +use oxc_span::{Atom, CompactString, Span}; pub use oxc_syntax::{ scope::ScopeId, symbol::{SymbolFlags, SymbolId}, @@ -31,7 +31,7 @@ export type IndexVec = Array; #[cfg_attr(all(feature = "serde", feature = "wasm"), derive(tsify::Tsify))] pub struct SymbolTable { pub spans: IndexVec, - pub names: IndexVec, + pub names: IndexVec, pub flags: IndexVec, pub scope_ids: IndexVec, /// Pointer to the AST Node where this symbol is declared @@ -63,21 +63,25 @@ impl SymbolTable { .find_map(|(symbol, inner_span)| if inner_span == span { Some(symbol) } else { None }) } - pub fn get_symbol_id_from_name(&self, name: &Atom) -> Option { - self.names - .iter_enumerated() - .find_map(|(symbol, inner_name)| if inner_name == name { Some(symbol) } else { None }) + pub fn get_symbol_id_from_name(&self, name: &str) -> Option { + self.names.iter_enumerated().find_map(|(symbol, inner_name)| { + if inner_name.as_str() == name { + Some(symbol) + } else { + None + } + }) } pub fn get_span(&self, symbol_id: SymbolId) -> Span { self.spans[symbol_id] } - pub fn get_name(&self, symbol_id: SymbolId) -> &Atom { + pub fn get_name(&self, symbol_id: SymbolId) -> &str { &self.names[symbol_id] } - pub fn set_name(&mut self, symbol_id: SymbolId, name: Atom) { + pub fn set_name(&mut self, symbol_id: SymbolId, name: CompactString) { self.names[symbol_id] = name; } @@ -113,7 +117,7 @@ impl SymbolTable { scope_id: ScopeId, ) -> SymbolId { _ = self.spans.push(span); - _ = self.names.push(name); + _ = self.names.push(name.into_compact_string()); _ = self.flags.push(flag); _ = self.scope_ids.push(scope_id); self.resolved_references.push(vec![]) diff --git a/crates/oxc_semantic/tests/util/symbol_tester.rs b/crates/oxc_semantic/tests/util/symbol_tester.rs index fc763c438067e..75e6b8f3810f9 100644 --- a/crates/oxc_semantic/tests/util/symbol_tester.rs +++ b/crates/oxc_semantic/tests/util/symbol_tester.rs @@ -39,8 +39,11 @@ impl<'a> SymbolTester<'a> { semantic: Semantic<'a>, target: &str, ) -> Self { - let symbols_with_target_name: Vec<_> = - semantic.scopes().iter_bindings().filter(|(_, _, name)| name == &target).collect(); + let symbols_with_target_name: Vec<_> = semantic + .scopes() + .iter_bindings() + .filter(|(_, _, name)| name.as_str() == target) + .collect(); let data = match symbols_with_target_name.len() { 0 => Err(miette!("Could not find declaration for {target}")), 1 => Ok(symbols_with_target_name.iter().map(|(_, symbol_id, _)| *symbol_id).next().unwrap()), @@ -139,7 +142,7 @@ impl<'a> SymbolTester<'a> { self.test_result = match self.test_result { Ok(symbol_id) => { let binding = Atom::from(self.target_symbol_name.clone()); - if self.semantic.module_record().exported_bindings.contains_key(&binding) + if self.semantic.module_record().exported_bindings.contains_key(binding.as_str()) && self.semantic.scopes().get_root_binding(&binding) == Some(symbol_id) { Ok(symbol_id) diff --git a/crates/oxc_span/Cargo.toml b/crates/oxc_span/Cargo.toml index e44f787ef0b85..0b060e9787a25 100644 --- a/crates/oxc_span/Cargo.toml +++ b/crates/oxc_span/Cargo.toml @@ -21,6 +21,7 @@ doctest = false [dependencies] miette = { workspace = true } inlinable_string = "0.1.15" +compact_str = { version = "0.7.1", features = ["serde"] } tsify = { workspace = true, optional = true } wasm-bindgen = { workspace = true, optional = true } diff --git a/crates/oxc_span/src/atom.rs b/crates/oxc_span/src/atom.rs index 7e1aa4e7d6e96..d14520bf5b92e 100644 --- a/crates/oxc_span/src/atom.rs +++ b/crates/oxc_span/src/atom.rs @@ -7,6 +7,7 @@ use std::{ #[cfg(feature = "serde")] use serde::{Serialize, Serializer}; +use compact_str::CompactString; use inlinable_string::inline_string::{InlineString, INLINE_STRING_CAPACITY}; const BASE54_CHARS: &[u8; 64] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_0123456789"; @@ -18,22 +19,22 @@ const BASE54_CHARS: &[u8; 64] = b"abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRST #[allow(dead_code)] const TS_APPEND_CONTENT: &'static str = r#" export type Atom = string; +export type CompactString = string; "#; /// An inlinable string for oxc_allocator. /// -/// SAFETY: It is unsafe to use this string after the allocator is dropped. -/// +/// Use [CompactString] with [Atom::to_compact_string()] for the lifetimeless form. #[derive(Clone, Eq, Hash)] -pub struct Atom(AtomImpl); +pub struct Atom<'a>(AtomImpl<'a>); /// Immutable Inlinable String /// /// https://github.com/fitzgen/inlinable_string/blob/master/src/lib.rs #[derive(Clone, Eq, PartialEq)] -enum AtomImpl { +enum AtomImpl<'a> { /// A arena heap-allocated string. - Arena(&'static str), + Arena(&'a str), /// A heap-allocated string. Heap(Box), /// A small string stored inline. @@ -41,7 +42,7 @@ enum AtomImpl { } #[cfg(feature = "serde")] -impl Serialize for Atom { +impl<'a> Serialize for Atom<'a> { fn serialize(&self, serializer: S) -> Result where S: Serializer, @@ -50,7 +51,7 @@ impl Serialize for Atom { } } -impl Atom { +impl<'a> Atom<'a> { pub fn new_inline(s: &str) -> Self { Self(AtomImpl::Inline(InlineString::from(s))) } @@ -73,6 +74,22 @@ impl Atom { } } + pub fn into_compact_string(self) -> CompactString { + match self.0 { + AtomImpl::Arena(s) => CompactString::new(s), + AtomImpl::Heap(s) => CompactString::new(s), + AtomImpl::Inline(s) => CompactString::new(s), + } + } + + pub fn to_compact_string(&self) -> CompactString { + match &self.0 { + AtomImpl::Arena(s) => CompactString::new(s), + AtomImpl::Heap(s) => CompactString::new(s), + AtomImpl::Inline(s) => CompactString::new(s), + } + } + /// Get the shortest mangled name for a given n. /// Code adapted from [terser](https://github.com/terser/terser/blob/8b966d687395ab493d2c6286cc9dd38650324c11/lib/scope.js#L1041-L1051) pub fn base54(n: usize) -> Self { @@ -95,18 +112,17 @@ impl Atom { } } -impl<'a> From<&'a str> for Atom { +impl<'a> From<&'a str> for Atom<'a> { fn from(s: &'a str) -> Self { if s.len() <= INLINE_STRING_CAPACITY { Self(AtomImpl::Inline(InlineString::from(s))) } else { - // SAFETY: It is unsafe to use this string after the allocator is dropped. - Self(AtomImpl::Arena(unsafe { std::mem::transmute(s) })) + Self(AtomImpl::Arena(s)) } } } -impl From for Atom { +impl<'a> From for Atom<'a> { fn from(s: String) -> Self { if s.len() <= INLINE_STRING_CAPACITY { Self(AtomImpl::Inline(InlineString::from(s.as_str()))) @@ -116,7 +132,7 @@ impl From for Atom { } } -impl From> for Atom { +impl<'a> From> for Atom<'a> { fn from(s: Cow<'_, str>) -> Self { if s.len() <= INLINE_STRING_CAPACITY { Self(AtomImpl::Inline(InlineString::from(s.borrow()))) @@ -126,7 +142,7 @@ impl From> for Atom { } } -impl Deref for Atom { +impl<'a> Deref for Atom<'a> { type Target = str; fn deref(&self) -> &Self::Target { @@ -134,33 +150,33 @@ impl Deref for Atom { } } -impl AsRef for Atom { +impl<'a> AsRef for Atom<'a> { #[inline] fn as_ref(&self) -> &str { self.as_str() } } -impl Borrow for Atom { +impl<'a> Borrow for Atom<'a> { #[inline] fn borrow(&self) -> &str { self.as_str() } } -impl> PartialEq for Atom { +impl<'a, T: AsRef> PartialEq for Atom<'a> { fn eq(&self, other: &T) -> bool { self.as_str() == other.as_ref() } } -impl PartialEq for &str { - fn eq(&self, other: &Atom) -> bool { +impl<'a> PartialEq> for &str { + fn eq(&self, other: &Atom<'a>) -> bool { *self == other.as_str() } } -impl hash::Hash for AtomImpl { +impl<'a> hash::Hash for AtomImpl<'a> { #[inline] fn hash(&self, hasher: &mut H) { match self { @@ -171,13 +187,13 @@ impl hash::Hash for AtomImpl { } } -impl fmt::Debug for Atom { +impl<'a> fmt::Debug for Atom<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Debug::fmt(self.as_str(), f) } } -impl fmt::Display for Atom { +impl<'a> fmt::Display for Atom<'a> { fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { fmt::Display::fmt(self.as_str(), f) } diff --git a/crates/oxc_span/src/lib.rs b/crates/oxc_span/src/lib.rs index cf595e883509c..a5c5a86581fde 100644 --- a/crates/oxc_span/src/lib.rs +++ b/crates/oxc_span/src/lib.rs @@ -11,3 +11,4 @@ pub use crate::{ source_type::{Language, LanguageVariant, ModuleKind, SourceType, VALID_EXTENSIONS}, span::{GetSpan, Span, SPAN}, }; +pub use compact_str::CompactString; diff --git a/crates/oxc_syntax/src/module_record.rs b/crates/oxc_syntax/src/module_record.rs index 2d25b0bf68f01..5a9e1b4803aa8 100644 --- a/crates/oxc_syntax/src/module_record.rs +++ b/crates/oxc_syntax/src/module_record.rs @@ -4,9 +4,10 @@ use std::{fmt, hash::BuildHasherDefault, path::PathBuf, sync::Arc}; use dashmap::DashMap; use indexmap::IndexMap; -use oxc_span::{Atom, Span}; use rustc_hash::{FxHashMap, FxHasher}; +use oxc_span::{CompactString, Span}; + /// Module Record /// /// See @@ -26,13 +27,13 @@ pub struct ModuleRecord { /// import ModuleSpecifier /// export ExportFromClause FromClause /// Keyed by ModuleSpecifier, valued by all node occurrences - pub requested_modules: IndexMap, BuildHasherDefault>, + pub requested_modules: IndexMap, BuildHasherDefault>, /// `[[LoadedModules]]` /// /// A map from the specifier strings used by the module represented by this record to request the importation of a module to the resolved Module Record. /// The list does not contain two different Records with the same `[[Specifier]]`. - pub loaded_modules: DashMap, BuildHasherDefault>, + pub loaded_modules: DashMap, BuildHasherDefault>, /// `[[ImportEntries]]` /// @@ -59,7 +60,7 @@ pub struct ModuleRecord { /// not including export * as namespace declarations. pub star_export_entries: Vec, - pub exported_bindings: FxHashMap, + pub exported_bindings: FxHashMap, pub exported_bindings_duplicated: Vec, pub export_default: Option, @@ -100,16 +101,16 @@ impl fmt::Debug for ModuleRecord { #[derive(Debug, Clone, PartialEq, Eq)] pub struct NameSpan { - name: Atom, + name: CompactString, span: Span, } impl NameSpan { - pub fn new(name: Atom, span: Span) -> Self { + pub fn new(name: CompactString, span: Span) -> Self { Self { name, span } } - pub fn name(&self) -> &Atom { + pub fn name(&self) -> &CompactString { &self.name } diff --git a/crates/oxc_transformer/src/context.rs b/crates/oxc_transformer/src/context.rs index 7b14d2df504ad..29dde38acb1c2 100644 --- a/crates/oxc_transformer/src/context.rs +++ b/crates/oxc_transformer/src/context.rs @@ -7,7 +7,7 @@ use std::{ use oxc_ast::AstBuilder; use oxc_diagnostics::Error; use oxc_semantic::{ScopeId, ScopeTree, Semantic, SymbolId, SymbolTable}; -use oxc_span::{Atom, SourceType}; +use oxc_span::{CompactString, SourceType}; #[derive(Clone)] pub struct TransformerCtx<'a> { @@ -37,7 +37,7 @@ impl<'a> TransformerCtx<'a> { RefMut::map(self.semantic.borrow_mut(), |semantic| semantic.scopes_mut()) } - pub fn add_binding(&self, name: Atom) { + pub fn add_binding(&self, name: CompactString) { // TODO: use the correct scope and symbol id self.scopes_mut().add_binding(ScopeId::new(0), name, SymbolId::new(0)); } diff --git a/crates/oxc_transformer/src/es2015/arrow_functions.rs b/crates/oxc_transformer/src/es2015/arrow_functions.rs index 3385ca49aa412..e41eb282cd040 100644 --- a/crates/oxc_transformer/src/es2015/arrow_functions.rs +++ b/crates/oxc_transformer/src/es2015/arrow_functions.rs @@ -41,7 +41,7 @@ impl<'a> VisitMut<'a> for ArrowFunctions<'a> { self.nodes.pop(); } - fn visit_jsx_identifier(&mut self, ident: &mut JSXIdentifier) { + fn visit_jsx_identifier(&mut self, ident: &mut JSXIdentifier<'a>) { let parent_kind = self.nodes.last().unwrap(); let parent_parent_kind = self.nodes[self.nodes.len() - 2]; if ident.name == "this" @@ -69,9 +69,9 @@ impl<'a> ArrowFunctions<'a> { }) } - fn get_this_name(&self) -> Atom { + fn get_this_name(&self) -> Atom<'a> { let uid = if self.uid == 1 { String::new() } else { self.uid.to_string() }; - format!("_this{uid}",).into() + self.ast.new_atom(&format!("_this{uid}")) } pub fn transform_statements(&mut self, stmts: &mut Vec<'a, Statement<'a>>) { diff --git a/crates/oxc_transformer/src/es2015/duplicate_keys.rs b/crates/oxc_transformer/src/es2015/duplicate_keys.rs index dbc2091d83689..718a357430ab3 100644 --- a/crates/oxc_transformer/src/es2015/duplicate_keys.rs +++ b/crates/oxc_transformer/src/es2015/duplicate_keys.rs @@ -64,7 +64,7 @@ impl<'a> DuplicateKeys<'a> { if is_duplicate { obj_property.computed = true; - let string_literal = StringLiteral::new(SPAN, name.as_str().into()); + let string_literal = StringLiteral::new(SPAN, name.clone()); let expr = self.ast.literal_string_expression(string_literal); obj_property.key = PropertyKey::Expression(expr); } diff --git a/crates/oxc_transformer/src/es2015/function_name.rs b/crates/oxc_transformer/src/es2015/function_name.rs index bf779b200154f..aa8c4d54cb6a5 100644 --- a/crates/oxc_transformer/src/es2015/function_name.rs +++ b/crates/oxc_transformer/src/es2015/function_name.rs @@ -111,7 +111,7 @@ impl<'a> FunctionName<'a> { fn transform_expression( &mut self, expr: &mut Expression<'a>, - mut id: BindingIdentifier, + mut id: BindingIdentifier<'a>, scope_id: Option, ) { // function () {} -> function name() {} diff --git a/crates/oxc_transformer/src/es2015/new_target.rs b/crates/oxc_transformer/src/es2015/new_target.rs index a9f721f45d3a1..c039c9e37008d 100644 --- a/crates/oxc_transformer/src/es2015/new_target.rs +++ b/crates/oxc_transformer/src/es2015/new_target.rs @@ -14,14 +14,14 @@ use std::rc::Rc; pub struct NewTarget<'a> { ast: Rc>, ctx: TransformerCtx<'a>, - kinds: Vec<'a, NewTargetKind>, + kinds: Vec<'a, NewTargetKind<'a>>, } #[derive(Debug)] -enum NewTargetKind { +enum NewTargetKind<'a> { Method, Constructor, - Function(Option), + Function(Option>), } impl<'a> VisitMut<'a> for NewTarget<'a> { @@ -52,7 +52,7 @@ impl<'a> NewTarget<'a> { }) } - fn get_kind(&self, kind: AstKind<'a>) -> Option { + fn get_kind(&self, kind: AstKind<'a>) -> Option> { match kind { AstKind::MethodDefinition(def) => match def.kind { MethodDefinitionKind::Get @@ -97,9 +97,9 @@ impl<'a> NewTarget<'a> { NewTargetKind::Function(name) => { // TODO packages/babel-helper-create-class-features-plugin/src/fields.ts#L192 unshadow // It will mutate previous ast node, it is difficult at now. - let id = name - .clone() - .unwrap_or_else(|| self.ctx.scopes().generate_uid("target")); + let id = name.clone().unwrap_or_else(|| { + self.ast.new_atom(self.ctx.scopes().generate_uid("target").as_str()) + }); let test = self.ast.binary_expression( SPAN, self.ast.this_expression(SPAN), diff --git a/crates/oxc_transformer/src/es2019/json_strings.rs b/crates/oxc_transformer/src/es2019/json_strings.rs index b4d223fd0a7ff..ffb9c95de5dd1 100644 --- a/crates/oxc_transformer/src/es2019/json_strings.rs +++ b/crates/oxc_transformer/src/es2019/json_strings.rs @@ -1,4 +1,6 @@ -use oxc_ast::ast::*; +use std::rc::Rc; + +use oxc_ast::{ast::*, AstBuilder}; use oxc_span::Atom; use oxc_syntax::identifier::{LS, PS}; @@ -9,17 +11,19 @@ use crate::options::{TransformOptions, TransformTarget}; /// References: /// * /// * -pub struct JsonStrings; +pub struct JsonStrings<'a> { + ast: Rc>, +} -impl JsonStrings { - pub fn new(options: &TransformOptions) -> Option { - (options.target < TransformTarget::ES2019 || options.json_strings).then(|| Self {}) +impl<'a> JsonStrings<'a> { + pub fn new(ast: Rc>, options: &TransformOptions) -> Option { + (options.target < TransformTarget::ES2019 || options.json_strings).then(|| Self { ast }) } // Allow `U+2028` and `U+2029` in string literals // // - fn normalize_str(str: &str) -> Option { + fn normalize_str(&self, str: &str) -> Option> { if !str.contains(LS) && !str.contains(PS) { return None; } @@ -33,7 +37,7 @@ impl JsonStrings { } is_escaped = !is_escaped && matches!(c, '\\'); } - Some(buf.into()) + Some(self.ast.new_atom(&buf)) } #[allow(clippy::unused_self)] @@ -48,8 +52,8 @@ impl JsonStrings { } #[allow(clippy::unused_self)] - pub fn transform_directive(&mut self, directive: &mut Directive) { - if let Some(value) = Self::normalize_str(directive.directive.as_str()) { + pub fn transform_directive(&mut self, directive: &mut Directive<'a>) { + if let Some(value) = self.normalize_str(directive.directive.as_str()) { directive.directive = value; } } diff --git a/crates/oxc_transformer/src/es2022/class_static_block.rs b/crates/oxc_transformer/src/es2022/class_static_block.rs index 498e9f4a29670..b647fd000d29a 100644 --- a/crates/oxc_transformer/src/es2022/class_static_block.rs +++ b/crates/oxc_transformer/src/es2022/class_static_block.rs @@ -25,7 +25,7 @@ impl<'a> ClassStaticBlock<'a> { return; } - let private_names: HashSet = class_body + let private_names: HashSet> = class_body .body .iter() .filter_map(ClassElement::property_key) @@ -107,7 +107,7 @@ impl<'a> ClassStaticBlock<'a> { } } -fn generate_uid(deny_list: &HashSet, i: &mut u32) -> Atom { +fn generate_uid<'a>(deny_list: &HashSet>, i: &mut u32) -> Atom<'a> { *i += 1; let mut uid: Atom = if *i == 1 { "_".to_string() } else { format!("_{i}") }.into(); diff --git a/crates/oxc_transformer/src/lib.rs b/crates/oxc_transformer/src/lib.rs index 24d41af086dc9..a4d6e73ad276a 100644 --- a/crates/oxc_transformer/src/lib.rs +++ b/crates/oxc_transformer/src/lib.rs @@ -72,7 +72,7 @@ pub struct Transformer<'a> { // es2020 es2020_nullish_coalescing_operators: Option>, // es2019 - es2019_json_strings: Option, + es2019_json_strings: Option>, es2019_optional_catch_binding: Option>, // es2016 es2016_exponentiation_operator: Option>, @@ -114,7 +114,7 @@ impl<'a> Transformer<'a> { // es2020 es2020_nullish_coalescing_operators: NullishCoalescingOperator::new(Rc::clone(&ast), ctx.clone(), &options), // es2019 - es2019_json_strings: JsonStrings::new(&options), + es2019_json_strings: JsonStrings::new(Rc::clone(&ast), &options), es2019_optional_catch_binding: OptionalCatchBinding::new(Rc::clone(&ast), &options), // es2016 es2016_exponentiation_operator: ExponentiationOperator::new(Rc::clone(&ast), ctx.clone(), &options), @@ -302,7 +302,7 @@ impl<'a> VisitMut<'a> for Transformer<'a> { self.leave_node(kind); } - fn visit_directive(&mut self, directive: &mut Directive) { + fn visit_directive(&mut self, directive: &mut Directive<'a>) { self.es2019_json_strings .as_mut() .map(|t: &mut JsonStrings| t.transform_directive(directive)); diff --git a/crates/oxc_transformer/src/proposals/decorators.rs b/crates/oxc_transformer/src/proposals/decorators.rs index d0cb6a83ee1ef..7124e3d8eb2c3 100644 --- a/crates/oxc_transformer/src/proposals/decorators.rs +++ b/crates/oxc_transformer/src/proposals/decorators.rs @@ -1,9 +1,9 @@ -use std::{collections::HashMap, rc::Rc}; +use std::{borrow::Cow, collections::HashMap, rc::Rc}; use bitflags::bitflags; use oxc_allocator::{Box, Vec}; use oxc_ast::{ast::*, AstBuilder}; -use oxc_span::{Atom, SPAN}; +use oxc_span::{CompactString, SPAN}; use oxc_syntax::operator::{AssignmentOperator, LogicalOperator}; use serde::Deserialize; @@ -23,7 +23,7 @@ pub struct Decorators<'a> { top_statements: Vec<'a, Statement<'a>>, // Insert to the bottom of the program bottom_statements: Vec<'a, Statement<'a>>, - uid_map: HashMap, + uid_map: HashMap, } bitflags! { @@ -120,7 +120,8 @@ impl<'a> Decorators<'a> { }) } - pub fn get_variable_declarator(&self, name: Atom) -> VariableDeclarator<'a> { + pub fn get_variable_declarator(&self, name: &str) -> VariableDeclarator<'a> { + let name = self.ast.new_atom(name); self.ast.variable_declarator( SPAN, VariableDeclarationKind::Var, @@ -135,21 +136,25 @@ impl<'a> Decorators<'a> { #[allow(clippy::unnecessary_wraps)] pub fn get_assignment_target_maybe_default( &self, - name: Atom, + name: &str, ) -> Option> { + let name = self.ast.new_atom(name); Some(AssignmentTargetMaybeDefault::AssignmentTarget( self.ast.simple_assignment_target_identifier(IdentifierReference::new(SPAN, name)), )) } // TODO: use generate_uid of scope to generate unique name - pub fn get_unique_name(&mut self, name: &Atom) -> Atom { - let uid = self.uid_map.entry(name.clone()).or_insert(0); + pub fn get_unique_name(&mut self, name: &str) -> CompactString { + let uid = self.uid_map.entry(CompactString::new(name)).or_insert(0); *uid += 1; - Atom::from(format!("_{name}{}", if *uid == 1 { String::new() } else { uid.to_string() })) + CompactString::from(format!( + "_{name}{}", + if *uid == 1 { String::new() } else { uid.to_string() } + )) } - pub fn get_call_with_this(&self, name: Atom) -> Expression<'a> { + pub fn get_call_with_this(&self, name: &str) -> Expression<'a> { self.get_call_with_arguments( name, self.ast.new_vec_single(Argument::Expression(self.ast.this_expression(SPAN))), @@ -158,9 +163,10 @@ impl<'a> Decorators<'a> { pub fn get_call_with_arguments( &self, - name: Atom, + name: &str, arguments: Vec<'a, Argument<'a>>, ) -> Expression<'a> { + let name = self.ast.new_atom(name); self.ast.call_expression( SPAN, self.ast.identifier_reference_expression(IdentifierReference::new(SPAN, name)), @@ -193,7 +199,7 @@ impl<'a> Decorators<'a> { .id .clone() .map(|id| self.get_unique_name(&id.name)) - .or_else(|| Some(self.get_unique_name(&"class".into()))) + .or_else(|| Some(self.get_unique_name("class"))) } else { None }; @@ -209,7 +215,9 @@ impl<'a> Decorators<'a> { ModuleExportName::Identifier( IdentifierName::new( SPAN, - class_name.clone().unwrap(), + self.ast.new_atom( + class_name.as_ref().unwrap(), + ), ), ), ModuleExportName::Identifier( @@ -250,7 +258,7 @@ impl<'a> Decorators<'a> { .id .clone() .map(|id| self.get_unique_name(&id.name)) - .or_else(|| Some(self.get_unique_name(&"class".into()))) + .or_else(|| Some(self.get_unique_name("class"))) } else { None }; @@ -265,11 +273,11 @@ impl<'a> Decorators<'a> { SPAN, ModuleExportName::Identifier(IdentifierName::new( SPAN, - class_name.clone().unwrap(), + self.ast.new_atom(class_name.as_ref().unwrap()), )), ModuleExportName::Identifier(IdentifierName::new( SPAN, - "default".into(), + self.ast.new_atom("default"), )), )), None, @@ -315,7 +323,7 @@ impl<'a> Decorators<'a> { pub fn transform_class( &mut self, class: &mut Box<'a, Class<'a>>, - class_name: Option, + class_name: Option, ) -> Declaration<'a> { if self.options.version.is_legacy() { return self.transform_class_legacy(class, class_name); @@ -339,22 +347,22 @@ impl<'a> Decorators<'a> { Argument::Expression(self.ast.array_expression(SPAN, self.ast.new_vec(), None)); if has_decorator { - let class_name = class_name.unwrap_or_else(|| self.get_unique_name(&"class".into())); + let class_name = class_name.unwrap_or_else(|| self.get_unique_name("class")); - let class_decs_name = self.get_unique_name(&"classDecs".into()); - let init_class_name = self.get_unique_name(&"initClass".into()); + let class_decs_name = self.get_unique_name("classDecs"); + let init_class_name = self.get_unique_name("initClass"); { // insert var _initClass, _classDecs; - declarations.push(self.get_variable_declarator(init_class_name.clone())); - declarations.push(self.get_variable_declarator(class_decs_name.clone())); + declarations.push(self.get_variable_declarator(&init_class_name)); + declarations.push(self.get_variable_declarator(&class_decs_name)); } { // insert _classDecs = decorators; let left = self.ast.simple_assignment_target_identifier(IdentifierReference::new( SPAN, - class_decs_name.clone(), + self.ast.new_atom(&class_decs_name), )); let right = self.ast.array_expression( @@ -378,7 +386,7 @@ impl<'a> Decorators<'a> { { // insert let _className let declarations = - self.ast.new_vec_single(self.get_variable_declarator(class_name.clone())); + self.ast.new_vec_single(self.get_variable_declarator(&class_name)); let variable_declaration = self.ast.variable_declaration( SPAN, VariableDeclarationKind::Let, @@ -390,19 +398,19 @@ impl<'a> Decorators<'a> { ))); } - c_elements.push(self.get_assignment_target_maybe_default(class_name)); - c_elements.push(self.get_assignment_target_maybe_default(init_class_name.clone())); + c_elements.push(self.get_assignment_target_maybe_default(&class_name)); + c_elements.push(self.get_assignment_target_maybe_default(&init_class_name)); class_decorators_argument = Argument::Expression(self.ast.identifier_reference_expression( - IdentifierReference::new(SPAN, class_decs_name), + IdentifierReference::new(SPAN, self.ast.new_atom(&class_decs_name)), )); { // call _initClass let callee = self.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - init_class_name, + self.ast.new_atom(&init_class_name), )); let call_expr = self.ast.call_expression(SPAN, callee, self.ast.new_vec(), false, None); @@ -415,10 +423,10 @@ impl<'a> Decorators<'a> { let mut is_proto = false; let mut is_static = false; - let mut name = Atom::new_inline(""); - class.body.body.iter_mut().for_each(|element| { + let mut name; + for element in class.body.body.iter_mut() { if !element.has_decorator() { - return; + continue; } match element { ClassElement::MethodDefinition(def) => { @@ -432,7 +440,7 @@ impl<'a> Decorators<'a> { flag |= DecoratorFlags::Static; } - def.decorators.iter().for_each(|decorator| { + for decorator in &def.decorators { member_decorators_vec.push(ArrayExpressionElement::Expression( self.get_decorator_info( &def.key, @@ -441,7 +449,7 @@ impl<'a> Decorators<'a> { decorator, ), )); - }); + } def.decorators.clear(); @@ -463,7 +471,7 @@ impl<'a> Decorators<'a> { self.ast.binding_pattern_identifier( BindingIdentifier::new( SPAN, - "_".into(), + self.ast.new_atom("_"), ), ), None, @@ -491,7 +499,7 @@ impl<'a> Decorators<'a> { .identifier_reference_expression( IdentifierReference::new( SPAN, - "_".into(), + self.ast.new_atom("_"), ), ), ), @@ -506,9 +514,9 @@ impl<'a> Decorators<'a> { } name = self.get_unique_name(&if def.computed { - "init_computedKey".into() + Cow::Borrowed("init_computedKey") } else { - format!("call_{}", def.key.name().unwrap()).into() + Cow::Owned(format!("call_{}", def.key.name().unwrap())) }); let mut arguments = self.ast.new_vec_with_capacity(2); @@ -516,7 +524,7 @@ impl<'a> Decorators<'a> { arguments.push(Argument::Expression( self.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - "v".into(), + self.ast.new_atom("v"), )), )); @@ -537,7 +545,10 @@ impl<'a> Decorators<'a> { SPAN, self.ast.binding_pattern( self.ast.binding_pattern_identifier( - BindingIdentifier::new(SPAN, "v".into()), + BindingIdentifier::new( + SPAN, + self.ast.new_atom("v"), + ), ), None, false, @@ -557,12 +568,12 @@ impl<'a> Decorators<'a> { self.ast.new_vec_single(if is_setter { self.ast.expression_statement( SPAN, - self.get_call_with_arguments(name.clone(), arguments), + self.get_call_with_arguments(&name, arguments), ) } else { self.ast.return_statement( SPAN, - Some(self.get_call_with_this(name.clone())), + Some(self.get_call_with_this(&name)), ) }), )), @@ -571,7 +582,7 @@ impl<'a> Decorators<'a> { self.ast.copy(&def.value.modifiers), ); } else { - return; + continue; } } ClassElement::PropertyDefinition(def) => { @@ -582,16 +593,16 @@ impl<'a> Decorators<'a> { }; name = self.get_unique_name(&if def.computed { - "init_computedKey".into() + Cow::Borrowed("init_computedKey") } else { - format!("init_{}", def.key.name().unwrap()).into() + Cow::Owned(format!("init_{}", def.key.name().unwrap())) }); - def.decorators.iter().for_each(|decorator| { + for decorator in &def.decorators { member_decorators_vec.push(ArrayExpressionElement::Expression( self.get_decorator_info(&def.key, None, flag, decorator), )); - }); + } def.decorators.clear(); let mut arguments = self @@ -606,25 +617,25 @@ impl<'a> Decorators<'a> { SPAN, self.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - name.clone(), + self.ast.new_atom(&name), )), arguments, false, None, )); } - _ => return, + _ => continue, } - e_elements.push(self.get_assignment_target_maybe_default(name.clone())); - declarations.push(self.get_variable_declarator(name.clone())); - }); + e_elements.push(self.get_assignment_target_maybe_default(&name)); + declarations.push(self.get_variable_declarator(&name)); + } if is_proto { // The class has method decorator and is not static - let name = self.get_unique_name(&"initProto".into()); - e_elements.push(self.get_assignment_target_maybe_default(name.clone())); - declarations.push(self.get_variable_declarator(name.clone())); + let name = self.get_unique_name("initProto"); + e_elements.push(self.get_assignment_target_maybe_default(&name)); + declarations.push(self.get_variable_declarator(&name)); // constructor() { _initProto(this) } if let Some(constructor_element) = class.body.body.iter_mut().find( @@ -632,7 +643,7 @@ impl<'a> Decorators<'a> { ) { if let ClassElement::MethodDefinition(def) = constructor_element { if let Some(body) = &mut def.value.body { - body.statements.insert(0, self.ast.expression_statement(SPAN, self.get_call_with_this(name))); + body.statements.insert(0, self.ast.expression_statement(SPAN, self.get_call_with_this(&name))); } } else { unreachable!(); @@ -660,7 +671,7 @@ impl<'a> Decorators<'a> { SPAN, self.ast.new_vec(), self.ast.new_vec_single( - self.ast.expression_statement(SPAN, self.get_call_with_this(name)) + self.ast.expression_statement(SPAN, self.get_call_with_this(&name)) ), )), None, @@ -673,9 +684,9 @@ impl<'a> Decorators<'a> { } if is_static { - let name = self.get_unique_name(&"initStatic".into()); - e_elements.push(self.get_assignment_target_maybe_default(name.clone())); - declarations.push(self.get_variable_declarator(name.clone())); + let name = self.get_unique_name("initStatic"); + e_elements.push(self.get_assignment_target_maybe_default(&name)); + declarations.push(self.get_variable_declarator(&name)); init_static_name = Some(name); } } @@ -709,9 +720,9 @@ impl<'a> Decorators<'a> { SPAN, self.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - "babelHelpers".into(), + self.ast.new_atom("babelHelpers"), )), - IdentifierName::new(SPAN, "applyDecs2305".into()), + IdentifierName::new(SPAN, self.ast.new_atom("applyDecs2305")), false, ); @@ -741,7 +752,10 @@ impl<'a> Decorators<'a> { call_expr = self.ast.static_member_expression( SPAN, call_expr, - IdentifierName::new(SPAN, if has_decorator { "c".into() } else { "e".into() }), + IdentifierName::new( + SPAN, + self.ast.new_atom(if has_decorator { "c" } else { "e" }), + ), false, ); } @@ -760,7 +774,7 @@ impl<'a> Decorators<'a> { // call initStatic let callee = self.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - init_static_name, + self.ast.new_atom(&init_static_name), )); let arguments = self.ast.new_vec_single(Argument::Expression(self.ast.this_expression(SPAN))); @@ -781,26 +795,25 @@ impl<'a> Decorators<'a> { pub fn transform_class_legacy( &mut self, class: &mut Box<'a, Class<'a>>, - class_name: Option, + class_name: Option, ) -> Declaration<'a> { let class_binding_identifier = &class.id.clone().unwrap_or_else(|| { - BindingIdentifier::new( - SPAN, - class_name.unwrap_or_else(|| self.get_unique_name(&"class".into())), - ) + let class_name = class_name.unwrap_or_else(|| self.get_unique_name("class")); + BindingIdentifier::new(SPAN, self.ast.new_atom(&class_name)) }); let class_name = BindingPattern::new_with_kind( self.ast.binding_pattern_identifier(self.ast.copy(class_binding_identifier)), ); let init = { - let class_identifier_name: Atom = self.get_unique_name(&"class".into()); - let class_identifier = IdentifierReference::new(SPAN, class_identifier_name.clone()); + let class_identifier_name = self.get_unique_name("class"); + let class_identifier = + IdentifierReference::new(SPAN, self.ast.new_atom(&class_identifier_name)); let decl = self.ast.variable_declaration( SPAN, VariableDeclarationKind::Var, - self.ast.new_vec_single(self.get_variable_declarator(class_identifier_name)), + self.ast.new_vec_single(self.get_variable_declarator(&class_identifier_name)), Modifiers::empty(), ); self.top_statements @@ -889,7 +902,7 @@ impl<'a> Decorators<'a> { self.ast.binding_pattern( self.ast.binding_pattern_identifier(BindingIdentifier::new( SPAN, - "o".into(), + self.ast.new_atom("o"), )), None, false, @@ -902,7 +915,7 @@ impl<'a> Decorators<'a> { SPAN, self.ast.identifier_reference_expression(IdentifierReference::new( SPAN, - "o".into(), + self.ast.new_atom("o"), )), PrivateIdentifier::new(SPAN, name), false, @@ -939,7 +952,7 @@ impl<'a> Decorators<'a> { self.ast.binding_pattern( self.ast.binding_pattern_identifier(BindingIdentifier::new( SPAN, - "v".into(), + self.ast.new_atom("v"), )), None, false, @@ -974,7 +987,10 @@ impl<'a> Decorators<'a> { private_field, ), self.ast.identifier_reference_expression( - IdentifierReference::new(SPAN, "v".into()), + IdentifierReference::new( + SPAN, + self.ast.new_atom("v"), + ), ), ), )), diff --git a/crates/oxc_transformer/src/react_jsx/mod.rs b/crates/oxc_transformer/src/react_jsx/mod.rs index 96d38facb7969..fe7162ed53663 100644 --- a/crates/oxc_transformer/src/react_jsx/mod.rs +++ b/crates/oxc_transformer/src/react_jsx/mod.rs @@ -8,7 +8,7 @@ use oxc_diagnostics::{ miette::{self, Diagnostic}, thiserror::Error, }; -use oxc_span::{Atom, GetSpan, Span, SPAN}; +use oxc_span::{Atom, CompactString, GetSpan, Span, SPAN}; use oxc_syntax::{ identifier::{is_irregular_whitespace, is_line_terminator}, xml_entities::XML_ENTITIES, @@ -58,7 +58,7 @@ pub struct ReactJsx<'a> { import_fragment: bool, import_create_element: bool, require_jsx_runtime: bool, - jsx_runtime_importer: Atom, + jsx_runtime_importer: CompactString, pub babel_8_breaking: Option, default_runtime: ReactJsxRuntime, } @@ -129,9 +129,9 @@ impl<'a> ReactJsx<'a> { let jsx_runtime_importer = if jsx_options.import_source == "react" || default_runtime.is_classic() { - Atom::new_inline("react/jsx-runtime") + CompactString::from("react/jsx-runtime") } else { - Atom::from(format!("{}/jsx-runtime", jsx_options.import_source)) + CompactString::from(format!("{}/jsx-runtime", jsx_options.import_source)) }; Some(Self { ast, @@ -209,8 +209,8 @@ impl<'a> ReactJsx<'a> { program.body.splice(index..index, imports); } - fn new_string_literal(name: &str) -> StringLiteral { - StringLiteral::new(SPAN, name.into()) + fn new_string_literal(&self, name: &str) -> StringLiteral<'a> { + StringLiteral::new(SPAN, self.ast.new_atom(name)) } fn add_import<'b>( @@ -242,7 +242,7 @@ impl<'a> ReactJsx<'a> { self.require_jsx_runtime = true; self.add_require_statement( "_reactJsxRuntime", - Self::new_string_literal(self.jsx_runtime_importer.as_str()), + self.new_string_literal(self.jsx_runtime_importer.as_str()), false, ); } @@ -256,7 +256,7 @@ impl<'a> ReactJsx<'a> { self.add_import_statement( "jsx", "_jsx", - Self::new_string_literal(self.jsx_runtime_importer.as_str()), + self.new_string_literal(self.jsx_runtime_importer.as_str()), ); } } @@ -266,7 +266,7 @@ impl<'a> ReactJsx<'a> { self.add_require_jsx_runtime(); } else if !self.import_jsxs { self.import_jsxs = true; - let source = Self::new_string_literal(self.jsx_runtime_importer.as_str()); + let source = self.new_string_literal(self.jsx_runtime_importer.as_str()); self.add_import_statement("jsxs", "_jsxs", source); } } @@ -276,7 +276,7 @@ impl<'a> ReactJsx<'a> { self.add_require_jsx_runtime(); } else if !self.import_fragment { self.import_fragment = true; - let source = Self::new_string_literal(self.jsx_runtime_importer.as_str()); + let source = self.new_string_literal(self.jsx_runtime_importer.as_str()); self.add_import_statement("Fragment", "_Fragment", source); self.add_import_jsx(); } @@ -289,22 +289,25 @@ impl<'a> ReactJsx<'a> { if self.ctx.source_type().is_script() { self.add_require_statement( "_react", - Self::new_string_literal(self.options.import_source.as_ref()), + self.new_string_literal(self.options.import_source.as_ref()), true, ); } else { - let source = Self::new_string_literal(self.options.import_source.as_ref()); + let source = self.new_string_literal(self.options.import_source.as_ref()); self.add_import_statement("createElement", "_createElement", source); } } } - fn add_import_statement(&mut self, imported: &str, local: &str, source: StringLiteral) { + fn add_import_statement(&mut self, imported: &str, local: &str, source: StringLiteral<'a>) { let mut specifiers = self.ast.new_vec_with_capacity(1); specifiers.push(ImportDeclarationSpecifier::ImportSpecifier(ImportSpecifier { span: SPAN, - imported: ModuleExportName::Identifier(IdentifierName::new(SPAN, imported.into())), - local: BindingIdentifier::new(SPAN, local.into()), + imported: ModuleExportName::Identifier(IdentifierName::new( + SPAN, + self.ast.new_atom(imported), + )), + local: BindingIdentifier::new(SPAN, self.ast.new_atom(local)), import_kind: ImportOrExportKind::Value, })); let import_statement = self.ast.import_declaration( @@ -319,7 +322,12 @@ impl<'a> ReactJsx<'a> { self.imports.push(decl); } - fn add_require_statement(&mut self, variable_name: &str, source: StringLiteral, front: bool) { + fn add_require_statement( + &mut self, + variable_name: &str, + source: StringLiteral<'a>, + front: bool, + ) { let callee = self .ast .identifier_reference_expression(IdentifierReference::new(SPAN, "require".into())); @@ -328,7 +336,10 @@ impl<'a> ReactJsx<'a> { .new_vec_single(Argument::Expression(self.ast.literal_string_expression(source))); let init = self.ast.call_expression(SPAN, callee, arguments, false, None); let id = self.ast.binding_pattern( - self.ast.binding_pattern_identifier(BindingIdentifier::new(SPAN, variable_name.into())), + self.ast.binding_pattern_identifier(BindingIdentifier::new( + SPAN, + self.ast.new_atom(variable_name), + )), None, false, ); @@ -486,8 +497,8 @@ impl<'a> ReactJsx<'a> { object_ident_name: &str, property_name: &str, ) -> Expression<'a> { - let property = IdentifierName::new(SPAN, property_name.into()); - let ident = IdentifierReference::new(SPAN, object_ident_name.into()); + let property = IdentifierName::new(SPAN, self.ast.new_atom(property_name)); + let ident = IdentifierReference::new(SPAN, self.ast.new_atom(object_ident_name)); let object = self.ast.identifier_reference_expression(ident); self.ast.static_member_expression(SPAN, object, property, false) } @@ -499,7 +510,7 @@ impl<'a> ReactJsx<'a> { let property = callee.next(); property.map_or_else( || { - let ident = IdentifierReference::new(SPAN, member.into()); + let ident = IdentifierReference::new(SPAN, self.ast.new_atom(member)); self.ast.identifier_reference_expression(ident) }, |property_name| self.get_static_member_expression(member, property_name), diff --git a/crates/oxc_transformer/src/regexp/regexp_flags.rs b/crates/oxc_transformer/src/regexp/regexp_flags.rs index 8029e08bd832a..e8c58472275b0 100644 --- a/crates/oxc_transformer/src/regexp/regexp_flags.rs +++ b/crates/oxc_transformer/src/regexp/regexp_flags.rs @@ -53,13 +53,13 @@ impl<'a> RegexpFlags<'a> { // `/regex/flags` -> `new RegExp('regex', 'flags')` pub fn transform_expression(&self, expr: &mut Expression<'a>) { let Expression::RegExpLiteral(literal) = expr else { return }; - let regex = &literal.regex; + let regex = literal.regex.clone(); if regex.flags.intersection(self.transform_flags).is_empty() { return; } let ident = IdentifierReference::new(SPAN, Atom::from("RegExp")); let callee = self.ast.identifier_reference_expression(ident); - let pattern = StringLiteral::new(SPAN, Atom::from(regex.pattern.as_str())); + let pattern = StringLiteral::new(SPAN, regex.pattern.clone()); let flags = StringLiteral::new(SPAN, Atom::from(regex.flags.to_string())); let pattern_literal = self.ast.literal_string_expression(pattern); let flags_literal = self.ast.literal_string_expression(flags); diff --git a/crates/oxc_transformer/src/typescript/mod.rs b/crates/oxc_transformer/src/typescript/mod.rs index cd2687d77df3f..1a161ce7ca1d3 100644 --- a/crates/oxc_transformer/src/typescript/mod.rs +++ b/crates/oxc_transformer/src/typescript/mod.rs @@ -24,9 +24,9 @@ pub struct TypeScript<'a> { ast: Rc>, ctx: TransformerCtx<'a>, verbatim_module_syntax: bool, - export_name_set: FxHashSet, + export_name_set: FxHashSet>, options: TypescriptOptions, - namespace_arg_names: FxHashMap, + namespace_arg_names: FxHashMap, usize>, } impl<'a> TypeScript<'a> { @@ -318,7 +318,7 @@ impl<'a> TypeScript<'a> { fn transform_ts_enum_members( &self, members: &mut Vec<'a, TSEnumMember<'a>>, - enum_name: &Atom, + enum_name: &Atom<'a>, ) -> Vec<'a, Statement<'a>> { let mut default_init = self.ast.literal_number_expression(NumericLiteral { span: SPAN, @@ -668,7 +668,7 @@ impl<'a> TypeScript<'a> { } } - fn get_namespace_arg_name(&mut self, name: &Atom) -> Atom { + fn get_namespace_arg_name(&mut self, name: &Atom<'a>) -> Atom<'a> { let count = self.namespace_arg_names.entry(name.clone()).or_insert(0); *count += 1; format!("_{name}{}", if *count > 1 { count.to_string() } else { String::new() }).into() diff --git a/crates/oxc_transformer/src/utils.rs b/crates/oxc_transformer/src/utils.rs index 0d700ec26031e..db3ebeda23d28 100644 --- a/crates/oxc_transformer/src/utils.rs +++ b/crates/oxc_transformer/src/utils.rs @@ -25,12 +25,13 @@ pub trait CreateVars<'a> { stmts.insert(0, stmt); } - fn create_new_var(&mut self, expr: &Expression<'a>) -> IdentifierReference { + fn create_new_var(&mut self, expr: &Expression<'a>) -> IdentifierReference<'a> { let name = self.ctx().scopes().generate_uid_based_on_node(expr); self.ctx().add_binding(name.clone()); // Add `var name` to scope // TODO: hookup symbol id + let name = self.ctx().ast.new_atom(name.as_str()); let binding_identifier = BindingIdentifier::new(Span::default(), name.clone()); let binding_pattern_kind = self.ctx().ast.binding_pattern_identifier(binding_identifier); let binding = self.ctx().ast.binding_pattern(binding_pattern_kind, None, false); @@ -43,7 +44,10 @@ pub trait CreateVars<'a> { /// Possibly generate a memoised identifier if it is not static and has consequences. /// - fn maybe_generate_memoised(&mut self, expr: &Expression<'a>) -> Option { + fn maybe_generate_memoised( + &mut self, + expr: &Expression<'a>, + ) -> Option> { if self.ctx().symbols().is_static(expr) { None } else { diff --git a/tasks/prettier_conformance/src/lib.rs b/tasks/prettier_conformance/src/lib.rs index b325941499338..21d1ca5c2fa8f 100644 --- a/tasks/prettier_conformance/src/lib.rs +++ b/tasks/prettier_conformance/src/lib.rs @@ -12,7 +12,7 @@ use walkdir::WalkDir; use oxc_allocator::Allocator; use oxc_parser::Parser; use oxc_prettier::{Prettier, PrettierOptions}; -use oxc_span::{Atom, SourceType}; +use oxc_span::SourceType; use oxc_tasks_common::project_root; use crate::{ @@ -257,7 +257,7 @@ impl TestRunner { path: &Path, input: &str, prettier_options: PrettierOptions, - snapshot_options: &[(Atom, String)], + snapshot_options: &[(String, String)], snap_content: &str, ) -> String { let filename = path.file_name().unwrap().to_string_lossy(); diff --git a/tasks/prettier_conformance/src/runner.rs b/tasks/prettier_conformance/src/runner.rs index 279cebe32bc19..b68c84447e09f 100644 --- a/tasks/prettier_conformance/src/runner.rs +++ b/tasks/prettier_conformance/src/runner.rs @@ -186,7 +186,7 @@ impl TestRunner { path: &Path, input: &str, prettier_options: PrettierOptions, - snapshot_options: &[(Atom, String)], + snapshot_options: &[(String, String)], snap_content: &str, ) -> String { let filename = path.file_name().unwrap().to_string_lossy(); diff --git a/tasks/prettier_conformance/src/spec.rs b/tasks/prettier_conformance/src/spec.rs index cae735516dee8..327b56319257d 100644 --- a/tasks/prettier_conformance/src/spec.rs +++ b/tasks/prettier_conformance/src/spec.rs @@ -9,11 +9,11 @@ use oxc_ast::{ }; use oxc_parser::Parser; use oxc_prettier::{ArrowParens, EndOfLine, PrettierOptions, QuoteProps, TrailingComma}; -use oxc_span::{Atom, GetSpan, SourceType}; +use oxc_span::{GetSpan, SourceType}; #[derive(Default)] pub struct SpecParser { - pub calls: Vec<(PrettierOptions, Vec<(Atom, String)>)>, + pub calls: Vec<(PrettierOptions, Vec<(String, String)>)>, source_text: String, } @@ -39,7 +39,7 @@ impl VisitMut<'_> for SpecParser { return; } let mut parsers = vec![]; - let mut snapshot_options = vec![]; + let mut snapshot_options: Vec<(String, String)> = vec![]; let mut options = PrettierOptions::default(); if let Some(argument) = expr.arguments.get(1) { @@ -110,7 +110,7 @@ impl VisitMut<'_> for SpecParser { }; if name != "errors" { snapshot_options.push(( - name, + name.to_string(), obj_prop.value.span().source_text(&self.source_text).to_string(), )); } @@ -120,7 +120,7 @@ impl VisitMut<'_> for SpecParser { } snapshot_options.push(( - "parsers".into(), + "parsers".to_string(), format!( "[{}]", parsers.iter().map(|p| format!("\"{p}\"")).collect::>().join(", ") @@ -128,7 +128,7 @@ impl VisitMut<'_> for SpecParser { )); if !snapshot_options.iter().any(|item| item.0 == "printWidth") { - snapshot_options.push(("printWidth".into(), "80".into())); + snapshot_options.push(("printWidth".to_string(), "80".into())); } snapshot_options.sort_by(|a, b| a.0.cmp(&b.0));