66
77const utils = require ( '../utils' )
88const casing = require ( '../utils/casing' )
9+ const regexp = require ( '../utils/regexp' )
910
1011/**
1112 * @param {string } str
@@ -44,69 +45,37 @@ function getRegisteredDirectives(componentObject) {
4445 . filter ( ( res ) => ! ! res )
4546}
4647
47- class DefinedInSetupDirectives {
48- constructor ( ) {
49- /**
50- * Directive names
51- * @type {Set<string> }
52- */
53- this . names = new Set ( )
54- }
55-
56- /**
57- * @param {string } name
58- */
59- addName ( name ) {
60- this . names . add ( name )
61- }
62-
63- /**
64- * @param {string } rawName
65- */
66- isDefinedDirective ( rawName ) {
67- const camelName = camelize ( rawName )
68- const variableName = `v${ casing . capitalize ( camelName ) } `
69- return this . names . has ( variableName )
70- }
48+ /**
49+ * @param {string } rawName
50+ * @param {Set<string> } definedNames
51+ */
52+ function isDefinedInSetup ( rawName , definedNames ) {
53+ const camelName = camelize ( rawName )
54+ const variableName = `v${ casing . capitalize ( camelName ) } `
55+ return definedNames . has ( variableName )
7156}
7257
73- class DefinedInOptionDirectives {
74- constructor ( ) {
75- /**
76- * Directive names
77- * @type {Set<string> }
78- */
79- this . names = new Set ( )
80- }
81-
82- /**
83- * @param {string } name
84- */
85- addName ( name ) {
86- this . names . add ( name )
58+ /**
59+ * @param {string } rawName
60+ * @param {Set<string> } definedNames
61+ */
62+ function isDefinedInOptions ( rawName , definedNames ) {
63+ const camelName = camelize ( rawName )
64+ if ( definedNames . has ( rawName ) || definedNames . has ( camelName ) ) {
65+ return true
8766 }
8867
89- /**
90- * @param { string } rawName
91- */
92- isDefinedDirective ( rawName ) {
93- const camelName = camelize ( rawName )
94- if ( this . names . has ( rawName ) || this . names . has ( camelName ) ) {
68+ // allow case-insensitive only when the directive name itself contains capitalized letters
69+ for ( const name of definedNames ) {
70+ if (
71+ name . toLowerCase ( ) === camelName . toLowerCase ( ) &&
72+ name !== name . toLowerCase ( )
73+ ) {
9574 return true
9675 }
97-
98- // allow case-insensitive ONLY when the directive name itself contains capitalized letters
99- for ( const name of this . names ) {
100- if (
101- name . toLowerCase ( ) === camelName . toLowerCase ( ) &&
102- name !== name . toLowerCase ( )
103- ) {
104- return true
105- }
106- }
107-
108- return false
10976 }
77+
78+ return false
11079}
11180
11281module . exports = {
@@ -122,11 +91,9 @@ module.exports = {
12291 {
12392 type : 'object' ,
12493 properties : {
125- ignorePatterns : {
94+ ignore : {
12695 type : 'array' ,
127- items : {
128- type : 'string'
129- } ,
96+ items : { type : 'string' } ,
13097 uniqueItems : true
13198 }
13299 } ,
@@ -140,8 +107,8 @@ module.exports = {
140107 /** @param {RuleContext } context */
141108 create ( context ) {
142109 const options = context . options [ 0 ] || { }
143- /** @type { string[] } */
144- const ignorePatterns = options . ignorePatterns || [ ]
110+ const { ignore = [ ] } = options
111+ const isAnyIgnored = regexp . toRegExpGroupMatcher ( ignore )
145112
146113 /**
147114 * Check whether the given directive name is a verify target or not.
@@ -150,107 +117,101 @@ module.exports = {
150117 * @returns {boolean }
151118 */
152119 function isVerifyTargetDirective ( rawName ) {
153- if ( utils . isBuiltInDirectiveName ( rawName ) ) {
120+ const kebabName = casing . kebabCase ( rawName )
121+ if (
122+ utils . isBuiltInDirectiveName ( rawName ) ||
123+ isAnyIgnored ( rawName , kebabName )
124+ ) {
154125 return false
155126 }
156-
157- const ignored = ignorePatterns . some ( ( pattern ) =>
158- new RegExp ( pattern ) . test ( rawName )
159- )
160- return ! ignored
127+ return true
161128 }
162129
163- /** @type { (rawName:string, reportNode: ASTNode) => void } */
164- let verifyName
165- /** @type {RuleListener } */
166- let scriptVisitor = { }
167- /** @type {TemplateListener } */
168- const templateBodyVisitor = {
169- /** @param {VDirective } node */
170- 'VAttribute[directive=true]' ( node ) {
171- const name = node . key . name . name
172- if ( utils . isBuiltInDirectiveName ( name ) ) {
173- return
130+ /**
131+ * @param {(rawName: string) => boolean } isDefined
132+ * @returns {TemplateListener }
133+ */
134+ function createTemplateBodyVisitor ( isDefined ) {
135+ return {
136+ /** @param {VDirective } node */
137+ 'VAttribute[directive=true]' ( node ) {
138+ const name = node . key . name . name
139+ if ( utils . isBuiltInDirectiveName ( name ) ) {
140+ return
141+ }
142+ const rawName = node . key . name . rawName || name
143+ if ( isVerifyTargetDirective ( rawName ) && ! isDefined ( rawName ) ) {
144+ context . report ( {
145+ node : node . key ,
146+ messageId : 'undef' ,
147+ data : {
148+ name : rawName
149+ }
150+ } )
151+ }
174152 }
175- verifyName ( node . key . name . rawName || name , node . key )
176153 }
177154 }
178155
179156 if ( utils . isScriptSetup ( context ) ) {
180157 // For <script setup>
181- const definedInSetupDirectives = new DefinedInSetupDirectives ( )
182- const definedInOptionDirectives = new DefinedInOptionDirectives ( )
158+ /** @type {Set<string> } */
159+ const definedInSetupDirectives = new Set ( )
160+ /** @type {Set<string> } */
161+ const definedInOptionDirectives = new Set ( )
183162
184163 const globalScope = context . sourceCode . scopeManager . globalScope
185164 if ( globalScope ) {
186165 for ( const variable of globalScope . variables ) {
187- definedInSetupDirectives . addName ( variable . name )
166+ definedInSetupDirectives . add ( variable . name )
188167 }
189168 const moduleScope = globalScope . childScopes . find (
190169 ( scope ) => scope . type === 'module'
191170 )
192171 for ( const variable of ( moduleScope && moduleScope . variables ) || [ ] ) {
193- definedInSetupDirectives . addName ( variable . name )
172+ definedInSetupDirectives . add ( variable . name )
194173 }
195174 }
196175
197- scriptVisitor = utils . defineVueVisitor ( context , {
176+ const scriptVisitor = utils . defineVueVisitor ( context , {
198177 onVueObjectEnter ( node ) {
199178 for ( const directive of getRegisteredDirectives ( node ) ) {
200- definedInOptionDirectives . addName ( directive . name )
179+ definedInOptionDirectives . add ( directive . name )
201180 }
202181 }
203182 } )
204183
205- verifyName = ( rawName , reportNode ) => {
206- if (
207- ! isVerifyTargetDirective ( rawName ) ||
208- definedInSetupDirectives . isDefinedDirective ( rawName ) ||
209- definedInOptionDirectives . isDefinedDirective ( rawName )
210- ) {
211- return
212- }
184+ const templateBodyVisitor = createTemplateBodyVisitor (
185+ ( rawName ) =>
186+ isDefinedInSetup ( rawName , definedInSetupDirectives ) ||
187+ isDefinedInOptions ( rawName , definedInOptionDirectives )
188+ )
213189
214- context . report ( {
215- node : reportNode ,
216- messageId : 'undef' ,
217- data : {
218- name : rawName
219- }
220- } )
221- }
190+ return utils . defineTemplateBodyVisitor (
191+ context ,
192+ templateBodyVisitor ,
193+ scriptVisitor
194+ )
222195 } else {
223196 // For Options API
224- const definedInOptionDirectives = new DefinedInOptionDirectives ( )
197+ /** @type {Set<string> } */
198+ const definedInOptionDirectives = new Set ( )
225199
226- scriptVisitor = utils . executeOnVue ( context , ( obj ) => {
200+ const scriptVisitor = utils . executeOnVue ( context , ( obj ) => {
227201 for ( const directive of getRegisteredDirectives ( obj ) ) {
228- definedInOptionDirectives . addName ( directive . name )
202+ definedInOptionDirectives . add ( directive . name )
229203 }
230204 } )
231205
232- verifyName = ( rawName , reportNode ) => {
233- if (
234- ! isVerifyTargetDirective ( rawName ) ||
235- definedInOptionDirectives . isDefinedDirective ( rawName )
236- ) {
237- return
238- }
206+ const templateBodyVisitor = createTemplateBodyVisitor ( ( rawName ) =>
207+ isDefinedInOptions ( rawName , definedInOptionDirectives )
208+ )
239209
240- context . report ( {
241- node : reportNode ,
242- messageId : 'undef' ,
243- data : {
244- name : rawName
245- }
246- } )
247- }
210+ return utils . defineTemplateBodyVisitor (
211+ context ,
212+ templateBodyVisitor ,
213+ scriptVisitor
214+ )
248215 }
249-
250- return utils . defineTemplateBodyVisitor (
251- context ,
252- templateBodyVisitor ,
253- scriptVisitor
254- )
255216 }
256217}
0 commit comments