diff --git a/packages/eslint-plugin/src/rules/prefer-literal-enum-member.ts b/packages/eslint-plugin/src/rules/prefer-literal-enum-member.ts index 65336c9d2051..1535cca21ea7 100644 --- a/packages/eslint-plugin/src/rules/prefer-literal-enum-member.ts +++ b/packages/eslint-plugin/src/rules/prefer-literal-enum-member.ts @@ -77,69 +77,66 @@ export default createRule({ return false; } - function isAllowedBitwiseOperand( - decl: TSESTree.TSEnumDeclaration, - node: TSESTree.Node, - ): boolean { - return ( - node.type === AST_NODE_TYPES.Literal || isSelfEnumMember(decl, node) - ); - } - return { TSEnumMember(node): void { // If there is no initializer, then this node is just the name of the member, so ignore. if (node.initializer == null) { return; } - // any old literal - if (node.initializer.type === AST_NODE_TYPES.Literal) { - return; - } - // TemplateLiteral without expressions - if ( - node.initializer.type === AST_NODE_TYPES.TemplateLiteral && - node.initializer.expressions.length === 0 - ) { - return; - } const declaration = node.parent.parent; - // -1 and +1 - if (node.initializer.type === AST_NODE_TYPES.UnaryExpression) { - if ( - node.initializer.argument.type === AST_NODE_TYPES.Literal && - ['+', '-'].includes(node.initializer.operator) - ) { - return; + function isAllowedInitializerExpressionRecursive( + node: TSESTree.Expression | TSESTree.PrivateIdentifier, + partOfBitwiseComputation: boolean, + ): boolean { + // You can only refer to an enum member if it's part of a bitwise computation. + // so C = B isn't allowed (special case), but C = A | B is. + if (partOfBitwiseComputation && isSelfEnumMember(declaration, node)) { + return true; } - if ( - allowBitwiseExpressions && - node.initializer.operator === '~' && - isAllowedBitwiseOperand(declaration, node.initializer.argument) - ) { - return; + switch (node.type) { + // any old literal + case AST_NODE_TYPES.Literal: + return true; + + // TemplateLiteral without expressions + case AST_NODE_TYPES.TemplateLiteral: + return node.expressions.length === 0; + + case AST_NODE_TYPES.UnaryExpression: + // +123, -123, etc. + if (['+', '-'].includes(node.operator)) { + return isAllowedInitializerExpressionRecursive( + node.argument, + partOfBitwiseComputation, + ); + } + + if (allowBitwiseExpressions) { + return ( + node.operator === '~' && + isAllowedInitializerExpressionRecursive(node.argument, true) + ); + } + return false; + + case AST_NODE_TYPES.BinaryExpression: + if (allowBitwiseExpressions) { + return ( + ['|', '&', '^', '<<', '>>', '>>>'].includes(node.operator) && + isAllowedInitializerExpressionRecursive(node.left, true) && + isAllowedInitializerExpressionRecursive(node.right, true) + ); + } + return false; + + default: + return false; } } - if ( - node.initializer.type === AST_NODE_TYPES.UnaryExpression && - node.initializer.argument.type === AST_NODE_TYPES.Literal && - (['+', '-'].includes(node.initializer.operator) || - (allowBitwiseExpressions && node.initializer.operator === '~')) - ) { - return; - } - if ( - allowBitwiseExpressions && - node.initializer.type === AST_NODE_TYPES.BinaryExpression && - ['|', '&', '^', '<<', '>>', '>>>'].includes( - node.initializer.operator, - ) && - isAllowedBitwiseOperand(declaration, node.initializer.left) && - isAllowedBitwiseOperand(declaration, node.initializer.right) - ) { + if (isAllowedInitializerExpressionRecursive(node.initializer, false)) { return; } diff --git a/packages/eslint-plugin/tests/rules/prefer-literal-enum-member.test.ts b/packages/eslint-plugin/tests/rules/prefer-literal-enum-member.test.ts index 1247ee27bf29..d38232630cf6 100644 --- a/packages/eslint-plugin/tests/rules/prefer-literal-enum-member.test.ts +++ b/packages/eslint-plugin/tests/rules/prefer-literal-enum-member.test.ts @@ -110,6 +110,50 @@ enum Foo { enum Foo { ['A-1'] = 1 << 0, C = ~Foo['A-1'], +} + `, + options: [{ allowBitwiseExpressions: true }], + }, + { + code: ` +enum Foo { + A = 1 << 0, + B = 1 << 1, + C = 1 << 2, + D = A | B | C, +} + `, + options: [{ allowBitwiseExpressions: true }], + }, + { + code: ` +enum Foo { + A = 1 << 0, + B = 1 << 1, + C = 1 << 2, + D = Foo.A | Foo.B | Foo.C, +} + `, + options: [{ allowBitwiseExpressions: true }], + }, + { + code: ` +enum Foo { + A = 1 << 0, + B = 1 << 1, + C = 1 << 2, + D = Foo.A | (Foo.B & ~Foo.C), +} + `, + options: [{ allowBitwiseExpressions: true }], + }, + { + code: ` +enum Foo { + A = 1 << 0, + B = 1 << 1, + C = 1 << 2, + D = Foo.A | -Foo.B, } `, options: [{ allowBitwiseExpressions: true }], @@ -433,5 +477,19 @@ enum Foo { }, ], }, + { + code: ` +enum Foo { + A, + B = +A, +} + `, + errors: [ + { + messageId: 'notLiteral', + line: 4, + }, + ], + }, ], }); pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy