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

Added support for 'ignore-rest-args' option in 'no-any' rule #4581

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.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 12 additions & 0 deletions src/rules/code-examples/noAny.examples.ts
Original file line number Diff line number Diff line change
Expand Up @@ -31,4 +31,16 @@ export const codeExamples = [
let foo: any;
`,
},
{
description:
"Disallows usages of `any` as a type declaration except rest spread parameters.",
config: Lint.Utils.dedent`
"rules": { "no-any": [true, { "ignore-rest-args": true }] }
`,
pass: Lint.Utils.dedent`
function foo(a: number, ...rest: any[]): void {
return;
}
`,
},
];
45 changes: 40 additions & 5 deletions src/rules/noAnyRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,15 @@
* limitations under the License.
*/

import { isArrayTypeNode, isParameterDeclaration } from "tsutils";
import * as ts from "typescript";

import * as Lint from "../index";

import { codeExamples } from "./code-examples/noAny.examples";

const OPTION_IGNORE_REST_ARGS = "ignore-rest-args";

export class Rule extends Lint.Rules.AbstractRule {
/* tslint:disable:object-literal-sort-keys */
public static metadata: Lint.IRuleMetadata = {
Expand All @@ -38,9 +41,16 @@ export class Rule extends Lint.Rules.AbstractRule {

Also see the \`no-unsafe-any\` rule.
`,
optionsDescription: "Not configurable.",
options: null,
optionExamples: [true],
optionsDescription: Lint.Utils.dedent`
If \`"${OPTION_IGNORE_REST_ARGS}": true\` is provided rest arguments will be ignored.
`,
options: {
type: "object",
properties: {
[OPTION_IGNORE_REST_ARGS]: { type: "boolean" },
},
},
optionExamples: [true, [true, { [OPTION_IGNORE_REST_ARGS]: true }]],
type: "typescript",
typescriptOnly: true,
codeExamples,
Expand All @@ -51,16 +61,41 @@ export class Rule extends Lint.Rules.AbstractRule {
"Type declaration of 'any' loses type-safety. Consider replacing it with a more precise type.";

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithFunction(sourceFile, walk);
const options: Options = getOptions(this.ruleArguments[0] as Partial<Options> | undefined);
return this.applyWithFunction(sourceFile, walk, options);
}
}

function walk(ctx: Lint.WalkContext) {
interface Options {
[OPTION_IGNORE_REST_ARGS]: boolean;
}

function getOptions(options: Partial<Options> | undefined): Options {
return {
[OPTION_IGNORE_REST_ARGS]: false,
...options,
};
}

function walk(ctx: Lint.WalkContext<Options>) {
return ts.forEachChild(ctx.sourceFile, function cb(node: ts.Node): void {
if (node.kind === ts.SyntaxKind.AnyKeyword) {
if (ctx.options[OPTION_IGNORE_REST_ARGS] && isRestParameterArrayType(node)) {
return;
}

const start = node.end - 3;
return ctx.addFailure(start, node.end, Rule.FAILURE_STRING);
}

return ts.forEachChild(node, cb);
});
}

function isRestParameterArrayType(anyTypeNode: ts.Node) {
return (
isArrayTypeNode(anyTypeNode.parent) &&
isParameterDeclaration(anyTypeNode.parent.parent) &&
anyTypeNode.parent.parent.getChildAt(0).kind === ts.SyntaxKind.DotDotDotToken
JoshuaKGoldberg marked this conversation as resolved.
Show resolved Hide resolved
);
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,25 @@ function foo(a: any) : any { // 2 errors
return;
}

const fooArrow(a: any[]) => {
~~~ [0]
return;
}

function bar(...a: any[]) {
~~~ [0]
return;
}

const barArrow = (...a: any[]): any => {
~~~ [0]
~~~ [0]
return;
}

let a: any = 2, // error
~~~ [0]
b: any = 4; // error
b: any[] = 4; // error
~~~ [0]

let {a: c, b: d}: {c: any, d: number} = {c: 99, d: 100}; // error
Expand Down
38 changes: 38 additions & 0 deletions test/rules/no-any/ignore-rest-args/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
var x: any; // error
~~~ [0]

function foo(a: any) : any { // 2 errors
~~~ [0]
~~~ [0]
return;
}

const fooArrow(a: any[]) => {
~~~ [0]
return;
}

function bar(...a: any[]) {
return;
}

const barArrow = (...a: any[]): any => {
~~~ [0]
return;
}

const function(...a: { [key: any]: any }[]) {
~~~ [0]
~~~ [0]
return;
}

let a: any = 2, // error
~~~ [0]
b: any[] = 4; // error
~~~ [0]

let {a: c, b: d}: {c: any, d: number} = {c: 99, d: 100}; // error
~~~ [0]

[0]: Type declaration of 'any' loses type-safety. Consider replacing it with a more precise type.
5 changes: 5 additions & 0 deletions test/rules/no-any/ignore-rest-args/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"no-any": [true, { "ignore-rest-args": true }]
}
}