More fixes to uncalled function checks in && expressions (#49868)

This commit is contained in:
Andrew Branch
2022-07-22 16:06:16 -07:00
committed by GitHub
parent 4e23f515e0
commit 6aefc1dcea
6 changed files with 534 additions and 1 deletions

View File

@@ -33955,7 +33955,11 @@ namespace ts {
const operator = operatorToken.kind;
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
if (operator === SyntaxKind.AmpersandAmpersandToken) {
const parent = walkUpParenthesizedExpressions(node.parent);
let parent = node.parent;
while (parent.kind === SyntaxKind.ParenthesizedExpression
|| isBinaryExpression(parent) && (parent.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken || parent.operatorToken.kind === SyntaxKind.BarBarToken)) {
parent = parent.parent;
}
checkTestingKnownTruthyCallableOrAwaitableType(node.left, isIfStatement(parent) ? parent.thenStatement : undefined);
}
checkTruthinessOfType(leftType, node.left);

View File

@@ -0,0 +1,58 @@
tests/cases/compiler/uncalledFunctionChecksInConditional2.ts(20,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
tests/cases/compiler/uncalledFunctionChecksInConditional2.ts(38,5): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
==== tests/cases/compiler/uncalledFunctionChecksInConditional2.ts (2 errors) ====
{
const perf = window.performance
// Simplified
if (
perf &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures
) {
perf.measure("");
perf.clearMarks("")
perf.clearMeasures("")
}
// With ||
if (
perf &&
perf.mark &&
perf.measure || !!true
~~~~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
) {
perf.mark("");
}
};
// Original #49192
declare let inBrowser: boolean;
{
let mark;
let measure;
const perf = inBrowser && window.performance
/* istanbul ignore if */
if (
perf &&
perf.mark &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures
~~~~~~~~~~~~~~~~~~
!!! error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead?
) {
mark = (tag) => perf.mark(tag)
measure = (name, startTag, endTag) => {
perf.measure(name, startTag, endTag)
perf.clearMarks(startTag)
perf.clearMarks(endTag)
// perf.clearMeasures(name)
}
}
};

View File

@@ -0,0 +1,91 @@
//// [uncalledFunctionChecksInConditional2.ts]
{
const perf = window.performance
// Simplified
if (
perf &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures
) {
perf.measure("");
perf.clearMarks("")
perf.clearMeasures("")
}
// With ||
if (
perf &&
perf.mark &&
perf.measure || !!true
) {
perf.mark("");
}
};
// Original #49192
declare let inBrowser: boolean;
{
let mark;
let measure;
const perf = inBrowser && window.performance
/* istanbul ignore if */
if (
perf &&
perf.mark &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures
) {
mark = (tag) => perf.mark(tag)
measure = (name, startTag, endTag) => {
perf.measure(name, startTag, endTag)
perf.clearMarks(startTag)
perf.clearMarks(endTag)
// perf.clearMeasures(name)
}
}
};
//// [uncalledFunctionChecksInConditional2.js]
{
var perf = window.performance;
// Simplified
if (perf &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures) {
perf.measure("");
perf.clearMarks("");
perf.clearMeasures("");
}
// With ||
if (perf &&
perf.mark &&
perf.measure || !!true) {
perf.mark("");
}
}
;
{
var mark = void 0;
var measure = void 0;
var perf_1 = inBrowser && window.performance;
/* istanbul ignore if */
if (perf_1 &&
perf_1.mark &&
perf_1.measure &&
perf_1.clearMarks &&
perf_1.clearMeasures) {
mark = function (tag) { return perf_1.mark(tag); };
measure = function (name, startTag, endTag) {
perf_1.measure(name, startTag, endTag);
perf_1.clearMarks(startTag);
perf_1.clearMarks(endTag);
// perf.clearMeasures(name)
};
}
}
;

View File

@@ -0,0 +1,150 @@
=== tests/cases/compiler/uncalledFunctionChecksInConditional2.ts ===
{
const perf = window.performance
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>window.performance : Symbol(performance, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>performance : Symbol(performance, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
// Simplified
if (
perf &&
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
perf.measure &&
>perf.measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
perf.clearMarks &&
>perf.clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
perf.clearMeasures
>perf.clearMeasures : Symbol(Performance.clearMeasures, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>clearMeasures : Symbol(Performance.clearMeasures, Decl(lib.dom.d.ts, --, --))
) {
perf.measure("");
>perf.measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
perf.clearMarks("")
>perf.clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
perf.clearMeasures("")
>perf.clearMeasures : Symbol(Performance.clearMeasures, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>clearMeasures : Symbol(Performance.clearMeasures, Decl(lib.dom.d.ts, --, --))
}
// With ||
if (
perf &&
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
perf.mark &&
>perf.mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
perf.measure || !!true
>perf.measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
) {
perf.mark("");
>perf.mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 1, 7))
>mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
}
};
// Original #49192
declare let inBrowser: boolean;
>inBrowser : Symbol(inBrowser, Decl(uncalledFunctionChecksInConditional2.ts, 26, 11))
{
let mark;
>mark : Symbol(mark, Decl(uncalledFunctionChecksInConditional2.ts, 28, 5))
let measure;
>measure : Symbol(measure, Decl(uncalledFunctionChecksInConditional2.ts, 29, 5))
const perf = inBrowser && window.performance
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>inBrowser : Symbol(inBrowser, Decl(uncalledFunctionChecksInConditional2.ts, 26, 11))
>window.performance : Symbol(performance, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
>performance : Symbol(performance, Decl(lib.dom.d.ts, --, --), Decl(lib.dom.d.ts, --, --))
/* istanbul ignore if */
if (
perf &&
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
perf.mark &&
>perf.mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
perf.measure &&
>perf.measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
perf.clearMarks &&
>perf.clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
perf.clearMeasures
>perf.clearMeasures : Symbol(Performance.clearMeasures, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>clearMeasures : Symbol(Performance.clearMeasures, Decl(lib.dom.d.ts, --, --))
) {
mark = (tag) => perf.mark(tag)
>mark : Symbol(mark, Decl(uncalledFunctionChecksInConditional2.ts, 28, 5))
>tag : Symbol(tag, Decl(uncalledFunctionChecksInConditional2.ts, 39, 12))
>perf.mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>mark : Symbol(Performance.mark, Decl(lib.dom.d.ts, --, --))
>tag : Symbol(tag, Decl(uncalledFunctionChecksInConditional2.ts, 39, 12))
measure = (name, startTag, endTag) => {
>measure : Symbol(measure, Decl(uncalledFunctionChecksInConditional2.ts, 29, 5))
>name : Symbol(name, Decl(uncalledFunctionChecksInConditional2.ts, 40, 15))
>startTag : Symbol(startTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 20))
>endTag : Symbol(endTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 30))
perf.measure(name, startTag, endTag)
>perf.measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>measure : Symbol(Performance.measure, Decl(lib.dom.d.ts, --, --))
>name : Symbol(name, Decl(uncalledFunctionChecksInConditional2.ts, 40, 15))
>startTag : Symbol(startTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 20))
>endTag : Symbol(endTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 30))
perf.clearMarks(startTag)
>perf.clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>startTag : Symbol(startTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 20))
perf.clearMarks(endTag)
>perf.clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>perf : Symbol(perf, Decl(uncalledFunctionChecksInConditional2.ts, 30, 7))
>clearMarks : Symbol(Performance.clearMarks, Decl(lib.dom.d.ts, --, --))
>endTag : Symbol(endTag, Decl(uncalledFunctionChecksInConditional2.ts, 40, 30))
// perf.clearMeasures(name)
}
}
};

View File

@@ -0,0 +1,180 @@
=== tests/cases/compiler/uncalledFunctionChecksInConditional2.ts ===
{
const perf = window.performance
>perf : Performance
>window.performance : Performance
>window : Window & typeof globalThis
>performance : Performance
// Simplified
if (
perf &&
>perf && perf.measure && perf.clearMarks && perf.clearMeasures : (measureName?: string | undefined) => void
>perf && perf.measure && perf.clearMarks : (markName?: string | undefined) => void
>perf && perf.measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf : Performance
perf.measure &&
>perf.measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf : Performance
>measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
perf.clearMarks &&
>perf.clearMarks : (markName?: string | undefined) => void
>perf : Performance
>clearMarks : (markName?: string | undefined) => void
perf.clearMeasures
>perf.clearMeasures : (measureName?: string | undefined) => void
>perf : Performance
>clearMeasures : (measureName?: string | undefined) => void
) {
perf.measure("");
>perf.measure("") : PerformanceMeasure
>perf.measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf : Performance
>measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>"" : ""
perf.clearMarks("")
>perf.clearMarks("") : void
>perf.clearMarks : (markName?: string | undefined) => void
>perf : Performance
>clearMarks : (markName?: string | undefined) => void
>"" : ""
perf.clearMeasures("")
>perf.clearMeasures("") : void
>perf.clearMeasures : (measureName?: string | undefined) => void
>perf : Performance
>clearMeasures : (measureName?: string | undefined) => void
>"" : ""
}
// With ||
if (
perf &&
>perf && perf.mark && perf.measure || !!true : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf && perf.mark && perf.measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf && perf.mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>perf : Performance
perf.mark &&
>perf.mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>perf : Performance
>mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
perf.measure || !!true
>perf.measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf : Performance
>measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>!!true : true
>!true : false
>true : true
) {
perf.mark("");
>perf.mark("") : PerformanceMark
>perf.mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>perf : Performance
>mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>"" : ""
}
};
// Original #49192
declare let inBrowser: boolean;
>inBrowser : boolean
{
let mark;
>mark : any
let measure;
>measure : any
const perf = inBrowser && window.performance
>perf : false | Performance
>inBrowser && window.performance : false | Performance
>inBrowser : boolean
>window.performance : Performance
>window : Window & typeof globalThis
>performance : Performance
/* istanbul ignore if */
if (
perf &&
>perf && perf.mark && perf.measure && perf.clearMarks && perf.clearMeasures : false | ((measureName?: string | undefined) => void)
>perf && perf.mark && perf.measure && perf.clearMarks : false | ((markName?: string | undefined) => void)
>perf && perf.mark && perf.measure : false | ((measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure)
>perf && perf.mark : false | ((markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark)
>perf : false | Performance
perf.mark &&
>perf.mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>perf : Performance
>mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
perf.measure &&
>perf.measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf : Performance
>measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
perf.clearMarks &&
>perf.clearMarks : (markName?: string | undefined) => void
>perf : Performance
>clearMarks : (markName?: string | undefined) => void
perf.clearMeasures
>perf.clearMeasures : (measureName?: string | undefined) => void
>perf : Performance
>clearMeasures : (measureName?: string | undefined) => void
) {
mark = (tag) => perf.mark(tag)
>mark = (tag) => perf.mark(tag) : (tag: any) => PerformanceMark
>mark : any
>(tag) => perf.mark(tag) : (tag: any) => PerformanceMark
>tag : any
>perf.mark(tag) : PerformanceMark
>perf.mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>perf : Performance
>mark : (markName: string, markOptions?: PerformanceMarkOptions | undefined) => PerformanceMark
>tag : any
measure = (name, startTag, endTag) => {
>measure = (name, startTag, endTag) => { perf.measure(name, startTag, endTag) perf.clearMarks(startTag) perf.clearMarks(endTag) // perf.clearMeasures(name) } : (name: any, startTag: any, endTag: any) => void
>measure : any
>(name, startTag, endTag) => { perf.measure(name, startTag, endTag) perf.clearMarks(startTag) perf.clearMarks(endTag) // perf.clearMeasures(name) } : (name: any, startTag: any, endTag: any) => void
>name : any
>startTag : any
>endTag : any
perf.measure(name, startTag, endTag)
>perf.measure(name, startTag, endTag) : PerformanceMeasure
>perf.measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>perf : Performance
>measure : (measureName: string, startOrMeasureOptions?: string | PerformanceMeasureOptions | undefined, endMark?: string | undefined) => PerformanceMeasure
>name : any
>startTag : any
>endTag : any
perf.clearMarks(startTag)
>perf.clearMarks(startTag) : void
>perf.clearMarks : (markName?: string | undefined) => void
>perf : Performance
>clearMarks : (markName?: string | undefined) => void
>startTag : any
perf.clearMarks(endTag)
>perf.clearMarks(endTag) : void
>perf.clearMarks : (markName?: string | undefined) => void
>perf : Performance
>clearMarks : (markName?: string | undefined) => void
>endTag : any
// perf.clearMeasures(name)
}
}
};

View File

@@ -0,0 +1,50 @@
// @lib: esnext,dom
// @strictNullChecks: true
{
const perf = window.performance
// Simplified
if (
perf &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures
) {
perf.measure("");
perf.clearMarks("")
perf.clearMeasures("")
}
// With ||
if (
perf &&
perf.mark &&
perf.measure || !!true
) {
perf.mark("");
}
};
// Original #49192
declare let inBrowser: boolean;
{
let mark;
let measure;
const perf = inBrowser && window.performance
/* istanbul ignore if */
if (
perf &&
perf.mark &&
perf.measure &&
perf.clearMarks &&
perf.clearMeasures
) {
mark = (tag) => perf.mark(tag)
measure = (name, startTag, endTag) => {
perf.measure(name, startTag, endTag)
perf.clearMarks(startTag)
perf.clearMarks(endTag)
// perf.clearMeasures(name)
}
}
};