mirror of
https://github.com/swc-project/swc.git
synced 2024-11-22 06:46:41 +03:00
perf(visit): Add linear AST traversal (#9452)
**Description:** Babel decorator pass uses `fastTraverse`, and I think we can have one. **Related issue:** - Closes https://github.com/swc-project/swc/issues/9451
This commit is contained in:
parent
6187fcb134
commit
911d4eaa14
9
.changeset/olive-pianos-lay.md
Normal file
9
.changeset/olive-pianos-lay.md
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
---
|
||||||
|
swc_css_visit: patch
|
||||||
|
swc_ecma_visit: patch
|
||||||
|
swc_html_visit: patch
|
||||||
|
swc_xml_visit: patch
|
||||||
|
swc_core: patch
|
||||||
|
---
|
||||||
|
|
||||||
|
perf(visit): Add linear AST traversal
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -11092,7 +11092,6 @@ pub mod fields {
|
|||||||
#[doc = "Represents [`TokenAndSpan::token`]"]
|
#[doc = "Represents [`TokenAndSpan::token`]"]
|
||||||
Token,
|
Token,
|
||||||
}
|
}
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum AstParentKind {
|
pub enum AstParentKind {
|
||||||
Attribute(AttributeField),
|
Attribute(AttributeField),
|
||||||
@ -11131,7 +11130,6 @@ pub mod fields {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum AstParentNodeRef<'ast> {
|
pub enum AstParentNodeRef<'ast> {
|
||||||
Attribute(&'ast Attribute, AttributeField),
|
Attribute(&'ast Attribute, AttributeField),
|
||||||
@ -11176,6 +11174,7 @@ pub mod fields {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(any(docsrs, feature = "path"))]
|
||||||
impl<'ast> AstParentNodeRef<'ast> {
|
impl<'ast> AstParentNodeRef<'ast> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn kind(&self) -> AstParentKind {
|
pub fn kind(&self) -> AstParentKind {
|
||||||
@ -11202,5 +11201,185 @@ pub mod fields {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'ast> From<&'ast Attribute> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Attribute) -> Self {
|
||||||
|
NodeRef::Attribute(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast AttributeToken> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast AttributeToken) -> Self {
|
||||||
|
NodeRef::AttributeToken(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Child> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Child) -> Self {
|
||||||
|
NodeRef::Child(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Comment> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Comment) -> Self {
|
||||||
|
NodeRef::Comment(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Document> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Document) -> Self {
|
||||||
|
NodeRef::Document(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast DocumentFragment> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast DocumentFragment) -> Self {
|
||||||
|
NodeRef::DocumentFragment(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast DocumentMode> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast DocumentMode) -> Self {
|
||||||
|
NodeRef::DocumentMode(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast DocumentType> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast DocumentType) -> Self {
|
||||||
|
NodeRef::DocumentType(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Element> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Element) -> Self {
|
||||||
|
NodeRef::Element(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Namespace> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Namespace) -> Self {
|
||||||
|
NodeRef::Namespace(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Raw> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Raw) -> Self {
|
||||||
|
NodeRef::Raw(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Text> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Text) -> Self {
|
||||||
|
NodeRef::Text(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Token> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Token) -> Self {
|
||||||
|
NodeRef::Token(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast TokenAndSpan> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast TokenAndSpan) -> Self {
|
||||||
|
NodeRef::TokenAndSpan(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum NodeRef<'ast> {
|
||||||
|
Attribute(&'ast Attribute),
|
||||||
|
AttributeToken(&'ast AttributeToken),
|
||||||
|
Child(&'ast Child),
|
||||||
|
Comment(&'ast Comment),
|
||||||
|
Document(&'ast Document),
|
||||||
|
DocumentFragment(&'ast DocumentFragment),
|
||||||
|
DocumentMode(&'ast DocumentMode),
|
||||||
|
DocumentType(&'ast DocumentType),
|
||||||
|
Element(&'ast Element),
|
||||||
|
Namespace(&'ast Namespace),
|
||||||
|
Raw(&'ast Raw),
|
||||||
|
Text(&'ast Text),
|
||||||
|
Token(&'ast Token),
|
||||||
|
TokenAndSpan(&'ast TokenAndSpan),
|
||||||
|
}
|
||||||
|
impl<'ast> NodeRef<'ast> {
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
pub fn raw_children(&'ast self) -> Box<dyn 'ast + Iterator<Item = NodeRef<'ast>>> {
|
||||||
|
match self {
|
||||||
|
NodeRef::Attribute(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>().chain(
|
||||||
|
node.namespace
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::Namespace(&item))),
|
||||||
|
);
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::AttributeToken(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Child(node) => match node {
|
||||||
|
Child::DocumentType(v0) => Box::new(::std::iter::once(NodeRef::DocumentType(v0))),
|
||||||
|
Child::Element(v0) => Box::new(::std::iter::once(NodeRef::Element(v0))),
|
||||||
|
Child::Text(v0) => Box::new(::std::iter::once(NodeRef::Text(v0))),
|
||||||
|
Child::Comment(v0) => Box::new(::std::iter::once(NodeRef::Comment(v0))),
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>()),
|
||||||
|
},
|
||||||
|
NodeRef::Comment(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Document(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>()
|
||||||
|
.chain(::std::iter::once(NodeRef::DocumentMode(&node.mode)))
|
||||||
|
.chain(
|
||||||
|
node.children
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::Child(&item))),
|
||||||
|
);
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::DocumentFragment(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>().chain(
|
||||||
|
node.children
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::Child(&item))),
|
||||||
|
);
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::DocumentMode(node) => match node {
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>()),
|
||||||
|
},
|
||||||
|
NodeRef::DocumentType(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Element(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>()
|
||||||
|
.chain(::std::iter::once(NodeRef::Namespace(&node.namespace)))
|
||||||
|
.chain(
|
||||||
|
node.attributes
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::Attribute(&item))),
|
||||||
|
)
|
||||||
|
.chain(
|
||||||
|
node.children
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::Child(&item))),
|
||||||
|
)
|
||||||
|
.chain(
|
||||||
|
node.content
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::DocumentFragment(&item))),
|
||||||
|
);
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Namespace(node) => match node {
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>()),
|
||||||
|
},
|
||||||
|
NodeRef::Raw(node) => match node {
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>()),
|
||||||
|
},
|
||||||
|
NodeRef::Text(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Token(node) => match node {
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>()),
|
||||||
|
},
|
||||||
|
NodeRef::TokenAndSpan(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>()
|
||||||
|
.chain(::std::iter::once(NodeRef::Token(&node.token)));
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
#[cfg(any(docsrs, feature = "path"))]
|
||||||
pub use self::fields::{AstParentKind, AstParentNodeRef};
|
pub use self::fields::{AstParentKind, AstParentNodeRef};
|
||||||
|
@ -10660,7 +10660,6 @@ pub mod fields {
|
|||||||
#[doc = "Represents [`TokenAndSpan::token`]"]
|
#[doc = "Represents [`TokenAndSpan::token`]"]
|
||||||
Token,
|
Token,
|
||||||
}
|
}
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum AstParentKind {
|
pub enum AstParentKind {
|
||||||
Attribute(AttributeField),
|
Attribute(AttributeField),
|
||||||
@ -10699,7 +10698,6 @@ pub mod fields {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum AstParentNodeRef<'ast> {
|
pub enum AstParentNodeRef<'ast> {
|
||||||
Attribute(&'ast Attribute, AttributeField),
|
Attribute(&'ast Attribute, AttributeField),
|
||||||
@ -10744,6 +10742,7 @@ pub mod fields {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
#[cfg(any(docsrs, feature = "path"))]
|
||||||
impl<'ast> AstParentNodeRef<'ast> {
|
impl<'ast> AstParentNodeRef<'ast> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn kind(&self) -> AstParentKind {
|
pub fn kind(&self) -> AstParentKind {
|
||||||
@ -10770,5 +10769,178 @@ pub mod fields {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
impl<'ast> From<&'ast Attribute> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Attribute) -> Self {
|
||||||
|
NodeRef::Attribute(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast AttributeToken> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast AttributeToken) -> Self {
|
||||||
|
NodeRef::AttributeToken(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast CdataSection> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast CdataSection) -> Self {
|
||||||
|
NodeRef::CdataSection(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Child> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Child) -> Self {
|
||||||
|
NodeRef::Child(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Comment> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Comment) -> Self {
|
||||||
|
NodeRef::Comment(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Document> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Document) -> Self {
|
||||||
|
NodeRef::Document(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast DocumentMode> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast DocumentMode) -> Self {
|
||||||
|
NodeRef::DocumentMode(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast DocumentType> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast DocumentType) -> Self {
|
||||||
|
NodeRef::DocumentType(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Element> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Element) -> Self {
|
||||||
|
NodeRef::Element(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Namespace> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Namespace) -> Self {
|
||||||
|
NodeRef::Namespace(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast ProcessingInstruction> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast ProcessingInstruction) -> Self {
|
||||||
|
NodeRef::ProcessingInstruction(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Text> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Text) -> Self {
|
||||||
|
NodeRef::Text(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast Token> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast Token) -> Self {
|
||||||
|
NodeRef::Token(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'ast> From<&'ast TokenAndSpan> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast TokenAndSpan) -> Self {
|
||||||
|
NodeRef::TokenAndSpan(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum NodeRef<'ast> {
|
||||||
|
Attribute(&'ast Attribute),
|
||||||
|
AttributeToken(&'ast AttributeToken),
|
||||||
|
CdataSection(&'ast CdataSection),
|
||||||
|
Child(&'ast Child),
|
||||||
|
Comment(&'ast Comment),
|
||||||
|
Document(&'ast Document),
|
||||||
|
DocumentMode(&'ast DocumentMode),
|
||||||
|
DocumentType(&'ast DocumentType),
|
||||||
|
Element(&'ast Element),
|
||||||
|
Namespace(&'ast Namespace),
|
||||||
|
ProcessingInstruction(&'ast ProcessingInstruction),
|
||||||
|
Text(&'ast Text),
|
||||||
|
Token(&'ast Token),
|
||||||
|
TokenAndSpan(&'ast TokenAndSpan),
|
||||||
|
}
|
||||||
|
impl<'ast> NodeRef<'ast> {
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
pub fn raw_children(&'ast self) -> Box<dyn 'ast + Iterator<Item = NodeRef<'ast>>> {
|
||||||
|
match self {
|
||||||
|
NodeRef::Attribute(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>().chain(
|
||||||
|
node.namespace
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::Namespace(&item))),
|
||||||
|
);
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::AttributeToken(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::CdataSection(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Child(node) => match node {
|
||||||
|
Child::DocumentType(v0) => Box::new(::std::iter::once(NodeRef::DocumentType(v0))),
|
||||||
|
Child::Element(v0) => Box::new(::std::iter::once(NodeRef::Element(v0))),
|
||||||
|
Child::Text(v0) => Box::new(::std::iter::once(NodeRef::Text(v0))),
|
||||||
|
Child::CdataSection(v0) => Box::new(::std::iter::once(NodeRef::CdataSection(v0))),
|
||||||
|
Child::Comment(v0) => Box::new(::std::iter::once(NodeRef::Comment(v0))),
|
||||||
|
Child::ProcessingInstruction(v0) => {
|
||||||
|
Box::new(::std::iter::once(NodeRef::ProcessingInstruction(v0)))
|
||||||
|
}
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>()),
|
||||||
|
},
|
||||||
|
NodeRef::Comment(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Document(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>().chain(
|
||||||
|
node.children
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::Child(&item))),
|
||||||
|
);
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::DocumentMode(node) => match node {
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>()),
|
||||||
|
},
|
||||||
|
NodeRef::DocumentType(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Element(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>()
|
||||||
|
.chain(
|
||||||
|
node.attributes
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::Attribute(&item))),
|
||||||
|
)
|
||||||
|
.chain(
|
||||||
|
node.children
|
||||||
|
.iter()
|
||||||
|
.flat_map(|item| ::std::iter::once(NodeRef::Child(&item))),
|
||||||
|
);
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Namespace(node) => match node {
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>()),
|
||||||
|
},
|
||||||
|
NodeRef::ProcessingInstruction(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Text(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>();
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
NodeRef::Token(node) => match node {
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>()),
|
||||||
|
},
|
||||||
|
NodeRef::TokenAndSpan(node) => {
|
||||||
|
let iterator = ::std::iter::empty::<NodeRef<'ast>>()
|
||||||
|
.chain(::std::iter::once(NodeRef::Token(&node.token)));
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
#[cfg(any(docsrs, feature = "path"))]
|
||||||
pub use self::fields::{AstParentKind, AstParentNodeRef};
|
pub use self::fields::{AstParentKind, AstParentNodeRef};
|
||||||
|
@ -1261,14 +1261,71 @@ fn extract_generic<'a>(name: &str, ty: &'a Type) -> Option<&'a Type> {
|
|||||||
|
|
||||||
None
|
None
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn to_iter(e: TokenStream, ty: &Type, node_names: &[Ident]) -> Option<Expr> {
|
||||||
|
if let Some(ty) = extract_vec(ty) {
|
||||||
|
let inner_expr = to_iter(quote!(item), ty, node_names)?;
|
||||||
|
return Some(parse_quote!(#e.iter().flat_map(|item| #inner_expr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ty) = extract_generic("Option", ty) {
|
||||||
|
let inner_expr = to_iter(quote!(item), ty, node_names)?;
|
||||||
|
return Some(parse_quote!(#e.iter().flat_map(|item| #inner_expr)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(ty) = extract_generic("Box", ty) {
|
||||||
|
let inner_expr = to_iter(quote!(item), ty, node_names)?;
|
||||||
|
return Some(parse_quote!({
|
||||||
|
let item = &*#e;
|
||||||
|
#inner_expr
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Type::Path(p) = ty {
|
||||||
|
let ty = &p.path.segments.last().unwrap().ident;
|
||||||
|
|
||||||
|
if node_names.contains(ty) {
|
||||||
|
return Some(parse_quote!(::std::iter::once(NodeRef::#ty(&#e))));
|
||||||
|
}
|
||||||
|
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
todo!("to_iter for {:?}", ty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
fn define_fields(crate_name: &Ident, node_types: &[&Item]) -> Vec<Item> {
|
fn define_fields(crate_name: &Ident, node_types: &[&Item]) -> Vec<Item> {
|
||||||
let mut items = Vec::<Item>::new();
|
let mut items = Vec::<Item>::new();
|
||||||
let mut kind_enum_members = Vec::new();
|
let mut kind_enum_members = Vec::new();
|
||||||
|
let mut parent_enum_members = Vec::new();
|
||||||
let mut node_ref_enum_members = Vec::new();
|
let mut node_ref_enum_members = Vec::new();
|
||||||
|
|
||||||
let mut kind_set_index_arms = Vec::<Arm>::new();
|
let mut kind_set_index_arms = Vec::<Arm>::new();
|
||||||
let mut node_ref_set_index_arms = Vec::<Arm>::new();
|
let mut node_ref_set_index_arms = Vec::<Arm>::new();
|
||||||
let mut node_ref_kind_arms = Vec::<Arm>::new();
|
let mut node_ref_kind_arms = Vec::<Arm>::new();
|
||||||
|
let mut node_ref_iter_next_arms = Vec::<Arm>::new();
|
||||||
|
|
||||||
|
let node_names = node_types
|
||||||
|
.iter()
|
||||||
|
.filter_map(|ty| match ty {
|
||||||
|
Item::Enum(data) => Some(data.ident.clone()),
|
||||||
|
Item::Struct(data) => Some(data.ident.clone()),
|
||||||
|
_ => None,
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
let is_node_ref_raw = |ty: &Type| match ty {
|
||||||
|
Type::Path(p) => node_names.contains(&p.path.segments.last().unwrap().ident),
|
||||||
|
_ => false,
|
||||||
|
};
|
||||||
|
|
||||||
|
let is_node_ref = |ty: &Type| {
|
||||||
|
if let Some(ty) = extract_generic("Box", ty) {
|
||||||
|
return is_node_ref_raw(ty);
|
||||||
|
}
|
||||||
|
|
||||||
|
is_node_ref_raw(ty)
|
||||||
|
};
|
||||||
|
|
||||||
{
|
{
|
||||||
let mut defs = Vec::<Item>::new();
|
let mut defs = Vec::<Item>::new();
|
||||||
@ -1330,10 +1387,58 @@ fn define_fields(crate_name: &Ident, node_types: &[&Item]) -> Vec<Item> {
|
|||||||
#type_name(#fields_enum_name)
|
#type_name(#fields_enum_name)
|
||||||
));
|
));
|
||||||
|
|
||||||
node_ref_enum_members.push(quote!(
|
parent_enum_members.push(quote!(
|
||||||
#type_name(&'ast #type_name, #fields_enum_name)
|
#type_name(&'ast #type_name, #fields_enum_name)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
node_ref_enum_members.push(quote!(
|
||||||
|
#type_name(&'ast #type_name)
|
||||||
|
));
|
||||||
|
|
||||||
|
items.push(parse_quote!(
|
||||||
|
impl<'ast> From<&'ast #type_name> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast #type_name) -> Self {
|
||||||
|
NodeRef::#type_name(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut arms = Vec::<Arm>::new();
|
||||||
|
|
||||||
|
for variant in &data.variants {
|
||||||
|
let variant_name = &variant.ident;
|
||||||
|
|
||||||
|
// TODO: Support all kinds of fields
|
||||||
|
if variant.fields.len() != 1 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
for f in variant.fields.iter().filter(|f| is_node_ref(&f.ty)) {
|
||||||
|
let mut ty = &f.ty;
|
||||||
|
if let Some(inner) = extract_generic("Box", ty) {
|
||||||
|
ty = inner;
|
||||||
|
}
|
||||||
|
|
||||||
|
arms.push(parse_quote!(
|
||||||
|
#type_name::#variant_name(v0) => {
|
||||||
|
Box::new(::std::iter::once(NodeRef::#ty(v0)))
|
||||||
|
},
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
node_ref_iter_next_arms.push(parse_quote!(
|
||||||
|
NodeRef::#type_name(node) => {
|
||||||
|
match node {
|
||||||
|
#(#arms)*
|
||||||
|
|
||||||
|
_ => Box::new(::std::iter::empty::<NodeRef<'ast>>())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
defs.push(parse_quote!(
|
defs.push(parse_quote!(
|
||||||
impl #fields_enum_name {
|
impl #fields_enum_name {
|
||||||
#[inline(always)]
|
#[inline(always)]
|
||||||
@ -1361,10 +1466,51 @@ fn define_fields(crate_name: &Ident, node_types: &[&Item]) -> Vec<Item> {
|
|||||||
#type_name(#fields_enum_name)
|
#type_name(#fields_enum_name)
|
||||||
));
|
));
|
||||||
|
|
||||||
node_ref_enum_members.push(quote!(
|
parent_enum_members.push(quote!(
|
||||||
#type_name(&'ast #type_name, #fields_enum_name)
|
#type_name(&'ast #type_name, #fields_enum_name)
|
||||||
));
|
));
|
||||||
|
|
||||||
|
node_ref_enum_members.push(quote!(
|
||||||
|
#type_name(&'ast #type_name)
|
||||||
|
));
|
||||||
|
|
||||||
|
items.push(parse_quote!(
|
||||||
|
impl<'ast> From<&'ast #type_name> for NodeRef<'ast> {
|
||||||
|
fn from(node: &'ast #type_name) -> Self {
|
||||||
|
NodeRef::#type_name(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
|
|
||||||
|
{
|
||||||
|
let mut iter: Expr = parse_quote!(::std::iter::empty::<NodeRef<'ast>>());
|
||||||
|
|
||||||
|
match &data.fields {
|
||||||
|
Fields::Named(fields) => {
|
||||||
|
for f in fields.named.iter() {
|
||||||
|
let ident = &f.ident;
|
||||||
|
let iter_expr =
|
||||||
|
to_iter(quote!(node.#ident), &f.ty, &node_names);
|
||||||
|
if let Some(iter_expr) = iter_expr {
|
||||||
|
iter = parse_quote!(#iter.chain(#iter_expr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Fields::Unnamed(_fields) => {
|
||||||
|
// TODO: Support unnamed fields
|
||||||
|
}
|
||||||
|
Fields::Unit => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
node_ref_iter_next_arms.push(parse_quote!(
|
||||||
|
NodeRef::#type_name(node) => {
|
||||||
|
let iterator = #iter;
|
||||||
|
Box::new(iterator)
|
||||||
|
}
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
defs.push(parse_quote!(
|
defs.push(parse_quote!(
|
||||||
impl #fields_enum_name {
|
impl #fields_enum_name {
|
||||||
pub(crate) fn set_index(&mut self, index: usize) {
|
pub(crate) fn set_index(&mut self, index: usize) {
|
||||||
@ -1392,7 +1538,6 @@ fn define_fields(crate_name: &Ident, node_types: &[&Item]) -> Vec<Item> {
|
|||||||
|
|
||||||
{
|
{
|
||||||
defs.push(parse_quote!(
|
defs.push(parse_quote!(
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
|
||||||
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
#[derive(Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
|
||||||
pub enum AstParentKind {
|
pub enum AstParentKind {
|
||||||
#(#kind_enum_members),*
|
#(#kind_enum_members),*
|
||||||
@ -1413,9 +1558,14 @@ fn define_fields(crate_name: &Ident, node_types: &[&Item]) -> Vec<Item> {
|
|||||||
|
|
||||||
{
|
{
|
||||||
defs.push(parse_quote!(
|
defs.push(parse_quote!(
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
|
||||||
#[derive(Debug, Clone, Copy)]
|
#[derive(Debug, Clone, Copy)]
|
||||||
pub enum AstParentNodeRef<'ast> {
|
pub enum AstParentNodeRef<'ast> {
|
||||||
|
#(#parent_enum_members),*
|
||||||
|
}
|
||||||
|
));
|
||||||
|
items.push(parse_quote!(
|
||||||
|
#[derive(Debug, Clone, Copy)]
|
||||||
|
pub enum NodeRef<'ast> {
|
||||||
#(#node_ref_enum_members),*
|
#(#node_ref_enum_members),*
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
@ -1437,6 +1587,7 @@ fn define_fields(crate_name: &Ident, node_types: &[&Item]) -> Vec<Item> {
|
|||||||
}
|
}
|
||||||
));
|
));
|
||||||
defs.push(parse_quote!(
|
defs.push(parse_quote!(
|
||||||
|
#[cfg(any(docsrs, feature = "path"))]
|
||||||
impl<'ast> AstParentNodeRef<'ast> {
|
impl<'ast> AstParentNodeRef<'ast> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn kind(&self) -> AstParentKind {
|
pub fn kind(&self) -> AstParentKind {
|
||||||
@ -1446,14 +1597,27 @@ fn define_fields(crate_name: &Ident, node_types: &[&Item]) -> Vec<Item> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
items.push(parse_quote!(
|
||||||
|
impl<'ast> NodeRef<'ast> {
|
||||||
|
#[allow(unreachable_patterns)]
|
||||||
|
pub fn raw_children(&'ast self) -> Box<dyn 'ast + Iterator<Item = NodeRef<'ast>>> {
|
||||||
|
match self {
|
||||||
|
#(#node_ref_iter_next_arms)*
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
items.push(parse_quote!(
|
items.insert(
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
0,
|
||||||
pub mod fields {
|
parse_quote!(
|
||||||
#(#defs)*
|
#[cfg(any(docsrs, feature = "path"))]
|
||||||
}
|
pub mod fields {
|
||||||
));
|
#(#defs)*
|
||||||
|
}
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
items.push(parse_quote!(
|
items.push(parse_quote!(
|
||||||
#[cfg(any(docsrs, feature = "path"))]
|
#[cfg(any(docsrs, feature = "path"))]
|
||||||
|
Loading…
Reference in New Issue
Block a user