From f04c04b35512a40c3f897733a093cfb7717e5725 Mon Sep 17 00:00:00 2001 From: Jonathan Delgado Date: Mon, 20 May 2019 15:09:59 -0700 Subject: [PATCH 1/2] fix(no-magic-numbers): add support for TS enums --- .../src/rules/no-magic-numbers.ts | 19 ++++++++++++++++++- .../tests/rules/no-magic-numbers.test.ts | 3 +++ 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index f298bfd68f2..473416e56d9 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -55,6 +55,18 @@ export default util.createRule({ return typeof node.value === 'number'; } + /** + * Checks if the node grandparent is a Typescript enum declaration + * @param node the node to be validated. + * @returns true if the node grandparent is a Typescript enum declaration + * @private + */ + function isGrandparentTSEnumDeclaration(node: TSESTree.Node): boolean { + return node.parent && node.parent.parent + ? node.parent.parent.type === AST_NODE_TYPES.TSEnumDeclaration + : false; + } + /** * Checks if the node grandparent is a Typescript type alias declaration * @param node the node to be validated. @@ -133,7 +145,12 @@ export default util.createRule({ return { Literal(node) { - // Check TypeScript specific nodes + // Check if the node is a TypeScript enum declaration + if (isGrandparentTSEnumDeclaration(node)) { + return; + } + + // Check TypeScript specific nodes for Numeric Literal if ( options.ignoreNumericLiteralTypes && isNumber(node) && 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 2b184ad76b2..e39d7a9e366 100644 --- a/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts +++ b/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts @@ -17,6 +17,9 @@ ruleTester.run('no-magic-numbers', rule, { { code: 'type Foo = true;', }, + { + code: 'enum foo { SECOND = 1000 }', + }, { code: 'type Foo = 1;', options: [{ ignoreNumericLiteralTypes: true }], From 399c522d373a06c4ebbfb68a065a27153ddc59b1 Mon Sep 17 00:00:00 2001 From: Jonathan Delgado Date: Mon, 20 May 2019 17:41:10 -0700 Subject: [PATCH 2/2] fix(eslint-plugin): add ignoreEnums option --- .../docs/rules/no-magic-numbers.md | 24 ++++++++++++ .../src/rules/no-magic-numbers.ts | 31 ++++++++------- .../tests/rules/no-magic-numbers.test.ts | 39 +++++++++++++++++-- .../eslint-plugin/typings/eslint-rules.d.ts | 1 + 4 files changed, 79 insertions(+), 16 deletions(-) diff --git a/packages/eslint-plugin/docs/rules/no-magic-numbers.md b/packages/eslint-plugin/docs/rules/no-magic-numbers.md index 2ff5aab519d..b5a1e92fd09 100644 --- a/packages/eslint-plugin/docs/rules/no-magic-numbers.md +++ b/packages/eslint-plugin/docs/rules/no-magic-numbers.md @@ -41,4 +41,28 @@ Examples of **correct** code for the `{ "ignoreNumericLiteralTypes": true }` opt type SmallPrimes = 2 | 3 | 5 | 7 | 11; ``` +### ignoreEnums + +A boolean to specify if enums used in Typescript are considered okay. `false` by default. + +Examples of **incorrect** code for the `{ "ignoreEnum": false }` option: + +```ts +/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreEnum": false }]*/ + +enum foo = { + SECOND = 1000, +} +``` + +Examples of **correct** code for the `{ "ignoreEnum": true }` option: + +```ts +/*eslint @typescript-eslint/no-magic-numbers: ["error", { "ignoreEnum": true }]*/ + +enum foo = { + SECOND = 1000, +} +``` + Taken with ❤️ [from ESLint core](https://github.com/eslint/eslint/blob/master/docs/rules/no-magic-numbers.md) diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 473416e56d9..1880aa19c9d 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -29,6 +29,9 @@ export default util.createRule({ ignoreNumericLiteralTypes: { type: 'boolean', }, + ignoreEnums: { + type: 'boolean', + }, }, }, ], @@ -41,6 +44,7 @@ export default util.createRule({ enforceConst: false, detectObjects: false, ignoreNumericLiteralTypes: false, + ignoreEnums: false, }, ], create(context, [options]) { @@ -55,18 +59,6 @@ export default util.createRule({ return typeof node.value === 'number'; } - /** - * Checks if the node grandparent is a Typescript enum declaration - * @param node the node to be validated. - * @returns true if the node grandparent is a Typescript enum declaration - * @private - */ - function isGrandparentTSEnumDeclaration(node: TSESTree.Node): boolean { - return node.parent && node.parent.parent - ? node.parent.parent.type === AST_NODE_TYPES.TSEnumDeclaration - : false; - } - /** * Checks if the node grandparent is a Typescript type alias declaration * @param node the node to be validated. @@ -97,6 +89,19 @@ export default util.createRule({ return false; } + /** + * Checks if the node parent is a Typescript enum member + * @param node the node to be validated. + * @returns true if the node parent is a Typescript enum member + * @private + */ + function isParentTSEnumDeclaration(node: TSESTree.Node): boolean { + return ( + typeof node.parent !== 'undefined' && + node.parent.type === AST_NODE_TYPES.TSEnumMember + ); + } + /** * Checks if the node parent is a Typescript literal type * @param node the node to be validated. @@ -146,7 +151,7 @@ export default util.createRule({ return { Literal(node) { // Check if the node is a TypeScript enum declaration - if (isGrandparentTSEnumDeclaration(node)) { + if (options.ignoreEnums && isParentTSEnumDeclaration(node)) { return; } 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 e39d7a9e366..09b6c35d0b4 100644 --- a/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts +++ b/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts @@ -17,9 +17,6 @@ ruleTester.run('no-magic-numbers', rule, { { code: 'type Foo = true;', }, - { - code: 'enum foo { SECOND = 1000 }', - }, { code: 'type Foo = 1;', options: [{ ignoreNumericLiteralTypes: true }], @@ -36,6 +33,14 @@ ruleTester.run('no-magic-numbers', rule, { code: 'type Foo = 1 | -1;', options: [{ ignoreNumericLiteralTypes: true }], }, + { + code: 'enum foo { SECOND = 1000 }', + options: [{ ignoreEnums: true }], + }, + { + code: 'enum foo { SECOND = 1000, NUM = "0123456789" }', + options: [{ ignoreEnums: true }], + }, ], invalid: [ @@ -133,5 +138,33 @@ ruleTester.run('no-magic-numbers', rule, { }, ], }, + { + code: 'enum foo { SECOND = 1000 }', + options: [{ ignoreEnums: false }], + errors: [ + { + messageId: 'noMagic', + data: { + raw: '1000', + }, + line: 1, + column: 21, + }, + ], + }, + { + code: 'enum foo { SECOND = 1000, NUM = "0123456789" }', + options: [{ ignoreEnums: false }], + errors: [ + { + messageId: 'noMagic', + data: { + raw: '1000', + }, + line: 1, + column: 21, + }, + ], + }, ], }); diff --git a/packages/eslint-plugin/typings/eslint-rules.d.ts b/packages/eslint-plugin/typings/eslint-rules.d.ts index 98ee285d1a2..774f0842aa5 100644 --- a/packages/eslint-plugin/typings/eslint-rules.d.ts +++ b/packages/eslint-plugin/typings/eslint-rules.d.ts @@ -180,6 +180,7 @@ declare module 'eslint/lib/rules/no-magic-numbers' { enforceConst?: boolean; detectObjects?: boolean; ignoreNumericLiteralTypes?: boolean; + ignoreEnums?: boolean; } ], {