From be6b8b7ce6767427f1b108bcbeeaa96706aa082c Mon Sep 17 00:00:00 2001 From: Boshen Date: Mon, 26 Feb 2024 19:34:40 +0800 Subject: [PATCH] [BREAKING CHANGE] Change `Atom` to `Atom<'a>` to make it safe (#2497) Part of #2295 This PR splits the `Atom` type into `Atom<'a>` and `CompactString`. All the AST node strings now use `Atom<'a>` instead of `Atom` to signify it belongs to the arena. It is now up to the user to select which form of the string to use. This PR essentially removes the really unsafe code https://github.com/oxc-project/oxc/blob/93742f89e91bc7c45491b6d2b49a134fa65f2b5c/crates/oxc_span/src/atom.rs#L98-L107 which can lead to ![image](https://github.com/oxc-project/oxc/assets/1430279/8c513c4f-19b0-4b63-b61c-e07c187c95b5) --- Cargo.lock | 30 +++ crates/oxc_ast/src/ast/js.rs | 208 +++++++++--------- crates/oxc_ast/src/ast/jsx.rs | 32 +-- crates/oxc_ast/src/ast/literal.rs | 24 +- crates/oxc_ast/src/ast/ts.rs | 70 +++--- crates/oxc_ast/src/ast_builder.rs | 115 ++++++---- crates/oxc_ast/src/ast_kind.rs | 42 ++-- crates/oxc_ast/src/span.rs | 10 +- .../syntax_directed_operations/bound_names.rs | 78 +++---- .../gather_node_parts.rs | 36 +-- crates/oxc_ast/src/visit.rs | 40 ++-- crates/oxc_ast/src/visit_mut.rs | 48 ++-- crates/oxc_codegen/src/gen.rs | 38 ++-- crates/oxc_js_regex/src/ast.rs | 12 +- .../deepscan/bad_array_method_on_arguments.rs | 10 +- .../rules/deepscan/number_arg_out_of_range.rs | 10 +- .../rules/eslint/array_callback_return/mod.rs | 12 +- .../src/rules/eslint/no_class_assign.rs | 6 +- .../src/rules/eslint/no_const_assign.rs | 6 +- .../src/rules/eslint/no_control_regex.rs | 12 +- .../src/rules/eslint/no_dupe_class_members.rs | 4 +- .../src/rules/eslint/no_func_assign.rs | 6 +- .../src/rules/eslint/no_global_assign.rs | 10 +- .../src/rules/eslint/no_new_wrappers.rs | 6 +- .../src/rules/eslint/no_obj_calls.rs | 38 ++-- .../src/rules/eslint/no_redeclare.rs | 23 +- .../eslint/no_shadow_restricted_names.rs | 33 ++- .../oxc_linter/src/rules/eslint/no_undef.rs | 4 +- .../src/rules/eslint/no_unused_labels.rs | 6 +- .../eslint/no_unused_private_class_members.rs | 40 ++-- crates/oxc_linter/src/rules/import/export.rs | 8 +- .../oxc_linter/src/rules/import/namespace.rs | 4 +- crates/oxc_linter/src/rules/import/no_amd.rs | 9 +- .../oxc_linter/src/rules/import/no_cycle.rs | 4 +- .../src/rules/import/no_deprecated.rs | 4 +- .../import/no_named_as_default_member.rs | 12 +- .../src/rules/import/no_unused_modules.rs | 4 +- .../rules/jest/no_confusing_set_timeout.rs | 4 +- .../src/rules/jest/no_identical_title.rs | 2 +- .../src/rules/jest/no_test_prefixes.rs | 10 +- .../oxc_linter/src/rules/jest/valid_expect.rs | 30 +-- .../oxc_linter/src/rules/jest/valid_title.rs | 20 +- .../src/rules/oxc/only_used_in_recursion.rs | 9 +- .../src/rules/react/jsx_no_duplicate_props.rs | 6 +- .../src/rules/react/jsx_no_undef.rs | 6 +- .../adjacent_overload_signatures.rs | 26 ++- .../src/rules/typescript/ban_types.rs | 6 +- .../src/rules/typescript/no_this_alias.rs | 18 +- .../no_unnecessary_type_constraint.rs | 6 +- .../src/rules/unicorn/catch_error_name.rs | 30 +-- .../src/rules/unicorn/error_message.rs | 6 +- .../rules/unicorn/explicit_length_check.rs | 10 +- .../src/rules/unicorn/no_this_assignment.rs | 8 +- .../src/rules/unicorn/prefer_date_now.rs | 4 +- .../rules/unicorn/prefer_modern_dom_apis.rs | 8 +- .../prefer_native_coercion_functions.rs | 2 +- .../src/rules/unicorn/prefer_node_protocol.rs | 4 +- .../unicorn/prefer_string_replace_all.rs | 8 +- .../src/rules/unicorn/prefer_string_slice.rs | 6 +- .../unicorn/prefer_string_trim_start_end.rs | 6 +- .../unicorn/text_encoding_identifier_case.rs | 21 +- .../no_unused_private_class_members.snap | 6 +- crates/oxc_linter/src/utils/jest.rs | 13 +- .../src/utils/jest/parse_jest_fn.rs | 10 +- crates/oxc_linter/src/utils/nextjs.rs | 4 +- crates/oxc_minifier/src/mangler/mod.rs | 6 +- crates/oxc_parser/src/js/expression.rs | 28 ++- crates/oxc_parser/src/js/function.rs | 4 +- crates/oxc_parser/src/js/list.rs | 14 +- crates/oxc_parser/src/js/module.rs | 14 +- crates/oxc_parser/src/js/statement.rs | 4 +- crates/oxc_parser/src/jsx/mod.rs | 6 +- crates/oxc_prettier/src/format/block.rs | 4 +- crates/oxc_prettier/src/format/mod.rs | 54 ++--- .../src/format/template_literal.rs | 6 +- crates/oxc_semantic/src/binder.rs | 8 +- crates/oxc_semantic/src/builder.rs | 29 ++- crates/oxc_semantic/src/checker/javascript.rs | 33 +-- crates/oxc_semantic/src/checker/typescript.rs | 6 +- crates/oxc_semantic/src/class/builder.rs | 8 +- crates/oxc_semantic/src/class/table.rs | 19 +- crates/oxc_semantic/src/control_flow.rs | 10 +- crates/oxc_semantic/src/diagnostics.rs | 4 +- crates/oxc_semantic/src/lib.rs | 6 +- .../oxc_semantic/src/module_record/builder.rs | 66 ++++-- crates/oxc_semantic/src/reference.rs | 8 +- crates/oxc_semantic/src/scope.rs | 32 +-- crates/oxc_semantic/src/symbol.rs | 22 +- .../oxc_semantic/tests/util/symbol_tester.rs | 9 +- crates/oxc_span/Cargo.toml | 1 + crates/oxc_span/src/atom.rs | 58 +++-- crates/oxc_span/src/lib.rs | 1 + crates/oxc_syntax/src/module_record.rs | 15 +- crates/oxc_transformer/src/context.rs | 4 +- .../src/es2015/arrow_functions.rs | 6 +- .../src/es2015/duplicate_keys.rs | 2 +- .../src/es2015/function_name.rs | 2 +- .../oxc_transformer/src/es2015/new_target.rs | 14 +- .../src/es2019/json_strings.rs | 22 +- .../src/es2022/class_static_block.rs | 4 +- crates/oxc_transformer/src/lib.rs | 6 +- .../src/proposals/decorators.rs | 164 +++++++------- crates/oxc_transformer/src/react_jsx/mod.rs | 51 +++-- .../src/regexp/regexp_flags.rs | 4 +- crates/oxc_transformer/src/typescript/mod.rs | 8 +- crates/oxc_transformer/src/utils.rs | 8 +- tasks/prettier_conformance/src/lib.rs | 4 +- tasks/prettier_conformance/src/runner.rs | 2 +- tasks/prettier_conformance/src/spec.rs | 12 +- 109 files changed, 1165 insertions(+), 966 deletions(-) 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));