📄 prefer-tsutils-methods¶
📊 Analysis Summary¶
| Metric | Count |
|---|---|
| 🔧 Functions | 6 |
| 📦 Imports | 3 |
| 📊 Variables & Constants | 1 |
| 📑 Type Aliases | 1 |
📚 Table of Contents¶
🛠️ File Location:¶
📂 packages/eslint-plugin-internal/src/rules/prefer-tsutils-methods.ts
📤 Default Export¶
| Property | Value |
|---|---|
name |
'prefer-tsutils-methods' |
meta.type |
'problem' |
meta.docs.description |
'Enforce using ts-api-utils methods over direct bitwise flag checks' |
meta.fixable |
'code' |
meta.messages.preferMethod |
'Prefer tsutils.{{ method }}() over bitwise {{ flagType }} check' |
meta.schema |
[] |
defaultOptions |
[] |
Entry point: create — documented under Functions.
📦 Imports¶
| Name | Source |
|---|---|
TSESTree |
@typescript-eslint/utils |
AST_NODE_TYPES |
@typescript-eslint/utils |
createRule |
../util/index.js |
Variables & Constants¶
| Name | Type | Kind | Value | Exported |
|---|---|---|---|---|
FLAG_CONFIGS |
{ ObjectFlags: { flagsProperty: strin... |
const | { ObjectFlags: { flagsProperty: 'objectFlags', method: 'isObjectFlagSet', }, ... |
✗ |
Functions¶
create(context: any): { BinaryExpression(node: TSESTree.BinaryExpression): void; }¶
Parameters:
contextany
Returns: { BinaryExpression(node: TSESTree.BinaryExpression): void; }
Calls:
isFlagTypecontext.sourceCode.getTextisTsFlagAccessisFlagOrExpressionisFlagPropertyAccessanalyzeBitwiseAndcontext.reportfixer.replaceText
Code
create(context) {
function isTsFlagAccess(node: TSESTree.Node) {
if (
node.type === AST_NODE_TYPES.MemberExpression &&
node.object.type === AST_NODE_TYPES.MemberExpression &&
node.object.object.type === AST_NODE_TYPES.Identifier &&
node.object.object.name === 'ts' &&
node.object.property.type === AST_NODE_TYPES.Identifier
) {
const flagType = node.object.property.name;
if (isFlagType(flagType)) {
return { flagType, fullText: context.sourceCode.getText(node) };
}
}
return null;
}
function isFlagOrExpression(
node: TSESTree.Node,
): { flagType: FlagType; fullText: string } | null {
if (
node.type === AST_NODE_TYPES.BinaryExpression &&
node.operator === '|'
) {
const leftFlag = isTsFlagAccess(node.left);
if (leftFlag) {
return {
flagType: leftFlag.flagType,
fullText: context.sourceCode.getText(node),
};
}
const leftOr = isFlagOrExpression(node.left);
if (leftOr) {
return {
flagType: leftOr.flagType,
fullText: context.sourceCode.getText(node),
};
}
}
return null;
}
function isFlagPropertyAccess(
node: TSESTree.Node,
expectedFlagType: FlagType,
) {
if (
node.type === AST_NODE_TYPES.MemberExpression &&
node.property.type === AST_NODE_TYPES.Identifier
) {
const propName = node.property.name;
const expectedPropName = FLAG_CONFIGS[expectedFlagType].flagsProperty;
if (propName === expectedPropName) {
return {
objectText: context.sourceCode.getText(node.object),
};
}
}
return null;
}
function analyzeBitwiseAnd(node: TSESTree.BinaryExpression) {
const { left, right } = node;
const rightFlag = isTsFlagAccess(right) ?? isFlagOrExpression(right);
if (rightFlag) {
const leftPropAccess = isFlagPropertyAccess(left, rightFlag.flagType);
if (leftPropAccess) {
return {
flagText: rightFlag.fullText,
flagType: rightFlag.flagType,
objectText: leftPropAccess.objectText,
};
}
}
const leftFlag = isTsFlagAccess(left) ?? isFlagOrExpression(left);
if (leftFlag) {
const rightPropAccess = isFlagPropertyAccess(right, leftFlag.flagType);
if (rightPropAccess) {
return {
flagText: leftFlag.fullText,
flagType: leftFlag.flagType,
objectText: rightPropAccess.objectText,
};
}
}
return null;
}
return {
BinaryExpression(node: TSESTree.BinaryExpression): void {
if (node.operator !== '&') {
return;
}
const analysis = analyzeBitwiseAnd(node);
if (!analysis) {
return;
}
const { flagText, flagType, objectText } = analysis;
const method = FLAG_CONFIGS[flagType].method;
let nodeToReplace: TSESTree.Node = node;
let isNegated = false;
if (
node.parent.type === AST_NODE_TYPES.BinaryExpression &&
(node.parent.operator === '===' || node.parent.operator === '!==') &&
node.parent.right.type === AST_NODE_TYPES.Literal &&
node.parent.right.value === 0
) {
nodeToReplace = node.parent;
isNegated = node.parent.operator === '===';
}
const replacement = isNegated
? `!tsutils.${method}(${objectText}, ${flagText})`
: `tsutils.${method}(${objectText}, ${flagText})`;
context.report({
node: nodeToReplace,
messageId: 'preferMethod',
data: { flagType, method },
fix: fixer => fixer.replaceText(nodeToReplace, replacement),
});
},
};
}
isFlagType(name: string): name is FlagType¶
Parameters:
namestring
Returns: name is FlagType
Code
Internal helpers¶
Declared inside another function in this file.
isTsFlagAccess(node: TSESTree.Node): { flagType: FlagType; fullText: any; }¶
Parameters:
nodeTSESTree.Node
Returns: { flagType: FlagType; fullText: any; }
Calls:
isFlagTypecontext.sourceCode.getText
Code
function isTsFlagAccess(node: TSESTree.Node) {
if (
node.type === AST_NODE_TYPES.MemberExpression &&
node.object.type === AST_NODE_TYPES.MemberExpression &&
node.object.object.type === AST_NODE_TYPES.Identifier &&
node.object.object.name === 'ts' &&
node.object.property.type === AST_NODE_TYPES.Identifier
) {
const flagType = node.object.property.name;
if (isFlagType(flagType)) {
return { flagType, fullText: context.sourceCode.getText(node) };
}
}
return null;
}
isFlagOrExpression(node: TSESTree.Node): { flagType: FlagType; fullText: string } | null¶
Parameters:
nodeTSESTree.Node
Returns: { flagType: FlagType; fullText: string } | null
Calls:
isTsFlagAccesscontext.sourceCode.getTextisFlagOrExpression
Code
function isFlagOrExpression(
node: TSESTree.Node,
): { flagType: FlagType; fullText: string } | null {
if (
node.type === AST_NODE_TYPES.BinaryExpression &&
node.operator === '|'
) {
const leftFlag = isTsFlagAccess(node.left);
if (leftFlag) {
return {
flagType: leftFlag.flagType,
fullText: context.sourceCode.getText(node),
};
}
const leftOr = isFlagOrExpression(node.left);
if (leftOr) {
return {
flagType: leftOr.flagType,
fullText: context.sourceCode.getText(node),
};
}
}
return null;
}
isFlagPropertyAccess(node: TSESTree.Node, expectedFlagType: FlagType): { objectText: any; }¶
Parameters:
nodeTSESTree.NodeexpectedFlagTypeFlagType
Returns: { objectText: any; }
Calls:
context.sourceCode.getText
Code
function isFlagPropertyAccess(
node: TSESTree.Node,
expectedFlagType: FlagType,
) {
if (
node.type === AST_NODE_TYPES.MemberExpression &&
node.property.type === AST_NODE_TYPES.Identifier
) {
const propName = node.property.name;
const expectedPropName = FLAG_CONFIGS[expectedFlagType].flagsProperty;
if (propName === expectedPropName) {
return {
objectText: context.sourceCode.getText(node.object),
};
}
}
return null;
}
analyzeBitwiseAnd(node: TSESTree.BinaryExpression): { flagText: any; flagType: FlagType; objectText: any; }¶
Parameters:
nodeTSESTree.BinaryExpression
Returns: { flagText: any; flagType: FlagType; objectText: any; }
Calls:
isTsFlagAccessisFlagOrExpressionisFlagPropertyAccess
Code
function analyzeBitwiseAnd(node: TSESTree.BinaryExpression) {
const { left, right } = node;
const rightFlag = isTsFlagAccess(right) ?? isFlagOrExpression(right);
if (rightFlag) {
const leftPropAccess = isFlagPropertyAccess(left, rightFlag.flagType);
if (leftPropAccess) {
return {
flagText: rightFlag.fullText,
flagType: rightFlag.flagType,
objectText: leftPropAccess.objectText,
};
}
}
const leftFlag = isTsFlagAccess(left) ?? isFlagOrExpression(left);
if (leftFlag) {
const rightPropAccess = isFlagPropertyAccess(right, leftFlag.flagType);
if (rightPropAccess) {
return {
flagText: leftFlag.fullText,
flagType: leftFlag.flagType,
objectText: rightPropAccess.objectText,
};
}
}
return null;
}
Type Aliases¶
FlagType¶
Generated by Syntax Scribe