@@ -594,12 +594,11 @@ namespace ts {
594594 emitLines ( node . statements ) ;
595595 }
596596
597- // Return a temp variable name to be used in `export default` statements.
597+ // Return a temp variable name to be used in `export default`/`export class ... extends` statements.
598598 // The temp name will be of the form _default_counter.
599599 // Note that export default is only allowed at most once in a module, so we
600600 // do not need to keep track of created temp names.
601- function getExportDefaultTempVariableName ( ) : string {
602- const baseName = "_default" ;
601+ function getExportTempVariableName ( baseName : string ) : string {
603602 if ( ! currentIdentifiers . has ( baseName ) ) {
604603 return baseName ;
605604 }
@@ -613,24 +612,31 @@ namespace ts {
613612 }
614613 }
615614
615+ function emitTempVariableDeclaration ( expr : Expression , baseName : string , diagnostic : SymbolAccessibilityDiagnostic ) : string {
616+ const tempVarName = getExportTempVariableName ( baseName ) ;
617+ if ( ! noDeclare ) {
618+ write ( "declare " ) ;
619+ }
620+ write ( "const " ) ;
621+ write ( tempVarName ) ;
622+ write ( ": " ) ;
623+ writer . getSymbolAccessibilityDiagnostic = ( ) => diagnostic ;
624+ resolver . writeTypeOfExpression ( expr , enclosingDeclaration , TypeFormatFlags . UseTypeOfFunction | TypeFormatFlags . UseTypeAliasValue , writer ) ;
625+ write ( ";" ) ;
626+ writeLine ( ) ;
627+ return tempVarName ;
628+ }
629+
616630 function emitExportAssignment ( node : ExportAssignment ) {
617631 if ( node . expression . kind === SyntaxKind . Identifier ) {
618632 write ( node . isExportEquals ? "export = " : "export default " ) ;
619633 writeTextOfNode ( currentText , node . expression ) ;
620634 }
621635 else {
622- // Expression
623- const tempVarName = getExportDefaultTempVariableName ( ) ;
624- if ( ! noDeclare ) {
625- write ( "declare " ) ;
626- }
627- write ( "var " ) ;
628- write ( tempVarName ) ;
629- write ( ": " ) ;
630- writer . getSymbolAccessibilityDiagnostic = getDefaultExportAccessibilityDiagnostic ;
631- resolver . writeTypeOfExpression ( node . expression , enclosingDeclaration , TypeFormatFlags . UseTypeOfFunction | TypeFormatFlags . UseTypeAliasValue , writer ) ;
632- write ( ";" ) ;
633- writeLine ( ) ;
636+ const tempVarName = emitTempVariableDeclaration ( node . expression , "_default" , {
637+ diagnosticMessage : Diagnostics . Default_export_of_the_module_has_or_is_using_private_name_0 ,
638+ errorNode : node
639+ } ) ;
634640 write ( node . isExportEquals ? "export = " : "export default " ) ;
635641 write ( tempVarName ) ;
636642 }
@@ -644,13 +650,6 @@ namespace ts {
644650 // write each of these declarations asynchronously
645651 writeAsynchronousModuleElements ( nodes ) ;
646652 }
647-
648- function getDefaultExportAccessibilityDiagnostic ( ) : SymbolAccessibilityDiagnostic {
649- return {
650- diagnosticMessage : Diagnostics . Default_export_of_the_module_has_or_is_using_private_name_0 ,
651- errorNode : node
652- } ;
653- }
654653 }
655654
656655 function isModuleElementVisible ( node : Declaration ) {
@@ -1097,7 +1096,7 @@ namespace ts {
10971096 }
10981097 }
10991098
1100- function emitHeritageClause ( className : Identifier , typeReferences : ExpressionWithTypeArguments [ ] , isImplementsList : boolean ) {
1099+ function emitHeritageClause ( typeReferences : ExpressionWithTypeArguments [ ] , isImplementsList : boolean ) {
11011100 if ( typeReferences ) {
11021101 write ( isImplementsList ? " implements " : " extends " ) ;
11031102 emitCommaList ( typeReferences , emitTypeOfTypeReference ) ;
@@ -1110,12 +1109,6 @@ namespace ts {
11101109 else if ( ! isImplementsList && node . expression . kind === SyntaxKind . NullKeyword ) {
11111110 write ( "null" ) ;
11121111 }
1113- else {
1114- writer . getSymbolAccessibilityDiagnostic = getHeritageClauseVisibilityError ;
1115- errorNameNode = className ;
1116- resolver . writeBaseConstructorTypeOfClass ( < ClassLikeDeclaration > enclosingDeclaration , enclosingDeclaration , TypeFormatFlags . UseTypeOfFunction | TypeFormatFlags . UseTypeAliasValue , writer ) ;
1117- errorNameNode = undefined ;
1118- }
11191112
11201113 function getHeritageClauseVisibilityError ( ) : SymbolAccessibilityDiagnostic {
11211114 let diagnosticMessage : DiagnosticMessage ;
@@ -1151,23 +1144,43 @@ namespace ts {
11511144 }
11521145 }
11531146
1147+ const prevEnclosingDeclaration = enclosingDeclaration ;
1148+ enclosingDeclaration = node ;
1149+ const baseTypeNode = getClassExtendsHeritageClauseElement ( node ) ;
1150+ let tempVarName : string ;
1151+ if ( baseTypeNode && ! isEntityNameExpression ( baseTypeNode . expression ) ) {
1152+ tempVarName = baseTypeNode . expression . kind === SyntaxKind . NullKeyword ?
1153+ "null" :
1154+ emitTempVariableDeclaration ( baseTypeNode . expression , `${ node . name . text } _base` , {
1155+ diagnosticMessage : Diagnostics . extends_clause_of_exported_class_0_has_or_is_using_private_name_1 ,
1156+ errorNode : baseTypeNode ,
1157+ typeName : node . name
1158+ } ) ;
1159+ }
1160+
11541161 emitJsDocComments ( node ) ;
11551162 emitModuleElementDeclarationFlags ( node ) ;
11561163 if ( hasModifier ( node , ModifierFlags . Abstract ) ) {
11571164 write ( "abstract " ) ;
11581165 }
1159-
11601166 write ( "class " ) ;
11611167 writeTextOfNode ( currentText , node . name ) ;
1162- const prevEnclosingDeclaration = enclosingDeclaration ;
1163- enclosingDeclaration = node ;
11641168 emitTypeParameters ( node . typeParameters ) ;
1165- const baseTypeNode = getClassExtendsHeritageClauseElement ( node ) ;
11661169 if ( baseTypeNode ) {
1167- node . name ;
1168- emitHeritageClause ( node . name , [ baseTypeNode ] , /*isImplementsList*/ false ) ;
1170+ if ( ! isEntityNameExpression ( baseTypeNode . expression ) ) {
1171+ write ( " extends " ) ;
1172+ write ( tempVarName ) ;
1173+ if ( baseTypeNode . typeArguments ) {
1174+ write ( "<" ) ;
1175+ emitCommaList ( baseTypeNode . typeArguments , emitType ) ;
1176+ write ( ">" ) ;
1177+ }
1178+ }
1179+ else {
1180+ emitHeritageClause ( [ baseTypeNode ] , /*isImplementsList*/ false ) ;
1181+ }
11691182 }
1170- emitHeritageClause ( node . name , getClassImplementsHeritageClauseElements ( node ) , /*isImplementsList*/ true ) ;
1183+ emitHeritageClause ( getClassImplementsHeritageClauseElements ( node ) , /*isImplementsList*/ true ) ;
11711184 write ( " {" ) ;
11721185 writeLine ( ) ;
11731186 increaseIndent ( ) ;
@@ -1189,7 +1202,7 @@ namespace ts {
11891202 emitTypeParameters ( node . typeParameters ) ;
11901203 const interfaceExtendsTypes = filter ( getInterfaceBaseTypeNodes ( node ) , base => isEntityNameExpression ( base . expression ) ) ;
11911204 if ( interfaceExtendsTypes && interfaceExtendsTypes . length ) {
1192- emitHeritageClause ( node . name , interfaceExtendsTypes , /*isImplementsList*/ false ) ;
1205+ emitHeritageClause ( interfaceExtendsTypes , /*isImplementsList*/ false ) ;
11931206 }
11941207 write ( " {" ) ;
11951208 writeLine ( ) ;
0 commit comments