.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / tslint / lib / rules / returnUndefinedRule.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.applyWithProgram = function (sourceFile, program) {
29         return this.applyWithFunction(sourceFile, walk, undefined, program.getTypeChecker());
30     };
31     /* tslint:disable:object-literal-sort-keys */
32     Rule.metadata = {
33         ruleName: "return-undefined",
34         description: "Prefer `return;` in void functions and `return undefined;` in value-returning functions.",
35         optionsDescription: "Not configurable.",
36         options: null,
37         optionExamples: [true],
38         type: "style",
39         typescriptOnly: false,
40         requiresTypeInfo: true,
41     };
42     /* tslint:enable:object-literal-sort-keys */
43     Rule.FAILURE_STRING_VALUE_RETURN = "Value-returning function should use `return undefined;`, not just `return;`.";
44     Rule.FAILURE_STRING_VOID_RETURN = "`void` function should use `return;`, not `return undefined;`.";
45     return Rule;
46 }(Lint.Rules.TypedRule));
47 exports.Rule = Rule;
48 function walk(ctx, checker) {
49     return ts.forEachChild(ctx.sourceFile, function cb(node) {
50         if (tsutils_1.isReturnStatement(node)) {
51             check(node);
52         }
53         return ts.forEachChild(node, cb);
54     });
55     function check(node) {
56         var actualReturnKind = getReturnKindFromReturnStatement(node);
57         if (actualReturnKind === undefined) {
58             return;
59         }
60         var functionReturningFrom = Lint.ancestorWhere(node, isFunctionLike);
61         if (functionReturningFrom === undefined) {
62             // Return outside of function is invalid
63             return;
64         }
65         var returnKindFromType = getReturnKindFromFunction(functionReturningFrom, checker);
66         if (returnKindFromType !== undefined && returnKindFromType !== actualReturnKind) {
67             ctx.addFailureAtNode(node, returnKindFromType === "void" /* Void */
68                 ? Rule.FAILURE_STRING_VOID_RETURN
69                 : Rule.FAILURE_STRING_VALUE_RETURN);
70         }
71     }
72 }
73 function getReturnKindFromReturnStatement(node) {
74     if (node.expression === undefined) {
75         return "void" /* Void */;
76     }
77     else if (tsutils_1.isIdentifier(node.expression) && node.expression.text === "undefined") {
78         return "value" /* Value */;
79     }
80     else {
81         return undefined;
82     }
83 }
84 function getReturnKindFromFunction(node, checker) {
85     switch (node.kind) {
86         case ts.SyntaxKind.Constructor:
87         case ts.SyntaxKind.SetAccessor:
88             return "void" /* Void */;
89         case ts.SyntaxKind.GetAccessor:
90             return "value" /* Value */;
91     }
92     // Handle generator functions/methods:
93     if (node.asteriskToken !== undefined) {
94         return "void" /* Void */;
95     }
96     var contextual = isFunctionExpressionLike(node) && node.type === undefined
97         ? tryGetReturnType(checker.getContextualType(node), checker)
98         : undefined;
99     var returnType = contextual !== undefined
100         ? contextual
101         : tryGetReturnType(checker.getTypeAtLocation(node), checker);
102     if (returnType === undefined || tsutils_1.isTypeFlagSet(returnType, ts.TypeFlags.Any)) {
103         return undefined;
104     }
105     var effectivelyVoidChecker = tsutils_1.hasModifier(node.modifiers, ts.SyntaxKind.AsyncKeyword)
106         ? isEffectivelyVoidPromise
107         : isEffectivelyVoid;
108     if (effectivelyVoidChecker(returnType)) {
109         return "void" /* Void */;
110     }
111     return "value" /* Value */;
112 }
113 /** True for `void`, `undefined`, Promise<void>, or `void | undefined | Promise<void>`. */
114 function isEffectivelyVoidPromise(type) {
115     // Would need access to `checker.getPromisedTypeOfPromise` to do this properly.
116     // Assume that the return type is the global Promise (since this is an async function) and get its type argument.
117     return (
118     // tslint:disable-next-line:no-bitwise
119     tsutils_1.isTypeFlagSet(type, ts.TypeFlags.Void | ts.TypeFlags.Undefined) ||
120         (tsutils_1.isUnionType(type) && type.types.every(isEffectivelyVoidPromise)) ||
121         (tsutils_1.isTypeReference(type) &&
122             type.typeArguments !== undefined &&
123             type.typeArguments.length === 1 &&
124             isEffectivelyVoidPromise(type.typeArguments[0])));
125 }
126 /** True for `void`, `undefined`, or `void | undefined`. */
127 function isEffectivelyVoid(type) {
128     return (
129     // tslint:disable-next-line:no-bitwise
130     tsutils_1.isTypeFlagSet(type, ts.TypeFlags.Void | ts.TypeFlags.Undefined) ||
131         (tsutils_1.isUnionType(type) && type.types.every(isEffectivelyVoid)));
132 }
133 function tryGetReturnType(fnType, checker) {
134     if (fnType === undefined) {
135         return undefined;
136     }
137     var sigs = checker.getSignaturesOfType(fnType, ts.SignatureKind.Call);
138     if (sigs.length !== 1) {
139         return undefined;
140     }
141     return checker.getReturnTypeOfSignature(sigs[0]);
142 }
143 function isFunctionLike(node) {
144     switch (node.kind) {
145         case ts.SyntaxKind.FunctionDeclaration:
146         case ts.SyntaxKind.FunctionExpression:
147         case ts.SyntaxKind.ArrowFunction:
148         case ts.SyntaxKind.MethodDeclaration:
149         case ts.SyntaxKind.Constructor:
150         case ts.SyntaxKind.GetAccessor:
151         case ts.SyntaxKind.SetAccessor:
152             return true;
153         default:
154             return false;
155     }
156 }
157 function isFunctionExpressionLike(node) {
158     return (node.kind === ts.SyntaxKind.FunctionExpression || node.kind === ts.SyntaxKind.ArrowFunction);
159 }