@@ -355,11 +355,24 @@ namespace ts {
355355 ? Diagnostics . Cannot_redeclare_block_scoped_variable_0
356356 : Diagnostics . Duplicate_identifier_0 ;
357357
358- forEach ( symbol . declarations , declaration => {
359- if ( hasModifier ( declaration , ModifierFlags . Default ) ) {
358+ if ( symbol . declarations && symbol . declarations . length ) {
359+ // If the current node is a default export of some sort, then check if
360+ // there are any other default exports that we need to error on.
361+ // We'll know whether we have other default exports depending on if `symbol` already has a declaration list set.
362+ if ( isDefaultExport ) {
360363 message = Diagnostics . A_module_cannot_have_multiple_default_exports ;
361364 }
362- } ) ;
365+ else {
366+ // This is to properly report an error in the case "export default { }" is after export default of class declaration or function declaration.
367+ // Error on multiple export default in the following case:
368+ // 1. multiple export default of class declaration or function declaration by checking NodeFlags.Default
369+ // 2. multiple export default of export assignment. This one doesn't have NodeFlags.Default on (as export default doesn't considered as modifiers)
370+ if ( symbol . declarations && symbol . declarations . length &&
371+ ( isDefaultExport || ( node . kind === SyntaxKind . ExportAssignment && ! ( < ExportAssignment > node ) . isExportEquals ) ) ) {
372+ message = Diagnostics . A_module_cannot_have_multiple_default_exports ;
373+ }
374+ }
375+ }
363376
364377 forEach ( symbol . declarations , declaration => {
365378 file . bindDiagnostics . push ( createDiagnosticForNode ( declaration . name || declaration , message , getDisplayName ( declaration ) ) ) ;
@@ -1111,7 +1124,7 @@ namespace ts {
11111124 }
11121125 else {
11131126 forEachChild ( node , bind ) ;
1114- if ( node . operator === SyntaxKind . PlusEqualsToken || node . operator === SyntaxKind . MinusMinusToken ) {
1127+ if ( node . operator === SyntaxKind . PlusPlusToken || node . operator === SyntaxKind . MinusMinusToken ) {
11151128 bindAssignmentTargetFlow ( node . operand ) ;
11161129 }
11171130 }
@@ -1360,7 +1373,7 @@ namespace ts {
13601373 function hasExportDeclarations ( node : ModuleDeclaration | SourceFile ) : boolean {
13611374 const body = node . kind === SyntaxKind . SourceFile ? node : ( < ModuleDeclaration > node ) . body ;
13621375 if ( body && ( body . kind === SyntaxKind . SourceFile || body . kind === SyntaxKind . ModuleBlock ) ) {
1363- for ( const stat of ( < Block > body ) . statements ) {
1376+ for ( const stat of ( < BlockLike > body ) . statements ) {
13641377 if ( stat . kind === SyntaxKind . ExportDeclaration || stat . kind === SyntaxKind . ExportAssignment ) {
13651378 return true ;
13661379 }
@@ -1944,12 +1957,15 @@ namespace ts {
19441957 bindAnonymousDeclaration ( node , SymbolFlags . Alias , getDeclarationName ( node ) ) ;
19451958 }
19461959 else {
1960+ // An export default clause with an expression exports a value
1961+ // We want to exclude both class and function here, this is necessary to issue an error when there are both
1962+ // default export-assignment and default export function and class declaration.
19471963 const flags = node . kind === SyntaxKind . ExportAssignment && exportAssignmentIsAlias ( < ExportAssignment > node )
19481964 // An export default clause with an EntityNameExpression exports all meanings of that identifier
19491965 ? SymbolFlags . Alias
19501966 // An export default clause with any other expression exports a value
19511967 : SymbolFlags . Property ;
1952- declareSymbol ( container . symbol . exports , container . symbol , node , flags , SymbolFlags . PropertyExcludes | SymbolFlags . AliasExcludes ) ;
1968+ declareSymbol ( container . symbol . exports , container . symbol , node , flags , SymbolFlags . Property | SymbolFlags . AliasExcludes | SymbolFlags . Class | SymbolFlags . Function ) ;
19531969 }
19541970 }
19551971
0 commit comments