mirror of
https://github.com/oxc-project/oxc.git
synced 2026-11-04 10:29:58 +00:00
feat(rust): oxc-index-vec v4.0 (#14254)
Closes https://github.com/oxc-project/backlog/issues/109 Also did a bunch of macro stuff to reduce the boilerplates.
This commit is contained in:
1 parent
ee4546f379
commit
3656908d0e
26 files changed
+134
-323
No files matched your search
Generated
+9
-13
@@ -715,7 +715,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1201,7 +1201,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "4b0f83760fb341a774ed326568e19f5a863af4a952def8c39f9ab92fd95b88e5"
|
||||
dependencies = [
|
||||
"equivalent",
|
||||
"hashbrown 0.15.5",
|
||||
"hashbrown 0.16.0",
|
||||
"rayon",
|
||||
"serde",
|
||||
"serde_core",
|
||||
@@ -1835,7 +1835,6 @@ version = "0.93.0"
|
||||
dependencies = [
|
||||
"bitflags 2.9.4",
|
||||
"itertools",
|
||||
"nonmax",
|
||||
"oxc_index",
|
||||
"oxc_syntax",
|
||||
"petgraph",
|
||||
@@ -1851,7 +1850,6 @@ dependencies = [
|
||||
"dragonbox_ecma",
|
||||
"insta",
|
||||
"itoa",
|
||||
"nonmax",
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
"oxc_data_structures",
|
||||
@@ -1973,10 +1971,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "oxc_index"
|
||||
version = "3.1.0"
|
||||
version = "4.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "967ae797e1f284bd1385f2d8e8ab94293ad27f623c76839ecf66827521365f5b"
|
||||
checksum = "eb3e6120999627ec9703025eab7c9f410ebb7e95557632a8902ca48210416c2b"
|
||||
dependencies = [
|
||||
"nonmax",
|
||||
"serde",
|
||||
]
|
||||
|
||||
@@ -2041,7 +2040,6 @@ dependencies = [
|
||||
"lazy-regex",
|
||||
"markdown",
|
||||
"memchr",
|
||||
"nonmax",
|
||||
"oxc-schemars",
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
@@ -2102,7 +2100,6 @@ dependencies = [
|
||||
"oxc_allocator",
|
||||
"oxc_ast",
|
||||
"oxc_data_structures",
|
||||
"oxc_index",
|
||||
"oxc_parser",
|
||||
"oxc_semantic",
|
||||
"oxc_span",
|
||||
@@ -2236,7 +2233,6 @@ dependencies = [
|
||||
"napi-derive",
|
||||
"oxc",
|
||||
"oxc_formatter",
|
||||
"oxc_index",
|
||||
"oxc_linter",
|
||||
"oxc_napi",
|
||||
"oxc_transformer_plugins",
|
||||
@@ -2928,7 +2924,7 @@ dependencies = [
|
||||
"errno",
|
||||
"libc",
|
||||
"linux-raw-sys",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3032,7 +3028,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5b55fb86dfd3a2f5f76ea78310a88f96c4ea21a3031f8d212443d56123fd0521"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3293,7 +3289,7 @@ dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"once_cell",
|
||||
"rustix",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3801,7 +3797,7 @@ version = "0.1.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c2a7b1c03c876122aa43f3020e6c3c3ee5c05081c9a00739faf7503aeba10d22"
|
||||
dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.61.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
||||
+1
-1
@@ -158,7 +158,7 @@ unicode-id-start = "1"
|
||||
javascript-globals = "1"
|
||||
json-strip-comments = "3"
|
||||
oxc-browserslist = "2"
|
||||
oxc_index = "3"
|
||||
oxc_index = { version = "4", features = ["nonmax", "serde"] }
|
||||
oxc_resolver = "11"
|
||||
oxc_sourcemap = "4"
|
||||
|
||||
|
||||
@@ -26,6 +26,5 @@ oxc_syntax = { workspace = true }
|
||||
|
||||
bitflags = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
nonmax = { workspace = true }
|
||||
petgraph = { workspace = true, default-features = false, features = ["std", "stable_graph"] }
|
||||
rustc-hash = { workspace = true }
|
||||
@@ -45,7 +45,7 @@ impl DisplayDot for ControlFlowGraph {
|
||||
let block = &self.basic_blocks[*node.1];
|
||||
let mut attrs = Attrs::default().with("label", block.display_dot());
|
||||
|
||||
if *node.1 == 0 {
|
||||
if node.1.index() == 0 {
|
||||
attrs += ("color", "green");
|
||||
}
|
||||
if block.is_unreachable() {
|
||||
|
||||
@@ -6,8 +6,7 @@ pub mod visit;
|
||||
use std::fmt;
|
||||
|
||||
use itertools::Itertools;
|
||||
use nonmax::NonMaxU32;
|
||||
use oxc_index::{Idx, IndexVec};
|
||||
use oxc_index::{IndexVec, define_nonmax_u32_index_type};
|
||||
use petgraph::{
|
||||
Direction,
|
||||
visit::{Control, DfsEvent, EdgeRef},
|
||||
@@ -28,20 +27,9 @@ pub use dot::DisplayDot;
|
||||
use visit::set_depth_first_search;
|
||||
|
||||
pub type BlockNodeId = petgraph::stable_graph::NodeIndex;
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct BasicBlockId(NonMaxU32);
|
||||
|
||||
impl Idx for BasicBlockId {
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
assert!(idx < u32::MAX as usize);
|
||||
// SAFETY: We just checked `idx` is valid for `NonMaxU32`
|
||||
Self(unsafe { NonMaxU32::new_unchecked(idx as u32) })
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize
|
||||
}
|
||||
define_nonmax_u32_index_type! {
|
||||
pub struct BasicBlockId;
|
||||
}
|
||||
|
||||
impl PartialEq<u32> for BasicBlockId {
|
||||
|
||||
@@ -33,7 +33,6 @@ bitflags = { workspace = true }
|
||||
cow-utils = { workspace = true }
|
||||
dragonbox_ecma = { workspace = true }
|
||||
itoa = { workspace = true }
|
||||
nonmax = { workspace = true }
|
||||
rustc-hash = { workspace = true }
|
||||
|
||||
[dev-dependencies]
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
use std::path::Path;
|
||||
|
||||
use nonmax::NonMaxU32;
|
||||
|
||||
use oxc_index::{Idx, IndexVec};
|
||||
use oxc_index::{IndexVec, define_nonmax_u32_index_type};
|
||||
use oxc_span::Span;
|
||||
use oxc_syntax::identifier::{LS, PS};
|
||||
|
||||
@@ -11,21 +9,9 @@ use crate::str::{LS_LAST_2_BYTES, LS_OR_PS_FIRST_BYTE, PS_LAST_2_BYTES};
|
||||
/// Number of lines to check with linear search when translating byte position to line index
|
||||
const LINE_SEARCH_LINEAR_ITERATIONS: usize = 16;
|
||||
|
||||
/// Index into vec of `ColumnOffsets`
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct ColumnOffsetsId(NonMaxU32);
|
||||
|
||||
impl Idx for ColumnOffsetsId {
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
assert!(idx < u32::MAX as usize);
|
||||
// SAFETY: We just checked `idx` is a legal value for `NonMaxU32`
|
||||
Self(unsafe { NonMaxU32::new_unchecked(idx as u32) })
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize
|
||||
}
|
||||
define_nonmax_u32_index_type! {
|
||||
/// Index into vec of `ColumnOffsets`
|
||||
struct ColumnOffsetsId;
|
||||
}
|
||||
|
||||
/// Line offset tables.
|
||||
|
||||
@@ -35,7 +35,7 @@ oxc_codegen = { workspace = true }
|
||||
oxc_data_structures = { workspace = true, features = ["box_macros"] }
|
||||
oxc_diagnostics = { workspace = true }
|
||||
oxc_ecmascript = { workspace = true }
|
||||
oxc_index = { workspace = true, features = ["serde"] }
|
||||
oxc_index = { workspace = true }
|
||||
oxc_macros = { workspace = true, features = ["ruledocs"] }
|
||||
oxc_parser = { workspace = true }
|
||||
oxc_regular_expression = { workspace = true }
|
||||
@@ -59,7 +59,6 @@ json-strip-comments = { workspace = true }
|
||||
language-tags = { workspace = true }
|
||||
lazy-regex = { workspace = true }
|
||||
memchr = { workspace = true }
|
||||
nonmax = { workspace = true }
|
||||
papaya = { workspace = true }
|
||||
phf = { workspace = true, features = ["macros"] }
|
||||
rayon = { workspace = true }
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
use nonmax::NonMaxU32;
|
||||
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_index::{Idx, IndexVec};
|
||||
use oxc_index::{IndexVec, define_nonmax_u32_index_type};
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_regular_expression::{
|
||||
ast::LookAroundAssertionKind,
|
||||
@@ -117,20 +115,8 @@ enum BackRefInfoTarget<'a> {
|
||||
Name(&'a str),
|
||||
}
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||
pub struct RegexNodeId(NonMaxU32);
|
||||
|
||||
impl Idx for RegexNodeId {
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
assert!(idx < u32::MAX as usize);
|
||||
// SAFETY: We just checked `idx` is valid for `NonMaxU32`
|
||||
Self(unsafe { NonMaxU32::new_unchecked(idx as u32) })
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize
|
||||
}
|
||||
define_nonmax_u32_index_type! {
|
||||
pub struct RegexNodeId;
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
use oxc_ast::{AstKind, ast::Expression};
|
||||
use oxc_diagnostics::OxcDiagnostic;
|
||||
use oxc_index::Idx;
|
||||
use oxc_macros::declare_oxc_lint;
|
||||
use oxc_span::Span;
|
||||
use rustc_hash::FxHashMap;
|
||||
@@ -500,7 +499,7 @@ fn test() {
|
||||
(
|
||||
" test('should pass', async () => {
|
||||
expect.hasAssertions();
|
||||
|
||||
|
||||
expect(true).toBeDefined();
|
||||
expect(true).toBeDefined();
|
||||
expect(true).toBeDefined();
|
||||
|
||||
@@ -7,7 +7,6 @@ use oxc_ast::{
|
||||
match_member_expression,
|
||||
},
|
||||
};
|
||||
use oxc_index::Idx;
|
||||
use oxc_semantic::{AstNode, ReferenceId, Semantic, SymbolId};
|
||||
use oxc_span::CompactStr;
|
||||
|
||||
|
||||
@@ -24,7 +24,6 @@ doctest = false
|
||||
oxc_allocator = { workspace = true, features = ["bitset"] }
|
||||
oxc_ast = { workspace = true }
|
||||
oxc_data_structures = { workspace = true, features = ["inline_string"] }
|
||||
oxc_index = { workspace = true }
|
||||
oxc_semantic = { workspace = true }
|
||||
oxc_span = { workspace = true }
|
||||
oxc_syntax = { workspace = true }
|
||||
|
||||
@@ -8,7 +8,6 @@ use base54::base54;
|
||||
use oxc_allocator::{Allocator, BitSet, Vec};
|
||||
use oxc_ast::ast::{Declaration, Program, Statement};
|
||||
use oxc_data_structures::inline_string::InlineString;
|
||||
use oxc_index::Idx;
|
||||
use oxc_semantic::{AstNodes, Scoping, Semantic, SemanticBuilder, SymbolId};
|
||||
use oxc_span::{Atom, CompactStr};
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@ use rustc_hash::{FxHashMap, FxHashSet};
|
||||
use self_cell::self_cell;
|
||||
|
||||
use oxc_allocator::{Allocator, CloneIn, FromIn, HashMap as ArenaHashMap, Vec as ArenaVec};
|
||||
use oxc_index::{Idx, IndexVec};
|
||||
use oxc_index::IndexVec;
|
||||
use oxc_span::{Atom, Span};
|
||||
use oxc_syntax::{
|
||||
node::NodeId,
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
use std::{fs, path::Path};
|
||||
|
||||
use oxc_allocator::Allocator;
|
||||
use oxc_index::Idx;
|
||||
use oxc_parser::Parser;
|
||||
use oxc_semantic::{ScopeId, Semantic, SemanticBuilder};
|
||||
use oxc_span::SourceType;
|
||||
|
||||
@@ -42,7 +42,6 @@ to_js_string = ["dep:dragonbox_ecma"]
|
||||
serialize = [
|
||||
"bitflags/serde",
|
||||
"dep:serde",
|
||||
"oxc_index/serde",
|
||||
"oxc_estree/serialize",
|
||||
]
|
||||
|
||||
|
||||
@@ -1,41 +1,25 @@
|
||||
//! Comment Node ID.
|
||||
|
||||
use oxc_index::Idx;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Serialize, Serializer};
|
||||
use oxc_index::define_index_type;
|
||||
|
||||
use oxc_allocator::{Allocator, CloneIn, Dummy};
|
||||
use oxc_ast_macros::ast;
|
||||
|
||||
/// Comment Node ID.
|
||||
#[ast]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[generate_derive(CloneIn)]
|
||||
#[clone_in(default)]
|
||||
#[content_eq(skip)]
|
||||
#[estree(skip)]
|
||||
pub struct CommentNodeId(u32);
|
||||
define_index_type! {
|
||||
/// Comment Node ID.
|
||||
#[ast]
|
||||
#[generate_derive(CloneIn)]
|
||||
#[clone_in(default)]
|
||||
#[content_eq(skip)]
|
||||
#[estree(skip)]
|
||||
pub struct CommentNodeId = u32;
|
||||
}
|
||||
|
||||
impl CommentNodeId {
|
||||
/// Mock comment node ID.
|
||||
///
|
||||
/// This is used for synthetically-created AST nodes, among other things.
|
||||
pub const DUMMY: Self = CommentNodeId::new(0);
|
||||
|
||||
/// Create `CommentNodeId` from `u32`.
|
||||
pub const fn new(idx: u32) -> Self {
|
||||
Self(idx)
|
||||
}
|
||||
}
|
||||
|
||||
impl Idx for CommentNodeId {
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
Self(u32::try_from(idx).expect("`idx` is greater than `u32::MAX`"))
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0 as usize
|
||||
}
|
||||
}
|
||||
|
||||
impl Default for CommentNodeId {
|
||||
@@ -51,10 +35,3 @@ impl<'a> Dummy<'a> for CommentNodeId {
|
||||
Self::DUMMY
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl Serialize for CommentNodeId {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_u32(self.0)
|
||||
}
|
||||
}
|
||||
@@ -1,13 +1,11 @@
|
||||
//! AST Node ID and flags.
|
||||
use bitflags::bitflags;
|
||||
use nonmax::NonMaxU32;
|
||||
use oxc_index::Idx;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Serialize, Serializer};
|
||||
use oxc_index::define_nonmax_u32_index_type;
|
||||
|
||||
/// AST Node ID
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct NodeId(NonMaxU32);
|
||||
define_nonmax_u32_index_type! {
|
||||
/// AST Node ID
|
||||
pub struct NodeId;
|
||||
}
|
||||
|
||||
impl NodeId {
|
||||
/// Mock node id.
|
||||
@@ -17,46 +15,6 @@ impl NodeId {
|
||||
|
||||
/// Node id of the Program node.
|
||||
pub const ROOT: Self = NodeId::new(0);
|
||||
|
||||
/// Create `NodeId` from `u32`.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `idx` is `u32::MAX`.
|
||||
pub const fn new(idx: u32) -> Self {
|
||||
if let Some(idx) = NonMaxU32::new(idx) {
|
||||
return Self(idx);
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
|
||||
/// Create `NodeId` from `u32` unchecked.
|
||||
///
|
||||
/// # SAFETY
|
||||
/// `idx` must not be `u32::MAX`.
|
||||
pub const unsafe fn new_unchecked(idx: u32) -> Self {
|
||||
// SAFETY: Caller must ensure `idx` is not `u32::MAX`
|
||||
unsafe { Self(NonMaxU32::new_unchecked(idx)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Idx for NodeId {
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
assert!(idx < u32::MAX as usize);
|
||||
// SAFETY: We just checked `idx` is a legal value for `NonMaxU32`
|
||||
Self(unsafe { NonMaxU32::new_unchecked(idx as u32) })
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl Serialize for NodeId {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_u32(self.0.get())
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
#![expect(missing_docs)] // fixme
|
||||
use bitflags::bitflags;
|
||||
use nonmax::NonMaxU32;
|
||||
use oxc_index::Idx;
|
||||
use oxc_index::define_nonmax_u32_index_type;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Serialize, Serializer};
|
||||
use serde::Serialize;
|
||||
|
||||
use oxc_allocator::{Allocator, CloneIn};
|
||||
|
||||
@@ -11,25 +10,13 @@ use crate::{node::NodeId, symbol::SymbolId};
|
||||
|
||||
use oxc_ast_macros::ast;
|
||||
|
||||
#[ast]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[builder(default)]
|
||||
#[clone_in(default)]
|
||||
#[content_eq(skip)]
|
||||
#[estree(skip)]
|
||||
pub struct ReferenceId(NonMaxU32);
|
||||
|
||||
impl Idx for ReferenceId {
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
assert!(idx < u32::MAX as usize);
|
||||
// SAFETY: We just checked `idx` is a legal value for `NonMaxU32`
|
||||
Self(unsafe { NonMaxU32::new_unchecked(idx as u32) })
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize
|
||||
}
|
||||
define_nonmax_u32_index_type! {
|
||||
#[ast]
|
||||
#[builder(default)]
|
||||
#[clone_in(default)]
|
||||
#[content_eq(skip)]
|
||||
#[estree(skip)]
|
||||
pub struct ReferenceId;
|
||||
}
|
||||
|
||||
impl<'alloc> CloneIn<'alloc> for ReferenceId {
|
||||
@@ -47,13 +34,6 @@ impl<'alloc> CloneIn<'alloc> for ReferenceId {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl Serialize for ReferenceId {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_u32(self.0.get())
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
/// Describes how a symbol is being referenced in the AST.
|
||||
///
|
||||
|
||||
@@ -1,54 +1,17 @@
|
||||
#![expect(missing_docs)] // fixme
|
||||
use bitflags::bitflags;
|
||||
use nonmax::NonMaxU32;
|
||||
use oxc_allocator::{Allocator, CloneIn};
|
||||
use oxc_index::Idx;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Serialize, Serializer};
|
||||
use oxc_index::define_nonmax_u32_index_type;
|
||||
|
||||
use oxc_ast_macros::ast;
|
||||
|
||||
#[ast]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[builder(default)]
|
||||
#[clone_in(default)]
|
||||
#[content_eq(skip)]
|
||||
#[estree(skip)]
|
||||
pub struct ScopeId(NonMaxU32);
|
||||
|
||||
impl ScopeId {
|
||||
/// Create `ScopeId` from `u32`.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `idx` is `u32::MAX`.
|
||||
pub const fn new(idx: u32) -> Self {
|
||||
if let Some(idx) = NonMaxU32::new(idx) {
|
||||
return Self(idx);
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
|
||||
/// Create `ScopeId` from `u32` unchecked.
|
||||
///
|
||||
/// # SAFETY
|
||||
/// `idx` must not be `u32::MAX`.
|
||||
pub const unsafe fn new_unchecked(idx: u32) -> Self {
|
||||
// SAFETY: Caller must ensure `idx` is not `u32::MAX`
|
||||
unsafe { Self(NonMaxU32::new_unchecked(idx)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Idx for ScopeId {
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
assert!(idx < u32::MAX as usize);
|
||||
// SAFETY: We just checked `idx` is a legal value for `NonMaxU32`
|
||||
Self(unsafe { NonMaxU32::new_unchecked(idx as u32) })
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize
|
||||
}
|
||||
define_nonmax_u32_index_type! {
|
||||
#[ast]
|
||||
#[builder(default)]
|
||||
#[clone_in(default)]
|
||||
#[content_eq(skip)]
|
||||
#[estree(skip)]
|
||||
pub struct ScopeId;
|
||||
}
|
||||
|
||||
impl<'alloc> CloneIn<'alloc> for ScopeId {
|
||||
@@ -66,13 +29,6 @@ impl<'alloc> CloneIn<'alloc> for ScopeId {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl Serialize for ScopeId {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_u32(self.0.get())
|
||||
}
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
|
||||
pub struct ScopeFlags: u16 {
|
||||
|
||||
@@ -1,54 +1,19 @@
|
||||
#![expect(missing_docs)] // fixme
|
||||
use bitflags::bitflags;
|
||||
use nonmax::NonMaxU32;
|
||||
use oxc_allocator::{Allocator, CloneIn};
|
||||
use oxc_index::Idx;
|
||||
use oxc_index::define_nonmax_u32_index_type;
|
||||
#[cfg(feature = "serialize")]
|
||||
use serde::{Serialize, Serializer};
|
||||
use serde::Serialize;
|
||||
|
||||
use oxc_ast_macros::ast;
|
||||
|
||||
#[ast]
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
#[builder(default)]
|
||||
#[clone_in(default)]
|
||||
#[content_eq(skip)]
|
||||
#[estree(skip)]
|
||||
pub struct SymbolId(NonMaxU32);
|
||||
|
||||
impl SymbolId {
|
||||
/// Create `SymbolId` from `u32`.
|
||||
///
|
||||
/// # Panics
|
||||
/// Panics if `idx` is `u32::MAX`.
|
||||
pub const fn new(idx: u32) -> Self {
|
||||
if let Some(idx) = NonMaxU32::new(idx) {
|
||||
return Self(idx);
|
||||
}
|
||||
panic!();
|
||||
}
|
||||
|
||||
/// Create `SymbolId` from `u32` unchecked.
|
||||
///
|
||||
/// # SAFETY
|
||||
/// `idx` must not be `u32::MAX`.
|
||||
pub const unsafe fn new_unchecked(idx: u32) -> Self {
|
||||
// SAFETY: Caller must ensure `idx` is not `u32::MAX`
|
||||
unsafe { Self(NonMaxU32::new_unchecked(idx)) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Idx for SymbolId {
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
assert!(idx < u32::MAX as usize);
|
||||
// SAFETY: We just checked `idx` is a legal value for `NonMaxU32`
|
||||
Self(unsafe { NonMaxU32::new_unchecked(idx as u32) })
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize
|
||||
}
|
||||
define_nonmax_u32_index_type! {
|
||||
#[ast]
|
||||
#[builder(default)]
|
||||
#[clone_in(default)]
|
||||
#[content_eq(skip)]
|
||||
#[estree(skip)]
|
||||
pub struct SymbolId;
|
||||
}
|
||||
|
||||
impl<'alloc> CloneIn<'alloc> for SymbolId {
|
||||
@@ -66,34 +31,8 @@ impl<'alloc> CloneIn<'alloc> for SymbolId {
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl Serialize for SymbolId {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_u32(self.0.get())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, Copy, Eq, PartialEq, Ord, PartialOrd, Hash)]
|
||||
pub struct RedeclarationId(NonMaxU32);
|
||||
|
||||
impl Idx for RedeclarationId {
|
||||
#[expect(clippy::cast_possible_truncation)]
|
||||
fn from_usize(idx: usize) -> Self {
|
||||
assert!(idx < u32::MAX as usize);
|
||||
// SAFETY: We just checked `idx` is valid for `NonMaxU32`
|
||||
Self(unsafe { NonMaxU32::new_unchecked(idx as u32) })
|
||||
}
|
||||
|
||||
fn index(self) -> usize {
|
||||
self.0.get() as usize
|
||||
}
|
||||
}
|
||||
|
||||
#[cfg(feature = "serialize")]
|
||||
impl Serialize for RedeclarationId {
|
||||
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
|
||||
serializer.serialize_u32(self.0.get())
|
||||
}
|
||||
define_nonmax_u32_index_type! {
|
||||
pub struct RedeclarationId;
|
||||
}
|
||||
|
||||
bitflags! {
|
||||
|
||||
@@ -24,7 +24,6 @@ doctest = false
|
||||
[dependencies]
|
||||
oxc = { workspace = true, features = ["ast_visit", "codegen", "minifier", "mangler", "semantic", "serialize", "transformer", "isolated_declarations", "regular_expression", "cfg"] }
|
||||
oxc_formatter = { workspace = true }
|
||||
oxc_index = { workspace = true }
|
||||
oxc_linter = { workspace = true }
|
||||
oxc_napi = { workspace = true }
|
||||
oxc_transformer_plugins = { workspace = true }
|
||||
|
||||
@@ -30,7 +30,6 @@ use oxc::{
|
||||
transformer::{TransformOptions, Transformer},
|
||||
};
|
||||
use oxc_formatter::{FormatOptions, Formatter};
|
||||
use oxc_index::Idx;
|
||||
use oxc_linter::{
|
||||
ConfigStore, ConfigStoreBuilder, ContextSubHost, ExternalPluginStore, LintOptions, Linter,
|
||||
ModuleRecord, Oxlintrc,
|
||||
|
||||
@@ -23,7 +23,7 @@ cow-utils = { workspace = true }
|
||||
indexmap = { workspace = true }
|
||||
itertools = { workspace = true }
|
||||
lazy-regex = { workspace = true }
|
||||
oxc_index = { workspace = true, features = ["serde"] }
|
||||
oxc_index = { workspace = true }
|
||||
phf = { workspace = true, features = ["macros"] }
|
||||
phf_codegen = { workspace = true }
|
||||
prettyplease = { workspace = true }
|
||||
|
||||
@@ -48,8 +48,8 @@ pub fn load_file(
|
||||
(skeleton.name.clone(), Skeleton::Enum(skeleton), is_meta)
|
||||
}
|
||||
Item::Macro(item) => {
|
||||
let Some(skeleton) = parse_macro(&item, file_id) else { continue };
|
||||
(skeleton.name.clone(), Skeleton::Enum(skeleton), false)
|
||||
let Some((name, skeleton, is_meta)) = parse_macro(&item, file_id) else { continue };
|
||||
(name, skeleton, is_meta)
|
||||
}
|
||||
_ => continue,
|
||||
};
|
||||
@@ -74,13 +74,21 @@ fn parse_enum(item: ItemEnum, file_id: FileId) -> Option<(EnumSkeleton, /* is_me
|
||||
Some((EnumSkeleton { name, is_foreign, file_id, item, inherits: vec![] }, is_meta))
|
||||
}
|
||||
|
||||
fn parse_macro(item: &ItemMacro, file_id: FileId) -> Option<EnumSkeleton> {
|
||||
if !item.mac.path.is_ident("inherit_variants") {
|
||||
return None;
|
||||
fn parse_macro(item: &ItemMacro, file_id: FileId) -> Option<(String, Skeleton, bool)> {
|
||||
if item.mac.path.is_ident("inherit_variants") {
|
||||
let skeleton = parse_inherit_variants_macro(item, file_id);
|
||||
return Some((skeleton.name.clone(), Skeleton::Enum(skeleton), false));
|
||||
}
|
||||
if item.mac.path.is_ident("define_nonmax_u32_index_type")
|
||||
|| item.mac.path.is_ident("define_index_type")
|
||||
{
|
||||
return parse_index_type_macro(item, file_id);
|
||||
}
|
||||
None
|
||||
}
|
||||
|
||||
let skeleton = item
|
||||
.mac
|
||||
fn parse_inherit_variants_macro(item: &ItemMacro, file_id: FileId) -> EnumSkeleton {
|
||||
item.mac
|
||||
.parse_body_with(|input: &ParseBuffer| {
|
||||
// Because of `@inherit`s we can't use the actual `ItemEnum` parse.
|
||||
// This closure is similar to how `ItemEnum` parser works, with the exception
|
||||
@@ -129,9 +137,56 @@ fn parse_macro(item: &ItemMacro, file_id: FileId) -> Option<EnumSkeleton> {
|
||||
let item = ItemEnum { attrs, vis, enum_token, ident, generics, brace_token, variants };
|
||||
Ok(EnumSkeleton { name, is_foreign: false, file_id, item, inherits })
|
||||
})
|
||||
.expect("Failed to parse contents of `inherit_variants!` macro");
|
||||
.expect("Failed to parse contents of `inherit_variants!` macro")
|
||||
}
|
||||
|
||||
Some(skeleton)
|
||||
fn parse_index_type_macro(item: &ItemMacro, file_id: FileId) -> Option<(String, Skeleton, bool)> {
|
||||
item.mac
|
||||
.parse_body_with(|input: &ParseBuffer| {
|
||||
let attrs = input.call(Attribute::parse_outer)?;
|
||||
let vis = input.parse::<Visibility>()?;
|
||||
let _ = input.parse::<Token![struct]>()?;
|
||||
let ident = input.parse::<Ident>()?;
|
||||
// Handle optional `= Type` for define_index_type
|
||||
if input.parse::<Token![=]>().is_ok() {
|
||||
let _ = input.parse::<Ident>()?;
|
||||
}
|
||||
let _ = input.parse::<Token![;]>()?;
|
||||
|
||||
let Some((name, is_foreign, is_meta)) = get_type_name(&attrs, &ident) else {
|
||||
return Ok(None);
|
||||
};
|
||||
|
||||
// Create minimal ItemStruct - the field type doesn't matter since these are primitives
|
||||
let item_struct = ItemStruct {
|
||||
attrs,
|
||||
vis,
|
||||
struct_token: <_>::default(),
|
||||
ident,
|
||||
generics: <_>::default(),
|
||||
fields: syn::Fields::Unnamed(syn::FieldsUnnamed {
|
||||
paren_token: <_>::default(),
|
||||
unnamed: {
|
||||
let mut punct = Punctuated::new();
|
||||
punct.push(syn::Field {
|
||||
attrs: vec![],
|
||||
vis: syn::Visibility::Inherited,
|
||||
mutability: syn::FieldMutability::None,
|
||||
ident: None,
|
||||
colon_token: None,
|
||||
ty: syn::parse_quote!(NonMaxU32),
|
||||
});
|
||||
punct
|
||||
},
|
||||
}),
|
||||
semi_token: None,
|
||||
};
|
||||
|
||||
let skeleton =
|
||||
StructSkeleton { name: name.clone(), is_foreign, file_id, item: item_struct };
|
||||
Ok(Some((name, Skeleton::Struct(skeleton), is_meta)))
|
||||
})
|
||||
.ok()?
|
||||
}
|
||||
|
||||
/// Get name of type, and whether it has an `#[ast_meta]` attribute on it.
|
||||
|
||||
@@ -257,6 +257,7 @@ impl<'c> Parser<'c> {
|
||||
"AtomicPtr" => primitive("AtomicPtr"),
|
||||
"&str" => primitive("&str"),
|
||||
"Atom" => primitive("Atom"),
|
||||
"NonMaxU32" => primitive("NonMaxU32"),
|
||||
// TODO: Remove the need for this by adding
|
||||
// `#[cfg_attr(target_pointer_width = "64", repr(align(8)))]` to all AST types
|
||||
"PointerAlign" => primitive("PointerAlign"),
|
||||
@@ -286,7 +287,7 @@ impl<'c> Parser<'c> {
|
||||
}
|
||||
|
||||
let was_inserted = self.type_names.insert(type_def.name().to_string());
|
||||
assert!(was_inserted);
|
||||
assert!(was_inserted, "{}", type_def.name());
|
||||
|
||||
self.extra_types.push(type_def);
|
||||
|
||||
|
||||
Reference in new issue
Block a user