Skip to content

Commit cf3e28e

Browse files
committed
Revert "feat(40197): handle uncalled function checks in binary expressions (#40260)"
This reverts commit eaf4f46.
1 parent eaf4f46 commit cf3e28e

15 files changed

+24
-1069
lines changed

src/compiler/binder.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -665,7 +665,7 @@ namespace ts {
665665
}
666666
// We create a return control flow graph for IIFEs and constructors. For constructors
667667
// we use the return control flow graph in strict property initialization checks.
668-
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined;
668+
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor || (isInJSFile && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined;
669669
currentExceptionTarget = undefined;
670670
currentBreakTarget = undefined;
671671
currentContinueTarget = undefined;
@@ -686,7 +686,7 @@ namespace ts {
686686
if (currentReturnTarget) {
687687
addAntecedent(currentReturnTarget, currentFlow);
688688
currentFlow = finishFlowLabel(currentReturnTarget);
689-
if (node.kind === SyntaxKind.Constructor || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) {
689+
if (node.kind === SyntaxKind.Constructor || (isInJSFile && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) {
690690
(<FunctionLikeDeclaration>node).returnFlowNode = currentFlow;
691691
}
692692
}

src/compiler/checker.ts

Lines changed: 19 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -30006,9 +30006,6 @@ namespace ts {
3000630006
workStacks.leftType[stackIndex] = leftType;
3000730007
const operator = node.operatorToken.kind;
3000830008
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
30009-
if (operator === SyntaxKind.AmpersandAmpersandToken) {
30010-
checkTestingKnownTruthyCallableType(node.left, leftType);
30011-
}
3001230009
checkTruthinessOfType(leftType, node.left);
3001330010
}
3001430011
advanceState(CheckBinaryExpressionState.FinishCheck);
@@ -30542,7 +30539,7 @@ namespace ts {
3054230539

3054330540
function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type {
3054430541
const type = checkTruthinessExpression(node.condition);
30545-
checkTestingKnownTruthyCallableType(node.condition, type, node.whenTrue);
30542+
checkTestingKnownTruthyCallableType(node.condition, node.whenTrue, type);
3054630543
const type1 = checkExpression(node.whenTrue, checkMode);
3054730544
const type2 = checkExpression(node.whenFalse, checkMode);
3054830545
return getUnionType([type1, type2], UnionReduction.Subtype);
@@ -33778,7 +33775,7 @@ namespace ts {
3377833775
// Grammar checking
3377933776
checkGrammarStatementInAmbientContext(node);
3378033777
const type = checkTruthinessExpression(node.expression);
33781-
checkTestingKnownTruthyCallableType(node.expression, type, node.thenStatement);
33778+
checkTestingKnownTruthyCallableType(node.expression, node.thenStatement, type);
3378233779
checkSourceElement(node.thenStatement);
3378333780

3378433781
if (node.thenStatement.kind === SyntaxKind.EmptyStatement) {
@@ -33788,16 +33785,16 @@ namespace ts {
3378833785
checkSourceElement(node.elseStatement);
3378933786
}
3379033787

33791-
function checkTestingKnownTruthyCallableType(condExpr: Expression, type: Type, body?: Statement | Expression) {
33788+
function checkTestingKnownTruthyCallableType(condExpr: Expression, body: Statement | Expression, type: Type) {
3379233789
if (!strictNullChecks) {
3379333790
return;
3379433791
}
3379533792

33796-
const location = isBinaryExpression(condExpr) ? condExpr.right : condExpr;
33797-
const testedNode = isIdentifier(location) ? location
33798-
: isPropertyAccessExpression(location) ? location.name
33799-
: isBinaryExpression(location) && isIdentifier(location.right) ? location.right
33800-
: undefined;
33793+
const testedNode = isIdentifier(condExpr)
33794+
? condExpr
33795+
: isPropertyAccessExpression(condExpr)
33796+
? condExpr.name
33797+
: undefined;
3380133798

3380233799
if (!testedNode) {
3380333800
return;
@@ -33818,34 +33815,27 @@ namespace ts {
3381833815
return;
3381933816
}
3382033817

33821-
const testedSymbol = getSymbolAtLocation(testedNode);
33822-
if (!testedSymbol) {
33818+
const testedFunctionSymbol = getSymbolAtLocation(testedNode);
33819+
if (!testedFunctionSymbol) {
3382333820
return;
3382433821
}
3382533822

33826-
const isUsed = isBinaryExpression(condExpr.parent) ? isFunctionUsedInBinaryExpressionChain(condExpr.parent, testedSymbol)
33827-
: body ? isFunctionUsedInConditionBody(condExpr, body, testedNode, testedSymbol)
33828-
: false;
33829-
if (!isUsed) {
33830-
error(location, Diagnostics.This_condition_will_always_return_true_since_the_function_is_always_defined_Did_you_mean_to_call_it_instead);
33831-
}
33832-
}
33833-
33834-
function isFunctionUsedInConditionBody(expr: Expression, body: Statement | Expression, testedNode: Node, testedSymbol: Symbol): boolean {
33835-
return !!forEachChild(body, function check(childNode): boolean | undefined {
33823+
const functionIsUsedInBody = forEachChild(body, function check(childNode): boolean | undefined {
3383633824
if (isIdentifier(childNode)) {
3383733825
const childSymbol = getSymbolAtLocation(childNode);
33838-
if (childSymbol && childSymbol === testedSymbol) {
33826+
if (childSymbol && childSymbol === testedFunctionSymbol) {
3383933827
// If the test was a simple identifier, the above check is sufficient
33840-
if (isIdentifier(expr)) {
33828+
if (isIdentifier(condExpr)) {
3384133829
return true;
3384233830
}
3384333831
// Otherwise we need to ensure the symbol is called on the same target
3384433832
let testedExpression = testedNode.parent;
3384533833
let childExpression = childNode.parent;
3384633834
while (testedExpression && childExpression) {
33835+
3384733836
if (isIdentifier(testedExpression) && isIdentifier(childExpression) ||
33848-
testedExpression.kind === SyntaxKind.ThisKeyword && childExpression.kind === SyntaxKind.ThisKeyword) {
33837+
testedExpression.kind === SyntaxKind.ThisKeyword && childExpression.kind === SyntaxKind.ThisKeyword
33838+
) {
3384933839
return getSymbolAtLocation(testedExpression) === getSymbolAtLocation(childExpression);
3385033840
}
3385133841

@@ -33862,18 +33852,13 @@ namespace ts {
3386233852
}
3386333853
}
3386433854
}
33855+
3386533856
return forEachChild(childNode, check);
3386633857
});
33867-
}
3386833858

33869-
function isFunctionUsedInBinaryExpressionChain(node: Node, testedSymbol: Symbol): boolean {
33870-
while (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
33871-
if (isCallExpression(node.right) && testedSymbol === getSymbolAtLocation(node.right.expression)) {
33872-
return true;
33873-
}
33874-
node = node.parent;
33859+
if (!functionIsUsedInBody) {
33860+
error(condExpr, Diagnostics.This_condition_will_always_return_true_since_the_function_is_always_defined_Did_you_mean_to_call_it_instead);
3387533861
}
33876-
return false;
3387733862
}
3387833863

3387933864
function checkDoStatement(node: DoStatement) {

src/compiler/emitter.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2811,7 +2811,7 @@ namespace ts {
28112811
if (isSimilarNode && currentSourceFile) {
28122812
pos = skipTrivia(currentSourceFile.text, pos);
28132813
}
2814-
if (isSimilarNode && contextNode.pos !== startPos) {
2814+
if (emitLeadingCommentsOfPosition && isSimilarNode && contextNode.pos !== startPos) {
28152815
const needsIndent = indentLeading && currentSourceFile && !positionsAreOnSameLine(startPos, pos, currentSourceFile);
28162816
if (needsIndent) {
28172817
increaseIndent();
@@ -2822,7 +2822,7 @@ namespace ts {
28222822
}
28232823
}
28242824
pos = writeTokenText(token, writer, pos);
2825-
if (isSimilarNode && contextNode.end !== pos) {
2825+
if (emitTrailingCommentsOfPosition && isSimilarNode && contextNode.end !== pos) {
28262826
emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true);
28272827
}
28282828
return pos;
@@ -3468,7 +3468,7 @@ namespace ts {
34683468
// "comment1" is not considered to be leading comment for node.initializer
34693469
// but rather a trailing comment on the previous node.
34703470
const initializer = node.initializer;
3471-
if ((getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) {
3471+
if (emitTrailingCommentsOfPosition && (getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) {
34723472
const commentRange = getCommentRange(initializer);
34733473
emitTrailingCommentsOfPosition(commentRange.pos);
34743474
}

tests/baselines/reference/truthinessCallExpressionCoercion2.errors.txt

Lines changed: 0 additions & 108 deletions
This file was deleted.

0 commit comments

Comments
 (0)