From aeea4cd40e2ac66ff596a205ba7bfc95aa376128 Mon Sep 17 00:00:00 2001 From: Alexander T Date: Thu, 12 Sep 2019 13:05:04 +0300 Subject: [PATCH] feat(eslint-plugin): [no-magic-numbers] add ignoreReadonlyClassProperties option (#938) --- .../docs/rules/no-magic-numbers.md | 28 ++++++++++++ .../src/rules/no-magic-numbers.ts | 25 +++++++++++ .../tests/rules/no-magic-numbers.test.ts | 44 +++++++++++++++++++ .../eslint-plugin/typings/eslint-rules.d.ts | 1 + 4 files changed, 98 insertions(+) diff --git a/packages/eslint-plugin/docs/rules/no-magic-numbers.md b/packages/eslint-plugin/docs/rules/no-magic-numbers.md index cf647833887..215890a2e83 100644 --- a/packages/eslint-plugin/docs/rules/no-magic-numbers.md +++ b/packages/eslint-plugin/docs/rules/no-magic-numbers.md @@ -41,6 +41,34 @@ Examples of **correct** code for the `{ "ignoreNumericLiteralTypes": true }` opt type SmallPrimes = 2 | 3 | 5 | 7 | 11; ``` +### ignoreReadonlyClassProperties + +Examples of **incorrect** code for the `{ "ignoreReadonlyClassProperties": false }` option: + +```ts +/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreReadonlyClassProperties": false }]*/ + +class Foo { + readonly A = 1; + readonly B = 2; + public static readonly C = 1; + static readonly D = 1; +} +``` + +Examples of **correct** code for the `{ "ignoreReadonlyClassProperties": true }` option: + +```ts +/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreReadonlyClassProperties": true }]*/ + +class Foo { + readonly A = 1; + readonly B = 2; + public static readonly C = 1; + static readonly D = 1; +} +``` + ### ignoreEnums A boolean to specify if enums used in Typescript are considered okay. `false` by default. diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 005bae9eb0a..01a2505498f 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -33,6 +33,9 @@ export default util.createRule({ ignoreEnums: { type: 'boolean', }, + ignoreReadonlyClassProperties: { + type: 'boolean', + }, }, }, ], @@ -46,6 +49,7 @@ export default util.createRule({ detectObjects: false, ignoreNumericLiteralTypes: false, ignoreEnums: false, + ignoreReadonlyClassProperties: false, }, ], create(context, [options]) { @@ -149,6 +153,20 @@ export default util.createRule({ return false; } + /** + * Checks if the node parent is a readonly class property + * @param node the node to be validated. + * @returns true if the node parent is a readonly class property + * @private + */ + function isParentTSReadonlyClassProperty(node: TSESTree.Node): boolean { + return ( + !!node.parent && + node.parent.type === AST_NODE_TYPES.ClassProperty && + !!node.parent.readonly + ); + } + return { Literal(node): void { // Check if the node is a TypeScript enum declaration @@ -156,6 +174,13 @@ export default util.createRule({ return; } + if ( + options.ignoreReadonlyClassProperties && + isParentTSReadonlyClassProperty(node) + ) { + return; + } + // Check TypeScript specific nodes for Numeric Literal if ( options.ignoreNumericLiteralTypes && diff --git a/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts b/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts index 09b6c35d0b4..1ab26cfa704 100644 --- a/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts +++ b/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts @@ -41,6 +41,17 @@ ruleTester.run('no-magic-numbers', rule, { code: 'enum foo { SECOND = 1000, NUM = "0123456789" }', options: [{ ignoreEnums: true }], }, + { + code: ` +class Foo { + readonly A = 1; + readonly B = 2; + public static readonly C = 1; + static readonly D = 1; +} + `, + options: [{ ignoreReadonlyClassProperties: true }], + }, ], invalid: [ @@ -166,5 +177,38 @@ ruleTester.run('no-magic-numbers', rule, { }, ], }, + { + code: ` +class Foo { + readonly A = 1; + readonly B = 2; + public static readonly C = 1; + static readonly D = 1; +} + `, + options: [{ ignoreReadonlyClassProperties: false }], + errors: [ + { + messageId: 'noMagic', + line: 3, + column: 16, + }, + { + messageId: 'noMagic', + line: 4, + column: 16, + }, + { + messageId: 'noMagic', + line: 5, + column: 30, + }, + { + messageId: 'noMagic', + line: 6, + column: 23, + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index de6545f744d..120b11433cb 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -199,6 +199,7 @@ declare module 'eslint/lib/rules/no-magic-numbers' { detectObjects?: boolean; ignoreNumericLiteralTypes?: boolean; ignoreEnums?: boolean; + ignoreReadonlyClassProperties?: boolean; }, ], {