@@ -2423,7 +2423,7 @@ module ts {
24232423 return check(type);
24242424 function check(type: InterfaceType): boolean {
24252425 let target = <InterfaceType>getTargetType(type);
2426- return target === checkBase || forEach(target.baseTypes , check);
2426+ return target === checkBase || forEach(getBaseTypes( target) , check);
24272427 }
24282428 }
24292429
@@ -2451,6 +2451,69 @@ module ts {
24512451 return result;
24522452 }
24532453
2454+ function getBaseTypes(type: InterfaceType): ObjectType[] {
2455+ if (!(<InterfaceTypeWithBaseTypes>type).baseTypes) {
2456+ if (type.symbol.flags & SymbolFlags.Class) {
2457+ resolveBaseTypesOfClass(<InterfaceTypeWithBaseTypes>type);
2458+ }
2459+ else if (type.symbol.flags & SymbolFlags.Interface) {
2460+ resolveBaseTypesOfInterface(<InterfaceTypeWithBaseTypes>type);
2461+ }
2462+ else {
2463+ Debug.fail("type must be class or interface");
2464+ }
2465+ }
2466+
2467+ return (<InterfaceTypeWithBaseTypes>type).baseTypes;
2468+ }
2469+
2470+ function resolveBaseTypesOfClass(type: InterfaceTypeWithBaseTypes): void {
2471+ type.baseTypes = [];
2472+ let declaration = <ClassDeclaration>getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration);
2473+ let baseTypeNode = getClassExtendsHeritageClauseElement(declaration);
2474+ if (baseTypeNode) {
2475+ let baseType = getTypeFromHeritageClauseElement(baseTypeNode);
2476+ if (baseType !== unknownType) {
2477+ if (getTargetType(baseType).flags & TypeFlags.Class) {
2478+ if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
2479+ type.baseTypes.push(baseType);
2480+ }
2481+ else {
2482+ error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
2483+ }
2484+ }
2485+ else {
2486+ error(baseTypeNode, Diagnostics.A_class_may_only_extend_another_class);
2487+ }
2488+ }
2489+ }
2490+ }
2491+
2492+ function resolveBaseTypesOfInterface(type: InterfaceTypeWithBaseTypes): void {
2493+ type.baseTypes = [];
2494+ forEach(type.symbol.declarations, declaration => {
2495+ if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
2496+ forEach(getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration), node => {
2497+ let baseType = getTypeFromHeritageClauseElement(node);
2498+
2499+ if (baseType !== unknownType) {
2500+ if (getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface)) {
2501+ if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
2502+ type.baseTypes.push(baseType);
2503+ }
2504+ else {
2505+ error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
2506+ }
2507+ }
2508+ else {
2509+ error(node, Diagnostics.An_interface_may_only_extend_a_class_or_another_interface);
2510+ }
2511+ }
2512+ });
2513+ }
2514+ });
2515+ }
2516+
24542517 function getDeclaredTypeOfClass(symbol: Symbol): InterfaceType {
24552518 let links = getSymbolLinks(symbol);
24562519 if (!links.declaredType) {
@@ -2464,25 +2527,7 @@ module ts {
24642527 (<GenericType>type).target = <GenericType>type;
24652528 (<GenericType>type).typeArguments = type.typeParameters;
24662529 }
2467- type.baseTypes = [];
2468- let declaration = <ClassDeclaration>getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration);
2469- let baseTypeNode = getClassExtendsHeritageClauseElement(declaration);
2470- if (baseTypeNode) {
2471- let baseType = getTypeFromHeritageClauseElement(baseTypeNode);
2472- if (baseType !== unknownType) {
2473- if (getTargetType(baseType).flags & TypeFlags.Class) {
2474- if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
2475- type.baseTypes.push(baseType);
2476- }
2477- else {
2478- error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
2479- }
2480- }
2481- else {
2482- error(baseTypeNode, Diagnostics.A_class_may_only_extend_another_class);
2483- }
2484- }
2485- }
2530+
24862531 type.declaredProperties = getNamedMembers(symbol.members);
24872532 type.declaredCallSignatures = emptyArray;
24882533 type.declaredConstructSignatures = emptyArray;
@@ -2505,28 +2550,7 @@ module ts {
25052550 (<GenericType>type).target = <GenericType>type;
25062551 (<GenericType>type).typeArguments = type.typeParameters;
25072552 }
2508- type.baseTypes = [];
2509- forEach(symbol.declarations, declaration => {
2510- if (declaration.kind === SyntaxKind.InterfaceDeclaration && getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration)) {
2511- forEach(getInterfaceBaseTypeNodes(<InterfaceDeclaration>declaration), node => {
2512- let baseType = getTypeFromHeritageClauseElement(node);
25132553
2514- if (baseType !== unknownType) {
2515- if (getTargetType(baseType).flags & (TypeFlags.Class | TypeFlags.Interface)) {
2516- if (type !== baseType && !hasBaseType(<InterfaceType>baseType, type)) {
2517- type.baseTypes.push(baseType);
2518- }
2519- else {
2520- error(declaration, Diagnostics.Type_0_recursively_references_itself_as_a_base_type, typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.WriteArrayAsGenericType));
2521- }
2522- }
2523- else {
2524- error(node, Diagnostics.An_interface_may_only_extend_a_class_or_another_interface);
2525- }
2526- }
2527- });
2528- }
2529- });
25302554 type.declaredProperties = getNamedMembers(symbol.members);
25312555 type.declaredCallSignatures = getSignaturesOfSymbol(symbol.members["__call"]);
25322556 type.declaredConstructSignatures = getSignaturesOfSymbol(symbol.members["__new"]);
@@ -2646,9 +2670,9 @@ module ts {
26462670 let constructSignatures = type.declaredConstructSignatures;
26472671 let stringIndexType = type.declaredStringIndexType;
26482672 let numberIndexType = type.declaredNumberIndexType;
2649- if (type.baseTypes .length) {
2673+ if (getBaseTypes( type) .length) {
26502674 members = createSymbolTable(type.declaredProperties);
2651- forEach(type.baseTypes , baseType => {
2675+ forEach(getBaseTypes( type) , baseType => {
26522676 addInheritedMembers(members, getPropertiesOfObjectType(baseType));
26532677 callSignatures = concatenate(callSignatures, getSignaturesOfType(baseType, SignatureKind.Call));
26542678 constructSignatures = concatenate(constructSignatures, getSignaturesOfType(baseType, SignatureKind.Construct));
@@ -2667,7 +2691,7 @@ module ts {
26672691 let constructSignatures = instantiateList(target.declaredConstructSignatures, mapper, instantiateSignature);
26682692 let stringIndexType = target.declaredStringIndexType ? instantiateType(target.declaredStringIndexType, mapper) : undefined;
26692693 let numberIndexType = target.declaredNumberIndexType ? instantiateType(target.declaredNumberIndexType, mapper) : undefined;
2670- forEach(target.baseTypes , baseType => {
2694+ forEach(getBaseTypes( target) , baseType => {
26712695 let instantiatedBaseType = instantiateType(baseType, mapper);
26722696 addInheritedMembers(members, getPropertiesOfObjectType(instantiatedBaseType));
26732697 callSignatures = concatenate(callSignatures, getSignaturesOfType(instantiatedBaseType, SignatureKind.Call));
@@ -2697,8 +2721,8 @@ module ts {
26972721 }
26982722
26992723 function getDefaultConstructSignatures(classType: InterfaceType): Signature[] {
2700- if (classType.baseTypes .length) {
2701- let baseType = classType.baseTypes [0];
2724+ if (getBaseTypes( classType) .length) {
2725+ let baseType = getBaseTypes( classType) [0];
27022726 let baseSignatures = getSignaturesOfType(getTypeOfSymbol(baseType.symbol), SignatureKind.Construct);
27032727 return map(baseSignatures, baseSignature => {
27042728 let signature = baseType.flags & TypeFlags.Reference ?
@@ -2820,9 +2844,9 @@ module ts {
28202844 if (!constructSignatures.length) {
28212845 constructSignatures = getDefaultConstructSignatures(classType);
28222846 }
2823- if (classType.baseTypes .length) {
2847+ if (getBaseTypes( classType) .length) {
28242848 members = createSymbolTable(getNamedMembers(members));
2825- addInheritedMembers(members, getPropertiesOfObjectType(getTypeOfSymbol(classType.baseTypes [0].symbol)));
2849+ addInheritedMembers(members, getPropertiesOfObjectType(getTypeOfSymbol(getBaseTypes( classType) [0].symbol)));
28262850 }
28272851 }
28282852 stringIndexType = undefined;
@@ -5550,7 +5574,7 @@ module ts {
55505574 let baseClass: Type;
55515575 if (enclosingClass && getClassExtendsHeritageClauseElement(enclosingClass)) {
55525576 let classType = <InterfaceType>getDeclaredTypeOfSymbol(getSymbolOfNode(enclosingClass));
5553- baseClass = classType.baseTypes. length && classType.baseTypes [0];
5577+ baseClass = getBaseTypes( classType). length && getBaseTypes( classType) [0];
55545578 }
55555579
55565580 if (!baseClass) {
@@ -9829,7 +9853,7 @@ module ts {
98299853 errorNode = declaredNumberIndexer || declaredStringIndexer;
98309854 // condition 'errorNode === undefined' may appear if types does not declare nor string neither number indexer
98319855 if (!errorNode && (type.flags & TypeFlags.Interface)) {
9832- let someBaseTypeHasBothIndexers = forEach((<InterfaceType>type).baseTypes , base => getIndexTypeOfType(base, IndexKind.String) && getIndexTypeOfType(base, IndexKind.Number));
9856+ let someBaseTypeHasBothIndexers = forEach(getBaseTypes (<InterfaceType>type), base => getIndexTypeOfType(base, IndexKind.String) && getIndexTypeOfType(base, IndexKind.Number));
98339857 errorNode = someBaseTypeHasBothIndexers ? undefined : type.symbol.declarations[0];
98349858 }
98359859 }
@@ -9869,7 +9893,7 @@ module ts {
98699893 // for interfaces property and indexer might be inherited from different bases
98709894 // check if any base class already has both property and indexer.
98719895 // check should be performed only if 'type' is the first type that brings property\indexer together
9872- let someBaseClassHasBothPropertyAndIndexer = forEach((<InterfaceType>containingType).baseTypes , base => getPropertyOfObjectType(base, prop.name) && getIndexTypeOfType(base, indexKind));
9896+ let someBaseClassHasBothPropertyAndIndexer = forEach(getBaseTypes (<InterfaceType>containingType), base => getPropertyOfObjectType(base, prop.name) && getIndexTypeOfType(base, indexKind));
98739897 errorNode = someBaseClassHasBothPropertyAndIndexer ? undefined : containingType.symbol.declarations[0];
98749898 }
98759899
@@ -9953,9 +9977,9 @@ module ts {
99539977 emitExtends = emitExtends || !isInAmbientContext(node);
99549978 checkHeritageClauseElement(baseTypeNode);
99559979 }
9956- if (type.baseTypes .length) {
9980+ if (getBaseTypes( type) .length) {
99579981 if (produceDiagnostics) {
9958- let baseType = type.baseTypes [0];
9982+ let baseType = getBaseTypes( type) [0];
99599983 checkTypeAssignableTo(type, baseType, node.name || node, Diagnostics.Class_0_incorrectly_extends_base_class_1);
99609984 let staticBaseType = getTypeOfSymbol(baseType.symbol);
99619985 checkTypeAssignableTo(staticType, getTypeWithoutConstructors(staticBaseType), node.name || node,
@@ -9969,7 +9993,7 @@ module ts {
99699993 }
99709994 }
99719995
9972- if (type.baseTypes .length || (baseTypeNode && compilerOptions.separateCompilation)) {
9996+ if (getBaseTypes( type) .length || (baseTypeNode && compilerOptions.separateCompilation)) {
99739997 // Check that base type can be evaluated as expression
99749998 checkExpressionOrQualifiedName(baseTypeNode.expression);
99759999 }
@@ -10113,15 +10137,15 @@ module ts {
1011310137 }
1011410138
1011510139 function checkInheritedPropertiesAreIdentical(type: InterfaceType, typeNode: Node): boolean {
10116- if (!type.baseTypes. length || type.baseTypes .length === 1) {
10140+ if (!getBaseTypes( type). length || getBaseTypes( type) .length === 1) {
1011710141 return true;
1011810142 }
1011910143
1012010144 let seen: Map<{ prop: Symbol; containingType: Type }> = {};
1012110145 forEach(type.declaredProperties, p => { seen[p.name] = { prop: p, containingType: type }; });
1012210146 let ok = true;
1012310147
10124- for (let base of type.baseTypes ) {
10148+ for (let base of getBaseTypes( type) ) {
1012510149 let properties = getPropertiesOfObjectType(base);
1012610150 for (let prop of properties) {
1012710151 if (!hasProperty(seen, prop.name)) {
@@ -10169,7 +10193,7 @@ module ts {
1016910193 let type = <InterfaceType>getDeclaredTypeOfSymbol(symbol);
1017010194 // run subsequent checks only if first set succeeded
1017110195 if (checkInheritedPropertiesAreIdentical(type, node.name)) {
10172- forEach(type.baseTypes , baseType => {
10196+ forEach(getBaseTypes( type) , baseType => {
1017310197 checkTypeAssignableTo(type, baseType, node.name, Diagnostics.Interface_0_incorrectly_extends_interface_1);
1017410198 });
1017510199 checkIndexConstraints(type);
0 commit comments