Skip to content
This repository has been archived by the owner on Mar 25, 2021. It is now read-only.

Radix rule checks Number.parseInt(), window.Number.parseInt(), global… #3901

Merged
merged 1 commit into from Jun 26, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
43 changes: 34 additions & 9 deletions src/rules/radixRule.ts
Expand Up @@ -44,20 +44,45 @@ export class Rule extends Lint.Rules.AbstractRule {
}
}

function isParseInt(expression: ts.LeftHandSideExpression) {
return isIdentifier(expression) && expression.text === "parseInt";
}

function isPropertyAccessParseInt(
expression: ts.LeftHandSideExpression,
): expression is ts.PropertyAccessExpression {
return isPropertyAccessExpression(expression) && expression.name.text === "parseInt";

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this seems like it would ban myCustomClass.parseInt(arg), which could be a perfectly valid use of a non-library function called parseInt. true?

please add a test for this case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

isPropertyAccessParseInt() will return true for that case yes. However, in conjunction with isPropertyAccessOfProperty() and isPropertyAccessOfIdentifier(), the check is constrained to specific instances. A test already exists for this:
parser.parseInt("123"); on line 6 of the radix rule test.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice

}

function isPropertyAccessOfIdentifier(
expression: ts.LeftHandSideExpression,
identifers: string[],
): expression is ts.PropertyAccessExpression {
return isPropertyAccessExpression(expression) && isIdentifier(expression.expression) &&
identifers.some((identifer) => (expression.expression as ts.Identifier).text === identifer);
}

function isPropertyAccessOfProperty(
expression: ts.LeftHandSideExpression,
identifers: string[],
): expression is ts.PropertyAccessExpression {
return isPropertyAccessExpression(expression) && isPropertyAccessExpression(expression.expression) &&
identifers.some((identifer) => (expression.expression as ts.PropertyAccessExpression).name.text === identifer);
}

function walk(ctx: Lint.WalkContext<void>) {
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
if (isCallExpression(node) && node.arguments.length === 1 &&
(
// parseInt("123")
isIdentifier(node.expression) && node.expression.text === "parseInt" ||
// window.parseInt("123") || global.parseInt("123")
isPropertyAccessExpression(node.expression) &&
node.expression.name.text === "parseInt" &&
isIdentifier(node.expression.expression) &&
(
node.expression.expression.text === "global" ||
node.expression.expression.text === "window"
)
isParseInt(node.expression) ||
// window.parseInt("123") || global.parseInt("123") || Number.parseInt("123")
isPropertyAccessParseInt(node.expression) &&
isPropertyAccessOfIdentifier(node.expression, [ "global", "window", "Number" ]) ||
// window.Number.parseInt("123") || global.Number.parseInt("123")
isPropertyAccessParseInt(node.expression) &&
isPropertyAccessOfProperty(node.expression, [ "Number" ]) &&
isPropertyAccessOfIdentifier(node.expression.expression, [ "global", "window" ])
)) {
ctx.addFailureAtNode(node, Rule.FAILURE_STRING);
}
Expand Down
15 changes: 15 additions & 0 deletions test/rules/radix/test.ts.lint
Expand Up @@ -11,3 +11,18 @@ global.parseInt("123");
global.global.parseInt("123");
window.parseInt("123");
~~~~~~~~~~~~~~~~~~~~~~ [Missing radix parameter]

Number.parseInt("123", 10);
Number.parseInt("123");
~~~~~~~~~~~~~~~~~~~~~~ [Missing radix parameter]
other.Number.parseInt("123");

global.Number.parseInt("123", 10);
global.Number.parseInt("123");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Missing radix parameter]
other.global.Number.parseInt("123");

window.Number.parseInt("123", 10);
window.Number.parseInt("123");
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ [Missing radix parameter]
other.window.Number.parseInt("123");