Skip to content

Commit 432fff1

Browse files
committed
Merge pull request #823 from chrisbubernak/betterErrorsForBitwiseOperatorsOnBooleans
Fix for issue #712
2 parents ded27df + 7398853 commit 432fff1

10 files changed

+277
-176
lines changed

src/compiler/checker.ts

Lines changed: 31 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5050,10 +5050,21 @@ module ts {
50505050
if (leftType.flags & (TypeFlags.Undefined | TypeFlags.Null)) leftType = rightType;
50515051
if (rightType.flags & (TypeFlags.Undefined | TypeFlags.Null)) rightType = leftType;
50525052

5053-
var leftOk = checkArithmeticOperandType(node.left, leftType, Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
5054-
var rightOk = checkArithmeticOperandType(node.right, rightType, Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
5055-
if (leftOk && rightOk) {
5056-
checkAssignmentOperator(numberType);
5053+
var suggestedOperator: SyntaxKind;
5054+
// if a user tries to apply a bitwise operator to 2 boolean operands
5055+
// try and return them a helpful suggestion
5056+
if ((leftType.flags & TypeFlags.Boolean) &&
5057+
(rightType.flags & TypeFlags.Boolean) &&
5058+
(suggestedOperator = getSuggestedBooleanOperator(node.operator)) !== undefined) {
5059+
error(node, Diagnostics.The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead, tokenToString(node.operator), tokenToString(suggestedOperator));
5060+
}
5061+
else {
5062+
// otherwise just check each operand separately and report errors as normal
5063+
var leftOk = checkArithmeticOperandType(node.left, leftType, Diagnostics.The_left_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
5064+
var rightOk = checkArithmeticOperandType(node.right, rightType, Diagnostics.The_right_hand_side_of_an_arithmetic_operation_must_be_of_type_any_number_or_an_enum_type);
5065+
if (leftOk && rightOk) {
5066+
checkAssignmentOperator(numberType);
5067+
}
50575068
}
50585069

50595070
return numberType;
@@ -5118,6 +5129,22 @@ module ts {
51185129
case SyntaxKind.CommaToken:
51195130
return rightType;
51205131
}
5132+
5133+
function getSuggestedBooleanOperator(operator: SyntaxKind): SyntaxKind {
5134+
switch (operator) {
5135+
case SyntaxKind.BarToken:
5136+
case SyntaxKind.BarEqualsToken:
5137+
return SyntaxKind.BarBarToken;
5138+
case SyntaxKind.CaretToken:
5139+
case SyntaxKind.CaretEqualsToken:
5140+
return SyntaxKind.ExclamationEqualsEqualsToken;
5141+
case SyntaxKind.AmpersandToken:
5142+
case SyntaxKind.AmpersandEqualsToken:
5143+
return SyntaxKind.AmpersandAmpersandToken;
5144+
default:
5145+
return undefined;
5146+
}
5147+
}
51215148

51225149
function checkAssignmentOperator(valueType: Type): void {
51235150
if (fullTypeCheck && operator >= SyntaxKind.FirstAssignment && operator <= SyntaxKind.LastAssignment) {

src/compiler/diagnosticInformationMap.generated.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,7 @@ module ts {
261261
Property_0_is_protected_in_type_1_but_public_in_type_2: { code: 2444, category: DiagnosticCategory.Error, key: "Property '{0}' is protected in type '{1}' but public in type '{2}'." },
262262
Property_0_is_protected_and_only_accessible_within_class_1_and_its_subclasses: { code: 2445, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible within class '{1}' and its subclasses." },
263263
Property_0_is_protected_and_only_accessible_through_an_instance_of_class_1: { code: 2446, category: DiagnosticCategory.Error, key: "Property '{0}' is protected and only accessible through an instance of class '{1}'." },
264+
The_0_operator_is_not_allowed_for_boolean_types_Consider_using_1_instead: { code: 2447, category: DiagnosticCategory.Error, key: "The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead." },
264265
Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." },
265266
Type_parameter_0_of_exported_class_has_or_is_using_name_1_from_private_module_2: { code: 4001, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using name '{1}' from private module '{2}'." },
266267
Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." },

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1036,6 +1036,10 @@
10361036
"category": "Error",
10371037
"code": 2446
10381038
},
1039+
"The '{0}' operator is not allowed for boolean types. Consider using '{1}' instead.": {
1040+
"category": "Error",
1041+
"code": 2447
1042+
},
10391043

10401044
"Import declaration '{0}' is using private name '{1}'.": {
10411045
"category": "Error",

tests/baselines/reference/arithmeticOperatorWithInvalidOperands.errors.txt

Lines changed: 10 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -395,8 +395,7 @@ tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeti
395395
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(417,16): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
396396
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(418,16): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
397397
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(420,12): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
398-
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(421,12): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
399-
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(421,16): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
398+
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(421,12): error TS2447: The '&' operator is not allowed for boolean types. Consider using '&&' instead.
400399
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(422,12): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
401400
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(423,12): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
402401
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(423,16): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
@@ -451,8 +450,7 @@ tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeti
451450
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(474,16): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
452451
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(475,16): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
453452
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(477,12): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
454-
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(478,12): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
455-
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(478,16): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
453+
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(478,12): error TS2447: The '^' operator is not allowed for boolean types. Consider using '!==' instead.
456454
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(479,12): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
457455
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(480,12): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
458456
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(480,16): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
@@ -507,8 +505,7 @@ tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeti
507505
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(531,17): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
508506
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(532,17): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
509507
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(534,13): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
510-
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(535,13): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
511-
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(535,17): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
508+
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(535,13): error TS2447: The '|' operator is not allowed for boolean types. Consider using '||' instead.
512509
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(536,13): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
513510
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(537,13): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
514511
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(537,17): error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
@@ -560,7 +557,7 @@ tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeti
560557
tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts(581,13): error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
561558

562559

563-
==== tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts (560 errors) ====
560+
==== tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeticOperatorWithInvalidOperands.ts (557 errors) ====
564561
// these operators require their operands to be of type Any, the Number primitive type, or
565562
// an enum type
566563
enum E { a, b, c }
@@ -1776,10 +1773,8 @@ tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeti
17761773
~
17771774
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
17781775
var r8b2 = b & b;
1779-
~
1780-
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
1781-
~
1782-
!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
1776+
~~~~~
1777+
!!! error TS2447: The '&' operator is not allowed for boolean types. Consider using '&&' instead.
17831778
var r8b3 = b & c;
17841779
~
17851780
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
@@ -1945,10 +1940,8 @@ tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeti
19451940
~
19461941
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
19471942
var r9b2 = b ^ b;
1948-
~
1949-
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
1950-
~
1951-
!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
1943+
~~~~~
1944+
!!! error TS2447: The '^' operator is not allowed for boolean types. Consider using '!==' instead.
19521945
var r9b3 = b ^ c;
19531946
~
19541947
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
@@ -2114,10 +2107,8 @@ tests/cases/conformance/expressions/binaryOperators/arithmeticOperator/arithmeti
21142107
~
21152108
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
21162109
var r10b2 = b | b;
2117-
~
2118-
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
2119-
~
2120-
!!! error TS2363: The right-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.
2110+
~~~~~
2111+
!!! error TS2447: The '|' operator is not allowed for boolean types. Consider using '||' instead.
21212112
var r10b3 = b | c;
21222113
~
21232114
!!! error TS2362: The left-hand side of an arithmetic operation must be of type 'any', 'number' or an enum type.

0 commit comments

Comments
 (0)