Skip to content

Commit

Permalink
Add ignore-properties to no-inferrable-types (palantir#2178)
Browse files Browse the repository at this point in the history
  • Loading branch information
ajafff authored and nchen63 committed Feb 7, 2017
1 parent 44f74e9 commit 0def9f7
Show file tree
Hide file tree
Showing 8 changed files with 204 additions and 24 deletions.
71 changes: 47 additions & 24 deletions src/rules/noInferrableTypesRule.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,12 @@ import * as ts from "typescript";
import * as Lint from "../index";

const OPTION_IGNORE_PARMS = "ignore-params";
const OPTION_IGNORE_PROPERTIES = "ignore-properties";

interface IOptions {
ignoreParameters: boolean;
ignoreProperties: boolean;
}

export class Rule extends Lint.Rules.AbstractRule {
/* tslint:disable:object-literal-sort-keys */
Expand All @@ -28,20 +34,26 @@ export class Rule extends Lint.Rules.AbstractRule {
description: "Disallows explicit type declarations for variables or parameters initialized to a number, string, or boolean.",
rationale: "Explicit types where they can be easily infered by the compiler make code more verbose.",
optionsDescription: Lint.Utils.dedent`
One argument may be optionally provided:
Two argument may be optionally provided:
* \`${OPTION_IGNORE_PARMS}\` allows specifying an inferrable type annotation for function params.
This can be useful when combining with the \`typedef\` rule.`,
This can be useful when combining with the \`typedef\` rule.
* \`${OPTION_IGNORE_PROPERTIES}\` allows specifying an inferrable type annotation for class properties.`,
options: {
type: "array",
items: {
type: "string",
enum: [OPTION_IGNORE_PARMS],
enum: [OPTION_IGNORE_PARMS, OPTION_IGNORE_PROPERTIES],
},
minLength: 0,
maxLength: 1,
maxLength: 2,
},
optionExamples: ["true", `[true, "${OPTION_IGNORE_PARMS}"]`],
hasFix: true,
optionExamples: [
"true",
`[true, "${OPTION_IGNORE_PARMS}"]`,
`[true, "${OPTION_IGNORE_PARMS}", "${OPTION_IGNORE_PROPERTIES}"]`,
],
type: "typescript",
typescriptOnly: true,
};
Expand All @@ -52,29 +64,37 @@ export class Rule extends Lint.Rules.AbstractRule {
}

public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] {
return this.applyWithWalker(new NoInferrableTypesWalker(sourceFile, this.getOptions()));
return this.applyWithWalker(new NoInferrableTypesWalker(sourceFile, this.ruleName, {
ignoreParameters: this.ruleArguments.indexOf(OPTION_IGNORE_PARMS) !== -1,
ignoreProperties: this.ruleArguments.indexOf(OPTION_IGNORE_PROPERTIES) !== -1,
}));
}
}

