Revert "Revert "feat(40197): handle uncalled function checks in binary expressions (#40260)"" (#41462)
This reverts commit cf3e28ea66
.
This commit is contained in:
parent
06a2210eb5
commit
64be2a8d16
|
@ -670,7 +670,7 @@ namespace ts {
|
|||
}
|
||||
// We create a return control flow graph for IIFEs and constructors. For constructors
|
||||
// we use the return control flow graph in strict property initialization checks.
|
||||
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor || (isInJSFile && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined;
|
||||
currentReturnTarget = isIIFE || node.kind === SyntaxKind.Constructor || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression)) ? createBranchLabel() : undefined;
|
||||
currentExceptionTarget = undefined;
|
||||
currentBreakTarget = undefined;
|
||||
currentContinueTarget = undefined;
|
||||
|
@ -691,7 +691,7 @@ namespace ts {
|
|||
if (currentReturnTarget) {
|
||||
addAntecedent(currentReturnTarget, currentFlow);
|
||||
currentFlow = finishFlowLabel(currentReturnTarget);
|
||||
if (node.kind === SyntaxKind.Constructor || (isInJSFile && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) {
|
||||
if (node.kind === SyntaxKind.Constructor || (isInJSFile(node) && (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.FunctionExpression))) {
|
||||
(<FunctionLikeDeclaration>node).returnFlowNode = currentFlow;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -30156,6 +30156,9 @@ namespace ts {
|
|||
workStacks.leftType[stackIndex] = leftType;
|
||||
const operator = node.operatorToken.kind;
|
||||
if (operator === SyntaxKind.AmpersandAmpersandToken || operator === SyntaxKind.BarBarToken || operator === SyntaxKind.QuestionQuestionToken) {
|
||||
if (operator === SyntaxKind.AmpersandAmpersandToken) {
|
||||
checkTestingKnownTruthyCallableType(node.left, leftType);
|
||||
}
|
||||
checkTruthinessOfType(leftType, node.left);
|
||||
}
|
||||
advanceState(CheckBinaryExpressionState.FinishCheck);
|
||||
|
@ -30689,7 +30692,7 @@ namespace ts {
|
|||
|
||||
function checkConditionalExpression(node: ConditionalExpression, checkMode?: CheckMode): Type {
|
||||
const type = checkTruthinessExpression(node.condition);
|
||||
checkTestingKnownTruthyCallableType(node.condition, node.whenTrue, type);
|
||||
checkTestingKnownTruthyCallableType(node.condition, type, node.whenTrue);
|
||||
const type1 = checkExpression(node.whenTrue, checkMode);
|
||||
const type2 = checkExpression(node.whenFalse, checkMode);
|
||||
return getUnionType([type1, type2], UnionReduction.Subtype);
|
||||
|
@ -33926,7 +33929,7 @@ namespace ts {
|
|||
// Grammar checking
|
||||
checkGrammarStatementInAmbientContext(node);
|
||||
const type = checkTruthinessExpression(node.expression);
|
||||
checkTestingKnownTruthyCallableType(node.expression, node.thenStatement, type);
|
||||
checkTestingKnownTruthyCallableType(node.expression, type, node.thenStatement);
|
||||
checkSourceElement(node.thenStatement);
|
||||
|
||||
if (node.thenStatement.kind === SyntaxKind.EmptyStatement) {
|
||||
|
@ -33936,16 +33939,16 @@ namespace ts {
|
|||
checkSourceElement(node.elseStatement);
|
||||
}
|
||||
|
||||
function checkTestingKnownTruthyCallableType(condExpr: Expression, body: Statement | Expression, type: Type) {
|
||||
function checkTestingKnownTruthyCallableType(condExpr: Expression, type: Type, body?: Statement | Expression) {
|
||||
if (!strictNullChecks) {
|
||||
return;
|
||||
}
|
||||
|
||||
const testedNode = isIdentifier(condExpr)
|
||||
? condExpr
|
||||
: isPropertyAccessExpression(condExpr)
|
||||
? condExpr.name
|
||||
: undefined;
|
||||
const location = isBinaryExpression(condExpr) ? condExpr.right : condExpr;
|
||||
const testedNode = isIdentifier(location) ? location
|
||||
: isPropertyAccessExpression(location) ? location.name
|
||||
: isBinaryExpression(location) && isIdentifier(location.right) ? location.right
|
||||
: undefined;
|
||||
|
||||
if (!testedNode) {
|
||||
return;
|
||||
|
@ -33966,27 +33969,34 @@ namespace ts {
|
|||
return;
|
||||
}
|
||||
|
||||
const testedFunctionSymbol = getSymbolAtLocation(testedNode);
|
||||
if (!testedFunctionSymbol) {
|
||||
const testedSymbol = getSymbolAtLocation(testedNode);
|
||||
if (!testedSymbol) {
|
||||
return;
|
||||
}
|
||||
|
||||
const functionIsUsedInBody = forEachChild(body, function check(childNode): boolean | undefined {
|
||||
const isUsed = isBinaryExpression(condExpr.parent) ? isFunctionUsedInBinaryExpressionChain(condExpr.parent, testedSymbol)
|
||||
: body ? isFunctionUsedInConditionBody(condExpr, body, testedNode, testedSymbol)
|
||||
: false;
|
||||
if (!isUsed) {
|
||||
error(location, Diagnostics.This_condition_will_always_return_true_since_the_function_is_always_defined_Did_you_mean_to_call_it_instead);
|
||||
}
|
||||
}
|
||||
|
||||
function isFunctionUsedInConditionBody(expr: Expression, body: Statement | Expression, testedNode: Node, testedSymbol: Symbol): boolean {
|
||||
return !!forEachChild(body, function check(childNode): boolean | undefined {
|
||||
if (isIdentifier(childNode)) {
|
||||
const childSymbol = getSymbolAtLocation(childNode);
|
||||
if (childSymbol && childSymbol === testedFunctionSymbol) {
|
||||
if (childSymbol && childSymbol === testedSymbol) {
|
||||
// If the test was a simple identifier, the above check is sufficient
|
||||
if (isIdentifier(condExpr)) {
|
||||
if (isIdentifier(expr)) {
|
||||
return true;
|
||||
}
|
||||
// Otherwise we need to ensure the symbol is called on the same target
|
||||
let testedExpression = testedNode.parent;
|
||||
let childExpression = childNode.parent;
|
||||
while (testedExpression && childExpression) {
|
||||
|
||||
if (isIdentifier(testedExpression) && isIdentifier(childExpression) ||
|
||||
testedExpression.kind === SyntaxKind.ThisKeyword && childExpression.kind === SyntaxKind.ThisKeyword
|
||||
) {
|
||||
testedExpression.kind === SyntaxKind.ThisKeyword && childExpression.kind === SyntaxKind.ThisKeyword) {
|
||||
return getSymbolAtLocation(testedExpression) === getSymbolAtLocation(childExpression);
|
||||
}
|
||||
|
||||
|
@ -34003,13 +34013,18 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
return forEachChild(childNode, check);
|
||||
});
|
||||
}
|
||||
|
||||
if (!functionIsUsedInBody) {
|
||||
error(condExpr, Diagnostics.This_condition_will_always_return_true_since_the_function_is_always_defined_Did_you_mean_to_call_it_instead);
|
||||
function isFunctionUsedInBinaryExpressionChain(node: Node, testedSymbol: Symbol): boolean {
|
||||
while (isBinaryExpression(node) && node.operatorToken.kind === SyntaxKind.AmpersandAmpersandToken) {
|
||||
if (isCallExpression(node.right) && testedSymbol === getSymbolAtLocation(node.right.expression)) {
|
||||
return true;
|
||||
}
|
||||
node = node.parent;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function checkDoStatement(node: DoStatement) {
|
||||
|
|
|
@ -2812,7 +2812,7 @@ namespace ts {
|
|||
if (isSimilarNode && currentSourceFile) {
|
||||
pos = skipTrivia(currentSourceFile.text, pos);
|
||||
}
|
||||
if (emitLeadingCommentsOfPosition && isSimilarNode && contextNode.pos !== startPos) {
|
||||
if (isSimilarNode && contextNode.pos !== startPos) {
|
||||
const needsIndent = indentLeading && currentSourceFile && !positionsAreOnSameLine(startPos, pos, currentSourceFile);
|
||||
if (needsIndent) {
|
||||
increaseIndent();
|
||||
|
@ -2823,7 +2823,7 @@ namespace ts {
|
|||
}
|
||||
}
|
||||
pos = writeTokenText(token, writer, pos);
|
||||
if (emitTrailingCommentsOfPosition && isSimilarNode && contextNode.end !== pos) {
|
||||
if (isSimilarNode && contextNode.end !== pos) {
|
||||
emitTrailingCommentsOfPosition(pos, /*prefixSpace*/ true);
|
||||
}
|
||||
return pos;
|
||||
|
@ -3469,7 +3469,7 @@ namespace ts {
|
|||
// "comment1" is not considered to be leading comment for node.initializer
|
||||
// but rather a trailing comment on the previous node.
|
||||
const initializer = node.initializer;
|
||||
if (emitTrailingCommentsOfPosition && (getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) {
|
||||
if ((getEmitFlags(initializer) & EmitFlags.NoLeadingComments) === 0) {
|
||||
const commentRange = getCommentRange(initializer);
|
||||
emitTrailingCommentsOfPosition(commentRange.pos);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,108 @@
|
|||
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(3,5): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(6,10): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(30,18): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(36,46): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(47,5): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(50,10): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(66,9): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
tests/cases/compiler/truthinessCallExpressionCoercion2.ts(69,14): error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
|
||||
|
||||
==== tests/cases/compiler/truthinessCallExpressionCoercion2.ts (8 errors) ====
|
||||
function test(required1: () => boolean, required2: () => boolean, optional?: () => boolean) {
|
||||
// error
|
||||
required1 && console.log('required');
|
||||
~~~~~~~~~
|
||||
!!! error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
|
||||
// error
|
||||
1 && required1 && console.log('required');
|
||||
~~~~~~~~~
|
||||
!!! error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
|
||||
// ok
|
||||
required1 && required1();
|
||||
|
||||
// ok
|
||||
required1 && 1 && required1();
|
||||
|
||||
// ok
|
||||
optional && console.log('optional');
|
||||
|
||||
// ok
|
||||
1 && optional && console.log('optional');
|
||||
|
||||
// ok
|
||||
!!required1 && console.log('not required');
|
||||
|
||||
// ok
|
||||
required1() && console.log('required call');
|
||||
|
||||
// ok
|
||||
required1 && required2 && required1() && required2();
|
||||
|
||||
// error
|
||||
required1 && required2 && required1() && console.log('foo');
|
||||
~~~~~~~~~
|
||||
!!! error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
}
|
||||
|
||||
function checksConsole() {
|
||||
// error
|
||||
typeof window !== 'undefined' && window.console &&
|
||||
((window.console as any).firebug || (window.console.exception && window.console.table));
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
!!! error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
}
|
||||
|
||||
function checksPropertyAccess() {
|
||||
const x = {
|
||||
foo: {
|
||||
bar() { return true; }
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
x.foo.bar && console.log('x.foo.bar');
|
||||
~~~~~~~~~
|
||||
!!! error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
|
||||
// error
|
||||
1 && x.foo.bar && console.log('x.foo.bar');
|
||||
~~~~~~~~~
|
||||
!!! error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
|
||||
// ok
|
||||
x.foo.bar && x.foo.bar();
|
||||
|
||||
// ok
|
||||
x.foo.bar && 1 && x.foo.bar();
|
||||
}
|
||||
|
||||
class Foo {
|
||||
optional?: () => boolean;
|
||||
required() {
|
||||
return true;
|
||||
}
|
||||
test() {
|
||||
// error
|
||||
this.required && console.log('required');
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
|
||||
// error
|
||||
1 && this.required && console.log('required');
|
||||
~~~~~~~~~~~~~
|
||||
!!! error TS2774: This condition will always return true since the function is always defined. Did you mean to call it instead?
|
||||
|
||||
// ok
|
||||
this.required && this.required();
|
||||
|
||||
// ok
|
||||
this.required && 1 && this.required();
|
||||
|
||||
// ok
|
||||
1 && this.optional && console.log('optional');
|
||||
}
|
||||
}
|
||||
|
146
tests/baselines/reference/truthinessCallExpressionCoercion2.js
Normal file
146
tests/baselines/reference/truthinessCallExpressionCoercion2.js
Normal file
|
@ -0,0 +1,146 @@
|
|||
//// [truthinessCallExpressionCoercion2.ts]
|
||||
function test(required1: () => boolean, required2: () => boolean, optional?: () => boolean) {
|
||||
// error
|
||||
required1 && console.log('required');
|
||||
|
||||
// error
|
||||
1 && required1 && console.log('required');
|
||||
|
||||
// ok
|
||||
required1 && required1();
|
||||
|
||||
// ok
|
||||
required1 && 1 && required1();
|
||||
|
||||
// ok
|
||||
optional && console.log('optional');
|
||||
|
||||
// ok
|
||||
1 && optional && console.log('optional');
|
||||
|
||||
// ok
|
||||
!!required1 && console.log('not required');
|
||||
|
||||
// ok
|
||||
required1() && console.log('required call');
|
||||
|
||||
// ok
|
||||
required1 && required2 && required1() && required2();
|
||||
|
||||
// error
|
||||
required1 && required2 && required1() && console.log('foo');
|
||||
}
|
||||
|
||||
function checksConsole() {
|
||||
// error
|
||||
typeof window !== 'undefined' && window.console &&
|
||||
((window.console as any).firebug || (window.console.exception && window.console.table));
|
||||
}
|
||||
|
||||
function checksPropertyAccess() {
|
||||
const x = {
|
||||
foo: {
|
||||
bar() { return true; }
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
x.foo.bar && console.log('x.foo.bar');
|
||||
|
||||
// error
|
||||
1 && x.foo.bar && console.log('x.foo.bar');
|
||||
|
||||
// ok
|
||||
x.foo.bar && x.foo.bar();
|
||||
|
||||
// ok
|
||||
x.foo.bar && 1 && x.foo.bar();
|
||||
}
|
||||
|
||||
class Foo {
|
||||
optional?: () => boolean;
|
||||
required() {
|
||||
return true;
|
||||
}
|
||||
test() {
|
||||
// error
|
||||
this.required && console.log('required');
|
||||
|
||||
// error
|
||||
1 && this.required && console.log('required');
|
||||
|
||||
// ok
|
||||
this.required && this.required();
|
||||
|
||||
// ok
|
||||
this.required && 1 && this.required();
|
||||
|
||||
// ok
|
||||
1 && this.optional && console.log('optional');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//// [truthinessCallExpressionCoercion2.js]
|
||||
function test(required1, required2, optional) {
|
||||
// error
|
||||
required1 && console.log('required');
|
||||
// error
|
||||
1 && required1 && console.log('required');
|
||||
// ok
|
||||
required1 && required1();
|
||||
// ok
|
||||
required1 && 1 && required1();
|
||||
// ok
|
||||
optional && console.log('optional');
|
||||
// ok
|
||||
1 && optional && console.log('optional');
|
||||
// ok
|
||||
!!required1 && console.log('not required');
|
||||
// ok
|
||||
required1() && console.log('required call');
|
||||
// ok
|
||||
required1 && required2 && required1() && required2();
|
||||
// error
|
||||
required1 && required2 && required1() && console.log('foo');
|
||||
}
|
||||
function checksConsole() {
|
||||
// error
|
||||
typeof window !== 'undefined' && window.console &&
|
||||
(window.console.firebug || (window.console.exception && window.console.table));
|
||||
}
|
||||
function checksPropertyAccess() {
|
||||
var x = {
|
||||
foo: {
|
||||
bar: function () { return true; }
|
||||
}
|
||||
};
|
||||
// error
|
||||
x.foo.bar && console.log('x.foo.bar');
|
||||
// error
|
||||
1 && x.foo.bar && console.log('x.foo.bar');
|
||||
// ok
|
||||
x.foo.bar && x.foo.bar();
|
||||
// ok
|
||||
x.foo.bar && 1 && x.foo.bar();
|
||||
}
|
||||
var Foo = /** @class */ (function () {
|
||||
function Foo() {
|
||||
}
|
||||
Foo.prototype.required = function () {
|
||||
return true;
|
||||
};
|
||||
Foo.prototype.test = function () {
|
||||
// error
|
||||
this.required && console.log('required');
|
||||
// error
|
||||
1 && this.required && console.log('required');
|
||||
// ok
|
||||
this.required && this.required();
|
||||
// ok
|
||||
this.required && 1 && this.required();
|
||||
// ok
|
||||
1 && this.optional && console.log('optional');
|
||||
};
|
||||
return Foo;
|
||||
}());
|
|
@ -0,0 +1,226 @@
|
|||
=== tests/cases/compiler/truthinessCallExpressionCoercion2.ts ===
|
||||
function test(required1: () => boolean, required2: () => boolean, optional?: () => boolean) {
|
||||
>test : Symbol(test, Decl(truthinessCallExpressionCoercion2.ts, 0, 0))
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 0, 39))
|
||||
>optional : Symbol(optional, Decl(truthinessCallExpressionCoercion2.ts, 0, 65))
|
||||
|
||||
// error
|
||||
required1 && console.log('required');
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// error
|
||||
1 && required1 && console.log('required');
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// ok
|
||||
required1 && required1();
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
|
||||
// ok
|
||||
required1 && 1 && required1();
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
|
||||
// ok
|
||||
optional && console.log('optional');
|
||||
>optional : Symbol(optional, Decl(truthinessCallExpressionCoercion2.ts, 0, 65))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// ok
|
||||
1 && optional && console.log('optional');
|
||||
>optional : Symbol(optional, Decl(truthinessCallExpressionCoercion2.ts, 0, 65))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// ok
|
||||
!!required1 && console.log('not required');
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// ok
|
||||
required1() && console.log('required call');
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// ok
|
||||
required1 && required2 && required1() && required2();
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 0, 39))
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 0, 39))
|
||||
|
||||
// error
|
||||
required1 && required2 && required1() && console.log('foo');
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>required2 : Symbol(required2, Decl(truthinessCallExpressionCoercion2.ts, 0, 39))
|
||||
>required1 : Symbol(required1, Decl(truthinessCallExpressionCoercion2.ts, 0, 14))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
}
|
||||
|
||||
function checksConsole() {
|
||||
>checksConsole : Symbol(checksConsole, Decl(truthinessCallExpressionCoercion2.ts, 30, 1))
|
||||
|
||||
// error
|
||||
typeof window !== 'undefined' && window.console &&
|
||||
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
|
||||
>window.console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
((window.console as any).firebug || (window.console.exception && window.console.table));
|
||||
>window.console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>window.console.exception : Symbol(Console.exception, Decl(lib.dom.d.ts, --, --))
|
||||
>window.console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>exception : Symbol(Console.exception, Decl(lib.dom.d.ts, --, --))
|
||||
>window.console.table : Symbol(Console.table, Decl(lib.dom.d.ts, --, --))
|
||||
>window.console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>window : Symbol(window, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>table : Symbol(Console.table, Decl(lib.dom.d.ts, --, --))
|
||||
}
|
||||
|
||||
function checksPropertyAccess() {
|
||||
>checksPropertyAccess : Symbol(checksPropertyAccess, Decl(truthinessCallExpressionCoercion2.ts, 36, 1))
|
||||
|
||||
const x = {
|
||||
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 39, 9))
|
||||
|
||||
foo: {
|
||||
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
|
||||
bar() { return true; }
|
||||
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
x.foo.bar && console.log('x.foo.bar');
|
||||
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 39, 9))
|
||||
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// error
|
||||
1 && x.foo.bar && console.log('x.foo.bar');
|
||||
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 39, 9))
|
||||
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// ok
|
||||
x.foo.bar && x.foo.bar();
|
||||
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 39, 9))
|
||||
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 39, 9))
|
||||
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
|
||||
// ok
|
||||
x.foo.bar && 1 && x.foo.bar();
|
||||
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 39, 9))
|
||||
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>x.foo.bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
>x.foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>x : Symbol(x, Decl(truthinessCallExpressionCoercion2.ts, 39, 9))
|
||||
>foo : Symbol(foo, Decl(truthinessCallExpressionCoercion2.ts, 39, 15))
|
||||
>bar : Symbol(bar, Decl(truthinessCallExpressionCoercion2.ts, 40, 14))
|
||||
}
|
||||
|
||||
class Foo {
|
||||
>Foo : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 56, 1))
|
||||
|
||||
optional?: () => boolean;
|
||||
>optional : Symbol(Foo.optional, Decl(truthinessCallExpressionCoercion2.ts, 58, 11))
|
||||
|
||||
required() {
|
||||
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
|
||||
return true;
|
||||
}
|
||||
test() {
|
||||
>test : Symbol(Foo.test, Decl(truthinessCallExpressionCoercion2.ts, 62, 5))
|
||||
|
||||
// error
|
||||
this.required && console.log('required');
|
||||
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 56, 1))
|
||||
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// error
|
||||
1 && this.required && console.log('required');
|
||||
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 56, 1))
|
||||
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
|
||||
// ok
|
||||
this.required && this.required();
|
||||
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 56, 1))
|
||||
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 56, 1))
|
||||
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
|
||||
// ok
|
||||
this.required && 1 && this.required();
|
||||
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 56, 1))
|
||||
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>this.required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 56, 1))
|
||||
>required : Symbol(Foo.required, Decl(truthinessCallExpressionCoercion2.ts, 59, 29))
|
||||
|
||||
// ok
|
||||
1 && this.optional && console.log('optional');
|
||||
>this.optional : Symbol(Foo.optional, Decl(truthinessCallExpressionCoercion2.ts, 58, 11))
|
||||
>this : Symbol(Foo, Decl(truthinessCallExpressionCoercion2.ts, 56, 1))
|
||||
>optional : Symbol(Foo.optional, Decl(truthinessCallExpressionCoercion2.ts, 58, 11))
|
||||
>console.log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
>console : Symbol(console, Decl(lib.dom.d.ts, --, --))
|
||||
>log : Symbol(Console.log, Decl(lib.dom.d.ts, --, --))
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,318 @@
|
|||
=== tests/cases/compiler/truthinessCallExpressionCoercion2.ts ===
|
||||
function test(required1: () => boolean, required2: () => boolean, optional?: () => boolean) {
|
||||
>test : (required1: () => boolean, required2: () => boolean, optional?: (() => boolean) | undefined) => void
|
||||
>required1 : () => boolean
|
||||
>required2 : () => boolean
|
||||
>optional : (() => boolean) | undefined
|
||||
|
||||
// error
|
||||
required1 && console.log('required');
|
||||
>required1 && console.log('required') : void
|
||||
>required1 : () => boolean
|
||||
>console.log('required') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'required' : "required"
|
||||
|
||||
// error
|
||||
1 && required1 && console.log('required');
|
||||
>1 && required1 && console.log('required') : void
|
||||
>1 && required1 : () => boolean
|
||||
>1 : 1
|
||||
>required1 : () => boolean
|
||||
>console.log('required') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'required' : "required"
|
||||
|
||||
// ok
|
||||
required1 && required1();
|
||||
>required1 && required1() : boolean
|
||||
>required1 : () => boolean
|
||||
>required1() : boolean
|
||||
>required1 : () => boolean
|
||||
|
||||
// ok
|
||||
required1 && 1 && required1();
|
||||
>required1 && 1 && required1() : boolean
|
||||
>required1 && 1 : 1
|
||||
>required1 : () => boolean
|
||||
>1 : 1
|
||||
>required1() : boolean
|
||||
>required1 : () => boolean
|
||||
|
||||
// ok
|
||||
optional && console.log('optional');
|
||||
>optional && console.log('optional') : void | undefined
|
||||
>optional : (() => boolean) | undefined
|
||||
>console.log('optional') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'optional' : "optional"
|
||||
|
||||
// ok
|
||||
1 && optional && console.log('optional');
|
||||
>1 && optional && console.log('optional') : void | undefined
|
||||
>1 && optional : (() => boolean) | undefined
|
||||
>1 : 1
|
||||
>optional : (() => boolean) | undefined
|
||||
>console.log('optional') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'optional' : "optional"
|
||||
|
||||
// ok
|
||||
!!required1 && console.log('not required');
|
||||
>!!required1 && console.log('not required') : void
|
||||
>!!required1 : true
|
||||
>!required1 : false
|
||||
>required1 : () => boolean
|
||||
>console.log('not required') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'not required' : "not required"
|
||||
|
||||
// ok
|
||||
required1() && console.log('required call');
|
||||
>required1() && console.log('required call') : false | void
|
||||
>required1() : boolean
|
||||
>required1 : () => boolean
|
||||
>console.log('required call') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'required call' : "required call"
|
||||
|
||||
// ok
|
||||
required1 && required2 && required1() && required2();
|
||||
>required1 && required2 && required1() && required2() : boolean
|
||||
>required1 && required2 && required1() : boolean
|
||||
>required1 && required2 : () => boolean
|
||||
>required1 : () => boolean
|
||||
>required2 : () => boolean
|
||||
>required1() : boolean
|
||||
>required1 : () => boolean
|
||||
>required2() : boolean
|
||||
>required2 : () => boolean
|
||||
|
||||
// error
|
||||
required1 && required2 && required1() && console.log('foo');
|
||||
>required1 && required2 && required1() && console.log('foo') : false | void
|
||||
>required1 && required2 && required1() : boolean
|
||||
>required1 && required2 : () => boolean
|
||||
>required1 : () => boolean
|
||||
>required2 : () => boolean
|
||||
>required1() : boolean
|
||||
>required1 : () => boolean
|
||||
>console.log('foo') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'foo' : "foo"
|
||||
}
|
||||
|
||||
function checksConsole() {
|
||||
>checksConsole : () => void
|
||||
|
||||
// error
|
||||
typeof window !== 'undefined' && window.console &&
|
||||
>typeof window !== 'undefined' && window.console && ((window.console as any).firebug || (window.console.exception && window.console.table)) : any
|
||||
>typeof window !== 'undefined' && window.console : false | Console
|
||||
>typeof window !== 'undefined' : boolean
|
||||
>typeof window : "string" | "number" | "bigint" | "boolean" | "symbol" | "undefined" | "object" | "function"
|
||||
>window : Window & typeof globalThis
|
||||
>'undefined' : "undefined"
|
||||
>window.console : Console
|
||||
>window : Window & typeof globalThis
|
||||
>console : Console
|
||||
|
||||
((window.console as any).firebug || (window.console.exception && window.console.table));
|
||||
>((window.console as any).firebug || (window.console.exception && window.console.table)) : any
|
||||
>(window.console as any).firebug || (window.console.exception && window.console.table) : any
|
||||
>(window.console as any).firebug : any
|
||||
>(window.console as any) : any
|
||||
>window.console as any : any
|
||||
>window.console : Console
|
||||
>window : Window & typeof globalThis
|
||||
>console : Console
|
||||
>firebug : any
|
||||
>(window.console.exception && window.console.table) : (tabularData?: any, properties?: string[] | undefined) => void
|
||||
>window.console.exception && window.console.table : (tabularData?: any, properties?: string[] | undefined) => void
|
||||
>window.console.exception : (message?: string | undefined, ...optionalParams: any[]) => void
|
||||
>window.console : Console
|
||||
>window : Window & typeof globalThis
|
||||
>console : Console
|
||||
>exception : (message?: string | undefined, ...optionalParams: any[]) => void
|
||||
>window.console.table : (tabularData?: any, properties?: string[] | undefined) => void
|
||||
>window.console : Console
|
||||
>window : Window & typeof globalThis
|
||||
>console : Console
|
||||
>table : (tabularData?: any, properties?: string[] | undefined) => void
|
||||
}
|
||||
|
||||
function checksPropertyAccess() {
|
||||
>checksPropertyAccess : () => void
|
||||
|
||||
const x = {
|
||||
>x : { foo: { bar(): boolean; }; }
|
||||
>{ foo: { bar() { return true; } } } : { foo: { bar(): boolean; }; }
|
||||
|
||||
foo: {
|
||||
>foo : { bar(): boolean; }
|
||||
>{ bar() { return true; } } : { bar(): boolean; }
|
||||
|
||||
bar() { return true; }
|
||||
>bar : () => boolean
|
||||
>true : true
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
x.foo.bar && console.log('x.foo.bar');
|
||||
>x.foo.bar && console.log('x.foo.bar') : void
|
||||
>x.foo.bar : () => boolean
|
||||
>x.foo : { bar(): boolean; }
|
||||
>x : { foo: { bar(): boolean; }; }
|
||||
>foo : { bar(): boolean; }
|
||||
>bar : () => boolean
|
||||
>console.log('x.foo.bar') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'x.foo.bar' : "x.foo.bar"
|
||||
|
||||
// error
|
||||
1 && x.foo.bar && console.log('x.foo.bar');
|
||||
>1 && x.foo.bar && console.log('x.foo.bar') : void
|
||||
>1 && x.foo.bar : () => boolean
|
||||
>1 : 1
|
||||
>x.foo.bar : () => boolean
|
||||
>x.foo : { bar(): boolean; }
|
||||
>x : { foo: { bar(): boolean; }; }
|
||||
>foo : { bar(): boolean; }
|
||||
>bar : () => boolean
|
||||
>console.log('x.foo.bar') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'x.foo.bar' : "x.foo.bar"
|
||||
|
||||
// ok
|
||||
x.foo.bar && x.foo.bar();
|
||||
>x.foo.bar && x.foo.bar() : boolean
|
||||
>x.foo.bar : () => boolean
|
||||
>x.foo : { bar(): boolean; }
|
||||
>x : { foo: { bar(): boolean; }; }
|
||||
>foo : { bar(): boolean; }
|
||||
>bar : () => boolean
|
||||
>x.foo.bar() : boolean
|
||||
>x.foo.bar : () => boolean
|
||||
>x.foo : { bar(): boolean; }
|
||||
>x : { foo: { bar(): boolean; }; }
|
||||
>foo : { bar(): boolean; }
|
||||
>bar : () => boolean
|
||||
|
||||
// ok
|
||||
x.foo.bar && 1 && x.foo.bar();
|
||||
>x.foo.bar && 1 && x.foo.bar() : boolean
|
||||
>x.foo.bar && 1 : 1
|
||||
>x.foo.bar : () => boolean
|
||||
>x.foo : { bar(): boolean; }
|
||||
>x : { foo: { bar(): boolean; }; }
|
||||
>foo : { bar(): boolean; }
|
||||
>bar : () => boolean
|
||||
>1 : 1
|
||||
>x.foo.bar() : boolean
|
||||
>x.foo.bar : () => boolean
|
||||
>x.foo : { bar(): boolean; }
|
||||
>x : { foo: { bar(): boolean; }; }
|
||||
>foo : { bar(): boolean; }
|
||||
>bar : () => boolean
|
||||
}
|
||||
|
||||
class Foo {
|
||||
>Foo : Foo
|
||||
|
||||
optional?: () => boolean;
|
||||
>optional : (() => boolean) | undefined
|
||||
|
||||
required() {
|
||||
>required : () => boolean
|
||||
|
||||
return true;
|
||||
>true : true
|
||||
}
|
||||
test() {
|
||||
>test : () => void
|
||||
|
||||
// error
|
||||
this.required && console.log('required');
|
||||
>this.required && console.log('required') : void
|
||||
>this.required : () => boolean
|
||||
>this : this
|
||||
>required : () => boolean
|
||||
>console.log('required') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'required' : "required"
|
||||
|
||||
// error
|
||||
1 && this.required && console.log('required');
|
||||
>1 && this.required && console.log('required') : void
|
||||
>1 && this.required : () => boolean
|
||||
>1 : 1
|
||||
>this.required : () => boolean
|
||||
>this : this
|
||||
>required : () => boolean
|
||||
>console.log('required') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'required' : "required"
|
||||
|
||||
// ok
|
||||
this.required && this.required();
|
||||
>this.required && this.required() : boolean
|
||||
>this.required : () => boolean
|
||||
>this : this
|
||||
>required : () => boolean
|
||||
>this.required() : boolean
|
||||
>this.required : () => boolean
|
||||
>this : this
|
||||
>required : () => boolean
|
||||
|
||||
// ok
|
||||
this.required && 1 && this.required();
|
||||
>this.required && 1 && this.required() : boolean
|
||||
>this.required && 1 : 1
|
||||
>this.required : () => boolean
|
||||
>this : this
|
||||
>required : () => boolean
|
||||
>1 : 1
|
||||
>this.required() : boolean
|
||||
>this.required : () => boolean
|
||||
>this : this
|
||||
>required : () => boolean
|
||||
|
||||
// ok
|
||||
1 && this.optional && console.log('optional');
|
||||
>1 && this.optional && console.log('optional') : void | undefined
|
||||
>1 && this.optional : (() => boolean) | undefined
|
||||
>1 : 1
|
||||
>this.optional : (() => boolean) | undefined
|
||||
>this : this
|
||||
>optional : (() => boolean) | undefined
|
||||
>console.log('optional') : void
|
||||
>console.log : (...data: any[]) => void
|
||||
>console : Console
|
||||
>log : (...data: any[]) => void
|
||||
>'optional' : "optional"
|
||||
}
|
||||
}
|
||||
|
83
tests/cases/compiler/truthinessCallExpressionCoercion2.ts
Normal file
83
tests/cases/compiler/truthinessCallExpressionCoercion2.ts
Normal file
|
@ -0,0 +1,83 @@
|
|||
// @strictNullChecks: true
|
||||
// @lib: esnext,dom
|
||||
|
||||
function test(required1: () => boolean, required2: () => boolean, optional?: () => boolean) {
|
||||
// error
|
||||
required1 && console.log('required');
|
||||
|
||||
// error
|
||||
1 && required1 && console.log('required');
|
||||
|
||||
// ok
|
||||
required1 && required1();
|
||||
|
||||
// ok
|
||||
required1 && 1 && required1();
|
||||
|
||||
// ok
|
||||
optional && console.log('optional');
|
||||
|
||||
// ok
|
||||
1 && optional && console.log('optional');
|
||||
|
||||
// ok
|
||||
!!required1 && console.log('not required');
|
||||
|
||||
// ok
|
||||
required1() && console.log('required call');
|
||||
|
||||
// ok
|
||||
required1 && required2 && required1() && required2();
|
||||
|
||||
// error
|
||||
required1 && required2 && required1() && console.log('foo');
|
||||
}
|
||||
|
||||
function checksConsole() {
|
||||
// error
|
||||
typeof window !== 'undefined' && window.console &&
|
||||
((window.console as any).firebug || (window.console.exception && window.console.table));
|
||||
}
|
||||
|
||||
function checksPropertyAccess() {
|
||||
const x = {
|
||||
foo: {
|
||||
bar() { return true; }
|
||||
}
|
||||
}
|
||||
|
||||
// error
|
||||
x.foo.bar && console.log('x.foo.bar');
|
||||
|
||||
// error
|
||||
1 && x.foo.bar && console.log('x.foo.bar');
|
||||
|
||||
// ok
|
||||
x.foo.bar && x.foo.bar();
|
||||
|
||||
// ok
|
||||
x.foo.bar && 1 && x.foo.bar();
|
||||
}
|
||||
|
||||
class Foo {
|
||||
optional?: () => boolean;
|
||||
required() {
|
||||
return true;
|
||||
}
|
||||
test() {
|
||||
// error
|
||||
this.required && console.log('required');
|
||||
|
||||
// error
|
||||
1 && this.required && console.log('required');
|
||||
|
||||
// ok
|
||||
this.required && this.required();
|
||||
|
||||
// ok
|
||||
this.required && 1 && this.required();
|
||||
|
||||
// ok
|
||||
1 && this.optional && console.log('optional');
|
||||
}
|
||||
}
|
|
@ -7,12 +7,14 @@
|
|||
//// if (this.#test) {
|
||||
//// console.log('test')
|
||||
//// }
|
||||
//// this.#test && console.log('test');
|
||||
//// }
|
||||
////}
|
||||
////
|
||||
////function foo() {
|
||||
//// function test() { return Math.random() > 0.5; }
|
||||
//// test ? console.log('test') : undefined;
|
||||
//// test && console.log('test');
|
||||
////}
|
||||
////
|
||||
////function foo() {
|
||||
|
@ -23,6 +25,7 @@
|
|||
//// }
|
||||
//// x.foo.bar ? console.log('test') : undefined;
|
||||
//// if (x.foo.bar) {}
|
||||
//// x.foo.bar && console.log('test');
|
||||
////}
|
||||
|
||||
verify.codeFixAll({
|
||||
|
@ -35,12 +38,14 @@ verify.codeFixAll({
|
|||
if (this.#test()) {
|
||||
console.log('test')
|
||||
}
|
||||
this.#test() && console.log('test');
|
||||
}
|
||||
}
|
||||
|
||||
function foo() {
|
||||
function test() { return Math.random() > 0.5; }
|
||||
test() ? console.log('test') : undefined;
|
||||
test() && console.log('test');
|
||||
}
|
||||
|
||||
function foo() {
|
||||
|
@ -51,5 +56,6 @@ function foo() {
|
|||
}
|
||||
x.foo.bar() ? console.log('test') : undefined;
|
||||
if (x.foo.bar()) {}
|
||||
x.foo.bar() && console.log('test');
|
||||
}`,
|
||||
});
|
||||
|
|
19
tests/cases/fourslash/codeFixMissingCallParentheses12.ts
Normal file
19
tests/cases/fourslash/codeFixMissingCallParentheses12.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @strictNullChecks: true
|
||||
////function foo(fn: () => boolean) {
|
||||
//// fn/**/ && console.log('test');
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Add_missing_call_parentheses.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo(fn: () => boolean) {
|
||||
fn() && console.log('test');
|
||||
}`,
|
||||
});
|
21
tests/cases/fourslash/codeFixMissingCallParentheses13.ts
Normal file
21
tests/cases/fourslash/codeFixMissingCallParentheses13.ts
Normal file
|
@ -0,0 +1,21 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @strictNullChecks: true
|
||||
////function foo() {
|
||||
//// function test() { return Math.random() > 0.5; }
|
||||
//// test/**/ && console.log('test');
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Add_missing_call_parentheses.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() {
|
||||
function test() { return Math.random() > 0.5; }
|
||||
test() && console.log('test');
|
||||
}`,
|
||||
});
|
29
tests/cases/fourslash/codeFixMissingCallParentheses14.ts
Normal file
29
tests/cases/fourslash/codeFixMissingCallParentheses14.ts
Normal file
|
@ -0,0 +1,29 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @strictNullChecks: true
|
||||
////function foo() {
|
||||
//// const x = {
|
||||
//// foo: {
|
||||
//// bar() { return true; }
|
||||
//// }
|
||||
//// }
|
||||
//// x.foo.bar/**/ && console.log('test');
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Add_missing_call_parentheses.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo() {
|
||||
const x = {
|
||||
foo: {
|
||||
bar() { return true; }
|
||||
}
|
||||
}
|
||||
x.foo.bar() && console.log('test');
|
||||
}`,
|
||||
});
|
30
tests/cases/fourslash/codeFixMissingCallParentheses15.ts
Normal file
30
tests/cases/fourslash/codeFixMissingCallParentheses15.ts
Normal file
|
@ -0,0 +1,30 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @strictNullChecks: true
|
||||
////class Foo {
|
||||
//// test() {
|
||||
//// return true;
|
||||
//// }
|
||||
//// run() {
|
||||
//// this.test/**/ && console.log('test');
|
||||
//// }
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Add_missing_call_parentheses.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`class Foo {
|
||||
test() {
|
||||
return true;
|
||||
}
|
||||
run() {
|
||||
this.test() && console.log('test');
|
||||
}
|
||||
}`,
|
||||
});
|
||||
|
25
tests/cases/fourslash/codeFixMissingCallParentheses16.ts
Normal file
25
tests/cases/fourslash/codeFixMissingCallParentheses16.ts
Normal file
|
@ -0,0 +1,25 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @strictNullChecks: true
|
||||
////class Foo {
|
||||
//// #test = () => true;
|
||||
//// run() {
|
||||
//// this.#test/**/ && console.log('test');
|
||||
//// }
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Add_missing_call_parentheses.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`class Foo {
|
||||
#test = () => true;
|
||||
run() {
|
||||
this.#test() && console.log('test');
|
||||
}
|
||||
}`,
|
||||
});
|
19
tests/cases/fourslash/codeFixMissingCallParentheses17.ts
Normal file
19
tests/cases/fourslash/codeFixMissingCallParentheses17.ts
Normal file
|
@ -0,0 +1,19 @@
|
|||
/// <reference path='fourslash.ts'/>
|
||||
|
||||
// @strictNullChecks: true
|
||||
////function foo(fn: () => boolean) {
|
||||
//// 1 && fn/**/ && console.log('test');
|
||||
////}
|
||||
|
||||
verify.codeFixAvailable([
|
||||
{ description: ts.Diagnostics.Add_missing_call_parentheses.message }
|
||||
]);
|
||||
|
||||
verify.codeFix({
|
||||
description: ts.Diagnostics.Add_missing_call_parentheses.message,
|
||||
index: 0,
|
||||
newFileContent:
|
||||
`function foo(fn: () => boolean) {
|
||||
1 && fn() && console.log('test');
|
||||
}`,
|
||||
});
|
Loading…
Reference in a new issue