Track parameter references errors in resolve name rather than secondary pass (#30349)

This commit is contained in:
Wesley Wigham
2019-04-23 13:46:19 -07:00
committed by GitHub
parent 84b8ab816c
commit b02b823f03
13 changed files with 430 additions and 150 deletions

View File

@@ -1292,6 +1292,8 @@ namespace ts {
let lastLocation: Node | undefined;
let lastSelfReferenceLocation: Node | undefined;
let propertyWithInvalidInitializer: Node | undefined;
let associatedDeclarationForContainingInitializer: ParameterDeclaration | BindingElement | undefined;
let withinDeferredContext = false;
const errorLocation = location;
let grandparent: Node;
let isInExternalModule = false;
@@ -1352,6 +1354,7 @@ namespace ts {
}
}
}
withinDeferredContext = withinDeferredContext || getIsDeferredContext(location, lastLocation);
switch (location.kind) {
case SyntaxKind.SourceFile:
if (!isExternalOrCommonJsModule(<SourceFile>location)) break;
@@ -1547,6 +1550,19 @@ namespace ts {
// js type aliases do not resolve names from their host, so skip past it
location = getJSDocHost(location);
break;
case SyntaxKind.Parameter:
if (lastLocation && lastLocation === (location as ParameterDeclaration).initializer) {
associatedDeclarationForContainingInitializer = location as ParameterDeclaration;
}
break;
case SyntaxKind.BindingElement:
if (lastLocation && lastLocation === (location as BindingElement).initializer) {
const root = getRootDeclaration(location);
if (root.kind === SyntaxKind.Parameter) {
associatedDeclarationForContainingInitializer = location as BindingElement;
}
}
break;
}
if (isSelfReferenceLocation(location)) {
lastSelfReferenceLocation = location;
@@ -1651,10 +1667,42 @@ namespace ts {
errorOrSuggestion(!compilerOptions.allowUmdGlobalAccess, errorLocation!, Diagnostics._0_refers_to_a_UMD_global_but_the_current_file_is_a_module_Consider_adding_an_import_instead, unescapeLeadingUnderscores(name));
}
}
// If we're in a parameter initializer, we can't reference the values of the parameter whose initializer we're within or parameters to the right
if (result && associatedDeclarationForContainingInitializer && !withinDeferredContext && (meaning & SymbolFlags.Value) === SymbolFlags.Value) {
const candidate = getMergedSymbol(getLateBoundSymbol(result));
const root = (getRootDeclaration(associatedDeclarationForContainingInitializer) as ParameterDeclaration);
// A parameter initializer or binding pattern initializer within a parameter cannot refer to itself
if (candidate === getSymbolOfNode(associatedDeclarationForContainingInitializer)) {
error(errorLocation, Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, declarationNameToString(associatedDeclarationForContainingInitializer.name));
}
// And it cannot refer to any declarations which come after it
else if (candidate.valueDeclaration && candidate.valueDeclaration.pos > associatedDeclarationForContainingInitializer.pos && root.parent.locals && lookup(root.parent.locals, candidate.escapedName, meaning) === candidate) {
error(errorLocation, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(associatedDeclarationForContainingInitializer.name), declarationNameToString(<Identifier>errorLocation));
}
}
}
return result;
}
function getIsDeferredContext(location: Node, lastLocation: Node | undefined): boolean {
if (location.kind !== SyntaxKind.ArrowFunction && location.kind !== SyntaxKind.FunctionExpression) {
// initializers in instance property declaration of class like entities are executed in constructor and thus deferred
return isTypeQueryNode(location) || ((
isFunctionLikeDeclaration(location) ||
(location.kind === SyntaxKind.PropertyDeclaration && !hasModifier(location, ModifierFlags.Static))
) && (!lastLocation || lastLocation !== (location as FunctionLike | PropertyDeclaration).name)); // A name is evaluated within the enclosing scope - so it shouldn't count as deferred
}
if (lastLocation && lastLocation === (location as FunctionExpression | ArrowFunction).name) {
return false;
}
// generator functions and async functions are not inlined in control flow when immediately invoked
if ((location as FunctionExpression | ArrowFunction).asteriskToken || hasModifier(location, ModifierFlags.Async)) {
return true;
}
return !getImmediatelyInvokedFunctionExpression(location);
}
function isSelfReferenceLocation(node: Node): boolean {
switch (node.kind) {
case SyntaxKind.FunctionDeclaration:
@@ -26304,74 +26352,6 @@ namespace ts {
}
}
// Check that a parameter initializer contains no references to parameters declared to the right of itself
function checkParameterInitializer(node: HasExpressionInitializer): void {
if (getRootDeclaration(node).kind !== SyntaxKind.Parameter) {
return;
}
const func = getContainingFunction(node);
visit(node.initializer!);
function visit(n: Node): void {
if (isTypeNode(n) || isDeclarationName(n)) {
// do not dive in types
// skip declaration names (i.e. in object literal expressions)
return;
}
if (n.kind === SyntaxKind.PropertyAccessExpression) {
// skip property names in property access expression
return visit((<PropertyAccessExpression>n).expression);
}
else if (n.kind === SyntaxKind.Identifier) {
// check FunctionLikeDeclaration.locals (stores parameters\function local variable)
// if it contains entry with a specified name
const symbol = resolveName(n, (<Identifier>n).escapedText, SymbolFlags.Value | SymbolFlags.Alias, /*nameNotFoundMessage*/undefined, /*nameArg*/undefined, /*isUse*/ false);
if (!symbol || symbol === unknownSymbol || !symbol.valueDeclaration) {
return;
}
if (symbol.valueDeclaration === node) {
error(n, Diagnostics.Parameter_0_cannot_be_referenced_in_its_initializer, declarationNameToString(node.name));
return;
}
// locals map for function contain both parameters and function locals
// so we need to do a bit of extra work to check if reference is legal
const enclosingContainer = getEnclosingBlockScopeContainer(symbol.valueDeclaration);
if (enclosingContainer === func) {
if (symbol.valueDeclaration.kind === SyntaxKind.Parameter ||
symbol.valueDeclaration.kind === SyntaxKind.BindingElement) {
// it is ok to reference parameter in initializer if either
// - parameter is located strictly on the left of current parameter declaration
if (symbol.valueDeclaration.pos < node.pos) {
return;
}
// - parameter is wrapped in function-like entity
if (findAncestor(
n,
current => {
if (current === node.initializer) {
return "quit";
}
return isFunctionLike(current.parent) ||
// computed property names/initializers in instance property declaration of class like entities
// are executed in constructor and thus deferred
(current.parent.kind === SyntaxKind.PropertyDeclaration &&
!(hasModifier(current.parent, ModifierFlags.Static)) &&
isClassLike(current.parent.parent));
})) {
return;
}
// fall through to report error
}
error(n, Diagnostics.Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it, declarationNameToString(node.name), declarationNameToString(<Identifier>n));
}
}
else {
return forEachChild(n, visit);
}
}
}
function convertAutoToAny(type: Type) {
return type === autoType ? anyType : type === autoArrayType ? anyArrayType : type;
}
@@ -26448,7 +26428,6 @@ namespace ts {
else {
checkTypeAssignableToAndOptionallyElaborate(initializerType, getWidenedTypeForVariableLikeDeclaration(node), node, node.initializer);
}
checkParameterInitializer(node);
}
return;
}
@@ -26465,7 +26444,6 @@ namespace ts {
hasEntries(symbol.exports);
if (!isJSObjectLiteralInitializer && node.parent.parent.kind !== SyntaxKind.ForInStatement) {
checkTypeAssignableToAndOptionallyElaborate(checkExpressionCached(initializer), type, node, initializer, /*headMessage*/ undefined);
checkParameterInitializer(node);
}
}
if (symbol.declarations.length > 1) {

View File

@@ -0,0 +1,52 @@
tests/cases/compiler/capturedParametersInInitializers1.ts(18,20): error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it.
tests/cases/compiler/capturedParametersInInitializers1.ts(22,26): error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it.
tests/cases/compiler/capturedParametersInInitializers1.ts(38,21): error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it.
==== tests/cases/compiler/capturedParametersInInitializers1.ts (3 errors) ====
// ok - usage is deferred
function foo1(y = class {c = x}, x = 1) {
new y().c;
}
// ok - used in file
function foo2(y = function(x: typeof z) {}, z = 1) {
}
// ok -used in type
let a;
function foo3(y = { x: <typeof z>a }, z = 1) {
}
// error - used before declaration
function foo4(y = {z}, z = 1) {
~
!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it.
}
// error - used before declaration, IIFEs are inlined
function foo5(y = (() => z)(), z = 1) {
~
!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it.
}
// ok - IIFE inside another function
function foo6(y = () => (() => z)(), z = 1) {
}
// ok - used inside immediately invoked generator function
function foo7(y = (function*() {yield z})(), z = 1) {
}
// ok - used inside immediately invoked async function
function foo8(y = (async () => z)(), z = 1) {
}
// error - used as computed name of method
function foo9(y = {[z]() { return z; }}, z = 1) {
~
!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it.
}

View File

@@ -13,28 +13,72 @@ function foo2(y = function(x: typeof z) {}, z = 1) {
let a;
function foo3(y = { x: <typeof z>a }, z = 1) {
}
}
// error - used before declaration
function foo4(y = {z}, z = 1) {
}
// error - used before declaration, IIFEs are inlined
function foo5(y = (() => z)(), z = 1) {
}
// ok - IIFE inside another function
function foo6(y = () => (() => z)(), z = 1) {
}
// ok - used inside immediately invoked generator function
function foo7(y = (function*() {yield z})(), z = 1) {
}
// ok - used inside immediately invoked async function
function foo8(y = (async () => z)(), z = 1) {
}
// error - used as computed name of method
function foo9(y = {[z]() { return z; }}, z = 1) {
}
//// [capturedParametersInInitializers1.js]
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
return new (P || (P = Promise))(function (resolve, reject) {
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
function step(result) { result.done ? resolve(result.value) : new P(function (resolve) { resolve(result.value); }).then(fulfilled, rejected); }
step((generator = generator.apply(thisArg, _arguments || [])).next());
});
};
// ok - usage is deferred
function foo1(y, x) {
if (y === void 0) { y = /** @class */ (function () {
function class_1() {
this.c = x;
}
return class_1;
}()); }
if (x === void 0) { x = 1; }
function foo1(y = class {
constructor() {
this.c = x;
}
}, x = 1) {
new y().c;
}
// ok - used in file
function foo2(y, z) {
if (y === void 0) { y = function (x) { }; }
if (z === void 0) { z = 1; }
function foo2(y = function (x) { }, z = 1) {
}
// ok -used in type
var a;
function foo3(y, z) {
if (y === void 0) { y = { x: a }; }
if (z === void 0) { z = 1; }
let a;
function foo3(y = { x: a }, z = 1) {
}
// error - used before declaration
function foo4(y = { z }, z = 1) {
}
// error - used before declaration, IIFEs are inlined
function foo5(y = (() => z)(), z = 1) {
}
// ok - IIFE inside another function
function foo6(y = () => (() => z)(), z = 1) {
}
// ok - used inside immediately invoked generator function
function foo7(y = (function* () { yield z; })(), z = 1) {
}
// ok - used inside immediately invoked async function
function foo8(y = (() => __awaiter(this, void 0, void 0, function* () { return z; }))(), z = 1) {
}
// error - used as computed name of method
function foo9(y = { [z]() { return z; } }, z = 1) {
}

View File

@@ -36,3 +36,54 @@ function foo3(y = { x: <typeof z>a }, z = 1) {
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 12, 37))
}
// error - used before declaration
function foo4(y = {z}, z = 1) {
>foo4 : Symbol(foo4, Decl(capturedParametersInInitializers1.ts, 14, 1))
>y : Symbol(y, Decl(capturedParametersInInitializers1.ts, 17, 14))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 17, 19))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 17, 22))
}
// error - used before declaration, IIFEs are inlined
function foo5(y = (() => z)(), z = 1) {
>foo5 : Symbol(foo5, Decl(capturedParametersInInitializers1.ts, 18, 1))
>y : Symbol(y, Decl(capturedParametersInInitializers1.ts, 21, 14))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 21, 30))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 21, 30))
}
// ok - IIFE inside another function
function foo6(y = () => (() => z)(), z = 1) {
>foo6 : Symbol(foo6, Decl(capturedParametersInInitializers1.ts, 22, 1))
>y : Symbol(y, Decl(capturedParametersInInitializers1.ts, 25, 14))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 25, 36))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 25, 36))
}
// ok - used inside immediately invoked generator function
function foo7(y = (function*() {yield z})(), z = 1) {
>foo7 : Symbol(foo7, Decl(capturedParametersInInitializers1.ts, 26, 1))
>y : Symbol(y, Decl(capturedParametersInInitializers1.ts, 29, 14))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 29, 44))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 29, 44))
}
// ok - used inside immediately invoked async function
function foo8(y = (async () => z)(), z = 1) {
>foo8 : Symbol(foo8, Decl(capturedParametersInInitializers1.ts, 30, 1))
>y : Symbol(y, Decl(capturedParametersInInitializers1.ts, 33, 14))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 33, 36))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 33, 36))
}
// error - used as computed name of method
function foo9(y = {[z]() { return z; }}, z = 1) {
>foo9 : Symbol(foo9, Decl(capturedParametersInInitializers1.ts, 34, 1))
>y : Symbol(y, Decl(capturedParametersInInitializers1.ts, 37, 14))
>[z] : Symbol([z], Decl(capturedParametersInInitializers1.ts, 37, 19))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 37, 40))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 37, 40))
>z : Symbol(z, Decl(capturedParametersInInitializers1.ts, 37, 40))
}

