@@ -25,7 +25,10 @@ interface Config {
25
25
26
26
type Options = [ Config ] ;
27
27
28
- type MessageIds = 'unwantedPublicAccessibility' | 'missingAccessibility' ;
28
+ type MessageIds =
29
+ | 'unwantedPublicAccessibility'
30
+ | 'missingAccessibility'
31
+ | 'addExplicitAccessibility' ;
29
32
30
33
const accessibilityLevel = {
31
34
oneOf : [
@@ -47,6 +50,7 @@ const accessibilityLevel = {
47
50
export default util . createRule < Options , MessageIds > ( {
48
51
name : 'explicit-member-accessibility' ,
49
52
meta : {
53
+ hasSuggestions : true ,
50
54
type : 'problem' ,
51
55
docs : {
52
56
description :
@@ -60,6 +64,7 @@ export default util.createRule<Options, MessageIds>({
60
64
'Missing accessibility modifier on {{type}} {{name}}.' ,
61
65
unwantedPublicAccessibility :
62
66
'Public accessibility modifier on {{type}} {{name}}.' ,
67
+ addExplicitAccessibility : "Add '{{ type }}' accessibility modifier" ,
63
68
} ,
64
69
schema : [
65
70
{
@@ -103,26 +108,6 @@ export default util.createRule<Options, MessageIds>({
103
108
const propCheck = overrides . properties ?? baseCheck ;
104
109
const paramPropCheck = overrides . parameterProperties ?? baseCheck ;
105
110
const ignoredMethodNames = new Set ( option . ignoredMethodNames ?? [ ] ) ;
106
- /**
107
- * Generates the report for rule violations
108
- */
109
- function reportIssue (
110
- messageId : MessageIds ,
111
- nodeType : string ,
112
- node : TSESTree . Node ,
113
- nodeName : string ,
114
- fix : TSESLint . ReportFixFunction | null = null ,
115
- ) : void {
116
- context . report ( {
117
- node,
118
- messageId,
119
- data : {
120
- type : nodeType ,
121
- name : nodeName ,
122
- } ,
123
- fix,
124
- } ) ;
125
- }
126
111
127
112
/**
128
113
* Checks if a method declaration has an accessibility modifier.
@@ -164,20 +149,25 @@ export default util.createRule<Options, MessageIds>({
164
149
check === 'no-public' &&
165
150
methodDefinition . accessibility === 'public'
166
151
) {
167
- reportIssue (
168
- 'unwantedPublicAccessibility' ,
169
- nodeType ,
170
- methodDefinition ,
171
- methodName ,
172
- getUnwantedPublicAccessibilityFixer ( methodDefinition ) ,
173
- ) ;
152
+ context . report ( {
153
+ node : methodDefinition ,
154
+ messageId : 'unwantedPublicAccessibility' ,
155
+ data : {
156
+ type : nodeType ,
157
+ name : methodName ,
158
+ } ,
159
+ fix : getUnwantedPublicAccessibilityFixer ( methodDefinition ) ,
160
+ } ) ;
174
161
} else if ( check === 'explicit' && ! methodDefinition . accessibility ) {
175
- reportIssue (
176
- 'missingAccessibility' ,
177
- nodeType ,
178
- methodDefinition ,
179
- methodName ,
180
- ) ;
162
+ context . report ( {
163
+ node : methodDefinition ,
164
+ messageId : 'missingAccessibility' ,
165
+ data : {
166
+ type : nodeType ,
167
+ name : methodName ,
168
+ } ,
169
+ suggest : getMissingAccessibilitySuggestions ( methodDefinition ) ,
170
+ } ) ;
181
171
}
182
172
}
183
173
@@ -223,6 +213,48 @@ export default util.createRule<Options, MessageIds>({
223
213
} ;
224
214
}
225
215
216
+ /**
217
+ * Creates a fixer that adds a "public" keyword with following spaces
218
+ */
219
+ function getMissingAccessibilitySuggestions (
220
+ node :
221
+ | TSESTree . MethodDefinition
222
+ | TSESTree . PropertyDefinition
223
+ | TSESTree . TSAbstractMethodDefinition
224
+ | TSESTree . TSAbstractPropertyDefinition
225
+ | TSESTree . TSParameterProperty ,
226
+ ) : TSESLint . ReportSuggestionArray < MessageIds > {
227
+ function fix (
228
+ accessibility : TSESTree . Accessibility ,
229
+ fixer : TSESLint . RuleFixer ,
230
+ ) : TSESLint . RuleFix | null {
231
+ if ( node ?. decorators ?. length ) {
232
+ const lastDecorator = node . decorators [ node . decorators . length - 1 ] ;
233
+ const nextToken = sourceCode . getTokenAfter ( lastDecorator ) ! ;
234
+ return fixer . insertTextBefore ( nextToken , `${ accessibility } ` ) ;
235
+ }
236
+ return fixer . insertTextBefore ( node , `${ accessibility } ` ) ;
237
+ }
238
+
239
+ return [
240
+ {
241
+ messageId : 'addExplicitAccessibility' ,
242
+ data : { type : 'public' } ,
243
+ fix : fixer => fix ( 'public' , fixer ) ,
244
+ } ,
245
+ {
246
+ messageId : 'addExplicitAccessibility' ,
247
+ data : { type : 'private' } ,
248
+ fix : fixer => fix ( 'private' , fixer ) ,
249
+ } ,
250
+ {
251
+ messageId : 'addExplicitAccessibility' ,
252
+ data : { type : 'protected' } ,
253
+ fix : fixer => fix ( 'protected' , fixer ) ,
254
+ } ,
255
+ ] ;
256
+ }
257
+
226
258
/**
227
259
* Checks if property has an accessibility modifier.
228
260
* @param propertyDefinition The node representing a PropertyDefinition.
@@ -246,23 +278,28 @@ export default util.createRule<Options, MessageIds>({
246
278
propCheck === 'no-public' &&
247
279
propertyDefinition . accessibility === 'public'
248
280
) {
249
- reportIssue (
250
- 'unwantedPublicAccessibility' ,
251
- nodeType ,
252
- propertyDefinition ,
253
- propertyName ,
254
- getUnwantedPublicAccessibilityFixer ( propertyDefinition ) ,
255
- ) ;
281
+ context . report ( {
282
+ node : propertyDefinition ,
283
+ messageId : 'unwantedPublicAccessibility' ,
284
+ data : {
285
+ type : nodeType ,
286
+ name : propertyName ,
287
+ } ,
288
+ fix : getUnwantedPublicAccessibilityFixer ( propertyDefinition ) ,
289
+ } ) ;
256
290
} else if (
257
291
propCheck === 'explicit' &&
258
292
! propertyDefinition . accessibility
259
293
) {
260
- reportIssue (
261
- 'missingAccessibility' ,
262
- nodeType ,
263
- propertyDefinition ,
264
- propertyName ,
265
- ) ;
294
+ context . report ( {
295
+ node : propertyDefinition ,
296
+ messageId : 'missingAccessibility' ,
297
+ data : {
298
+ type : nodeType ,
299
+ name : propertyName ,
300
+ } ,
301
+ suggest : getMissingAccessibilitySuggestions ( propertyDefinition ) ,
302
+ } ) ;
266
303
}
267
304
}
268
305
@@ -291,19 +328,29 @@ export default util.createRule<Options, MessageIds>({
291
328
switch ( paramPropCheck ) {
292
329
case 'explicit' : {
293
330
if ( ! node . accessibility ) {
294
- reportIssue ( 'missingAccessibility' , nodeType , node , nodeName ) ;
331
+ context . report ( {
332
+ node,
333
+ messageId : 'missingAccessibility' ,
334
+ data : {
335
+ type : nodeType ,
336
+ name : nodeName ,
337
+ } ,
338
+ suggest : getMissingAccessibilitySuggestions ( node ) ,
339
+ } ) ;
295
340
}
296
341
break ;
297
342
}
298
343
case 'no-public' : {
299
344
if ( node . accessibility === 'public' && node . readonly ) {
300
- reportIssue (
301
- 'unwantedPublicAccessibility' ,
302
- nodeType ,
345
+ context . report ( {
303
346
node,
304
- nodeName ,
305
- getUnwantedPublicAccessibilityFixer ( node ) ,
306
- ) ;
347
+ messageId : 'unwantedPublicAccessibility' ,
348
+ data : {
349
+ type : nodeType ,
350
+ name : nodeName ,
351
+ } ,
352
+ fix : getUnwantedPublicAccessibilityFixer ( node ) ,
353
+ } ) ;
307
354
}
308
355
break ;
309
356
}
0 commit comments