forked from palantir/tslint
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add ArrayType rule to enforce 'T[]' or 'Array<T>' (palantir#1498)
* Add ArrayType to SyntaxWalker
- Loading branch information
Showing
10 changed files
with
228 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
import * as ts from "typescript"; | ||
|
||
import * as Lint from "../lint"; | ||
|
||
const OPTION_ARRAY = "array"; | ||
const OPTION_GENERIC = "generic"; | ||
|
||
export class Rule extends Lint.Rules.AbstractRule { | ||
/* tslint:disable:object-literal-sort-keys */ | ||
public static metadata: Lint.IRuleMetadata = { | ||
ruleName: "array-type", | ||
description: "Requires using either 'T[]' or 'Array<T>' for arrays.", | ||
optionsDescription: Lint.Utils.dedent` | ||
One of the following arguments must be provided: | ||
* \`"${OPTION_ARRAY}"\` enforces use of 'T[]'. | ||
* \`"${OPTION_GENERIC}"\` enforces use of 'Array<T>'.`, | ||
options: { | ||
type: "string", | ||
enum: [OPTION_ARRAY, OPTION_GENERIC], | ||
}, | ||
optionExamples: ["[true, array]", "[true, generic]"], | ||
type: "style", | ||
}; | ||
/* tslint:enable:object-literal-sort-keys */ | ||
|
||
public static FAILURE_STRING_ARRAY = "Array type using 'Array<T>' is forbidden. Use 'T[]' instead."; | ||
public static FAILURE_STRING_GENERIC = "Array type using 'T[]' is forbidden. Use 'Array<T>' instead."; | ||
|
||
public apply(sourceFile: ts.SourceFile): Lint.RuleFailure[] { | ||
const alignWalker = new ArrayTypeWalker(sourceFile, this.getOptions()); | ||
return this.applyWithWalker(alignWalker); | ||
} | ||
} | ||
|
||
class ArrayTypeWalker extends Lint.RuleWalker { | ||
public visitArrayType(node: ts.ArrayTypeNode) { | ||
if (this.hasOption(OPTION_GENERIC)) { | ||
const typeName = node.elementType; | ||
const fix = new Lint.Fix(Rule.metadata.ruleName, [ | ||
this.appendText(typeName.getStart(), "Array<"), | ||
// Delete the square brackets and replace with an angle bracket | ||
this.createReplacement(typeName.getEnd(), node.getEnd() - typeName.getEnd(), ">"), | ||
]); | ||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING_GENERIC, fix)); | ||
} | ||
|
||
super.visitArrayType(node); | ||
} | ||
|
||
public visitTypeReference(node: ts.TypeReferenceNode) { | ||
const typeName = node.typeName.getText(); | ||
if (this.hasOption(OPTION_ARRAY) && typeName === "Array") { | ||
const typeArgs = node.typeArguments; | ||
let fix: Lint.Fix; | ||
if (!typeArgs || typeArgs.length === 0) { | ||
// Create an 'any' array | ||
fix = new Lint.Fix(Rule.metadata.ruleName, [ | ||
this.createReplacement(node.getStart(), node.getWidth(), "any[]"), | ||
]); | ||
} else if (typeArgs && typeArgs.length === 1) { | ||
const typeStart = typeArgs[0].getStart(); | ||
const typeEnd = typeArgs[0].getEnd(); | ||
fix = new Lint.Fix(Rule.metadata.ruleName, [ | ||
// Delete Array and the first angle bracket | ||
this.deleteText(node.getStart(), typeStart - node.getStart()), | ||
// Delete the last angle bracket and replace with square brackets | ||
this.createReplacement(typeEnd, node.getEnd() - typeEnd, "[]"), | ||
]); | ||
} | ||
this.addFailure(this.createFailure(node.getStart(), node.getWidth(), Rule.FAILURE_STRING_ARRAY, fix)); | ||
} | ||
|
||
super.visitTypeReference(node); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
let x: number[] = [1] as number[]; | ||
let y: string[] = <string[]>["2"]; | ||
let z: any[] = [3, "4"]; | ||
|
||
let xx: number[][] = [[1, 2], [3]]; | ||
let yy: number[][] = [[4, 5], [6]]; | ||
|
||
type Arr<T> = T[]; | ||
|
||
// Ignore user defined aliases | ||
let yyyy: Arr<Arr<string>[][]> = [[[["2"]]]]; | ||
|
||
interface ArrayClass<T> { | ||
foo: T[]; | ||
bar: T[]; | ||
baz: Arr<T>; | ||
} | ||
|
||
function fooFunction(foo: ArrayClass<string>[]) { | ||
return foo.map(e => e.foo); | ||
} | ||
|
||
function barFunction(bar: ArrayClass<String>[]) { | ||
return bar.map(e => e.bar); | ||
} | ||
|
||
function bazFunction(baz: Arr<ArrayClass<String>>) { | ||
return baz.map(e => e.baz); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,38 @@ | ||
let x: Array<number> = [1] as number[]; | ||
~~~~~~~~~~~~~ [Array type using 'Array<T>' is forbidden. Use 'T[]' instead.] | ||
let y: string[] = <Array<string>>["2"]; | ||
~~~~~~~~~~~~~ [Array type using 'Array<T>' is forbidden. Use 'T[]' instead.] | ||
let z: Array = [3, "4"]; | ||
~~~~~ [Array type using 'Array<T>' is forbidden. Use 'T[]' instead.] | ||
|
||
let xx: Array<Array<number>> = [[1, 2], [3]]; | ||
~~~~~~~~~~~~~~~~~~~~ [Array type using 'Array<T>' is forbidden. Use 'T[]' instead.] | ||
~~~~~~~~~~~~~ [Array type using 'Array<T>' is forbidden. Use 'T[]' instead.] | ||
let yy: number[][] = [[4, 5], [6]]; | ||
|
||
type Arr<T> = Array<T>; | ||
~~~~~~~~ [Array type using 'Array<T>' is forbidden. Use 'T[]' instead.] | ||
|
||
// Ignore user defined aliases | ||
let yyyy: Arr<Array<Arr<string>>[]> = [[[["2"]]]]; | ||
~~~~~~~~~~~~~~~~~~ [Array type using 'Array<T>' is forbidden. Use 'T[]' instead.] | ||
|
||
interface ArrayClass<T> { | ||
foo: Array<T>; | ||
~~~~~~~~ [Array type using 'Array<T>' is forbidden. Use 'T[]' instead.] | ||
bar: T[]; | ||
baz: Arr<T>; | ||
} | ||
|
||
function fooFunction(foo: Array<ArrayClass<string>>) { | ||
~~~~~~~~~~~~~~~~~~~~~~~~~ [Array type using 'Array<T>' is forbidden. Use 'T[]' instead.] | ||
return foo.map(e => e.foo); | ||
} | ||
|
||
function barFunction(bar: ArrayClass<String>[]) { | ||
return bar.map(e => e.bar); | ||
} | ||
|
||
function bazFunction(baz: Arr<ArrayClass<String>>) { | ||
return baz.map(e => e.baz); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"rules": { | ||
"array-type": [true, "array"] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,29 @@ | ||
let x: Array<number> = [1] as Array<number>; | ||
let y: Array<string> = <Array<string>>["2"]; | ||
let z: Array = [3, "4"]; | ||
|
||
let xx: Array<Array<number>> = [[1, 2], [3]]; | ||
let yy: Array<Array<number>> = [[4, 5], [6]]; | ||
|
||
type Arr<T> = Array<T>; | ||
|
||
// Ignore user defined aliases | ||
let yyyy: Arr<Array<Array<Arr<string>>>> = [[[["2"]]]]; | ||
|
||
interface ArrayClass<T> { | ||
foo: Array<T>; | ||
bar: Array<T>; | ||
baz: Arr<T>; | ||
} | ||
|
||
function fooFunction(foo: Array<ArrayClass<string>>) { | ||
return foo.map(e => e.foo); | ||
} | ||
|
||
function barFunction(bar: Array<ArrayClass<String>>) { | ||
return bar.map(e => e.bar); | ||
} | ||
|
||
function bazFunction(baz: Arr<ArrayClass<String>>) { | ||
return baz.map(e => e.baz); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,36 @@ | ||
let x: Array<number> = [1] as number[]; | ||
~~~~~~~~ [Array type using 'T[]' is forbidden. Use 'Array<T>' instead.] | ||
let y: string[] = <Array<string>>["2"]; | ||
~~~~~~~~ [Array type using 'T[]' is forbidden. Use 'Array<T>' instead.] | ||
let z: Array = [3, "4"]; | ||
|
||
let xx: Array<Array<number>> = [[1, 2], [3]]; | ||
let yy: number[][] = [[4, 5], [6]]; | ||
~~~~~~~~~~ [Array type using 'T[]' is forbidden. Use 'Array<T>' instead.] | ||
~~~~~~~~ [Array type using 'T[]' is forbidden. Use 'Array<T>' instead.] | ||
|
||
type Arr<T> = Array<T>; | ||
|
||
// Ignore user defined aliases | ||
let yyyy: Arr<Array<Arr<string>>[]> = [[[["2"]]]]; | ||
~~~~~~~~~~~~~~~~~~~~ [Array type using 'T[]' is forbidden. Use 'Array<T>' instead.] | ||
|
||
interface ArrayClass<T> { | ||
foo: Array<T>; | ||
bar: T[]; | ||
~~~ [Array type using 'T[]' is forbidden. Use 'Array<T>' instead.] | ||
baz: Arr<T>; | ||
} | ||
|
||
function fooFunction(foo: Array<ArrayClass<string>>) { | ||
return foo.map(e => e.foo); | ||
} | ||
|
||
function barFunction(bar: ArrayClass<String>[]) { | ||
~~~~~~~~~~~~~~~~~~~~ [Array type using 'T[]' is forbidden. Use 'Array<T>' instead.] | ||
return bar.map(e => e.bar); | ||
} | ||
|
||
function bazFunction(baz: Arr<ArrayClass<String>>) { | ||
return baz.map(e => e.baz); | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
{ | ||
"rules": { | ||
"array-type": [true, "generic"] | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters