@@ -11,71 +11,12 @@ import {
11
11
import { codeFrameColumns } from '@babel/code-frame' ;
12
12
import { addNamed } from '@babel/helper-module-imports' ;
13
13
14
- function getTypeAnnotation ( node : BabelCore . types . Node ) {
15
- if (
16
- 'typeAnnotation' in node &&
17
- node . typeAnnotation &&
18
- node . typeAnnotation . type === 'TSTypeAnnotation'
19
- ) {
20
- return node . typeAnnotation . typeAnnotation ;
21
- }
22
- }
23
-
24
14
export default ( {
25
15
types : t ,
26
16
} : typeof BabelCore ) : BabelCore . PluginObj < SimpleTypeResolveOptions > => {
27
17
let ctx : SimpleTypeResolveContext | undefined ;
28
18
let helpers : Set < string > | undefined ;
29
19
30
- function processProps (
31
- comp : BabelCore . types . Function ,
32
- options : BabelCore . types . ObjectExpression
33
- ) {
34
- const props = comp . params [ 0 ] ;
35
- if ( ! props ) return ;
36
-
37
- if ( props . type === 'AssignmentPattern' ) {
38
- ctx ! . propsTypeDecl = getTypeAnnotation ( props . left ) ;
39
- ctx ! . propsRuntimeDefaults = props . right ;
40
- } else {
41
- ctx ! . propsTypeDecl = getTypeAnnotation ( props ) ;
42
- }
43
-
44
- if ( ! ctx ! . propsTypeDecl ) return ;
45
-
46
- const runtimeProps = extractRuntimeProps ( ctx ! ) ;
47
- if ( ! runtimeProps ) {
48
- return ;
49
- }
50
-
51
- const ast = parseExpression ( runtimeProps ) ;
52
- options . properties . push ( t . objectProperty ( t . identifier ( 'props' ) , ast ) ) ;
53
- }
54
-
55
- function processEmits (
56
- comp : BabelCore . types . Function ,
57
- options : BabelCore . types . ObjectExpression
58
- ) {
59
- const setupCtx = comp . params [ 1 ] && getTypeAnnotation ( comp . params [ 1 ] ) ;
60
- if (
61
- ! setupCtx ||
62
- ! t . isTSTypeReference ( setupCtx ) ||
63
- ! t . isIdentifier ( setupCtx . typeName , { name : 'SetupContext' } )
64
- )
65
- return ;
66
-
67
- const emitType = setupCtx . typeParameters ?. params [ 0 ] ;
68
- if ( ! emitType ) return ;
69
-
70
- ctx ! . emitsTypeDecl = emitType ;
71
- const runtimeEmits = extractRuntimeEmits ( ctx ! ) ;
72
-
73
- const ast = t . arrayExpression (
74
- Array . from ( runtimeEmits ) . map ( ( e ) => t . stringLiteral ( e ) )
75
- ) ;
76
- options . properties . push ( t . objectProperty ( t . identifier ( 'emits' ) , ast ) ) ;
77
- }
78
-
79
20
return {
80
21
name : 'babel-plugin-resolve-type' ,
81
22
inherits : typescript ,
@@ -125,8 +66,10 @@ export default ({
125
66
) ;
126
67
}
127
68
128
- const node = path . node ;
69
+ const { node } = path ;
70
+
129
71
if ( ! t . isIdentifier ( node . callee , { name : 'defineComponent' } ) ) return ;
72
+ if ( ! checkDefineComponent ( path ) ) return ;
130
73
131
74
const comp = node . arguments [ 0 ] ;
132
75
if ( ! comp || ! t . isFunction ( comp ) ) return ;
@@ -137,14 +80,11 @@ export default ({
137
80
node . arguments . push ( options ) ;
138
81
}
139
82
140
- if ( ! t . isObjectExpression ( options ) ) {
141
- throw new Error (
142
- '[@vue/babel-plugin-resolve-type] Options inside of defineComponent should be an object expression.'
143
- ) ;
144
- }
145
-
146
- processProps ( comp , options ) ;
147
- processEmits ( comp , options ) ;
83
+ node . arguments [ 1 ] = processProps ( comp , options ) || options ;
84
+ node . arguments [ 1 ] = processEmits ( comp , node . arguments [ 1 ] ) || options ;
85
+ } ,
86
+ VariableDeclarator ( path ) {
87
+ inferComponentName ( path ) ;
148
88
} ,
149
89
} ,
150
90
post ( file ) {
@@ -153,4 +93,128 @@ export default ({
153
93
}
154
94
} ,
155
95
} ;
96
+
97
+ function inferComponentName (
98
+ path : BabelCore . NodePath < BabelCore . types . VariableDeclarator >
99
+ ) {
100
+ const id = path . get ( 'id' ) ;
101
+ const init = path . get ( 'init' ) ;
102
+ if ( ! id || ! id . isIdentifier ( ) || ! init || ! init . isCallExpression ( ) ) return ;
103
+
104
+ if ( ! init . get ( 'callee' ) ?. isIdentifier ( { name : 'defineComponent' } ) ) return ;
105
+ if ( ! checkDefineComponent ( init ) ) return ;
106
+
107
+ const nameProperty = t . objectProperty (
108
+ t . identifier ( 'name' ) ,
109
+ t . stringLiteral ( id . node . name )
110
+ ) ;
111
+ const { arguments : args } = init . node ;
112
+ if ( args . length === 0 ) return ;
113
+
114
+ if ( args . length === 1 ) {
115
+ init . node . arguments . push ( t . objectExpression ( [ ] ) ) ;
116
+ }
117
+ args [ 1 ] = addProperty ( t , args [ 1 ] , nameProperty ) ;
118
+ }
119
+
120
+ function processProps (
121
+ comp : BabelCore . types . Function ,
122
+ options :
123
+ | BabelCore . types . ArgumentPlaceholder
124
+ | BabelCore . types . JSXNamespacedName
125
+ | BabelCore . types . SpreadElement
126
+ | BabelCore . types . Expression
127
+ ) {
128
+ const props = comp . params [ 0 ] ;
129
+ if ( ! props ) return ;
130
+
131
+ if ( props . type === 'AssignmentPattern' ) {
132
+ ctx ! . propsTypeDecl = getTypeAnnotation ( props . left ) ;
133
+ ctx ! . propsRuntimeDefaults = props . right ;
134
+ } else {
135
+ ctx ! . propsTypeDecl = getTypeAnnotation ( props ) ;
136
+ }
137
+
138
+ if ( ! ctx ! . propsTypeDecl ) return ;
139
+
140
+ const runtimeProps = extractRuntimeProps ( ctx ! ) ;
141
+ if ( ! runtimeProps ) {
142
+ return ;
143
+ }
144
+
145
+ const ast = parseExpression ( runtimeProps ) ;
146
+ return addProperty (
147
+ t ,
148
+ options ,
149
+ t . objectProperty ( t . identifier ( 'props' ) , ast )
150
+ ) ;
151
+ }
152
+
153
+ function processEmits (
154
+ comp : BabelCore . types . Function ,
155
+ options :
156
+ | BabelCore . types . ArgumentPlaceholder
157
+ | BabelCore . types . JSXNamespacedName
158
+ | BabelCore . types . SpreadElement
159
+ | BabelCore . types . Expression
160
+ ) {
161
+ const setupCtx = comp . params [ 1 ] && getTypeAnnotation ( comp . params [ 1 ] ) ;
162
+ if (
163
+ ! setupCtx ||
164
+ ! t . isTSTypeReference ( setupCtx ) ||
165
+ ! t . isIdentifier ( setupCtx . typeName , { name : 'SetupContext' } )
166
+ )
167
+ return ;
168
+
169
+ const emitType = setupCtx . typeParameters ?. params [ 0 ] ;
170
+ if ( ! emitType ) return ;
171
+
172
+ ctx ! . emitsTypeDecl = emitType ;
173
+ const runtimeEmits = extractRuntimeEmits ( ctx ! ) ;
174
+
175
+ const ast = t . arrayExpression (
176
+ Array . from ( runtimeEmits ) . map ( ( e ) => t . stringLiteral ( e ) )
177
+ ) ;
178
+ return addProperty (
179
+ t ,
180
+ options ,
181
+ t . objectProperty ( t . identifier ( 'emits' ) , ast )
182
+ ) ;
183
+ }
156
184
} ;
185
+
186
+ function getTypeAnnotation ( node : BabelCore . types . Node ) {
187
+ if (
188
+ 'typeAnnotation' in node &&
189
+ node . typeAnnotation &&
190
+ node . typeAnnotation . type === 'TSTypeAnnotation'
191
+ ) {
192
+ return node . typeAnnotation . typeAnnotation ;
193
+ }
194
+ }
195
+
196
+ function checkDefineComponent (
197
+ path : BabelCore . NodePath < BabelCore . types . CallExpression >
198
+ ) {
199
+ const defineCompImport =
200
+ path . scope . getBinding ( 'defineComponent' ) ?. path . parent ;
201
+ if ( ! defineCompImport ) return true ;
202
+
203
+ return (
204
+ defineCompImport . type === 'ImportDeclaration' &&
205
+ / ^ @ ? v u e ( \/ | $ ) / . test ( defineCompImport . source . value )
206
+ ) ;
207
+ }
208
+
209
+ function addProperty < T extends BabelCore . types . Node > (
210
+ t : ( typeof BabelCore ) [ 'types' ] ,
211
+ object : T ,
212
+ property : BabelCore . types . ObjectProperty
213
+ ) {
214
+ if ( t . isObjectExpression ( object ) ) {
215
+ object . properties . unshift ( property ) ;
216
+ } else if ( t . isExpression ( object ) ) {
217
+ return t . objectExpression ( [ property , t . spreadElement ( object ) ] ) ;
218
+ }
219
+ return object ;
220
+ }
0 commit comments