.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / tslint / lib / rules / noDuplicateSuperRule.js
1 "use strict";
2 /**
3  * @license
4  * Copyright 2017 Palantir Technologies, Inc.
5  *
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
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
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.
17  */
18 Object.defineProperty(exports, "__esModule", { value: true });
19 var tslib_1 = require("tslib");
20 var tsutils_1 = require("tsutils");
21 var ts = require("typescript");
22 var Lint = require("../index");
23 var Rule = /** @class */ (function (_super) {
24     tslib_1.__extends(Rule, _super);
25     function Rule() {
26         return _super !== null && _super.apply(this, arguments) || this;
27     }
28     Rule.prototype.apply = function (sourceFile) {
29         return this.applyWithFunction(sourceFile, walk);
30     };
31     /* tslint:disable:object-literal-sort-keys */
32     Rule.metadata = {
33         ruleName: "no-duplicate-super",
34         description: "Warns if 'super()' appears twice in a constructor.",
35         rationale: "The second call to 'super()' will fail at runtime.",
36         optionsDescription: "Not configurable.",
37         options: null,
38         optionExamples: [true],
39         type: "functionality",
40         typescriptOnly: false,
41     };
42     /* tslint:enable:object-literal-sort-keys */
43     Rule.FAILURE_STRING_DUPLICATE = "Multiple calls to 'super()' found. It must be called only once.";
44     Rule.FAILURE_STRING_LOOP = "'super()' called in a loop. It must be called only once.";
45     return Rule;
46 }(Lint.Rules.AbstractRule));
47 exports.Rule = Rule;
48 function walk(ctx) {
49     return ts.forEachChild(ctx.sourceFile, function cb(node) {
50         if (tsutils_1.isConstructorDeclaration(node) && node.body !== undefined) {
51             getSuperForNode(node.body);
52         }
53         return ts.forEachChild(node, cb);
54     });
55     function getSuperForNode(node) {
56         if (tsutils_1.isIterationStatement(node)) {
57             var bodySuper = combineSequentialChildren(node);
58             if (typeof bodySuper === "number") {
59                 return 0 /* NoSuper */;
60             }
61             if (!bodySuper.break) {
62                 ctx.addFailureAtNode(bodySuper.node, Rule.FAILURE_STRING_LOOP);
63             }
64             return tslib_1.__assign({}, bodySuper, { break: false });
65         }
66         switch (node.kind) {
67             case ts.SyntaxKind.ReturnStatement:
68             case ts.SyntaxKind.ThrowStatement:
69                 return 1 /* Return */;
70             case ts.SyntaxKind.BreakStatement:
71                 return 2 /* Break */;
72             case ts.SyntaxKind.ClassDeclaration:
73             case ts.SyntaxKind.ClassExpression:
74                 // 'super()' is bound differently inside, so ignore.
75                 return 0 /* NoSuper */;
76             case ts.SyntaxKind.SuperKeyword:
77                 return node.parent.kind === ts.SyntaxKind.CallExpression &&
78                     node.parent.expression === node
79                     ? { node: node.parent, break: false }
80                     : 0 /* NoSuper */;
81             case ts.SyntaxKind.ConditionalExpression: {
82                 var _a = node, condition = _a.condition, whenTrue = _a.whenTrue, whenFalse = _a.whenFalse;
83                 var inCondition = getSuperForNode(condition);
84                 var inBranches = worse(getSuperForNode(whenTrue), getSuperForNode(whenFalse));
85                 if (typeof inCondition !== "number" && typeof inBranches !== "number") {
86                     addDuplicateFailure(inCondition.node, inBranches.node);
87                 }
88                 return worse(inCondition, inBranches);
89             }
90             case ts.SyntaxKind.IfStatement: {
91                 var _b = node, thenStatement = _b.thenStatement, elseStatement = _b.elseStatement;
92                 return worse(getSuperForNode(thenStatement), elseStatement !== undefined ? getSuperForNode(elseStatement) : 0 /* NoSuper */);
93             }
94             case ts.SyntaxKind.SwitchStatement:
95                 return getSuperForSwitch(node);
96             default:
97                 return combineSequentialChildren(node);
98         }
99     }
100     function getSuperForSwitch(node) {
101         // 'super()' from any clause. Used to track whether 'super()' happens in the switch at all.
102         var foundSingle;
103         // 'super()' from the previous clause if it did not 'break;'.
104         var fallthroughSingle;
105         for (var _i = 0, _a = node.caseBlock.clauses; _i < _a.length; _i++) {
106             var clause = _a[_i];
107             var clauseSuper = combineSequentialChildren(clause);
108             switch (clauseSuper) {
109                 case 0 /* NoSuper */:
110                     break;
111                 case 2 /* Break */:
112                     fallthroughSingle = undefined;
113                     break;
114                 case 1 /* Return */:
115                     return 0 /* NoSuper */;
116                 default:
117                     if (fallthroughSingle !== undefined) {
118                         addDuplicateFailure(fallthroughSingle, clauseSuper.node);
119                     }
120                     if (!clauseSuper.break) {
121                         fallthroughSingle = clauseSuper.node;
122                     }
123                     foundSingle = clauseSuper.node;
124             }
125         }
126         return foundSingle !== undefined ? { node: foundSingle, break: false } : 0 /* NoSuper */;
127     }
128     /**
129      * Combines children that come one after another.
130      * (As opposed to if/else, switch, or loops, which need their own handling.)
131      */
132     function combineSequentialChildren(node) {
133         var seenSingle;
134         var res = ts.forEachChild(node, function (child) {
135             var childSuper = getSuperForNode(child);
136             switch (childSuper) {
137                 case 0 /* NoSuper */:
138                     return undefined;
139                 case 2 /* Break */:
140                     if (seenSingle !== undefined) {
141                         return tslib_1.__assign({}, seenSingle, { break: true });
142                     }
143                     return childSuper;
144                 case 1 /* Return */:
145                     return childSuper;
146                 default:
147                     if (seenSingle !== undefined && !seenSingle.break) {
148                         addDuplicateFailure(seenSingle.node, childSuper.node);
149                     }
150                     seenSingle = childSuper;
151                     return undefined;
152             }
153         });
154         return res !== undefined ? res : seenSingle !== undefined ? seenSingle : 0 /* NoSuper */;
155     }
156     function addDuplicateFailure(a, b) {
157         ctx.addFailure(a.getStart(), b.end, Rule.FAILURE_STRING_DUPLICATE);
158     }
159 }
160 // If/else run separately, so return the branch more likely to result in eventual errors.
161 function worse(a, b) {
162     return typeof a === "number"
163         ? typeof b === "number"
164             ? a < b
165                 ? b
166                 : a
167             : b
168         : typeof b === "number"
169             ? a
170             : a.break
171                 ? b
172                 : a;
173 }