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