From 0df69ed1b62945bacf7cb269c9c54501703e1764 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 13 Feb 2015 10:07:37 -0800 Subject: [PATCH] Static checking for export declarations --- src/compiler/checker.ts | 37 ++++++++++++++----- .../diagnosticInformationMap.generated.ts | 5 ++- src/compiler/diagnosticMessages.json | 14 ++++++- 3 files changed, 44 insertions(+), 12 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 743a39b48fc..b72797daa4a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9358,7 +9358,7 @@ module ts { return node; } - function checkExternalImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration): boolean { + function checkExternalImportOrExportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration): boolean { var moduleName = getExternalModuleName(node); if (getFullWidth(moduleName) !== 0 && moduleName.kind !== SyntaxKind.StringLiteral) { error(moduleName, Diagnostics.String_literal_expected); @@ -9366,7 +9366,9 @@ module ts { } var inAmbientExternalModule = node.parent.kind === SyntaxKind.ModuleBlock && (node.parent.parent).name.kind === SyntaxKind.StringLiteral; if (node.parent.kind !== SyntaxKind.SourceFile && !inAmbientExternalModule) { - error(moduleName, Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module); + error(moduleName, node.kind === SyntaxKind.ExportDeclaration ? + Diagnostics.Export_declarations_are_not_permitted_in_an_internal_module : + Diagnostics.Import_declarations_in_an_internal_module_cannot_reference_an_external_module); return false; } if (inAmbientExternalModule && isExternalModuleNameRelative((moduleName).text)) { @@ -9374,13 +9376,13 @@ module ts { // An ExternalImportDeclaration in an AmbientExternalModuleDeclaration may reference // other external modules only through top - level external module names. // Relative external module names are not permitted. - error(node, Diagnostics.Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name); + error(node, Diagnostics.Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name); return false; } return true; } - function checkImportSymbol(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier) { + function checkImportSymbol(node: ImportEqualsDeclaration | ImportClause | NamespaceImport | ImportSpecifier | ExportSpecifier) { var symbol = getSymbolOfNode(node); var target = resolveImport(symbol); if (target !== unknownSymbol) { @@ -9389,7 +9391,10 @@ module ts { (symbol.flags & SymbolFlags.Type ? SymbolFlags.Type : 0) | (symbol.flags & SymbolFlags.Namespace ? SymbolFlags.Namespace : 0); if (target.flags & excludedMeanings) { - error(node, Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0, symbolToString(symbol)); + var message = node.kind === SyntaxKind.ExportSpecifier ? + Diagnostics.Export_declaration_conflicts_with_exported_declaration_of_0 : + Diagnostics.Import_declaration_conflicts_with_local_declaration_of_0; + error(node, message, symbolToString(symbol)); } } } @@ -9404,15 +9409,13 @@ module ts { if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) { grammarErrorOnFirstToken(node, Diagnostics.An_import_declaration_cannot_have_modifiers); } - if (checkExternalImportDeclaration(node)) { + if (checkExternalImportOrExportDeclaration(node)) { var importClause = node.importClause; if (importClause) { if (importClause.name) { - // TODO: Check that import references an export default instance checkImportBinding(importClause); } if (importClause.namedBindings) { - // TODO: Check that import references an export namespace if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { checkImportBinding(importClause.namedBindings); } @@ -9448,12 +9451,23 @@ module ts { } } else { - if (checkExternalImportDeclaration(node)) { + if (checkExternalImportOrExportDeclaration(node)) { checkImportBinding(node); } } } + function checkExportDeclaration(node: ExportDeclaration) { + if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) { + grammarErrorOnFirstToken(node, Diagnostics.An_export_declaration_cannot_have_modifiers); + } + if (!node.moduleSpecifier || checkExternalImportOrExportDeclaration(node)) { + if (node.exportClause) { + forEach(node.exportClause.elements, checkImportSymbol); + } + } + } + function checkExportAssignment(node: ExportAssignment) { // Grammar checking if (!checkGrammarModifiers(node) && (node.flags & NodeFlags.Modifier)) { @@ -9559,6 +9573,8 @@ module ts { return checkImportDeclaration(node); case SyntaxKind.ImportEqualsDeclaration: return checkImportEqualsDeclaration(node); + case SyntaxKind.ExportDeclaration: + return checkExportDeclaration(node); case SyntaxKind.ExportAssignment: return checkExportAssignment(node); case SyntaxKind.EmptyStatement: @@ -10491,12 +10507,13 @@ module ts { case SyntaxKind.InterfaceDeclaration: case SyntaxKind.ModuleDeclaration: case SyntaxKind.EnumDeclaration: - case SyntaxKind.ExportAssignment: case SyntaxKind.VariableStatement: case SyntaxKind.FunctionDeclaration: case SyntaxKind.TypeAliasDeclaration: case SyntaxKind.ImportDeclaration: case SyntaxKind.ImportEqualsDeclaration: + case SyntaxKind.ExportDeclaration: + case SyntaxKind.ExportAssignment: case SyntaxKind.Parameter: break; default: diff --git a/src/compiler/diagnosticInformationMap.generated.ts b/src/compiler/diagnosticInformationMap.generated.ts index 495145f1b6b..a6c9b5399d1 100644 --- a/src/compiler/diagnosticInformationMap.generated.ts +++ b/src/compiler/diagnosticInformationMap.generated.ts @@ -149,6 +149,8 @@ module ts { A_parameter_property_may_not_be_a_binding_pattern: { code: 1187, category: DiagnosticCategory.Error, key: "A parameter property may not be a binding pattern." }, An_import_declaration_cannot_have_modifiers: { code: 1188, category: DiagnosticCategory.Error, key: "An import declaration cannot have modifiers." }, External_module_0_has_no_default_export_or_export_assignment: { code: 1189, category: DiagnosticCategory.Error, key: "External module '{0}' has no default export or export assignment." }, + An_export_declaration_cannot_have_modifiers: { code: 1190, category: DiagnosticCategory.Error, key: "An export declaration cannot have modifiers." }, + Export_declarations_are_not_permitted_in_an_internal_module: { code: 1191, category: DiagnosticCategory.Error, key: "Export declarations are not permitted in an internal module." }, Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." }, Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." }, Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." }, @@ -277,7 +279,7 @@ module ts { Ambient_external_module_declaration_cannot_specify_relative_module_name: { code: 2436, category: DiagnosticCategory.Error, key: "Ambient external module declaration cannot specify relative module name." }, Module_0_is_hidden_by_a_local_declaration_with_the_same_name: { code: 2437, category: DiagnosticCategory.Error, key: "Module '{0}' is hidden by a local declaration with the same name" }, Import_name_cannot_be_0: { code: 2438, category: DiagnosticCategory.Error, key: "Import name cannot be '{0}'" }, - Import_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: { code: 2439, category: DiagnosticCategory.Error, key: "Import declaration in an ambient external module declaration cannot reference external module through relative external module name." }, + Import_or_export_declaration_in_an_ambient_external_module_declaration_cannot_reference_external_module_through_relative_external_module_name: { code: 2439, category: DiagnosticCategory.Error, key: "Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name." }, Import_declaration_conflicts_with_local_declaration_of_0: { code: 2440, category: DiagnosticCategory.Error, key: "Import declaration conflicts with local declaration of '{0}'" }, Duplicate_identifier_0_Compiler_reserves_name_1_in_top_level_scope_of_an_external_module: { code: 2441, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'. Compiler reserves name '{1}' in top level scope of an external module." }, Types_have_separate_declarations_of_a_private_property_0: { code: 2442, category: DiagnosticCategory.Error, key: "Types have separate declarations of a private property '{0}'." }, @@ -306,6 +308,7 @@ module ts { super_cannot_be_referenced_in_a_computed_property_name: { code: 2466, category: DiagnosticCategory.Error, key: "'super' cannot be referenced in a computed property name." }, A_computed_property_name_cannot_reference_a_type_parameter_from_its_containing_type: { code: 2466, category: DiagnosticCategory.Error, key: "A computed property name cannot reference a type parameter from its containing type." }, Spread_operator_in_new_expressions_is_only_available_when_targeting_ECMAScript_6_and_higher: { code: 2468, category: DiagnosticCategory.Error, key: "Spread operator in 'new' expressions is only available when targeting ECMAScript 6 and higher." }, + Export_declaration_conflicts_with_exported_declaration_of_0: { code: 2469, category: DiagnosticCategory.Error, key: "Export declaration conflicts with exported declaration of '{0}'" }, Import_declaration_0_is_using_private_name_1: { code: 4000, category: DiagnosticCategory.Error, key: "Import declaration '{0}' is using private name '{1}'." }, Type_parameter_0_of_exported_class_has_or_is_using_private_name_1: { code: 4002, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported class has or is using private name '{1}'." }, Type_parameter_0_of_exported_interface_has_or_is_using_private_name_1: { code: 4004, category: DiagnosticCategory.Error, key: "Type parameter '{0}' of exported interface has or is using private name '{1}'." }, diff --git a/src/compiler/diagnosticMessages.json b/src/compiler/diagnosticMessages.json index 5bc9eedb386..16cfe5e10e8 100644 --- a/src/compiler/diagnosticMessages.json +++ b/src/compiler/diagnosticMessages.json @@ -587,6 +587,14 @@ "category": "Error", "code": 1189 }, + "An export declaration cannot have modifiers.": { + "category": "Error", + "code": 1190 + }, + "Export declarations are not permitted in an internal module.": { + "category": "Error", + "code": 1191 + }, "Duplicate identifier '{0}'.": { "category": "Error", @@ -1100,7 +1108,7 @@ "category": "Error", "code": 2438 }, - "Import declaration in an ambient external module declaration cannot reference external module through relative external module name.": { + "Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name.": { "category": "Error", "code": 2439 }, @@ -1216,6 +1224,10 @@ "category": "Error", "code": 2468 }, + "Export declaration conflicts with exported declaration of '{0}'": { + "category": "Error", + "code": 2469 + }, "Import declaration '{0}' is using private name '{1}'.": { "category": "Error",