4
4
*/
5
5
'use strict'
6
6
7
+ const utils = require ( '../utils' )
8
+ /**
9
+ * @typedef {import('../utils').ComponentProp } ComponentProp
10
+ */
11
+
7
12
// ------------------------------------------------------------------------------
8
13
// Helpers
9
14
// ------------------------------------------------------------------------------
@@ -29,6 +34,97 @@ const isLooksLike = (a, b) =>
29
34
: isLooksLike ( aVal , bVal )
30
35
} )
31
36
37
+ /**
38
+ * @param {ComponentProp } property
39
+ * @param {RuleContext } context
40
+ */
41
+ const checkProperty = ( property , context ) => {
42
+ if ( ! property . value ) {
43
+ return
44
+ }
45
+
46
+ if (
47
+ isLooksLike ( property . value , { type : 'Identifier' , name : 'Object' } ) &&
48
+ property . node . value . type !== 'TSAsExpression'
49
+ ) {
50
+ context . report ( {
51
+ node : property . node ,
52
+ message : 'Expected type annotation on object prop.'
53
+ } )
54
+ }
55
+
56
+ if (
57
+ property . type === 'object' &&
58
+ property . value . type === 'ObjectExpression' &&
59
+ property . node . value . type === 'ObjectExpression'
60
+ ) {
61
+ const typePropert = property . node . value . properties . find (
62
+ ( prop ) =>
63
+ prop . type === 'Property' &&
64
+ prop . key . type === 'Identifier' &&
65
+ prop . key . name === 'type'
66
+ )
67
+ if (
68
+ typePropert &&
69
+ typePropert . type === 'Property' &&
70
+ isLooksLike ( typePropert . value , { type : 'Identifier' , name : 'Object' } )
71
+ ) {
72
+ context . report ( {
73
+ node : property . node ,
74
+ message : 'Expected type annotation on object prop.'
75
+ } )
76
+ }
77
+ }
78
+
79
+ if ( property . node . value . type === 'ObjectExpression' ) {
80
+ for ( const prop of property . node . value . properties ) {
81
+ if ( prop . type !== 'Property' ) {
82
+ continue
83
+ }
84
+ if ( prop . key . type !== 'Identifier' || prop . key . name !== 'type' ) {
85
+ continue
86
+ }
87
+ if ( prop . value . type !== 'TSAsExpression' ) {
88
+ continue
89
+ }
90
+
91
+ const { typeAnnotation } = prop . value
92
+ if (
93
+ [ 'TSAnyKeyword' , 'TSUnknownKeyword' ] . includes ( typeAnnotation . type ) ||
94
+ ! typeAnnotation . typeName ||
95
+ ! [ 'Prop' , 'PropType' ] . includes ( typeAnnotation . typeName . name )
96
+ ) {
97
+ context . report ( {
98
+ node : property . node ,
99
+ message : 'Expected type annotation on object prop.'
100
+ } )
101
+ }
102
+ }
103
+ }
104
+
105
+ if ( property . node . value . type === 'TSAsExpression' ) {
106
+ const { typeAnnotation } = property . node . value
107
+ if ( typeAnnotation . type === 'TSFunctionType' ) {
108
+ return
109
+ }
110
+ if (
111
+ [
112
+ 'TSAnyKeyword' ,
113
+ 'TSTypeLiteral' ,
114
+ 'TSUnknownKeyword' ,
115
+ 'TSObjectKeyword'
116
+ ] . includes ( typeAnnotation . type ) ||
117
+ ! typeAnnotation . typeName ||
118
+ ! [ 'Prop' , 'PropType' ] . includes ( typeAnnotation . typeName . name )
119
+ ) {
120
+ context . report ( {
121
+ node : property . node ,
122
+ message : 'Expected type annotation on object prop.'
123
+ } )
124
+ }
125
+ }
126
+ }
127
+
32
128
//------------------------------------------------------------------------------
33
129
// Rule Definition
34
130
//------------------------------------------------------------------------------
@@ -47,73 +143,21 @@ module.exports = {
47
143
} ,
48
144
/** @param {RuleContext } context */
49
145
create ( context ) {
50
- return {
51
- /** @param {ExportDefaultDeclaration } node */
52
- ExportDefaultDeclaration ( node ) {
53
- if ( node . declaration . type !== 'ObjectExpression' ) {
54
- return
55
- }
56
- if ( ! Array . isArray ( node . declaration . properties ) ) {
57
- return
146
+ return utils . compositingVisitors (
147
+ utils . defineScriptSetupVisitor ( context , {
148
+ onDefinePropsEnter ( _node , props ) {
149
+ for ( const prop of props ) {
150
+ checkProperty ( prop , context )
151
+ }
58
152
}
153
+ } ) ,
154
+ utils . executeOnVue ( context , ( obj ) => {
155
+ const props = utils . getComponentPropsFromOptions ( obj )
59
156
60
- const property = node . declaration . properties . find (
61
- ( property ) =>
62
- property . type === 'Property' &&
63
- isLooksLike ( property . key , { type : 'Identifier' , name : 'props' } ) &&
64
- property . value . type === 'ObjectExpression'
65
- )
66
-
67
- if (
68
- ! property ||
69
- property . type === 'SpreadElement' ||
70
- ! ( 'properties' in property . value )
71
- ) {
72
- return
73
- }
74
- const properties = property . value . properties
75
- . filter (
76
- ( prop ) =>
77
- prop . type === 'Property' && prop . value . type === 'ObjectExpression'
78
- )
79
- . map ( ( prop ) =>
80
- prop . value . properties . find ( ( propValueProperty ) =>
81
- isLooksLike ( propValueProperty . key , {
82
- type : 'Identifier' ,
83
- name : 'type'
84
- } )
85
- )
86
- )
87
- for ( const prop of properties ) {
88
- if ( ! prop ) {
89
- continue
90
- }
91
- if ( isLooksLike ( prop . value , { type : 'Identifier' , name : 'Object' } ) ) {
92
- context . report ( {
93
- node : prop ,
94
- message : 'Expected type annotation on object prop.'
95
- } )
96
- }
97
- if ( prop . value . type === 'TSAsExpression' ) {
98
- const { typeAnnotation } = prop . value
99
- if (
100
- [
101
- 'TSAnyKeyword' ,
102
- 'TSTypeLiteral' ,
103
- 'TSUnknownKeyword' ,
104
- 'TSObjectKeyword'
105
- ] . includes ( typeAnnotation . type ) ||
106
- ! typeAnnotation . typeName ||
107
- ! [ 'Prop' , 'PropType' ] . includes ( typeAnnotation . typeName . name )
108
- ) {
109
- context . report ( {
110
- node : prop ,
111
- message : 'Expected type annotation on object prop.'
112
- } )
113
- }
114
- }
157
+ for ( const prop of props ) {
158
+ checkProperty ( prop , context )
115
159
}
116
- }
117
- }
160
+ } )
161
+ )
118
162
}
119
163
}
0 commit comments