diff --git a/Cargo.lock b/Cargo.lock index 50126c7269c44..bb015e3ac1ce1 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2311,6 +2311,7 @@ dependencies = [ name = "oxc_semantic" version = "0.101.0" dependencies = [ + "hashbrown 0.16.0", "insta", "itertools", "oxc_allocator", @@ -2356,6 +2357,7 @@ dependencies = [ "oxc_allocator", "oxc_ast_macros", "oxc_estree", + "rustc-hash", "serde", ] diff --git a/apps/oxlint/src-js/generated/deserialize.js b/apps/oxlint/src-js/generated/deserialize.js index eeb50e6b2d993..3df6d419c65a1 100644 --- a/apps/oxlint/src-js/generated/deserialize.js +++ b/apps/oxlint/src-js/generated/deserialize.js @@ -201,7 +201,7 @@ function deserializeIdentifierName(pos) { __proto__: NodeProto, type: "Identifier", decorators: null, - name: deserializeStr(pos + 8), + name: deserializeIdent(pos + 8), optional: null, typeAnnotation: null, start, @@ -223,7 +223,7 @@ function deserializeIdentifierReference(pos) { __proto__: NodeProto, type: "Identifier", decorators: null, - name: deserializeStr(pos + 8), + name: deserializeIdent(pos + 8), optional: null, typeAnnotation: null, start, @@ -245,7 +245,7 @@ function deserializeBindingIdentifier(pos) { __proto__: NodeProto, type: "Identifier", decorators: null, - name: deserializeStr(pos + 8), + name: deserializeIdent(pos + 8), optional: null, typeAnnotation: null, start, @@ -267,7 +267,7 @@ function deserializeLabelIdentifier(pos) { __proto__: NodeProto, type: "Identifier", decorators: null, - name: deserializeStr(pos + 8), + name: deserializeIdent(pos + 8), optional: null, typeAnnotation: null, start, @@ -2649,7 +2649,7 @@ function deserializePrivateIdentifier(pos) { return { __proto__: NodeProto, type: "PrivateIdentifier", - name: deserializeStr(pos + 8), + name: deserializeIdent(pos + 8), start, end, range: [start, end], @@ -3685,7 +3685,7 @@ function deserializeJSXIdentifier(pos) { return { __proto__: NodeProto, type: "JSXIdentifier", - name: deserializeStr(pos + 8), + name: deserializeIdent(pos + 8), start, end, range: [start, end], diff --git a/crates/oxc_allocator/src/clone_in.rs b/crates/oxc_allocator/src/clone_in.rs index 99914c777a10f..812b436b89f6b 100644 --- a/crates/oxc_allocator/src/clone_in.rs +++ b/crates/oxc_allocator/src/clone_in.rs @@ -1,6 +1,12 @@ -use std::{alloc::Layout, cell::Cell, hash::Hash, ptr::NonNull, slice}; +use std::{ + alloc::Layout, + cell::Cell, + hash::{BuildHasher, Hash}, + ptr::NonNull, + slice, +}; -use crate::{Allocator, Box, HashMap, Vec}; +use crate::{Allocator, Box, HashMapImpl, Vec}; /// A trait to explicitly clone an object into an arena allocator. /// @@ -207,13 +213,14 @@ where } } -impl<'new_alloc, K, V, CK, CV> CloneIn<'new_alloc> for HashMap<'_, K, V> +impl<'new_alloc, K, V, CK, CV, H> CloneIn<'new_alloc> for HashMapImpl<'_, K, V, H> where K: CloneIn<'new_alloc, Cloned = CK>, V: CloneIn<'new_alloc, Cloned = CV>, CK: Hash + Eq, + H: BuildHasher + Default, { - type Cloned = HashMap<'new_alloc, CK, CV>; + type Cloned = HashMapImpl<'new_alloc, CK, CV, H>; fn clone_in(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { // Keys in original hash map are guaranteed to be unique. @@ -223,7 +230,7 @@ where // `hashbrown::HashMap` also has a faster cloning method in its `Clone` implementation, // but those APIs are not exposed, and `Clone` doesn't support custom allocators. // So sadly this is a lot slower than it could be, especially for `Copy` types. - let mut cloned = HashMap::with_capacity_in(self.len(), allocator); + let mut cloned = HashMapImpl::with_capacity_in(self.len(), allocator); for (key, value) in self { cloned.insert(key.clone_in(allocator), value.clone_in(allocator)); } @@ -231,7 +238,7 @@ where } fn clone_in_with_semantic_ids(&self, allocator: &'new_alloc Allocator) -> Self::Cloned { - let mut cloned = HashMap::with_capacity_in(self.len(), allocator); + let mut cloned = HashMapImpl::with_capacity_in(self.len(), allocator); for (key, value) in self { cloned.insert( key.clone_in_with_semantic_ids(allocator), @@ -281,7 +288,8 @@ impl_clone_in! { #[cfg(test)] mod test { - use super::{Allocator, CloneIn, HashMap, Vec}; + use super::{Allocator, CloneIn, Vec}; + use crate::HashMap; #[test] fn clone_in_boxed_slice() { diff --git a/crates/oxc_allocator/src/hash_map.rs b/crates/oxc_allocator/src/hash_map.rs index 06dac053acd6f..251c292c0ee89 100644 --- a/crates/oxc_allocator/src/hash_map.rs +++ b/crates/oxc_allocator/src/hash_map.rs @@ -8,13 +8,12 @@ #![expect(clippy::inline_always)] use std::{ - hash::Hash, + hash::{BuildHasher, Hash}, mem::ManuallyDrop, ops::{Deref, DerefMut}, }; use bumpalo::Bump; -use rustc_hash::FxBuildHasher; // Re-export additional types from `hashbrown` pub use hashbrown::{ @@ -27,7 +26,7 @@ pub use hashbrown::{ use crate::Allocator; -type FxHashMap<'alloc, K, V> = hashbrown::HashMap; +type InternalHashMap<'alloc, K, V, H> = hashbrown::HashMap; /// A hash map without `Drop`, that uses [`FxHasher`] to hash keys, and stores data in arena allocator. /// @@ -49,7 +48,26 @@ type FxHashMap<'alloc, K, V> = hashbrown::HashMap(pub(crate) ManuallyDrop>); +pub struct HashMapImpl<'alloc, K, V, H: BuildHasher>( + pub(crate) ManuallyDrop>, +); + +// Workaround for `FxBuildHasher` not implementing `Debug`. +#[derive(Default, Debug)] +#[expect(missing_docs)] // TODO +pub struct FxBuildHasher; + +impl BuildHasher for FxBuildHasher { + type Hasher = rustc_hash::FxHasher; + + #[inline(always)] + fn build_hasher(&self) -> Self::Hasher { + rustc_hash::FxHasher::default() + } +} + +#[expect(missing_docs)] // TODO +pub type HashMap<'alloc, K, V> = HashMapImpl<'alloc, K, V, FxBuildHasher>; /// SAFETY: Even though `Bump` is not `Sync`, we can make `HashMap` `Sync` if both `K` and `V` /// are `Sync` because: @@ -85,12 +103,12 @@ pub struct HashMap<'alloc, K, V>(pub(crate) ManuallyDrop /// /// TODO: Fix these holes. /// TODO: Remove any other methods that currently allow performing allocations with only a `&self` reference. -unsafe impl Sync for HashMap<'_, K, V> {} +unsafe impl Sync for HashMapImpl<'_, K, V, H> {} // TODO: `IntoIter`, `Drain`, and other consuming iterators provided by `hashbrown` are `Drop`. // Wrap them in `ManuallyDrop` to prevent that. -impl<'alloc, K, V> HashMap<'alloc, K, V> { +impl<'alloc, K, V, H: BuildHasher + Default> HashMapImpl<'alloc, K, V, H> { /// Const assertions that `K` and `V` are not `Drop`. /// Must be referenced in all methods which create a `HashMap`. const ASSERT_K_AND_V_ARE_NOT_DROP: () = { @@ -112,7 +130,7 @@ impl<'alloc, K, V> HashMap<'alloc, K, V> { pub fn new_in(allocator: &'alloc Allocator) -> Self { const { Self::ASSERT_K_AND_V_ARE_NOT_DROP }; - let inner = FxHashMap::with_hasher_in(FxBuildHasher, allocator.bump()); + let inner = InternalHashMap::with_hasher_in(H::default(), allocator.bump()); Self(ManuallyDrop::new(inner)) } @@ -125,7 +143,7 @@ impl<'alloc, K, V> HashMap<'alloc, K, V> { const { Self::ASSERT_K_AND_V_ARE_NOT_DROP }; let inner = - FxHashMap::with_capacity_and_hasher_in(capacity, FxBuildHasher, allocator.bump()); + InternalHashMap::with_capacity_and_hasher_in(capacity, H::default(), allocator.bump()); Self(ManuallyDrop::new(inner)) } @@ -153,7 +171,8 @@ impl<'alloc, K, V> HashMap<'alloc, K, V> { // * Positive: Avoids potential large over-allocation for iterators where upper bound may be a large over-estimate // e.g. filter iterators. let capacity = iter.size_hint().0; - let map = FxHashMap::with_capacity_and_hasher_in(capacity, FxBuildHasher, allocator.bump()); + let map = + InternalHashMap::with_capacity_and_hasher_in(capacity, H::default(), allocator.bump()); // Wrap in `ManuallyDrop` *before* calling `for_each`, so compiler doesn't insert unnecessary code // to drop the `FxHashMap` in case of a panic in iterator's `next` method let mut map = ManuallyDrop::new(map); @@ -202,8 +221,8 @@ impl<'alloc, K, V> HashMap<'alloc, K, V> { } // Provide access to all `hashbrown::HashMap`'s methods via deref -impl<'alloc, K, V> Deref for HashMap<'alloc, K, V> { - type Target = FxHashMap<'alloc, K, V>; +impl<'alloc, K, V, H: BuildHasher> Deref for HashMapImpl<'alloc, K, V, H> { + type Target = InternalHashMap<'alloc, K, V, H>; #[inline] fn deref(&self) -> &Self::Target { @@ -211,14 +230,14 @@ impl<'alloc, K, V> Deref for HashMap<'alloc, K, V> { } } -impl<'alloc, K, V> DerefMut for HashMap<'alloc, K, V> { +impl<'alloc, K, V, H: BuildHasher> DerefMut for HashMapImpl<'alloc, K, V, H> { #[inline] - fn deref_mut(&mut self) -> &mut FxHashMap<'alloc, K, V> { + fn deref_mut(&mut self) -> &mut InternalHashMap<'alloc, K, V, H> { &mut self.0 } } -impl<'alloc, K, V> IntoIterator for HashMap<'alloc, K, V> { +impl<'alloc, K, V, H: BuildHasher> IntoIterator for HashMapImpl<'alloc, K, V, H> { type IntoIter = IntoIter; type Item = (K, V); @@ -235,8 +254,8 @@ impl<'alloc, K, V> IntoIterator for HashMap<'alloc, K, V> { } } -impl<'alloc, 'i, K, V> IntoIterator for &'i HashMap<'alloc, K, V> { - type IntoIter = <&'i FxHashMap<'alloc, K, V> as IntoIterator>::IntoIter; +impl<'alloc, 'i, K, V, H: BuildHasher> IntoIterator for &'i HashMapImpl<'alloc, K, V, H> { + type IntoIter = <&'i InternalHashMap<'alloc, K, V, H> as IntoIterator>::IntoIter; type Item = (&'i K, &'i V); /// Creates an iterator over the entries of a `HashMap` in arbitrary order. @@ -250,8 +269,8 @@ impl<'alloc, 'i, K, V> IntoIterator for &'i HashMap<'alloc, K, V> { } } -impl<'alloc, 'i, K, V> IntoIterator for &'i mut HashMap<'alloc, K, V> { - type IntoIter = <&'i mut FxHashMap<'alloc, K, V> as IntoIterator>::IntoIter; +impl<'alloc, 'i, K, V, H: BuildHasher> IntoIterator for &'i mut HashMapImpl<'alloc, K, V, H> { + type IntoIter = <&'i mut InternalHashMap<'alloc, K, V, H> as IntoIterator>::IntoIter; type Item = (&'i K, &'i mut V); /// Creates an iterator over the entries of a `HashMap` in arbitrary order @@ -266,10 +285,11 @@ impl<'alloc, 'i, K, V> IntoIterator for &'i mut HashMap<'alloc, K, V> { } } -impl PartialEq for HashMap<'_, K, V> +impl PartialEq for HashMapImpl<'_, K, V, H> where K: Eq + Hash, V: PartialEq, + H: BuildHasher, { #[inline(always)] fn eq(&self, other: &Self) -> bool { @@ -277,10 +297,11 @@ where } } -impl Eq for HashMap<'_, K, V> +impl Eq for HashMapImpl<'_, K, V, H> where K: Eq + Hash, V: Eq, + H: BuildHasher, { } diff --git a/crates/oxc_allocator/src/hash_set.rs b/crates/oxc_allocator/src/hash_set.rs index 4b0721ac5174f..f14e744535d00 100644 --- a/crates/oxc_allocator/src/hash_set.rs +++ b/crates/oxc_allocator/src/hash_set.rs @@ -14,14 +14,13 @@ use std::{ }; use bumpalo::Bump; -use rustc_hash::FxBuildHasher; // Re-export additional types from `hashbrown` pub use hashbrown::hash_set::{ Difference, Drain, Entry, ExtractIf, Intersection, IntoIter, Iter, SymmetricDifference, Union, }; -use crate::{Allocator, HashMap}; +use crate::{Allocator, HashMap, hash_map::FxBuildHasher}; type FxHashSet<'alloc, T> = hashbrown::HashSet; diff --git a/crates/oxc_allocator/src/lib.rs b/crates/oxc_allocator/src/lib.rs index 5ca3a798db4a9..7c6fdd3ef58ad 100644 --- a/crates/oxc_allocator/src/lib.rs +++ b/crates/oxc_allocator/src/lib.rs @@ -69,7 +69,7 @@ pub use bitset::BitSet; pub use boxed::Box; pub use clone_in::CloneIn; pub use convert::{FromIn, IntoIn}; -pub use hash_map::HashMap; +pub use hash_map::{FxBuildHasher, HashMap, HashMapImpl}; pub use hash_set::HashSet; #[cfg(feature = "pool")] pub use pool::*; diff --git a/crates/oxc_ast/src/ast/js.rs b/crates/oxc_ast/src/ast/js.rs index 2fcac614cfb66..c43e806fc2488 100644 --- a/crates/oxc_ast/src/ast/js.rs +++ b/crates/oxc_ast/src/ast/js.rs @@ -25,7 +25,7 @@ use std::cell::Cell; use oxc_allocator::{Box, CloneIn, Dummy, GetAddress, TakeIn, UnstableAddress, Vec}; use oxc_ast_macros::ast; use oxc_estree::ESTree; -use oxc_span::{Atom, ContentEq, GetSpan, GetSpanMut, SourceType, Span}; +use oxc_span::{Atom, ContentEq, GetSpan, GetSpanMut, Ident, SourceType, Span}; use oxc_syntax::{ operator::{ AssignmentOperator, BinaryOperator, LogicalOperator, UnaryOperator, UpdateOperator, @@ -234,7 +234,7 @@ pub use match_expression; pub struct IdentifierName<'a> { pub span: Span, #[estree(json_safe)] - pub name: Atom<'a>, + pub name: Ident<'a>, } /// `x` inside `func` in `const x = 0; function func() { console.log(x); }` @@ -253,8 +253,9 @@ pub struct IdentifierName<'a> { pub struct IdentifierReference<'a> { pub span: Span, /// The name of the identifier being referenced. + // pub name: Atom<'a>, #[estree(json_safe)] - pub name: Atom<'a>, + pub name: Ident<'a>, /// Reference ID /// /// Identifies what identifier this refers to, and how it is used. This is @@ -283,7 +284,7 @@ pub struct BindingIdentifier<'a> { pub span: Span, /// The identifier name being bound. #[estree(json_safe)] - pub name: Atom<'a>, + pub name: Ident<'a>, /// Unique identifier for this binding. /// /// This gets initialized during [`semantic analysis`] in the bind step. If @@ -309,7 +310,7 @@ pub struct BindingIdentifier<'a> { pub struct LabelIdentifier<'a> { pub span: Span, #[estree(json_safe)] - pub name: Atom<'a>, + pub name: Ident<'a>, } /// `this` in `return this.prop;` @@ -2285,7 +2286,7 @@ pub enum MethodDefinitionKind { #[generate_derive(CloneIn, Dummy, TakeIn, GetSpan, GetSpanMut, ContentEq, ESTree, UnstableAddress)] pub struct PrivateIdentifier<'a> { pub span: Span, - pub name: Atom<'a>, + pub name: Ident<'a>, } /// Class Static Block diff --git a/crates/oxc_ast/src/ast/jsx.rs b/crates/oxc_ast/src/ast/jsx.rs index b5109a2c66476..1fbe5c99af1f3 100644 --- a/crates/oxc_ast/src/ast/jsx.rs +++ b/crates/oxc_ast/src/ast/jsx.rs @@ -7,7 +7,7 @@ use oxc_allocator::{Box, CloneIn, Dummy, GetAddress, TakeIn, UnstableAddress, Vec}; use oxc_ast_macros::ast; use oxc_estree::ESTree; -use oxc_span::{Atom, ContentEq, GetSpan, GetSpanMut, Span}; +use oxc_span::{Atom, ContentEq, GetSpan, GetSpanMut, Ident, Span}; use super::{inherit_variants, js::*, literal::*, ts::*}; @@ -424,7 +424,7 @@ pub struct JSXIdentifier<'a> { pub span: Span, /// The name of the identifier. #[estree(json_safe)] - pub name: Atom<'a>, + pub name: Ident<'a>, } // 1.4 JSX Children diff --git a/crates/oxc_ast/src/ast_builder_impl.rs b/crates/oxc_ast/src/ast_builder_impl.rs index 738367f02b195..00c738fac8f96 100644 --- a/crates/oxc_ast/src/ast_builder_impl.rs +++ b/crates/oxc_ast/src/ast_builder_impl.rs @@ -3,7 +3,7 @@ use std::borrow::Cow; use oxc_allocator::{Allocator, AllocatorAccessor, Box, FromIn, IntoIn, Vec}; -use oxc_span::{Atom, SPAN, Span}; +use oxc_span::{Atom, Ident, SPAN, Span}; use oxc_syntax::{ comment_node::CommentNodeId, number::NumberBase, operator::UnaryOperator, scope::ScopeId, }; @@ -98,6 +98,18 @@ impl<'a> AstBuilder<'a> { self.allocator.alloc_str(value) } + /// Allocate an [`Ident`] from a string slice. + #[inline] + pub fn ident(self, value: &str) -> Ident<'a> { + Ident::from_in(value, self.allocator) + } + + /// Allocate an [`Ident`] from an array of string slices. + #[inline] + pub fn ident_from_strs_array(self, strings: [&str; N]) -> Ident<'a> { + Ident::from_strs_array_in(strings, self.allocator) + } + /// Allocate an [`Atom`] from a string slice. #[inline] pub fn atom(self, value: &str) -> Atom<'a> { diff --git a/crates/oxc_ast/src/ast_impl/js.rs b/crates/oxc_ast/src/ast_impl/js.rs index 1a9d1d3f5e0ea..a1b03a673d785 100644 --- a/crates/oxc_ast/src/ast_impl/js.rs +++ b/crates/oxc_ast/src/ast_impl/js.rs @@ -4,7 +4,7 @@ use std::{ fmt::{self, Display}, }; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{Atom, GetSpan, Ident, Span}; use oxc_syntax::{operator::UnaryOperator, scope::ScopeFlags}; use crate::ast::*; @@ -504,7 +504,7 @@ impl<'a> PropertyKey<'a> { /// - `a: 1` in `{ a: 1 }` would return `None` pub fn private_name(&self) -> Option> { match self { - Self::PrivateIdentifier(ident) => Some(ident.name), + Self::PrivateIdentifier(ident) => Some(ident.name.as_atom()), _ => None, } } @@ -1259,7 +1259,7 @@ impl<'a> BindingPattern<'a> { /// - calling on `a = 1` in `let a = 1` would return `Some("a")` /// - calling on `a = 1` in `let {a = 1} = c` would return `Some("a")` /// - calling on `a: b` in `let {a: b} = c` would return `None` - pub fn get_identifier_name(&self) -> Option> { + pub fn get_identifier_name(&self) -> Option> { self.kind.get_identifier_name() } @@ -1296,7 +1296,7 @@ impl<'a> BindingPatternKind<'a> { /// - calling on `a = 1` in `let a = 1` would return `Some("a")` /// - calling on `a = 1` in `let {a = 1} = c` would return `Some("a")` /// - calling on `a: b` in `let {a: b} = c` would return `None` - pub fn get_identifier_name(&self) -> Option> { + pub fn get_identifier_name(&self) -> Option> { match self { Self::BindingIdentifier(ident) => Some(ident.name), Self::AssignmentPattern(assign) => assign.left.get_identifier_name(), @@ -1426,7 +1426,7 @@ impl ArrayPattern<'_> { impl<'a> Function<'a> { /// Returns this [`Function`]'s name, if it has one. #[inline] - pub fn name(&self) -> Option> { + pub fn name(&self) -> Option> { self.id.as_ref().map(|id| id.name) } @@ -1582,7 +1582,7 @@ impl<'a> ArrowFunctionExpression<'a> { impl<'a> Class<'a> { /// Returns this [`Class`]'s name, if it has one. #[inline] - pub fn name(&self) -> Option> { + pub fn name(&self) -> Option> { self.id.as_ref().map(|id| id.name) } @@ -1929,7 +1929,7 @@ impl<'a> ImportAttributeKey<'a> { /// Returns the string value of this import attribute key. pub fn as_atom(&self) -> Atom<'a> { match self { - Self::Identifier(identifier) => identifier.name, + Self::Identifier(identifier) => identifier.name.as_atom(), Self::StringLiteral(literal) => literal.value, } } @@ -1988,11 +1988,11 @@ impl<'a> ModuleExportName<'a> { /// - `export { foo }` => `"foo"` /// - `export { foo as bar }` => `"bar"` /// - `export { foo as "anything" }` => `"anything"` - pub fn name(&self) -> Atom<'a> { + pub fn name(&self) -> Ident<'a> { match self { Self::IdentifierName(identifier) => identifier.name, Self::IdentifierReference(identifier) => identifier.name, - Self::StringLiteral(literal) => literal.value, + Self::StringLiteral(literal) => Ident::from(literal.value), } } @@ -2003,7 +2003,7 @@ impl<'a> ModuleExportName<'a> { /// - `export { foo }` => `Some("foo")` /// - `export { foo as bar }` => `Some("bar")` /// - `export { foo as "anything" }` => `None` - pub fn identifier_name(&self) -> Option> { + pub fn identifier_name(&self) -> Option> { match self { Self::IdentifierName(identifier) => Some(identifier.name), Self::IdentifierReference(identifier) => Some(identifier.name), diff --git a/crates/oxc_ast/src/ast_impl/jsx.rs b/crates/oxc_ast/src/ast_impl/jsx.rs index adfa1e7b8e73f..85b2483ef9d9f 100644 --- a/crates/oxc_ast/src/ast_impl/jsx.rs +++ b/crates/oxc_ast/src/ast_impl/jsx.rs @@ -2,7 +2,7 @@ use std::fmt::{self, Display}; -use oxc_span::Atom; +use oxc_span::Ident; use crate::ast::*; @@ -50,7 +50,7 @@ impl<'a> JSXElementName<'a> { /// * `` /// * `` /// * `` - [namespaced identifiers](JSXElementName::NamespacedName) - pub fn get_identifier_name(&self) -> Option> { + pub fn get_identifier_name(&self) -> Option> { match self { Self::Identifier(id) => Some(id.as_ref().name), Self::IdentifierReference(id) => Some(id.as_ref().name), diff --git a/crates/oxc_ast/src/ast_impl/ts.rs b/crates/oxc_ast/src/ast_impl/ts.rs index 7ced1cd1a6310..91f5b4652c405 100644 --- a/crates/oxc_ast/src/ast_impl/ts.rs +++ b/crates/oxc_ast/src/ast_impl/ts.rs @@ -6,7 +6,7 @@ use std::fmt; -use oxc_span::Atom; +use oxc_span::{Atom, Ident}; use crate::ast::*; @@ -14,13 +14,13 @@ impl<'a> TSEnumMemberName<'a> { /// Get the name of this enum member. /// # Panics /// Panics if `self` is a `TemplateString` with no quasi. - pub fn static_name(&self) -> Atom<'a> { + pub fn static_name(&self) -> Ident<'a> { match self { Self::Identifier(ident) => ident.name, - Self::String(lit) | Self::ComputedString(lit) => lit.value, - Self::ComputedTemplateString(template) => template + Self::String(lit) | Self::ComputedString(lit) => Ident::from(lit.value), + Self::ComputedTemplateString(template) => Ident::from(template .single_quasi() - .expect("`TSEnumMemberName::TemplateString` should have no substitution and at least one quasi"), + .expect("`TSEnumMemberName::TemplateString` should have no substitution and at least one quasi")), } } } @@ -218,7 +218,7 @@ impl<'a> TSModuleDeclarationName<'a> { /// Get the static name of this module declaration name. pub fn name(&self) -> Atom<'a> { match self { - Self::Identifier(ident) => ident.name, + Self::Identifier(ident) => ident.name.as_atom(), Self::StringLiteral(lit) => lit.value, } } diff --git a/crates/oxc_ast/src/ast_kind_impl.rs b/crates/oxc_ast/src/ast_kind_impl.rs index 1057eaed7ab73..3a9a652ed9158 100644 --- a/crates/oxc_ast/src/ast_kind_impl.rs +++ b/crates/oxc_ast/src/ast_kind_impl.rs @@ -4,7 +4,7 @@ //! including type checking, conversions, and tree traversal helpers. use oxc_allocator::{Address, GetAddress, UnstableAddress}; -use oxc_span::{Atom, GetSpan}; +use oxc_span::{Atom, GetSpan, Ident}; use super::{AstKind, ast::*}; @@ -174,7 +174,7 @@ impl<'a> AstKind<'a> { /// /// Returns the identifier name if this is any kind of identifier node, /// `None` otherwise. - pub fn identifier_name(self) -> Option> { + pub fn identifier_name(self) -> Option> { match self { Self::BindingIdentifier(ident) => Some(ident.name), Self::IdentifierReference(ident) => Some(ident.name), @@ -392,7 +392,7 @@ impl AstKind<'_> { Self::VariableDeclaration(_) => "VariableDeclaration".into(), Self::VariableDeclarator(v) => format!( "VariableDeclarator({})", - v.id.get_identifier_name().unwrap_or(Atom::from(DESTRUCTURE.as_ref())) + v.id.get_identifier_name().unwrap_or(Ident::from(DESTRUCTURE.as_ref())) ) .into(), @@ -474,7 +474,7 @@ impl AstKind<'_> { Self::FormalParameters(_) => "FormalParameters".into(), Self::FormalParameter(p) => format!( "FormalParameter({})", - p.pattern.get_identifier_name().unwrap_or(Atom::from(DESTRUCTURE.as_ref())) + p.pattern.get_identifier_name().unwrap_or(Ident::from(DESTRUCTURE.as_ref())) ) .into(), Self::CatchParameter(_) => "CatchParameter".into(), @@ -628,7 +628,7 @@ impl<'a> MemberExpressionKind<'a> { pub fn static_property_name(&self) -> Option> { match self { Self::Computed(member_expr) => member_expr.static_property_name(), - Self::Static(member_expr) => Some(member_expr.property.name), + Self::Static(member_expr) => Some(member_expr.property.name.as_atom()), Self::PrivateField(_) => None, } } diff --git a/crates/oxc_ast/src/generated/ast_builder.rs b/crates/oxc_ast/src/generated/ast_builder.rs index 3a4a1c090aea8..b930cdffc8d30 100644 --- a/crates/oxc_ast/src/generated/ast_builder.rs +++ b/crates/oxc_ast/src/generated/ast_builder.rs @@ -13,6 +13,7 @@ use std::cell::Cell; use oxc_allocator::{Allocator, Box, IntoIn, Vec}; +use oxc_span::Ident; use oxc_syntax::{ comment_node::CommentNodeId, reference::ReferenceId, scope::ScopeId, symbol::SymbolId, }; @@ -247,10 +248,7 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The name of the identifier being referenced. #[inline] - pub fn expression_identifier(self, span: Span, name: A1) -> Expression<'a> - where - A1: Into>, - { + pub fn expression_identifier(self, span: Span, name: Ident<'a>) -> Expression<'a> { Expression::Identifier(self.alloc_identifier_reference(span, name)) } @@ -263,15 +261,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The name of the identifier being referenced. /// * `reference_id`: Reference ID #[inline] - pub fn expression_identifier_with_reference_id( + pub fn expression_identifier_with_reference_id( self, span: Span, - name: A1, + name: Ident<'a>, reference_id: ReferenceId, - ) -> Expression<'a> - where - A1: Into>, - { + ) -> Expression<'a> { Expression::Identifier(self.alloc_identifier_reference_with_reference_id( span, name, @@ -1226,11 +1221,8 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn identifier_name(self, span: Span, name: A1) -> IdentifierName<'a> - where - A1: Into>, - { - IdentifierName { span, name: name.into() } + pub fn identifier_name(self, span: Span, name: Ident<'a>) -> IdentifierName<'a> { + IdentifierName { span, name } } /// Build an [`IdentifierName`], and store it in the memory arena. @@ -1242,10 +1234,7 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn alloc_identifier_name(self, span: Span, name: A1) -> Box<'a, IdentifierName<'a>> - where - A1: Into>, - { + pub fn alloc_identifier_name(self, span: Span, name: Ident<'a>) -> Box<'a, IdentifierName<'a>> { Box::new_in(self.identifier_name(span, name), self.allocator) } @@ -1258,11 +1247,8 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The name of the identifier being referenced. #[inline] - pub fn identifier_reference(self, span: Span, name: A1) -> IdentifierReference<'a> - where - A1: Into>, - { - IdentifierReference { span, name: name.into(), reference_id: Default::default() } + pub fn identifier_reference(self, span: Span, name: Ident<'a>) -> IdentifierReference<'a> { + IdentifierReference { span, name, reference_id: Default::default() } } /// Build an [`IdentifierReference`], and store it in the memory arena. @@ -1274,14 +1260,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The name of the identifier being referenced. #[inline] - pub fn alloc_identifier_reference( + pub fn alloc_identifier_reference( self, span: Span, - name: A1, - ) -> Box<'a, IdentifierReference<'a>> - where - A1: Into>, - { + name: Ident<'a>, + ) -> Box<'a, IdentifierReference<'a>> { Box::new_in(self.identifier_reference(span, name), self.allocator) } @@ -1295,16 +1278,13 @@ impl<'a> AstBuilder<'a> { /// * `name`: The name of the identifier being referenced. /// * `reference_id`: Reference ID #[inline] - pub fn identifier_reference_with_reference_id( + pub fn identifier_reference_with_reference_id( self, span: Span, - name: A1, + name: Ident<'a>, reference_id: ReferenceId, - ) -> IdentifierReference<'a> - where - A1: Into>, - { - IdentifierReference { span, name: name.into(), reference_id: Cell::new(Some(reference_id)) } + ) -> IdentifierReference<'a> { + IdentifierReference { span, name, reference_id: Cell::new(Some(reference_id)) } } /// Build an [`IdentifierReference`] with `reference_id`, and store it in the memory arena. @@ -1317,15 +1297,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The name of the identifier being referenced. /// * `reference_id`: Reference ID #[inline] - pub fn alloc_identifier_reference_with_reference_id( + pub fn alloc_identifier_reference_with_reference_id( self, span: Span, - name: A1, + name: Ident<'a>, reference_id: ReferenceId, - ) -> Box<'a, IdentifierReference<'a>> - where - A1: Into>, - { + ) -> Box<'a, IdentifierReference<'a>> { Box::new_in( self.identifier_reference_with_reference_id(span, name, reference_id), self.allocator, @@ -1341,11 +1318,8 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The identifier name being bound. #[inline] - pub fn binding_identifier(self, span: Span, name: A1) -> BindingIdentifier<'a> - where - A1: Into>, - { - BindingIdentifier { span, name: name.into(), symbol_id: Default::default() } + pub fn binding_identifier(self, span: Span, name: Ident<'a>) -> BindingIdentifier<'a> { + BindingIdentifier { span, name, symbol_id: Default::default() } } /// Build a [`BindingIdentifier`], and store it in the memory arena. @@ -1357,14 +1331,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The identifier name being bound. #[inline] - pub fn alloc_binding_identifier( + pub fn alloc_binding_identifier( self, span: Span, - name: A1, - ) -> Box<'a, BindingIdentifier<'a>> - where - A1: Into>, - { + name: Ident<'a>, + ) -> Box<'a, BindingIdentifier<'a>> { Box::new_in(self.binding_identifier(span, name), self.allocator) } @@ -1378,16 +1349,13 @@ impl<'a> AstBuilder<'a> { /// * `name`: The identifier name being bound. /// * `symbol_id`: Unique identifier for this binding. #[inline] - pub fn binding_identifier_with_symbol_id( + pub fn binding_identifier_with_symbol_id( self, span: Span, - name: A1, + name: Ident<'a>, symbol_id: SymbolId, - ) -> BindingIdentifier<'a> - where - A1: Into>, - { - BindingIdentifier { span, name: name.into(), symbol_id: Cell::new(Some(symbol_id)) } + ) -> BindingIdentifier<'a> { + BindingIdentifier { span, name, symbol_id: Cell::new(Some(symbol_id)) } } /// Build a [`BindingIdentifier`] with `symbol_id`, and store it in the memory arena. @@ -1400,15 +1368,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The identifier name being bound. /// * `symbol_id`: Unique identifier for this binding. #[inline] - pub fn alloc_binding_identifier_with_symbol_id( + pub fn alloc_binding_identifier_with_symbol_id( self, span: Span, - name: A1, + name: Ident<'a>, symbol_id: SymbolId, - ) -> Box<'a, BindingIdentifier<'a>> - where - A1: Into>, - { + ) -> Box<'a, BindingIdentifier<'a>> { Box::new_in(self.binding_identifier_with_symbol_id(span, name, symbol_id), self.allocator) } @@ -1418,11 +1383,8 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn label_identifier(self, span: Span, name: A1) -> LabelIdentifier<'a> - where - A1: Into>, - { - LabelIdentifier { span, name: name.into() } + pub fn label_identifier(self, span: Span, name: Ident<'a>) -> LabelIdentifier<'a> { + LabelIdentifier { span, name } } /// Build a [`ThisExpression`]. @@ -1660,10 +1622,7 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn property_key_static_identifier(self, span: Span, name: A1) -> PropertyKey<'a> - where - A1: Into>, - { + pub fn property_key_static_identifier(self, span: Span, name: Ident<'a>) -> PropertyKey<'a> { PropertyKey::StaticIdentifier(self.alloc_identifier_name(span, name)) } @@ -1675,10 +1634,7 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn property_key_private_identifier(self, span: Span, name: A1) -> PropertyKey<'a> - where - A1: Into>, - { + pub fn property_key_private_identifier(self, span: Span, name: Ident<'a>) -> PropertyKey<'a> { PropertyKey::PrivateIdentifier(self.alloc_private_identifier(span, name)) } @@ -2622,14 +2578,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The name of the identifier being referenced. #[inline] - pub fn simple_assignment_target_assignment_target_identifier( + pub fn simple_assignment_target_assignment_target_identifier( self, span: Span, - name: A1, - ) -> SimpleAssignmentTarget<'a> - where - A1: Into>, - { + name: Ident<'a>, + ) -> SimpleAssignmentTarget<'a> { SimpleAssignmentTarget::AssignmentTargetIdentifier( self.alloc_identifier_reference(span, name), ) @@ -2644,15 +2597,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The name of the identifier being referenced. /// * `reference_id`: Reference ID #[inline] - pub fn simple_assignment_target_assignment_target_identifier_with_reference_id( + pub fn simple_assignment_target_assignment_target_identifier_with_reference_id( self, span: Span, - name: A1, + name: Ident<'a>, reference_id: ReferenceId, - ) -> SimpleAssignmentTarget<'a> - where - A1: Into>, - { + ) -> SimpleAssignmentTarget<'a> { SimpleAssignmentTarget::AssignmentTargetIdentifier( self.alloc_identifier_reference_with_reference_id(span, name, reference_id), ) @@ -5573,14 +5523,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The identifier name being bound. #[inline] - pub fn binding_pattern_kind_binding_identifier( + pub fn binding_pattern_kind_binding_identifier( self, span: Span, - name: A1, - ) -> BindingPatternKind<'a> - where - A1: Into>, - { + name: Ident<'a>, + ) -> BindingPatternKind<'a> { BindingPatternKind::BindingIdentifier(self.alloc_binding_identifier(span, name)) } @@ -5593,15 +5540,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The identifier name being bound. /// * `symbol_id`: Unique identifier for this binding. #[inline] - pub fn binding_pattern_kind_binding_identifier_with_symbol_id( + pub fn binding_pattern_kind_binding_identifier_with_symbol_id( self, span: Span, - name: A1, + name: Ident<'a>, symbol_id: SymbolId, - ) -> BindingPatternKind<'a> - where - A1: Into>, - { + ) -> BindingPatternKind<'a> { BindingPatternKind::BindingIdentifier( self.alloc_binding_identifier_with_symbol_id(span, name, symbol_id), ) @@ -7132,11 +7076,8 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn private_identifier(self, span: Span, name: A1) -> PrivateIdentifier<'a> - where - A1: Into>, - { - PrivateIdentifier { span, name: name.into() } + pub fn private_identifier(self, span: Span, name: Ident<'a>) -> PrivateIdentifier<'a> { + PrivateIdentifier { span, name } } /// Build a [`PrivateIdentifier`], and store it in the memory arena. @@ -7148,14 +7089,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn alloc_private_identifier( + pub fn alloc_private_identifier( self, span: Span, - name: A1, - ) -> Box<'a, PrivateIdentifier<'a>> - where - A1: Into>, - { + name: Ident<'a>, + ) -> Box<'a, PrivateIdentifier<'a>> { Box::new_in(self.private_identifier(span, name), self.allocator) } @@ -7820,10 +7758,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn import_attribute_key_identifier(self, span: Span, name: A1) -> ImportAttributeKey<'a> - where - A1: Into>, - { + pub fn import_attribute_key_identifier( + self, + span: Span, + name: Ident<'a>, + ) -> ImportAttributeKey<'a> { ImportAttributeKey::Identifier(self.identifier_name(span, name)) } @@ -8367,14 +8306,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn module_export_name_identifier_name( + pub fn module_export_name_identifier_name( self, span: Span, - name: A1, - ) -> ModuleExportName<'a> - where - A1: Into>, - { + name: Ident<'a>, + ) -> ModuleExportName<'a> { ModuleExportName::IdentifierName(self.identifier_name(span, name)) } @@ -8384,14 +8320,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The name of the identifier being referenced. #[inline] - pub fn module_export_name_identifier_reference( + pub fn module_export_name_identifier_reference( self, span: Span, - name: A1, - ) -> ModuleExportName<'a> - where - A1: Into>, - { + name: Ident<'a>, + ) -> ModuleExportName<'a> { ModuleExportName::IdentifierReference(self.identifier_reference(span, name)) } @@ -8402,15 +8335,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The name of the identifier being referenced. /// * `reference_id`: Reference ID #[inline] - pub fn module_export_name_identifier_reference_with_reference_id( + pub fn module_export_name_identifier_reference_with_reference_id( self, span: Span, - name: A1, + name: Ident<'a>, reference_id: ReferenceId, - ) -> ModuleExportName<'a> - where - A1: Into>, - { + ) -> ModuleExportName<'a> { ModuleExportName::IdentifierReference(self.identifier_reference_with_reference_id( span, name, @@ -8993,10 +8923,7 @@ impl<'a> AstBuilder<'a> { /// * `span`: Node location in source code /// * `name`: The name of the identifier. #[inline] - pub fn jsx_element_name_identifier(self, span: Span, name: A1) -> JSXElementName<'a> - where - A1: Into>, - { + pub fn jsx_element_name_identifier(self, span: Span, name: Ident<'a>) -> JSXElementName<'a> { JSXElementName::Identifier(self.alloc_jsx_identifier(span, name)) } @@ -9008,14 +8935,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The name of the identifier being referenced. #[inline] - pub fn jsx_element_name_identifier_reference( + pub fn jsx_element_name_identifier_reference( self, span: Span, - name: A1, - ) -> JSXElementName<'a> - where - A1: Into>, - { + name: Ident<'a>, + ) -> JSXElementName<'a> { JSXElementName::IdentifierReference(self.alloc_identifier_reference(span, name)) } @@ -9028,15 +8952,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The name of the identifier being referenced. /// * `reference_id`: Reference ID #[inline] - pub fn jsx_element_name_identifier_reference_with_reference_id( + pub fn jsx_element_name_identifier_reference_with_reference_id( self, span: Span, - name: A1, + name: Ident<'a>, reference_id: ReferenceId, - ) -> JSXElementName<'a> - where - A1: Into>, - { + ) -> JSXElementName<'a> { JSXElementName::IdentifierReference(self.alloc_identifier_reference_with_reference_id( span, name, @@ -9175,14 +9096,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The name of the identifier being referenced. #[inline] - pub fn jsx_member_expression_object_identifier_reference( + pub fn jsx_member_expression_object_identifier_reference( self, span: Span, - name: A1, - ) -> JSXMemberExpressionObject<'a> - where - A1: Into>, - { + name: Ident<'a>, + ) -> JSXMemberExpressionObject<'a> { JSXMemberExpressionObject::IdentifierReference(self.alloc_identifier_reference(span, name)) } @@ -9195,15 +9113,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The name of the identifier being referenced. /// * `reference_id`: Reference ID #[inline] - pub fn jsx_member_expression_object_identifier_reference_with_reference_id( + pub fn jsx_member_expression_object_identifier_reference_with_reference_id( self, span: Span, - name: A1, + name: Ident<'a>, reference_id: ReferenceId, - ) -> JSXMemberExpressionObject<'a> - where - A1: Into>, - { + ) -> JSXMemberExpressionObject<'a> { JSXMemberExpressionObject::IdentifierReference( self.alloc_identifier_reference_with_reference_id(span, name, reference_id), ) @@ -9409,10 +9324,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: Node location in source code /// * `name`: The name of the identifier. #[inline] - pub fn jsx_attribute_name_identifier(self, span: Span, name: A1) -> JSXAttributeName<'a> - where - A1: Into>, - { + pub fn jsx_attribute_name_identifier( + self, + span: Span, + name: Ident<'a>, + ) -> JSXAttributeName<'a> { JSXAttributeName::Identifier(self.alloc_jsx_identifier(span, name)) } @@ -9564,11 +9480,8 @@ impl<'a> AstBuilder<'a> { /// * `span`: Node location in source code /// * `name`: The name of the identifier. #[inline] - pub fn jsx_identifier(self, span: Span, name: A1) -> JSXIdentifier<'a> - where - A1: Into>, - { - JSXIdentifier { span, name: name.into() } + pub fn jsx_identifier(self, span: Span, name: Ident<'a>) -> JSXIdentifier<'a> { + JSXIdentifier { span, name } } /// Build a [`JSXIdentifier`], and store it in the memory arena. @@ -9580,10 +9493,7 @@ impl<'a> AstBuilder<'a> { /// * `span`: Node location in source code /// * `name`: The name of the identifier. #[inline] - pub fn alloc_jsx_identifier(self, span: Span, name: A1) -> Box<'a, JSXIdentifier<'a>> - where - A1: Into>, - { + pub fn alloc_jsx_identifier(self, span: Span, name: Ident<'a>) -> Box<'a, JSXIdentifier<'a>> { Box::new_in(self.jsx_identifier(span, name), self.allocator) } @@ -9930,10 +9840,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn ts_enum_member_name_identifier(self, span: Span, name: A1) -> TSEnumMemberName<'a> - where - A1: Into>, - { + pub fn ts_enum_member_name_identifier( + self, + span: Span, + name: Ident<'a>, + ) -> TSEnumMemberName<'a> { TSEnumMemberName::Identifier(self.alloc_identifier_name(span, name)) } @@ -11907,10 +11818,7 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The name of the identifier being referenced. #[inline] - pub fn ts_type_name_identifier_reference(self, span: Span, name: A1) -> TSTypeName<'a> - where - A1: Into>, - { + pub fn ts_type_name_identifier_reference(self, span: Span, name: Ident<'a>) -> TSTypeName<'a> { TSTypeName::IdentifierReference(self.alloc_identifier_reference(span, name)) } @@ -11923,15 +11831,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The name of the identifier being referenced. /// * `reference_id`: Reference ID #[inline] - pub fn ts_type_name_identifier_reference_with_reference_id( + pub fn ts_type_name_identifier_reference_with_reference_id( self, span: Span, - name: A1, + name: Ident<'a>, reference_id: ReferenceId, - ) -> TSTypeName<'a> - where - A1: Into>, - { + ) -> TSTypeName<'a> { TSTypeName::IdentifierReference(self.alloc_identifier_reference_with_reference_id( span, name, @@ -13495,14 +13400,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn ts_type_predicate_name_identifier( + pub fn ts_type_predicate_name_identifier( self, span: Span, - name: A1, - ) -> TSTypePredicateName<'a> - where - A1: Into>, - { + name: Ident<'a>, + ) -> TSTypePredicateName<'a> { TSTypePredicateName::Identifier(self.alloc_identifier_name(span, name)) } @@ -13620,14 +13522,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name`: The identifier name being bound. #[inline] - pub fn ts_module_declaration_name_identifier( + pub fn ts_module_declaration_name_identifier( self, span: Span, - name: A1, - ) -> TSModuleDeclarationName<'a> - where - A1: Into>, - { + name: Ident<'a>, + ) -> TSModuleDeclarationName<'a> { TSModuleDeclarationName::Identifier(self.binding_identifier(span, name)) } @@ -13638,15 +13537,12 @@ impl<'a> AstBuilder<'a> { /// * `name`: The identifier name being bound. /// * `symbol_id`: Unique identifier for this binding. #[inline] - pub fn ts_module_declaration_name_identifier_with_symbol_id( + pub fn ts_module_declaration_name_identifier_with_symbol_id( self, span: Span, - name: A1, + name: Ident<'a>, symbol_id: SymbolId, - ) -> TSModuleDeclarationName<'a> - where - A1: Into>, - { + ) -> TSModuleDeclarationName<'a> { TSModuleDeclarationName::Identifier( self.binding_identifier_with_symbol_id(span, name, symbol_id), ) @@ -14113,14 +14009,11 @@ impl<'a> AstBuilder<'a> { /// * `span`: The [`Span`] covering this node /// * `name` #[inline] - pub fn ts_import_type_qualifier_identifier( + pub fn ts_import_type_qualifier_identifier( self, span: Span, - name: A1, - ) -> TSImportTypeQualifier<'a> - where - A1: Into>, - { + name: Ident<'a>, + ) -> TSImportTypeQualifier<'a> { TSImportTypeQualifier::Identifier(self.alloc_identifier_name(span, name)) } diff --git a/crates/oxc_ast/src/serialize/jsx.rs b/crates/oxc_ast/src/serialize/jsx.rs index bc5e6fbe6dc03..905fb9cbe586a 100644 --- a/crates/oxc_ast/src/serialize/jsx.rs +++ b/crates/oxc_ast/src/serialize/jsx.rs @@ -1,5 +1,6 @@ use oxc_ast_macros::ast_meta; use oxc_estree::{ESTree, JsonSafeString, Serializer, StructSerializer}; +use oxc_span::Ident; use crate::ast::*; @@ -82,6 +83,6 @@ pub struct JSXElementThisExpression<'b>(pub &'b ThisExpression); impl ESTree for JSXElementThisExpression<'_> { fn serialize(&self, serializer: S) { - JSXIdentifier { span: self.0.span, name: Atom::from("this") }.serialize(serializer); + JSXIdentifier { span: self.0.span, name: Ident::new("this") }.serialize(serializer); } } diff --git a/crates/oxc_ast/src/serialize/ts.rs b/crates/oxc_ast/src/serialize/ts.rs index 77c786c982607..0c5037bbc92ac 100644 --- a/crates/oxc_ast/src/serialize/ts.rs +++ b/crates/oxc_ast/src/serialize/ts.rs @@ -1,5 +1,6 @@ use oxc_ast_macros::ast_meta; use oxc_estree::{Concat2, ESTree, JsonSafeString, Serializer, StructSerializer}; +use oxc_span::Ident; use crate::ast::*; @@ -275,7 +276,7 @@ pub struct TSGlobalDeclarationId<'a, 'b>(pub &'b TSGlobalDeclaration<'a>); impl ESTree for TSGlobalDeclarationId<'_, '_> { fn serialize(&self, serializer: S) { - let ident = IdentifierName { span: self.0.global_span, name: Atom::from("global") }; + let ident = IdentifierName { span: self.0.global_span, name: Ident::new("global") }; ident.serialize(serializer); } } diff --git a/crates/oxc_formatter/src/ast_nodes/generated/ast_nodes.rs b/crates/oxc_formatter/src/ast_nodes/generated/ast_nodes.rs index f06e0408163ab..4bd8d2c0e7e01 100644 --- a/crates/oxc_formatter/src/ast_nodes/generated/ast_nodes.rs +++ b/crates/oxc_formatter/src/ast_nodes/generated/ast_nodes.rs @@ -5,7 +5,7 @@ use std::mem::transmute; use oxc_allocator::Vec; use oxc_ast::ast::*; -use oxc_span::GetSpan; +use oxc_span::{GetSpan, Ident}; use crate::ast_nodes::AstNode; use crate::formatter::{ @@ -1190,7 +1190,7 @@ impl<'a> AstNode<'a, Expression<'a>> { impl<'a> AstNode<'a, IdentifierName<'a>> { #[inline] - pub fn name(&self) -> Atom<'a> { + pub fn name(&self) -> Ident<'a> { self.inner.name } @@ -1205,7 +1205,7 @@ impl<'a> AstNode<'a, IdentifierName<'a>> { impl<'a> AstNode<'a, IdentifierReference<'a>> { #[inline] - pub fn name(&self) -> Atom<'a> { + pub fn name(&self) -> Ident<'a> { self.inner.name } @@ -1220,7 +1220,7 @@ impl<'a> AstNode<'a, IdentifierReference<'a>> { impl<'a> AstNode<'a, BindingIdentifier<'a>> { #[inline] - pub fn name(&self) -> Atom<'a> { + pub fn name(&self) -> Ident<'a> { self.inner.name } @@ -1235,7 +1235,7 @@ impl<'a> AstNode<'a, BindingIdentifier<'a>> { impl<'a> AstNode<'a, LabelIdentifier<'a>> { #[inline] - pub fn name(&self) -> Atom<'a> { + pub fn name(&self) -> Ident<'a> { self.inner.name } @@ -4762,7 +4762,7 @@ impl<'a> AstNode<'a, PropertyDefinition<'a>> { impl<'a> AstNode<'a, PrivateIdentifier<'a>> { #[inline] - pub fn name(&self) -> Atom<'a> { + pub fn name(&self) -> Ident<'a> { self.inner.name } @@ -6212,7 +6212,7 @@ impl<'a> AstNode<'a, JSXAttributeValue<'a>> { impl<'a> AstNode<'a, JSXIdentifier<'a>> { #[inline] - pub fn name(&self) -> Atom<'a> { + pub fn name(&self) -> Ident<'a> { self.inner.name } diff --git a/crates/oxc_formatter/src/utils/member_chain/mod.rs b/crates/oxc_formatter/src/utils/member_chain/mod.rs index 4dfe3d5180411..e6f5c5f724d8b 100644 --- a/crates/oxc_formatter/src/utils/member_chain/mod.rs +++ b/crates/oxc_formatter/src/utils/member_chain/mod.rs @@ -391,8 +391,8 @@ pub fn is_member_call_chain<'a>( MemberChain::from_call_expression(expression, f).tail.is_member_call_chain() } -fn has_short_name(name: &Atom, tab_width: u8) -> bool { - name.as_str().len() <= tab_width as usize +fn has_short_name(name: &str, tab_width: u8) -> bool { + name.len() <= tab_width as usize } fn chain_members_iter<'a, 'b>( diff --git a/crates/oxc_isolated_declarations/src/class.rs b/crates/oxc_isolated_declarations/src/class.rs index 0ce862b1fdffa..f2aba514ce6ae 100644 --- a/crates/oxc_isolated_declarations/src/class.rs +++ b/crates/oxc_isolated_declarations/src/class.rs @@ -1,6 +1,6 @@ use oxc_allocator::{Allocator, Box as ArenaBox, CloneIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; -use oxc_span::{ContentEq, GetSpan, SPAN}; +use oxc_span::{ContentEq, GetSpan, Ident, SPAN}; use crate::{ IsolatedDeclarations, @@ -270,7 +270,7 @@ impl<'a> IsolatedDeclarations<'a> { } MethodDefinitionKind::Set => { let params = self.create_formal_parameters( - self.ast.binding_pattern_kind_binding_identifier(SPAN, "value"), + self.ast.binding_pattern_kind_binding_identifier(SPAN, Ident::new("value")), ); self.transform_class_method_definition(method, params, None) } @@ -449,7 +449,10 @@ impl<'a> IsolatedDeclarations<'a> { let params = &method.value.params; if params.items.is_empty() { self.create_formal_parameters( - self.ast.binding_pattern_kind_binding_identifier(SPAN, "value"), + self.ast.binding_pattern_kind_binding_identifier( + SPAN, + Ident::new("value"), + ), ) } else { let mut params = params.clone_in(self.ast.allocator); @@ -606,7 +609,7 @@ impl<'a> IsolatedDeclarations<'a> { // // When the class has at least one private identifier, create a unique constant identifier to retain the nominal typing behavior // Prevents other classes with the same public members from being used in place of the current class - let ident = self.ast.property_key_private_identifier(SPAN, "private"); + let ident = self.ast.property_key_private_identifier(SPAN, Ident::new("private")); let r#type = PropertyDefinitionType::PropertyDefinition; let decorators = self.ast.vec(); let element = self.ast.class_element_property_definition( diff --git a/crates/oxc_isolated_declarations/src/declaration.rs b/crates/oxc_isolated_declarations/src/declaration.rs index be23742cb9145..7738c0342d783 100644 --- a/crates/oxc_isolated_declarations/src/declaration.rs +++ b/crates/oxc_isolated_declarations/src/declaration.rs @@ -48,7 +48,7 @@ impl<'a> IsolatedDeclarations<'a> { ) -> Option> { if decl.id.kind.is_destructuring_pattern() { decl.id.bound_names(&mut |id| { - if !check_binding || self.scope.has_value_reference(&id.name) { + if !check_binding || self.scope.has_value_reference(id.name) { self.error(binding_element_export(id.span)); } }); @@ -57,7 +57,7 @@ impl<'a> IsolatedDeclarations<'a> { if check_binding && let Some(name) = decl.id.get_identifier_name() - && !self.scope.has_value_reference(&name) + && !self.scope.has_value_reference(name) { return None; } @@ -160,7 +160,7 @@ impl<'a> IsolatedDeclarations<'a> { match decl { Declaration::FunctionDeclaration(func) => { let needs_transform = !check_binding - || func.id.as_ref().is_some_and(|id| self.scope.has_value_reference(&id.name)); + || func.id.as_ref().is_some_and(|id| self.scope.has_value_reference(id.name)); needs_transform .then(|| Declaration::FunctionDeclaration(self.transform_function(func, None))) } @@ -169,12 +169,12 @@ impl<'a> IsolatedDeclarations<'a> { .map(Declaration::VariableDeclaration), Declaration::ClassDeclaration(decl) => { let needs_transform = !check_binding - || decl.id.as_ref().is_some_and(|id| self.scope.has_reference(&id.name)); + || decl.id.as_ref().is_some_and(|id| self.scope.has_reference(id.name)); needs_transform .then(|| Declaration::ClassDeclaration(self.transform_class(decl, None))) } Declaration::TSTypeAliasDeclaration(alias_decl) => { - if !check_binding || self.scope.has_reference(&alias_decl.id.name) { + if !check_binding || self.scope.has_reference(alias_decl.id.name) { let mut decl = decl.clone_in(self.ast.allocator); self.visit_declaration(&mut decl); Some(decl) @@ -183,7 +183,7 @@ impl<'a> IsolatedDeclarations<'a> { } } Declaration::TSInterfaceDeclaration(interface_decl) => { - if !check_binding || self.scope.has_reference(&interface_decl.id.name) { + if !check_binding || self.scope.has_reference(interface_decl.id.name) { let mut decl = decl.clone_in(self.ast.allocator); self.visit_declaration(&mut decl); Some(decl) @@ -192,7 +192,7 @@ impl<'a> IsolatedDeclarations<'a> { } } Declaration::TSEnumDeclaration(enum_decl) => { - if !check_binding || self.scope.has_reference(&enum_decl.id.name) { + if !check_binding || self.scope.has_reference(enum_decl.id.name) { Some(self.transform_ts_enum_declaration(enum_decl)) } else { None @@ -203,7 +203,7 @@ impl<'a> IsolatedDeclarations<'a> { || matches!( &decl.id, TSModuleDeclarationName::Identifier(ident) - if self.scope.has_reference(&ident.name) + if self.scope.has_reference(ident.name) ) { Some(Declaration::TSModuleDeclaration( @@ -217,7 +217,7 @@ impl<'a> IsolatedDeclarations<'a> { Some(Declaration::TSGlobalDeclaration(decl.clone_in(self.ast.allocator))) } Declaration::TSImportEqualsDeclaration(decl) => { - if !check_binding || self.scope.has_reference(&decl.id.name) { + if !check_binding || self.scope.has_reference(decl.id.name) { Some(Declaration::TSImportEqualsDeclaration(decl.clone_in(self.ast.allocator))) } else { None diff --git a/crates/oxc_isolated_declarations/src/enum.rs b/crates/oxc_isolated_declarations/src/enum.rs index 23c8b9792b64b..23d25ac060f04 100644 --- a/crates/oxc_isolated_declarations/src/enum.rs +++ b/crates/oxc_isolated_declarations/src/enum.rs @@ -1,9 +1,7 @@ -use rustc_hash::FxHashMap; - use oxc_allocator::CloneIn; use oxc_ast::ast::*; use oxc_ecmascript::{ToInt32, ToUint32}; -use oxc_span::{Atom, GetSpan, SPAN}; +use oxc_span::{GetSpan, Ident, IdentHashMap, SPAN}; use oxc_syntax::{ number::{NumberBase, ToJsString}, operator::{BinaryOperator, UnaryOperator}, @@ -21,7 +19,7 @@ impl<'a> IsolatedDeclarations<'a> { pub fn transform_ts_enum_declaration(&self, decl: &TSEnumDeclaration<'a>) -> Declaration<'a> { let mut members = self.ast.vec(); let mut prev_initializer_value = Some(ConstantValue::Number(-1.0)); - let mut prev_members = FxHashMap::default(); + let mut prev_members = IdentHashMap::default(); for member in &decl.body.members { let value = if let Some(initializer) = &member.initializer { let computed_value = @@ -54,7 +52,7 @@ impl<'a> IsolatedDeclarations<'a> { // Infinity let expr = if v.is_infinite() { - self.ast.expression_identifier(SPAN, "Infinity") + self.ast.expression_identifier(SPAN, Ident::new("Infinity")) } else { let value = if is_negative { -v } else { v }; self.ast.expression_numeric_literal( @@ -95,7 +93,7 @@ impl<'a> IsolatedDeclarations<'a> { &self, expr: &Expression<'a>, enum_name: &str, - prev_members: &FxHashMap, ConstantValue>, + prev_members: &IdentHashMap<'a, ConstantValue>, ) -> Option { self.evaluate(expr, enum_name, prev_members) } @@ -103,7 +101,7 @@ impl<'a> IsolatedDeclarations<'a> { fn evaluate_ref( expr: &Expression<'a>, enum_name: &str, - prev_members: &FxHashMap, ConstantValue>, + prev_members: &IdentHashMap<'a, ConstantValue>, ) -> Option { match expr { match_member_expression!(Expression) => { @@ -111,7 +109,9 @@ impl<'a> IsolatedDeclarations<'a> { let Expression::Identifier(ident) = expr.object() else { return None }; if ident.name == enum_name { let property = expr.static_property_name()?; - prev_members.get(property).cloned() + // TODO: do we need to convert to Ident here? + let property = Ident::from(property); + prev_members.get(&property).cloned() } else { None } @@ -137,7 +137,7 @@ impl<'a> IsolatedDeclarations<'a> { &self, expr: &Expression<'a>, enum_name: &str, - prev_members: &FxHashMap, ConstantValue>, + prev_members: &IdentHashMap<'a, ConstantValue>, ) -> Option { match expr { Expression::Identifier(_) @@ -172,7 +172,7 @@ impl<'a> IsolatedDeclarations<'a> { &self, expr: &BinaryExpression<'a>, enum_name: &str, - prev_members: &FxHashMap, ConstantValue>, + prev_members: &IdentHashMap<'a, ConstantValue>, ) -> Option { let left = self.evaluate(&expr.left, enum_name, prev_members)?; let right = self.evaluate(&expr.right, enum_name, prev_members)?; @@ -237,7 +237,7 @@ impl<'a> IsolatedDeclarations<'a> { &self, expr: &UnaryExpression<'a>, enum_name: &str, - prev_members: &FxHashMap, ConstantValue>, + prev_members: &IdentHashMap<'a, ConstantValue>, ) -> Option { let value = self.evaluate(&expr.argument, enum_name, prev_members)?; diff --git a/crates/oxc_isolated_declarations/src/lib.rs b/crates/oxc_isolated_declarations/src/lib.rs index 96c5ef9636166..3a61e81fefd71 100644 --- a/crates/oxc_isolated_declarations/src/lib.rs +++ b/crates/oxc_isolated_declarations/src/lib.rs @@ -13,7 +13,7 @@ use oxc_allocator::{Allocator, CloneIn, Vec as ArenaVec}; use oxc_ast::{AstBuilder, NONE, ast::*}; use oxc_ast_visit::Visit; use oxc_diagnostics::OxcDiagnostic; -use oxc_span::{Atom, GetSpan, SPAN, SourceType}; +use oxc_span::{GetSpan, Ident, SPAN, SourceType}; use crate::{diagnostics::function_with_assigning_properties, scope::ScopeTree}; @@ -439,7 +439,7 @@ impl<'a> IsolatedDeclarations<'a> { } fn remove_function_overloads_implementation(stmts: &mut Vec<&Statement<'a>>) { - let mut last_function_name: Option> = None; + let mut last_function_name: Option> = None; let mut is_export_default_function_overloads = false; stmts.retain(move |&stmt| match stmt { @@ -506,7 +506,8 @@ impl<'a> IsolatedDeclarations<'a> { fn get_assignable_properties_for_namespaces( stmts: &'a ArenaVec<'a, Statement<'a>>, ) -> FxHashMap<&'a str, FxHashSet>> { - let mut assignable_properties_for_namespace = FxHashMap::<&str, FxHashSet>::default(); + let mut assignable_properties_for_namespace = + FxHashMap::<&str, FxHashSet>>::default(); for stmt in stmts { let decl = match stmt { Statement::ExportNamedDeclaration(decl) => { @@ -536,7 +537,7 @@ impl<'a> IsolatedDeclarations<'a> { assignable_properties_for_namespace .entry(&ident.name) .or_default() - .insert(name); + .insert(name.as_atom()); } } } @@ -545,7 +546,7 @@ impl<'a> IsolatedDeclarations<'a> { assignable_properties_for_namespace .entry(&ident.name) .or_default() - .insert(name); + .insert(name.as_atom()); } } Some(Declaration::ClassDeclaration(cls)) => { @@ -553,14 +554,14 @@ impl<'a> IsolatedDeclarations<'a> { assignable_properties_for_namespace .entry(&ident.name) .or_default() - .insert(id.name); + .insert(id.name.as_atom()); } } Some(Declaration::TSEnumDeclaration(decl)) => { assignable_properties_for_namespace .entry(&ident.name) .or_default() - .insert(decl.id.name); + .insert(decl.id.name.as_atom()); } _ => {} } @@ -608,7 +609,7 @@ impl<'a> IsolatedDeclarations<'a> { Statement::FunctionDeclaration(func) => { if func.body.is_some() && let Some(name) = func.name() - && self.scope.has_value_reference(&name) + && self.scope.has_value_reference(name) { can_expando_function_names.insert(name); } @@ -618,7 +619,7 @@ impl<'a> IsolatedDeclarations<'a> { if declarator.id.type_annotation.is_none() && declarator.init.as_ref().is_some_and(Expression::is_function) && let Some(name) = declarator.id.get_identifier_name() - && self.scope.has_value_reference(&name) + && self.scope.has_value_reference(name) { can_expando_function_names.insert(name); } @@ -633,7 +634,7 @@ impl<'a> IsolatedDeclarations<'a> { && !assignable_properties_for_namespace .get(&ident.name.as_str()) .is_some_and(|properties| { - properties.contains(&static_member_expr.property.name) + properties.contains(&static_member_expr.property.name.as_atom()) }) { self.error(function_with_assigning_properties(static_member_expr.span)); diff --git a/crates/oxc_isolated_declarations/src/module.rs b/crates/oxc_isolated_declarations/src/module.rs index f8af0ef028a58..1af29772a4512 100644 --- a/crates/oxc_isolated_declarations/src/module.rs +++ b/crates/oxc_isolated_declarations/src/module.rs @@ -1,6 +1,6 @@ use oxc_allocator::{Box as ArenaBox, CloneIn, TakeIn, Vec as ArenaVec}; use oxc_ast::{NONE, ast::*}; -use oxc_span::{Atom, GetSpan, SPAN}; +use oxc_span::{GetSpan, Ident, SPAN}; use crate::{IsolatedDeclarations, diagnostics::default_export_inferred}; @@ -21,11 +21,11 @@ impl<'a> IsolatedDeclarations<'a> { )) } - pub(crate) fn create_unique_name(&self, name: &str) -> Atom<'a> { - let mut binding = self.ast.atom(name); + pub(crate) fn create_unique_name(&self, name: &str) -> Ident<'a> { + let mut binding = self.ast.ident(name); let mut i = 1; - while self.scope.has_reference(&binding) { - binding = self.ast.atom(format!("{name}_{i}").as_str()); + while self.scope.has_reference(binding) { + binding = self.ast.ident(format!("{name}_{i}").as_str()); i += 1; } binding @@ -141,13 +141,13 @@ impl<'a> IsolatedDeclarations<'a> { specifiers.iter().for_each(|specifier| { let is_referenced = match specifier { ImportDeclarationSpecifier::ImportSpecifier(specifier) => { - self.scope.has_reference(&specifier.local.name) + self.scope.has_reference(specifier.local.name) } ImportDeclarationSpecifier::ImportDefaultSpecifier(specifier) => { - self.scope.has_reference(&specifier.local.name) + self.scope.has_reference(specifier.local.name) } - ImportDeclarationSpecifier::ImportNamespaceSpecifier(_) => { - self.scope.has_reference(&specifier.name()) + ImportDeclarationSpecifier::ImportNamespaceSpecifier(specifier) => { + self.scope.has_reference(specifier.local.name) } }; if is_referenced { diff --git a/crates/oxc_isolated_declarations/src/return_type.rs b/crates/oxc_isolated_declarations/src/return_type.rs index c8bfca4245bee..b28a9abfa880d 100644 --- a/crates/oxc_isolated_declarations/src/return_type.rs +++ b/crates/oxc_isolated_declarations/src/return_type.rs @@ -9,7 +9,7 @@ use oxc_ast::{ }, }; use oxc_ast_visit::Visit; -use oxc_span::{Atom, GetSpan, SPAN}; +use oxc_span::{GetSpan, Ident, SPAN}; use oxc_syntax::scope::{ScopeFlags, ScopeId}; use crate::{IsolatedDeclarations, diagnostics::type_containing_private_name}; @@ -41,8 +41,8 @@ use crate::{IsolatedDeclarations, diagnostics::type_containing_private_name}; pub struct FunctionReturnType<'a> { ast: AstBuilder<'a>, return_expression: Option>>, - value_bindings: Vec>, - type_bindings: Vec>, + value_bindings: Vec>, + type_bindings: Vec>, return_statement_count: u8, scope_depth: u32, } diff --git a/crates/oxc_isolated_declarations/src/scope.rs b/crates/oxc_isolated_declarations/src/scope.rs index 84cef4a5d622f..20988f7e35c6b 100644 --- a/crates/oxc_isolated_declarations/src/scope.rs +++ b/crates/oxc_isolated_declarations/src/scope.rs @@ -1,11 +1,10 @@ use std::cell::Cell; use bitflags::bitflags; -use rustc_hash::FxHashMap; use oxc_ast::ast::*; use oxc_ast_visit::{Visit, walk::*}; -use oxc_span::Atom; +use oxc_span::{Ident, IdentHashMap}; use oxc_syntax::scope::{ScopeFlags, ScopeId}; bitflags! { @@ -20,14 +19,14 @@ bitflags! { /// Declaration scope. #[derive(Debug)] struct Scope<'a> { - bindings: FxHashMap, KindFlags>, - references: FxHashMap, KindFlags>, + bindings: IdentHashMap<'a, KindFlags>, + references: IdentHashMap<'a, KindFlags>, flags: ScopeFlags, } impl Scope<'_> { fn new(flags: ScopeFlags) -> Self { - Self { bindings: FxHashMap::default(), references: FxHashMap::default(), flags } + Self { bindings: IdentHashMap::default(), references: IdentHashMap::default(), flags } } } @@ -48,23 +47,23 @@ impl<'a> ScopeTree<'a> { scope.flags.contains(ScopeFlags::TsModuleBlock) } - pub fn has_reference(&self, name: &str) -> bool { + pub fn has_reference(&self, name: Ident) -> bool { let scope = self.levels.last().unwrap(); - scope.references.contains_key(name) + scope.references.contains_key(&name) } /// Check if the current scope has a value reference for the given name. - pub fn has_value_reference(&self, name: &str) -> bool { + pub fn has_value_reference(&self, name: Ident) -> bool { let scope = self.levels.last().unwrap(); - scope.references.get(name).iter().any(|flags| flags.contains(KindFlags::Value)) + scope.references.get(&name).iter().any(|flags| flags.contains(KindFlags::Value)) } - fn add_binding(&mut self, name: Atom<'a>, flags: KindFlags) { + fn add_binding(&mut self, name: Ident<'a>, flags: KindFlags) { let scope = self.levels.last_mut().unwrap(); scope.bindings.insert(name, flags); } - fn add_reference(&mut self, name: Atom<'a>, flags: KindFlags) { + fn add_reference(&mut self, name: Ident<'a>, flags: KindFlags) { let scope = self.levels.last_mut().unwrap(); scope.references.entry(name).and_modify(|f| *f |= flags).or_insert(flags); } diff --git a/crates/oxc_isolated_declarations/src/types.rs b/crates/oxc_isolated_declarations/src/types.rs index b4dfcdff615f8..ebe2102054bed 100644 --- a/crates/oxc_isolated_declarations/src/types.rs +++ b/crates/oxc_isolated_declarations/src/types.rs @@ -7,7 +7,7 @@ use oxc_ast::{ TSMethodSignatureKind, TSTupleElement, TSType, TSTypeOperatorOperator, }, }; -use oxc_span::{ContentEq, GetSpan, SPAN, Span}; +use oxc_span::{ContentEq, GetSpan, Ident, SPAN, Span}; use oxc_syntax::identifier::is_identifier_name; use crate::{ @@ -71,13 +71,16 @@ impl<'a> IsolatedDeclarations<'a> { match key { // ["string"] -> string PropertyKey::StringLiteral(literal) if is_identifier_name(&literal.value) => { - self.ast.property_key_static_identifier(literal.span, literal.value.as_str()) + self.ast.property_key_static_identifier(literal.span, Ident::from(literal.value)) } // [`string`] -> string PropertyKey::TemplateLiteral(literal) if is_identifier_name(&literal.quasis[0].value.raw) => { - self.ast.property_key_static_identifier(literal.span, literal.quasis[0].value.raw) + self.ast.property_key_static_identifier( + literal.span, + Ident::from(literal.quasis[0].value.raw), + ) } // [100] -> 100 // number literal will be cloned as-is diff --git a/crates/oxc_linter/src/rules/eslint/block_scoped_var.rs b/crates/oxc_linter/src/rules/eslint/block_scoped_var.rs index ae65abafcfb68..8ee1325b7a75a 100644 --- a/crates/oxc_linter/src/rules/eslint/block_scoped_var.rs +++ b/crates/oxc_linter/src/rules/eslint/block_scoped_var.rs @@ -5,7 +5,7 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::{GetSpan, Span}; +use oxc_span::{GetSpan, Ident, Span}; use oxc_syntax::{scope::ScopeId, symbol::SymbolId}; fn redeclaration_diagnostic(decl_span: Span, redeclare_span: Span, name: &str) -> OxcDiagnostic { @@ -199,7 +199,7 @@ fn run_for_declaration( // e.g. "var [a, b] = [1, 2]" for ident in pattern.get_binding_identifiers() { let name = ident.name.as_str(); - let Some(symbol) = ctx.scoping().find_binding(node.scope_id(), name) else { + let Some(symbol) = ctx.scoping().find_binding(node.scope_id(), &Ident::from(name)) else { continue; }; diff --git a/crates/oxc_linter/src/rules/eslint/func_names.rs b/crates/oxc_linter/src/rules/eslint/func_names.rs index 77cbb1bcf4013..9260dcfcdf802 100644 --- a/crates/oxc_linter/src/rules/eslint/func_names.rs +++ b/crates/oxc_linter/src/rules/eslint/func_names.rs @@ -10,7 +10,7 @@ use oxc_ast::{ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::NodeId; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{GetSpan, Ident, Span}; use oxc_syntax::{identifier::is_identifier_name, keyword::is_reserved_keyword_or_global_object}; use crate::{ @@ -264,7 +264,7 @@ fn is_recursive_function(func: &Function, func_name: &str, ctx: &LintContext) -> return false; }; - if let Some(binding) = ctx.scoping().find_binding(func_scope_id, func_name) { + if let Some(binding) = ctx.scoping().find_binding(func_scope_id, &Ident::from(func_name)) { return ctx.semantic().symbol_references(binding).any(|reference| { let parent = ctx.nodes().parent_node(reference.node_id()); // Check if this reference is the callee of a call expression (direct recursive call) @@ -431,7 +431,7 @@ fn is_invalid_function( /// Returns whether it's safe to insert a function name without breaking shadowing rules fn can_safely_apply_fix(func: &Function, name: &str, ctx: &LintContext) -> bool { - !ctx.scoping().find_binding(func.scope_id(), name).is_some_and(|shadowed_var| { + !ctx.scoping().find_binding(func.scope_id(), &Ident::from(name)).is_some_and(|shadowed_var| { ctx.semantic().symbol_references(shadowed_var).any(|reference| { func.span.contains_inclusive(ctx.nodes().get_node(reference.node_id()).kind().span()) }) @@ -468,7 +468,7 @@ fn guess_function_name<'a>(ctx: &LintContext<'a>, node_id: NodeId) -> Option( if ctx.is_reference_to_global_variable(ident) && (expr.is_specific_id(GLOBAL_WINDOW) || (expr.is_specific_id(GLOBAL_THIS))) { - return !is_shadowed(scope_id, ident.name.as_str(), ctx); + return !is_shadowed(scope_id, &ident.name, ctx); } false } -fn is_shadowed<'a>(scope_id: ScopeId, name: &'a str, ctx: &LintContext<'a>) -> bool { +fn is_shadowed(scope_id: ScopeId, name: &Ident, ctx: &LintContext) -> bool { ctx.scoping().find_binding(scope_id, name).is_some() } @@ -99,8 +99,9 @@ impl Rule for NoAlert { let callee = &call_expr.callee; if let Expression::Identifier(ident) = callee { - let name = ident.name.as_str(); - if !is_shadowed(scope_id, name, ctx) && is_prohibited_identifier(name) { + if !is_shadowed(scope_id, &ident.name, ctx) + && is_prohibited_identifier(ident.name.as_str()) + { return ctx.diagnostic(no_alert_diagnostic(ident.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 436a14c047763..d97069f82a243 100644 --- a/crates/oxc_linter/src/rules/eslint/no_global_assign.rs +++ b/crates/oxc_linter/src/rules/eslint/no_global_assign.rs @@ -68,7 +68,7 @@ impl Rule for NoGlobalAssign { for &reference_id in reference_id_list { let reference = symbol_table.get_reference(reference_id); if reference.is_write() - && !self.exceptions.iter().any(|n| n == name) + && !self.exceptions.iter().any(|n| n.as_str() == name.as_str()) && ctx .get_global_variable_value(name) .is_some_and(|global| global == GlobalValue::Readonly) diff --git a/crates/oxc_linter/src/rules/eslint/no_unused_vars/fixers/fix_vars.rs b/crates/oxc_linter/src/rules/eslint/no_unused_vars/fixers/fix_vars.rs index c0f54aaf18b36..d4cbd1cdd1875 100644 --- a/crates/oxc_linter/src/rules/eslint/no_unused_vars/fixers/fix_vars.rs +++ b/crates/oxc_linter/src/rules/eslint/no_unused_vars/fixers/fix_vars.rs @@ -138,7 +138,7 @@ impl NoUnusedVars { let scope_id = symbol.scope_id(); let mut i = 0; let mut new_name = ignored_name.clone(); - while scopes.scope_has_binding(scope_id, &new_name) { + while scopes.scope_has_binding(scope_id, &oxc_span::Ident::from(new_name.as_str())) { new_name = format!("{ignored_name}{i}"); i += 1; } diff --git a/crates/oxc_linter/src/rules/eslint/prefer_destructuring.rs b/crates/oxc_linter/src/rules/eslint/prefer_destructuring.rs index 7e9d1502f16ff..8073ac5e5a840 100644 --- a/crates/oxc_linter/src/rules/eslint/prefer_destructuring.rs +++ b/crates/oxc_linter/src/rules/eslint/prefer_destructuring.rs @@ -4,7 +4,7 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::{GetSpan, Span}; +use oxc_span::{GetSpan, Ident, Span}; use schemars::JsonSchema; use serde::{Deserialize, Serialize}; use serde_json::Value; @@ -186,7 +186,7 @@ impl Rule for PreferDestructuring { } let name = if matches!(declarator.id.kind, BindingPatternKind::BindingIdentifier(_)) { - declarator.id.get_identifier_name().map(|v| v.as_str()) + declarator.id.get_identifier_name().map(Ident::as_str) } else { None }; diff --git a/crates/oxc_linter/src/rules/eslint/prefer_object_has_own.rs b/crates/oxc_linter/src/rules/eslint/prefer_object_has_own.rs index 5efdeddc2db0e..3813a0bb84115 100644 --- a/crates/oxc_linter/src/rules/eslint/prefer_object_has_own.rs +++ b/crates/oxc_linter/src/rules/eslint/prefer_object_has_own.rs @@ -75,7 +75,8 @@ impl Rule for PreferObjectHasOwn { let object_property_name = object.static_property_name(); let is_object = has_left_hand_object(object); - let is_global_scope = ctx.scoping().find_binding(node.scope_id(), "Object").is_none(); + let is_global_scope = + ctx.scoping().find_binding(node.scope_id(), &oxc_span::Ident::new("Object")).is_none(); if is_method_call(call_expr, None, Some(&["call"]), Some(2), Some(2)) && object_property_name == Some("hasOwnProperty") diff --git a/crates/oxc_linter/src/rules/eslint/prefer_rest_params.rs b/crates/oxc_linter/src/rules/eslint/prefer_rest_params.rs index 7e2a1fc2c8029..52e1262cc1339 100644 --- a/crates/oxc_linter/src/rules/eslint/prefer_rest_params.rs +++ b/crates/oxc_linter/src/rules/eslint/prefer_rest_params.rs @@ -73,7 +73,8 @@ impl Rule for PreferRestParams { { return; } - let binding = ctx.scoping().find_binding(node.scope_id(), "arguments"); + let binding = + ctx.scoping().find_binding(node.scope_id(), &oxc_span::Ident::new("arguments")); if binding.is_none() { ctx.diagnostic(prefer_rest_params_diagnostic(node.span())); } diff --git a/crates/oxc_linter/src/rules/import/namespace.rs b/crates/oxc_linter/src/rules/import/namespace.rs index a4cd7957df7e6..fa2a6331e1d4f 100644 --- a/crates/oxc_linter/src/rules/import/namespace.rs +++ b/crates/oxc_linter/src/rules/import/namespace.rs @@ -7,7 +7,7 @@ use oxc_ast::{ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::AstNode; -use oxc_span::{GetSpan, Span}; +use oxc_span::{GetSpan, Ident, Span}; use schemars::JsonSchema; use serde::Deserialize; @@ -160,7 +160,9 @@ impl Rule for Namespace { return; } - let Some(symbol_id) = ctx.scoping().get_root_binding(entry.local_name.name()) else { + let Some(symbol_id) = + ctx.scoping().get_root_binding(&Ident::from(entry.local_name.name())) + else { return; }; diff --git a/crates/oxc_linter/src/rules/import/no_commonjs.rs b/crates/oxc_linter/src/rules/import/no_commonjs.rs index 33201ad6a568f..551f5e6dc88ea 100644 --- a/crates/oxc_linter/src/rules/import/no_commonjs.rs +++ b/crates/oxc_linter/src/rules/import/no_commonjs.rs @@ -4,7 +4,7 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::{GetSpan, Span}; +use oxc_span::{GetSpan, Ident, Span}; use schemars::JsonSchema; use serde::Deserialize; @@ -235,7 +235,11 @@ impl Rule for NoCommonjs { return; } - if ctx.scoping().find_binding(ctx.scoping().root_scope_id(), "require").is_some() { + if ctx + .scoping() + .find_binding(ctx.scoping().root_scope_id(), &Ident::from("require")) + .is_some() + { return; } 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 737ec6d35364c..3e66fe30c6456 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 @@ -5,7 +5,7 @@ use oxc_ast::{ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::SymbolId; -use oxc_span::{GetSpan, Span}; +use oxc_span::{GetSpan, Ident, Span}; use rustc_hash::FxHashMap; use crate::{context::LintContext, module_record::ImportImportName, rule::Rule}; @@ -91,7 +91,8 @@ impl Rule for NoNamedAsDefaultMember { continue; } - let Some(symbol_id) = ctx.scoping().get_root_binding(import_entry.local_name.name()) + let Some(symbol_id) = + ctx.scoping().get_root_binding(&Ident::from(import_entry.local_name.name())) else { return; }; diff --git a/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs b/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs index 41c475a874e46..7c6dc257a762e 100644 --- a/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs +++ b/crates/oxc_linter/src/rules/jest/no_jasmine_globals.rs @@ -79,7 +79,7 @@ impl Rule for NoJasmineGlobals { .scoping() .root_unresolved_references() .iter() - .filter(|(key, _)| NON_JASMINE_PROPERTY_NAMES.contains(key)); + .filter(|(key, _)| NON_JASMINE_PROPERTY_NAMES.contains(&key.as_str())); for (name, reference_ids) in jasmine_references { for &reference_id in reference_ids { diff --git a/crates/oxc_linter/src/rules/nextjs/inline_script_id.rs b/crates/oxc_linter/src/rules/nextjs/inline_script_id.rs index b4535fe921c0d..af5cbddea99ab 100644 --- a/crates/oxc_linter/src/rules/nextjs/inline_script_id.rs +++ b/crates/oxc_linter/src/rules/nextjs/inline_script_id.rs @@ -4,7 +4,7 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::{GetSpan, Span}; +use oxc_span::{GetSpan, Ident, Span}; use rustc_hash::FxHashSet; use crate::{AstNode, context::LintContext, rule::Rule}; @@ -146,12 +146,12 @@ impl Rule for InlineScriptId { } } - if prop_names_hash_set.contains("id") { + if prop_names_hash_set.contains(&Ident::new("id")) { continue; } if !jsx_element.children.is_empty() - || prop_names_hash_set.contains("dangerouslySetInnerHTML") + || prop_names_hash_set.contains(&Ident::new("dangerouslySetInnerHTML")) { ctx.diagnostic(inline_script_id_diagnostic(jsx_opening_element.name.span())); } diff --git a/crates/oxc_linter/src/rules/nextjs/no_sync_scripts.rs b/crates/oxc_linter/src/rules/nextjs/no_sync_scripts.rs index b82391c596ce2..0e2633840c169 100644 --- a/crates/oxc_linter/src/rules/nextjs/no_sync_scripts.rs +++ b/crates/oxc_linter/src/rules/nextjs/no_sync_scripts.rs @@ -4,7 +4,7 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::Span; +use oxc_span::{Ident, Span}; use rustc_hash::FxHashSet; use crate::{AstNode, context::LintContext, rule::Rule}; @@ -84,9 +84,9 @@ impl Rule for NoSyncScripts { }) .collect::>(); - if attributes_hs.contains("src") - && !attributes_hs.contains("async") - && !attributes_hs.contains("defer") + if attributes_hs.contains(&Ident::new("src")) + && !attributes_hs.contains(&Ident::new("async")) + && !attributes_hs.contains(&Ident::new("defer")) { ctx.diagnostic(no_sync_scripts_diagnostic(jsx_opening_element_name.span)); } @@ -99,7 +99,7 @@ fn test() { let pass = vec![ r"import {Head} from 'next/document'; - + export class Blah extends Head { render() { return ( @@ -111,7 +111,7 @@ fn test() { } }", r"import {Head} from 'next/document'; - + export class Blah extends Head { render(props) { return ( @@ -127,7 +127,7 @@ fn test() { let fail = vec![ r" import {Head} from 'next/document'; - + export class Blah extends Head { render() { return ( @@ -140,7 +140,7 @@ fn test() { }", r" import {Head} from 'next/document'; - + export class Blah extends Head { render(props) { return ( diff --git a/crates/oxc_linter/src/rules/oxc/no_async_endpoint_handlers.rs b/crates/oxc_linter/src/rules/oxc/no_async_endpoint_handlers.rs index fb6d00bc4a5c7..efc9179a6c21a 100644 --- a/crates/oxc_linter/src/rules/oxc/no_async_endpoint_handlers.rs +++ b/crates/oxc_linter/src/rules/oxc/no_async_endpoint_handlers.rs @@ -7,7 +7,7 @@ use oxc_ast::{ }; use oxc_diagnostics::{LabeledSpan, OxcDiagnostic}; use oxc_macros::declare_oxc_lint; -use oxc_span::{CompactStr, Span}; +use oxc_span::{CompactStr, Ident, Span}; use rustc_hash::FxHashSet; use schemars::JsonSchema; use serde_json::Value; @@ -273,7 +273,7 @@ impl NoAsyncEndpointHandlers { return; } - let name = f.name().map(|n| n.as_str()).or(id_name); + let name = f.name().map(Ident::as_str).or(id_name); if name.is_some_and(|name| self.is_allowed_name(name)) { return; } diff --git a/crates/oxc_linter/src/rules/react/exhaustive_deps.rs b/crates/oxc_linter/src/rules/react/exhaustive_deps.rs index b110ccf742e19..ce59f288fe033 100644 --- a/crates/oxc_linter/src/rules/react/exhaustive_deps.rs +++ b/crates/oxc_linter/src/rules/react/exhaustive_deps.rs @@ -20,7 +20,7 @@ use oxc_ast_visit::{Visit, walk::walk_function_body}; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::{ReferenceId, ScopeId, Semantic, SymbolId}; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{Atom, GetSpan, Ident, Span}; use crate::{ AstNode, @@ -770,7 +770,9 @@ impl ExhaustiveDeps { } } -fn get_node_name_without_react_namespace<'a, 'b>(expr: &'b Expression<'a>) -> Option<&'b Atom<'a>> { +fn get_node_name_without_react_namespace<'a, 'b>( + expr: &'b Expression<'a>, +) -> Option<&'b Ident<'a>> { match expr { Expression::StaticMemberExpression(member) => { if let Expression::Identifier(_ident) = &member.object { @@ -865,7 +867,7 @@ fn analyze_property_chain<'a, 'b>( match expr.get_inner_expression() { Expression::Identifier(ident) => Ok(Some(Dependency { span: ident.span(), - name: ident.name, + name: ident.name.as_atom(), reference_id: ident.reference_id(), chain: vec![], symbol_id: semantic.scoping().get_reference(ident.reference_id()).symbol_id(), @@ -889,7 +891,7 @@ fn concat_members<'a, 'b>( return Ok(None); }; - let new_chain = Vec::from([member_expr.property.name]); + let new_chain = Vec::from([member_expr.property.name.as_atom()]); Ok(Some(Dependency { span: member_expr.span, @@ -1157,7 +1159,7 @@ fn is_function_stable<'a, 'b>( // https://github.com/facebook/react/blob/fee786a057774ab687aff765345dd86fce534ab2/packages/eslint-plugin-react-hooks/src/ExhaustiveDeps.js#L1742 fn func_call_without_react_namespace<'a>( call_expr: &'a CallExpression<'a>, -) -> Option<&'a Atom<'a>> { +) -> Option<&'a Ident<'a>> { let inner_exp = call_expr.callee.get_inner_expression(); if let Expression::Identifier(ident) = inner_exp { @@ -1353,7 +1355,7 @@ impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> { if is_parent_call_expr { self.found_dependencies.insert(source); } else { - let new_chain = Vec::from([it.property.name]); + let new_chain = Vec::from([it.property.name.as_atom()]); let mut destructured_props: Vec> = vec![]; let mut did_see_ref = false; @@ -1434,7 +1436,7 @@ impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> { .unwrap_or(true); if needs_full_identifier || (destructured_props.is_empty() && !did_see_ref) { self.found_dependencies.insert(Dependency { - name: ident.name, + name: ident.name.as_atom(), reference_id, span: ident.span, chain: vec![], @@ -1443,7 +1445,7 @@ impl<'a> Visit<'a> for ExhaustiveDepsVisitor<'a, '_> { } else { for prop in destructured_props { self.found_dependencies.insert(Dependency { - name: ident.name, + name: ident.name.as_atom(), reference_id, span: ident.span, chain: vec![prop], @@ -1518,7 +1520,7 @@ mod fix { AstBuilder, ast::{ArrayExpression, Expression}, }; - use oxc_span::{Atom, GetSpan, SPAN}; + use oxc_span::{GetSpan, Ident, SPAN}; use crate::{ fixer::{RuleFix, RuleFixer}, @@ -1540,7 +1542,7 @@ mod fix { for name in names { vec.push( ast_builder - .expression_identifier(SPAN, Atom::from_cow_in(&name.name, &alloc)) + .expression_identifier(SPAN, Ident::from_cow_in(&name.name, &alloc)) .into(), ); } diff --git a/crates/oxc_linter/src/rules/react/forbid_elements.rs b/crates/oxc_linter/src/rules/react/forbid_elements.rs index e817bbb21e93e..6c44d86642383 100644 --- a/crates/oxc_linter/src/rules/react/forbid_elements.rs +++ b/crates/oxc_linter/src/rules/react/forbid_elements.rs @@ -108,7 +108,7 @@ impl Rule for ForbidElements { match argument { Argument::Identifier(it) => { - if !is_valid_identifier(&it.name) { + if !is_valid_identifier(&it.name.as_atom()) { return; } self.add_diagnostic_if_invalid_element( 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 86201861d4527..14803cb420087 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 @@ -69,7 +69,7 @@ impl Rule for JsxNoDuplicateProps { continue; }; - if let Some(old_span) = props.insert(ident.name, ident.span) { + if let Some(old_span) = props.insert(ident.name.as_atom(), ident.span) { ctx.diagnostic(jsx_no_duplicate_props_diagnostic( ident.name.as_str(), old_span, diff --git a/crates/oxc_linter/src/rules/react/jsx_props_no_spread_multi.rs b/crates/oxc_linter/src/rules/react/jsx_props_no_spread_multi.rs index 97a47f881fd7d..c7f03956c124e 100644 --- a/crates/oxc_linter/src/rules/react/jsx_props_no_spread_multi.rs +++ b/crates/oxc_linter/src/rules/react/jsx_props_no_spread_multi.rs @@ -81,10 +81,10 @@ impl Rule for JsxPropsNoSpreadMulti { argument_without_parenthesized.get_identifier_reference().map(|arg| arg.name) { identifier_names - .entry(identifier_name) + .entry(identifier_name.as_atom()) .and_modify(|first_span| { duplicate_spreads - .entry(identifier_name) + .entry(identifier_name.as_atom()) .or_insert_with(|| vec![*first_span]) .push(spread_attr.span); }) diff --git a/crates/oxc_linter/src/rules/react/no_danger_with_children.rs b/crates/oxc_linter/src/rules/react/no_danger_with_children.rs index 7c9b33e7f4acf..4d546f352ddeb 100644 --- a/crates/oxc_linter/src/rules/react/no_danger_with_children.rs +++ b/crates/oxc_linter/src/rules/react/no_danger_with_children.rs @@ -4,7 +4,7 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::Span; +use oxc_span::{Ident, Span}; use crate::{AstNode, context::LintContext, rule::Rule}; @@ -270,7 +270,7 @@ fn has_jsx_prop(ctx: &LintContext, node: &AstNode, prop_name: &'static str) -> b let Some(ident) = attr.argument.get_identifier_reference() else { return false; }; - does_object_var_have_prop_name(ctx, node, ident.name.as_str(), prop_name) + does_object_var_have_prop_name(ctx, node, &ident.name, prop_name) } }) } @@ -280,7 +280,7 @@ fn has_jsx_prop(ctx: &LintContext, node: &AstNode, prop_name: &'static str) -> b fn does_object_var_have_prop_name( ctx: &LintContext, node: &AstNode, - name: &str, + name: &Ident, prop_name: &str, ) -> bool { let Some(symbol) = &find_var_in_scope(ctx, node, name) else { @@ -309,13 +309,13 @@ fn does_object_var_have_prop_name( }; // If the next symbol is the same as the current symbol, then there is a cycle, // for example: `const props = {...props}`, so we will stop searching. - if let Some(next_symbol) = find_var_in_scope(ctx, node, ident.name.as_str()) + if let Some(next_symbol) = find_var_in_scope(ctx, node, &ident.name) && next_symbol.id() == symbol.id() { return false; } - does_object_var_have_prop_name(ctx, symbol, ident.name.as_str(), prop_name) + does_object_var_have_prop_name(ctx, symbol, &ident.name, prop_name) } }) } @@ -324,7 +324,7 @@ fn does_object_var_have_prop_name( fn find_var_in_scope<'c>( ctx: &'c LintContext, node: &AstNode, - name: &str, + name: &Ident, ) -> Option<&'c AstNode<'c>> { ctx.scoping() .find_binding(node.scope_id(), name) diff --git a/crates/oxc_linter/src/rules/react/react_in_jsx_scope.rs b/crates/oxc_linter/src/rules/react/react_in_jsx_scope.rs index 66181d0b69f6a..643828196819b 100644 --- a/crates/oxc_linter/src/rules/react/react_in_jsx_scope.rs +++ b/crates/oxc_linter/src/rules/react/react_in_jsx_scope.rs @@ -1,7 +1,7 @@ use oxc_ast::AstKind; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::{GetSpan, Span}; +use oxc_span::{GetSpan, Ident, Span}; use crate::{ AstNode, @@ -64,7 +64,7 @@ impl Rule for ReactInJsxScope { _ => return, }; let scope = ctx.scoping(); - let react_name = "React"; + let react_name = &Ident::new("React"); if scope.get_binding(scope.root_scope_id(), react_name).is_some() { return; } 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 ac93c937f7181..1b8527507b326 100644 --- a/crates/oxc_linter/src/rules/typescript/adjacent_overload_signatures.rs +++ b/crates/oxc_linter/src/rules/typescript/adjacent_overload_signatures.rs @@ -188,7 +188,7 @@ impl GetMethod for ModuleDeclaration<'_> { FunctionType::FunctionDeclaration | FunctionType::TSDeclareFunction ) { func_decl.id.as_ref().map(|id| Method { - name: id.name.to_compact_str(), + name: id.name.into(), r#static: false, call_signature: false, kind: MethodKind::Normal, @@ -204,7 +204,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.to_compact_str(), + name: id.name.into(), r#static: false, call_signature: false, kind: MethodKind::Normal, @@ -227,7 +227,7 @@ impl GetMethod for Declaration<'_> { FunctionType::FunctionDeclaration | FunctionType::TSDeclareFunction ) { func_decl.id.as_ref().map(|id| Method { - name: id.name.to_compact_str(), + name: id.name.into(), r#static: false, call_signature: false, kind: MethodKind::Normal, diff --git a/crates/oxc_linter/src/rules/typescript/explicit_module_boundary_types.rs b/crates/oxc_linter/src/rules/typescript/explicit_module_boundary_types.rs index 7a26beaa93d30..9f3464bad224b 100644 --- a/crates/oxc_linter/src/rules/typescript/explicit_module_boundary_types.rs +++ b/crates/oxc_linter/src/rules/typescript/explicit_module_boundary_types.rs @@ -9,7 +9,7 @@ use oxc_ast_visit::{ use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::ScopeFlags; -use oxc_span::{CompactStr, GetSpan, Span}; +use oxc_span::{CompactStr, GetSpan, Ident, Span}; use rustc_hash::FxHashMap; use schemars::JsonSchema; use serde::Deserialize; @@ -87,8 +87,8 @@ impl ExplicitModuleBoundaryTypesConfig { self.allowed_names.iter().any(|n| n == name) } - fn is_some_allowed_name>(&self, name: Option) -> bool { - name.is_some_and(|name| self.is_allowed_name(name.as_ref())) + fn is_some_allowed_name(&self, name: Option<&str>) -> bool { + name.is_some_and(|name| self.is_allowed_name(name)) } } @@ -341,7 +341,7 @@ impl<'a, 'c> ExplicitTypesChecker<'a, 'c> { return false; }; if let Some(Cow::Borrowed(name)) = id.static_name() { - self.target_symbol.replace(IdentifierName { name: Atom::from(name), span: id.span() }); + self.target_symbol.replace(IdentifierName { name: Ident::new(name), span: id.span() }); true } else { false @@ -362,7 +362,7 @@ impl<'a, 'c> ExplicitTypesChecker<'a, 'c> { #[expect(clippy::cast_possible_truncation)] let span = target_span.map_or(Span::sized(func.span.start, "function".len() as u32), |t| t.span); - let is_allowed = || self.rule.is_some_allowed_name(func.name().or(target_name)); + let is_allowed = || self.rule.is_some_allowed_name(func.name().or(target_name).as_deref()); // When allow_overload_functions is enabled, skip return type checking for all functions // This is a simplified implementation - a proper implementation would only skip @@ -399,7 +399,7 @@ impl<'a, 'c> ExplicitTypesChecker<'a, 'c> { let target_span = self.target_symbol.as_ref(); let target_name = target_span.map(|t| t.name); let span = target_span.map_or(arrow.params.span, |t| t.span); - let is_allowed = || self.rule.is_some_allowed_name(target_name); + let is_allowed = || self.rule.is_some_allowed_name(target_name.as_deref()); if !self.rule.allow_higher_order_functions { if !is_allowed() { @@ -581,7 +581,7 @@ impl<'a> Visit<'a> for ExplicitTypesChecker<'a, '_> { { return; } - if self.rule.is_some_allowed_name(el.static_name()) { + if self.rule.is_some_allowed_name(el.static_name().as_deref()) { return; } diff --git a/crates/oxc_linter/src/rules/typescript/no_require_imports.rs b/crates/oxc_linter/src/rules/typescript/no_require_imports.rs index 91c91b6893bbf..b977f5ffc67ac 100644 --- a/crates/oxc_linter/src/rules/typescript/no_require_imports.rs +++ b/crates/oxc_linter/src/rules/typescript/no_require_imports.rs @@ -178,7 +178,11 @@ impl Rule for NoRequireImports { } } - if ctx.scoping().find_binding(ctx.scoping().root_scope_id(), "require").is_some() { + if ctx + .scoping() + .find_binding(ctx.scoping().root_scope_id(), &oxc_span::Ident::new("require")) + .is_some() + { return; } diff --git a/crates/oxc_linter/src/rules/typescript/no_unnecessary_parameter_property_assignment.rs b/crates/oxc_linter/src/rules/typescript/no_unnecessary_parameter_property_assignment.rs index 1fef9f0d3b2e1..55e48954d36b5 100644 --- a/crates/oxc_linter/src/rules/typescript/no_unnecessary_parameter_property_assignment.rs +++ b/crates/oxc_linter/src/rules/typescript/no_unnecessary_parameter_property_assignment.rs @@ -232,7 +232,7 @@ fn get_property_name<'a>(assignment_target: &AssignmentTarget<'a>) -> Option { // this.property - Some(expr.property.name) + Some(expr.property.name.as_atom()) } AssignmentTarget::ComputedMemberExpression(expr) if matches!(&expr.object, Expression::ThisExpression(_)) => diff --git a/crates/oxc_linter/src/rules/unicorn/consistent_function_scoping.rs b/crates/oxc_linter/src/rules/unicorn/consistent_function_scoping.rs index 6eaef4929582b..edbf4c5387782 100644 --- a/crates/oxc_linter/src/rules/unicorn/consistent_function_scoping.rs +++ b/crates/oxc_linter/src/rules/unicorn/consistent_function_scoping.rs @@ -5,7 +5,7 @@ use oxc_ast_visit::{Visit, walk}; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; use oxc_semantic::{ReferenceId, ScopeFlags, ScopeId, SymbolId}; -use oxc_span::{Atom, GetSpan, Span}; +use oxc_span::{GetSpan, Ident, Span}; use schemars::JsonSchema; use serde::Deserialize; @@ -21,7 +21,7 @@ fn consistent_function_scoping( fn_span: Span, parent_scope_span: Option, parent_scope_kind: Option<&'static str>, - function_name: Option>, + function_name: Option>, ) -> OxcDiagnostic { let function_label = if let Some(name) = function_name { format!("Function `{name}` does not capture any variables from its parent scope") diff --git a/crates/oxc_linter/src/rules/unicorn/prefer_global_this.rs b/crates/oxc_linter/src/rules/unicorn/prefer_global_this.rs index beb1f738ec47b..34a063a93fc83 100644 --- a/crates/oxc_linter/src/rules/unicorn/prefer_global_this.rs +++ b/crates/oxc_linter/src/rules/unicorn/prefer_global_this.rs @@ -64,7 +64,7 @@ impl Rule for PreferGlobalThis { if !matches!(ident.name.as_str(), "window" | "self" | "global") || is_computed_member_expression_object(node, ctx) - || !ctx.scoping().root_unresolved_references().contains_key(&ident.name.as_str()) + || !ctx.scoping().root_unresolved_references().contains_key(&ident.name) { return; } diff --git a/crates/oxc_linter/src/rules/vue/no_import_compiler_macros.rs b/crates/oxc_linter/src/rules/vue/no_import_compiler_macros.rs index 2a1ad4c075328..d86acd8bd5b2f 100644 --- a/crates/oxc_linter/src/rules/vue/no_import_compiler_macros.rs +++ b/crates/oxc_linter/src/rules/vue/no_import_compiler_macros.rs @@ -4,17 +4,17 @@ use oxc_ast::{ }; use oxc_diagnostics::OxcDiagnostic; use oxc_macros::declare_oxc_lint; -use oxc_span::{Atom, Span}; +use oxc_span::Span; use crate::{AstNode, context::LintContext, frameworks::FrameworkOptions, rule::Rule}; -fn no_import_compiler_macros_diagnostic(span: Span, name: &Atom) -> OxcDiagnostic { +fn no_import_compiler_macros_diagnostic(span: Span, name: &str) -> OxcDiagnostic { OxcDiagnostic::warn(format!("'{name}' is a compiler macro and doesn't need to be imported.")) .with_help("Remove the import statement for this macro.") .with_label(span) } -fn invalid_import_compiler_macros_diagnostic(span: Span, name: &Atom) -> OxcDiagnostic { +fn invalid_import_compiler_macros_diagnostic(span: Span, name: &str) -> OxcDiagnostic { OxcDiagnostic::warn(format!( "'{name}' is a compiler macro and can't be imported outside of `