diff --git a/packages/eslint-plugin/src/rules/no-magic-numbers.ts b/packages/eslint-plugin/src/rules/no-magic-numbers.ts index 01a2505498f6..e3597cf83485 100644 --- a/packages/eslint-plugin/src/rules/no-magic-numbers.ts +++ b/packages/eslint-plugin/src/rules/no-magic-numbers.ts @@ -160,11 +160,23 @@ export default util.createRule({ * @private */ function isParentTSReadonlyClassProperty(node: TSESTree.Node): boolean { - return ( - !!node.parent && + if ( + node.parent && + node.parent.type === AST_NODE_TYPES.UnaryExpression && + ['-', '+'].includes(node.parent.operator) + ) { + node = node.parent; + } + + if ( + node.parent && node.parent.type === AST_NODE_TYPES.ClassProperty && - !!node.parent.readonly - ); + node.parent.readonly + ) { + return true; + } + + return false; } return { @@ -174,13 +186,6 @@ export default util.createRule({ return; } - if ( - options.ignoreReadonlyClassProperties && - isParentTSReadonlyClassProperty(node) - ) { - return; - } - // Check TypeScript specific nodes for Numeric Literal if ( options.ignoreNumericLiteralTypes && @@ -190,6 +195,34 @@ export default util.createRule({ return; } + // Check if the node is a readonly class property + if (isNumber(node) && isParentTSReadonlyClassProperty(node)) { + if (options.ignoreReadonlyClassProperties) { + return; + } + + let fullNumberNode: + | TSESTree.Literal + | TSESTree.UnaryExpression = node; + let raw = node.raw; + + if ( + node.parent && + node.parent.type === AST_NODE_TYPES.UnaryExpression + ) { + fullNumberNode = node.parent; + raw = `${node.parent.operator}${node.raw}`; + } + + context.report({ + messageId: 'noMagic', + node: fullNumberNode, + data: { raw }, + }); + + return; + } + // Let the base rule deal with the rest rules.Literal(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 1ab26cfa704d..f65610ea3f4b 100644 --- a/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts +++ b/packages/eslint-plugin/tests/rules/no-magic-numbers.test.ts @@ -48,6 +48,8 @@ class Foo { readonly B = 2; public static readonly C = 1; static readonly D = 1; + readonly E = -1; + readonly F = +1; } `, options: [{ ignoreReadonlyClassProperties: true }], @@ -184,6 +186,8 @@ class Foo { readonly B = 2; public static readonly C = 1; static readonly D = 1; + readonly E = -1; + readonly F = +1; } `, options: [{ ignoreReadonlyClassProperties: false }], @@ -208,6 +212,16 @@ class Foo { line: 6, column: 23, }, + { + messageId: 'noMagic', + line: 7, + column: 16, + }, + { + messageId: 'noMagic', + line: 8, + column: 16, + }, ], }, ],