@@ -36,6 +36,127 @@ const mapNativeType = (/** @type {string} */ nativeType) => {
36
36
}
37
37
}
38
38
39
+ /**
40
+ * @param {ComponentProp } prop
41
+ * @param {SourceCode } sourceCode
42
+ */
43
+ function getComponentPropData ( prop , sourceCode ) {
44
+ const unknownType = {
45
+ name : prop . propName ,
46
+ type : 'unknown' ,
47
+ required : undefined ,
48
+ defaultValue : undefined
49
+ }
50
+
51
+ if ( prop . type !== 'object' ) {
52
+ return unknownType
53
+ }
54
+ const type = optionGetType ( prop . value , sourceCode )
55
+ if ( type === null ) {
56
+ return unknownType
57
+ }
58
+ const required = optionGetRequired ( prop . value )
59
+ const defaultValue = optionGetDefault ( prop . value )
60
+
61
+ return {
62
+ name : prop . propName ,
63
+ type : mapNativeType ( type ) ,
64
+ required,
65
+ defaultValue
66
+ }
67
+ }
68
+
69
+ /**
70
+ * @param {Expression } node
71
+ * @param {SourceCode } sourceCode
72
+ * @returns {string | null }
73
+ */
74
+ function optionGetType ( node , sourceCode ) {
75
+ switch ( node . type ) {
76
+ case 'Identifier' : {
77
+ return node . name
78
+ }
79
+ case 'ObjectExpression' : {
80
+ // foo: {
81
+ const typeProperty = utils . findProperty ( node , 'type' )
82
+ if ( typeProperty == null ) {
83
+ return null
84
+ }
85
+ if ( typeProperty . value . type === 'TSAsExpression' ) {
86
+ const typeAnnotation = typeProperty . value . typeAnnotation
87
+ if ( typeAnnotation . typeName . name !== 'PropType' ) {
88
+ return null
89
+ }
90
+
91
+ // in some project configuration parser populates deprecated field `typeParameters` instead of `typeArguments`
92
+ const typeArguments =
93
+ 'typeArguments' in typeProperty . value
94
+ ? typeAnnotation . typeArguments
95
+ : typeAnnotation . typeParameters
96
+
97
+ const typeArgument = Array . isArray ( typeArguments )
98
+ ? typeArguments [ 0 ] . params [ 0 ]
99
+ : typeArguments . params [ 0 ]
100
+
101
+ if ( typeArgument === undefined ) {
102
+ return null
103
+ }
104
+
105
+ return sourceCode . getText ( typeArgument )
106
+ }
107
+ return optionGetType ( typeProperty . value , sourceCode )
108
+ }
109
+ case 'ArrayExpression' : {
110
+ return null
111
+ }
112
+ case 'FunctionExpression' :
113
+ case 'ArrowFunctionExpression' : {
114
+ return null
115
+ }
116
+ }
117
+
118
+ // Unknown
119
+ return null
120
+ }
121
+
122
+ /**
123
+ * @param {Expression } node
124
+ * @returns {boolean | undefined }
125
+ */
126
+ function optionGetRequired ( node ) {
127
+ if ( node . type === 'ObjectExpression' ) {
128
+ const requiredProperty = utils . findProperty ( node , 'required' )
129
+ if ( requiredProperty == null ) {
130
+ return undefined
131
+ }
132
+
133
+ if ( requiredProperty . value . type === 'Literal' ) {
134
+ return Boolean ( requiredProperty . value . value )
135
+ }
136
+ }
137
+
138
+ // Unknown
139
+ return undefined
140
+ }
141
+
142
+ /**
143
+ * @param {Expression } node
144
+ * @returns {Expression | undefined }
145
+ */
146
+ function optionGetDefault ( node ) {
147
+ if ( node . type === 'ObjectExpression' ) {
148
+ const defaultProperty = utils . findProperty ( node , 'default' )
149
+ if ( defaultProperty == null ) {
150
+ return undefined
151
+ }
152
+
153
+ return defaultProperty . value
154
+ }
155
+
156
+ // Unknown
157
+ return undefined
158
+ }
159
+
39
160
/**
40
161
* @typedef {import('../utils').ComponentProp } ComponentProp
41
162
*/
@@ -72,93 +193,6 @@ module.exports = {
72
193
create ( context ) {
73
194
const sourceCode = context . getSourceCode ( )
74
195
75
- /**
76
- * @param {Expression } node
77
- * @returns {string | null }
78
- */
79
- function optionGetType ( node ) {
80
- switch ( node . type ) {
81
- case 'Identifier' : {
82
- return node . name
83
- }
84
- case 'ObjectExpression' : {
85
- // foo: {
86
- const typeProperty = utils . findProperty ( node , 'type' )
87
- if ( typeProperty == null ) {
88
- return null
89
- }
90
- if ( typeProperty . value . type === 'TSAsExpression' ) {
91
- if (
92
- typeProperty . value . typeAnnotation . typeName . name !== 'PropType'
93
- ) {
94
- return null
95
- }
96
-
97
- const typeArgument =
98
- typeProperty . value . typeAnnotation . typeArguments . params [ 0 ]
99
- if ( typeArgument === undefined ) {
100
- return null
101
- }
102
-
103
- return sourceCode . getText ( typeArgument )
104
- }
105
- return optionGetType ( typeProperty . value )
106
- }
107
- case 'ArrayExpression' : {
108
- // foo: [
109
- return null
110
- // return node.elements.map((arrayElement) =>
111
- // optionGetType(arrayElement)
112
- // )
113
- }
114
- case 'FunctionExpression' :
115
- case 'ArrowFunctionExpression' : {
116
- return null
117
- }
118
- }
119
-
120
- // Unknown
121
- return null
122
- }
123
-
124
- /**
125
- * @param {Expression } node
126
- * @returns {boolean | undefined }
127
- */
128
- function optionGetRequired ( node ) {
129
- if ( node . type === 'ObjectExpression' ) {
130
- const requiredProperty = utils . findProperty ( node , 'required' )
131
- if ( requiredProperty == null ) {
132
- return undefined
133
- }
134
-
135
- if ( requiredProperty . value . type === 'Literal' ) {
136
- return Boolean ( requiredProperty . value . value )
137
- }
138
- }
139
-
140
- // Unknown
141
- return undefined
142
- }
143
-
144
- /**
145
- * @param {Expression } node
146
- * @returns {Expression | undefined }
147
- */
148
- function optionGetDefault ( node ) {
149
- if ( node . type === 'ObjectExpression' ) {
150
- const defaultProperty = utils . findProperty ( node , 'default' )
151
- if ( defaultProperty == null ) {
152
- return undefined
153
- }
154
-
155
- return defaultProperty . value
156
- }
157
-
158
- // Unknown
159
- return undefined
160
- }
161
-
162
196
const scriptSetup = utils . getScriptSetupElement ( context )
163
197
if ( ! scriptSetup || ! utils . hasAttribute ( scriptSetup , 'lang' , 'ts' ) ) {
164
198
return { }
@@ -176,31 +210,9 @@ module.exports = {
176
210
node,
177
211
messageId : 'hasArg' ,
178
212
* fix ( fixer ) {
179
- const propTypes = props . map ( ( prop ) => {
180
- const unknownType = {
181
- name : prop . propName ,
182
- type : 'unknown' ,
183
- required : undefined ,
184
- defaultValue : undefined
185
- }
186
-
187
- if ( prop . type !== 'object' ) {
188
- return unknownType
189
- }
190
- const type = optionGetType ( prop . value )
191
- if ( type === null ) {
192
- return unknownType
193
- }
194
- const required = optionGetRequired ( prop . value )
195
- const defaultValue = optionGetDefault ( prop . value )
196
-
197
- return {
198
- name : prop . propName ,
199
- type : mapNativeType ( type ) ,
200
- required,
201
- defaultValue
202
- }
203
- } )
213
+ const propTypes = props . map ( ( prop ) =>
214
+ getComponentPropData ( prop , sourceCode )
215
+ )
204
216
205
217
const definePropsType = `{ ${ propTypes
206
218
. map (
@@ -209,8 +221,10 @@ module.exports = {
209
221
)
210
222
. join ( ', ' ) } }`
211
223
224
+ // remove defineProps function parameters
212
225
yield fixer . replaceText ( node . arguments [ 0 ] , '' )
213
226
227
+ // add type annotation
214
228
if ( separateInterface ) {
215
229
const variableDeclarationNode = node . parent . parent
216
230
if ( ! variableDeclarationNode ) return
@@ -227,6 +241,7 @@ module.exports = {
227
241
)
228
242
}
229
243
244
+ // add defaults if needed
230
245
const defaults = propTypes . filter (
231
246
( { defaultValue } ) => defaultValue
232
247
)
0 commit comments