@@ -355,11 +355,24 @@ namespace ts {
355
355
? Diagnostics . Cannot_redeclare_block_scoped_variable_0
356
356
: Diagnostics . Duplicate_identifier_0 ;
357
357
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 ) {
360
363
message = Diagnostics . A_module_cannot_have_multiple_default_exports ;
361
364
}
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
+ }
363
376
364
377
forEach ( symbol . declarations , declaration => {
365
378
file . bindDiagnostics . push ( createDiagnosticForNode ( declaration . name || declaration , message , getDisplayName ( declaration ) ) ) ;
@@ -1111,7 +1124,7 @@ namespace ts {
1111
1124
}
1112
1125
else {
1113
1126
forEachChild ( node , bind ) ;
1114
- if ( node . operator === SyntaxKind . PlusEqualsToken || node . operator === SyntaxKind . MinusMinusToken ) {
1127
+ if ( node . operator === SyntaxKind . PlusPlusToken || node . operator === SyntaxKind . MinusMinusToken ) {
1115
1128
bindAssignmentTargetFlow ( node . operand ) ;
1116
1129
}
1117
1130
}
@@ -1360,7 +1373,7 @@ namespace ts {
1360
1373
function hasExportDeclarations ( node : ModuleDeclaration | SourceFile ) : boolean {
1361
1374
const body = node . kind === SyntaxKind . SourceFile ? node : ( < ModuleDeclaration > node ) . body ;
1362
1375
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 ) {
1364
1377
if ( stat . kind === SyntaxKind . ExportDeclaration || stat . kind === SyntaxKind . ExportAssignment ) {
1365
1378
return true ;
1366
1379
}
@@ -1944,12 +1957,15 @@ namespace ts {
1944
1957
bindAnonymousDeclaration ( node , SymbolFlags . Alias , getDeclarationName ( node ) ) ;
1945
1958
}
1946
1959
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.
1947
1963
const flags = node . kind === SyntaxKind . ExportAssignment && exportAssignmentIsAlias ( < ExportAssignment > node )
1948
1964
// An export default clause with an EntityNameExpression exports all meanings of that identifier
1949
1965
? SymbolFlags . Alias
1950
1966
// An export default clause with any other expression exports a value
1951
1967
: 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 ) ;
1953
1969
}
1954
1970
}
1955
1971
0 commit comments