1
1
use ego_tree:: { NodeId , Tree , NodeMut , NodeRef } ;
2
2
use html5ever:: { Attribute , tendril:: StrTendril } ;
3
- use swc_ecma_ast:: { JSXElement , JSXElementName , JSXAttrOrSpread , JSXAttrName , JSXAttrValue , Lit , JSXExpr , Expr , JSXElementChild , Module , Function , Stmt , ExportDefaultExpr , ExportDefaultDecl , DefaultDecl , ClassDecl , ClassMember , PropName , FnDecl , JSXFragment } ;
3
+ use swc_ecma_ast:: { JSXElement , JSXElementName , JSXAttrOrSpread , JSXAttrName , JSXAttrValue , Lit , JSXExpr , Expr , JSXElementChild , Module , Function , Stmt , ExportDefaultExpr , ExportDefaultDecl , DefaultDecl , ClassDecl , ClassMember , PropName , FnDecl , Callee , MemberProp } ;
4
4
use swc_ecma_visit:: { Visit , VisitWith } ;
5
5
6
6
use crate :: { scraper:: { Node , Element , Fragment } , utils:: { recursion_jsx_member, create_qualname, is_starts_with_uppercase} } ;
@@ -119,14 +119,14 @@ impl<'a> Visit for JSXVisitor<'a> {
119
119
120
120
fn visit_jsx_element_children ( & mut self , n : & [ JSXElementChild ] ) {
121
121
let mut nodes = vec ! [ ] ;
122
- let mut elements: Vec < JSXElementChild > = vec ! [ ] ;
122
+ let mut elements: Vec < & JSXElementChild > = vec ! [ ] ;
123
123
for child in n. iter ( ) {
124
124
match child {
125
125
JSXElementChild :: JSXElement ( element) => {
126
126
if let JSXElementName :: Ident ( ident) = & element. opening . name {
127
127
let name = ident. sym . to_string ( ) ;
128
128
if is_starts_with_uppercase ( name. as_str ( ) ) {
129
- let mut visitor = JSXFragmentVisitor :: new ( self . module , name. as_str ( ) ) ;
129
+ let mut visitor = JSXFragmentVisitor :: new ( self . module , name. as_str ( ) , SearchType :: Normal ) ;
130
130
self . module . visit_with ( & mut visitor) ;
131
131
let mut current = self . tree . get_mut ( self . current_node . unwrap ( ) ) . unwrap ( ) ;
132
132
// 将 Fragment 的子节点添加到当前节点
@@ -136,22 +136,66 @@ impl<'a> Visit for JSXVisitor<'a> {
136
136
let mut current = self . tree . get_mut ( self . current_node . unwrap ( ) ) . unwrap ( ) ;
137
137
let tree_node = current. append ( node) ;
138
138
nodes. push ( tree_node. id ( ) ) ;
139
- elements. push ( JSXElementChild :: JSXElement ( element . clone ( ) ) ) ;
139
+ elements. push ( child ) ;
140
140
}
141
141
} else {
142
142
let node = self . create_element ( element) ;
143
143
let mut current = self . tree . get_mut ( self . current_node . unwrap ( ) ) . unwrap ( ) ;
144
144
let tree_node = current. append ( node) ;
145
145
nodes. push ( tree_node. id ( ) ) ;
146
- elements. push ( JSXElementChild :: JSXElement ( element . clone ( ) ) ) ;
146
+ elements. push ( child ) ;
147
147
}
148
148
} ,
149
- JSXElementChild :: JSXFragment ( fragment ) => {
149
+ JSXElementChild :: JSXFragment ( _ ) => {
150
150
let node = self . create_fragment ( ) ;
151
151
let mut current = self . tree . get_mut ( self . current_node . unwrap ( ) ) . unwrap ( ) ;
152
152
let tree_node = current. append ( node) ;
153
153
nodes. push ( tree_node. id ( ) ) ;
154
- elements. push ( JSXElementChild :: JSXFragment ( fragment. clone ( ) ) ) ;
154
+ elements. push ( child) ;
155
+ } ,
156
+ // 找到函数调用中的 JSX
157
+ JSXElementChild :: JSXExprContainer ( expr) => {
158
+ match & expr. expr {
159
+ JSXExpr :: JSXEmptyExpr ( _) => { } ,
160
+ JSXExpr :: Expr ( expr) => {
161
+ match & * * expr {
162
+ Expr :: Call ( call_expr) => {
163
+ match & call_expr. callee {
164
+ Callee :: Expr ( expr) => {
165
+ match & * * expr {
166
+ Expr :: Ident ( ident) => {
167
+ let name = ident. sym . to_string ( ) ;
168
+ let mut visitor = JSXFragmentVisitor :: new ( self . module , name. as_str ( ) , SearchType :: Normal ) ;
169
+ self . module . visit_with ( & mut visitor) ;
170
+ let mut current = self . tree . get_mut ( self . current_node . unwrap ( ) ) . unwrap ( ) ;
171
+ // 将 Fragment 的子节点添加到当前节点
172
+ recursion_sub_tree ( & visitor. tree . root ( ) , & mut current) ;
173
+ } ,
174
+ Expr :: Member ( member_expr) => {
175
+ if let Expr :: This ( _) = & * member_expr. obj {
176
+ match & member_expr. prop {
177
+ MemberProp :: Ident ( ident) => {
178
+ let name = ident. sym . to_string ( ) ;
179
+ let mut visitor = JSXFragmentVisitor :: new ( self . module , name. as_str ( ) , SearchType :: Class ) ;
180
+ self . module . visit_with ( & mut visitor) ;
181
+ let mut current = self . tree . get_mut ( self . current_node . unwrap ( ) ) . unwrap ( ) ;
182
+ // 将 Fragment 的子节点添加到当前节点
183
+ recursion_sub_tree ( & visitor. tree . root ( ) , & mut current) ;
184
+ } ,
185
+ _ => { }
186
+ }
187
+ }
188
+ } ,
189
+ _ => { }
190
+ }
191
+ } ,
192
+ _ => { }
193
+ }
194
+ } ,
195
+ _ => { }
196
+ }
197
+ } ,
198
+ }
155
199
} ,
156
200
_ => { }
157
201
}
@@ -165,27 +209,35 @@ impl<'a> Visit for JSXVisitor<'a> {
165
209
}
166
210
}
167
211
212
+ #[ derive( PartialEq ) ]
213
+ pub enum SearchType {
214
+ Normal ,
215
+ Class
216
+ }
217
+
168
218
pub struct JSXFragmentVisitor < ' a > {
169
219
pub module : & ' a Module ,
170
220
pub tree : Tree < Node > ,
171
- pub search_fn : & ' a str
221
+ pub search_fn : & ' a str ,
222
+ pub search_type : SearchType
172
223
}
173
224
174
225
impl < ' a > JSXFragmentVisitor < ' a > {
175
- pub fn new ( module : & ' a Module , search_fn : & ' a str ) -> Self {
226
+ pub fn new ( module : & ' a Module , search_fn : & ' a str , search_type : SearchType ) -> Self {
176
227
JSXFragmentVisitor {
177
228
module,
178
229
tree : Tree :: new ( Node :: Fragment (
179
230
Fragment :: new ( Some ( create_qualname ( search_fn) ) )
180
231
) ) ,
181
- search_fn
232
+ search_fn,
233
+ search_type
182
234
}
183
235
}
184
236
}
185
237
186
238
impl < ' a > Visit for JSXFragmentVisitor < ' a > {
187
239
fn visit_fn_decl ( & mut self , n : & FnDecl ) {
188
- if n. ident . sym . to_string ( ) == self . search_fn {
240
+ if n. ident . sym . to_string ( ) == self . search_fn && self . search_type == SearchType :: Normal {
189
241
match & * n. function {
190
242
Function { body : Some ( body) , .. } => {
191
243
for stmt in & body. stmts {
@@ -202,6 +254,32 @@ impl<'a> Visit for JSXFragmentVisitor<'a> {
202
254
}
203
255
}
204
256
}
257
+
258
+ fn visit_class_method ( & mut self , n : & swc_ecma_ast:: ClassMethod ) {
259
+ if self . search_type == SearchType :: Class {
260
+ match & n. key {
261
+ PropName :: Ident ( ident) => {
262
+ if ident. sym . to_string ( ) == self . search_fn {
263
+ match & * n. function {
264
+ Function { body : Some ( body) , .. } => {
265
+ for stmt in & body. stmts {
266
+ match stmt {
267
+ Stmt :: Return ( return_stmt) => {
268
+ let mut jsx_visitor = JSXVisitor :: new ( & mut self . tree , self . module ) ;
269
+ return_stmt. visit_with ( & mut jsx_visitor) ;
270
+ } ,
271
+ _ => { }
272
+ }
273
+ }
274
+ } ,
275
+ _ => { }
276
+ }
277
+ }
278
+ } ,
279
+ _ => { }
280
+ }
281
+ }
282
+ }
205
283
}
206
284
207
285
pub struct AstVisitor < ' a > {
0 commit comments