4 * Copyright 2018 Palantir Technologies, Inc.
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
18 Object.defineProperty(exports, "__esModule", { value: true });
19 var tslib_1 = require("tslib");
20 var ts = require("typescript");
21 var Lint = require("../index");
22 var OPTION_ARRAY = "array";
23 var OPTION_GENERIC = "generic";
24 var OPTION_ARRAY_SIMPLE = "array-simple";
25 var Rule = /** @class */ (function (_super) {
26 tslib_1.__extends(Rule, _super);
28 return _super !== null && _super.apply(this, arguments) || this;
30 Rule.prototype.apply = function (sourceFile) {
31 return this.applyWithFunction(sourceFile, walk, this.ruleArguments[0]);
33 /* tslint:disable:object-literal-sort-keys */
35 ruleName: "array-type",
36 description: "Requires using either 'T[]' or 'Array<T>' for arrays.",
38 optionsDescription: Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n One of the following arguments must be provided:\n\n * `\"", "\"` enforces use of `T[]` for all types T.\n * `\"", "\"` enforces use of `Array<T>` for all types T.\n * `\"", "\"` enforces use of `T[]` if `T` is a simple type (primitive or type reference)."], ["\n One of the following arguments must be provided:\n\n * \\`\"", "\"\\` enforces use of \\`T[]\\` for all types T.\n * \\`\"", "\"\\` enforces use of \\`Array<T>\\` for all types T.\n * \\`\"", "\"\\` enforces use of \\`T[]\\` if \\`T\\` is a simple type (primitive or type reference)."])), OPTION_ARRAY, OPTION_GENERIC, OPTION_ARRAY_SIMPLE),
41 enum: [OPTION_ARRAY, OPTION_GENERIC, OPTION_ARRAY_SIMPLE],
43 optionExamples: [[true, OPTION_ARRAY], [true, OPTION_GENERIC], [true, OPTION_ARRAY_SIMPLE]],
47 /* tslint:enable:object-literal-sort-keys */
48 Rule.FAILURE_STRING_ARRAY = "Array type using 'Array<T>' is forbidden. Use 'T[]' instead.";
49 Rule.FAILURE_STRING_GENERIC = "Array type using 'T[]' is forbidden. Use 'Array<T>' instead.";
50 Rule.FAILURE_STRING_ARRAY_SIMPLE = "Array type using 'Array<T>' is forbidden for simple types. Use 'T[]' instead.";
51 Rule.FAILURE_STRING_GENERIC_SIMPLE = "Array type using 'T[]' is forbidden for non-simple types. Use 'Array<T>' instead.";
53 }(Lint.Rules.AbstractRule));
56 var sourceFile = ctx.sourceFile, option = ctx.options;
57 return ts.forEachChild(sourceFile, function cb(node) {
59 case ts.SyntaxKind.ArrayType:
62 case ts.SyntaxKind.TypeReference:
63 checkTypeReference(node);
65 return ts.forEachChild(node, cb);
67 function checkArrayType(node) {
68 var elementType = node.elementType, parent = node.parent;
69 if (option === "array" || (option === "array-simple" && isSimpleType(elementType))) {
72 var failureString = option === "generic" ? Rule.FAILURE_STRING_GENERIC : Rule.FAILURE_STRING_GENERIC_SIMPLE;
73 var parens = elementType.kind === ts.SyntaxKind.ParenthesizedType ? 1 : 0;
74 // Add a space if the type is preceded by 'as' and the node has no leading whitespace
75 var space = parens === 0 &&
76 parent.kind === ts.SyntaxKind.AsExpression &&
77 node.getStart() === node.getFullStart();
79 new Lint.Replacement(elementType.getStart(), parens, (space ? " " : "") + "Array<"),
80 // Delete the square brackets and replace with an angle bracket
81 Lint.Replacement.replaceFromTo(elementType.getEnd() - parens, node.getEnd(), ">"),
83 ctx.addFailureAtNode(node, failureString, fix);
85 function checkTypeReference(node) {
86 var typeName = node.typeName, typeArguments = node.typeArguments;
87 if (option === "generic" || !isArrayIdentifier(typeName)) {
90 var failureString = option === "array" ? Rule.FAILURE_STRING_ARRAY : Rule.FAILURE_STRING_ARRAY_SIMPLE;
91 if (typeArguments === undefined || typeArguments.length === 0) {
92 // Create an 'any' array
93 ctx.addFailureAtNode(node, failureString, Lint.Replacement.replaceFromTo(node.getStart(), node.getEnd(), "any[]"));
96 if (typeArguments.length !== 1 ||
97 (option === "array-simple" && !isSimpleType(typeArguments[0]))) {
100 var type = typeArguments[0];
101 var parens = typeNeedsParentheses(type);
102 ctx.addFailureAtNode(node, failureString, [
104 Lint.Replacement.replaceFromTo(node.getStart(), type.getStart(), parens ? "(" : ""),
105 // Delete '>' and replace with '[]
106 Lint.Replacement.replaceFromTo(type.getEnd(), node.getEnd(), parens ? ")[]" : "[]"),
110 function typeNeedsParentheses(type) {
112 case ts.SyntaxKind.UnionType:
113 case ts.SyntaxKind.FunctionType:
114 case ts.SyntaxKind.IntersectionType:
115 case ts.SyntaxKind.TypeOperator:
121 function isArrayIdentifier(name) {
122 return name.kind === ts.SyntaxKind.Identifier && name.text === "Array";
124 function isSimpleType(nodeType) {
125 switch (nodeType.kind) {
126 case ts.SyntaxKind.AnyKeyword:
127 case ts.SyntaxKind.ArrayType:
128 case ts.SyntaxKind.BooleanKeyword:
129 case ts.SyntaxKind.NullKeyword:
130 case ts.SyntaxKind.ObjectKeyword:
131 case ts.SyntaxKind.UndefinedKeyword:
132 case ts.SyntaxKind.NumberKeyword:
133 case ts.SyntaxKind.StringKeyword:
134 case ts.SyntaxKind.SymbolKeyword:
135 case ts.SyntaxKind.VoidKeyword:
136 case ts.SyntaxKind.NeverKeyword:
137 case ts.SyntaxKind.ThisType:
138 case ts.SyntaxKind.UnknownKeyword:
140 case ts.SyntaxKind.ParenthesizedType:
141 return isSimpleType(nodeType.type);
142 case ts.SyntaxKind.TypeReference:
143 // TypeReferences must be non-generic or be another Array with a simple type
144 var _a = nodeType, typeName = _a.typeName, typeArguments = _a.typeArguments;
145 if (typeArguments === undefined) {
148 switch (typeArguments.length) {
152 return (typeName.kind === ts.SyntaxKind.Identifier &&
153 typeName.text === "Array" &&
154 isSimpleType(typeArguments[0]));
162 var templateObject_1;