swc_coverage_instrument/macros/
create_instrumentation_visitor.rs1#[macro_export]
7macro_rules! create_instrumentation_visitor {
8 ($name:ident { $($vis: vis $field:ident: $t:ty),* $(,)? }) => {
9 #[allow(unused)]
10 use swc_core::{common::{Span, Spanned}, ecma::ast::*};
11
12 pub struct $name<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> {
14 source_map: std::sync::Arc<S>,
17 comments: C,
18 cov: std::rc::Rc<std::cell::RefCell<crate::SourceCoverage>>,
19 cov_fn_ident: Ident,
20 cov_fn_temp_ident: Ident,
21 instrument_options: crate::InstrumentOptions,
22 #[allow(dead_code)] pub before: Vec<Stmt>,
24 nodes: Vec<crate::Node>,
25 should_ignore: Option<crate::hint_comments::IgnoreScope>,
26 $($vis $field: $t,)*
27 }
28
29 impl<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> $name<C, S> {
30 pub fn new(
31 source_map: std::sync::Arc<S>,
32 comments: C,
33 cov: std::rc::Rc<std::cell::RefCell<crate::SourceCoverage>>,
34 instrument_options: crate::InstrumentOptions,
35 nodes: Vec<crate::Node>,
36 should_ignore: Option<crate::hint_comments::IgnoreScope>,
37 $($field: $t,)*
38 ) -> $name<C, S> {
39 $name {
40 source_map: source_map,
41 comments: comments,
42 cov: cov,
43 cov_fn_ident: crate::COVERAGE_FN_IDENT.get().expect("Coverage fn Ident should be initialized already").clone(),
44 cov_fn_temp_ident: crate::COVERAGE_FN_TRUE_TEMP_IDENT.get().expect("Coverage fn Ident should be initialized already").clone(),
45 instrument_options: instrument_options,
46 before: vec![],
47 nodes: nodes,
48 should_ignore,
49 $($field,)*
50 }
51 }
52
53 fn print_node(&self) -> String {
55 if self.nodes.len() > 0 {
56 format!(
57 "{}",
58 self.nodes
59 .iter()
60 .map(|n| n.to_string())
61 .collect::<Vec<String>>()
62 .join(":")
63 )
64 } else {
65 "".to_string()
66 }
67 }
68
69 fn on_enter_with_span(&mut self, span: Option<&Span>) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>) {
70 let old = self.should_ignore;
71 let ret = match old {
72 Some(crate::hint_comments::IgnoreScope::Next) => old,
73 _ => {
74 self.should_ignore = crate::hint_comments::should_ignore(&self.comments, span);
75 self.should_ignore
76 }
77 };
78
79 (old, ret)
80 }
81
82 fn on_exit(&mut self, old: Option<crate::hint_comments::IgnoreScope>) {
83 self.should_ignore = old;
84 self.nodes.pop();
85 }
86 }
87
88
89 trait CoverageInstrumentationMutVisitEnter<N> {
94 fn on_enter(&mut self, n: &mut N) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>);
95 }
96
97 macro_rules! on_enter {
99 ($N: tt) => {
100 impl<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> CoverageInstrumentationMutVisitEnter<$N> for $name<C, S> {
101 #[inline]
102 fn on_enter(&mut self, n: &mut swc_core::ecma::ast::$N) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>) {
103 self.nodes.push(crate::Node::$N);
104 self.on_enter_with_span(Some(&n.span))
105 }
106 }
107 }
108 }
109
110 impl<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> CoverageInstrumentationMutVisitEnter<Expr> for $name<C, S> {
111 fn on_enter(&mut self, n: &mut swc_core::ecma::ast::Expr) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>) {
112 self.nodes.push(crate::Node::Expr);
113 let span = n.span();
114 self.on_enter_with_span(Some(&span))
115 }
116 }
117
118 impl<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> CoverageInstrumentationMutVisitEnter<Stmt> for $name<C, S> {
119 fn on_enter(&mut self, n: &mut Stmt) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>) {
120 self.nodes.push(crate::Node::Stmt);
121 self.on_enter_with_span(Some(&n.span()))
122 }
123 }
124
125 impl<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> CoverageInstrumentationMutVisitEnter<ModuleDecl> for $name<C, S> {
126 fn on_enter(&mut self, n: &mut swc_core::ecma::ast::ModuleDecl) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>) {
127 self.nodes.push(crate::Node::ModuleDecl);
128 let span = n.span();
129
130 self.on_enter_with_span(Some(&span))
131 }
132 }
133
134 impl<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> CoverageInstrumentationMutVisitEnter<ClassDecl> for $name<C, S> {
135 fn on_enter(&mut self, n: &mut swc_core::ecma::ast::ClassDecl) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>) {
136 self.nodes.push(crate::Node::ClassDecl);
137 self.on_enter_with_span(Some(&n.class.span))
138 }
139 }
140
141 impl<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> CoverageInstrumentationMutVisitEnter<FnExpr> for $name<C, S> {
142 fn on_enter(&mut self, n: &mut swc_core::ecma::ast::FnExpr) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>) {
143 self.nodes.push(crate::Node::FnExpr);
144 self.on_enter_with_span(Some(&n.function.span))
145 }
146 }
147
148 impl<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> CoverageInstrumentationMutVisitEnter<MethodProp> for $name<C, S> {
149 fn on_enter(&mut self, n: &mut swc_core::ecma::ast::MethodProp) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>) {
150 self.nodes.push(crate::Node::MethodProp);
151 self.on_enter_with_span(Some(&n.function.span))
152 }
153 }
154
155 impl<C: Clone + swc_core::common::comments::Comments, S: swc_core::common::SourceMapper> CoverageInstrumentationMutVisitEnter<FnDecl> for $name<C, S> {
156 fn on_enter(&mut self, n: &mut swc_core::ecma::ast::FnDecl) -> (Option<crate::hint_comments::IgnoreScope>, Option<crate::hint_comments::IgnoreScope>) {
157 self.nodes.push(crate::Node::FnDecl);
158 self.on_enter_with_span(Some(&n.function.span))
159 }
160 }
161
162 on_enter!(BinExpr);
163 on_enter!(VarDeclarator);
164 on_enter!(VarDecl);
165 on_enter!(CondExpr);
166 on_enter!(ExprStmt);
167 on_enter!(IfStmt);
168 on_enter!(LabeledStmt);
169 on_enter!(ContinueStmt);
170 on_enter!(ClassProp);
171 on_enter!(PrivateProp);
172 on_enter!(ClassMethod);
173 on_enter!(ArrowExpr);
174 on_enter!(ForStmt);
175 on_enter!(ForOfStmt);
176 on_enter!(ForInStmt);
177 on_enter!(WhileStmt);
178 on_enter!(DoWhileStmt);
179 on_enter!(SwitchStmt);
180 on_enter!(SwitchCase);
181 on_enter!(BreakStmt);
182 on_enter!(ReturnStmt);
183 on_enter!(BlockStmt);
184 on_enter!(WithStmt);
185 on_enter!(TryStmt);
186 on_enter!(ThrowStmt);
187 on_enter!(ExportDecl);
188 on_enter!(ExportDefaultDecl);
189 on_enter!(DebuggerStmt);
190 on_enter!(AssignPat);
191 on_enter!(GetterProp);
192 on_enter!(SetterProp);
193 on_enter!(TaggedTpl);
194 }
195}