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:
Boshen committed 2025-10-04 04:58:42 +00:00
1 parent ee4546f379
commit 3656908d0e
26 files changed
+134 -323

No files matched your search

Generated
+9 -13
View File
@@ -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
View File
@@ -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"
-1
View File
@@ -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 }
+1 -1
View File
@@ -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() {
+3 -15
View File
@@ -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 {
-1
View File
@@ -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]
+4 -18
View File
@@ -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.
+1 -2
View File
@@ -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();
-1
View File
@@ -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;
-1
View File
@@ -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 }
-1
View File
@@ -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};
+1 -1
View File
@@ -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
View File
@@ -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;
-1
View File
@@ -42,7 +42,6 @@ to_js_string = ["dep:dragonbox_ecma"]
serialize = [
"bitflags/serde",
"dep:serde",
"oxc_index/serde",
"oxc_estree/serialize",
]
+10 -33
View File
@@ -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)
}
}
+5 -47
View File
@@ -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! {
+9 -29
View File
@@ -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.
///
+8 -52
View File
@@ -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 {
+11 -72
View File
@@ -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! {
-1
View File
@@ -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 }
-1
View File
@@ -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,
+1 -1
View File
@@ -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 }
+64 -9
View File
@@ -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.
+2 -1
View File
@@ -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);