4 * Copyright 2013 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");
21 var utils = require("tsutils");
22 var ts = require("typescript");
23 var Lint = require("../index");
24 var OPTION_IGNORE_ACCESSORS = "ignore-accessors";
25 var Rule = /** @class */ (function (_super) {
26 tslib_1.__extends(Rule, _super);
28 return _super !== null && _super.apply(this, arguments) || this;
30 /* tslint:enable:object-literal-sort-keys */
31 Rule.FAILURE_STRING = function (name) {
32 return "All '" + name + "' signatures should be adjacent";
34 Rule.prototype.apply = function (sourceFile) {
35 // tslint:disable-next-line: no-object-literal-type-assertion
36 var rawOptions = tslib_1.__assign({}, this.ruleArguments[0]);
37 return this.applyWithFunction(sourceFile, walk, {
38 ignoreAccessors: !!rawOptions[OPTION_IGNORE_ACCESSORS],
41 /* tslint:disable:object-literal-sort-keys */
43 ruleName: "adjacent-overload-signatures",
44 description: "Enforces function overloads to be consecutive.",
45 optionsDescription: Lint.Utils.dedent(templateObject_1 || (templateObject_1 = tslib_1.__makeTemplateObject(["\n If `", "` is specified, then getters and setters are not considered to be overloads\n of function with the same signature."], ["\n If \\`", "\\` is specified, then getters and setters are not considered to be overloads\n of function with the same signature."])), OPTION_IGNORE_ACCESSORS),
49 _a[OPTION_IGNORE_ACCESSORS] = {
53 additionalProperties: false,
55 optionExamples: [true, [true, { OPTION_IGNORE_ACCESSORS: true }]],
56 rationale: "Improves readability and organization by grouping naturally related items together.",
61 }(Lint.Rules.AbstractRule));
64 var sourceFile = ctx.sourceFile;
65 visitStatements(sourceFile.statements);
66 return ts.forEachChild(sourceFile, function cb(node) {
68 case ts.SyntaxKind.ModuleBlock:
69 visitStatements(node.statements);
71 case ts.SyntaxKind.InterfaceDeclaration:
72 case ts.SyntaxKind.ClassDeclaration:
73 case ts.SyntaxKind.TypeLiteral: {
74 var members = node.members;
75 addFailures(getMisplacedOverloads(members, function (member) {
76 return utils.isSignatureDeclaration(member)
77 ? getOverloadKey(member)
79 }, ctx.options.ignoreAccessors));
82 return ts.forEachChild(node, cb);
84 function visitStatements(statements) {
85 addFailures(getMisplacedOverloads(statements, function (statement) {
86 return utils.isFunctionDeclaration(statement) && statement.name !== undefined
89 }, ctx.options.ignoreAccessors));
91 function addFailures(misplacedOverloads) {
92 for (var _i = 0, misplacedOverloads_1 = misplacedOverloads; _i < misplacedOverloads_1.length; _i++) {
93 var node = misplacedOverloads_1[_i];
94 ctx.addFailureAtNode(node, Rule.FAILURE_STRING(printOverload(node)));
98 /** 'getOverloadName' may return undefined for nodes that cannot be overloads, e.g. a `const` declaration. */
99 function getMisplacedOverloads(overloads, getKey, ignoreAccessors) {
102 var seen = new Set();
103 for (var _i = 0, overloads_1 = overloads; _i < overloads_1.length; _i++) {
104 var node = overloads_1[_i];
105 if (node.kind === ts.SyntaxKind.SemicolonClassElement ||
106 (ignoreAccessors && isAccessor(node))) {
109 var key = getKey(node);
110 if (key !== undefined) {
111 if (seen.has(key) && lastKey !== key) {
123 function isAccessor(member) {
124 return member.kind === ts.SyntaxKind.GetAccessor || member.kind === ts.SyntaxKind.SetAccessor;
126 function printOverload(node) {
127 var info = getOverloadInfo(node);
128 return typeof info === "string" ? info : info === undefined ? "<unknown>" : info.name;
130 function getOverloadKey(node) {
131 var info = getOverloadInfo(node);
132 if (info === undefined) {
135 var _a = typeof info === "string" ? [false, info] : [info.computed, info.name], computed = _a[0], name = _a[1];
136 var isStatic = utils.hasModifier(node.modifiers, ts.SyntaxKind.StaticKeyword);
137 return (computed ? "0" : "1") + (isStatic ? "0" : "1") + name;
139 exports.getOverloadKey = getOverloadKey;
140 function getOverloadInfo(node) {
142 case ts.SyntaxKind.ConstructSignature:
143 case ts.SyntaxKind.Constructor:
144 return "constructor";
145 case ts.SyntaxKind.CallSignature:
148 var name = node.name;
149 if (name === undefined) {
153 case ts.SyntaxKind.Identifier:
155 case ts.SyntaxKind.ComputedPropertyName:
156 var expression = name.expression;
157 return utils.isLiteralExpression(expression)
159 : { name: expression.getText(), computed: true };
161 return utils.isLiteralExpression(name) ? name.text : undefined;
166 var templateObject_1;