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

Add allow-delete option to no-unbound-method rule #4548

Merged
18 changes: 14 additions & 4 deletions src/rules/noUnboundMethodRule.ts
Expand Up @@ -18,6 +18,7 @@
import {
hasModifier,
isCallExpression,
isDeleteExpression,
isIdentifier,
isPropertyAccessExpression,
isTypeOfExpression,
Expand All @@ -29,6 +30,7 @@ import * as Lint from "../index";
const OPTION_IGNORE_STATIC = "ignore-static";
const OPTION_WHITELIST = "whitelist";
const OPTION_ALLOW_TYPEOF = "allow-typeof";
const OPTION_ALLOW_DELETE = "allow-delete";

const OPTION_WHITELIST_EXAMPLE = [
true,
Expand All @@ -40,12 +42,14 @@ const OPTION_WHITELIST_EXAMPLE = [
];

interface Options {
allowDelete: boolean;
allowTypeof: boolean;
ignoreStatic: boolean;
whitelist: Set<string>;
}

interface OptionsInput {
[OPTION_ALLOW_DELETE]?: boolean;
[OPTION_ALLOW_TYPEOF]?: boolean;
[OPTION_IGNORE_STATIC]?: boolean;
[OPTION_WHITELIST]?: string[];
Expand All @@ -62,6 +66,7 @@ export class Rule extends Lint.Rules.TypedRule {
The object may have three properties:
piotrgajow marked this conversation as resolved.
Show resolved Hide resolved

* "${OPTION_IGNORE_STATIC}" - to ignore static methods.
* "${OPTION_ALLOW_DELETE}" - ignore methods referenced in a delete expression.
* "${OPTION_ALLOW_TYPEOF}" - ignore methods referenced in a typeof expression.
* "${OPTION_WHITELIST}" - ignore method references in parameters of specifed function calls.

Expand All @@ -75,6 +80,7 @@ export class Rule extends Lint.Rules.TypedRule {
{
type: "object",
properties: {
[OPTION_ALLOW_DELETE]: { type: "boolean" },
[OPTION_ALLOW_TYPEOF]: { type: "boolean" },
[OPTION_IGNORE_STATIC]: { type: "boolean" },
[OPTION_WHITELIST]: {
Expand Down Expand Up @@ -146,6 +152,7 @@ export class Rule extends Lint.Rules.TypedRule {

function parseArguments(args: Array<string | OptionsInput>): Options {
const options: Options = {
allowDelete: false,
allowTypeof: false,
ignoreStatic: false,
whitelist: new Set(),
Expand All @@ -157,6 +164,7 @@ function parseArguments(args: Array<string | OptionsInput>): Options {
options.ignoreStatic = true;
}
} else {
options.allowDelete = arg[OPTION_ALLOW_DELETE] || false;
options.allowTypeof = arg[OPTION_ALLOW_TYPEOF] || false;
options.ignoreStatic = arg[OPTION_IGNORE_STATIC] || false;
options.whitelist = new Set(arg[OPTION_WHITELIST]);
Expand All @@ -174,9 +182,7 @@ function walk(ctx: Lint.WalkContext<Options>, tc: ts.TypeChecker) {

const isMethodAccess =
declaration !== undefined && isMethod(declaration, ctx.options.ignoreStatic);
const shouldBeReported =
isMethodAccess &&
!isWhitelisted(node, ctx.options.whitelist, ctx.options.allowTypeof);
const shouldBeReported = isMethodAccess && !isWhitelisted(node, ctx.options);
if (shouldBeReported) {
ctx.addFailureAtNode(node, Rule.FAILURE_STRING);
}
Expand Down Expand Up @@ -228,7 +234,11 @@ function isSafeUse(node: ts.Node): boolean {
}
}

function isWhitelisted(node: ts.Node, whitelist: Set<string>, allowTypeof: boolean): boolean {
function isWhitelisted(node: ts.Node, options: Options): boolean {
const { whitelist, allowTypeof, allowDelete } = options;
if (isDeleteExpression(node.parent)) {
return allowDelete;
}
if (isTypeOfExpression(node.parent)) {
return allowTypeof;
}
Expand Down
8 changes: 8 additions & 0 deletions test/rules/no-unbound-method/whitelist/test.tsx.lint
Expand Up @@ -69,4 +69,12 @@ Validators.compose(Validators.required);
(await someMethod())(c.method);
~~~~~~~~ [0]

const a = {
getText() {
return 'text';
}
};

delete a.getText;
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved

[0]: Avoid referencing unbound methods which may cause unintentional scoping of 'this'.
2 changes: 1 addition & 1 deletion test/rules/no-unbound-method/whitelist/tslint.json
Expand Up @@ -3,6 +3,6 @@
"typeCheck": true
},
"rules": {
"no-unbound-method": [true, { "whitelist": ["expect"], "allow-typeof": true }]
"no-unbound-method": [true, { "whitelist": ["expect"], "allow-typeof": true, "allow-delete": true }]
}
}