View File

@@ -44,3 +44,76 @@ function foo3(y = { x: <typeof z>a }, z = 1) {
>1 : 1
}
// error - used before declaration
function foo4(y = {z}, z = 1) {
>foo4 : (y?: { z: number; }, z?: number) => void
>y : { z: number; }
>{z} : { z: number; }
>z : number
>z : number
>1 : 1
}
// error - used before declaration, IIFEs are inlined
function foo5(y = (() => z)(), z = 1) {
>foo5 : (y?: number, z?: number) => void
>y : number
>(() => z)() : number
>(() => z) : () => number
>() => z : () => number
>z : number
>z : number
>1 : 1
}
// ok - IIFE inside another function
function foo6(y = () => (() => z)(), z = 1) {
>foo6 : (y?: () => number, z?: number) => void
>y : () => number
>() => (() => z)() : () => number
>(() => z)() : number
>(() => z) : () => number
>() => z : () => number
>z : number
>z : number
>1 : 1
}
// ok - used inside immediately invoked generator function
function foo7(y = (function*() {yield z})(), z = 1) {
>foo7 : (y?: IterableIterator<number>, z?: number) => void
>y : IterableIterator<number>
>(function*() {yield z})() : IterableIterator<number>
>(function*() {yield z}) : () => IterableIterator<number>
>function*() {yield z} : () => IterableIterator<number>
>yield z : any
>z : number
>z : number
>1 : 1
}
// ok - used inside immediately invoked async function
function foo8(y = (async () => z)(), z = 1) {
>foo8 : (y?: Promise<number>, z?: number) => void
>y : Promise<number>
>(async () => z)() : Promise<number>
>(async () => z) : () => Promise<number>
>async () => z : () => Promise<number>
>z : number
>z : number
>1 : 1
}
// error - used as computed name of method
function foo9(y = {[z]() { return z; }}, z = 1) {
>foo9 : (y?: { [x: number]: () => number; }, z?: number) => void
>y : { [x: number]: () => number; }
>{[z]() { return z; }} : { [x: number]: () => number; }
>[z] : () => number
>z : number
>z : number
>z : number
>1 : 1
}

