Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 24 additions & 32 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5058,9 +5058,10 @@ namespace ts {
if (!links.resolvedSignature) {
const parameters: Symbol[] = [];
let hasLiteralTypes = false;
let minArgumentCount = -1;
let minArgumentCount = 0;
let thisParameter: Symbol = undefined;
let hasThisParameter: boolean;
const iife = getImmediatelyInvokedFunctionExpression(declaration);
const isJSConstructSignature = isJSDocConstructSignature(declaration);

// If this is a JSDoc construct signature, then skip the first parameter in the
Expand All @@ -5087,14 +5088,12 @@ namespace ts {
hasLiteralTypes = true;
}

if (param.initializer || param.questionToken || param.dotDotDotToken || isJSDocOptionalParameter(param)) {
if (minArgumentCount < 0) {
minArgumentCount = i - (hasThisParameter ? 1 : 0);
}
}
else {
// If we see any required parameters, it means the prior ones were not in fact optional.
minArgumentCount = -1;
// Record a new minimum argument count if this is not an optional parameter
const isOptionalParameter = param.initializer || param.questionToken || param.dotDotDotToken ||
iife && parameters.length > iife.arguments.length && !param.type ||
isJSDocOptionalParameter(param);
if (!isOptionalParameter) {
minArgumentCount = parameters.length;
}
}

Expand All @@ -5109,13 +5108,6 @@ namespace ts {
}
}

if (minArgumentCount < 0) {
minArgumentCount = declaration.parameters.length - (hasThisParameter ? 1 : 0);
}
if (isJSConstructSignature) {
minArgumentCount--;
}

const classType = declaration.kind === SyntaxKind.Constructor ?
getDeclaredTypeOfClassOrInterface(getMergedSymbol((<ClassDeclaration>declaration.parent).symbol))
: undefined;
Expand Down Expand Up @@ -10933,23 +10925,23 @@ namespace ts {
const func = parameter.parent;
if (isContextSensitiveFunctionOrObjectLiteralMethod(func)) {
const iife = getImmediatelyInvokedFunctionExpression(func);
if (iife) {
if (iife && iife.arguments) {
const indexOfParameter = indexOf(func.parameters, parameter);
if (iife.arguments && indexOfParameter < iife.arguments.length) {
if (parameter.dotDotDotToken) {
const restTypes: Type[] = [];
for (let i = indexOfParameter; i < iife.arguments.length; i++) {
restTypes.push(getWidenedLiteralType(checkExpression(iife.arguments[i])));
}
return createArrayType(getUnionType(restTypes));
}
const links = getNodeLinks(iife);
const cached = links.resolvedSignature;
links.resolvedSignature = anySignature;
const type = getWidenedLiteralType(checkExpression(iife.arguments[indexOfParameter]));
links.resolvedSignature = cached;
return type;
}
if (parameter.dotDotDotToken) {
const restTypes: Type[] = [];
for (let i = indexOfParameter; i < iife.arguments.length; i++) {
restTypes.push(getWidenedLiteralType(checkExpression(iife.arguments[i])));
}
return restTypes.length ? createArrayType(getUnionType(restTypes)) : undefined;
}
const links = getNodeLinks(iife);
const cached = links.resolvedSignature;
links.resolvedSignature = anySignature;
const type = indexOfParameter < iife.arguments.length ?
getWidenedLiteralType(checkExpression(iife.arguments[indexOfParameter])) :
parameter.initializer ? undefined : undefinedWideningType;

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@sandersn this will need to be covered in your change for initialized parameters.

links.resolvedSignature = cached;
return type;
}
const contextualSignature = getContextualSignature(func);
if (contextualSignature) {
Expand Down
6 changes: 6 additions & 0 deletions tests/baselines/reference/contextuallyTypedIife.js
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,9 @@
// contextually typed parameters.
let twelve = (f => f(12))(i => i);
let eleven = (o => o.a(11))({ a: function(n) { return n; } });
// missing arguments
(function(x, undefined) { return x; })(42);
((x, y, z) => 42)();


//// [contextuallyTypedIife.js]
Expand Down Expand Up @@ -102,3 +105,6 @@ let eleven = (o => o.a(11))({ a: function(n) { return n; } });
// contextually typed parameters.
var twelve = (function (f) { return f(12); })(function (i) { return i; });
var eleven = (function (o) { return o.a(11); })({ a: function (n) { return n; } });
// missing arguments
(function (x, undefined) { return x; })(42);
(function (x, y, z) { return 42; })();
11 changes: 11 additions & 0 deletions tests/baselines/reference/contextuallyTypedIife.symbols
Original file line number Diff line number Diff line change
Expand Up @@ -119,3 +119,14 @@ let eleven = (o => o.a(11))({ a: function(n) { return n; } });
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 28, 42))
>n : Symbol(n, Decl(contextuallyTypedIife.ts, 28, 42))

// missing arguments
(function(x, undefined) { return x; })(42);
>x : Symbol(x, Decl(contextuallyTypedIife.ts, 30, 10))
>undefined : Symbol(undefined, Decl(contextuallyTypedIife.ts, 30, 12))
>x : Symbol(x, Decl(contextuallyTypedIife.ts, 30, 10))

((x, y, z) => 42)();
>x : Symbol(x, Decl(contextuallyTypedIife.ts, 31, 2))
>y : Symbol(y, Decl(contextuallyTypedIife.ts, 31, 4))
>z : Symbol(z, Decl(contextuallyTypedIife.ts, 31, 7))

19 changes: 19 additions & 0 deletions tests/baselines/reference/contextuallyTypedIife.types
Original file line number Diff line number Diff line change
Expand Up @@ -250,3 +250,22 @@ let eleven = (o => o.a(11))({ a: function(n) { return n; } });
>n : any
>n : any

// missing arguments
(function(x, undefined) { return x; })(42);
>(function(x, undefined) { return x; })(42) : number
>(function(x, undefined) { return x; }) : (x: number, undefined: any) => number
>function(x, undefined) { return x; } : (x: number, undefined: any) => number
>x : number
>undefined : any
>x : number
>42 : 42

((x, y, z) => 42)();
>((x, y, z) => 42)() : number
>((x, y, z) => 42) : (x: any, y: any, z: any) => number
>(x, y, z) => 42 : (x: any, y: any, z: any) => number
>x : any
>y : any
>z : any
>42 : 42

110 changes: 110 additions & 0 deletions tests/baselines/reference/contextuallyTypedIifeStrict.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,110 @@
//// [contextuallyTypedIifeStrict.ts]
// arrow
(jake => { })("build");
// function expression
(function (cats) { })("lol");
// Lots of Irritating Superfluous Parentheses
(function (x) { } ("!"));
((((function (y) { }))))("-");
// multiple arguments
((a, b, c) => { })("foo", 101, false);
// default parameters
((m = 10) => m + 1)(12);
((n = 10) => n + 1)();
// optional parameters
((j?) => j + 1)(12);
((k?) => k + 1)();
((l, o?) => l + o)(12); // o should be any
// rest parameters
((...numbers) => numbers.every(n => n > 0))(5,6,7);
((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
((...noNumbers) => noNumbers.some(n => n > 0))();
((first, ...rest) => first ? [] : rest.map(n => n > 0))(8,9,10);
// destructuring parameters (with defaults too!)
(({ q }) => q)({ q : 13 });
(({ p = 14 }) => p)({ p : 15 });
(({ r = 17 } = { r: 18 }) => r)({r : 19});
(({ u = 22 } = { u: 23 }) => u)();
// contextually typed parameters.
let twelve = (f => f(12))(i => i);
let eleven = (o => o.a(11))({ a: function(n) { return n; } });
// missing arguments
(function(x, undefined) { return x; })(42);
((x, y, z) => 42)();


//// [contextuallyTypedIifeStrict.js]
// arrow
(function (jake) { })("build");
// function expression
(function (cats) { })("lol");
// Lots of Irritating Superfluous Parentheses
(function (x) { }("!"));
((((function (y) { }))))("-");
// multiple arguments
(function (a, b, c) { })("foo", 101, false);
// default parameters
(function (m) {
if (m === void 0) { m = 10; }
return m + 1;
})(12);
(function (n) {
if (n === void 0) { n = 10; }
return n + 1;
})();
// optional parameters
(function (j) { return j + 1; })(12);
(function (k) { return k + 1; })();
(function (l, o) { return l + o; })(12); // o should be any
// rest parameters
(function () {
var numbers = [];
for (var _i = 0; _i < arguments.length; _i++) {
numbers[_i] = arguments[_i];
}
return numbers.every(function (n) { return n > 0; });
})(5, 6, 7);
(function () {
var mixed = [];
for (var _i = 0; _i < arguments.length; _i++) {
mixed[_i] = arguments[_i];
}
return mixed.every(function (n) { return !!n; });
})(5, 'oops', 'oh no');
(function () {
var noNumbers = [];
for (var _i = 0; _i < arguments.length; _i++) {
noNumbers[_i] = arguments[_i];
}
return noNumbers.some(function (n) { return n > 0; });
})();
(function (first) {
var rest = [];
for (var _i = 1; _i < arguments.length; _i++) {
rest[_i - 1] = arguments[_i];
}
return first ? [] : rest.map(function (n) { return n > 0; });
})(8, 9, 10);
// destructuring parameters (with defaults too!)
(function (_a) {
var q = _a.q;
return q;
})({ q: 13 });
(function (_a) {
var _b = _a.p, p = _b === void 0 ? 14 : _b;
return p;
})({ p: 15 });
(function (_a) {
var _b = (_a === void 0 ? { r: 18 } : _a).r, r = _b === void 0 ? 17 : _b;
return r;
})({ r: 19 });
(function (_a) {
var _b = (_a === void 0 ? { u: 23 } : _a).u, u = _b === void 0 ? 22 : _b;
return u;
})();
// contextually typed parameters.
var twelve = (function (f) { return f(12); })(function (i) { return i; });
var eleven = (function (o) { return o.a(11); })({ a: function (n) { return n; } });
// missing arguments
(function (x, undefined) { return x; })(42);
(function (x, y, z) { return 42; })();
132 changes: 132 additions & 0 deletions tests/baselines/reference/contextuallyTypedIifeStrict.symbols
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
=== tests/cases/conformance/expressions/functions/contextuallyTypedIifeStrict.ts ===
// arrow
(jake => { })("build");
>jake : Symbol(jake, Decl(contextuallyTypedIifeStrict.ts, 1, 1))

// function expression
(function (cats) { })("lol");
>cats : Symbol(cats, Decl(contextuallyTypedIifeStrict.ts, 3, 11))

// Lots of Irritating Superfluous Parentheses
(function (x) { } ("!"));
>x : Symbol(x, Decl(contextuallyTypedIifeStrict.ts, 5, 11))

((((function (y) { }))))("-");
>y : Symbol(y, Decl(contextuallyTypedIifeStrict.ts, 6, 14))

// multiple arguments
((a, b, c) => { })("foo", 101, false);
>a : Symbol(a, Decl(contextuallyTypedIifeStrict.ts, 8, 2))
>b : Symbol(b, Decl(contextuallyTypedIifeStrict.ts, 8, 4))
>c : Symbol(c, Decl(contextuallyTypedIifeStrict.ts, 8, 7))

// default parameters
((m = 10) => m + 1)(12);
>m : Symbol(m, Decl(contextuallyTypedIifeStrict.ts, 10, 2))
>m : Symbol(m, Decl(contextuallyTypedIifeStrict.ts, 10, 2))

((n = 10) => n + 1)();
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 11, 2))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 11, 2))

// optional parameters
((j?) => j + 1)(12);
>j : Symbol(j, Decl(contextuallyTypedIifeStrict.ts, 13, 2))
>j : Symbol(j, Decl(contextuallyTypedIifeStrict.ts, 13, 2))

((k?) => k + 1)();
>k : Symbol(k, Decl(contextuallyTypedIifeStrict.ts, 14, 2))
>k : Symbol(k, Decl(contextuallyTypedIifeStrict.ts, 14, 2))

((l, o?) => l + o)(12); // o should be any
>l : Symbol(l, Decl(contextuallyTypedIifeStrict.ts, 15, 2))
>o : Symbol(o, Decl(contextuallyTypedIifeStrict.ts, 15, 4))
>l : Symbol(l, Decl(contextuallyTypedIifeStrict.ts, 15, 2))
>o : Symbol(o, Decl(contextuallyTypedIifeStrict.ts, 15, 4))

// rest parameters
((...numbers) => numbers.every(n => n > 0))(5,6,7);
>numbers : Symbol(numbers, Decl(contextuallyTypedIifeStrict.ts, 17, 2))
>numbers.every : Symbol(Array.every, Decl(lib.d.ts, --, --))
>numbers : Symbol(numbers, Decl(contextuallyTypedIifeStrict.ts, 17, 2))
>every : Symbol(Array.every, Decl(lib.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 17, 31))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 17, 31))

