Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Appearance settings

Commit cf3e28e

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

15 files changed

+24-1,069Lines changed: 24 additions & 1069 deletions
Expand file treeCollapse file tree
Open diff view settings
Collapse file

‎src/compiler/binder.ts‎

Copy file name to clipboardExpand all lines: src/compiler/binder.ts
+2-2Lines 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
}
Collapse file

‎src/compiler/checker.ts‎

Copy file name to clipboardExpand all lines: src/compiler/checker.ts
+19-34Lines 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) {
Collapse file

‎src/compiler/emitter.ts‎

Copy file name to clipboardExpand all lines: src/compiler/emitter.ts
+3-3Lines 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
}
Collapse file

‎tests/baselines/reference/truthinessCallExpressionCoercion2.errors.txt‎

Copy file name to clipboardExpand all lines: tests/baselines/reference/truthinessCallExpressionCoercion2.errors.txt
-108Lines changed: 0 additions & 108 deletions
This file was deleted.

0 commit comments

Comments
0 (0)
Morty Proxy This is a proxified and sanitized view of the page, visit original site.