View File

@@ -1,14 +1,32 @@
tests/cases/compiler/capturedParametersInInitializers2.ts(1,36): error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it.
tests/cases/compiler/capturedParametersInInitializers2.ts(4,26): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/compiler/capturedParametersInInitializers2.ts(3,20): error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it.
tests/cases/compiler/capturedParametersInInitializers2.ts(4,14): error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it.
tests/cases/compiler/capturedParametersInInitializers2.ts(6,10): error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it.
tests/cases/compiler/capturedParametersInInitializers2.ts(13,26): error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
tests/cases/compiler/capturedParametersInInitializers2.ts(13,27): error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it.
==== tests/cases/compiler/capturedParametersInInitializers2.ts (2 errors) ====
function foo(y = class {static c = x}, x = 1) {
~
==== tests/cases/compiler/capturedParametersInInitializers2.ts (5 errors) ====
function foo(
y = class {
static c = x;
~
!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it.
get [x]() {return x;}
~
!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it.
constructor() { x; }
[z]() { return z; }
~
!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'z' declared after it.
},
x = 1,
z = 2
) {
y.c
}
function foo2(y = class {[x] = x}, x = 1) {
~~~
!!! error TS1166: A computed property name in a class property declaration must refer to an expression whose type is a literal type or a 'unique symbol' type.
~
!!! error TS2373: Initializer of parameter 'y' cannot reference identifier 'x' declared after it.
}

View File

@@ -1,20 +1,37 @@
//// [capturedParametersInInitializers2.ts]
function foo(y = class {static c = x}, x = 1) {
function foo(
y = class {
static c = x;
get [x]() {return x;}
constructor() { x; }
[z]() { return z; }
},
x = 1,
z = 2
) {
y.c
}
function foo2(y = class {[x] = x}, x = 1) {
}
//// [capturedParametersInInitializers2.js]
function foo(y, x) {
function foo(y, x, z) {
if (y === void 0) { y = (_a = /** @class */ (function () {
function class_1() {
x;
}
Object.defineProperty(class_1.prototype, x, {
get: function () { return x; },
enumerable: true,
configurable: true
});
class_1.prototype[z] = function () { return z; };
return class_1;
}()),
_a.c = x,
_a); }
if (x === void 0) { x = 1; }
if (z === void 0) { z = 2; }
var _a;
y.c;
}

View File

@@ -1,21 +1,45 @@
=== tests/cases/compiler/capturedParametersInInitializers2.ts ===
function foo(y = class {static c = x}, x = 1) {
function foo(
>foo : Symbol(foo, Decl(capturedParametersInInitializers2.ts, 0, 0))
>y : Symbol(y, Decl(capturedParametersInInitializers2.ts, 0, 13))
>c : Symbol((Anonymous class).c, Decl(capturedParametersInInitializers2.ts, 0, 24))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 0, 38))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 0, 38))
y.c
>y.c : Symbol((Anonymous class).c, Decl(capturedParametersInInitializers2.ts, 0, 24))
y = class {
>y : Symbol(y, Decl(capturedParametersInInitializers2.ts, 0, 13))
>c : Symbol((Anonymous class).c, Decl(capturedParametersInInitializers2.ts, 0, 24))
static c = x;
>c : Symbol((Anonymous class).c, Decl(capturedParametersInInitializers2.ts, 1, 15))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 6, 6))
get [x]() {return x;}
>[x] : Symbol((Anonymous class)[x], Decl(capturedParametersInInitializers2.ts, 2, 21))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 6, 6))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 6, 6))
constructor() { x; }
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 6, 6))
[z]() { return z; }
>[z] : Symbol((Anonymous class)[z], Decl(capturedParametersInInitializers2.ts, 4, 28))
>z : Symbol(z, Decl(capturedParametersInInitializers2.ts, 7, 10))
>z : Symbol(z, Decl(capturedParametersInInitializers2.ts, 7, 10))
},
x = 1,
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 6, 6))
z = 2
>z : Symbol(z, Decl(capturedParametersInInitializers2.ts, 7, 10))
) {
y.c
>y.c : Symbol((Anonymous class).c, Decl(capturedParametersInInitializers2.ts, 1, 15))
>y : Symbol(y, Decl(capturedParametersInInitializers2.ts, 0, 13))
>c : Symbol((Anonymous class).c, Decl(capturedParametersInInitializers2.ts, 1, 15))
}
function foo2(y = class {[x] = x}, x = 1) {
>foo2 : Symbol(foo2, Decl(capturedParametersInInitializers2.ts, 2, 1))
>y : Symbol(y, Decl(capturedParametersInInitializers2.ts, 3, 14))
>[x] : Symbol((Anonymous class)[x], Decl(capturedParametersInInitializers2.ts, 3, 25))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 3, 34))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 3, 34))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 3, 34))
>foo2 : Symbol(foo2, Decl(capturedParametersInInitializers2.ts, 11, 1))
>y : Symbol(y, Decl(capturedParametersInInitializers2.ts, 12, 14))
>[x] : Symbol((Anonymous class)[x], Decl(capturedParametersInInitializers2.ts, 12, 25))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 12, 34))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 12, 34))
>x : Symbol(x, Decl(capturedParametersInInitializers2.ts, 12, 34))
}

