do not resolve parameters/type parameters if it is requested from restricted locations

This commit is contained in:
Vladimir Matveev 2015-11-17 13:27:52 -08:00
parent 13bc120fe2
commit e0a8af00a7
7 changed files with 195 additions and 7 deletions

View file

@ -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 === (<FunctionLikeDeclaration>location).body) {
let useResult = true;
if (isFunctionLike(location) && lastLocation && lastLocation !== (<FunctionLikeDeclaration>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 === (<FunctionLikeDeclaration>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 === (<FunctionLikeDeclaration>location).type ||
lastLocation.kind === SyntaxKind.Parameter;
}
}
if (useResult) {
break loop;
}
result = undefined;
else {
result = undefined;
}
}
}
switch (location.kind) {

View file

@ -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<T extends typeof a>(a: T) {
~
!!! error TS2304: Cannot find name 'a'.
a.b;
}
function f1<T extends typeof a>({a}: {a:T}) {
~
!!! error TS2304: Cannot find name 'a'.
a.b;
}
function f2<T extends typeof a>([a]: T[]) {
~
!!! error TS2304: Cannot find name 'a'.
a.b;
}
class A {
m0<T extends typeof a>(a: T) {
~
!!! error TS2304: Cannot find name 'a'.
a.b
}
m1<T extends typeof a>({a}: {a:T}) {
~
!!! error TS2304: Cannot find name 'a'.
a.b
}
m2<T extends typeof a>([a]: T[]) {
~
!!! error TS2304: Cannot find name 'a'.
a.b
}
}

View file

@ -0,0 +1,53 @@
//// [parameterNamesInTypeParameterList.ts]
function f0<T extends typeof a>(a: T) {
a.b;
}
function f1<T extends typeof a>({a}: {a:T}) {
a.b;
}
function f2<T extends typeof a>([a]: T[]) {
a.b;
}
class A {
m0<T extends typeof a>(a: T) {
a.b
}
m1<T extends typeof a>({a}: {a:T}) {
a.b
}
m2<T extends typeof a>([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;
})();

View file

@ -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<T>(a: T) : string {
return "";
}
class A {
[foo<T>(a)]<T>(a: T) {
~
!!! error TS2304: Cannot find name 'T'.
~
!!! error TS2304: Cannot find name 'a'.
}
}

View file

@ -0,0 +1,21 @@
//// [typeParametersAndParametersInComputedNames.ts]
function foo<T>(a: T) : string {
return "";
}
class A {
[foo<T>(a)]<T>(a: T) {
}
}
//// [typeParametersAndParametersInComputedNames.js]
function foo(a) {
return "";
}
var A = (function () {
function A() {
}
A.prototype[foo(a)] = function (a) {
};
return A;
})();

View file

@ -0,0 +1,23 @@
function f0<T extends typeof a>(a: T) {
a.b;
}
function f1<T extends typeof a>({a}: {a:T}) {
a.b;
}
function f2<T extends typeof a>([a]: T[]) {
a.b;
}
class A {
m0<T extends typeof a>(a: T) {
a.b
}
m1<T extends typeof a>({a}: {a:T}) {
a.b
}
m2<T extends typeof a>([a]: T[]) {
a.b
}
}

View file

@ -0,0 +1,8 @@
function foo<T>(a: T) : string {
return "";
}
class A {
[foo<T>(a)]<T>(a: T) {
}
}