1
1
import { Parser as HTMLParser } from 'htmlparser2'
2
- import { parse , ParserOptions } from '@babel/parser'
2
+ import { parse } from '@babel/parser'
3
+ import { PrivateName , Expression , Statement } from '@babel/types'
3
4
import { camelize , capitalize , isHTMLTag , isSVGTag , isVoidTag } from '@vue/shared'
4
- import traverse from '@babel/traverse'
5
5
import { ParseResult , TagMeta } from './types'
6
6
7
7
export function parseVueSFC ( code : string , id ?: string ) : ParseResult {
@@ -43,8 +43,12 @@ export function parseVueSFC(code: string, id?: string): ParseResult {
43
43
Object . entries ( attributes ) . forEach ( ( [ key , value ] ) => {
44
44
if ( ! value )
45
45
return
46
- if ( key . startsWith ( 'v-' ) || key . startsWith ( '@' ) || key . startsWith ( ':' ) )
47
- expressions . add ( value )
46
+ if ( key . startsWith ( 'v-' ) || key . startsWith ( '@' ) || key . startsWith ( ':' ) ) {
47
+ if ( key === 'v-if' )
48
+ expressions . add ( `for (let ${ value } ) {}` )
49
+ else
50
+ expressions . add ( `(${ value } )` )
51
+ }
48
52
if ( key === 'ref' )
49
53
identifiers . add ( value )
50
54
} )
@@ -71,7 +75,7 @@ export function parseVueSFC(code: string, id?: string): ParseResult {
71
75
ontext ( text ) {
72
76
if ( templateLevel > 0 ) {
73
77
Array . from ( text . matchAll ( / \{ \{ ( .* ?) \} \} / g) ) . forEach ( ( [ , expression ] ) => {
74
- expressions . add ( expression )
78
+ expressions . add ( `( ${ expression } )` )
75
79
} )
76
80
}
77
81
} ,
@@ -102,7 +106,10 @@ export function parseVueSFC(code: string, id?: string): ParseResult {
102
106
parser . write ( code )
103
107
parser . end ( )
104
108
105
- expressions . forEach ( exp => getIdentifiersFromCode ( exp , identifiers ) )
109
+ expressions . forEach ( ( exp ) => {
110
+ const nodes = parse ( exp ) . program . body
111
+ nodes . forEach ( node => getIdentifiersUsage ( node , identifiers ) )
112
+ } )
106
113
107
114
return {
108
115
id,
@@ -115,12 +122,70 @@ export function parseVueSFC(code: string, id?: string): ParseResult {
115
122
}
116
123
}
117
124
118
- export function getIdentifiersFromCode ( code : string , identifiers = new Set < string > ( ) , options : ParserOptions = { } ) {
119
- const ast = parse ( code , options ) as any
120
- traverse ( ast , {
121
- Identifier ( path ) {
122
- identifiers . add ( path . node . name )
123
- } ,
124
- } )
125
+ export function getIdentifiersDeclaration ( nodes : Statement [ ] , identifiers = new Set < string > ( ) ) {
126
+ for ( const node of nodes ) {
127
+ if ( node . type === 'ImportDeclaration' ) {
128
+ for ( const specifier of node . specifiers )
129
+ identifiers . add ( specifier . local . name )
130
+ }
131
+ else if ( node . type === 'VariableDeclaration' ) {
132
+ for ( const declarator of node . declarations ) {
133
+ // @ts -expect-error
134
+ identifiers . add ( declarator . id . name )
135
+ }
136
+ }
137
+ else if ( node . type === 'FunctionDeclaration' ) {
138
+ if ( node . id )
139
+ identifiers . add ( node . id . name )
140
+ }
141
+ // else {
142
+ // console.log(node)
143
+ // }
144
+ }
145
+ return identifiers
146
+ }
147
+
148
+ export function getIdentifiersUsage ( node ?: Expression | PrivateName | Statement , identifiers = new Set < string > ( ) ) {
149
+ if ( ! node )
150
+ return identifiers
151
+
152
+ if ( node . type === 'ExpressionStatement' ) {
153
+ getIdentifiersUsage ( node . expression , identifiers )
154
+ }
155
+ else if ( node . type === 'Identifier' ) {
156
+ identifiers . add ( node . name )
157
+ }
158
+ else if ( node . type === 'MemberExpression' ) {
159
+ getIdentifiersUsage ( node . object , identifiers )
160
+ }
161
+ else if ( node . type === 'CallExpression' ) {
162
+ // @ts -expect-error
163
+ getIdentifiersUsage ( node . callee , identifiers )
164
+ node . arguments . forEach ( ( arg ) => {
165
+ // @ts -expect-error
166
+ getIdentifiersUsage ( arg , identifiers )
167
+ } )
168
+ }
169
+ else if ( node . type === 'BinaryExpression' || node . type === 'LogicalExpression' ) {
170
+ getIdentifiersUsage ( node . left , identifiers )
171
+ getIdentifiersUsage ( node . right , identifiers )
172
+ }
173
+ else if ( node . type === 'ForOfStatement' || node . type === 'ForInStatement' ) {
174
+ getIdentifiersUsage ( node . right , identifiers )
175
+ }
176
+ else if ( node . type === 'ConditionalExpression' ) {
177
+ getIdentifiersUsage ( node . test , identifiers )
178
+ getIdentifiersUsage ( node . consequent , identifiers )
179
+ getIdentifiersUsage ( node . alternate , identifiers )
180
+ }
181
+ else if ( node . type === 'ObjectExpression' ) {
182
+ node . properties . forEach ( ( prop ) => {
183
+ // @ts -expect-error
184
+ getIdentifiersUsage ( prop . value , identifiers )
185
+ } )
186
+ }
187
+ // else {
188
+ // console.log(node)
189
+ // }
125
190
return identifiers
126
191
}
0 commit comments