diff --git a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts index fe0637cb8e5..7ac808329df 100644 --- a/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts +++ b/packages/eslint-plugin/src/rules/explicit-member-accessibility.ts @@ -25,7 +25,10 @@ interface Config { type Options = [Config]; -type MessageIds = 'unwantedPublicAccessibility' | 'missingAccessibility'; +type MessageIds = + | 'unwantedPublicAccessibility' + | 'missingAccessibility' + | 'addExplicitAccessibility'; const accessibilityLevel = { oneOf: [ @@ -47,6 +50,7 @@ const accessibilityLevel = { export default util.createRule({ name: 'explicit-member-accessibility', meta: { + hasSuggestions: true, type: 'problem', docs: { description: @@ -60,6 +64,7 @@ export default util.createRule({ 'Missing accessibility modifier on {{type}} {{name}}.', unwantedPublicAccessibility: 'Public accessibility modifier on {{type}} {{name}}.', + addExplicitAccessibility: "Add '{{ type }}' accessibility modifier", }, schema: [ { @@ -103,26 +108,6 @@ export default util.createRule({ const propCheck = overrides.properties ?? baseCheck; const paramPropCheck = overrides.parameterProperties ?? baseCheck; const ignoredMethodNames = new Set(option.ignoredMethodNames ?? []); - /** - * Generates the report for rule violations - */ - function reportIssue( - messageId: MessageIds, - nodeType: string, - node: TSESTree.Node, - nodeName: string, - fix: TSESLint.ReportFixFunction | null = null, - ): void { - context.report({ - node, - messageId, - data: { - type: nodeType, - name: nodeName, - }, - fix, - }); - } /** * Checks if a method declaration has an accessibility modifier. @@ -164,20 +149,25 @@ export default util.createRule({ check === 'no-public' && methodDefinition.accessibility === 'public' ) { - reportIssue( - 'unwantedPublicAccessibility', - nodeType, - methodDefinition, - methodName, - getUnwantedPublicAccessibilityFixer(methodDefinition), - ); + context.report({ + node: methodDefinition, + messageId: 'unwantedPublicAccessibility', + data: { + type: nodeType, + name: methodName, + }, + fix: getUnwantedPublicAccessibilityFixer(methodDefinition), + }); } else if (check === 'explicit' && !methodDefinition.accessibility) { - reportIssue( - 'missingAccessibility', - nodeType, - methodDefinition, - methodName, - ); + context.report({ + node: methodDefinition, + messageId: 'missingAccessibility', + data: { + type: nodeType, + name: methodName, + }, + suggest: getMissingAccessibilitySuggestions(methodDefinition), + }); } } @@ -223,6 +213,48 @@ export default util.createRule({ }; } + /** + * Creates a fixer that adds a "public" keyword with following spaces + */ + function getMissingAccessibilitySuggestions( + node: + | TSESTree.MethodDefinition + | TSESTree.PropertyDefinition + | TSESTree.TSAbstractMethodDefinition + | TSESTree.TSAbstractPropertyDefinition + | TSESTree.TSParameterProperty, + ): TSESLint.ReportSuggestionArray { + function fix( + accessibility: TSESTree.Accessibility, + fixer: TSESLint.RuleFixer, + ): TSESLint.RuleFix | null { + if (node?.decorators?.length) { + const lastDecorator = node.decorators[node.decorators.length - 1]; + const nextToken = sourceCode.getTokenAfter(lastDecorator)!; + return fixer.insertTextBefore(nextToken, `${accessibility} `); + } + return fixer.insertTextBefore(node, `${accessibility} `); + } + + return [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + fix: fixer => fix('public', fixer), + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + fix: fixer => fix('private', fixer), + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + fix: fixer => fix('protected', fixer), + }, + ]; + } + /** * Checks if property has an accessibility modifier. * @param propertyDefinition The node representing a PropertyDefinition. @@ -246,23 +278,28 @@ export default util.createRule({ propCheck === 'no-public' && propertyDefinition.accessibility === 'public' ) { - reportIssue( - 'unwantedPublicAccessibility', - nodeType, - propertyDefinition, - propertyName, - getUnwantedPublicAccessibilityFixer(propertyDefinition), - ); + context.report({ + node: propertyDefinition, + messageId: 'unwantedPublicAccessibility', + data: { + type: nodeType, + name: propertyName, + }, + fix: getUnwantedPublicAccessibilityFixer(propertyDefinition), + }); } else if ( propCheck === 'explicit' && !propertyDefinition.accessibility ) { - reportIssue( - 'missingAccessibility', - nodeType, - propertyDefinition, - propertyName, - ); + context.report({ + node: propertyDefinition, + messageId: 'missingAccessibility', + data: { + type: nodeType, + name: propertyName, + }, + suggest: getMissingAccessibilitySuggestions(propertyDefinition), + }); } } @@ -291,19 +328,29 @@ export default util.createRule({ switch (paramPropCheck) { case 'explicit': { if (!node.accessibility) { - reportIssue('missingAccessibility', nodeType, node, nodeName); + context.report({ + node, + messageId: 'missingAccessibility', + data: { + type: nodeType, + name: nodeName, + }, + suggest: getMissingAccessibilitySuggestions(node), + }); } break; } case 'no-public': { if (node.accessibility === 'public' && node.readonly) { - reportIssue( - 'unwantedPublicAccessibility', - nodeType, + context.report({ node, - nodeName, - getUnwantedPublicAccessibilityFixer(node), - ); + messageId: 'unwantedPublicAccessibility', + data: { + type: nodeType, + name: nodeName, + }, + fix: getUnwantedPublicAccessibilityFixer(node), + }); } break; } diff --git a/packages/eslint-plugin/tests/rules/explicit-member-accessibility.test.ts b/packages/eslint-plugin/tests/rules/explicit-member-accessibility.test.ts index cf387053c29..04a6fa55842 100644 --- a/packages/eslint-plugin/tests/rules/explicit-member-accessibility.test.ts +++ b/packages/eslint-plugin/tests/rules/explicit-member-accessibility.test.ts @@ -366,9 +366,37 @@ export class XXXX { messageId: 'missingAccessibility', column: 22, line: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +export class XXXX { + public constructor(public readonly value: string) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +export class XXXX { + public constructor(private readonly value: string) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +export class XXXX { + public constructor(protected readonly value: string) {} +} + `, + }, + ], }, ], - output: null, }, { filename: 'test.ts', @@ -378,8 +406,40 @@ export class WithParameterProperty { } `, options: [{ accessibility: 'explicit' }], - errors: [{ messageId: 'missingAccessibility' }], - output: null, + errors: [ + { + messageId: 'missingAccessibility', + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +export class WithParameterProperty { + public constructor(public readonly value: string) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +export class WithParameterProperty { + public constructor(private readonly value: string) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +export class WithParameterProperty { + public constructor(protected readonly value: string) {} +} + `, + }, + ], + }, + ], }, { filename: 'test.ts', @@ -397,8 +457,40 @@ export class XXXX { }, }, ], - errors: [{ messageId: 'missingAccessibility' }], - output: null, + errors: [ + { + messageId: 'missingAccessibility', + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +export class XXXX { + public constructor(public readonly samosa: string) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +export class XXXX { + public constructor(private readonly samosa: string) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +export class XXXX { + public constructor(protected readonly samosa: string) {} +} + `, + }, + ], + }, + ], }, { filename: 'test.ts', @@ -413,8 +505,40 @@ class Test { overrides: { parameterProperties: 'explicit' }, }, ], - errors: [{ messageId: 'missingAccessibility' }], - output: null, + errors: [ + { + messageId: 'missingAccessibility', + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + public constructor(public readonly foo: string) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + public constructor(private readonly foo: string) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + public constructor(protected readonly foo: string) {} +} + `, + }, + ], + }, + ], }, { filename: 'test.ts', @@ -435,9 +559,49 @@ class Test { }, line: 3, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + + output: ` +class Test { + public x: number; + public getX() { + return this.x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + + output: ` +class Test { + private x: number; + public getX() { + return this.x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + + output: ` +class Test { + protected x: number; + public getX() { + return this.x; + } +} + `, + }, + ], }, ], - output: null, }, { filename: 'test.ts', @@ -458,9 +622,46 @@ class Test { }, line: 4, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + private x: number; + public getX() { + return this.x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private x: number; + private getX() { + return this.x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + private x: number; + protected getX() { + return this.x; + } +} + `, + }, + ], }, ], - output: null, }, { filename: 'test.ts', @@ -481,6 +682,44 @@ class Test { }, line: 3, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + public x?: number; + getX?() { + return this.x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private x?: number; + getX?() { + return this.x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + protected x?: number; + getX?() { + return this.x; + } +} + `, + }, + ], }, { messageId: 'missingAccessibility', @@ -490,9 +729,46 @@ class Test { }, line: 4, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + x?: number; + public getX?() { + return this.x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + x?: number; + private getX?() { + return this.x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + x?: number; + protected getX?() { + return this.x; + } +} + `, + }, + ], }, ], - output: null, }, { filename: 'test.ts', @@ -613,15 +889,126 @@ class Test { messageId: 'missingAccessibility', line: 7, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + public get internalValue() { + return this.x; + } + set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + private get internalValue() { + return this.x; + } + set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + protected get internalValue() { + return this.x; + } + set internalValue(value: number) { + this.x = value; + } +} + `, + }, + ], }, { messageId: 'missingAccessibility', line: 10, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + get internalValue() { + return this.x; + } + public set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + get internalValue() { + return this.x; + } + private set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + get internalValue() { + return this.x; + } + protected set internalValue(value: number) { + this.x = value; + } +} + `, + }, + ], }, ], options: [{ overrides: { constructors: 'no-public' } }], - output: null, }, { filename: 'test.ts', @@ -644,19 +1031,186 @@ class Test { messageId: 'missingAccessibility', line: 4, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + private x: number; + public constructor(x: number) { + this.x = x; + } + get internalValue() { + return this.x; + } + set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private x: number; + private constructor(x: number) { + this.x = x; + } + get internalValue() { + return this.x; + } + set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + private x: number; + protected constructor(x: number) { + this.x = x; + } + get internalValue() { + return this.x; + } + set internalValue(value: number) { + this.x = value; + } +} + `, + }, + ], }, { messageId: 'missingAccessibility', line: 7, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + public get internalValue() { + return this.x; + } + set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + private get internalValue() { + return this.x; + } + set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + protected get internalValue() { + return this.x; + } + set internalValue(value: number) { + this.x = value; + } +} + `, + }, + ], }, { messageId: 'missingAccessibility', line: 10, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + get internalValue() { + return this.x; + } + public set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + get internalValue() { + return this.x; + } + private set internalValue(value: number) { + this.x = value; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + private x: number; + constructor(x: number) { + this.x = x; + } + get internalValue() { + return this.x; + } + protected set internalValue(value: number) { + this.x = value; + } +} + `, + }, + ], }, ], - output: null, }, { filename: 'test.ts', @@ -673,6 +1227,44 @@ class Test { messageId: 'missingAccessibility', line: 3, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + public constructor(public x: number) {} + public foo(): string { + return 'foo'; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private constructor(public x: number) {} + public foo(): string { + return 'foo'; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + protected constructor(public x: number) {} + public foo(): string { + return 'foo'; + } +} + `, + }, + ], }, ], options: [ @@ -680,7 +1272,6 @@ class Test { overrides: { parameterProperties: 'no-public' }, }, ], - output: null, }, { filename: 'test.ts', @@ -694,9 +1285,37 @@ class Test { messageId: 'missingAccessibility', line: 3, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + public constructor(public x: number) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private constructor(public x: number) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + protected constructor(public x: number) {} +} + `, + }, + ], }, ], - output: null, }, { filename: 'test.ts', @@ -742,9 +1361,37 @@ class Test { messageId: 'missingAccessibility', line: 3, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + public x = 2; +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private x = 2; +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + protected x = 2; +} + `, + }, + ], }, ], - output: null, }, { filename: 'test.ts', @@ -786,9 +1433,37 @@ class Test { messageId: 'missingAccessibility', line: 3, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class Test { + public constructor(public ...x: any[]) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class Test { + private constructor(public ...x: any[]) {} +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class Test { + protected constructor(public ...x: any[]) {} +} + `, + }, + ], }, ], - output: null, }, { filename: 'test.ts', @@ -1071,6 +1746,35 @@ abstract class SomeClass { messageId: 'missingAccessibility', line: 3, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +abstract class SomeClass { + public abstract method(): string; +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +abstract class SomeClass { + private abstract method(): string; +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +abstract class SomeClass { + protected abstract method(): string; +} + `, + }, + ], }, ], }, @@ -1112,6 +1816,35 @@ abstract class SomeClass { messageId: 'missingAccessibility', line: 3, column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +abstract class SomeClass { + public abstract x: string; +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +abstract class SomeClass { + private abstract x: string; +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +abstract class SomeClass { + protected abstract x: string; +} + `, + }, + ], }, ], }, @@ -1140,5 +1873,446 @@ abstract class SomeClass { } `, }, + { + code: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + errors: [ + { + messageId: 'missingAccessibility', + line: 3, + column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class DecoratedClass { + public constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class DecoratedClass { + private constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class DecoratedClass { + protected constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + ], + }, + { + messageId: 'missingAccessibility', + line: 3, + column: 15, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() public readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() private readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() protected readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + ], + }, + { + messageId: 'missingAccessibility', + line: 4, + column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() public x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() private x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() protected x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + ], + }, + { + messageId: 'missingAccessibility', + line: 5, + column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() public getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() private getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() protected getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + ], + }, + { + messageId: 'missingAccessibility', + line: 8, + column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + public get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + private get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + protected get y() { + return this.x; + } + @foo @bar() set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + ], + }, + { + messageId: 'missingAccessibility', + line: 13, + column: 3, + suggestions: [ + { + messageId: 'addExplicitAccessibility', + data: { type: 'public' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() public set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'private' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() private set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + { + messageId: 'addExplicitAccessibility', + data: { type: 'protected' }, + output: ` +class DecoratedClass { + constructor(@foo @bar() readonly arg: string) {} + @foo @bar() x: string; + @foo @bar() getX() { + return this.x; + } + @foo + @bar() + get y() { + return this.x; + } + @foo @bar() protected set y(@foo @bar() value: x) { + this.x = x; + } +} + `, + }, + ], + }, + ], + }, ], });