class NoInferrableTypesWalker extends Lint.RuleWalker {
public visitVariableDeclaration(node: ts.VariableDeclaration) {
this.checkDeclaration(node);
super.visitVariableDeclaration(node);
}

public visitParameterDeclaration(node: ts.ParameterDeclaration) {
if (!this.hasOption(OPTION_IGNORE_PARMS)) {
this.checkDeclaration(node);
}
super.visitParameterDeclaration(node);
}

public visitPropertyDeclaration(node: ts.PropertyDeclaration) {
this.checkDeclaration(node);
super.visitPropertyDeclaration(node);
class NoInferrableTypesWalker extends Lint.AbstractWalker<IOptions> {
public walk(sourceFile: ts.SourceFile) {
const cb = (node: ts.Node): void => {
switch (node.kind) {
case ts.SyntaxKind.Parameter:
if (!this.options.ignoreParameters) {
this.checkDeclaration(node as ts.ParameterDeclaration);
}
break;
case ts.SyntaxKind.PropertyDeclaration:
if (this.options.ignoreProperties) {
break;
}
/* falls through*/
case ts.SyntaxKind.VariableDeclaration:
this.checkDeclaration(node as ts.VariableLikeDeclaration);
default:
}
return ts.forEachChild(node, cb);
};
return ts.forEachChild(sourceFile, cb);
}

private checkDeclaration(node: ts.ParameterDeclaration | ts.VariableDeclaration | ts.PropertyDeclaration) {
private checkDeclaration(node: ts.VariableLikeDeclaration) {
if (node.type != null && node.initializer != null) {
let failure: string | null = null;

Expand Down Expand Up @@ -105,7 +125,10 @@ class NoInferrableTypesWalker extends Lint.RuleWalker {
}

if (failure != null) {
this.addFailureAtNode(node.type, Rule.FAILURE_STRING_FACTORY(failure));
this.addFailureAtNode(node.type,
Rule.FAILURE_STRING_FACTORY(failure),
this.createFix(Lint.Replacement.deleteFromTo(node.name.end, node.type.end)),
);
}
}
}
Expand Down
31 changes: 31 additions & 0 deletions test/rules/no-inferrable-types/default/test.ts.fix
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// errors, inferrable type is declared
let x = 7;
let y = false;
let z = "foo";
class C {
x = 1;
}

// errors, types are inferrable
function foo (a = 5, b = true, c = "bah") { }

class Foo {
bar = 0;
baz = true,
bas = "moar";
}

// not errors, inferrable type is not declared
let _x = 7;
let _y = false;
let _z = "foo";

// not error, type is not inferrable
let weird: any = 123;

// not errors, inferrable type is not declared
function bar(a = 5, b = true, c = "bah") { }

// not errors, types are not inferrable
function baz(a: any = 5, b: any = true, c: any = "bah") { }

9 changes: 9 additions & 0 deletions test/rules/no-inferrable-types/default/test.ts.lint
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,15 @@ function foo (a: number = 5, b: boolean = true, c: string = "bah") { }
~~~~~~~ [boolean]
~~~~~~ [string]

class Foo {
bar: number = 0;
~~~~~~ [number]
baz: boolean = true,
~~~~~~~ [boolean]
bas: string = "moar";
~~~~~~ [string]
}

// not errors, inferrable type is not declared
let _x = 7;
let _y = false;
Expand Down
32 changes: 32 additions & 0 deletions test/rules/no-inferrable-types/ignore-params/test.ts.fix
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// errors, inferrable type is declared
let x = 7;
let y = false;
let z = "foo";

// not errors, we are skipping params
function foo (a: number = 5, b: boolean = true, c: string = "bah") { }

class TestClass {
doSomething(a: number = 5, b: boolean = true, c: string = "bah") {}
}

class Foo {
bar = 0;
baz = true,
bas = "moar";
}

// not errors, inferrable type is not declared
let _x = 7;
let _y = false;
let _z = "foo";

// not error, type is not inferrable
let weird: any = 123;

// not errors, inferrable type is not declared
function bar(a = 5, b = true, c = "bah") { }

// not errors, types are not inferrable
function baz(a: any = 5, b: any = true, c: any = "bah") { }

9 changes: 9 additions & 0 deletions test/rules/no-inferrable-types/ignore-params/test.ts.lint
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@ class TestClass {
doSomething(a: number = 5, b: boolean = true, c: string = "bah") {}
}

class Foo {
bar: number = 0;
~~~~~~ [number]
baz: boolean = true,
~~~~~~~ [boolean]
bas: string = "moar";
~~~~~~ [string]
}

// not errors, inferrable type is not declared
let _x = 7;
let _y = false;
Expand Down
31 changes: 31 additions & 0 deletions test/rules/no-inferrable-types/ignore-properties/test.ts.fix
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// errors, inferrable type is declared
let x = 7;
let y = false;
let z = "foo";
class C {
x: number = 1;
}

// errors, types are inferrable
function foo (a = 5, b = true, c = "bah") { }

class Foo {
bar: number = 0;
baz: boolean = true,
bas: string = "moar";
}

// not errors, inferrable type is not declared
let _x = 7;
let _y = false;
let _z = "foo";

// not error, type is not inferrable
let weird: any = 123;

// not errors, inferrable type is not declared
function bar(a = 5, b = true, c = "bah") { }

// not errors, types are not inferrable
function baz(a: any = 5, b: any = true, c: any = "bah") { }

40 changes: 40 additions & 0 deletions test/rules/no-inferrable-types/ignore-properties/test.ts.lint
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// errors, inferrable type is declared
let x: number = 7;
~~~~~~ [number]
let y: boolean = false;
~~~~~~~ [boolean]
let z: string = "foo";
~~~~~~ [string]
class C {
x: number = 1;
}

// errors, types are inferrable
function foo (a: number = 5, b: boolean = true, c: string = "bah") { }
~~~~~~ [number]
~~~~~~~ [boolean]
~~~~~~ [string]

class Foo {
bar: number = 0;
baz: boolean = true,
bas: string = "moar";
}

// not errors, inferrable type is not declared
let _x = 7;
let _y = false;
let _z = "foo";

// not error, type is not inferrable
let weird: any = 123;

// not errors, inferrable type is not declared
function bar(a = 5, b = true, c = "bah") { }

// not errors, types are not inferrable
function baz(a: any = 5, b: any = true, c: any = "bah") { }

[number]: Type number trivially inferred from a number literal, remove type annotation
[boolean]: Type boolean trivially inferred from a boolean literal, remove type annotation
[string]: Type string trivially inferred from a string literal, remove type annotation
5 changes: 5 additions & 0 deletions test/rules/no-inferrable-types/ignore-properties/tslint.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
{
"rules": {
"no-inferrable-types": [true, "ignore-properties"]
}
}

0 comments on commit 0def9f7

Please sign in to comment.