aboutsummaryrefslogtreecommitdiff
path: root/node_modules/tslint/lib/rules/strictBooleanExpressionsRule.js
diff options
context:
space:
mode:
authorFlorian Dold <florian.dold@gmail.com>2017-08-14 05:01:11 +0200
committerFlorian Dold <florian.dold@gmail.com>2017-08-14 05:02:09 +0200
commit363723fc84f7b8477592e0105aeb331ec9a017af (patch)
tree29f92724f34131bac64d6a318dd7e30612e631c7 /node_modules/tslint/lib/rules/strictBooleanExpressionsRule.js
parent5634e77ad96bfe1818f6b6ee70b7379652e5487f (diff)
node_modules
Diffstat (limited to 'node_modules/tslint/lib/rules/strictBooleanExpressionsRule.js')
-rw-r--r--node_modules/tslint/lib/rules/strictBooleanExpressionsRule.js99
1 files changed, 69 insertions, 30 deletions
diff --git a/node_modules/tslint/lib/rules/strictBooleanExpressionsRule.js b/node_modules/tslint/lib/rules/strictBooleanExpressionsRule.js
index a202e2c49..0d1851179 100644
--- a/node_modules/tslint/lib/rules/strictBooleanExpressionsRule.js
+++ b/node_modules/tslint/lib/rules/strictBooleanExpressionsRule.js
@@ -24,6 +24,7 @@ var OPTION_ALLOW_UNDEFINED_UNION = "allow-undefined-union";
var OPTION_ALLOW_STRING = "allow-string";
var OPTION_ALLOW_NUMBER = "allow-number";
var OPTION_ALLOW_MIX = "allow-mix";
+var OPTION_ALLOW_BOOLEAN_OR_UNDEFINED = "allow-boolean-or-undefined";
// tslint:disable object-literal-sort-keys switch-default
var Rule = (function (_super) {
tslib_1.__extends(Rule, _super);
@@ -31,32 +32,39 @@ var Rule = (function (_super) {
return _super !== null && _super.apply(this, arguments) || this;
}
Rule.prototype.applyWithProgram = function (sourceFile, program) {
- var options = parseOptions(this.ruleArguments, program.getCompilerOptions().strictNullChecks === true);
+ var options = parseOptions(this.ruleArguments, Lint.isStrictNullChecksEnabled(program.getCompilerOptions()));
return this.applyWithFunction(sourceFile, function (ctx) { return walk(ctx, program.getTypeChecker()); }, options);
};
+ Rule.metadata = {
+ ruleName: "strict-boolean-expressions",
+ description: (_a = ["\n Restricts the types allowed in boolean expressions. By default only booleans are allowed.\n\n The following nodes are checked:\n\n * Arguments to the `!`, `&&`, and `||` operators\n * The condition in a conditional expression (`cond ? x : y`)\n * Conditions for `if`, `for`, `while`, and `do-while` statements."], _a.raw = ["\n Restricts the types allowed in boolean expressions. By default only booleans are allowed.\n\n The following nodes are checked:\n\n * Arguments to the \\`!\\`, \\`&&\\`, and \\`||\\` operators\n * The condition in a conditional expression (\\`cond ? x : y\\`)\n * Conditions for \\`if\\`, \\`for\\`, \\`while\\`, and \\`do-while\\` statements."], Lint.Utils.dedent(_a)),
+ optionsDescription: (_b = ["\n These options may be provided:\n\n * `", "` allows union types containing `null`.\n - It does *not* allow `null` itself.\n - Without the '--strictNullChecks' compiler option, this will allow anything other than a string, number, or enum.\n * `", "` allows union types containing `undefined`.\n - It does *not* allow `undefined` itself.\n - Without the '--strictNullChecks' compiler option, this will allow anything other than a string, number, or enum.\n * `", "` allows strings.\n - It does *not* allow unions containing `string`.\n - It does *not* allow string literal types.\n * `", "` allows numbers.\n - It does *not* allow unions containing `number`.\n - It does *not* allow enums or number literal types.\n * `", "` allows multiple of the above to appear together.\n - For example, `string | number` or `RegExp | null | undefined` would normally not be allowed.\n - A type like `\"foo\" | \"bar\" | undefined` is always allowed, because it has only one way to be false.\n * `", "` allows `boolean | undefined`.\n - Also allows `true | false | undefined`.\n - Does not allow `false | undefined`.\n - This option is a subset of `", "`, so you don't need to enable both options at the same time.\n "], _b.raw = ["\n These options may be provided:\n\n * \\`", "\\` allows union types containing \\`null\\`.\n - It does *not* allow \\`null\\` itself.\n - Without the '--strictNullChecks' compiler option, this will allow anything other than a string, number, or enum.\n * \\`", "\\` allows union types containing \\`undefined\\`.\n - It does *not* allow \\`undefined\\` itself.\n - Without the '--strictNullChecks' compiler option, this will allow anything other than a string, number, or enum.\n * \\`", "\\` allows strings.\n - It does *not* allow unions containing \\`string\\`.\n - It does *not* allow string literal types.\n * \\`", "\\` allows numbers.\n - It does *not* allow unions containing \\`number\\`.\n - It does *not* allow enums or number literal types.\n * \\`", "\\` allows multiple of the above to appear together.\n - For example, \\`string | number\\` or \\`RegExp | null | undefined\\` would normally not be allowed.\n - A type like \\`\"foo\" | \"bar\" | undefined\\` is always allowed, because it has only one way to be false.\n * \\`", "\\` allows \\`boolean | undefined\\`.\n - Also allows \\`true | false | undefined\\`.\n - Does not allow \\`false | undefined\\`.\n - This option is a subset of \\`", "\\`, so you don't need to enable both options at the same time.\n "], Lint.Utils.dedent(_b, OPTION_ALLOW_NULL_UNION, OPTION_ALLOW_UNDEFINED_UNION, OPTION_ALLOW_STRING, OPTION_ALLOW_NUMBER, OPTION_ALLOW_MIX, OPTION_ALLOW_BOOLEAN_OR_UNDEFINED, OPTION_ALLOW_UNDEFINED_UNION)),
+ options: {
+ type: "array",
+ items: {
+ type: "string",
+ enum: [
+ OPTION_ALLOW_NULL_UNION,
+ OPTION_ALLOW_UNDEFINED_UNION,
+ OPTION_ALLOW_STRING,
+ OPTION_ALLOW_NUMBER,
+ OPTION_ALLOW_BOOLEAN_OR_UNDEFINED,
+ ],
+ },
+ minLength: 0,
+ maxLength: 5,
+ },
+ optionExamples: [
+ true,
+ [true, OPTION_ALLOW_NULL_UNION, OPTION_ALLOW_UNDEFINED_UNION, OPTION_ALLOW_STRING, OPTION_ALLOW_NUMBER],
+ [true, OPTION_ALLOW_BOOLEAN_OR_UNDEFINED],
+ ],
+ type: "functionality",
+ typescriptOnly: true,
+ requiresTypeInfo: true,
+ };
return Rule;
}(Lint.Rules.TypedRule));
-Rule.metadata = {
- ruleName: "strict-boolean-expressions",
- description: (_a = ["\n Restricts the types allowed in boolean expressions. By default only booleans are allowed.\n\n The following nodes are checked:\n\n * Arguments to the `!`, `&&`, and `||` operators\n * The condition in a conditional expression (`cond ? x : y`)\n * Conditions for `if`, `for`, `while`, and `do-while` statements."], _a.raw = ["\n Restricts the types allowed in boolean expressions. By default only booleans are allowed.\n\n The following nodes are checked:\n\n * Arguments to the \\`!\\`, \\`&&\\`, and \\`||\\` operators\n * The condition in a conditional expression (\\`cond ? x : y\\`)\n * Conditions for \\`if\\`, \\`for\\`, \\`while\\`, and \\`do-while\\` statements."], Lint.Utils.dedent(_a)),
- optionsDescription: (_b = ["\n These options may be provided:\n\n * `", "` allows union types containing `null`.\n - It does *not* allow `null` itself.\n - Without the '--strictNullChecks' compiler option, this will allow anything other than a string, number, or enum.\n * `", "` allows union types containing `undefined`.\n - It does *not* allow `undefined` itself.\n - Without the '--strictNullChecks' compiler option, this will allow anything other than a string, number, or enum.\n * `", "` allows strings.\n - It does *not* allow unions containing `string`.\n - It does *not* allow string literal types.\n * `", "` allows numbers.\n - It does *not* allow unions containing `number`.\n - It does *not* allow enums or number literal types.\n * `", "` allow multiple of the above to appear together.\n - For example, `string | number` or `RegExp | null | undefined` would normally not be allowed.\n - A type like `\"foo\" | \"bar\" | undefined` is always allowed, because it has only one way to be false."], _b.raw = ["\n These options may be provided:\n\n * \\`", "\\` allows union types containing \\`null\\`.\n - It does *not* allow \\`null\\` itself.\n - Without the '--strictNullChecks' compiler option, this will allow anything other than a string, number, or enum.\n * \\`", "\\` allows union types containing \\`undefined\\`.\n - It does *not* allow \\`undefined\\` itself.\n - Without the '--strictNullChecks' compiler option, this will allow anything other than a string, number, or enum.\n * \\`", "\\` allows strings.\n - It does *not* allow unions containing \\`string\\`.\n - It does *not* allow string literal types.\n * \\`", "\\` allows numbers.\n - It does *not* allow unions containing \\`number\\`.\n - It does *not* allow enums or number literal types.\n * \\`", "\\` allow multiple of the above to appear together.\n - For example, \\`string | number\\` or \\`RegExp | null | undefined\\` would normally not be allowed.\n - A type like \\`\"foo\" | \"bar\" | undefined\\` is always allowed, because it has only one way to be false."], Lint.Utils.dedent(_b, OPTION_ALLOW_NULL_UNION, OPTION_ALLOW_UNDEFINED_UNION, OPTION_ALLOW_STRING, OPTION_ALLOW_NUMBER, OPTION_ALLOW_MIX)),
- options: {
- type: "array",
- items: {
- type: "string",
- enum: [OPTION_ALLOW_NULL_UNION, OPTION_ALLOW_UNDEFINED_UNION, OPTION_ALLOW_STRING, OPTION_ALLOW_NUMBER],
- },
- minLength: 0,
- maxLength: 5,
- },
- optionExamples: [
- true,
- [true, OPTION_ALLOW_NULL_UNION, OPTION_ALLOW_UNDEFINED_UNION, OPTION_ALLOW_STRING, OPTION_ALLOW_NUMBER],
- ],
- type: "functionality",
- typescriptOnly: true,
- requiresTypeInfo: true,
-};
exports.Rule = Rule;
function parseOptions(ruleArguments, strictNullChecks) {
return {
@@ -66,6 +74,7 @@ function parseOptions(ruleArguments, strictNullChecks) {
allowString: has(OPTION_ALLOW_STRING),
allowNumber: has(OPTION_ALLOW_NUMBER),
allowMix: has(OPTION_ALLOW_MIX),
+ allowBooleanOrUndefined: has(OPTION_ALLOW_BOOLEAN_OR_UNDEFINED),
};
function has(name) {
return ruleArguments.indexOf(name) !== -1;
@@ -115,7 +124,6 @@ function walk(ctx, checker) {
if (condition !== undefined) {
checkExpression(condition, node);
}
- break;
}
}
return ts.forEachChild(node, cb);
@@ -145,14 +153,41 @@ function getTypeFailure(type, options) {
}
switch (triState(kind)) {
case true:
- return 0 /* AlwaysTruthy */;
+ // Allow 'any'. Allow 'true' itself, but not any other always-truthy type.
+ // tslint:disable-next-line no-bitwise
+ return Lint.isTypeFlagSet(type, ts.TypeFlags.Any | ts.TypeFlags.BooleanLiteral) ? undefined : 0 /* AlwaysTruthy */;
case false:
- return 1 /* AlwaysFalsy */;
+ // Allow 'false' itself, but not any other always-falsy type
+ return Lint.isTypeFlagSet(type, ts.TypeFlags.BooleanLiteral) ? undefined : 1 /* AlwaysFalsy */;
case undefined:
return undefined;
}
}
+function isBooleanUndefined(type) {
+ var isTruthy = false;
+ for (var _i = 0, _a = type.types; _i < _a.length; _i++) {
+ var ty = _a[_i];
+ if (Lint.isTypeFlagSet(ty, ts.TypeFlags.Boolean)) {
+ isTruthy = true;
+ }
+ else if (Lint.isTypeFlagSet(ty, ts.TypeFlags.BooleanLiteral)) {
+ isTruthy = isTruthy || ty.intrinsicName === "true";
+ }
+ else if (!Lint.isTypeFlagSet(ty, ts.TypeFlags.Void | ts.TypeFlags.Undefined)) {
+ return undefined;
+ }
+ }
+ return isTruthy;
+}
function handleUnion(type, options) {
+ if (options.allowBooleanOrUndefined) {
+ switch (isBooleanUndefined(type)) {
+ case true:
+ return undefined;
+ case false:
+ return 1 /* AlwaysFalsy */;
+ }
+ }
// Tracks whether it's possibly truthy.
var anyTruthy = false;
// Counts falsy kinds to see if there's a mix. Also tracks whether it's possibly falsy.
@@ -236,10 +271,11 @@ function getKind(type) {
}
}
function numberLiteralIsZero(type) {
- // Uses 'value' in TypeScript>=2.4.
+ // for compatibility with typescript@<2.4.0
return type.value !== undefined ? type.value === 0 : type.text === "0";
}
function stringLiteralIsEmpty(type) {
+ // for compatibility with typescript@<2.4.0
return (type.value !== undefined ? type.value : type.text) === "";
}
/** Matches `&&` and `||` operators. */
@@ -291,12 +327,12 @@ function showLocation(n) {
return "operand for the '" + binaryBooleanExpressionKind(n) + "' operator";
}
}
-function showFailure(location, ty, isUnionType, options) {
+function showFailure(location, ty, unionType, options) {
var expectedTypes = showExpectedTypes(options);
var expected = expectedTypes.length === 1
? "Only " + expectedTypes[0] + "s are allowed"
: "Allowed types are " + stringOr(expectedTypes);
- var tyFail = showTypeFailure(ty, isUnionType, options.strictNullChecks);
+ var tyFail = showTypeFailure(ty, unionType, options.strictNullChecks);
return "This type is not allowed in the " + showLocation(location) + " because it " + tyFail + ". " + expected + ".";
}
function showExpectedTypes(options) {
@@ -313,10 +349,13 @@ function showExpectedTypes(options) {
if (options.allowNumber) {
parts.push("number");
}
+ if (options.allowBooleanOrUndefined) {
+ parts.push("boolean-or-undefined");
+ }
return parts;
}
-function showTypeFailure(ty, isUnionType, strictNullChecks) {
- var is = isUnionType ? "could be" : "is";
+function showTypeFailure(ty, unionType, strictNullChecks) {
+ var is = unionType ? "could be" : "is";
switch (ty) {
case 0 /* AlwaysTruthy */:
return strictNullChecks