From 5fb24d1b105982224ea4e2275879509293fae39a Mon Sep 17 00:00:00 2001 From: Oleksandr T Date: Thu, 3 Feb 2022 19:41:17 +0200 Subject: [PATCH] feat(47698): handle uncalled function statements --- src/compiler/checker.ts | 17 +- src/compiler/diagnosticMessages.json | 4 + .../codefixes/fixMissingCallParentheses.ts | 1 + .../controlFlowOptionalChain.errors.txt | 71 +- .../discriminantPropertyCheck.errors.txt | 243 +++++++ .../iteratorsAndStrictNullChecks.errors.txt | 16 + .../keyofAndIndexedAccess.errors.txt | 664 ++++++++++++++++++ .../nonPrimitiveStrictNull.errors.txt | 5 +- .../reference/optionalMethods.errors.txt | 65 ++ ...ruthinessCallExpressionCoercion.errors.txt | 5 +- ...uthinessCallExpressionCoercion1.errors.txt | 5 +- .../typeFromPrototypeAssignment.errors.txt | 47 +- .../typeFromPrototypeAssignment2.errors.txt | 47 +- .../umdGlobalAugmentationNoCrash.errors.txt | 26 + ...GlobalAugmentationIsNotCircular.errors.txt | 30 + .../uncalledFunction(strict=false).js | 54 ++ .../uncalledFunction(strict=false).symbols | 69 ++ .../uncalledFunction(strict=false).types | 77 ++ .../uncalledFunction(strict=true).errors.txt | 54 ++ .../uncalledFunction(strict=true).js | 55 ++ .../uncalledFunction(strict=true).symbols | 69 ++ .../uncalledFunction(strict=true).types | 77 ++ tests/cases/compiler/uncalledFunction.ts | 28 + .../codeFixMissingCallParentheses11.ts | 12 +- .../codeFixMissingCallParentheses18.ts | 15 + .../codeFixMissingCallParentheses19.ts | 15 + 26 files changed, 1763 insertions(+), 8 deletions(-) create mode 100644 tests/baselines/reference/discriminantPropertyCheck.errors.txt create mode 100644 tests/baselines/reference/iteratorsAndStrictNullChecks.errors.txt create mode 100644 tests/baselines/reference/keyofAndIndexedAccess.errors.txt create mode 100644 tests/baselines/reference/optionalMethods.errors.txt create mode 100644 tests/baselines/reference/umdGlobalAugmentationNoCrash.errors.txt create mode 100644 tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.errors.txt create mode 100644 tests/baselines/reference/uncalledFunction(strict=false).js create mode 100644 tests/baselines/reference/uncalledFunction(strict=false).symbols create mode 100644 tests/baselines/reference/uncalledFunction(strict=false).types create mode 100644 tests/baselines/reference/uncalledFunction(strict=true).errors.txt create mode 100644 tests/baselines/reference/uncalledFunction(strict=true).js create mode 100644 tests/baselines/reference/uncalledFunction(strict=true).symbols create mode 100644 tests/baselines/reference/uncalledFunction(strict=true).types create mode 100644 tests/cases/compiler/uncalledFunction.ts create mode 100644 tests/cases/fourslash/codeFixMissingCallParentheses18.ts create mode 100644 tests/cases/fourslash/codeFixMissingCallParentheses19.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 4140f49f9a6f4..8e4e1178ce535 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -37156,7 +37156,7 @@ namespace ts { function checkExpressionStatement(node: ExpressionStatement) { // Grammar checking checkGrammarStatementInAmbientContext(node); - + checkUncalledFunction(node); checkExpression(node.expression); } @@ -39944,6 +39944,21 @@ namespace ts { return targetSymbol; } + function checkUncalledFunction(node: ExpressionStatement) { + if (!strictNullChecks) return; + + const expression = node.expression; + switch (expression.kind) { + case SyntaxKind.Identifier: + case SyntaxKind.PropertyAccessExpression: + case SyntaxKind.ElementAccessExpression: { + if (isFunctionType(getTypeOfNode(expression))) { + error(expression, Diagnostics.This_expression_refers_to_function_Did_you_mean_to_call_it_instead); + } + } + } + } + function checkImportBinding(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) { checkCollisionsForDeclarationName(node, node.name); checkAliasSymbol(node); diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index f00183c8ec8cb..7cc85a70e077e 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -3353,6 +3353,10 @@ "category": "Error", "code": 2822 }, + "This expression refers to function. Did you mean to call it instead?": { + "category": "Error", + "code": 2823 + }, "Cannot find namespace '{0}'. Did you mean '{1}'?": { "category": "Error", "code": 2833 diff --git a/src/services/codefixes/fixMissingCallParentheses.ts b/src/services/codefixes/fixMissingCallParentheses.ts index e86aa129aa40b..b04786582b5bb 100644 --- a/src/services/codefixes/fixMissingCallParentheses.ts +++ b/src/services/codefixes/fixMissingCallParentheses.ts @@ -3,6 +3,7 @@ namespace ts.codefix { const fixId = "fixMissingCallParentheses"; const errorCodes = [ Diagnostics.This_condition_will_always_return_true_since_this_function_is_always_defined_Did_you_mean_to_call_it_instead.code, + Diagnostics.This_expression_refers_to_function_Did_you_mean_to_call_it_instead.code, ]; registerCodeFix({ diff --git a/tests/baselines/reference/controlFlowOptionalChain.errors.txt b/tests/baselines/reference/controlFlowOptionalChain.errors.txt index 1dfe8e9e328a0..dc4229d7ed959 100644 --- a/tests/baselines/reference/controlFlowOptionalChain.errors.txt +++ b/tests/baselines/reference/controlFlowOptionalChain.errors.txt @@ -2,10 +2,15 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(10,1): error TS2 tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(14,1): error TS2454: Variable 'b' is used before being assigned. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(18,1): error TS2454: Variable 'c' is used before being assigned. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(22,1): error TS2454: Variable 'd' is used before being assigned. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(29,5): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(35,5): error TS2722: Cannot invoke an object which is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(39,1): error TS2722: Cannot invoke an object which is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(44,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(45,5): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(52,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(52,5): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(57,1): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(57,1): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(68,5): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(72,1): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(83,5): error TS2532: Object is possibly 'undefined'. @@ -16,20 +21,36 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(105,5): error TS tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(111,1): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(112,1): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(112,1): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(125,5): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(130,5): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(130,5): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(134,1): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(134,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(172,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(181,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(193,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(202,9): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(208,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(211,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(214,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(214,9): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(217,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(220,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(223,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(223,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(235,9): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(238,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(241,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(244,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(244,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(256,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(265,9): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(271,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(274,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(277,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(277,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(286,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(298,9): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(307,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(310,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(319,9): error TS2532: Object is possibly 'undefined'. @@ -46,6 +67,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(358,9): error TS tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(367,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(370,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(379,9): error TS2532: Object is possibly 'undefined'. +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(391,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(406,9): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(418,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(421,9): error TS2532: Object is possibly 'undefined'. tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(430,9): error TS2532: Object is possibly 'undefined'. @@ -61,7 +84,7 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(518,13): error T tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error TS2532: Object is possibly 'undefined'. -==== tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts (61 errors) ==== +==== tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts (84 errors) ==== // assignments in shortcutting chain declare const o: undefined | { [key: string]: any; @@ -99,6 +122,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T if (f?.(x)) { x; // number f; // (x: any) => x is number + ~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? f(x); } else { @@ -118,7 +143,11 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T if (o2?.f(x)) { x; // number o2.f; // (x: any) => x is number + ~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? o2?.f; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? o2?.f(x); } else { @@ -128,6 +157,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T o2.f; ~~ !!! error TS2532: Object is possibly 'undefined'. + ~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } x; o2; @@ -135,6 +166,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T o2.f; ~~ !!! error TS2532: Object is possibly 'undefined'. + ~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? declare const o3: { x: 1, y: string } | { x: 2, y: number } | undefined; if (o3?.x === 1) { @@ -223,6 +256,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T if (o6?.f()) { o6; // Derived o6.f; + ~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } else { o6; @@ -230,12 +265,16 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T o6.f; ~~ !!! error TS2532: Object is possibly 'undefined'. + ~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } o6; o6?.f; o6.f; ~~ !!! error TS2532: Object is possibly 'undefined'. + ~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? // asserts declare const isDefined: (value: T) => asserts value is NonNullable; @@ -274,6 +313,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (o?.bar() === value) { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } if (o?.foo == value) { o.foo; @@ -283,6 +324,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (o?.bar() == value) { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } @@ -295,6 +338,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (o?.bar() === value) { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } if (o?.foo == value) { o.foo; @@ -304,6 +349,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (o?.bar() == value) { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } @@ -322,6 +369,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T o.bar; // Error ~ !!! error TS2532: Object is possibly 'undefined'. + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } if (o?.foo == value) { o.foo; // Error @@ -337,6 +386,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T o.bar; // Error ~ !!! error TS2532: Object is possibly 'undefined'. + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } @@ -349,6 +400,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (o?.bar() === value) { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } if (o?.foo == value) { o.foo; // Error @@ -364,6 +417,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T o.bar; // Error ~ !!! error TS2532: Object is possibly 'undefined'. + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } @@ -376,6 +431,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (o?.bar() !== undefined) { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } if (o?.foo != undefined) { o.foo; @@ -385,6 +442,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (o?.bar() != undefined) { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } @@ -403,6 +462,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T o.bar; // Error ~ !!! error TS2532: Object is possibly 'undefined'. + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } if (o?.foo != null) { o.foo; @@ -412,6 +473,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (o?.bar() != null) { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } @@ -424,6 +487,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (o?.bar() !== undefined) { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } @@ -549,6 +614,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (typeof o?.bar() === "number") { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } if (o?.baz instanceof Error) { o.baz; @@ -564,6 +631,8 @@ tests/cases/conformance/controlFlow/controlFlowOptionalChain.ts(567,21): error T } if (typeof o?.bar() === "number") { o.bar; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } if (o?.baz instanceof Error) { o.baz; diff --git a/tests/baselines/reference/discriminantPropertyCheck.errors.txt b/tests/baselines/reference/discriminantPropertyCheck.errors.txt new file mode 100644 index 0000000000000..787c8bc84ef4a --- /dev/null +++ b/tests/baselines/reference/discriminantPropertyCheck.errors.txt @@ -0,0 +1,243 @@ +tests/cases/compiler/discriminantPropertyCheck.ts(94,17): error TS2823: This expression refers to function. Did you mean to call it instead? + + +==== tests/cases/compiler/discriminantPropertyCheck.ts (1 errors) ==== + type Item = Item1 | Item2; + + interface Base { + bar: boolean; + } + + interface Item1 extends Base { + kind: "A"; + foo: string | undefined; + baz: boolean; + qux: true; + } + + interface Item2 extends Base { + kind: "B"; + foo: string | undefined; + baz: boolean; + qux: false; + } + + function goo1(x: Item) { + if (x.kind === "A" && x.foo !== undefined) { + x.foo.length; + } + } + + function goo2(x: Item) { + if (x.foo !== undefined && x.kind === "A") { + x.foo.length; // Error, intervening discriminant guard + } + } + + function foo1(x: Item) { + if (x.bar && x.foo !== undefined) { + x.foo.length; + } + } + + function foo2(x: Item) { + if (x.foo !== undefined && x.bar) { + x.foo.length; + } + } + + function foo3(x: Item) { + if (x.baz && x.foo !== undefined) { + x.foo.length; + } + } + + function foo4(x: Item) { + if (x.foo !== undefined && x.baz) { + x.foo.length; + } + } + + function foo5(x: Item) { + if (x.qux && x.foo !== undefined) { + x.foo.length; + } + } + + function foo6(x: Item) { + if (x.foo !== undefined && x.qux) { + x.foo.length; // Error, intervening discriminant guard + } + } + + // Repro from #27493 + + enum Types { Str = 1, Num = 2 } + + type Instance = StrType | NumType; + + interface StrType { + type: Types.Str; + value: string; + length: number; + } + + interface NumType { + type: Types.Num; + value: number; + } + + function func2(inst: Instance) { + while (true) { + switch (inst.type) { + case Types.Str: { + inst.value.length; + break; + } + case Types.Num: { + inst.value.toExponential; + ~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + break; + } + } + } + } + + // Repro from #29106 + + const f = (_a: string, _b: string): void => {}; + + interface A { + a?: string; + b?: string; + } + + interface B { + a: string; + b: string; + } + + type U = A | B; + + const u: U = {} as any; + + u.a && u.b && f(u.a, u.b); + + u.b && u.a && f(u.a, u.b); + + // Repro from #29012 + + type Additive = '+' | '-'; + type Multiplicative = '*' | '/'; + + interface AdditiveObj { + key: Additive + } + + interface MultiplicativeObj { + key: Multiplicative + } + + type Obj = AdditiveObj | MultiplicativeObj + + export function foo(obj: Obj) { + switch (obj.key) { + case '+': { + onlyPlus(obj.key); + return; + } + } + } + + function onlyPlus(arg: '+') { + return arg; + } + + // Repro from #29496 + + declare function never(value: never): never; + + const enum BarEnum { + bar1 = 1, + bar2 = 2, + } + + type UnionOfBar = TypeBar1 | TypeBar2; + type TypeBar1 = { type: BarEnum.bar1 }; + type TypeBar2 = { type: BarEnum.bar2 }; + + function func3(value: Partial) { + if (value.type !== undefined) { + switch (value.type) { + case BarEnum.bar1: + break; + case BarEnum.bar2: + break; + default: + never(value.type); + } + } + } + + // Repro from #30557 + + interface TypeA { + Name: "TypeA"; + Value1: "Cool stuff!"; + } + + interface TypeB { + Name: "TypeB"; + Value2: 0; + } + + type Type = TypeA | TypeB; + + declare function isType(x: unknown): x is Type; + + function WorksProperly(data: Type) { + if (data.Name === "TypeA") { + const value1 = data.Value1; + } + } + + function DoesNotWork(data: unknown) { + if (isType(data)) { + if (data.Name === "TypeA") { + const value1 = data.Value1; + } + } + } + + // Repro from #36777 + + type TestA = { + type: 'testA'; + bananas: 3; + } + + type TestB = { + type: 'testB'; + apples: 5; + } + + type AllTests = TestA | TestB; + + type MapOfAllTests = Record; + + const doTestingStuff = (mapOfTests: MapOfAllTests, ids: string[]) => { + ids.forEach(id => { + let test; + test = mapOfTests[id]; + if (test.type === 'testA') { + console.log(test.bananas); + } + switch (test.type) { + case 'testA': { + console.log(test.bananas); + } + } + }); + }; + \ No newline at end of file diff --git a/tests/baselines/reference/iteratorsAndStrictNullChecks.errors.txt b/tests/baselines/reference/iteratorsAndStrictNullChecks.errors.txt new file mode 100644 index 0000000000000..5fff7d6fb6d22 --- /dev/null +++ b/tests/baselines/reference/iteratorsAndStrictNullChecks.errors.txt @@ -0,0 +1,16 @@ +tests/cases/compiler/iteratorsAndStrictNullChecks.ts(3,5): error TS2823: This expression refers to function. Did you mean to call it instead? + + +==== tests/cases/compiler/iteratorsAndStrictNullChecks.ts (1 errors) ==== + // for..of + for (const x of ["a", "b"]) { + x.substring; + ~~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + } + + // Spread + const xs = [1, 2, 3]; + const ys = [4, 5]; + xs.push(...ys); + \ No newline at end of file diff --git a/tests/baselines/reference/keyofAndIndexedAccess.errors.txt b/tests/baselines/reference/keyofAndIndexedAccess.errors.txt new file mode 100644 index 0000000000000..507456fd4b917 --- /dev/null +++ b/tests/baselines/reference/keyofAndIndexedAccess.errors.txt @@ -0,0 +1,664 @@ +tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts(557,9): error TS2823: This expression refers to function. Did you mean to call it instead? + + +==== tests/cases/conformance/types/keyof/keyofAndIndexedAccess.ts (1 errors) ==== + class Shape { + name: string; + width: number; + height: number; + visible: boolean; + } + + class TaggedShape extends Shape { + tag: string; + } + + class Item { + name: string; + price: number; + } + + class Options { + visible: "yes" | "no"; + } + + type Dictionary = { [x: string]: T }; + type NumericallyIndexed = { [x: number]: T }; + + const enum E { A, B, C } + + type K00 = keyof any; // string + type K01 = keyof string; // "toString" | "charAt" | ... + type K02 = keyof number; // "toString" | "toFixed" | "toExponential" | ... + type K03 = keyof boolean; // "valueOf" + type K04 = keyof void; // never + type K05 = keyof undefined; // never + type K06 = keyof null; // never + type K07 = keyof never; // string | number | symbol + type K08 = keyof unknown; // never + + type K10 = keyof Shape; // "name" | "width" | "height" | "visible" + type K11 = keyof Shape[]; // "length" | "toString" | ... + type K12 = keyof Dictionary; // string + type K13 = keyof {}; // never + type K14 = keyof Object; // "constructor" | "toString" | ... + type K15 = keyof E; // "toString" | "toFixed" | "toExponential" | ... + type K16 = keyof [string, number]; // "0" | "1" | "length" | "toString" | ... + type K17 = keyof (Shape | Item); // "name" + type K18 = keyof (Shape & Item); // "name" | "width" | "height" | "visible" | "price" + type K19 = keyof NumericallyIndexed // never + + type KeyOf = keyof T; + + type K20 = KeyOf; // "name" | "width" | "height" | "visible" + type K21 = KeyOf>; // string + + type NAME = "name"; + type WIDTH_OR_HEIGHT = "width" | "height"; + + type Q10 = Shape["name"]; // string + type Q11 = Shape["width" | "height"]; // number + type Q12 = Shape["name" | "visible"]; // string | boolean + + type Q20 = Shape[NAME]; // string + type Q21 = Shape[WIDTH_OR_HEIGHT]; // number + + type Q30 = [string, number][0]; // string + type Q31 = [string, number][1]; // number + type Q32 = [string, number][number]; // string | number + type Q33 = [string, number][E.A]; // string + type Q34 = [string, number][E.B]; // number + type Q35 = [string, number]["0"]; // string + type Q36 = [string, number]["1"]; // string + + type Q40 = (Shape | Options)["visible"]; // boolean | "yes" | "no" + type Q41 = (Shape & Options)["visible"]; // true & "yes" | true & "no" | false & "yes" | false & "no" + + type Q50 = Dictionary["howdy"]; // Shape + type Q51 = Dictionary[123]; // Shape + type Q52 = Dictionary[E.B]; // Shape + + declare let cond: boolean; + + function getProperty(obj: T, key: K) { + return obj[key]; + } + + function setProperty(obj: T, key: K, value: T[K]) { + obj[key] = value; + } + + function f10(shape: Shape) { + let name = getProperty(shape, "name"); // string + let widthOrHeight = getProperty(shape, cond ? "width" : "height"); // number + let nameOrVisible = getProperty(shape, cond ? "name" : "visible"); // string | boolean + setProperty(shape, "name", "rectangle"); + setProperty(shape, cond ? "width" : "height", 10); + setProperty(shape, cond ? "name" : "visible", true); // Technically not safe + } + + function f11(a: Shape[]) { + let len = getProperty(a, "length"); // number + setProperty(a, "length", len); + } + + function f12(t: [Shape, boolean]) { + let len = getProperty(t, "length"); + let s2 = getProperty(t, "0"); // Shape + let b2 = getProperty(t, "1"); // boolean + } + + function f13(foo: any, bar: any) { + let x = getProperty(foo, "x"); // any + let y = getProperty(foo, "100"); // any + let z = getProperty(foo, bar); // any + } + + class Component { + props: PropType; + getProperty(key: K) { + return this.props[key]; + } + setProperty(key: K, value: PropType[K]) { + this.props[key] = value; + } + } + + function f20(component: Component) { + let name = component.getProperty("name"); // string + let widthOrHeight = component.getProperty(cond ? "width" : "height"); // number + let nameOrVisible = component.getProperty(cond ? "name" : "visible"); // string | boolean + component.setProperty("name", "rectangle"); + component.setProperty(cond ? "width" : "height", 10) + component.setProperty(cond ? "name" : "visible", true); // Technically not safe + } + + function pluck(array: T[], key: K) { + return array.map(x => x[key]); + } + + function f30(shapes: Shape[]) { + let names = pluck(shapes, "name"); // string[] + let widths = pluck(shapes, "width"); // number[] + let nameOrVisibles = pluck(shapes, cond ? "name" : "visible"); // (string | boolean)[] + } + + function f31(key: K) { + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; + return shape[key]; // Shape[K] + } + + function f32(key: K) { + const shape: Shape = { name: "foo", width: 5, height: 10, visible: true }; + return shape[key]; // Shape[K] + } + + function f33(shape: S, key: K) { + let name = getProperty(shape, "name"); + let prop = getProperty(shape, key); + return prop; + } + + function f34(ts: TaggedShape) { + let tag1 = f33(ts, "tag"); + let tag2 = getProperty(ts, "tag"); + } + + class C { + public x: string; + protected y: string; + private z: string; + } + + // Indexed access expressions have always permitted access to private and protected members. + // For consistency we also permit such access in indexed access types. + function f40(c: C) { + type X = C["x"]; + type Y = C["y"]; + type Z = C["z"]; + let x: X = c["x"]; + let y: Y = c["y"]; + let z: Z = c["z"]; + } + + function f50(k: keyof T, s: string) { + const x1 = s as keyof T; + const x2 = k as string; + } + + function f51(k: K, s: string) { + const x1 = s as keyof T; + const x2 = k as string; + } + + function f52(obj: { [x: string]: boolean }, k: Exclude, s: string, n: number) { + const x1 = obj[s]; + const x2 = obj[n]; + const x3 = obj[k]; + } + + function f53>(obj: { [x: string]: boolean }, k: K, s: string, n: number) { + const x1 = obj[s]; + const x2 = obj[n]; + const x3 = obj[k]; + } + + function f54(obj: T, key: keyof T) { + for (let s in obj[key]) { + } + const b = "foo" in obj[key]; + } + + function f55(obj: T, key: K) { + for (let s in obj[key]) { + } + const b = "foo" in obj[key]; + } + + function f60(source: T, target: T) { + for (let k in source) { + target[k] = source[k]; + } + } + + function f70(func: (k1: keyof (T | U), k2: keyof (T & U)) => void) { + func<{ a: any, b: any }, { a: any, c: any }>('a', 'a'); + func<{ a: any, b: any }, { a: any, c: any }>('a', 'b'); + func<{ a: any, b: any }, { a: any, c: any }>('a', 'c'); + } + + function f71(func: (x: T, y: U) => Partial) { + let x = func({ a: 1, b: "hello" }, { c: true }); + x.a; // number | undefined + x.b; // string | undefined + x.c; // boolean | undefined + } + + function f72(func: (x: T, y: U, k: K) => (T & U)[K]) { + let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number + let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string + let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean + } + + function f73(func: (x: T, y: U, k: K) => (T & U)[K]) { + let a = func({ a: 1, b: "hello" }, { c: true }, 'a'); // number + let b = func({ a: 1, b: "hello" }, { c: true }, 'b'); // string + let c = func({ a: 1, b: "hello" }, { c: true }, 'c'); // boolean + } + + function f74(func: (x: T, y: U, k: K) => (T | U)[K]) { + let a = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'a'); // number + let b = func({ a: 1, b: "hello" }, { a: 2, b: true }, 'b'); // string | boolean + } + + function f80(obj: T) { + let a1 = obj.a; // { x: any } + let a2 = obj['a']; // { x: any } + let a3 = obj['a'] as T['a']; // T["a"] + let x1 = obj.a.x; // any + let x2 = obj['a']['x']; // any + let x3 = obj['a']['x'] as T['a']['x']; // T["a"]["x"] + } + + function f81(obj: T) { + return obj['a']['x'] as T['a']['x']; + } + + function f82() { + let x1 = f81({ a: { x: "hello" } }); // string + let x2 = f81({ a: { x: 42 } }); // number + } + + function f83(obj: T, key: K) { + return obj[key]['x'] as T[K]['x']; + } + + function f84() { + let x1 = f83({ foo: { x: "hello" } }, "foo"); // string + let x2 = f83({ bar: { x: 42 } }, "bar"); // number + } + + class C1 { + x: number; + get(key: K) { + return this[key]; + } + set(key: K, value: this[K]) { + this[key] = value; + } + foo() { + let x1 = this.x; // number + let x2 = this["x"]; // number + let x3 = this.get("x"); // this["x"] + let x4 = getProperty(this, "x"); // this["x"] + this.x = 42; + this["x"] = 42; + this.set("x", 42); + setProperty(this, "x", 42); + } + } + + type S2 = { + a: string; + b: string; + }; + + function f90(x1: S2[keyof S2], x2: T[keyof S2], x3: S2[K]) { + x1 = x2; + x1 = x3; + x2 = x1; + x2 = x3; + x3 = x1; + x3 = x2; + x1.length; + x2.length; + x3.length; + } + + function f91(x: T, y: T[keyof T], z: T[K]) { + let a: {}; + a = x; + a = y; + a = z; + } + + function f92(x: T, y: T[keyof T], z: T[K]) { + let a: {} | null | undefined; + a = x; + a = y; + a = z; + } + + // Repros from #12011 + + class Base { + get(prop: K) { + return this[prop]; + } + set(prop: K, value: this[K]) { + this[prop] = value; + } + } + + class Person extends Base { + parts: number; + constructor(parts: number) { + super(); + this.set("parts", parts); + } + getParts() { + return this.get("parts") + } + } + + class OtherPerson { + parts: number; + constructor(parts: number) { + setProperty(this, "parts", parts); + } + getParts() { + return getProperty(this, "parts") + } + } + + // Modified repro from #12544 + + function path(obj: T, key1: K1): T[K1]; + function path(obj: T, key1: K1, key2: K2): T[K1][K2]; + function path(obj: T, key1: K1, key2: K2, key3: K3): T[K1][K2][K3]; + function path(obj: any, ...keys: (string | number)[]): any; + function path(obj: any, ...keys: (string | number)[]): any { + let result = obj; + for (let k of keys) { + result = result[k]; + } + return result; + } + + type Thing = { + a: { x: number, y: string }, + b: boolean + }; + + + function f1(thing: Thing) { + let x1 = path(thing, 'a'); // { x: number, y: string } + let x2 = path(thing, 'a', 'y'); // string + let x3 = path(thing, 'b'); // boolean + let x4 = path(thing, ...['a', 'x']); // any + } + + // Repro from comment in #12114 + + const assignTo2 = (object: T, key1: K1, key2: K2) => + (value: T[K1][K2]) => object[key1][key2] = value; + + // Modified repro from #12573 + + declare function one(handler: (t: T) => void): T + var empty = one(() => {}) // inferred as {}, expected + + type Handlers = { [K in keyof T]: (t: T[K]) => void } + declare function on(handlerHash: Handlers): T + var hashOfEmpty1 = on({ test: () => {} }); // {} + var hashOfEmpty2 = on({ test: (x: boolean) => {} }); // { test: boolean } + + // Repro from #12624 + + interface Options1 { + data?: Data + computed?: Computed; + } + + declare class Component1 { + constructor(options: Options1); + get(key: K): (Data & Computed)[K]; + } + + let c1 = new Component1({ + data: { + hello: "" + } + }); + + c1.get("hello"); + + // Repro from #12625 + + interface Options2 { + data?: Data + computed?: Computed; + } + + declare class Component2 { + constructor(options: Options2); + get(key: K): (Data & Computed)[K]; + } + + // Repro from #12641 + + interface R { + p: number; + } + + function f(p: K) { + let a: any; + a[p].add; // any + } + + // Repro from #12651 + + type MethodDescriptor = { + name: string; + args: any[]; + returnValue: any; + } + + declare function dispatchMethod(name: M['name'], args: M['args']): M['returnValue']; + + type SomeMethodDescriptor = { + name: "someMethod"; + args: [string, number]; + returnValue: string[]; + } + + let result = dispatchMethod("someMethod", ["hello", 35]); + + // Repro from #13073 + + type KeyTypes = "a" | "b" + let MyThingy: { [key in KeyTypes]: string[] }; + + function addToMyThingy(key: S) { + MyThingy[key].push("a"); + } + + // Repro from #13102 + + type Handler = { + onChange: (name: keyof T) => void; + }; + + function onChangeGenericFunction(handler: Handler) { + handler.onChange('preset') + } + + // Repro from #13285 + + function updateIds, K extends string>( + obj: T, + idFields: K[], + idMapping: Partial> + ): Record { + for (const idField of idFields) { + const newId: T[K] | undefined = idMapping[obj[idField]]; + if (newId) { + obj[idField] = newId; + } + } + return obj; + } + + // Repro from #13285 + + function updateIds2( + obj: T, + key: K, + stringMap: { [oldId: string]: string } + ) { + var x = obj[key]; + stringMap[x]; // Should be OK. + } + + // Repro from #13514 + + declare function head>(list: T): T[0]; + + // Repro from #13604 + + class A { + props: T & { foo: string }; + } + + class B extends A<{ x: number}> { + f(p: this["props"]) { + p.x; + } + } + + // Repro from #13749 + + class Form { + private childFormFactories: {[K in keyof T]: (v: T[K]) => Form} + + public set(prop: K, value: T[K]) { + this.childFormFactories[prop](value) + } + } + + // Repro from #13787 + + class SampleClass

{ + public props: Readonly

; + constructor(props: P) { + this.props = Object.freeze(props); + } + } + + interface Foo { + foo: string; + } + + declare function merge(obj1: T, obj2: U): T & U; + + class AnotherSampleClass extends SampleClass { + constructor(props: T) { + const foo: Foo = { foo: "bar" }; + super(merge(props, foo)); + } + + public brokenMethod() { + this.props.foo.concat; + ~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + } + } + new AnotherSampleClass({}); + + // Positive repro from #17166 + function f3>(t: T, k: K, tk: T[K]): void { + for (let key in t) { + key = k // ok, K ==> keyof T + t[key] = tk; // ok, T[K] ==> T[keyof T] + } + } + + // # 21185 + type Predicates = { + [T in keyof TaggedRecord]: (variant: TaggedRecord[keyof TaggedRecord]) => variant is TaggedRecord[T] + } + + // Repros from #23592 + + type Example = { [K in keyof T]: T[K]["prop"] }; + type Result = Example<{ a: { prop: string }; b: { prop: number } }>; + + type Helper2 = { [K in keyof T]: Extract }; + type Example2 = { [K in keyof Helper2]: Helper2[K]["prop"] }; + type Result2 = Example2<{ 1: { prop: string }; 2: { prop: number } }>; + + // Repro from #23618 + + type DBBoolTable = { [k in K]: 0 | 1 } + enum Flag { + FLAG_1 = "flag_1", + FLAG_2 = "flag_2" + } + + type SimpleDBRecord = { staticField: number } & DBBoolTable + function getFlagsFromSimpleRecord(record: SimpleDBRecord, flags: Flag[]) { + return record[flags[0]]; + } + + type DynamicDBRecord = ({ dynamicField: number } | { dynamicField: string }) & DBBoolTable + function getFlagsFromDynamicRecord(record: DynamicDBRecord, flags: Flag[]) { + return record[flags[0]]; + } + + // Repro from #21368 + + interface I { + foo: string; + } + + declare function take(p: T): void; + + function fn(o: T, k: K) { + take<{} | null | undefined>(o[k]); + take(o[k]); + } + + // Repro from #23133 + + class Unbounded { + foo(x: T[keyof T]) { + let y: {} | undefined | null = x; + } + } + + // Repro from #23940 + + interface I7 { + x: any; + } + type Foo7 = T; + declare function f7(type: K): Foo7; + + // Repro from #21770 + + type Dict = { [key in T]: number }; + type DictDict = { [key in V]: Dict }; + + function ff1(dd: DictDict, k1: V, k2: T): number { + return dd[k1][k2]; + } + + function ff2(dd: DictDict, k1: V, k2: T): number { + const d: Dict = dd[k1]; + return d[k2]; + } + + // Repro from #26409 + + const cf1 = (t: T, k: K) => + { + const s: string = t[k]; + t.cool; + }; + + const cf2 = (t: T, k: K) => + { + const s: string = t[k]; + t.cool; + }; + \ No newline at end of file diff --git a/tests/baselines/reference/nonPrimitiveStrictNull.errors.txt b/tests/baselines/reference/nonPrimitiveStrictNull.errors.txt index 6b26c4d42ac8c..f041cb0c8693d 100644 --- a/tests/baselines/reference/nonPrimitiveStrictNull.errors.txt +++ b/tests/baselines/reference/nonPrimitiveStrictNull.errors.txt @@ -1,4 +1,5 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts(6,1): error TS2454: Variable 'a' is used before being assigned. +tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts(6,1): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts(7,1): error TS2322: Type 'undefined' is not assignable to type 'object'. tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts(8,1): error TS2322: Type 'null' is not assignable to type 'object'. tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts(9,1): error TS2322: Type 'object | null' is not assignable to type 'object'. @@ -22,7 +23,7 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts(52,14): err tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts(53,14): error TS2344: Type 'undefined' does not satisfy the constraint 'object'. -==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts (18 errors) ==== +==== tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts (19 errors) ==== var a: object declare var b: object | null declare var c: object | undefined @@ -31,6 +32,8 @@ tests/cases/conformance/types/nonPrimitive/nonPrimitiveStrictNull.ts(53,14): err a.toString; // error ~ !!! error TS2454: Variable 'a' is used before being assigned. + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? a = undefined; // error ~ !!! error TS2322: Type 'undefined' is not assignable to type 'object'. diff --git a/tests/baselines/reference/optionalMethods.errors.txt b/tests/baselines/reference/optionalMethods.errors.txt new file mode 100644 index 0000000000000..c57670f3c37cb --- /dev/null +++ b/tests/baselines/reference/optionalMethods.errors.txt @@ -0,0 +1,65 @@ +tests/cases/conformance/types/namedTypes/optionalMethods.ts(11,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/types/namedTypes/optionalMethods.ts(38,5): error TS2823: This expression refers to function. Did you mean to call it instead? + + +==== tests/cases/conformance/types/namedTypes/optionalMethods.ts (2 errors) ==== + interface Foo { + a: number; + b?: number; + f(): number; + g?(): number; + } + + function test1(x: Foo) { + x.a; + x.b; + x.f; + ~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + x.g; + let f1 = x.f(); + let g1 = x.g && x.g(); + let g2 = x.g ? x.g() : 0; + } + + class Bar { + a: number; + b?: number; + c? = 2; + constructor(public d?: number, public e = 10) {} + f() { + return 1; + } + g?(): number; // Body of optional method can be omitted + h?() { + return 2; + } + } + + function test2(x: Bar) { + x.a; + x.b; + x.c; + x.d; + x.e; + x.f; + ~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + x.g; + let f1 = x.f(); + let g1 = x.g && x.g(); + let g2 = x.g ? x.g() : 0; + let h1 = x.h && x.h(); + let h2 = x.h ? x.h() : 0; + } + + class Base { + a?: number; + f?(): number; + } + + class Derived extends Base { + a = 1; + f(): number { return 1; } + } + \ No newline at end of file diff --git a/tests/baselines/reference/truthinessCallExpressionCoercion.errors.txt b/tests/baselines/reference/truthinessCallExpressionCoercion.errors.txt index d9645dc64922a..2929372ec0c11 100644 --- a/tests/baselines/reference/truthinessCallExpressionCoercion.errors.txt +++ b/tests/baselines/reference/truthinessCallExpressionCoercion.errors.txt @@ -2,12 +2,13 @@ tests/cases/compiler/truthinessCallExpressionCoercion.ts(2,9): error TS2774: Thi tests/cases/compiler/truthinessCallExpressionCoercion.ts(18,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? tests/cases/compiler/truthinessCallExpressionCoercion.ts(36,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? tests/cases/compiler/truthinessCallExpressionCoercion.ts(50,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? +tests/cases/compiler/truthinessCallExpressionCoercion.ts(54,9): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/compiler/truthinessCallExpressionCoercion.ts(66,13): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? tests/cases/compiler/truthinessCallExpressionCoercion.ts(76,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? -==== tests/cases/compiler/truthinessCallExpressionCoercion.ts (7 errors) ==== +==== tests/cases/compiler/truthinessCallExpressionCoercion.ts (8 errors) ==== function onlyErrorsWhenTestingNonNullableFunctionType(required: () => boolean, optional?: () => boolean) { if (required) { // error ~~~~~~~~ @@ -70,6 +71,8 @@ tests/cases/compiler/truthinessCallExpressionCoercion.ts(82,9): error TS2774: Th if (x.foo.bar) { // ok x.foo.bar; + ~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } diff --git a/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt b/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt index ae4486bc5937a..5e2150cc030de 100644 --- a/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt +++ b/tests/baselines/reference/truthinessCallExpressionCoercion1.errors.txt @@ -2,10 +2,11 @@ tests/cases/compiler/truthinessCallExpressionCoercion1.ts(3,5): error TS2774: Th tests/cases/compiler/truthinessCallExpressionCoercion1.ts(19,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/truthinessCallExpressionCoercion1.ts(33,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/truthinessCallExpressionCoercion1.ts(46,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/truthinessCallExpressionCoercion1.ts(63,9): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/compiler/truthinessCallExpressionCoercion1.ts(76,9): error TS2774: This condition will always return true since this function is always defined. Did you mean to call it instead? -==== tests/cases/compiler/truthinessCallExpressionCoercion1.ts (5 errors) ==== +==== tests/cases/compiler/truthinessCallExpressionCoercion1.ts (6 errors) ==== function onlyErrorsWhenTestingNonNullableFunctionType(required: () => boolean, optional?: () => boolean) { // error required ? console.log('required') : undefined; @@ -77,6 +78,8 @@ tests/cases/compiler/truthinessCallExpressionCoercion1.ts(76,9): error TS2774: T // ok if (chrome.platformKeys.subtleCrypto().exportKey) { chrome.platformKeys.subtleCrypto().exportKey + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } diff --git a/tests/baselines/reference/typeFromPrototypeAssignment.errors.txt b/tests/baselines/reference/typeFromPrototypeAssignment.errors.txt index edd3435c445c3..ea188f4e082a9 100644 --- a/tests/baselines/reference/typeFromPrototypeAssignment.errors.txt +++ b/tests/baselines/reference/typeFromPrototypeAssignment.errors.txt @@ -1,7 +1,22 @@ +tests/cases/conformance/salsa/a.js(7,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(8,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(9,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(15,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(16,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(17,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(21,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(22,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(23,9): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/salsa/a.js(27,20): error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'. +tests/cases/conformance/salsa/a.js(29,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(30,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(31,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(36,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(37,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(38,1): error TS2823: This expression refers to function. Did you mean to call it instead? -==== tests/cases/conformance/salsa/a.js (1 errors) ==== +==== tests/cases/conformance/salsa/a.js (16 errors) ==== // all references to _map, set, get, addon should be ok /** @constructor */ @@ -9,22 +24,40 @@ tests/cases/conformance/salsa/a.js(27,20): error TS2339: Property 'addon' does n this._map = {}; this._map this.set + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.get + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.addon + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? }; Multimap.prototype = { set: function() { this._map this.set + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.get + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.addon + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? }, get() { this._map this.set + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.get + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.addon + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } @@ -33,13 +66,25 @@ tests/cases/conformance/salsa/a.js(27,20): error TS2339: Property 'addon' does n !!! error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'. this._map this.set + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.get + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.addon + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } var mm = new Multimap(); mm._map mm.set + ~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? mm.get + ~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? mm.addon + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? \ No newline at end of file diff --git a/tests/baselines/reference/typeFromPrototypeAssignment2.errors.txt b/tests/baselines/reference/typeFromPrototypeAssignment2.errors.txt index d4f66132d44a0..815f6bc5037b7 100644 --- a/tests/baselines/reference/typeFromPrototypeAssignment2.errors.txt +++ b/tests/baselines/reference/typeFromPrototypeAssignment2.errors.txt @@ -1,7 +1,22 @@ +tests/cases/conformance/salsa/a.js(8,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(9,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(10,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(16,13): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(17,13): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(18,13): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(22,13): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(23,13): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(24,13): error TS2823: This expression refers to function. Did you mean to call it instead? tests/cases/conformance/salsa/a.js(28,24): error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'. +tests/cases/conformance/salsa/a.js(30,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(31,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(32,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(37,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(38,5): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/conformance/salsa/a.js(39,5): error TS2823: This expression refers to function. Did you mean to call it instead? -==== tests/cases/conformance/salsa/a.js (1 errors) ==== +==== tests/cases/conformance/salsa/a.js (16 errors) ==== // non top-level: // all references to _map, set, get, addon should be ok (function container() { @@ -10,22 +25,40 @@ tests/cases/conformance/salsa/a.js(28,24): error TS2339: Property 'addon' does n this._map = {}; this._map this.set + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.get + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.addon + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? }; Multimap.prototype = { set: function() { this._map this.set + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.get + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.addon + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? }, get() { this._map this.set + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.get + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.addon + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } } @@ -34,14 +67,26 @@ tests/cases/conformance/salsa/a.js(28,24): error TS2339: Property 'addon' does n !!! error TS2339: Property 'addon' does not exist on type '{ set: () => void; get(): void; }'. this._map this.set + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.get + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? this.addon + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? } var mm = new Multimap(); mm._map mm.set + ~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? mm.get + ~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? mm.addon + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? }); \ No newline at end of file diff --git a/tests/baselines/reference/umdGlobalAugmentationNoCrash.errors.txt b/tests/baselines/reference/umdGlobalAugmentationNoCrash.errors.txt new file mode 100644 index 0000000000000..eed451e6870e5 --- /dev/null +++ b/tests/baselines/reference/umdGlobalAugmentationNoCrash.errors.txt @@ -0,0 +1,26 @@ +tests/cases/compiler/emits.ts(2,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/compiler/some_module.ts(2,1): error TS2823: This expression refers to function. Did you mean to call it instead? + + +==== tests/cases/compiler/global.d.ts (0 errors) ==== + declare global { + const React: typeof import("./module"); + } + export {}; + +==== tests/cases/compiler/module.d.ts (0 errors) ==== + export as namespace React; + export function foo(): string; + +==== tests/cases/compiler/some_module.ts (1 errors) ==== + export {} + React.foo; + ~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + +==== tests/cases/compiler/emits.ts (1 errors) ==== + console.log("hello"); + React.foo; + ~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + \ No newline at end of file diff --git a/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.errors.txt b/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.errors.txt new file mode 100644 index 0000000000000..007b30caffbab --- /dev/null +++ b/tests/baselines/reference/umdNamespaceMergedWithGlobalAugmentationIsNotCircular.errors.txt @@ -0,0 +1,30 @@ +tests/cases/compiler/emits.ts(2,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/compiler/some_module.ts(2,1): error TS2823: This expression refers to function. Did you mean to call it instead? + + +==== tests/cases/compiler/global.d.ts (0 errors) ==== + declare global { + const React: typeof import("./module"); + } + + export { }; + +==== tests/cases/compiler/module.d.ts (0 errors) ==== + export = React; + export as namespace React; + + declare namespace React { + function createRef(): any; + } + +==== tests/cases/compiler/some_module.ts (1 errors) ==== + export { }; + React.createRef; + ~~~~~~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + +==== tests/cases/compiler/emits.ts (1 errors) ==== + console.log("hello"); + React.createRef; + ~~~~~~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? \ No newline at end of file diff --git a/tests/baselines/reference/uncalledFunction(strict=false).js b/tests/baselines/reference/uncalledFunction(strict=false).js new file mode 100644 index 0000000000000..17f4487a34651 --- /dev/null +++ b/tests/baselines/reference/uncalledFunction(strict=false).js @@ -0,0 +1,54 @@ +//// [uncalledFunction.ts] +function a() {} +a; + +const b = () => {} +b; + +const c = { + d: () => {}, + e: { + f: () => {} + } +} + +c.d; +c['d']; + +c.e.f; +c.e['f']; + +class C { + m1() {} + m2() { + this.m1; + this['m1']; + } +} + + +//// [uncalledFunction.js] +function a() { } +a; +var b = function () { }; +b; +var c = { + d: function () { }, + e: { + f: function () { } + } +}; +c.d; +c['d']; +c.e.f; +c.e['f']; +var C = /** @class */ (function () { + function C() { + } + C.prototype.m1 = function () { }; + C.prototype.m2 = function () { + this.m1; + this['m1']; + }; + return C; +}()); diff --git a/tests/baselines/reference/uncalledFunction(strict=false).symbols b/tests/baselines/reference/uncalledFunction(strict=false).symbols new file mode 100644 index 0000000000000..b65dcee947017 --- /dev/null +++ b/tests/baselines/reference/uncalledFunction(strict=false).symbols @@ -0,0 +1,69 @@ +=== tests/cases/compiler/uncalledFunction.ts === +function a() {} +>a : Symbol(a, Decl(uncalledFunction.ts, 0, 0)) + +a; +>a : Symbol(a, Decl(uncalledFunction.ts, 0, 0)) + +const b = () => {} +>b : Symbol(b, Decl(uncalledFunction.ts, 3, 5)) + +b; +>b : Symbol(b, Decl(uncalledFunction.ts, 3, 5)) + +const c = { +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) + + d: () => {}, +>d : Symbol(d, Decl(uncalledFunction.ts, 6, 11)) + + e: { +>e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) + + f: () => {} +>f : Symbol(f, Decl(uncalledFunction.ts, 8, 8)) + } +} + +c.d; +>c.d : Symbol(d, Decl(uncalledFunction.ts, 6, 11)) +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) +>d : Symbol(d, Decl(uncalledFunction.ts, 6, 11)) + +c['d']; +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) +>'d' : Symbol(d, Decl(uncalledFunction.ts, 6, 11)) + +c.e.f; +>c.e.f : Symbol(f, Decl(uncalledFunction.ts, 8, 8)) +>c.e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) +>e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) +>f : Symbol(f, Decl(uncalledFunction.ts, 8, 8)) + +c.e['f']; +>c.e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) +>e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) +>'f' : Symbol(f, Decl(uncalledFunction.ts, 8, 8)) + +class C { +>C : Symbol(C, Decl(uncalledFunction.ts, 17, 9)) + + m1() {} +>m1 : Symbol(C.m1, Decl(uncalledFunction.ts, 19, 9)) + + m2() { +>m2 : Symbol(C.m2, Decl(uncalledFunction.ts, 20, 11)) + + this.m1; +>this.m1 : Symbol(C.m1, Decl(uncalledFunction.ts, 19, 9)) +>this : Symbol(C, Decl(uncalledFunction.ts, 17, 9)) +>m1 : Symbol(C.m1, Decl(uncalledFunction.ts, 19, 9)) + + this['m1']; +>this : Symbol(C, Decl(uncalledFunction.ts, 17, 9)) +>'m1' : Symbol(C.m1, Decl(uncalledFunction.ts, 19, 9)) + } +} + diff --git a/tests/baselines/reference/uncalledFunction(strict=false).types b/tests/baselines/reference/uncalledFunction(strict=false).types new file mode 100644 index 0000000000000..cc5f907266502 --- /dev/null +++ b/tests/baselines/reference/uncalledFunction(strict=false).types @@ -0,0 +1,77 @@ +=== tests/cases/compiler/uncalledFunction.ts === +function a() {} +>a : () => void + +a; +>a : () => void + +const b = () => {} +>b : () => void +>() => {} : () => void + +b; +>b : () => void + +const c = { +>c : { d: () => void; e: { f: () => void; }; } +>{ d: () => {}, e: { f: () => {} }} : { d: () => void; e: { f: () => void; }; } + + d: () => {}, +>d : () => void +>() => {} : () => void + + e: { +>e : { f: () => void; } +>{ f: () => {} } : { f: () => void; } + + f: () => {} +>f : () => void +>() => {} : () => void + } +} + +c.d; +>c.d : () => void +>c : { d: () => void; e: { f: () => void; }; } +>d : () => void + +c['d']; +>c['d'] : () => void +>c : { d: () => void; e: { f: () => void; }; } +>'d' : "d" + +c.e.f; +>c.e.f : () => void +>c.e : { f: () => void; } +>c : { d: () => void; e: { f: () => void; }; } +>e : { f: () => void; } +>f : () => void + +c.e['f']; +>c.e['f'] : () => void +>c.e : { f: () => void; } +>c : { d: () => void; e: { f: () => void; }; } +>e : { f: () => void; } +>'f' : "f" + +class C { +>C : C + + m1() {} +>m1 : () => void + + m2() { +>m2 : () => void + + this.m1; +>this.m1 : () => void +>this : this +>m1 : () => void + + this['m1']; +>this['m1'] : () => void +>this : this +>'m1' : "m1" + } +} + diff --git a/tests/baselines/reference/uncalledFunction(strict=true).errors.txt b/tests/baselines/reference/uncalledFunction(strict=true).errors.txt new file mode 100644 index 0000000000000..728593c243177 --- /dev/null +++ b/tests/baselines/reference/uncalledFunction(strict=true).errors.txt @@ -0,0 +1,54 @@ +tests/cases/compiler/uncalledFunction.ts(2,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/compiler/uncalledFunction.ts(5,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/compiler/uncalledFunction.ts(14,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/compiler/uncalledFunction.ts(15,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/compiler/uncalledFunction.ts(17,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/compiler/uncalledFunction.ts(18,1): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/compiler/uncalledFunction.ts(23,9): error TS2823: This expression refers to function. Did you mean to call it instead? +tests/cases/compiler/uncalledFunction.ts(24,9): error TS2823: This expression refers to function. Did you mean to call it instead? + + +==== tests/cases/compiler/uncalledFunction.ts (8 errors) ==== + function a() {} + a; + ~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + + const b = () => {} + b; + ~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + + const c = { + d: () => {}, + e: { + f: () => {} + } + } + + c.d; + ~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + c['d']; + ~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + + c.e.f; + ~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + c.e['f']; + ~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + + class C { + m1() {} + m2() { + this.m1; + ~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + this['m1']; + ~~~~~~~~~~ +!!! error TS2823: This expression refers to function. Did you mean to call it instead? + } + } + \ No newline at end of file diff --git a/tests/baselines/reference/uncalledFunction(strict=true).js b/tests/baselines/reference/uncalledFunction(strict=true).js new file mode 100644 index 0000000000000..519f1c02ca396 --- /dev/null +++ b/tests/baselines/reference/uncalledFunction(strict=true).js @@ -0,0 +1,55 @@ +//// [uncalledFunction.ts] +function a() {} +a; + +const b = () => {} +b; + +const c = { + d: () => {}, + e: { + f: () => {} + } +} + +c.d; +c['d']; + +c.e.f; +c.e['f']; + +class C { + m1() {} + m2() { + this.m1; + this['m1']; + } +} + + +//// [uncalledFunction.js] +"use strict"; +function a() { } +a; +var b = function () { }; +b; +var c = { + d: function () { }, + e: { + f: function () { } + } +}; +c.d; +c['d']; +c.e.f; +c.e['f']; +var C = /** @class */ (function () { + function C() { + } + C.prototype.m1 = function () { }; + C.prototype.m2 = function () { + this.m1; + this['m1']; + }; + return C; +}()); diff --git a/tests/baselines/reference/uncalledFunction(strict=true).symbols b/tests/baselines/reference/uncalledFunction(strict=true).symbols new file mode 100644 index 0000000000000..b65dcee947017 --- /dev/null +++ b/tests/baselines/reference/uncalledFunction(strict=true).symbols @@ -0,0 +1,69 @@ +=== tests/cases/compiler/uncalledFunction.ts === +function a() {} +>a : Symbol(a, Decl(uncalledFunction.ts, 0, 0)) + +a; +>a : Symbol(a, Decl(uncalledFunction.ts, 0, 0)) + +const b = () => {} +>b : Symbol(b, Decl(uncalledFunction.ts, 3, 5)) + +b; +>b : Symbol(b, Decl(uncalledFunction.ts, 3, 5)) + +const c = { +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) + + d: () => {}, +>d : Symbol(d, Decl(uncalledFunction.ts, 6, 11)) + + e: { +>e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) + + f: () => {} +>f : Symbol(f, Decl(uncalledFunction.ts, 8, 8)) + } +} + +c.d; +>c.d : Symbol(d, Decl(uncalledFunction.ts, 6, 11)) +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) +>d : Symbol(d, Decl(uncalledFunction.ts, 6, 11)) + +c['d']; +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) +>'d' : Symbol(d, Decl(uncalledFunction.ts, 6, 11)) + +c.e.f; +>c.e.f : Symbol(f, Decl(uncalledFunction.ts, 8, 8)) +>c.e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) +>e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) +>f : Symbol(f, Decl(uncalledFunction.ts, 8, 8)) + +c.e['f']; +>c.e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) +>c : Symbol(c, Decl(uncalledFunction.ts, 6, 5)) +>e : Symbol(e, Decl(uncalledFunction.ts, 7, 16)) +>'f' : Symbol(f, Decl(uncalledFunction.ts, 8, 8)) + +class C { +>C : Symbol(C, Decl(uncalledFunction.ts, 17, 9)) + + m1() {} +>m1 : Symbol(C.m1, Decl(uncalledFunction.ts, 19, 9)) + + m2() { +>m2 : Symbol(C.m2, Decl(uncalledFunction.ts, 20, 11)) + + this.m1; +>this.m1 : Symbol(C.m1, Decl(uncalledFunction.ts, 19, 9)) +>this : Symbol(C, Decl(uncalledFunction.ts, 17, 9)) +>m1 : Symbol(C.m1, Decl(uncalledFunction.ts, 19, 9)) + + this['m1']; +>this : Symbol(C, Decl(uncalledFunction.ts, 17, 9)) +>'m1' : Symbol(C.m1, Decl(uncalledFunction.ts, 19, 9)) + } +} + diff --git a/tests/baselines/reference/uncalledFunction(strict=true).types b/tests/baselines/reference/uncalledFunction(strict=true).types new file mode 100644 index 0000000000000..cc5f907266502 --- /dev/null +++ b/tests/baselines/reference/uncalledFunction(strict=true).types @@ -0,0 +1,77 @@ +=== tests/cases/compiler/uncalledFunction.ts === +function a() {} +>a : () => void + +a; +>a : () => void + +const b = () => {} +>b : () => void +>() => {} : () => void + +b; +>b : () => void + +const c = { +>c : { d: () => void; e: { f: () => void; }; } +>{ d: () => {}, e: { f: () => {} }} : { d: () => void; e: { f: () => void; }; } + + d: () => {}, +>d : () => void +>() => {} : () => void + + e: { +>e : { f: () => void; } +>{ f: () => {} } : { f: () => void; } + + f: () => {} +>f : () => void +>() => {} : () => void + } +} + +c.d; +>c.d : () => void +>c : { d: () => void; e: { f: () => void; }; } +>d : () => void + +c['d']; +>c['d'] : () => void +>c : { d: () => void; e: { f: () => void; }; } +>'d' : "d" + +c.e.f; +>c.e.f : () => void +>c.e : { f: () => void; } +>c : { d: () => void; e: { f: () => void; }; } +>e : { f: () => void; } +>f : () => void + +c.e['f']; +>c.e['f'] : () => void +>c.e : { f: () => void; } +>c : { d: () => void; e: { f: () => void; }; } +>e : { f: () => void; } +>'f' : "f" + +class C { +>C : C + + m1() {} +>m1 : () => void + + m2() { +>m2 : () => void + + this.m1; +>this.m1 : () => void +>this : this +>m1 : () => void + + this['m1']; +>this['m1'] : () => void +>this : this +>'m1' : "m1" + } +} + diff --git a/tests/cases/compiler/uncalledFunction.ts b/tests/cases/compiler/uncalledFunction.ts new file mode 100644 index 0000000000000..b6353ef8d346f --- /dev/null +++ b/tests/cases/compiler/uncalledFunction.ts @@ -0,0 +1,28 @@ +// @strict: true, false + +function a() {} +a; + +const b = () => {} +b; + +const c = { + d: () => {}, + e: { + f: () => {} + } +} + +c.d; +c['d']; + +c.e.f; +c.e['f']; + +class C { + m1() {} + m2() { + this.m1; + this['m1']; + } +} diff --git a/tests/cases/fourslash/codeFixMissingCallParentheses11.ts b/tests/cases/fourslash/codeFixMissingCallParentheses11.ts index 76e4b2a9a443c..412b1aea08746 100644 --- a/tests/cases/fourslash/codeFixMissingCallParentheses11.ts +++ b/tests/cases/fourslash/codeFixMissingCallParentheses11.ts @@ -27,6 +27,11 @@ //// if (x.foo.bar) {} //// x.foo.bar && console.log('test'); ////} +////function f() {} +////f; +//// +////const a = { b: () => {} }; +////a.b; verify.codeFixAll({ fixAllDescription: ts.Diagnostics.Add_all_missing_call_parentheses.message, @@ -57,5 +62,10 @@ function foo() { x.foo.bar() ? console.log('test') : undefined; if (x.foo.bar()) {} x.foo.bar() && console.log('test'); -}`, +} +function f() {} +f(); + +const a = { b: () => {} }; +a.b();`, }); diff --git a/tests/cases/fourslash/codeFixMissingCallParentheses18.ts b/tests/cases/fourslash/codeFixMissingCallParentheses18.ts new file mode 100644 index 0000000000000..f386b140ed44a --- /dev/null +++ b/tests/cases/fourslash/codeFixMissingCallParentheses18.ts @@ -0,0 +1,15 @@ +/// + +// @strictNullChecks: true +////function foo() {} +////[|foo;|] + +verify.codeFixAvailable([ + { description: ts.Diagnostics.Add_missing_call_parentheses.message } +]); + +verify.codeFix({ + description: ts.Diagnostics.Add_missing_call_parentheses.message, + index: 0, + newRangeContent: `foo();`, +}); diff --git a/tests/cases/fourslash/codeFixMissingCallParentheses19.ts b/tests/cases/fourslash/codeFixMissingCallParentheses19.ts new file mode 100644 index 0000000000000..3e925eaf1a6a2 --- /dev/null +++ b/tests/cases/fourslash/codeFixMissingCallParentheses19.ts @@ -0,0 +1,15 @@ +/// + +// @strictNullChecks: true +////const a = { b: () => {} } +////[|a.b;|] + +verify.codeFixAvailable([ + { description: ts.Diagnostics.Add_missing_call_parentheses.message } +]); + +verify.codeFix({ + description: ts.Diagnostics.Add_missing_call_parentheses.message, + index: 0, + newRangeContent: `a.b();`, +});