((...mixed) => mixed.every(n => !!n))(5,'oops','oh no');
>mixed : Symbol(mixed, Decl(contextuallyTypedIifeStrict.ts, 18, 2))
>mixed.every : Symbol(Array.every, Decl(lib.d.ts, --, --))
>mixed : Symbol(mixed, Decl(contextuallyTypedIifeStrict.ts, 18, 2))
>every : Symbol(Array.every, Decl(lib.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 18, 27))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 18, 27))

((...noNumbers) => noNumbers.some(n => n > 0))();
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIifeStrict.ts, 19, 2))
>noNumbers.some : Symbol(Array.some, Decl(lib.d.ts, --, --))
>noNumbers : Symbol(noNumbers, Decl(contextuallyTypedIifeStrict.ts, 19, 2))
>some : Symbol(Array.some, Decl(lib.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 19, 34))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 19, 34))

((first, ...rest) => first ? [] : rest.map(n => n > 0))(8,9,10);
>first : Symbol(first, Decl(contextuallyTypedIifeStrict.ts, 20, 2))
>rest : Symbol(rest, Decl(contextuallyTypedIifeStrict.ts, 20, 8))
>first : Symbol(first, Decl(contextuallyTypedIifeStrict.ts, 20, 2))
>rest.map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>rest : Symbol(rest, Decl(contextuallyTypedIifeStrict.ts, 20, 8))
>map : Symbol(Array.map, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 20, 43))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 20, 43))