View File

@@ -1,13 +1,38 @@
=== tests/cases/compiler/capturedParametersInInitializers2.ts ===
function foo(y = class {static c = x}, x = 1) {
>foo : (y?: typeof (Anonymous class), x?: number) => void
function foo(
>foo : (y?: typeof (Anonymous class), x?: number, z?: number) => void
y = class {
>y : typeof (Anonymous class)
>class {static c = x} : typeof (Anonymous class)
>class { static c = x; get [x]() {return x;} constructor() { x; } [z]() { return z; } } : typeof (Anonymous class)
static c = x;
>c : number
>x : number
get [x]() {return x;}
>[x] : number
>x : number
>x : number
constructor() { x; }
>x : number
[z]() { return z; }
>[z] : () => number
>z : number
>z : number
},
x = 1,
>x : number
>1 : 1
z = 2
>z : number
>2 : 2
) {
y.c
>y.c : number
>y : typeof (Anonymous class)

View File

@@ -1,34 +0,0 @@
tests/cases/compiler/functionLikeInParameterInitializer.ts(2,34): error TS2373: Initializer of parameter 'func' cannot reference identifier 'foo' declared after it.
tests/cases/compiler/functionLikeInParameterInitializer.ts(6,44): error TS2373: Initializer of parameter 'func' cannot reference identifier 'foo' declared after it.
tests/cases/compiler/functionLikeInParameterInitializer.ts(11,50): error TS2373: Initializer of parameter 'func' cannot reference identifier 'foo' declared after it.
tests/cases/compiler/functionLikeInParameterInitializer.ts(16,41): error TS2373: Initializer of parameter 'func' cannot reference identifier 'foo' declared after it.
==== tests/cases/compiler/functionLikeInParameterInitializer.ts (4 errors) ====
// error
export function bar(func = () => foo) {
~~~
!!! error TS2373: Initializer of parameter 'func' cannot reference identifier 'foo' declared after it.
let foo = "in";
}
// error
export function baz1(func = { f() { return foo } }) {
~~~
!!! error TS2373: Initializer of parameter 'func' cannot reference identifier 'foo' declared after it.
let foo = "in";
}
// error
export function baz2(func = function () { return foo }) {
~~~
!!! error TS2373: Initializer of parameter 'func' cannot reference identifier 'foo' declared after it.
let foo = "in";
}
// error
export function baz3(func = class { x = foo }) {
~~~
!!! error TS2373: Initializer of parameter 'func' cannot reference identifier 'foo' declared after it.
let foo = "in";
}

View File

@@ -1,12 +1,11 @@
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(3,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(8,27): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(13,20): error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(21,18): error TS2372: Parameter 'a' cannot be referenced in its initializer.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(25,22): error TS2372: Parameter 'async' cannot be referenced in its initializer.
tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(29,15): error TS2448: Block-scoped variable 'foo' used before its declaration.
==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts (6 errors) ====
==== tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts (5 errors) ====
let foo: string = "";
function f1 (bar = foo) { // unexpected compiler error; works at runtime
@@ -17,8 +16,6 @@ tests/cases/conformance/functions/parameterInitializersForwardReferencing1.ts(29
}
function f2 (bar = (baz = foo) => baz) { // unexpected compiler error; works at runtime
~~~
!!! error TS2373: Initializer of parameter 'bar' cannot reference identifier 'foo' declared after it.
var foo: number = 2;
return bar(); // returns 1
}

View File

@@ -1,3 +1,4 @@
// @target: es6
// ok - usage is deferred
function foo1(y = class {c = x}, x = 1) {
new y().c;
@@ -12,4 +13,28 @@ function foo2(y = function(x: typeof z) {}, z = 1) {
let a;
function foo3(y = { x: <typeof z>a }, z = 1) {
}
}
// error - used before declaration
function foo4(y = {z}, z = 1) {
}
// error - used before declaration, IIFEs are inlined
function foo5(y = (() => z)(), z = 1) {
}
// ok - IIFE inside another function
function foo6(y = () => (() => z)(), z = 1) {
}
// ok - used inside immediately invoked generator function
function foo7(y = (function*() {yield z})(), z = 1) {
}
// ok - used inside immediately invoked async function
function foo8(y = (async () => z)(), z = 1) {
}
// error - used as computed name of method
function foo9(y = {[z]() { return z; }}, z = 1) {
}

View File

@@ -1,4 +1,14 @@
function foo(y = class {static c = x}, x = 1) {
// @target: es5
function foo(
y = class {
static c = x;
get [x]() {return x;}
constructor() { x; }
[z]() { return z; }
},
x = 1,
z = 2
) {
y.c
}
function foo2(y = class {[x] = x}, x = 1) {