-
Notifications
You must be signed in to change notification settings - Fork 0
/
lib.rs
156 lines (141 loc) · 5.38 KB
/
lib.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
use swc_core::common::DUMMY_SP;
use swc_core::ecma::ast::{
CallExpr, Callee, CatchClause, Expr, ExprOrSpread, ExprStmt, Ident, ImportDecl,
ImportNamedSpecifier, ImportSpecifier, Module, ModuleDecl, ModuleItem, Pat, Stmt, Str,
};
use swc_core::ecma::visit::{as_folder, VisitMutWith};
use swc_core::ecma::{
ast::Program,
visit::{FoldWith, VisitMut},
};
use swc_core::plugin::{plugin_transform, proxies::TransformPluginProgramMetadata};
mod tests;
// import { weirwoodErrorReport } from '@common/utils/basicAbility/monitor';
const IMPORT_PACKAGE_NAME: &str = "@common/utils/basicAbility/monitor";
const IMPORT_FN_NAME: &str = "weirwoodErrorReport";
pub struct CatchClauseVisitor {
pub has_catched: bool,
}
impl CatchClauseVisitor {
pub fn new() -> CatchClauseVisitor {
CatchClauseVisitor { has_catched: false }
}
}
impl VisitMut for CatchClauseVisitor {
fn visit_mut_module(&mut self, module: &mut Module) {
module.visit_mut_children_with(self);
if !self.has_catched {
return;
}
let mut uv_import_decl = None;
for item in &mut module.body {
if let ModuleItem::ModuleDecl(ModuleDecl::Import(import_decl)) = item {
if import_decl.src.value == IMPORT_PACKAGE_NAME {
uv_import_decl = Some(import_decl);
break;
}
}
}
if let Some(import_decl) = uv_import_decl {
let mut uv_imported = false;
for specifier in &import_decl.specifiers {
if let ImportSpecifier::Named(named_specifier) = specifier {
if named_specifier.local.sym == IMPORT_FN_NAME {
uv_imported = true;
break;
}
}
}
// 引入了包但未导入方法
if !uv_imported {
import_decl
.specifiers
.push(ImportSpecifier::Named(ImportNamedSpecifier {
span: DUMMY_SP,
local: Ident::new(IMPORT_FN_NAME.into(), DUMMY_SP),
imported: None,
is_type_only: false,
}));
}
//未引入包名和方法
} else {
let new_import_decl = ModuleDecl::Import(ImportDecl {
span: DUMMY_SP,
specifiers: vec![ImportSpecifier::Named(ImportNamedSpecifier {
span: DUMMY_SP,
local: Ident::new(IMPORT_FN_NAME.into(), DUMMY_SP),
imported: None,
is_type_only: false,
})],
src: Box::from(Str {
span: DUMMY_SP,
value: IMPORT_PACKAGE_NAME.into(),
raw: None,
}),
type_only: false,
with: None,
phase: Default::default(),
});
// 判断是否导入了模块
module
.body
.insert(0, ModuleItem::ModuleDecl(new_import_decl));
}
}
fn visit_mut_catch_clause(&mut self, catch_clause: &mut CatchClause) {
self.has_catched = true;
// 先判断catch里面使用已经使用了uvFn
let mut has_used_fn = false;
for stmt in &catch_clause.body.stmts {
if let Stmt::Expr(expr) = stmt {
if let Expr::Call(call_expr) = &*expr.expr {
if let Callee::Expr(callee_expr) = &call_expr.callee {
if let Expr::Ident(ident) = &**callee_expr {
if ident.sym == IMPORT_FN_NAME {
has_used_fn = true;
break;
}
}
}
}
}
}
// 如果没有使用过uvFn函数,那么插入uvFn(err)
if !has_used_fn {
let uv_ident = Expr::Ident(Ident::new(IMPORT_FN_NAME.into(), DUMMY_SP));
let uv_callee = Callee::Expr(Box::new(uv_ident));
let error_ident = match &catch_clause.param {
Some(pat) => match &pat {
Pat::Ident(ident) => ident.id.clone(),
_ => return,
},
None => return,
};
// 构建uvFn调用表达式
let uv_call_expr = Expr::Call(CallExpr {
callee: uv_callee,
args: vec![ExprOrSpread {
expr: Box::new(Expr::Ident(error_ident)),
spread: None,
}],
type_args: None,
span: DUMMY_SP,
});
// 插入uvFn调用语句到catch块的开头
let error_report_stmt = Stmt::Expr(ExprStmt {
span: DUMMY_SP,
expr: Box::new(uv_call_expr),
});
catch_clause.body.stmts.insert(0, error_report_stmt);
}
// 继续遍历catch块中的子节点
catch_clause.visit_mut_children_with(self);
}
}
// impl VisitMut for CatchClauseVisitor {}
/// 插件入口
#[plugin_transform]
pub fn process_transform(program: Program, _metadata: TransformPluginProgramMetadata) -> Program {
println!("hello world");
program.fold_with(&mut as_folder(CatchClauseVisitor::new()))
}