@@ -4819,24 +4819,21 @@ module ts {
4819
4819
error ( signatureDeclarationNode , Diagnostics . Specialized_overload_signature_is_not_assignable_to_any_non_specialized_signature ) ;
4820
4820
}
4821
4821
4822
- function checkFunctionOrConstructorSymbol ( symbol : Symbol ) {
4823
- function getEffectiveFlagsForFunctionCheck ( n : Node ) {
4824
- var flags = n . flags ;
4825
- // We want to determine if an overload is effectively ambient, which can happen if it
4826
- // is nested in an ambient context. However, do not treat members of interfaces differently
4827
- // based on whether the interface itself is in an ambient context. Interfaces should never
4828
- // be considered ambient for purposes of comparing overload attributes.
4829
- if ( n . parent . kind !== SyntaxKind . InterfaceDeclaration && isInAmbientContext ( n ) ) {
4830
- if ( ! ( flags & NodeFlags . Ambient ) ) {
4831
- // It is nested in an ambient context, which means it is automatically exported
4832
- flags |= NodeFlags . Export ;
4833
- }
4834
- flags |= NodeFlags . Ambient ;
4822
+ function getEffectiveDeclarationFlags ( n : Node , flagsToCheck : NodeFlags ) {
4823
+ var flags = n . flags ;
4824
+ if ( n . parent . kind !== SyntaxKind . InterfaceDeclaration && isInAmbientContext ( n ) ) {
4825
+ if ( ! ( flags & NodeFlags . Ambient ) ) {
4826
+ // It is nested in an ambient context, which means it is automatically exported
4827
+ flags |= NodeFlags . Export ;
4835
4828
}
4836
-
4837
- return flags & flagsToCheck ;
4829
+ flags |= NodeFlags . Ambient ;
4838
4830
}
4839
4831
4832
+ return flags & flagsToCheck ;
4833
+ }
4834
+
4835
+ function checkFunctionOrConstructorSymbol ( symbol : Symbol ) {
4836
+
4840
4837
function checkFlagAgreementBetweenOverloads ( overloads : Declaration [ ] , implementation : FunctionDeclaration , flagsToCheck : NodeFlags , someOverloadFlags : NodeFlags , allOverloadFlags : NodeFlags ) : void {
4841
4838
// Error if some overloads have a flag that is not shared by all overloads. To find the
4842
4839
// deviations, we XOR someOverloadFlags with allOverloadFlags
@@ -4849,10 +4846,10 @@ module ts {
4849
4846
// the canonical signature only if it is in the same container as the first overload
4850
4847
var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation . parent === overloads [ 0 ] . parent ;
4851
4848
var canonicalFlags = implementationSharesContainerWithFirstOverload
4852
- ? getEffectiveFlagsForFunctionCheck ( implementation )
4853
- : getEffectiveFlagsForFunctionCheck ( overloads [ 0 ] ) ;
4849
+ ? getEffectiveDeclarationFlags ( implementation , flagsToCheck )
4850
+ : getEffectiveDeclarationFlags ( overloads [ 0 ] , flagsToCheck ) ;
4854
4851
forEach ( overloads , o => {
4855
- var deviation = getEffectiveFlagsForFunctionCheck ( o ) ^ canonicalFlags ;
4852
+ var deviation = getEffectiveDeclarationFlags ( o , flagsToCheck ) ^ canonicalFlags ;
4856
4853
if ( deviation & NodeFlags . Export ) {
4857
4854
error ( o . name , Diagnostics . Overload_signatures_must_all_be_exported_or_not_exported ) ;
4858
4855
}
@@ -4880,7 +4877,7 @@ module ts {
4880
4877
for ( var i = 0 ; i < declarations . length ; i ++ ) {
4881
4878
var node = < FunctionDeclaration > declarations [ i ] ;
4882
4879
if ( node . kind === SyntaxKind . FunctionDeclaration || node . kind === SyntaxKind . Method || node . kind === SyntaxKind . Constructor ) {
4883
- var currentNodeFlags = getEffectiveFlagsForFunctionCheck ( node ) ;
4880
+ var currentNodeFlags = getEffectiveDeclarationFlags ( node , flagsToCheck ) ;
4884
4881
someNodeFlags |= currentNodeFlags ;
4885
4882
allNodeFlags &= currentNodeFlags ;
4886
4883
@@ -4951,14 +4948,97 @@ module ts {
4951
4948
}
4952
4949
}
4953
4950
4951
+ function checkExportsOnMergedDeclarations ( node : Node ) {
4952
+ var symbol : Symbol ;
4953
+
4954
+ // Exports should be checked only if enclosing module contains both exported and non exported declarations.
4955
+ // In case if all declarations are non-exported check is unnecesary.
4956
+
4957
+ // if localSymbol is defined on node then node itself is exported - check is required
4958
+ var symbol = node . localSymbol ;
4959
+ if ( ! symbol ) {
4960
+ // local symbol is undefined => this declaration is non-exported.
4961
+ // however symbol might contain other declarations that are exported
4962
+ symbol = getSymbolOfNode ( node ) ;
4963
+ if ( ! ( symbol . flags & SymbolFlags . Export ) ) {
4964
+ // this is a pure local symbol (all declarations are non-exported) - no need to check anything
4965
+ return ;
4966
+ }
4967
+ }
4968
+
4969
+ // run the check only for the first declaration in the list
4970
+ if ( getDeclarationOfKind ( symbol , node . kind ) !== node ) {
4971
+ return ;
4972
+ }
4973
+
4974
+ // we use SymbolFlags.ExportValue, SymbolFlags.ExportType and SymbolFlags.ExportNamespace
4975
+ // to denote disjoint declarationSpaces (without making new enum type).
4976
+ var exportedDeclarationSpaces : SymbolFlags = 0 ;
4977
+ var nonExportedDeclarationSpaces : SymbolFlags = 0 ;
4978
+ forEach ( symbol . declarations , d => {
4979
+ var declarationSpaces = getDeclarationSpaces ( d ) ;
4980
+ if ( getEffectiveDeclarationFlags ( d , NodeFlags . Export ) ) {
4981
+ exportedDeclarationSpaces |= declarationSpaces ;
4982
+ }
4983
+ else {
4984
+ nonExportedDeclarationSpaces |= declarationSpaces ;
4985
+ }
4986
+ } ) ;
4987
+
4988
+ var commonDeclarationSpace = exportedDeclarationSpaces & nonExportedDeclarationSpaces
4989
+
4990
+ if ( commonDeclarationSpace ) {
4991
+ // declaration spaces for exported and non-exported declarations intersect
4992
+ forEach ( symbol . declarations , d => {
4993
+ if ( getDeclarationSpaces ( d ) & commonDeclarationSpace ) {
4994
+ error ( d . name , Diagnostics . Individual_declarations_in_merged_declaration_0_must_be_all_exported_or_all_local , identifierToString ( d . name ) ) ;
4995
+ }
4996
+ } ) ;
4997
+ }
4998
+
4999
+ function getDeclarationSpaces ( d : Declaration ) : SymbolFlags {
5000
+ switch ( d . kind ) {
5001
+ case SyntaxKind . InterfaceDeclaration :
5002
+ return SymbolFlags . ExportType ;
5003
+ case SyntaxKind . ModuleDeclaration :
5004
+ return ( < ModuleDeclaration > d ) . name . kind === SyntaxKind . StringLiteral || isInstantiated ( d )
5005
+ ? SymbolFlags . ExportNamespace | SymbolFlags . ExportValue
5006
+ : SymbolFlags . ExportNamespace ;
5007
+ case SyntaxKind . ClassDeclaration :
5008
+ case SyntaxKind . EnumDeclaration :
5009
+ return SymbolFlags . ExportType | SymbolFlags . ExportValue ;
5010
+ case SyntaxKind . ImportDeclaration :
5011
+ var result : SymbolFlags = 0 ;
5012
+ var target = resolveImport ( getSymbolOfNode ( d ) ) ;
5013
+ forEach ( target . declarations , d => { result |= getDeclarationSpaces ( d ) ; } )
5014
+ return result ;
5015
+ default :
5016
+ return SymbolFlags . ExportValue ;
5017
+ }
5018
+ }
5019
+ }
5020
+
4954
5021
function checkFunctionDeclaration ( node : FunctionDeclaration ) {
4955
5022
checkSignatureDeclaration ( node ) ;
4956
5023
4957
- var symbol = getSymbolOfNode ( node ) ;
4958
- var firstDeclaration = getDeclarationOfKind ( symbol , node . kind ) ;
5024
+ var symbol = getSymbolOfNode ( node )
5025
+ // first we want to check the local symbol that contain this declaration
5026
+ // - if node.localSymbol !== undefined - this is current declaration is exported and localSymbol points to the local symbol
5027
+ // - if node.localSymbol === undefined - this node is non-exported so we can just pick the result of getSymbolOfNode
5028
+ var localSymbol = node . localSymbol || symbol ;
5029
+
5030
+ var firstDeclaration = getDeclarationOfKind ( localSymbol , node . kind ) ;
4959
5031
// Only type check the symbol once
4960
5032
if ( node === firstDeclaration ) {
4961
- checkFunctionOrConstructorSymbol ( symbol ) ;
5033
+ checkFunctionOrConstructorSymbol ( localSymbol ) ;
5034
+ }
5035
+
5036
+ if ( symbol . parent ) {
5037
+ // run check once for the first declaration
5038
+ if ( getDeclarationOfKind ( symbol , node . kind ) === node ) {
5039
+ // run check on export symbol to check that modifiers agree across all exported declarations
5040
+ checkFunctionOrConstructorSymbol ( symbol ) ;
5041
+ }
4962
5042
}
4963
5043
4964
5044
checkSourceElement ( node . body ) ;
@@ -5155,8 +5235,10 @@ module ts {
5155
5235
function checkVariableDeclaration ( node : VariableDeclaration ) {
5156
5236
checkSourceElement ( node . type ) ;
5157
5237
5158
- var symbol = getSymbolOfNode ( node ) ;
5238
+ checkExportsOnMergedDeclarations ( node ) ;
5159
5239
5240
+ var symbol = getSymbolOfNode ( node ) ;
5241
+
5160
5242
var typeOfValueDeclaration = getTypeOfVariableOrParameterOrProperty ( symbol ) ;
5161
5243
var type : Type ;
5162
5244
var useTypeFromValueDeclaration = node === symbol . valueDeclaration ;
@@ -5441,6 +5523,7 @@ module ts {
5441
5523
checkTypeNameIsReserved ( node . name , Diagnostics . Class_name_cannot_be_0 ) ;
5442
5524
checkTypeParameters ( node . typeParameters ) ;
5443
5525
checkCollisionWithCapturedThisVariable ( node , node . name ) ;
5526
+ checkExportsOnMergedDeclarations ( node ) ;
5444
5527
var symbol = getSymbolOfNode ( node ) ;
5445
5528
var type = < InterfaceType > getDeclaredTypeOfSymbol ( symbol ) ;
5446
5529
var staticType = < ObjectType > getTypeOfSymbol ( symbol ) ;
@@ -5595,6 +5678,7 @@ module ts {
5595
5678
function checkInterfaceDeclaration ( node : InterfaceDeclaration ) {
5596
5679
checkTypeNameIsReserved ( node . name , Diagnostics . Interface_name_cannot_be_0 ) ;
5597
5680
checkTypeParameters ( node . typeParameters ) ;
5681
+ checkExportsOnMergedDeclarations ( node ) ;
5598
5682
var symbol = getSymbolOfNode ( node ) ;
5599
5683
var firstInterfaceDecl = < InterfaceDeclaration > getDeclarationOfKind ( symbol , SyntaxKind . InterfaceDeclaration ) ;
5600
5684
if ( symbol . declarations . length > 1 ) {
@@ -5640,6 +5724,7 @@ module ts {
5640
5724
function checkEnumDeclaration ( node : EnumDeclaration ) {
5641
5725
checkTypeNameIsReserved ( node . name , Diagnostics . Enum_name_cannot_be_0 ) ;
5642
5726
checkCollisionWithCapturedThisVariable ( node , node . name ) ;
5727
+ checkExportsOnMergedDeclarations ( node ) ;
5643
5728
var enumSymbol = getSymbolOfNode ( node ) ;
5644
5729
var enumType = getDeclaredTypeOfSymbol ( enumSymbol ) ;
5645
5730
var autoValue = 0 ;
@@ -5711,6 +5796,7 @@ module ts {
5711
5796
5712
5797
function checkModuleDeclaration ( node : ModuleDeclaration ) {
5713
5798
checkCollisionWithCapturedThisVariable ( node , node . name ) ;
5799
+ checkExportsOnMergedDeclarations ( node ) ;
5714
5800
var symbol = getSymbolOfNode ( node ) ;
5715
5801
if ( symbol . flags & SymbolFlags . ValueModule && symbol . declarations . length > 1 && ! isInAmbientContext ( node ) ) {
5716
5802
var classOrFunc = getFirstNonAmbientClassOrFunctionDeclaration ( symbol ) ;
0 commit comments