Merge pull request #6091 from Microsoft/circularTypeofIssue

Fix circular typeof issue in function/namespace combo
This commit is contained in:
Anders Hejlsberg 2015-12-14 10:54:22 -08:00
commit ef9f4043c4
5 changed files with 128 additions and 25 deletions

View file

@ -3608,37 +3608,29 @@ namespace ts {
function resolveAnonymousTypeMembers(type: AnonymousType) {
const symbol = type.symbol;
let members: SymbolTable;
let callSignatures: Signature[];
let constructSignatures: Signature[];
let stringIndexType: Type;
let numberIndexType: Type;
if (type.target) {
members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false);
callSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper, instantiateSignature);
constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature);
stringIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.String), type.mapper);
numberIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.Number), type.mapper);
const members = createInstantiatedSymbolTable(getPropertiesOfObjectType(type.target), type.mapper, /*mappingThisOnly*/ false);
const callSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Call), type.mapper, instantiateSignature);
const constructSignatures = instantiateList(getSignaturesOfType(type.target, SignatureKind.Construct), type.mapper, instantiateSignature);
const stringIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.String), type.mapper);
const numberIndexType = instantiateType(getIndexTypeOfType(type.target, IndexKind.Number), type.mapper);
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
}
else if (symbol.flags & SymbolFlags.TypeLiteral) {
members = symbol.members;
callSignatures = getSignaturesOfSymbol(members["__call"]);
constructSignatures = getSignaturesOfSymbol(members["__new"]);
stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String);
numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number);
const members = symbol.members;
const callSignatures = getSignaturesOfSymbol(members["__call"]);
const constructSignatures = getSignaturesOfSymbol(members["__new"]);
const stringIndexType = getIndexTypeOfSymbol(symbol, IndexKind.String);
const numberIndexType = getIndexTypeOfSymbol(symbol, IndexKind.Number);
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
}
else {
// Combinations of function, class, enum and module
members = emptySymbols;
callSignatures = emptyArray;
constructSignatures = emptyArray;
let members = emptySymbols;
let constructSignatures: Signature[] = emptyArray;
if (symbol.flags & SymbolFlags.HasExports) {
members = getExportsOfSymbol(symbol);
}
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
callSignatures = getSignaturesOfSymbol(symbol);
}
if (symbol.flags & SymbolFlags.Class) {
const classType = getDeclaredTypeOfClassOrInterface(symbol);
constructSignatures = getSignaturesOfSymbol(symbol.members["__constructor"]);
@ -3651,10 +3643,16 @@ namespace ts {
addInheritedMembers(members, getPropertiesOfObjectType(baseConstructorType));
}
}
stringIndexType = undefined;
numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined;
const numberIndexType = (symbol.flags & SymbolFlags.Enum) ? stringType : undefined;
setObjectTypeMembers(type, members, emptyArray, constructSignatures, undefined, numberIndexType);
// We resolve the members before computing the signatures because a signature may use
// typeof with a qualified name expression that circularly references the type we are
// in the process of resolving (see issue #6072). The temporarily empty signature list
// will never be observed because a qualified name can't reference signatures.
if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) {
(<ResolvedType>type).callSignatures = getSignaturesOfSymbol(symbol);
}
}
setObjectTypeMembers(type, members, callSignatures, constructSignatures, stringIndexType, numberIndexType);
}
function resolveStructuredTypeMembers(type: ObjectType): ResolvedType {

View file

@ -0,0 +1,40 @@
//// [circularTypeofWithFunctionModule.ts]
// Repro from #6072
class Foo {}
function maker (value: string): typeof maker.Bar {
return maker.Bar;
}
namespace maker {
export class Bar extends Foo {}
}
//// [circularTypeofWithFunctionModule.js]
// Repro from #6072
var __extends = (this && this.__extends) || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
};
var Foo = (function () {
function Foo() {
}
return Foo;
}());
function maker(value) {
return maker.Bar;
}
var maker;
(function (maker) {
var Bar = (function (_super) {
__extends(Bar, _super);
function Bar() {
_super.apply(this, arguments);
}
return Bar;
}(Foo));
maker.Bar = Bar;
})(maker || (maker = {}));

View file

@ -0,0 +1,27 @@
=== tests/cases/compiler/circularTypeofWithFunctionModule.ts ===
// Repro from #6072
class Foo {}
>Foo : Symbol(Foo, Decl(circularTypeofWithFunctionModule.ts, 0, 0))
function maker (value: string): typeof maker.Bar {
>maker : Symbol(maker, Decl(circularTypeofWithFunctionModule.ts, 2, 12), Decl(circularTypeofWithFunctionModule.ts, 6, 1))
>value : Symbol(value, Decl(circularTypeofWithFunctionModule.ts, 4, 16))
>maker.Bar : Symbol(maker.Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17))
>maker : Symbol(maker, Decl(circularTypeofWithFunctionModule.ts, 2, 12), Decl(circularTypeofWithFunctionModule.ts, 6, 1))
>Bar : Symbol(maker.Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17))
return maker.Bar;
>maker.Bar : Symbol(maker.Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17))
>maker : Symbol(maker, Decl(circularTypeofWithFunctionModule.ts, 2, 12), Decl(circularTypeofWithFunctionModule.ts, 6, 1))
>Bar : Symbol(maker.Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17))
}
namespace maker {
>maker : Symbol(maker, Decl(circularTypeofWithFunctionModule.ts, 2, 12), Decl(circularTypeofWithFunctionModule.ts, 6, 1))
export class Bar extends Foo {}
>Bar : Symbol(Bar, Decl(circularTypeofWithFunctionModule.ts, 8, 17))
>Foo : Symbol(Foo, Decl(circularTypeofWithFunctionModule.ts, 0, 0))
}

View file

@ -0,0 +1,27 @@
=== tests/cases/compiler/circularTypeofWithFunctionModule.ts ===
// Repro from #6072
class Foo {}
>Foo : Foo
function maker (value: string): typeof maker.Bar {
>maker : typeof maker
>value : string
>maker.Bar : typeof maker.Bar
>maker : typeof maker
>Bar : typeof maker.Bar
return maker.Bar;
>maker.Bar : typeof maker.Bar
>maker : typeof maker
>Bar : typeof maker.Bar
}
namespace maker {
>maker : typeof maker
export class Bar extends Foo {}
>Bar : Bar
>Foo : Foo
}

View file

@ -0,0 +1,11 @@
// Repro from #6072
class Foo {}
function maker (value: string): typeof maker.Bar {
return maker.Bar;
}
namespace maker {
export class Bar extends Foo {}
}