// destructuring parameters (with defaults too!)
(({ q }) => q)({ q : 13 });
>q : Symbol(q, Decl(contextuallyTypedIifeStrict.ts, 22, 3))
>q : Symbol(q, Decl(contextuallyTypedIifeStrict.ts, 22, 3))
>q : Symbol(q, Decl(contextuallyTypedIifeStrict.ts, 22, 16))

(({ p = 14 }) => p)({ p : 15 });
>p : Symbol(p, Decl(contextuallyTypedIifeStrict.ts, 23, 3))
>p : Symbol(p, Decl(contextuallyTypedIifeStrict.ts, 23, 3))
>p : Symbol(p, Decl(contextuallyTypedIifeStrict.ts, 23, 21))

(({ r = 17 } = { r: 18 }) => r)({r : 19});
>r : Symbol(r, Decl(contextuallyTypedIifeStrict.ts, 24, 3))
>r : Symbol(r, Decl(contextuallyTypedIifeStrict.ts, 24, 16))
>r : Symbol(r, Decl(contextuallyTypedIifeStrict.ts, 24, 3))
>r : Symbol(r, Decl(contextuallyTypedIifeStrict.ts, 24, 33))

(({ u = 22 } = { u: 23 }) => u)();
>u : Symbol(u, Decl(contextuallyTypedIifeStrict.ts, 25, 3))
>u : Symbol(u, Decl(contextuallyTypedIifeStrict.ts, 25, 16))
>u : Symbol(u, Decl(contextuallyTypedIifeStrict.ts, 25, 3))

