mirror of
https://github.com/swc-project/swc.git
synced 2024-12-23 21:54:36 +03:00
VisitMut<T> and VisitMutwith<F> (#680)
This is a groundwork for dts generator.
This commit is contained in:
parent
f79223e98c
commit
15bef97278
@ -1,6 +1,6 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "swc_common"
|
name = "swc_common"
|
||||||
version = "0.5.3"
|
version = "0.5.4"
|
||||||
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
authors = ["강동윤 <kdy1997.dev@gmail.com>"]
|
||||||
license = "Apache-2.0/MIT"
|
license = "Apache-2.0/MIT"
|
||||||
repository = "https://github.com/swc-project/swc.git"
|
repository = "https://github.com/swc-project/swc.git"
|
||||||
|
@ -48,6 +48,27 @@ pub trait Visit<T: ?Sized> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Visitor based on a type system.
|
||||||
|
///
|
||||||
|
/// This trait requires `#![feature(specialization)]`.
|
||||||
|
pub trait VisitMut<T: ?Sized> {
|
||||||
|
fn visit_mut(&mut self, node: &mut T);
|
||||||
|
|
||||||
|
/// Creates a folder which applies `folder` after `self`.
|
||||||
|
fn then<F>(self, visitor: F) -> AndThen<Self, F>
|
||||||
|
where
|
||||||
|
Self: Sized,
|
||||||
|
F: VisitMut<T>,
|
||||||
|
{
|
||||||
|
AndThen {
|
||||||
|
first: self,
|
||||||
|
second: visitor,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl for Box<F> ----- -----
|
||||||
|
|
||||||
impl<T, F: ?Sized> Fold<T> for Box<F>
|
impl<T, F: ?Sized> Fold<T> for Box<F>
|
||||||
where
|
where
|
||||||
T: FoldWith<Self>,
|
T: FoldWith<Self>,
|
||||||
@ -58,6 +79,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized, F: ?Sized> VisitMut<T> for Box<F>
|
||||||
|
where
|
||||||
|
T: VisitMutWith<Self>,
|
||||||
|
F: VisitMut<T>,
|
||||||
|
{
|
||||||
|
fn visit_mut(&mut self, node: &mut T) {
|
||||||
|
(**self).visit_mut(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ?Sized, F: ?Sized> Visit<T> for Box<F>
|
impl<T: ?Sized, F: ?Sized> Visit<T> for Box<F>
|
||||||
where
|
where
|
||||||
T: VisitWith<Self>,
|
T: VisitWith<Self>,
|
||||||
@ -68,6 +99,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl for &'a mut F ----- -----
|
||||||
|
|
||||||
impl<'a, T, F: ?Sized> Fold<T> for &'a mut F
|
impl<'a, T, F: ?Sized> Fold<T> for &'a mut F
|
||||||
where
|
where
|
||||||
T: FoldWith<Self>,
|
T: FoldWith<Self>,
|
||||||
@ -78,6 +111,16 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, T, F: ?Sized> VisitMut<T> for &'a mut F
|
||||||
|
where
|
||||||
|
T: VisitMutWith<Self>,
|
||||||
|
F: VisitMut<T>,
|
||||||
|
{
|
||||||
|
fn visit_mut(&mut self, node: &mut T) {
|
||||||
|
(**self).visit_mut(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a, T: ?Sized, F: ?Sized> Visit<T> for &'a mut F
|
impl<'a, T: ?Sized, F: ?Sized> Visit<T> for &'a mut F
|
||||||
where
|
where
|
||||||
T: VisitWith<Self>,
|
T: VisitWith<Self>,
|
||||||
@ -88,6 +131,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- default impl for F ----- -----
|
||||||
|
|
||||||
impl<T, F> Fold<T> for F
|
impl<T, F> Fold<T> for F
|
||||||
where
|
where
|
||||||
T: FoldWith<F>,
|
T: FoldWith<F>,
|
||||||
@ -97,6 +142,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T: ?Sized, F> VisitMut<T> for F
|
||||||
|
where
|
||||||
|
T: VisitMutWith<F>,
|
||||||
|
{
|
||||||
|
default fn visit_mut(&mut self, t: &mut T) {
|
||||||
|
t.visit_mut_children(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ?Sized, F> Visit<T> for F
|
impl<T: ?Sized, F> Visit<T> for F
|
||||||
where
|
where
|
||||||
T: VisitWith<F>,
|
T: VisitWith<F>,
|
||||||
@ -133,6 +187,33 @@ pub trait FoldWith<F>: Sized {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Trait implemented for types which know how to visit itself.
|
||||||
|
///
|
||||||
|
///
|
||||||
|
/// # Derive
|
||||||
|
///
|
||||||
|
/// This trait can be derived with `#[derive(Fold)]`.
|
||||||
|
///
|
||||||
|
/// Note that derive ignores all fields with primitive type
|
||||||
|
/// because it would encourage mistakes. Use new type instead.
|
||||||
|
///
|
||||||
|
/// `#[fold(ignore)]` can be used to ignore a field.
|
||||||
|
pub trait VisitMutWith<F> {
|
||||||
|
/// This is used by default implementation of `Fold<Self>::fold`.
|
||||||
|
fn visit_mut_children(&mut self, f: &mut F);
|
||||||
|
|
||||||
|
/// Call `f.fold(self)`.
|
||||||
|
///
|
||||||
|
/// This bypasses a type inference bug which is caused by specialization.
|
||||||
|
|
||||||
|
fn visit_mut_with(&mut self, f: &mut F)
|
||||||
|
where
|
||||||
|
F: VisitMut<Self>,
|
||||||
|
{
|
||||||
|
f.visit_mut(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Trait implemented for types which know how to visit itself.
|
/// Trait implemented for types which know how to visit itself.
|
||||||
///
|
///
|
||||||
///
|
///
|
||||||
@ -157,6 +238,8 @@ pub trait VisitWith<F> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl for &T ----- -----
|
||||||
|
|
||||||
impl<'a, T: ?Sized, F> VisitWith<F> for &'a T
|
impl<'a, T: ?Sized, F> VisitWith<F> for &'a T
|
||||||
where
|
where
|
||||||
F: Visit<T>,
|
F: Visit<T>,
|
||||||
@ -166,6 +249,19 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl for &mut T ----- -----
|
||||||
|
|
||||||
|
impl<'a, T: ?Sized, F> VisitMutWith<F> for &'a mut T
|
||||||
|
where
|
||||||
|
F: VisitMut<T>,
|
||||||
|
{
|
||||||
|
fn visit_mut_children(&mut self, f: &mut F) {
|
||||||
|
f.visit_mut(&mut **self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl for Box<T> ----- -----
|
||||||
|
|
||||||
impl<T, F> FoldWith<F> for Box<T>
|
impl<T, F> FoldWith<F> for Box<T>
|
||||||
where
|
where
|
||||||
F: Fold<T>,
|
F: Fold<T>,
|
||||||
@ -175,6 +271,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, F> VisitMutWith<F> for Box<T>
|
||||||
|
where
|
||||||
|
F: VisitMut<T>,
|
||||||
|
{
|
||||||
|
fn visit_mut_children(&mut self, f: &mut F) {
|
||||||
|
f.visit_mut(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T: ?Sized, F> VisitWith<F> for Box<T>
|
impl<T: ?Sized, F> VisitWith<F> for Box<T>
|
||||||
where
|
where
|
||||||
F: Visit<T>,
|
F: Visit<T>,
|
||||||
@ -184,6 +289,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl for Vec<T> ----- -----
|
||||||
|
|
||||||
impl<T, F> FoldWith<F> for Vec<T>
|
impl<T, F> FoldWith<F> for Vec<T>
|
||||||
where
|
where
|
||||||
F: Fold<T>,
|
F: Fold<T>,
|
||||||
@ -194,6 +301,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, F> VisitMutWith<F> for Vec<T>
|
||||||
|
where
|
||||||
|
F: VisitMut<T>,
|
||||||
|
{
|
||||||
|
fn visit_mut_children(&mut self, f: &mut F) {
|
||||||
|
self.iter_mut().for_each(|node| f.visit_mut(node))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, F> VisitWith<F> for Vec<T>
|
impl<T, F> VisitWith<F> for Vec<T>
|
||||||
where
|
where
|
||||||
F: Visit<T>,
|
F: Visit<T>,
|
||||||
@ -203,6 +319,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl for [T] ----- -----
|
||||||
|
|
||||||
|
impl<T, F> VisitMutWith<F> for [T]
|
||||||
|
where
|
||||||
|
F: VisitMut<T>,
|
||||||
|
{
|
||||||
|
fn visit_mut_children(&mut self, f: &mut F) {
|
||||||
|
self.iter_mut().for_each(|node| f.visit_mut(node))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, F> VisitWith<F> for [T]
|
impl<T, F> VisitWith<F> for [T]
|
||||||
where
|
where
|
||||||
F: Visit<T>,
|
F: Visit<T>,
|
||||||
@ -212,6 +339,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl for Option<T> ----- -----
|
||||||
|
|
||||||
impl<T, F> FoldWith<F> for Option<T>
|
impl<T, F> FoldWith<F> for Option<T>
|
||||||
where
|
where
|
||||||
F: Fold<T>,
|
F: Fold<T>,
|
||||||
@ -221,6 +350,17 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<T, F> VisitMutWith<F> for Option<T>
|
||||||
|
where
|
||||||
|
F: VisitMut<T>,
|
||||||
|
{
|
||||||
|
fn visit_mut_children(&mut self, f: &mut F) {
|
||||||
|
if let Some(ref mut node) = *self {
|
||||||
|
f.visit_mut(node)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<T, F> VisitWith<F> for Option<T>
|
impl<T, F> VisitWith<F> for Option<T>
|
||||||
where
|
where
|
||||||
F: Visit<T>,
|
F: Visit<T>,
|
||||||
@ -232,34 +372,46 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl for String ----- -----
|
||||||
|
|
||||||
|
/// No op.
|
||||||
impl<F> FoldWith<F> for String {
|
impl<F> FoldWith<F> for String {
|
||||||
/// No op.
|
|
||||||
|
|
||||||
fn fold_children(self, _: &mut F) -> Self {
|
fn fold_children(self, _: &mut F) -> Self {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// No op.
|
||||||
|
impl<F> VisitMutWith<F> for String {
|
||||||
|
fn visit_mut_children(&mut self, _: &mut F) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// No op.
|
||||||
impl<F> VisitWith<F> for String {
|
impl<F> VisitWith<F> for String {
|
||||||
/// No op.
|
|
||||||
|
|
||||||
fn visit_children(&self, _: &mut F) {}
|
fn visit_children(&self, _: &mut F) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, S: StaticAtomSet> FoldWith<F> for Atom<S> {
|
// ----- ----- impl for string_cache::Atom ----- -----
|
||||||
/// No op.
|
|
||||||
|
|
||||||
|
/// No op.
|
||||||
|
impl<F, S: StaticAtomSet> FoldWith<F> for Atom<S> {
|
||||||
fn fold_children(self, _: &mut F) -> Self {
|
fn fold_children(self, _: &mut F) -> Self {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<F, S: StaticAtomSet> VisitWith<F> for Atom<S> {
|
|
||||||
/// No op.
|
/// No op.
|
||||||
|
impl<F, S: StaticAtomSet> VisitMutWith<F> for Atom<S> {
|
||||||
|
fn visit_mut_children(&mut self, _: &mut F) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// No op.
|
||||||
|
impl<F, S: StaticAtomSet> VisitWith<F> for Atom<S> {
|
||||||
fn visit_children(&self, _: &mut F) {}
|
fn visit_children(&self, _: &mut F) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl FoldWith for Either<A, B> ----- -----
|
||||||
|
|
||||||
impl<A, B, F> FoldWith<F> for Either<A, B>
|
impl<A, B, F> FoldWith<F> for Either<A, B>
|
||||||
where
|
where
|
||||||
F: Fold<A> + Fold<B>,
|
F: Fold<A> + Fold<B>,
|
||||||
@ -272,6 +424,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A, B, F> VisitMutWith<F> for Either<A, B>
|
||||||
|
where
|
||||||
|
F: VisitMut<A> + VisitMut<B>,
|
||||||
|
{
|
||||||
|
fn visit_mut_children(&mut self, f: &mut F) {
|
||||||
|
match self {
|
||||||
|
Either::Left(l) => f.visit_mut(l),
|
||||||
|
Either::Right(r) => f.visit_mut(r),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<A, B, F> VisitWith<F> for Either<A, B>
|
impl<A, B, F> VisitWith<F> for Either<A, B>
|
||||||
where
|
where
|
||||||
F: Visit<A> + Visit<B>,
|
F: Visit<A> + Visit<B>,
|
||||||
@ -284,6 +448,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl Fold for Either<A, B> ----- -----
|
||||||
|
|
||||||
impl<A, B, T> Fold<T> for Either<A, B>
|
impl<A, B, T> Fold<T> for Either<A, B>
|
||||||
where
|
where
|
||||||
T: FoldWith<A> + FoldWith<B> + FoldWith<Self>,
|
T: FoldWith<A> + FoldWith<B> + FoldWith<Self>,
|
||||||
@ -296,6 +462,18 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<A, B, T> VisitMut<T> for Either<A, B>
|
||||||
|
where
|
||||||
|
T: VisitMutWith<A> + VisitMutWith<B> + VisitMutWith<Self>,
|
||||||
|
{
|
||||||
|
fn visit_mut(&mut self, node: &mut T) {
|
||||||
|
match self {
|
||||||
|
Either::Left(l) => node.visit_mut_with(l),
|
||||||
|
Either::Right(r) => node.visit_mut_with(r),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<A, B, T> Visit<T> for Either<A, B>
|
impl<A, B, T> Visit<T> for Either<A, B>
|
||||||
where
|
where
|
||||||
T: VisitWith<A> + VisitWith<B> + VisitWith<Self>,
|
T: VisitWith<A> + VisitWith<B> + VisitWith<Self>,
|
||||||
@ -308,6 +486,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl FoldWith for Arc<T> ----- -----
|
||||||
|
|
||||||
impl<T, F> VisitWith<F> for Arc<T>
|
impl<T, F> VisitWith<F> for Arc<T>
|
||||||
where
|
where
|
||||||
T: ?Sized,
|
T: ?Sized,
|
||||||
@ -318,6 +498,8 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ----- ----- impl FoldWith for Cow<T> ----- -----
|
||||||
|
|
||||||
impl<'a, A, F> FoldWith<F> for Cow<'a, A>
|
impl<'a, A, F> FoldWith<F> for Cow<'a, A>
|
||||||
where
|
where
|
||||||
A: Clone + FoldWith<F>,
|
A: Clone + FoldWith<F>,
|
||||||
@ -329,6 +511,15 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl<'a, A, F> VisitMutWith<F> for Cow<'a, A>
|
||||||
|
where
|
||||||
|
A: Clone + VisitMutWith<F>,
|
||||||
|
{
|
||||||
|
fn visit_mut_children(&mut self, f: &mut F) {
|
||||||
|
self.to_mut().visit_mut_with(f)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
impl<A, F> VisitWith<F> for Cow<'_, A>
|
impl<A, F> VisitWith<F> for Cow<'_, A>
|
||||||
where
|
where
|
||||||
A: Clone + VisitWith<F>,
|
A: Clone + VisitWith<F>,
|
||||||
|
@ -1,11 +1,15 @@
|
|||||||
#![cfg_attr(feature = "fold", feature(specialization))]
|
#![cfg_attr(feature = "fold", feature(specialization))]
|
||||||
|
|
||||||
#[cfg(feature = "fold")]
|
#[cfg(feature = "fold")]
|
||||||
pub use self::fold::{Fold, FoldWith, Visit, VisitWith};
|
pub use self::fold::{Fold, FoldWith, Visit, VisitMut, VisitMutWith, VisitWith};
|
||||||
pub use self::{
|
pub use self::{
|
||||||
errors::{SourceMapper, SourceMapperDyn},
|
errors::{SourceMapper, SourceMapperDyn},
|
||||||
pos::*,
|
pos::{
|
||||||
source_map::{FileLines, FileLoader, FileName, FilePathMapping, SourceMap, SpanSnippetError},
|
hygiene, BytePos, CharPos, FileName, Globals, Loc, LocWithOpt, Mark, MultiSpan, SourceFile,
|
||||||
|
SourceFileAndBytePos, SourceFileAndLine, Span, SpanData, SpanLinesError, Spanned,
|
||||||
|
SyntaxContext, DUMMY_SP, GLOBALS, NO_EXPANSION,
|
||||||
|
},
|
||||||
|
source_map::{FileLines, FileLoader, FilePathMapping, SourceMap, SpanSnippetError},
|
||||||
};
|
};
|
||||||
pub use ast_node::{ast_node, DeserializeEnum, Fold, Spanned};
|
pub use ast_node::{ast_node, DeserializeEnum, Fold, Spanned};
|
||||||
pub use from_variant::FromVariant;
|
pub use from_variant::FromVariant;
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
#[cfg(feature = "fold")]
|
#[cfg(feature = "fold")]
|
||||||
use crate::fold::{FoldWith, VisitWith};
|
use crate::fold::{FoldWith, VisitMutWith, VisitWith};
|
||||||
pub use crate::syntax_pos::{
|
pub use crate::syntax_pos::{
|
||||||
hygiene, BytePos, CharPos, FileName, Globals, Loc, LocWithOpt, Mark, MultiSpan, SourceFile,
|
hygiene, BytePos, CharPos, FileName, Globals, Loc, LocWithOpt, Mark, MultiSpan, SourceFile,
|
||||||
SourceFileAndBytePos, SourceFileAndLine, Span, SpanData, SpanLinesError, SyntaxContext,
|
SourceFileAndBytePos, SourceFileAndLine, Span, SpanData, SpanLinesError, SyntaxContext,
|
||||||
@ -92,16 +92,22 @@ where
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// No op as span does not have any child.
|
||||||
#[cfg(feature = "fold")]
|
#[cfg(feature = "fold")]
|
||||||
impl<F> FoldWith<F> for Span {
|
impl<F> FoldWith<F> for Span {
|
||||||
/// No op as span does not have any child.
|
|
||||||
fn fold_children(self, _: &mut F) -> Span {
|
fn fold_children(self, _: &mut F) -> Span {
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// No op as span does not have any child.
|
||||||
|
#[cfg(feature = "fold")]
|
||||||
|
impl<F> VisitMutWith<F> for Span {
|
||||||
|
fn visit_mut_children(&mut self, _: &mut F) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// No op as span does not have any child.
|
||||||
#[cfg(feature = "fold")]
|
#[cfg(feature = "fold")]
|
||||||
impl<F> VisitWith<F> for Span {
|
impl<F> VisitWith<F> for Span {
|
||||||
/// No op as span does not have any child.
|
|
||||||
fn visit_children(&self, _: &mut F) {}
|
fn visit_children(&self, _: &mut F) {}
|
||||||
}
|
}
|
||||||
|
@ -19,6 +19,7 @@ mod analyze_source_file;
|
|||||||
pub mod hygiene;
|
pub mod hygiene;
|
||||||
mod span_encoding;
|
mod span_encoding;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
pub struct Globals {
|
pub struct Globals {
|
||||||
span_interner: Lock<span_encoding::SpanInterner>,
|
span_interner: Lock<span_encoding::SpanInterner>,
|
||||||
hygiene_data: Lock<hygiene::HygieneData>,
|
hygiene_data: Lock<hygiene::HygieneData>,
|
||||||
|
@ -130,7 +130,7 @@ impl Mark {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug, Default)]
|
||||||
pub(crate) struct HygieneData {
|
pub(crate) struct HygieneData {
|
||||||
marks: Vec<MarkData>,
|
marks: Vec<MarkData>,
|
||||||
syntax_contexts: Vec<SyntaxContextData>,
|
syntax_contexts: Vec<SyntaxContextData>,
|
||||||
|
@ -3,14 +3,15 @@ use std::{env, path::PathBuf, sync::Arc};
|
|||||||
use swc_common::{FilePathMapping, SourceFile, SourceMap};
|
use swc_common::{FilePathMapping, SourceFile, SourceMap};
|
||||||
|
|
||||||
fn init() {
|
fn init() {
|
||||||
rayon::ThreadPoolBuilder::new()
|
let _ = rayon::ThreadPoolBuilder::new()
|
||||||
.num_threads(100)
|
.num_threads(100)
|
||||||
.build_global()
|
.build_global();
|
||||||
.unwrap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn no_overlap() {
|
fn no_overlap() {
|
||||||
|
init();
|
||||||
|
|
||||||
let cm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
let cm = Arc::new(SourceMap::new(FilePathMapping::empty()));
|
||||||
|
|
||||||
let files: Vec<Arc<SourceFile>> = (0..100000)
|
let files: Vec<Arc<SourceFile>> = (0..100000)
|
||||||
|
@ -5,7 +5,7 @@ use syn::*;
|
|||||||
|
|
||||||
#[derive(Debug, FromField)]
|
#[derive(Debug, FromField)]
|
||||||
#[darling(attributes(fold))]
|
#[darling(attributes(fold))]
|
||||||
struct FieldAttrs {
|
pub struct FieldAttrs {
|
||||||
///
|
///
|
||||||
#[darling(default)]
|
#[darling(default)]
|
||||||
pub ignore: bool,
|
pub ignore: bool,
|
||||||
@ -182,7 +182,7 @@ pub fn derive(input: DeriveInput) -> ItemImpl {
|
|||||||
derive_generics.append_to(item)
|
derive_generics.append_to(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_skip_field(field: &Field) -> bool {
|
pub fn should_skip_field(field: &Field) -> bool {
|
||||||
let attrs = FieldAttrs::from_field(field).expect("#[derive(Fold)]: failed to parse attribute");
|
let attrs = FieldAttrs::from_field(field).expect("#[derive(Fold)]: failed to parse attribute");
|
||||||
if attrs.ignore {
|
if attrs.ignore {
|
||||||
return true;
|
return true;
|
||||||
@ -198,7 +198,7 @@ fn should_skip_field(field: &Field) -> bool {
|
|||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
fn normalize_type_for_bound(ty: Type) -> Type {
|
pub fn normalize_type_for_bound(ty: Type) -> Type {
|
||||||
use syn::fold::Fold;
|
use syn::fold::Fold;
|
||||||
|
|
||||||
struct Norm;
|
struct Norm;
|
||||||
|
@ -12,6 +12,7 @@ mod enum_deserialize;
|
|||||||
mod fold;
|
mod fold;
|
||||||
mod spanned;
|
mod spanned;
|
||||||
mod visit;
|
mod visit;
|
||||||
|
mod visit_mut;
|
||||||
|
|
||||||
/// Implements `FoldWith<F>` and `VisitWith<F>`.
|
/// Implements `FoldWith<F>` and `VisitWith<F>`.
|
||||||
///
|
///
|
||||||
@ -28,17 +29,20 @@ pub fn derive_fold(input: proc_macro::TokenStream) -> proc_macro::TokenStream {
|
|||||||
let name = input.ident.clone();
|
let name = input.ident.clone();
|
||||||
|
|
||||||
let fold_item = self::fold::derive(input.clone());
|
let fold_item = self::fold::derive(input.clone());
|
||||||
let visit_item = self::visit::derive(input);
|
let visit_item = self::visit::derive(input.clone());
|
||||||
|
let visit_mut_item = self::visit_mut::derive(input);
|
||||||
let item = Quote::new(def_site::<Span>()).quote_with(smart_quote!(
|
let item = Quote::new(def_site::<Span>()).quote_with(smart_quote!(
|
||||||
Vars {
|
Vars {
|
||||||
fold_item: fold_item,
|
fold_item,
|
||||||
visit_item: visit_item,
|
visit_item,
|
||||||
|
visit_mut_item,
|
||||||
NAME: Ident::new(&format!("IMPL_FOLD_FOR_{}",name), Span::call_site()),
|
NAME: Ident::new(&format!("IMPL_FOLD_FOR_{}",name), Span::call_site()),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
const NAME: () = {
|
const NAME: () = {
|
||||||
fold_item
|
fold_item
|
||||||
visit_item
|
visit_item
|
||||||
|
visit_mut_item
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
));
|
));
|
||||||
|
@ -1,20 +1,8 @@
|
|||||||
use darling::FromField;
|
use crate::fold::{normalize_type_for_bound, should_skip_field};
|
||||||
use pmutil::{smart_quote, Quote, ToTokensExt};
|
use pmutil::{smart_quote, Quote};
|
||||||
use swc_macros_common::prelude::*;
|
use swc_macros_common::prelude::*;
|
||||||
use syn::*;
|
use syn::*;
|
||||||
|
|
||||||
#[derive(Debug, FromField)]
|
|
||||||
#[darling(attributes(fold))]
|
|
||||||
struct FieldAttrs {
|
|
||||||
///
|
|
||||||
#[darling(default)]
|
|
||||||
pub ignore: bool,
|
|
||||||
|
|
||||||
/// Should we add bound for the field's type?
|
|
||||||
#[darling(default)]
|
|
||||||
pub bound: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn derive(input: DeriveInput) -> ItemImpl {
|
pub fn derive(input: DeriveInput) -> ItemImpl {
|
||||||
let mut derive_generics = Derive::new(&input);
|
let mut derive_generics = Derive::new(&input);
|
||||||
|
|
||||||
@ -149,49 +137,3 @@ pub fn derive(input: DeriveInput) -> ItemImpl {
|
|||||||
.parse();
|
.parse();
|
||||||
derive_generics.append_to(item)
|
derive_generics.append_to(item)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn should_skip_field(field: &Field) -> bool {
|
|
||||||
let attrs = FieldAttrs::from_field(field).expect("#[derive(Fold)]: failed to parse attribute");
|
|
||||||
if attrs.ignore {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
let ty_str = field.ty.dump().to_string();
|
|
||||||
match &*ty_str {
|
|
||||||
"bool" | "usize" | "u128" | "u64" | "u32" | "u16" | "u8" | "isize" | "i128" | "i64"
|
|
||||||
| "i32" | "i16" | "i8" | "f64" | "f32" | "String" => return true,
|
|
||||||
_ => {}
|
|
||||||
}
|
|
||||||
|
|
||||||
false
|
|
||||||
}
|
|
||||||
|
|
||||||
fn normalize_type_for_bound(ty: Type) -> Type {
|
|
||||||
use syn::fold::Fold;
|
|
||||||
|
|
||||||
struct Norm;
|
|
||||||
impl Fold for Norm {
|
|
||||||
fn fold_path(&mut self, path: Path) -> Path {
|
|
||||||
if path.segments.len() == 1 {
|
|
||||||
let seg = &path.segments[0];
|
|
||||||
if seg.ident != "Box" && seg.ident != "Option" && seg.ident != "Vec" {
|
|
||||||
return path.clone();
|
|
||||||
}
|
|
||||||
|
|
||||||
if let PathArguments::AngleBracketed(ref args) = seg.arguments {
|
|
||||||
if args.args.len() == 1 {
|
|
||||||
if let GenericArgument::Type(ref ty) = *args.args.last().unwrap() {
|
|
||||||
if let Type::Path(TypePath { ref path, .. }) = *ty {
|
|
||||||
return self.fold_path(path.clone());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fold::fold_path(self, path)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Norm.fold_type(ty)
|
|
||||||
}
|
|
||||||
|
142
macros/ast_node/src/visit_mut.rs
Normal file
142
macros/ast_node/src/visit_mut.rs
Normal file
@ -0,0 +1,142 @@
|
|||||||
|
use crate::fold::{normalize_type_for_bound, should_skip_field};
|
||||||
|
use pmutil::{smart_quote, Quote};
|
||||||
|
use swc_macros_common::prelude::*;
|
||||||
|
use syn::*;
|
||||||
|
|
||||||
|
pub fn derive(input: DeriveInput) -> ItemImpl {
|
||||||
|
let mut derive_generics = Derive::new(&input);
|
||||||
|
|
||||||
|
let preds = derive_generics
|
||||||
|
.all_generic_fields()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|f| {
|
||||||
|
f.attrs.iter().any(|attr| {
|
||||||
|
is_attr_name(attr, "fold") && (attr.tokens.to_string().contains("bound"))
|
||||||
|
})
|
||||||
|
})
|
||||||
|
.map(|f| f.ty.clone())
|
||||||
|
.map(normalize_type_for_bound)
|
||||||
|
.map(|ty| {
|
||||||
|
Quote::new(def_site::<Span>())
|
||||||
|
.quote_with(smart_quote!(
|
||||||
|
Vars { Type: &ty },
|
||||||
|
(Type: swc_common::VisitMutWith<__V>)
|
||||||
|
))
|
||||||
|
.parse()
|
||||||
|
});
|
||||||
|
derive_generics.add_where_predicates(preds);
|
||||||
|
|
||||||
|
let arms = Binder::new_from(&input)
|
||||||
|
.variants()
|
||||||
|
.into_iter()
|
||||||
|
.map(|v| {
|
||||||
|
let (pat, bindings) = v.bind("_", Some(def_site()), Some(def_site()));
|
||||||
|
|
||||||
|
let fields: Punctuated<Stmt, token::Semi> = bindings
|
||||||
|
.into_iter()
|
||||||
|
.filter_map(|binding| {
|
||||||
|
// This closure will not be called for unit-like struct.
|
||||||
|
|
||||||
|
let value = if should_skip_field(binding.field()) {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(
|
||||||
|
Quote::new(def_site::<Span>())
|
||||||
|
.quote_with(smart_quote!(
|
||||||
|
Vars {
|
||||||
|
FieldType: &binding.field().ty,
|
||||||
|
binded_field: binding.name(),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
swc_common::VisitMut::<FieldType>::visit_mut(
|
||||||
|
_v,
|
||||||
|
binded_field,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
))
|
||||||
|
.parse::<Stmt>(),
|
||||||
|
)
|
||||||
|
};
|
||||||
|
|
||||||
|
let _attrs = binding
|
||||||
|
.field()
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.filter(|attr| is_attr_name(attr, "cfg"))
|
||||||
|
.cloned()
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
|
value
|
||||||
|
})
|
||||||
|
.map(|t| Element::Punctuated(t, def_site()))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let body = match *v.data() {
|
||||||
|
// Handle unit-like structs separately
|
||||||
|
Fields::Unit => Box::new(
|
||||||
|
Quote::new(def_site::<Span>())
|
||||||
|
.quote_with(smart_quote!(Vars {}, {
|
||||||
|
{
|
||||||
|
// no-op
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.parse(),
|
||||||
|
),
|
||||||
|
_ => Box::new(
|
||||||
|
Quote::new(def_site::<Span>())
|
||||||
|
.quote_with(smart_quote!(Vars { fields }, {
|
||||||
|
{
|
||||||
|
fields
|
||||||
|
}
|
||||||
|
}))
|
||||||
|
.parse(),
|
||||||
|
),
|
||||||
|
};
|
||||||
|
|
||||||
|
Arm {
|
||||||
|
body,
|
||||||
|
|
||||||
|
attrs: v
|
||||||
|
.attrs()
|
||||||
|
.iter()
|
||||||
|
.filter(|attr| is_attr_name(attr, "cfg"))
|
||||||
|
.cloned()
|
||||||
|
.collect(),
|
||||||
|
pat,
|
||||||
|
guard: None,
|
||||||
|
fat_arrow_token: def_site(),
|
||||||
|
comma: Some(def_site()),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
let body = Expr::Match(ExprMatch {
|
||||||
|
attrs: Default::default(),
|
||||||
|
match_token: def_site(),
|
||||||
|
brace_token: def_site(),
|
||||||
|
expr: Box::new(
|
||||||
|
Quote::new(def_site::<Span>())
|
||||||
|
.quote_with(smart_quote!(Vars {}, { *self }))
|
||||||
|
.parse(),
|
||||||
|
),
|
||||||
|
arms,
|
||||||
|
});
|
||||||
|
|
||||||
|
let item = Quote::new(def_site::<Span>())
|
||||||
|
.quote_with(smart_quote!(
|
||||||
|
Vars {
|
||||||
|
Type: &input.ident,
|
||||||
|
body,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
impl<__V> swc_common::VisitMutWith<__V> for Type {
|
||||||
|
#[inline]
|
||||||
|
fn visit_mut_children(&mut self, _v: &mut __V) {
|
||||||
|
body
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
))
|
||||||
|
.parse();
|
||||||
|
derive_generics.append_to(item)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user