From e0a8af00a78d28c5b929835a5aceb623e032d6ea Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Tue, 17 Nov 2015 13:27:52 -0800 Subject: [PATCH] do not resolve parameters/type parameters if it is requested from restricted locations --- src/compiler/checker.ts | 36 ++++++++++--- ...rameterNamesInTypeParameterList.errors.txt | 44 +++++++++++++++ .../parameterNamesInTypeParameterList.js | 53 +++++++++++++++++++ ...ersAndParametersInComputedNames.errors.txt | 17 ++++++ ...eParametersAndParametersInComputedNames.js | 21 ++++++++ .../parameterNamesInTypeParameterList.ts | 23 ++++++++ ...eParametersAndParametersInComputedNames.ts | 8 +++ 7 files changed, 195 insertions(+), 7 deletions(-) create mode 100644 tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt create mode 100644 tests/baselines/reference/parameterNamesInTypeParameterList.js create mode 100644 tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt create mode 100644 tests/baselines/reference/typeParametersAndParametersInComputedNames.js create mode 100644 tests/cases/compiler/parameterNamesInTypeParameterList.ts create mode 100644 tests/cases/compiler/typeParametersAndParametersInComputedNames.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 378fd85265f..f9fd563b873 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -476,15 +476,37 @@ namespace ts { // Locals of a source file are not in scope (because they get merged into the global symbol table) if (location.locals && !isGlobalSourceFile(location)) { if (result = getSymbol(location.locals, name, meaning)) { - // Type parameters of a function are in scope in the entire function declaration, including the parameter - // list and return type. However, local types are only in scope in the function body. - if (!(meaning & SymbolFlags.Type) || - !(result.flags & (SymbolFlags.Type & ~SymbolFlags.TypeParameter)) || - !isFunctionLike(location) || - lastLocation === (location).body) { + let useResult = true; + if (isFunctionLike(location) && lastLocation && lastLocation !== (location).body) { + // symbol lookup restrictions for function-like declarations + // - Type parameters of a function are in scope in the entire function declaration, including the parameter + // list and return type. However, local types are only in scope in the function body. + // - parameters are only in the scope of function body + if (meaning & result.flags & SymbolFlags.Type) { + useResult = result.flags & SymbolFlags.TypeParameter + // type parameters are visible in parameter list, return type and type parameter list + ? lastLocation === (location).type || + lastLocation.kind === SyntaxKind.Parameter || + lastLocation.kind === SyntaxKind.TypeParameter + // local types not visible outside the function body + : false; + } + if (meaning & SymbolFlags.Value && result.flags & SymbolFlags.FunctionScopedVariable) { + // function scoped variables are visible only inside function body and parameter list + // technically here we might mix parameters and variables declared in function, + // however this case is detected separately when checking initializers of parameters + // to make sure that they reference no variables declared after them. + useResult = lastLocation === (location).type || + lastLocation.kind === SyntaxKind.Parameter; + } + } + + if (useResult) { break loop; } - result = undefined; + else { + result = undefined; + } } } switch (location.kind) { diff --git a/tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt b/tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt new file mode 100644 index 00000000000..54ddb963f94 --- /dev/null +++ b/tests/baselines/reference/parameterNamesInTypeParameterList.errors.txt @@ -0,0 +1,44 @@ +tests/cases/compiler/parameterNamesInTypeParameterList.ts(1,30): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(5,30): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(9,30): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(14,22): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(17,22): error TS2304: Cannot find name 'a'. +tests/cases/compiler/parameterNamesInTypeParameterList.ts(20,22): error TS2304: Cannot find name 'a'. + + +==== tests/cases/compiler/parameterNamesInTypeParameterList.ts (6 errors) ==== + function f0(a: T) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b; + } + + function f1({a}: {a:T}) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b; + } + + function f2([a]: T[]) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b; + } + + class A { + m0(a: T) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b + } + m1({a}: {a:T}) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b + } + m2([a]: T[]) { + ~ +!!! error TS2304: Cannot find name 'a'. + a.b + } + } \ No newline at end of file diff --git a/tests/baselines/reference/parameterNamesInTypeParameterList.js b/tests/baselines/reference/parameterNamesInTypeParameterList.js new file mode 100644 index 00000000000..2fbd7fad3cb --- /dev/null +++ b/tests/baselines/reference/parameterNamesInTypeParameterList.js @@ -0,0 +1,53 @@ +//// [parameterNamesInTypeParameterList.ts] +function f0(a: T) { + a.b; +} + +function f1({a}: {a:T}) { + a.b; +} + +function f2([a]: T[]) { + a.b; +} + +class A { + m0(a: T) { + a.b + } + m1({a}: {a:T}) { + a.b + } + m2([a]: T[]) { + a.b + } +} + +//// [parameterNamesInTypeParameterList.js] +function f0(a) { + a.b; +} +function f1(_a) { + var a = _a.a; + a.b; +} +function f2(_a) { + var a = _a[0]; + a.b; +} +var A = (function () { + function A() { + } + A.prototype.m0 = function (a) { + a.b; + }; + A.prototype.m1 = function (_a) { + var a = _a.a; + a.b; + }; + A.prototype.m2 = function (_a) { + var a = _a[0]; + a.b; + }; + return A; +})(); diff --git a/tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt b/tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt new file mode 100644 index 00000000000..872a0a10923 --- /dev/null +++ b/tests/baselines/reference/typeParametersAndParametersInComputedNames.errors.txt @@ -0,0 +1,17 @@ +tests/cases/compiler/typeParametersAndParametersInComputedNames.ts(6,10): error TS2304: Cannot find name 'T'. +tests/cases/compiler/typeParametersAndParametersInComputedNames.ts(6,13): error TS2304: Cannot find name 'a'. + + +==== tests/cases/compiler/typeParametersAndParametersInComputedNames.ts (2 errors) ==== + function foo(a: T) : string { + return ""; + } + + class A { + [foo(a)](a: T) { + ~ +!!! error TS2304: Cannot find name 'T'. + ~ +!!! error TS2304: Cannot find name 'a'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/typeParametersAndParametersInComputedNames.js b/tests/baselines/reference/typeParametersAndParametersInComputedNames.js new file mode 100644 index 00000000000..1cb53663fbd --- /dev/null +++ b/tests/baselines/reference/typeParametersAndParametersInComputedNames.js @@ -0,0 +1,21 @@ +//// [typeParametersAndParametersInComputedNames.ts] +function foo(a: T) : string { + return ""; +} + +class A { + [foo(a)](a: T) { + } +} + +//// [typeParametersAndParametersInComputedNames.js] +function foo(a) { + return ""; +} +var A = (function () { + function A() { + } + A.prototype[foo(a)] = function (a) { + }; + return A; +})(); diff --git a/tests/cases/compiler/parameterNamesInTypeParameterList.ts b/tests/cases/compiler/parameterNamesInTypeParameterList.ts new file mode 100644 index 00000000000..dba122db866 --- /dev/null +++ b/tests/cases/compiler/parameterNamesInTypeParameterList.ts @@ -0,0 +1,23 @@ +function f0(a: T) { + a.b; +} + +function f1({a}: {a:T}) { + a.b; +} + +function f2([a]: T[]) { + a.b; +} + +class A { + m0(a: T) { + a.b + } + m1({a}: {a:T}) { + a.b + } + m2([a]: T[]) { + a.b + } +} \ No newline at end of file diff --git a/tests/cases/compiler/typeParametersAndParametersInComputedNames.ts b/tests/cases/compiler/typeParametersAndParametersInComputedNames.ts new file mode 100644 index 00000000000..273dcb2a3ea --- /dev/null +++ b/tests/cases/compiler/typeParametersAndParametersInComputedNames.ts @@ -0,0 +1,8 @@ +function foo(a: T) : string { + return ""; +} + +class A { + [foo(a)](a: T) { + } +} \ No newline at end of file