// contextually typed parameters.
let twelve = (f => f(12))(i => i);
>twelve : Symbol(twelve, Decl(contextuallyTypedIifeStrict.ts, 27, 3))
>f : Symbol(f, Decl(contextuallyTypedIifeStrict.ts, 27, 14))
>f : Symbol(f, Decl(contextuallyTypedIifeStrict.ts, 27, 14))
>i : Symbol(i, Decl(contextuallyTypedIifeStrict.ts, 27, 26))
>i : Symbol(i, Decl(contextuallyTypedIifeStrict.ts, 27, 26))

let eleven = (o => o.a(11))({ a: function(n) { return n; } });
>eleven : Symbol(eleven, Decl(contextuallyTypedIifeStrict.ts, 28, 3))
>o : Symbol(o, Decl(contextuallyTypedIifeStrict.ts, 28, 14))
>o.a : Symbol(a, Decl(contextuallyTypedIifeStrict.ts, 28, 29))
>o : Symbol(o, Decl(contextuallyTypedIifeStrict.ts, 28, 14))
>a : Symbol(a, Decl(contextuallyTypedIifeStrict.ts, 28, 29))
>a : Symbol(a, Decl(contextuallyTypedIifeStrict.ts, 28, 29))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 28, 42))
>n : Symbol(n, Decl(contextuallyTypedIifeStrict.ts, 28, 42))

// missing arguments
(function(x, undefined) { return x; })(42);
>x : Symbol(x, Decl(contextuallyTypedIifeStrict.ts, 30, 10))
>undefined : Symbol(undefined, Decl(contextuallyTypedIifeStrict.ts, 30, 12))
>x : Symbol(x, Decl(contextuallyTypedIifeStrict.ts, 30, 10))

((x, y, z) => 42)();
>x : Symbol(x, Decl(contextuallyTypedIifeStrict.ts, 31, 2))
>y : Symbol(y, Decl(contextuallyTypedIifeStrict.ts, 31, 4))
>z : Symbol(z, Decl(contextuallyTypedIifeStrict.ts, 31, 7))

Loading