diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 7f83681a490e4..f5715f8747272 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -125,40 +125,47 @@ module ts { function declareModuleMember(node: Declaration, symbolKind: SymbolFlags, symbolExcludes: SymbolFlags) { // Exported module members are given 2 symbols: A local symbol that is classified with an ExportValue, // ExportType, or ExportContainer flag, and an associated export symbol with all the correct flags set - // on it. There are 2 main reasons: - // - // 1. We treat locals and exports of the same name as mutually exclusive within a container. - // That means the binder will issue a Duplicate Identifier error if you mix locals and exports - // with the same name in the same container. - // TODO: Make this a more specific error and decouple it from the exclusion logic. + // on it. Reasons: + // 1. During name resolution i.e for types we need to distingush local and exported symbols. + // All members are added to the exported one so local should never be returned. // 2. When we checkIdentifier in the checker, we set its resolved symbol to the local symbol, // but return the export symbol (by calling getExportSymbolOfValueSymbolIfExported). That way // when the emitter comes back to it, it knows not to qualify the name if it was found in a containing scope. + // Exported members will share local symbol with non-exported members var exportKind = 0; - var exportExcludes = 0; if (symbolKind & SymbolFlags.Value) { exportKind |= SymbolFlags.ExportValue; - exportExcludes |= SymbolFlags.Value; } if (symbolKind & SymbolFlags.Type) { exportKind |= SymbolFlags.ExportType; - exportExcludes |= SymbolFlags.Type; } if (symbolKind & SymbolFlags.Namespace) { exportKind |= SymbolFlags.ExportNamespace; - exportExcludes |= SymbolFlags.Namespace; } if (node.flags & NodeFlags.Export || (node.kind !== SyntaxKind.ImportDeclaration && isAmbientContext(container))) { if (exportKind) { - var local = declareSymbol(container.locals, undefined, node, exportKind, exportExcludes); - local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes); + var exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes); + var localSymbol = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); + node.symbol = exportSymbol; + // export function foo(); // 1 + // export function foo() {} // 2 + // at (1) we'll create two symbols: local and exported and link then together + // at (2) the same symbols will be returned as exported and local. + // make sure that local symbol is added to the list of local symbols just once. + if (!localSymbol.exportSymbol) { + if (!exportSymbol.localSymbols) { + exportSymbol.localSymbols = []; + } + exportSymbol.localSymbols.push(localSymbol); + localSymbol.exportSymbol = exportSymbol; + } } else { declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes); } } else { - declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes | exportKind); + declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes); } } diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 7e935b03c192c..1bcc920b57846 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -107,6 +107,9 @@ module ts { function cloneSymbol(symbol: Symbol): Symbol { var result = createSymbol(symbol.flags | SymbolFlags.Merged, symbol.name); result.declarations = symbol.declarations.slice(0); + if (symbol.localSymbols) { + result.localSymbols = symbol.localSymbols.slice(0); + } result.parent = symbol.parent; if (symbol.valueDeclaration) result.valueDeclaration = symbol.valueDeclaration; if (symbol.members) result.members = cloneSymbolTable(symbol.members); @@ -122,6 +125,12 @@ module ts { forEach(source.declarations, node => { target.declarations.push(node); }); + if (source.localSymbols) { + if (!target.localSymbols) { + target.localSymbols = []; + } + forEach(source.localSymbols, node => { target.localSymbols.push(node); }); + } if (source.members) { if (!target.members) target.members = {}; extendSymbolTable(target.members, source.members); @@ -2230,6 +2239,9 @@ module ts { // also transient so that we can just store data on it directly. var result = createSymbol(SymbolFlags.Instantiated | SymbolFlags.Transient, symbol.name); result.declarations = symbol.declarations; + if (symbol.localSymbols) { + result.localSymbols = symbol.localSymbols; + } result.parent = symbol.parent; result.target = symbol; result.mapper = mapper; @@ -2928,6 +2940,9 @@ module ts { forEach(properties, p => { var symbol = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, p.name); symbol.declarations = p.declarations; + if (p.localSymbols) { + symbol.localSymbols = p.localSymbols; + } symbol.parent = p.parent; symbol.type = widenedTypes[index++]; if (p.valueDeclaration) symbol.valueDeclaration = p.valueDeclaration; @@ -3455,6 +3470,9 @@ module ts { var type = checkExpression((member.declarations[0]).initializer, contextualPropType, contextualMapper); var prop = createSymbol(SymbolFlags.Property | SymbolFlags.Transient, member.name); prop.declarations = member.declarations; + if (member.localSymbols) { + prop.localSymbols = member.localSymbols; + } prop.parent = member.parent; if (member.valueDeclaration) prop.valueDeclaration = member.valueDeclaration; prop.type = type; @@ -4730,89 +4748,103 @@ module ts { return flags & flagsToCheck; } - function checkFlagAgreementBetweenOverloads(overloads: Declaration[], implementation: FunctionDeclaration, flagsToCheck: NodeFlags, someOverloadFlags: NodeFlags, allOverloadFlags: NodeFlags): void { - // Error if some overloads have a flag that is not shared by all overloads. To find the - // deviations, we XOR someOverloadFlags with allOverloadFlags - var someButNotAllOverloadFlags = someOverloadFlags ^ allOverloadFlags; - if (someButNotAllOverloadFlags !== 0) { - // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration - // Error on all deviations from this canonical set of flags - // The caveat is that if some overloads are defined in lib.d.ts, we don't want to - // report the errors on those. To achieve this, we will say that the implementation is - // the canonical signature only if it is in the same container as the first overload - var implementationSharesContainerWithFirstOverload = implementation !== undefined && implementation.parent === overloads[0].parent; - var canonicalFlags = implementationSharesContainerWithFirstOverload - ? getEffectiveFlagsForFunctionCheck(implementation) - : getEffectiveFlagsForFunctionCheck(overloads[0]); - forEach(overloads, o => { - var deviation = getEffectiveFlagsForFunctionCheck(o) ^ canonicalFlags; - if (deviation & NodeFlags.Export) { - error(o.name, Diagnostics.Overload_signatures_must_all_be_exported_or_not_exported); - } - else if (deviation & NodeFlags.Ambient) { - error(o.name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); - } - else if (deviation & NodeFlags.Private) { - error(o.name, Diagnostics.Overload_signatures_must_all_be_public_or_private); - } - else if (deviation & NodeFlags.QuestionMark) { - error(o.name, Diagnostics.Overload_signatures_must_all_be_optional_or_required); - } - }); - } + function getCanonicalFlags(implementation: FunctionDeclaration, overloads: Declaration[]): NodeFlags { + // Consider the canonical set of flags to be the flags of the bodyDeclaration or the first declaration + // Error on all deviations from this canonical set of flags + // The caveat is that if some overloads are defined in lib.d.ts, we don't want to + // report the errors on those. To achieve this, we will say that the implementation is + // the canonical signature only if it is in the same container as the first overload + var implementationSharesContainerWithFirstOverload = implementation && implementation.parent === overloads[0].parent; + + return implementationSharesContainerWithFirstOverload + ? getEffectiveFlagsForFunctionCheck(implementation) + : getEffectiveFlagsForFunctionCheck(overloads[0]); } + function checkFlagAgreementBetweenOverloads(overloads: Declaration[], canonicalFlags: NodeFlags): void { + forEach(overloads, o => { + var deviation = getEffectiveFlagsForFunctionCheck(o) ^ canonicalFlags; + if (deviation & NodeFlags.Export) { + error(o.name, Diagnostics.Overload_signatures_must_all_be_exported_or_not_exported); + } + else if (deviation & NodeFlags.Ambient) { + error(o.name, Diagnostics.Overload_signatures_must_all_be_ambient_or_non_ambient); + } + else if (deviation & NodeFlags.Private) { + error(o.name, Diagnostics.Overload_signatures_must_all_be_public_or_private); + } + else if (deviation & NodeFlags.QuestionMark) { + error(o.name, Diagnostics.Overload_signatures_must_all_be_optional_or_required); + } + }); + } var flagsToCheck: NodeFlags = NodeFlags.Export | NodeFlags.Ambient | NodeFlags.Private | NodeFlags.QuestionMark; var someNodeFlags: NodeFlags = 0; var allNodeFlags = flagsToCheck; var hasOverloads = false; var bodyDeclaration: FunctionDeclaration; var lastSeenNonAmbientDeclaration: FunctionDeclaration; - var declarations = symbol.declarations; var isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0; - for (var i = 0; i < declarations.length; i++) { - var node = declarations[i]; - if (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.Method || node.kind === SyntaxKind.Constructor) { - var currentNodeFlags = getEffectiveFlagsForFunctionCheck(node); - someNodeFlags |= currentNodeFlags; - allNodeFlags &= currentNodeFlags; - - var inAmbientContext = isInAmbientContext(node); - var inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext; - if (!inAmbientContextOrInterface) { - lastSeenNonAmbientDeclaration = node; - } - - if (node.body) { - if (bodyDeclaration) { - if (isConstructor) { - error(node, Diagnostics.Multiple_constructor_implementations_are_not_allowed); + + function checkDeclarationsInSymbol(symbol: Symbol): void { + var declarations = symbol.declarations; + for (var i = 0; i < declarations.length; i++) { + var node = declarations[i]; + if (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.Method || node.kind === SyntaxKind.Constructor) { + var currentNodeFlags = getEffectiveFlagsForFunctionCheck(node); + someNodeFlags |= currentNodeFlags; + allNodeFlags &= currentNodeFlags; + + var inAmbientContext = isInAmbientContext(node); + var inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext; + if (!inAmbientContextOrInterface) { + lastSeenNonAmbientDeclaration = node; + } + + if (node.body) { + if (bodyDeclaration) { + if (isConstructor) { + error(node, Diagnostics.Multiple_constructor_implementations_are_not_allowed); + } + else { + error(node, Diagnostics.Duplicate_function_implementation); + } } else { - error(node, Diagnostics.Duplicate_function_implementation); + bodyDeclaration = node; } } else { - bodyDeclaration = node; + hasOverloads = true; } } + } + + if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body) { + if (isConstructor) { + error(lastSeenNonAmbientDeclaration, Diagnostics.Constructor_implementation_expected); + } else { - hasOverloads = true; + error(lastSeenNonAmbientDeclaration, Diagnostics.Function_implementation_expected); } } } - if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body) { - if (isConstructor) { - error(lastSeenNonAmbientDeclaration, Diagnostics.Constructor_implementation_expected); - } - else { - error(lastSeenNonAmbientDeclaration, Diagnostics.Function_implementation_expected); - } - } + forEachLocalSymbol(symbol, checkDeclarationsInSymbol); if (hasOverloads) { - checkFlagAgreementBetweenOverloads(declarations, bodyDeclaration, flagsToCheck, someNodeFlags, allNodeFlags); + // Error if some overloads have a flag that is not shared by all overloads. + if (someNodeFlags !== allNodeFlags) { + if (isExportSymbolWithAssociatedLocalSymbols(symbol)) { + var canonicalFlags: NodeFlags = getCanonicalFlags(bodyDeclaration, symbol.localSymbols[0].declarations); + forEach(symbol.localSymbols, s => checkFlagAgreementBetweenOverloads(s.declarations, canonicalFlags)); + } + else { + var canonicalFlags: NodeFlags = getCanonicalFlags(bodyDeclaration, symbol.declarations); + checkFlagAgreementBetweenOverloads(symbol.declarations, canonicalFlags); + } + } + if (bodyDeclaration) { var signatures = getSignaturesOfSymbol(symbol); var bodySignature = getSignatureFromDeclaration(bodyDeclaration); @@ -4846,16 +4878,103 @@ module ts { // TODO: Check at least one return statement in non-void/any function (except single throw) } + function isLocalSymbolAssociatedWithExportSymbol(s: Symbol): boolean { + return s.exportSymbol !== undefined; + } + + function isExportSymbolWithAssociatedLocalSymbols(s: Symbol): boolean { + return s.localSymbols !== undefined; + } + + function forEachLocalSymbol(s: Symbol, action: (symbol: Symbol) => void): void { + if (isExportSymbolWithAssociatedLocalSymbols(s)) { + forEach(s.localSymbols, action); + } + else { + action(s); + } + } + + function checkExportsOnMergedDeclarations(symbol: Symbol, node: Node): void { + if (symbol.flags & SymbolFlags.Prototype) { + return; + } + + if (!isExportSymbolWithAssociatedLocalSymbols(symbol)) { + // exit early if + // - this is pure local symbol - they don't have exports + // - this is local symbol associated with export symbol, + // all such symbols will be processed during the check of export symbol + return; + } + + // this is definitely export symbol + // in both cases run check just once for the first symbol in the list + if (getDeclarationOfKind(symbol, node.kind) !== node) { + return; + } + + // we use SymbolFlags.ExportValue, SymbolFlags.ExportType and SymbolFlags.ExportNamespace + // to denote disjoint declarationSpaces (without making new enum type). + var declarationSpaces: SymbolFlags = 0; + var hasExport: boolean; + function checkDeclarationsInSymbol(symbol: Symbol): void { + var declarations = symbol.declarations; + for (var i = 0, len = declarations.length; i < len; ++i) { + var currentDeclarationSpaces = getDeclarationSpaces(declarations[i]); + var currentDeclarationHasExport = (declarations[i].flags & NodeFlags.Export) !== 0; + if (declarationSpaces & currentDeclarationSpaces) { + if (hasExport !== undefined) { + if (hasExport !== currentDeclarationHasExport) { + error(declarations[i].name, Diagnostics.All_declarations_of_merged_declaration_0_must_be_exported_or_not_exported, symbolToString(symbol)); + } + } + } + hasExport = hasExport || currentDeclarationHasExport; + declarationSpaces |= currentDeclarationSpaces; + } + } + + forEachLocalSymbol(symbol, checkDeclarationsInSymbol); + + function getDeclarationSpaces(d: Declaration): SymbolFlags { + switch (d.kind) { + case SyntaxKind.InterfaceDeclaration: + return SymbolFlags.ExportType; + case SyntaxKind.ModuleDeclaration: + return (d).name.kind === SyntaxKind.StringLiteral || isInstantiated(d) + ? SymbolFlags.ExportNamespace | SymbolFlags.ExportValue + : SymbolFlags.ExportNamespace; + case SyntaxKind.ClassDeclaration: + case SyntaxKind.EnumDeclaration: + return SymbolFlags.ExportType | SymbolFlags.ExportValue; + case SyntaxKind.ImportDeclaration: + var target = resolveImport(getSymbolOfNode(d)); + return target.flags & (SymbolFlags.ExportNamespace | SymbolFlags.ExportType | SymbolFlags.ExportValue); + default: + return SymbolFlags.ExportValue; + } + } + } + + function runOnceForSymbol(symbol: Symbol, node: Declaration, action: (s: Symbol) => void) { + // all local symbols associated with export symbol will be processed during the check of export symbol. + if (!isLocalSymbolAssociatedWithExportSymbol(symbol)) { + // symbol here is either local only symbol or export symbol + // in both cases run action once if given declaration is a first in group + var firstDeclaration = getDeclarationOfKind(symbol, node.kind); + if (node === firstDeclaration) { + action(symbol); + } + } + } + function checkFunctionDeclaration(node: FunctionDeclaration) { checkDeclarationModifiers(node); checkSignatureDeclaration(node); - var symbol = getSymbolOfNode(node); - var firstDeclaration = getDeclarationOfKind(symbol, node.kind); - // Only type check the symbol once - if (node === firstDeclaration) { - checkFunctionOrConstructorSymbol(symbol); - } + runOnceForSymbol(getSymbolOfNode(node), node, checkFunctionOrConstructorSymbol); + checkSourceElement(node.body); // If there is no body and no explicit return type, then report an error. @@ -5010,6 +5129,7 @@ module ts { checkSourceElement(node.type); var symbol = getSymbolOfNode(node); + checkExportsOnMergedDeclarations(symbol, node); var typeOfValueDeclaration = getTypeOfVariableOrParameterOrProperty(symbol); var type: Type; @@ -5299,6 +5419,8 @@ module ts { checkTypeNameIsReserved(node.name, Diagnostics.Class_name_cannot_be_0); checkTypeParameters(node.typeParameters); var symbol = getSymbolOfNode(node); + checkExportsOnMergedDeclarations(symbol, node); + var type = getDeclaredTypeOfSymbol(symbol); var staticType = getTypeOfSymbol(symbol); if (node.baseType) { @@ -5453,16 +5575,31 @@ module ts { checkDeclarationModifiers(node); checkTypeNameIsReserved(node.name, Diagnostics.Interface_name_cannot_be_0); checkTypeParameters(node.typeParameters); + var symbol = getSymbolOfNode(node); - var firstInterfaceDecl = getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); + checkExportsOnMergedDeclarations(symbol, node); + + var hasMoreThanOneDeclaration: boolean; if (symbol.declarations.length > 1) { + hasMoreThanOneDeclaration = true; + } + else if (isExportSymbolWithAssociatedLocalSymbols(symbol)) { + // current symbol is export with just one exported declaration + // check if the local symbol (it should be there and should be just one) has more than 1 declarations. + Debug.assert(symbol.localSymbols.length === 1); + hasMoreThanOneDeclaration = symbol.localSymbols[0].declarations.length > 1; + } + if (hasMoreThanOneDeclaration) { + var firstInterfaceDecl = symbol.localSymbols + ? forEach(symbol.localSymbols, s => getDeclarationOfKind(s, SyntaxKind.InterfaceDeclaration)) + : getDeclarationOfKind(symbol, SyntaxKind.InterfaceDeclaration); + if (node !== firstInterfaceDecl && !areTypeParametersIdentical(firstInterfaceDecl.typeParameters, node.typeParameters)) { error(node.name, Diagnostics.All_declarations_of_an_interface_must_have_identical_type_parameters); } } - // Only check this symbol once - if (node === firstInterfaceDecl) { + runOnceForSymbol(symbol, node, symbol => { var type = getDeclaredTypeOfSymbol(symbol); // run subsequent checks only if first set succeeded if (checkInheritedPropertiesAreIdentical(type, node.name)) { @@ -5471,7 +5608,8 @@ module ts { }); checkIndexConstraints(type); } - } + }); + forEach(node.baseTypes, checkTypeReference); forEach(node.members, checkSourceElement); @@ -5499,6 +5637,7 @@ module ts { checkDeclarationModifiers(node); checkTypeNameIsReserved(node.name, Diagnostics.Enum_name_cannot_be_0); var enumSymbol = getSymbolOfNode(node); + checkExportsOnMergedDeclarations(enumSymbol, node); var enumType = getDeclaredTypeOfSymbol(enumSymbol); var autoValue = 0; var ambient = isInAmbientContext(node); @@ -5529,31 +5668,33 @@ module ts { // for the first member. // // Only perform this check once per symbol - var firstDeclaration = getDeclarationOfKind(enumSymbol, node.kind); - if (node === firstDeclaration) { + runOnceForSymbol(enumSymbol, node, symbol => { var seenEnumMissingInitialInitializer = false; - forEach(enumSymbol.declarations, declaration => { - // return true if we hit a violation of the rule, false otherwise - if (declaration.kind !== SyntaxKind.EnumDeclaration) { - return false; - } - var enumDeclaration = declaration; - if (!enumDeclaration.members.length) { - return false; - } + forEachLocalSymbol(symbol, localSymbol => { + forEach(localSymbol.declarations, declaration => { + // return true if we hit a violation of the rule, false otherwise + if (declaration.kind !== SyntaxKind.EnumDeclaration) { + return false; + } - var firstEnumMember = enumDeclaration.members[0]; - if (!firstEnumMember.initializer) { - if (seenEnumMissingInitialInitializer) { - error(firstEnumMember.name, Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element); + var enumDeclaration = declaration; + if (!enumDeclaration.members.length) { + return false; } - else { - seenEnumMissingInitialInitializer = true; + + var firstEnumMember = enumDeclaration.members[0]; + if (!firstEnumMember.initializer) { + if (seenEnumMissingInitialInitializer) { + error(firstEnumMember.name, Diagnostics.In_an_enum_with_multiple_declarations_only_one_declaration_can_omit_an_initializer_for_its_first_enum_element); + } + else { + seenEnumMissingInitialInitializer = true; + } } - } + }); }); - } + }); } function getFirstNonAmbientClassOrFunctionDeclaration(symbol: Symbol): Declaration { @@ -5570,6 +5711,7 @@ module ts { function checkModuleDeclaration(node: ModuleDeclaration) { checkDeclarationModifiers(node); var symbol = getSymbolOfNode(node); + checkExportsOnMergedDeclarations(symbol, node); if (symbol.flags & SymbolFlags.ValueModule && symbol.declarations.length > 1 && !isInAmbientContext(node)) { var classOrFunc = getFirstNonAmbientClassOrFunctionDeclaration(symbol); if (classOrFunc) { diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index d9e35f29086ca..812229b18fb0a 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -131,6 +131,7 @@ module ts { A_signature_with_an_implementation_cannot_use_a_string_literal_type: { code: 2163, category: DiagnosticCategory.Error, key: "A signature with an implementation cannot use a string literal type." }, Interface_0_cannot_simultaneously_extend_types_1_and_2_Colon: { code: 2189, category: DiagnosticCategory.Error, key: "Interface '{0}' cannot simultaneously extend types '{1}' and '{2}':" }, Initializer_of_parameter_0_cannot_reference_identifier_1_declared_after_it: { code: 2190, category: DiagnosticCategory.Error, key: "Initializer of parameter '{0}' cannot reference identifier '{1}' declared after it." }, + All_declarations_of_merged_declaration_0_must_be_exported_or_not_exported: { code: 2192, category: DiagnosticCategory.Error, key: "All declarations of merged declaration '{0}' must be exported or not exported." }, super_cannot_be_referenced_in_constructor_arguments: { code: 2193, category: DiagnosticCategory.Error, key: "'super' cannot be referenced in constructor arguments." }, Return_type_of_constructor_signature_must_be_assignable_to_the_instance_type_of_the_class: { code: 2194, category: DiagnosticCategory.Error, key: "Return type of constructor signature must be assignable to the instance type of the class" }, Ambient_external_module_declaration_cannot_specify_relative_module_name: { code: 2196, category: DiagnosticCategory.Error, key: "Ambient external module declaration cannot specify relative module name." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 92b8d1a3e0eed..d8b248ad1ba9b 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -518,6 +518,10 @@ "category": "Error", "code": 2190 }, + "All declarations of merged declaration '{0}' must be exported or not exported.": { + "category": "Error", + "code": 2192 + }, "'super' cannot be referenced in constructor arguments.":{ "category": "Error", "code": 2193 diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 65ca7d01fbdec..5b00ecedcf108 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -648,7 +648,6 @@ module ts { IndexSignature = 0x00020000, // Index signature TypeParameter = 0x00040000, // Type parameter - // Export markers (see comment in declareModuleMember in binder) ExportValue = 0x00080000, // Exported value marker ExportType = 0x00100000, // Exported type marker ExportNamespace = 0x00200000, // Exported namespace marker @@ -707,7 +706,8 @@ module ts { exports?: SymbolTable; // Module exports exportSymbol?: Symbol; // Exported symbol associated with this symbol exportAssignSymbol?: Symbol; // Symbol exported from external module - valueDeclaration?: Declaration // First value declaration of the symbol + valueDeclaration?: Declaration;// First value declaration of the symbol + localSymbols?: Symbol[]; // List of local symbols that contribute to the export symbol } export interface SymbolLinks { diff --git a/tests/baselines/reference/anonymousModules.errors.txt b/tests/baselines/reference/anonymousModules.errors.txt index bebc718c007a9..2663477cc3e15 100644 --- a/tests/baselines/reference/anonymousModules.errors.txt +++ b/tests/baselines/reference/anonymousModules.errors.txt @@ -24,7 +24,7 @@ var bar = 2; ~~~ -!!! Duplicate identifier 'bar'. +!!! All declarations of merged declaration 'bar' must be exported or not exported. module { ~ diff --git a/tests/baselines/reference/duplicateSymbolsExportMatching.errors.txt b/tests/baselines/reference/duplicateSymbolsExportMatching.errors.txt index 3bc10adf7ea9f..9360686d6e420 100644 --- a/tests/baselines/reference/duplicateSymbolsExportMatching.errors.txt +++ b/tests/baselines/reference/duplicateSymbolsExportMatching.errors.txt @@ -25,11 +25,11 @@ interface I { } export interface I { } // error ~ -!!! Duplicate identifier 'I'. +!!! All declarations of merged declaration 'I' must be exported or not exported. export interface E { } interface E { } // error ~ -!!! Duplicate identifier 'E'. +!!! All declarations of merged declaration 'E' must be exported or not exported. } // Should report error only once for instantiated module @@ -39,7 +39,7 @@ } export module inst { // one error ~~~~ -!!! Duplicate identifier 'inst'. +!!! All declarations of merged declaration 'inst' must be exported or not exported. var t; } } @@ -49,20 +49,20 @@ var v: string; export var v: string; // one error (visibility) ~ -!!! Duplicate identifier 'v'. +!!! All declarations of merged declaration 'v' must be exported or not exported. var w: number; export var w: string; // two errors (visibility and type mismatch) ~ -!!! Duplicate identifier 'w'. +!!! All declarations of merged declaration 'w' must be exported or not exported. } module M { module F { + ~ +!!! A module declaration cannot be located prior to a class or function with which it is merged var t; } export function F() { } // Only one error for duplicate identifier (don't consider visibility) - ~ -!!! Duplicate identifier 'F'. } module M { @@ -70,7 +70,7 @@ module C { } export module C { // Two visibility errors (one for the clodule symbol, and one for the merged container symbol) ~ -!!! Duplicate identifier 'C'. +!!! All declarations of merged declaration 'C' must be exported or not exported. var t; } } @@ -79,4 +79,4 @@ interface D { } export interface D { } ~ -!!! Duplicate identifier 'D'. \ No newline at end of file +!!! All declarations of merged declaration 'D' must be exported or not exported. \ No newline at end of file diff --git a/tests/baselines/reference/functionOverloadErrors.errors.txt b/tests/baselines/reference/functionOverloadErrors.errors.txt index a839c286f811a..c2fcff7a943c8 100644 --- a/tests/baselines/reference/functionOverloadErrors.errors.txt +++ b/tests/baselines/reference/functionOverloadErrors.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/conformance/functions/functionOverloadErrors.ts (19 errors) ==== +==== tests/cases/conformance/functions/functionOverloadErrors.ts (14 errors) ==== //Function overload signature with initializer function fn1(x = 3); ~~~~~ @@ -86,26 +86,16 @@ //Function overloads with differing export module M { export function fn1(); - ~~~~~~~~~~~~~~~~~~~~~~ -!!! Function implementation expected. + ~~~ +!!! Overload signatures must all be exported or not exported. function fn1(n: string); - ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! Function implementation expected. - ~~~ -!!! Duplicate identifier 'fn1'. function fn1() { } - ~~~ -!!! Duplicate identifier 'fn1'. function fn2(n: string); - ~~~~~~~~~~~~~~~~~~~~~~~~ -!!! Function implementation expected. + ~~~ +!!! Overload signatures must all be exported or not exported. export function fn2(); - ~~~ -!!! Duplicate identifier 'fn2'. export function fn2() { } - ~~~ -!!! Duplicate identifier 'fn2'. } //Function overloads with differing ambience diff --git a/tests/baselines/reference/multivar.errors.txt b/tests/baselines/reference/multivar.errors.txt index bc46109903d1e..66db194234d8f 100644 --- a/tests/baselines/reference/multivar.errors.txt +++ b/tests/baselines/reference/multivar.errors.txt @@ -22,7 +22,7 @@ declare var d1, d2; var b2; ~~ -!!! Duplicate identifier 'b2'. +!!! All declarations of merged declaration 'b2' must be exported or not exported. declare var v1; } diff --git a/tests/baselines/reference/overloadModifiersMustAgree.errors.txt b/tests/baselines/reference/overloadModifiersMustAgree.errors.txt index cad91215f0689..f2aa56b8e4d0b 100644 --- a/tests/baselines/reference/overloadModifiersMustAgree.errors.txt +++ b/tests/baselines/reference/overloadModifiersMustAgree.errors.txt @@ -1,4 +1,4 @@ -==== tests/cases/compiler/overloadModifiersMustAgree.ts (5 errors) ==== +==== tests/cases/compiler/overloadModifiersMustAgree.ts (4 errors) ==== class baz { public foo(); ~~~ @@ -10,10 +10,8 @@ ~~~ !!! Overload signatures must all be ambient or non-ambient. export function bar(s: string); - ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! Function implementation expected. ~~~ -!!! Duplicate identifier 'bar'. +!!! Overload signatures must all be exported or not exported. function bar(s?: string) { } interface I {