Fixed nullish coalesce operator's precedence (#61372)

This commit is contained in:
Mateusz Burzyński
2025-06-30 22:49:03 +02:00
committed by GitHub
parent 58665cf3ae
commit 91cdbd518c
15 changed files with 240 additions and 30 deletions

View File

@@ -40472,18 +40472,29 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
}
function checkNullishCoalesceOperands(node: BinaryExpression) {
const { left, operatorToken, right } = node;
if (operatorToken.kind === SyntaxKind.QuestionQuestionToken) {
if (isBinaryExpression(left) && (left.operatorToken.kind === SyntaxKind.BarBarToken || left.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) {
grammarErrorOnNode(left, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(left.operatorToken.kind), tokenToString(operatorToken.kind));
}
if (isBinaryExpression(right) && (right.operatorToken.kind === SyntaxKind.BarBarToken || right.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken)) {
grammarErrorOnNode(right, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(right.operatorToken.kind), tokenToString(operatorToken.kind));
}
checkNullishCoalesceOperandLeft(node);
checkNullishCoalesceOperandRight(node);
if (node.operatorToken.kind !== SyntaxKind.QuestionQuestionToken) {
return;
}
if (isBinaryExpression(node.parent)) {
const { left, operatorToken } = node.parent;
if (isBinaryExpression(left) && operatorToken.kind === SyntaxKind.BarBarToken) {
grammarErrorOnNode(left, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(SyntaxKind.QuestionQuestionToken), tokenToString(operatorToken.kind));
}
}
else if (isBinaryExpression(node.left)) {
const { operatorToken } = node.left;
if (operatorToken.kind === SyntaxKind.BarBarToken || operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
grammarErrorOnNode(node.left, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(operatorToken.kind), tokenToString(SyntaxKind.QuestionQuestionToken));
}
}
else if (isBinaryExpression(node.right)) {
const { operatorToken } = node.right;
if (operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
grammarErrorOnNode(node.right, Diagnostics._0_and_1_operations_cannot_be_mixed_without_parentheses, tokenToString(SyntaxKind.QuestionQuestionToken), tokenToString(operatorToken.kind));
}
}
checkNullishCoalesceOperandLeft(node);
checkNullishCoalesceOperandRight(node);
}
function checkNullishCoalesceOperandLeft(node: BinaryExpression) {

View File

@@ -5675,17 +5675,17 @@ export const enum OperatorPrecedence {
// CoalesceExpression
Conditional,
// LogicalORExpression:
// LogicalANDExpression
// LogicalORExpression `||` LogicalANDExpression
LogicalOR,
// CoalesceExpression:
// CoalesceExpressionHead `??` BitwiseORExpression
// CoalesceExpressionHead:
// CoalesceExpression
// BitwiseORExpression
Coalesce = Conditional, // NOTE: This is wrong
// LogicalORExpression:
// LogicalANDExpression
// LogicalORExpression `||` LogicalANDExpression
LogicalOR,
Coalesce = LogicalOR,
// LogicalANDExpression:
// BitwiseORExpression