β¬ οΈ Back to Table of Contents
π prefer-literal-enum-member¶
π Analysis Summary¶
| Metric | Count |
|---|---|
| π§ Functions | 5 |
| π¦ Imports | 4 |
π Table of Contents¶
π οΈ File Location:¶
π packages/eslint-plugin/src/rules/prefer-literal-enum-member.ts
π€ Default Export¶
| Property | Value |
|---|---|
name |
'prefer-literal-enum-member' |
meta.type |
'suggestion' |
meta.docs.description |
'Require all enum members to be literal values' |
meta.docs.recommended |
'strict' |
meta.docs.requiresTypeChecking |
false |
meta.messages.notLiteral |
Explicit enum value must only be a literal value (string or number). |
meta.messages.notLiteralOrBitwiseExpression |
Explicit enum value must only be a literal value (string or number) or a bitwise expression. |
meta.schema |
[ { type: 'object', additionalProperties: false, properties: { allowBitwiseExpressions: { type: 'boolean', descriptio... |
defaultOptions |
[ { allowBitwiseExpressions: false, }, ] |
Entry point: create β documented under Functions.
π¦ Imports¶
| Name | Source |
|---|---|
TSESTree |
@typescript-eslint/utils |
AST_NODE_TYPES |
@typescript-eslint/utils |
createRule |
../util |
getStaticStringValue |
../util |
Functions¶
create(context: any, [{ allowBitwiseExpressions }]: any): { TSEnumMember(node: any): void; }¶
Parameters:
contextany[{ allowBitwiseExpressions }]any
Returns: { TSEnumMember(node: any): void; }
Calls:
decl.body.members.someisIdentifierWithNamegetStaticStringValue (from ../util)hasEnumMemberisSelfEnumMember['-', '+'].includesisAllowedInitializerExpressionRecursive['&', '^', '<<', '>>', '>>>', '|'].includescontext.report
Internal Comments:
// If there is no initializer, then this node is just the name of the member, so ignore.
// 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.
// any old literal
// TemplateLiteral without expressions
// +123, -123, etc.
Code
create(context, [{ allowBitwiseExpressions }]) {
function isIdentifierWithName(node: TSESTree.Node, name: string): boolean {
return node.type === AST_NODE_TYPES.Identifier && node.name === name;
}
function hasEnumMember(
decl: TSESTree.TSEnumDeclaration,
name: string,
): boolean {
return decl.body.members.some(
member =>
isIdentifierWithName(member.id, name) ||
(member.id.type === AST_NODE_TYPES.Literal &&
getStaticStringValue(member.id) === name),
);
}
function isSelfEnumMember(
decl: TSESTree.TSEnumDeclaration,
node: TSESTree.Node,
): boolean {
if (node.type === AST_NODE_TYPES.Identifier) {
return hasEnumMember(decl, node.name);
}
if (
node.type === AST_NODE_TYPES.MemberExpression &&
isIdentifierWithName(node.object, decl.id.name)
) {
if (node.property.type === AST_NODE_TYPES.Identifier) {
return hasEnumMember(decl, node.property.name);
}
if (node.computed) {
const propertyName = getStaticStringValue(node.property);
if (propertyName) {
return hasEnumMember(decl, propertyName);
}
}
}
return false;
}
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;
}
const declaration = node.parent.parent;
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;
}
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 (isAllowedInitializerExpressionRecursive(node.initializer, false)) {
return;
}
context.report({
node: node.id,
messageId: allowBitwiseExpressions
? 'notLiteralOrBitwiseExpression'
: 'notLiteral',
});
},
};
}
Internal helpers¶
Declared inside another function in this file.
isIdentifierWithName(node: TSESTree.Node, name: string): boolean¶
Parameters:
nodeTSESTree.Nodenamestring
Returns: boolean
Code
hasEnumMember(decl: TSESTree.TSEnumDeclaration, name: string): boolean¶
Parameters:
declTSESTree.TSEnumDeclarationnamestring
Returns: boolean
Calls:
decl.body.members.someisIdentifierWithNamegetStaticStringValue (from ../util)
Code
isSelfEnumMember(decl: TSESTree.TSEnumDeclaration, node: TSESTree.Node): boolean¶
Parameters:
declTSESTree.TSEnumDeclarationnodeTSESTree.Node
Returns: boolean
Calls:
hasEnumMemberisIdentifierWithNamegetStaticStringValue (from ../util)
Code
function isSelfEnumMember(
decl: TSESTree.TSEnumDeclaration,
node: TSESTree.Node,
): boolean {
if (node.type === AST_NODE_TYPES.Identifier) {
return hasEnumMember(decl, node.name);
}
if (
node.type === AST_NODE_TYPES.MemberExpression &&
isIdentifierWithName(node.object, decl.id.name)
) {
if (node.property.type === AST_NODE_TYPES.Identifier) {
return hasEnumMember(decl, node.property.name);
}
if (node.computed) {
const propertyName = getStaticStringValue(node.property);
if (propertyName) {
return hasEnumMember(decl, propertyName);
}
}
}
return false;
}
isAllowedInitializerExpressionRecursive(node: TSESTree.Expression | TSESTree.PrivateIβ¦, partOfBitwiseComputation: boolean): boolean¶
Parameters:
nodeTSESTree.Expression | TSESTree.PrivateIdentifierpartOfBitwiseComputationboolean
Returns: boolean
Calls:
isSelfEnumMember['-', '+'].includesisAllowedInitializerExpressionRecursive['&', '^', '<<', '>>', '>>>', '|'].includes
Internal Comments:
// 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.
// any old literal
// TemplateLiteral without expressions
// +123, -123, etc.
Code
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;
}
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;
}
}
Generated by Syntax Scribe