Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 0edb94a

Browse files
feat(eslint-plugin): [explicit-member-accessibility] suggest adding explicit accessibility specifiers (typescript-eslint#5492)
* feat(eslint-plugin): [explicit-member-accessibility] autofix missing accessibility * Convert auto-fix to suggestions * remove trim()s * Update packages/eslint-plugin/src/rules/explicit-member-accessibility.ts Co-authored-by: Josh Goldberg <[email protected]> * merge message IDs * ! Co-authored-by: Josh Goldberg <[email protected]> Co-authored-by: Josh Goldberg <[email protected]>
1 parent 1b2601a commit 0edb94a

File tree

2 files changed

+1291
-70
lines changed

2 files changed

+1291
-70
lines changed

packages/eslint-plugin/src/rules/explicit-member-accessibility.ts

Lines changed: 101 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,10 @@ interface Config {
2525

2626
type Options = [Config];
2727

28-
type MessageIds = 'unwantedPublicAccessibility' | 'missingAccessibility';
28+
type MessageIds =
29+
| 'unwantedPublicAccessibility'
30+
| 'missingAccessibility'
31+
| 'addExplicitAccessibility';
2932

3033
const accessibilityLevel = {
3134
oneOf: [
@@ -47,6 +50,7 @@ const accessibilityLevel = {
4750
export default util.createRule<Options, MessageIds>({
4851
name: 'explicit-member-accessibility',
4952
meta: {
53+
hasSuggestions: true,
5054
type: 'problem',
5155
docs: {
5256
description:
@@ -60,6 +64,7 @@ export default util.createRule<Options, MessageIds>({
6064
'Missing accessibility modifier on {{type}} {{name}}.',
6165
unwantedPublicAccessibility:
6266
'Public accessibility modifier on {{type}} {{name}}.',
67+
addExplicitAccessibility: "Add '{{ type }}' accessibility modifier",
6368
},
6469
schema: [
6570
{
@@ -103,26 +108,6 @@ export default util.createRule<Options, MessageIds>({
103108
const propCheck = overrides.properties ?? baseCheck;
104109
const paramPropCheck = overrides.parameterProperties ?? baseCheck;
105110
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-
}
126111

127112
/**
128113
* Checks if a method declaration has an accessibility modifier.
@@ -164,20 +149,25 @@ export default util.createRule<Options, MessageIds>({
164149
check === 'no-public' &&
165150
methodDefinition.accessibility === 'public'
166151
) {
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+
});
174161
} 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+
});
181171
}
182172
}
183173

@@ -223,6 +213,48 @@ export default util.createRule<Options, MessageIds>({
223213
};
224214
}
225215

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+
226258
/**
227259
* Checks if property has an accessibility modifier.
228260
* @param propertyDefinition The node representing a PropertyDefinition.
@@ -246,23 +278,28 @@ export default util.createRule<Options, MessageIds>({
246278
propCheck === 'no-public' &&
247279
propertyDefinition.accessibility === 'public'
248280
) {
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+
});
256290
} else if (
257291
propCheck === 'explicit' &&
258292
!propertyDefinition.accessibility
259293
) {
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+
});
266303
}
267304
}
268305

@@ -291,19 +328,29 @@ export default util.createRule<Options, MessageIds>({
291328
switch (paramPropCheck) {
292329
case 'explicit': {
293330
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+
});
295340
}
296341
break;
297342
}
298343
case 'no-public': {
299344
if (node.accessibility === 'public' && node.readonly) {
300-
reportIssue(
301-
'unwantedPublicAccessibility',
302-
nodeType,
345+
context.report({
303346
node,
304-
nodeName,
305-
getUnwantedPublicAccessibilityFixer(node),
306-
);
347+
messageId: 'unwantedPublicAccessibility',
348+
data: {
349+
type: nodeType,
350+
name: nodeName,
351+
},
352+
fix: getUnwantedPublicAccessibilityFixer(node),
353+
});
307354
}
308355
break;
309356
}

0 commit comments

Comments
 (0)