From 79be0a7d26bcedc2d59b121f5f3cbc47923f5854 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 12 Feb 2015 18:05:02 -0800 Subject: [PATCH 1/9] Support for ES6 export declarations (except export default and export *) --- src/compiler/binder.ts | 58 +++++++------- src/compiler/checker.ts | 47 ++++++++--- src/compiler/emitter.ts | 122 +++++++++++++++++++++++------ src/compiler/parser.ts | 161 ++++++++++++++++++++++++-------------- src/compiler/program.ts | 4 +- src/compiler/types.ts | 28 +++++-- src/compiler/utilities.ts | 6 +- 7 files changed, 293 insertions(+), 133 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 5a4a983537a..4bd562291d5 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -15,11 +15,11 @@ module ts { if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.TypeAliasDeclaration) { return ModuleInstanceState.NonInstantiated; } - // 2. const enum declarations don't make module instantiated + // 2. const enum declarations else if (isConstEnumDeclaration(node)) { return ModuleInstanceState.ConstEnumOnly; } - // 3. non - exported import declarations + // 3. non-exported import declarations else if ((node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) && !(node.flags & NodeFlags.Export)) { return ModuleInstanceState.NonInstantiated; } @@ -185,42 +185,39 @@ 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. - // 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. - var exportKind = 0; - if (symbolKind & SymbolFlags.Value) { - exportKind |= SymbolFlags.ExportValue; + var hasExportModifier = getCombinedNodeFlags(node) & NodeFlags.Export; + if (symbolKind & SymbolFlags.Import) { + if (node.kind === SyntaxKind.ExportSpecifier || (node.kind === SyntaxKind.ImportEqualsDeclaration && hasExportModifier)) { + declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes); + } + else { + declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes); + } } - if (symbolKind & SymbolFlags.Type) { - exportKind |= SymbolFlags.ExportType; - } - if (symbolKind & SymbolFlags.Namespace) { - exportKind |= SymbolFlags.ExportNamespace; - } - - if (getCombinedNodeFlags(node) & NodeFlags.Export || - (node.kind !== SyntaxKind.ImportDeclaration && node.kind !== SyntaxKind.ImportEqualsDeclaration && isAmbientContext(container))) { - if (exportKind) { + else { + // 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. + // 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. + if (hasExportModifier || isAmbientContext(container)) { + var exportKind = (symbolKind & SymbolFlags.Value ? SymbolFlags.ExportValue : 0) | + (symbolKind & SymbolFlags.Type ? SymbolFlags.ExportType : 0) | + (symbolKind & SymbolFlags.Namespace ? SymbolFlags.ExportNamespace : 0); var local = declareSymbol(container.locals, undefined, node, exportKind, symbolExcludes); local.exportSymbol = declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes); node.localSymbol = local; } else { - declareSymbol(container.symbol.exports, container.symbol, node, symbolKind, symbolExcludes); + declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes); } } - else { - declareSymbol(container.locals, undefined, node, symbolKind, symbolExcludes); - } } // All container nodes are kept on a linked list in declaration order. This list is used by the getLocalNameOfContainer function @@ -477,6 +474,7 @@ module ts { case SyntaxKind.ImportEqualsDeclaration: case SyntaxKind.NamespaceImport: case SyntaxKind.ImportSpecifier: + case SyntaxKind.ExportSpecifier: bindDeclaration(node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false); break; case SyntaxKind.ImportClause: diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 11b9de61b26..743a39b48fc 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -446,7 +446,8 @@ module ts { return node.kind === SyntaxKind.ImportEqualsDeclaration || node.kind === SyntaxKind.ImportClause && !!(node).name || node.kind === SyntaxKind.NamespaceImport || - node.kind === SyntaxKind.ImportSpecifier; + node.kind === SyntaxKind.ImportSpecifier || + node.kind === SyntaxKind.ExportSpecifier; } function getDeclarationOfImportSymbol(symbol: Symbol): Declaration { @@ -477,10 +478,10 @@ module ts { return resolveExternalModuleName(node, (node.parent.parent).moduleSpecifier); } - function getTargetOfImportSpecifier(node: ImportSpecifier): Symbol { - var moduleSymbol = resolveExternalModuleName(node, (node.parent.parent.parent).moduleSpecifier); + function getExternalModuleMember(node: ImportDeclaration | ExportDeclaration, specifier: ImportOrExportSpecifier): Symbol { + var moduleSymbol = resolveExternalModuleName(node, node.moduleSpecifier); if (moduleSymbol) { - var name = node.propertyName || node.name; + var name = specifier.propertyName || specifier.name; if (name.text) { var symbol = getSymbol(moduleSymbol.exports, name.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace); if (!symbol) { @@ -492,6 +493,16 @@ module ts { } } + function getTargetOfImportSpecifier(node: ImportSpecifier): Symbol { + return getExternalModuleMember(node.parent.parent.parent, node); + } + + function getTargetOfExportSpecifier(node: ExportSpecifier): Symbol { + return (node.parent.parent).moduleSpecifier ? + getExternalModuleMember(node.parent.parent, node) : + resolveEntityName(node, node.propertyName || node.name, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace); + } + function getTargetOfImportDeclaration(node: Declaration): Symbol { switch (node.kind) { case SyntaxKind.ImportEqualsDeclaration: @@ -502,6 +513,8 @@ module ts { return getTargetOfNamespaceImport(node); case SyntaxKind.ImportSpecifier: return getTargetOfImportSpecifier(node); + case SyntaxKind.ExportSpecifier: + return getTargetOfExportSpecifier(node); } } @@ -9346,7 +9359,7 @@ module ts { } function checkExternalImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration): boolean { - var moduleName = getImportedModuleName(node); + var moduleName = getExternalModuleName(node); if (getFullWidth(moduleName) !== 0 && moduleName.kind !== SyntaxKind.StringLiteral) { error(moduleName, Diagnostics.String_literal_expected); return false; @@ -10174,6 +10187,9 @@ module ts { case SyntaxKind.ImportDeclaration: generateNameForImportDeclaration(node); break; + case SyntaxKind.ExportDeclaration: + generateNameForExportDeclaration(node); + break; case SyntaxKind.SourceFile: case SyntaxKind.ModuleBlock: forEach((node).statements, generateNames); @@ -10219,17 +10235,27 @@ module ts { } } + function generateNameForImportOrExportDeclaration(node: ImportDeclaration | ExportDeclaration) { + var expr = getExternalModuleName(node); + var baseName = expr.kind === SyntaxKind.StringLiteral ? + escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; + assignGeneratedName(node, makeUniqueName(baseName)); + } + function generateNameForImportDeclaration(node: ImportDeclaration) { if (node.importClause && node.importClause.namedBindings && node.importClause.namedBindings.kind === SyntaxKind.NamedImports) { - var expr = getImportedModuleName(node); - var baseName = expr.kind === SyntaxKind.StringLiteral ? - escapeIdentifier(makeIdentifierFromModuleName((expr).text)) : "module"; - assignGeneratedName(node, makeUniqueName(baseName)); + generateNameForImportOrExportDeclaration(node); + } + } + + function generateNameForExportDeclaration(node: ExportDeclaration) { + if (node.moduleSpecifier) { + generateNameForImportOrExportDeclaration(node); } } } - function getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration) { + function getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration) { var links = getNodeLinks(node); if (!links.generatedName) { getGeneratedNamesForSourceFile(getSourceFile(node)); @@ -11322,6 +11348,7 @@ module ts { if (node.kind === SyntaxKind.InterfaceDeclaration || node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration || + node.kind === SyntaxKind.ExportDeclaration || node.kind === SyntaxKind.ExportAssignment || (node.flags & NodeFlags.Ambient)) { diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index b05dd62a86f..552c7201279 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -17,7 +17,7 @@ module ts { } interface ExternalImportInfo { - importNode: ImportDeclaration | ImportEqualsDeclaration; + rootNode: ImportDeclaration | ImportEqualsDeclaration | ExportDeclaration; declarationNode?: ImportEqualsDeclaration | ImportClause | NamespaceImport; namedImports?: NamedImports; } @@ -1568,6 +1568,7 @@ module ts { var tempVariables: Identifier[]; var tempParameters: Identifier[]; var externalImports: ExternalImportInfo[]; + var exportSpecifiers: Map; /** write emitted output to disk*/ var writeEmittedFiles = writeJavaScriptFile; @@ -3067,6 +3068,20 @@ module ts { emitEnd(node.name); } + function emitExportMemberAssignment(name: Identifier) { + if (exportSpecifiers && hasProperty(exportSpecifiers, name.text)) { + var exportName = exportSpecifiers[name.text].name; + writeLine(); + emitStart(exportName); + write("exports."); + emitNode(exportName); + emitEnd(exportName); + write(" = "); + emitNode(name); + write(";"); + } + } + function emitDestructuring(root: BinaryExpression | VariableDeclaration | ParameterDeclaration, value?: Expression) { var emitCount = 0; // An exported declaration is actually emitted as an assignment (to a property on the module object), so @@ -3299,6 +3314,16 @@ module ts { } } + function emitExportVariableAssignments(node: VariableDeclaration | BindingElement) { + var name = (node).name; + if (name.kind === SyntaxKind.Identifier) { + emitExportMemberAssignment(name); + } + else if (isBindingPattern(name)) { + forEach((name).elements, emitExportVariableAssignments); + } + } + function emitVariableStatement(node: VariableStatement) { if (!(node.flags & NodeFlags.Export)) { if (isLet(node.declarationList)) { @@ -3313,6 +3338,9 @@ module ts { } emitCommaList(node.declarationList.declarations); write(";"); + if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) { + forEach(node.declarationList.declarations, emitExportVariableAssignments); + } } function emitParameter(node: ParameterDeclaration) { @@ -3437,6 +3465,9 @@ module ts { emit(node.name); } emitSignatureAndBody(node); + if (languageVersion < ScriptTarget.ES6 && node.kind === SyntaxKind.FunctionDeclaration && node.parent === currentSourceFile) { + emitExportMemberAssignment((node).name); + } if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) { emitTrailingComments(node); } @@ -3773,6 +3804,9 @@ module ts { emitEnd(node); write(";"); } + if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) { + emitExportMemberAssignment(node.name); + } function emitConstructorOfClass() { var saveTempCount = tempCount; @@ -3899,6 +3933,9 @@ module ts { emitEnd(node); write(";"); } + if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) { + emitExportMemberAssignment(node.name); + } } function emitEnumMember(node: EnumMember) { @@ -3997,6 +4034,9 @@ module ts { emitModuleMemberName(node); write(" = {}));"); emitEnd(node); + if (languageVersion < ScriptTarget.ES6 && node.name.kind === SyntaxKind.Identifier && node.parent === currentSourceFile) { + emitExportMemberAssignment(node.name); + } } function emitRequire(moduleName: Expression) { @@ -4013,13 +4053,6 @@ module ts { } } - function emitImportAssignment(node: Declaration, moduleName: Expression) { - if (!(node.flags & NodeFlags.Export)) write("var "); - emitModuleMemberName(node); - write(" = "); - emitRequire(moduleName); - } - function emitImportDeclaration(node: ImportDeclaration | ImportEqualsDeclaration) { var info = getExternalImportInfo(node); if (info) { @@ -4028,7 +4061,7 @@ module ts { if (compilerOptions.module !== ModuleKind.AMD) { emitLeadingComments(node); emitStart(node); - var moduleName = getImportedModuleName(node); + var moduleName = getExternalModuleName(node); if (declarationNode) { if (!(declarationNode.flags & NodeFlags.Export)) write("var "); emitModuleMemberName(declarationNode); @@ -4082,11 +4115,35 @@ module ts { } } + function emitExportDeclaration(node: ExportDeclaration) { + if (node.exportClause && node.moduleSpecifier) { + var generatedName = resolver.getGeneratedNameForNode(node); + emitStart(node); + write("var "); + write(generatedName); + write(" = "); + emitRequire(getExternalModuleName(node)); + forEach(node.exportClause.elements, specifier => { + writeLine(); + emitStart(specifier); + write("exports."); + emitNode(specifier.name); + write(" = "); + write(generatedName); + write("."); + emitNode(specifier.propertyName || specifier.name); + write(";"); + emitEnd(specifier); + }); + emitEnd(node); + } + } + function createExternalImportInfo(node: Node): ExternalImportInfo { if (node.kind === SyntaxKind.ImportEqualsDeclaration) { if ((node).moduleReference.kind === SyntaxKind.ExternalModuleReference) { return { - importNode: node, + rootNode: node, declarationNode: node }; } @@ -4096,35 +4153,50 @@ module ts { if (importClause) { if (importClause.name) { return { - importNode: node, + rootNode: node, declarationNode: importClause }; } if (importClause.namedBindings.kind === SyntaxKind.NamespaceImport) { return { - importNode: node, + rootNode: node, declarationNode: importClause.namedBindings }; } return { - importNode: node, + rootNode: node, namedImports: importClause.namedBindings, localName: resolver.getGeneratedNameForNode(node) }; } return { - importNode: node + rootNode: node + } + } + else if (node.kind === SyntaxKind.ExportDeclaration) { + if ((node).moduleSpecifier) { + return { + rootNode: node, + }; } } } - function createExternalImports(sourceFile: SourceFile) { + function createExternalModuleInfo(sourceFile: SourceFile) { externalImports = []; + exportSpecifiers = {}; forEach(sourceFile.statements, node => { - var info = createExternalImportInfo(node); - if (info) { - if ((!info.declarationNode && !info.namedImports) || resolver.isReferencedImportDeclaration(node)) { - externalImports.push(info); + if (node.kind === SyntaxKind.ExportDeclaration && !(node).moduleSpecifier) { + forEach((node).exportClause.elements, e => { + exportSpecifiers[(e.propertyName || e.name).text] = e; + }); + } + else { + var info = createExternalImportInfo(node); + if (info) { + if ((!info.declarationNode && !info.namedImports) || resolver.isReferencedImportDeclaration(node)) { + externalImports.push(info); + } } } }); @@ -4134,7 +4206,7 @@ module ts { if (externalImports) { for (var i = 0; i < externalImports.length; i++) { var info = externalImports[i]; - if (info.importNode === node) { + if (info.rootNode === node) { return info; } } @@ -4158,7 +4230,7 @@ module ts { write("[\"require\", \"exports\""); forEach(externalImports, info => { write(", "); - var moduleName = getImportedModuleName(info.importNode); + var moduleName = getExternalModuleName(info.rootNode); if (moduleName.kind === SyntaxKind.StringLiteral) { emitLiteral(moduleName); } @@ -4178,7 +4250,7 @@ module ts { emit(info.declarationNode.name); } else { - write(resolver.getGeneratedNameForNode(info.importNode)); + write(resolver.getGeneratedNameForNode(info.rootNode)); } }); write(") {"); @@ -4263,7 +4335,7 @@ module ts { extendsEmitted = true; } if (isExternalModule(node)) { - createExternalImports(node); + createExternalModuleInfo(node); if (compilerOptions.module === ModuleKind.AMD) { emitAMDModule(node, startIndex); } @@ -4272,6 +4344,8 @@ module ts { } } else { + externalImports = undefined; + exportSpecifiers = undefined; emitCaptureThisForNodeIfNecessary(node); emitLinesStartingAt(node.statements, startIndex); emitTempDeclarations(/*newLine*/ true); @@ -4474,6 +4548,8 @@ module ts { return emitImportDeclaration(node); case SyntaxKind.ImportEqualsDeclaration: return emitImportEqualsDeclaration(node); + case SyntaxKind.ExportDeclaration: + return emitExportDeclaration(node); case SyntaxKind.SourceFile: return emitSourceFile(node); } diff --git a/src/compiler/parser.ts b/src/compiler/parser.ts index 76b1f2cb32b..a9e2a98bab8 100644 --- a/src/compiler/parser.ts +++ b/src/compiler/parser.ts @@ -261,10 +261,16 @@ module ts { case SyntaxKind.NamespaceImport: return visitNode(cbNode, (node).name); case SyntaxKind.NamedImports: - return visitNodes(cbNodes, (node).elements); + case SyntaxKind.NamedExports: + return visitNodes(cbNodes, (node).elements); + case SyntaxKind.ExportDeclaration: + return visitNodes(cbNodes, node.modifiers) || + visitNode(cbNode, (node).exportClause) || + visitNode(cbNode, (node).moduleSpecifier); case SyntaxKind.ImportSpecifier: - return visitNode(cbNode, (node).propertyName) || - visitNode(cbNode, (node).name); + case SyntaxKind.ExportSpecifier: + return visitNode(cbNode, (node).propertyName) || + visitNode(cbNode, (node).name); case SyntaxKind.ExportAssignment: return visitNodes(cbNodes, node.modifiers) || visitNode(cbNode, (node).exportName); @@ -282,28 +288,28 @@ module ts { } const enum ParsingContext { - SourceElements, // Elements in source file - ModuleElements, // Elements in module declaration - BlockStatements, // Statements in block - SwitchClauses, // Clauses in switch statement - SwitchClauseStatements, // Statements in switch clause - TypeMembers, // Members in interface or type literal - ClassMembers, // Members in class declaration - EnumMembers, // Members in enum declaration - TypeReferences, // Type references in extends or implements clause - VariableDeclarations, // Variable declarations in variable statement - ObjectBindingElements, // Binding elements in object binding list - ArrayBindingElements, // Binding elements in array binding list - ArgumentExpressions, // Expressions in argument list - ObjectLiteralMembers, // Members in object literal - ArrayLiteralMembers, // Members in array literal - Parameters, // Parameters in parameter list - TypeParameters, // Type parameters in type parameter list - TypeArguments, // Type arguments in type argument list - TupleElementTypes, // Element types in tuple element type list - HeritageClauses, // Heritage clauses for a class or interface declaration. - ImportSpecifiers, // Named import clause's import specifier list - Count // Number of parsing contexts + SourceElements, // Elements in source file + ModuleElements, // Elements in module declaration + BlockStatements, // Statements in block + SwitchClauses, // Clauses in switch statement + SwitchClauseStatements, // Statements in switch clause + TypeMembers, // Members in interface or type literal + ClassMembers, // Members in class declaration + EnumMembers, // Members in enum declaration + TypeReferences, // Type references in extends or implements clause + VariableDeclarations, // Variable declarations in variable statement + ObjectBindingElements, // Binding elements in object binding list + ArrayBindingElements, // Binding elements in array binding list + ArgumentExpressions, // Expressions in argument list + ObjectLiteralMembers, // Members in object literal + ArrayLiteralMembers, // Members in array literal + Parameters, // Parameters in parameter list + TypeParameters, // Type parameters in type parameter list + TypeArguments, // Type arguments in type argument list + TupleElementTypes, // Element types in tuple element type list + HeritageClauses, // Heritage clauses for a class or interface declaration. + ImportOrExportSpecifiers, // Named import clause's import specifier list + Count // Number of parsing contexts } const enum Tristate { @@ -314,27 +320,27 @@ module ts { function parsingContextErrors(context: ParsingContext): DiagnosticMessage { switch (context) { - case ParsingContext.SourceElements: return Diagnostics.Declaration_or_statement_expected; - case ParsingContext.ModuleElements: return Diagnostics.Declaration_or_statement_expected; - case ParsingContext.BlockStatements: return Diagnostics.Statement_expected; - case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected; - case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected; - case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected; - case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected; - case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected; - case ParsingContext.TypeReferences: return Diagnostics.Type_reference_expected; - case ParsingContext.VariableDeclarations: return Diagnostics.Variable_declaration_expected; - case ParsingContext.ObjectBindingElements: return Diagnostics.Property_destructuring_pattern_expected; - case ParsingContext.ArrayBindingElements: return Diagnostics.Array_element_destructuring_pattern_expected; - case ParsingContext.ArgumentExpressions: return Diagnostics.Argument_expression_expected; - case ParsingContext.ObjectLiteralMembers: return Diagnostics.Property_assignment_expected; - case ParsingContext.ArrayLiteralMembers: return Diagnostics.Expression_or_comma_expected; - case ParsingContext.Parameters: return Diagnostics.Parameter_declaration_expected; - case ParsingContext.TypeParameters: return Diagnostics.Type_parameter_declaration_expected; - case ParsingContext.TypeArguments: return Diagnostics.Type_argument_expected; - case ParsingContext.TupleElementTypes: return Diagnostics.Type_expected; - case ParsingContext.HeritageClauses: return Diagnostics.Unexpected_token_expected; - case ParsingContext.ImportSpecifiers: return Diagnostics.Identifier_expected; + case ParsingContext.SourceElements: return Diagnostics.Declaration_or_statement_expected; + case ParsingContext.ModuleElements: return Diagnostics.Declaration_or_statement_expected; + case ParsingContext.BlockStatements: return Diagnostics.Statement_expected; + case ParsingContext.SwitchClauses: return Diagnostics.case_or_default_expected; + case ParsingContext.SwitchClauseStatements: return Diagnostics.Statement_expected; + case ParsingContext.TypeMembers: return Diagnostics.Property_or_signature_expected; + case ParsingContext.ClassMembers: return Diagnostics.Unexpected_token_A_constructor_method_accessor_or_property_was_expected; + case ParsingContext.EnumMembers: return Diagnostics.Enum_member_expected; + case ParsingContext.TypeReferences: return Diagnostics.Type_reference_expected; + case ParsingContext.VariableDeclarations: return Diagnostics.Variable_declaration_expected; + case ParsingContext.ObjectBindingElements: return Diagnostics.Property_destructuring_pattern_expected; + case ParsingContext.ArrayBindingElements: return Diagnostics.Array_element_destructuring_pattern_expected; + case ParsingContext.ArgumentExpressions: return Diagnostics.Argument_expression_expected; + case ParsingContext.ObjectLiteralMembers: return Diagnostics.Property_assignment_expected; + case ParsingContext.ArrayLiteralMembers: return Diagnostics.Expression_or_comma_expected; + case ParsingContext.Parameters: return Diagnostics.Parameter_declaration_expected; + case ParsingContext.TypeParameters: return Diagnostics.Type_parameter_declaration_expected; + case ParsingContext.TypeArguments: return Diagnostics.Type_argument_expected; + case ParsingContext.TupleElementTypes: return Diagnostics.Type_expected; + case ParsingContext.HeritageClauses: return Diagnostics.Unexpected_token_expected; + case ParsingContext.ImportOrExportSpecifiers: return Diagnostics.Identifier_expected; } }; @@ -1481,7 +1487,10 @@ module ts { // 'const' is only a modifier if followed by 'enum'. return nextToken() === SyntaxKind.EnumKeyword; } - + if (token === SyntaxKind.ExportKeyword) { + nextToken(); + return token !== SyntaxKind.AsteriskToken && token !== SyntaxKind.OpenBraceToken && canFollowModifier(); + } nextToken(); return canFollowModifier(); } @@ -1541,7 +1550,7 @@ module ts { return token === SyntaxKind.CommaToken || isStartOfType(); case ParsingContext.HeritageClauses: return isHeritageClause(); - case ParsingContext.ImportSpecifiers: + case ParsingContext.ImportOrExportSpecifiers: return isIdentifierOrKeyword(); } @@ -1579,7 +1588,7 @@ module ts { case ParsingContext.EnumMembers: case ParsingContext.ObjectLiteralMembers: case ParsingContext.ObjectBindingElements: - case ParsingContext.ImportSpecifiers: + case ParsingContext.ImportOrExportSpecifiers: return token === SyntaxKind.CloseBraceToken; case ParsingContext.SwitchClauseStatements: return token === SyntaxKind.CloseBraceToken || token === SyntaxKind.CaseKeyword || token === SyntaxKind.DefaultKeyword; @@ -4671,7 +4680,7 @@ module ts { // parse namespace or named imports if (!importClause.name || parseOptional(SyntaxKind.CommaToken)) { - importClause.namedBindings = token === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImports(); + importClause.namedBindings = token === SyntaxKind.AsteriskToken ? parseNamespaceImport() : parseNamedImportsOrExports(SyntaxKind.NamedImports); } return finishNode(importClause); @@ -4715,8 +4724,8 @@ module ts { return finishNode(namespaceImport); } - function parseNamedImports(): NamedImports { - var namedImports = createNode(SyntaxKind.NamedImports); + function parseNamedImportsOrExports(kind: SyntaxKind): NamedImportsOrExports { + var node = createNode(kind); // NamedImports: // { } @@ -4726,12 +4735,22 @@ module ts { // ImportsList: // ImportSpecifier // ImportsList, ImportSpecifier - namedImports.elements = parseBracketedList(ParsingContext.ImportSpecifiers, parseImportSpecifier, SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken); - return finishNode(namedImports); + node.elements = parseBracketedList(ParsingContext.ImportOrExportSpecifiers, + kind === SyntaxKind.NamedImports ? parseImportSpecifier : parseExportSpecifier, + SyntaxKind.OpenBraceToken, SyntaxKind.CloseBraceToken); + return finishNode(node); } - function parseImportSpecifier(): ImportSpecifier { - var node = createNode(SyntaxKind.ImportSpecifier); + function parseExportSpecifier() { + return parseImportOrExportSpecifier(SyntaxKind.ExportSpecifier); + } + + function parseImportSpecifier() { + return parseImportOrExportSpecifier(SyntaxKind.ImportSpecifier); + } + + function parseImportOrExportSpecifier(kind: SyntaxKind): ImportOrExportSpecifier { + var node = createNode(kind); // ImportSpecifier: // ImportedBinding // IdentifierName as ImportedBinding @@ -4759,6 +4778,23 @@ module ts { return finishNode(node); } + function parseExportDeclaration(fullStart: number, modifiers: ModifiersArray): ExportDeclaration { + var node = createNode(SyntaxKind.ExportDeclaration, fullStart); + setModifiers(node, modifiers); + if (parseOptional(SyntaxKind.AsteriskToken)) { + parseExpected(SyntaxKind.FromKeyword); + node.moduleSpecifier = parseModuleSpecifier(); + } + else { + node.exportClause = parseNamedImportsOrExports(SyntaxKind.NamedExports); + if (parseOptional(SyntaxKind.FromKeyword)) { + node.moduleSpecifier = parseModuleSpecifier(); + } + } + parseSemicolon(); + return finishNode(node); + } + function parseExportAssignmentTail(fullStart: number, modifiers: ModifiersArray): ExportAssignment { var node = createNode(SyntaxKind.ExportAssignment, fullStart); setModifiers(node, modifiers); @@ -4795,7 +4831,7 @@ module ts { return lookAhead(nextTokenIsIdentifierOrKeywordOrStringLiteral); case SyntaxKind.ExportKeyword: // Check for export assignment or modifier on source element - return lookAhead(nextTokenIsEqualsTokenOrDeclarationStart); + return lookAhead(nextTokenCanFollowExportKeyword); case SyntaxKind.DeclareKeyword: case SyntaxKind.PublicKeyword: case SyntaxKind.PrivateKeyword: @@ -4826,9 +4862,10 @@ module ts { token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBraceToken; } - function nextTokenIsEqualsTokenOrDeclarationStart() { + function nextTokenCanFollowExportKeyword() { nextToken(); - return token === SyntaxKind.EqualsToken || isDeclarationStart(); + return token === SyntaxKind.EqualsToken || token === SyntaxKind.AsteriskToken || + token === SyntaxKind.OpenBraceToken || isDeclarationStart(); } function nextTokenIsDeclarationStart() { @@ -4848,6 +4885,9 @@ module ts { if (parseOptional(SyntaxKind.EqualsToken)) { return parseExportAssignmentTail(fullStart, modifiers); } + if (token === SyntaxKind.AsteriskToken || token === SyntaxKind.OpenBraceToken) { + return parseExportDeclaration(fullStart, modifiers); + } } switch (token) { @@ -4952,8 +4992,9 @@ module ts { sourceFile.externalModuleIndicator = forEach(sourceFile.statements, node => node.flags & NodeFlags.Export || node.kind === SyntaxKind.ImportEqualsDeclaration && (node).moduleReference.kind === SyntaxKind.ExternalModuleReference - || node.kind === SyntaxKind.ExportAssignment || node.kind === SyntaxKind.ImportDeclaration + || node.kind === SyntaxKind.ExportAssignment + || node.kind === SyntaxKind.ExportDeclaration ? node : undefined); } diff --git a/src/compiler/program.ts b/src/compiler/program.ts index ade6141952a..b74ef039fd6 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -351,8 +351,8 @@ module ts { function processImportedModules(file: SourceFile, basePath: string) { forEach(file.statements, node => { - if (node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration) { - var moduleNameExpr = getImportedModuleName(node); + if (node.kind === SyntaxKind.ImportDeclaration || node.kind === SyntaxKind.ImportEqualsDeclaration || node.kind === SyntaxKind.ExportDeclaration) { + var moduleNameExpr = getExternalModuleName(node); if (moduleNameExpr && moduleNameExpr.kind === SyntaxKind.StringLiteral) { var moduleNameText = (moduleNameExpr).text; if (moduleNameText) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 83cd99392c0..53aa08dae77 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -231,12 +231,15 @@ module ts { ModuleDeclaration, ModuleBlock, ImportEqualsDeclaration, - ExportAssignment, ImportDeclaration, ImportClause, NamespaceImport, NamedImports, ImportSpecifier, + ExportAssignment, + ExportDeclaration, + NamedExports, + ExportSpecifier, // Module references ExternalModuleReference, @@ -898,15 +901,26 @@ module ts { name: Identifier; } - export interface NamedImports extends Node { - elements: NodeArray; + export interface ExportDeclaration extends Statement, ModuleElement { + exportClause?: NamedExports; + moduleSpecifier?: Expression; } - export interface ImportSpecifier extends Declaration { - propertyName?: Identifier; // Property name to be imported from module - name: Identifier; // element name to be imported in the scope + export interface NamedImportsOrExports extends Node { + elements: NodeArray; } + export type NamedImports = NamedImportsOrExports; + export type NamedExports = NamedImportsOrExports; + + export interface ImportOrExportSpecifier extends Declaration { + propertyName?: Identifier; // Name preceding "as" keyword (or undefined when "as" is absent) + name: Identifier; // Declared name + } + + export type ImportSpecifier = ImportOrExportSpecifier; + export type ExportSpecifier = ImportOrExportSpecifier; + export interface ExportAssignment extends Statement, ModuleElement { exportName: Identifier; } @@ -1163,7 +1177,7 @@ module ts { } export interface EmitResolver { - getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string; + getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; getExpressionNameSubstitution(node: Identifier): string; getExportAssignmentName(node: SourceFile): string; isReferencedImportDeclaration(node: Node): boolean; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 9283064d7db..7c6b4d0be96 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -603,7 +603,7 @@ module ts { return node.kind === SyntaxKind.ImportEqualsDeclaration && (node).moduleReference.kind !== SyntaxKind.ExternalModuleReference; } - export function getImportedModuleName(node: Node): Expression { + export function getExternalModuleName(node: Node): Expression { if (node.kind === SyntaxKind.ImportDeclaration) { return (node).moduleSpecifier; } @@ -613,6 +613,9 @@ module ts { return (reference).expression; } } + if (node.kind === SyntaxKind.ExportDeclaration) { + return (node).moduleSpecifier; + } } export function hasDotDotDotToken(node: Node) { @@ -695,6 +698,7 @@ module ts { case SyntaxKind.ImportClause: case SyntaxKind.ImportSpecifier: case SyntaxKind.NamespaceImport: + case SyntaxKind.ExportSpecifier: return true; } return false; From 6c47c326a9b52245edfbad2b2cb2decabcac91a4 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Thu, 12 Feb 2015 18:05:50 -0800 Subject: [PATCH 2/9] Accepting new baselines --- .../baselines/reference/APISample_compile.js | 53 +++++---- .../reference/APISample_compile.types | 101 ++++++++++++------ tests/baselines/reference/APISample_linter.js | 53 +++++---- .../reference/APISample_linter.types | 101 ++++++++++++------ .../reference/APISample_transform.js | 53 +++++---- .../reference/APISample_transform.types | 101 ++++++++++++------ .../baselines/reference/APISample_watcher.js | 53 +++++---- .../reference/APISample_watcher.types | 101 ++++++++++++------ 8 files changed, 408 insertions(+), 208 deletions(-) diff --git a/tests/baselines/reference/APISample_compile.js b/tests/baselines/reference/APISample_compile.js index eeb78ce8250..9f75f86dc1c 100644 --- a/tests/baselines/reference/APISample_compile.js +++ b/tests/baselines/reference/APISample_compile.js @@ -259,23 +259,26 @@ declare module "typescript" { ModuleDeclaration = 197, ModuleBlock = 198, ImportEqualsDeclaration = 199, - ExportAssignment = 200, - ImportDeclaration = 201, - ImportClause = 202, - NamespaceImport = 203, - NamedImports = 204, - ImportSpecifier = 205, - ExternalModuleReference = 206, - CaseClause = 207, - DefaultClause = 208, - HeritageClause = 209, - CatchClause = 210, - PropertyAssignment = 211, - ShorthandPropertyAssignment = 212, - EnumMember = 213, - SourceFile = 214, - SyntaxList = 215, - Count = 216, + ImportDeclaration = 200, + ImportClause = 201, + NamespaceImport = 202, + NamedImports = 203, + ImportSpecifier = 204, + ExportAssignment = 205, + ExportDeclaration = 206, + NamedExports = 207, + ExportSpecifier = 208, + ExternalModuleReference = 209, + CaseClause = 210, + DefaultClause = 211, + HeritageClause = 212, + CatchClause = 213, + PropertyAssignment = 214, + ShorthandPropertyAssignment = 215, + EnumMember = 216, + SourceFile = 217, + SyntaxList = 218, + Count = 219, FirstAssignment = 52, LastAssignment = 63, FirstReservedWord = 65, @@ -727,13 +730,21 @@ declare module "typescript" { interface NamespaceImport extends Declaration { name: Identifier; } - interface NamedImports extends Node { - elements: NodeArray; + interface ExportDeclaration extends Statement, ModuleElement { + exportClause?: NamedExports; + moduleSpecifier?: Expression; } - interface ImportSpecifier extends Declaration { + interface NamedImportsOrExports extends Node { + elements: NodeArray; + } + type NamedImports = NamedImportsOrExports; + type NamedExports = NamedImportsOrExports; + interface ImportOrExportSpecifier extends Declaration { propertyName?: Identifier; name: Identifier; } + type ImportSpecifier = ImportOrExportSpecifier; + type ExportSpecifier = ImportOrExportSpecifier; interface ExportAssignment extends Statement, ModuleElement { exportName: Identifier; } @@ -902,7 +913,7 @@ declare module "typescript" { errorModuleName?: string; } interface EmitResolver { - getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string; + getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; getExpressionNameSubstitution(node: Identifier): string; getExportAssignmentName(node: SourceFile): string; isReferencedImportDeclaration(node: Node): boolean; diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index b85d0132a04..b992b3ba119 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -793,55 +793,64 @@ declare module "typescript" { ImportEqualsDeclaration = 199, >ImportEqualsDeclaration : SyntaxKind - ExportAssignment = 200, ->ExportAssignment : SyntaxKind - - ImportDeclaration = 201, + ImportDeclaration = 200, >ImportDeclaration : SyntaxKind - ImportClause = 202, + ImportClause = 201, >ImportClause : SyntaxKind - NamespaceImport = 203, + NamespaceImport = 202, >NamespaceImport : SyntaxKind - NamedImports = 204, + NamedImports = 203, >NamedImports : SyntaxKind - ImportSpecifier = 205, + ImportSpecifier = 204, >ImportSpecifier : SyntaxKind - ExternalModuleReference = 206, + ExportAssignment = 205, +>ExportAssignment : SyntaxKind + + ExportDeclaration = 206, +>ExportDeclaration : SyntaxKind + + NamedExports = 207, +>NamedExports : SyntaxKind + + ExportSpecifier = 208, +>ExportSpecifier : SyntaxKind + + ExternalModuleReference = 209, >ExternalModuleReference : SyntaxKind - CaseClause = 207, + CaseClause = 210, >CaseClause : SyntaxKind - DefaultClause = 208, + DefaultClause = 211, >DefaultClause : SyntaxKind - HeritageClause = 209, + HeritageClause = 212, >HeritageClause : SyntaxKind - CatchClause = 210, + CatchClause = 213, >CatchClause : SyntaxKind - PropertyAssignment = 211, + PropertyAssignment = 214, >PropertyAssignment : SyntaxKind - ShorthandPropertyAssignment = 212, + ShorthandPropertyAssignment = 215, >ShorthandPropertyAssignment : SyntaxKind - EnumMember = 213, + EnumMember = 216, >EnumMember : SyntaxKind - SourceFile = 214, + SourceFile = 217, >SourceFile : SyntaxKind - SyntaxList = 215, + SyntaxList = 218, >SyntaxList : SyntaxKind - Count = 216, + Count = 219, >Count : SyntaxKind FirstAssignment = 52, @@ -2196,9 +2205,9 @@ declare module "typescript" { >Identifier : Identifier namedBindings?: NamespaceImport | NamedImports; ->namedBindings : NamespaceImport | NamedImports +>namedBindings : NamespaceImport | NamedImportsOrExports >NamespaceImport : NamespaceImport ->NamedImports : NamedImports +>NamedImports : NamedImportsOrExports } interface NamespaceImport extends Declaration { >NamespaceImport : NamespaceImport @@ -2208,17 +2217,38 @@ declare module "typescript" { >name : Identifier >Identifier : Identifier } - interface NamedImports extends Node { ->NamedImports : NamedImports + interface ExportDeclaration extends Statement, ModuleElement { +>ExportDeclaration : ExportDeclaration +>Statement : Statement +>ModuleElement : ModuleElement + + exportClause?: NamedExports; +>exportClause : NamedImportsOrExports +>NamedExports : NamedImportsOrExports + + moduleSpecifier?: Expression; +>moduleSpecifier : Expression +>Expression : Expression + } + interface NamedImportsOrExports extends Node { +>NamedImportsOrExports : NamedImportsOrExports >Node : Node - elements: NodeArray; ->elements : NodeArray + elements: NodeArray; +>elements : NodeArray >NodeArray : NodeArray ->ImportSpecifier : ImportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier } - interface ImportSpecifier extends Declaration { ->ImportSpecifier : ImportSpecifier + type NamedImports = NamedImportsOrExports; +>NamedImports : NamedImportsOrExports +>NamedImportsOrExports : NamedImportsOrExports + + type NamedExports = NamedImportsOrExports; +>NamedExports : NamedImportsOrExports +>NamedImportsOrExports : NamedImportsOrExports + + interface ImportOrExportSpecifier extends Declaration { +>ImportOrExportSpecifier : ImportOrExportSpecifier >Declaration : Declaration propertyName?: Identifier; @@ -2229,6 +2259,14 @@ declare module "typescript" { >name : Identifier >Identifier : Identifier } + type ImportSpecifier = ImportOrExportSpecifier; +>ImportSpecifier : ImportOrExportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier + + type ExportSpecifier = ImportOrExportSpecifier; +>ExportSpecifier : ImportOrExportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier + interface ExportAssignment extends Statement, ModuleElement { >ExportAssignment : ExportAssignment >Statement : Statement @@ -2882,12 +2920,13 @@ declare module "typescript" { interface EmitResolver { >EmitResolver : EmitResolver - getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string; ->getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration) => string ->node : EnumDeclaration | ModuleDeclaration | ImportDeclaration + getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; +>getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration) => string +>node : EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration >ModuleDeclaration : ModuleDeclaration >EnumDeclaration : EnumDeclaration >ImportDeclaration : ImportDeclaration +>ExportDeclaration : ExportDeclaration getExpressionNameSubstitution(node: Identifier): string; >getExpressionNameSubstitution : (node: Identifier) => string diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index 1a5e6520805..0ec2bf4f77c 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -290,23 +290,26 @@ declare module "typescript" { ModuleDeclaration = 197, ModuleBlock = 198, ImportEqualsDeclaration = 199, - ExportAssignment = 200, - ImportDeclaration = 201, - ImportClause = 202, - NamespaceImport = 203, - NamedImports = 204, - ImportSpecifier = 205, - ExternalModuleReference = 206, - CaseClause = 207, - DefaultClause = 208, - HeritageClause = 209, - CatchClause = 210, - PropertyAssignment = 211, - ShorthandPropertyAssignment = 212, - EnumMember = 213, - SourceFile = 214, - SyntaxList = 215, - Count = 216, + ImportDeclaration = 200, + ImportClause = 201, + NamespaceImport = 202, + NamedImports = 203, + ImportSpecifier = 204, + ExportAssignment = 205, + ExportDeclaration = 206, + NamedExports = 207, + ExportSpecifier = 208, + ExternalModuleReference = 209, + CaseClause = 210, + DefaultClause = 211, + HeritageClause = 212, + CatchClause = 213, + PropertyAssignment = 214, + ShorthandPropertyAssignment = 215, + EnumMember = 216, + SourceFile = 217, + SyntaxList = 218, + Count = 219, FirstAssignment = 52, LastAssignment = 63, FirstReservedWord = 65, @@ -758,13 +761,21 @@ declare module "typescript" { interface NamespaceImport extends Declaration { name: Identifier; } - interface NamedImports extends Node { - elements: NodeArray; + interface ExportDeclaration extends Statement, ModuleElement { + exportClause?: NamedExports; + moduleSpecifier?: Expression; } - interface ImportSpecifier extends Declaration { + interface NamedImportsOrExports extends Node { + elements: NodeArray; + } + type NamedImports = NamedImportsOrExports; + type NamedExports = NamedImportsOrExports; + interface ImportOrExportSpecifier extends Declaration { propertyName?: Identifier; name: Identifier; } + type ImportSpecifier = ImportOrExportSpecifier; + type ExportSpecifier = ImportOrExportSpecifier; interface ExportAssignment extends Statement, ModuleElement { exportName: Identifier; } @@ -933,7 +944,7 @@ declare module "typescript" { errorModuleName?: string; } interface EmitResolver { - getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string; + getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; getExpressionNameSubstitution(node: Identifier): string; getExportAssignmentName(node: SourceFile): string; isReferencedImportDeclaration(node: Node): boolean; diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index f8f4b6bd199..3bb894b55de 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -937,55 +937,64 @@ declare module "typescript" { ImportEqualsDeclaration = 199, >ImportEqualsDeclaration : SyntaxKind - ExportAssignment = 200, ->ExportAssignment : SyntaxKind - - ImportDeclaration = 201, + ImportDeclaration = 200, >ImportDeclaration : SyntaxKind - ImportClause = 202, + ImportClause = 201, >ImportClause : SyntaxKind - NamespaceImport = 203, + NamespaceImport = 202, >NamespaceImport : SyntaxKind - NamedImports = 204, + NamedImports = 203, >NamedImports : SyntaxKind - ImportSpecifier = 205, + ImportSpecifier = 204, >ImportSpecifier : SyntaxKind - ExternalModuleReference = 206, + ExportAssignment = 205, +>ExportAssignment : SyntaxKind + + ExportDeclaration = 206, +>ExportDeclaration : SyntaxKind + + NamedExports = 207, +>NamedExports : SyntaxKind + + ExportSpecifier = 208, +>ExportSpecifier : SyntaxKind + + ExternalModuleReference = 209, >ExternalModuleReference : SyntaxKind - CaseClause = 207, + CaseClause = 210, >CaseClause : SyntaxKind - DefaultClause = 208, + DefaultClause = 211, >DefaultClause : SyntaxKind - HeritageClause = 209, + HeritageClause = 212, >HeritageClause : SyntaxKind - CatchClause = 210, + CatchClause = 213, >CatchClause : SyntaxKind - PropertyAssignment = 211, + PropertyAssignment = 214, >PropertyAssignment : SyntaxKind - ShorthandPropertyAssignment = 212, + ShorthandPropertyAssignment = 215, >ShorthandPropertyAssignment : SyntaxKind - EnumMember = 213, + EnumMember = 216, >EnumMember : SyntaxKind - SourceFile = 214, + SourceFile = 217, >SourceFile : SyntaxKind - SyntaxList = 215, + SyntaxList = 218, >SyntaxList : SyntaxKind - Count = 216, + Count = 219, >Count : SyntaxKind FirstAssignment = 52, @@ -2340,9 +2349,9 @@ declare module "typescript" { >Identifier : Identifier namedBindings?: NamespaceImport | NamedImports; ->namedBindings : NamespaceImport | NamedImports +>namedBindings : NamespaceImport | NamedImportsOrExports >NamespaceImport : NamespaceImport ->NamedImports : NamedImports +>NamedImports : NamedImportsOrExports } interface NamespaceImport extends Declaration { >NamespaceImport : NamespaceImport @@ -2352,17 +2361,38 @@ declare module "typescript" { >name : Identifier >Identifier : Identifier } - interface NamedImports extends Node { ->NamedImports : NamedImports + interface ExportDeclaration extends Statement, ModuleElement { +>ExportDeclaration : ExportDeclaration +>Statement : Statement +>ModuleElement : ModuleElement + + exportClause?: NamedExports; +>exportClause : NamedImportsOrExports +>NamedExports : NamedImportsOrExports + + moduleSpecifier?: Expression; +>moduleSpecifier : Expression +>Expression : Expression + } + interface NamedImportsOrExports extends Node { +>NamedImportsOrExports : NamedImportsOrExports >Node : Node - elements: NodeArray; ->elements : NodeArray + elements: NodeArray; +>elements : NodeArray >NodeArray : NodeArray ->ImportSpecifier : ImportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier } - interface ImportSpecifier extends Declaration { ->ImportSpecifier : ImportSpecifier + type NamedImports = NamedImportsOrExports; +>NamedImports : NamedImportsOrExports +>NamedImportsOrExports : NamedImportsOrExports + + type NamedExports = NamedImportsOrExports; +>NamedExports : NamedImportsOrExports +>NamedImportsOrExports : NamedImportsOrExports + + interface ImportOrExportSpecifier extends Declaration { +>ImportOrExportSpecifier : ImportOrExportSpecifier >Declaration : Declaration propertyName?: Identifier; @@ -2373,6 +2403,14 @@ declare module "typescript" { >name : Identifier >Identifier : Identifier } + type ImportSpecifier = ImportOrExportSpecifier; +>ImportSpecifier : ImportOrExportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier + + type ExportSpecifier = ImportOrExportSpecifier; +>ExportSpecifier : ImportOrExportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier + interface ExportAssignment extends Statement, ModuleElement { >ExportAssignment : ExportAssignment >Statement : Statement @@ -3026,12 +3064,13 @@ declare module "typescript" { interface EmitResolver { >EmitResolver : EmitResolver - getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string; ->getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration) => string ->node : EnumDeclaration | ModuleDeclaration | ImportDeclaration + getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; +>getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration) => string +>node : EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration >ModuleDeclaration : ModuleDeclaration >EnumDeclaration : EnumDeclaration >ImportDeclaration : ImportDeclaration +>ExportDeclaration : ExportDeclaration getExpressionNameSubstitution(node: Identifier): string; >getExpressionNameSubstitution : (node: Identifier) => string diff --git a/tests/baselines/reference/APISample_transform.js b/tests/baselines/reference/APISample_transform.js index 295d45c220e..1627415c834 100644 --- a/tests/baselines/reference/APISample_transform.js +++ b/tests/baselines/reference/APISample_transform.js @@ -291,23 +291,26 @@ declare module "typescript" { ModuleDeclaration = 197, ModuleBlock = 198, ImportEqualsDeclaration = 199, - ExportAssignment = 200, - ImportDeclaration = 201, - ImportClause = 202, - NamespaceImport = 203, - NamedImports = 204, - ImportSpecifier = 205, - ExternalModuleReference = 206, - CaseClause = 207, - DefaultClause = 208, - HeritageClause = 209, - CatchClause = 210, - PropertyAssignment = 211, - ShorthandPropertyAssignment = 212, - EnumMember = 213, - SourceFile = 214, - SyntaxList = 215, - Count = 216, + ImportDeclaration = 200, + ImportClause = 201, + NamespaceImport = 202, + NamedImports = 203, + ImportSpecifier = 204, + ExportAssignment = 205, + ExportDeclaration = 206, + NamedExports = 207, + ExportSpecifier = 208, + ExternalModuleReference = 209, + CaseClause = 210, + DefaultClause = 211, + HeritageClause = 212, + CatchClause = 213, + PropertyAssignment = 214, + ShorthandPropertyAssignment = 215, + EnumMember = 216, + SourceFile = 217, + SyntaxList = 218, + Count = 219, FirstAssignment = 52, LastAssignment = 63, FirstReservedWord = 65, @@ -759,13 +762,21 @@ declare module "typescript" { interface NamespaceImport extends Declaration { name: Identifier; } - interface NamedImports extends Node { - elements: NodeArray; + interface ExportDeclaration extends Statement, ModuleElement { + exportClause?: NamedExports; + moduleSpecifier?: Expression; } - interface ImportSpecifier extends Declaration { + interface NamedImportsOrExports extends Node { + elements: NodeArray; + } + type NamedImports = NamedImportsOrExports; + type NamedExports = NamedImportsOrExports; + interface ImportOrExportSpecifier extends Declaration { propertyName?: Identifier; name: Identifier; } + type ImportSpecifier = ImportOrExportSpecifier; + type ExportSpecifier = ImportOrExportSpecifier; interface ExportAssignment extends Statement, ModuleElement { exportName: Identifier; } @@ -934,7 +945,7 @@ declare module "typescript" { errorModuleName?: string; } interface EmitResolver { - getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string; + getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; getExpressionNameSubstitution(node: Identifier): string; getExportAssignmentName(node: SourceFile): string; isReferencedImportDeclaration(node: Node): boolean; diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 90b06ebb8ca..9d0dbdb0768 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -889,55 +889,64 @@ declare module "typescript" { ImportEqualsDeclaration = 199, >ImportEqualsDeclaration : SyntaxKind - ExportAssignment = 200, ->ExportAssignment : SyntaxKind - - ImportDeclaration = 201, + ImportDeclaration = 200, >ImportDeclaration : SyntaxKind - ImportClause = 202, + ImportClause = 201, >ImportClause : SyntaxKind - NamespaceImport = 203, + NamespaceImport = 202, >NamespaceImport : SyntaxKind - NamedImports = 204, + NamedImports = 203, >NamedImports : SyntaxKind - ImportSpecifier = 205, + ImportSpecifier = 204, >ImportSpecifier : SyntaxKind - ExternalModuleReference = 206, + ExportAssignment = 205, +>ExportAssignment : SyntaxKind + + ExportDeclaration = 206, +>ExportDeclaration : SyntaxKind + + NamedExports = 207, +>NamedExports : SyntaxKind + + ExportSpecifier = 208, +>ExportSpecifier : SyntaxKind + + ExternalModuleReference = 209, >ExternalModuleReference : SyntaxKind - CaseClause = 207, + CaseClause = 210, >CaseClause : SyntaxKind - DefaultClause = 208, + DefaultClause = 211, >DefaultClause : SyntaxKind - HeritageClause = 209, + HeritageClause = 212, >HeritageClause : SyntaxKind - CatchClause = 210, + CatchClause = 213, >CatchClause : SyntaxKind - PropertyAssignment = 211, + PropertyAssignment = 214, >PropertyAssignment : SyntaxKind - ShorthandPropertyAssignment = 212, + ShorthandPropertyAssignment = 215, >ShorthandPropertyAssignment : SyntaxKind - EnumMember = 213, + EnumMember = 216, >EnumMember : SyntaxKind - SourceFile = 214, + SourceFile = 217, >SourceFile : SyntaxKind - SyntaxList = 215, + SyntaxList = 218, >SyntaxList : SyntaxKind - Count = 216, + Count = 219, >Count : SyntaxKind FirstAssignment = 52, @@ -2292,9 +2301,9 @@ declare module "typescript" { >Identifier : Identifier namedBindings?: NamespaceImport | NamedImports; ->namedBindings : NamespaceImport | NamedImports +>namedBindings : NamespaceImport | NamedImportsOrExports >NamespaceImport : NamespaceImport ->NamedImports : NamedImports +>NamedImports : NamedImportsOrExports } interface NamespaceImport extends Declaration { >NamespaceImport : NamespaceImport @@ -2304,17 +2313,38 @@ declare module "typescript" { >name : Identifier >Identifier : Identifier } - interface NamedImports extends Node { ->NamedImports : NamedImports + interface ExportDeclaration extends Statement, ModuleElement { +>ExportDeclaration : ExportDeclaration +>Statement : Statement +>ModuleElement : ModuleElement + + exportClause?: NamedExports; +>exportClause : NamedImportsOrExports +>NamedExports : NamedImportsOrExports + + moduleSpecifier?: Expression; +>moduleSpecifier : Expression +>Expression : Expression + } + interface NamedImportsOrExports extends Node { +>NamedImportsOrExports : NamedImportsOrExports >Node : Node - elements: NodeArray; ->elements : NodeArray + elements: NodeArray; +>elements : NodeArray >NodeArray : NodeArray ->ImportSpecifier : ImportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier } - interface ImportSpecifier extends Declaration { ->ImportSpecifier : ImportSpecifier + type NamedImports = NamedImportsOrExports; +>NamedImports : NamedImportsOrExports +>NamedImportsOrExports : NamedImportsOrExports + + type NamedExports = NamedImportsOrExports; +>NamedExports : NamedImportsOrExports +>NamedImportsOrExports : NamedImportsOrExports + + interface ImportOrExportSpecifier extends Declaration { +>ImportOrExportSpecifier : ImportOrExportSpecifier >Declaration : Declaration propertyName?: Identifier; @@ -2325,6 +2355,14 @@ declare module "typescript" { >name : Identifier >Identifier : Identifier } + type ImportSpecifier = ImportOrExportSpecifier; +>ImportSpecifier : ImportOrExportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier + + type ExportSpecifier = ImportOrExportSpecifier; +>ExportSpecifier : ImportOrExportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier + interface ExportAssignment extends Statement, ModuleElement { >ExportAssignment : ExportAssignment >Statement : Statement @@ -2978,12 +3016,13 @@ declare module "typescript" { interface EmitResolver { >EmitResolver : EmitResolver - getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string; ->getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration) => string ->node : EnumDeclaration | ModuleDeclaration | ImportDeclaration + getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; +>getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration) => string +>node : EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration >ModuleDeclaration : ModuleDeclaration >EnumDeclaration : EnumDeclaration >ImportDeclaration : ImportDeclaration +>ExportDeclaration : ExportDeclaration getExpressionNameSubstitution(node: Identifier): string; >getExpressionNameSubstitution : (node: Identifier) => string diff --git a/tests/baselines/reference/APISample_watcher.js b/tests/baselines/reference/APISample_watcher.js index d083c54673e..6c4c0977aac 100644 --- a/tests/baselines/reference/APISample_watcher.js +++ b/tests/baselines/reference/APISample_watcher.js @@ -328,23 +328,26 @@ declare module "typescript" { ModuleDeclaration = 197, ModuleBlock = 198, ImportEqualsDeclaration = 199, - ExportAssignment = 200, - ImportDeclaration = 201, - ImportClause = 202, - NamespaceImport = 203, - NamedImports = 204, - ImportSpecifier = 205, - ExternalModuleReference = 206, - CaseClause = 207, - DefaultClause = 208, - HeritageClause = 209, - CatchClause = 210, - PropertyAssignment = 211, - ShorthandPropertyAssignment = 212, - EnumMember = 213, - SourceFile = 214, - SyntaxList = 215, - Count = 216, + ImportDeclaration = 200, + ImportClause = 201, + NamespaceImport = 202, + NamedImports = 203, + ImportSpecifier = 204, + ExportAssignment = 205, + ExportDeclaration = 206, + NamedExports = 207, + ExportSpecifier = 208, + ExternalModuleReference = 209, + CaseClause = 210, + DefaultClause = 211, + HeritageClause = 212, + CatchClause = 213, + PropertyAssignment = 214, + ShorthandPropertyAssignment = 215, + EnumMember = 216, + SourceFile = 217, + SyntaxList = 218, + Count = 219, FirstAssignment = 52, LastAssignment = 63, FirstReservedWord = 65, @@ -796,13 +799,21 @@ declare module "typescript" { interface NamespaceImport extends Declaration { name: Identifier; } - interface NamedImports extends Node { - elements: NodeArray; + interface ExportDeclaration extends Statement, ModuleElement { + exportClause?: NamedExports; + moduleSpecifier?: Expression; } - interface ImportSpecifier extends Declaration { + interface NamedImportsOrExports extends Node { + elements: NodeArray; + } + type NamedImports = NamedImportsOrExports; + type NamedExports = NamedImportsOrExports; + interface ImportOrExportSpecifier extends Declaration { propertyName?: Identifier; name: Identifier; } + type ImportSpecifier = ImportOrExportSpecifier; + type ExportSpecifier = ImportOrExportSpecifier; interface ExportAssignment extends Statement, ModuleElement { exportName: Identifier; } @@ -971,7 +982,7 @@ declare module "typescript" { errorModuleName?: string; } interface EmitResolver { - getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string; + getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; getExpressionNameSubstitution(node: Identifier): string; getExportAssignmentName(node: SourceFile): string; isReferencedImportDeclaration(node: Node): boolean; diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index e4cffc16aa1..fb342d09cdd 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -1062,55 +1062,64 @@ declare module "typescript" { ImportEqualsDeclaration = 199, >ImportEqualsDeclaration : SyntaxKind - ExportAssignment = 200, ->ExportAssignment : SyntaxKind - - ImportDeclaration = 201, + ImportDeclaration = 200, >ImportDeclaration : SyntaxKind - ImportClause = 202, + ImportClause = 201, >ImportClause : SyntaxKind - NamespaceImport = 203, + NamespaceImport = 202, >NamespaceImport : SyntaxKind - NamedImports = 204, + NamedImports = 203, >NamedImports : SyntaxKind - ImportSpecifier = 205, + ImportSpecifier = 204, >ImportSpecifier : SyntaxKind - ExternalModuleReference = 206, + ExportAssignment = 205, +>ExportAssignment : SyntaxKind + + ExportDeclaration = 206, +>ExportDeclaration : SyntaxKind + + NamedExports = 207, +>NamedExports : SyntaxKind + + ExportSpecifier = 208, +>ExportSpecifier : SyntaxKind + + ExternalModuleReference = 209, >ExternalModuleReference : SyntaxKind - CaseClause = 207, + CaseClause = 210, >CaseClause : SyntaxKind - DefaultClause = 208, + DefaultClause = 211, >DefaultClause : SyntaxKind - HeritageClause = 209, + HeritageClause = 212, >HeritageClause : SyntaxKind - CatchClause = 210, + CatchClause = 213, >CatchClause : SyntaxKind - PropertyAssignment = 211, + PropertyAssignment = 214, >PropertyAssignment : SyntaxKind - ShorthandPropertyAssignment = 212, + ShorthandPropertyAssignment = 215, >ShorthandPropertyAssignment : SyntaxKind - EnumMember = 213, + EnumMember = 216, >EnumMember : SyntaxKind - SourceFile = 214, + SourceFile = 217, >SourceFile : SyntaxKind - SyntaxList = 215, + SyntaxList = 218, >SyntaxList : SyntaxKind - Count = 216, + Count = 219, >Count : SyntaxKind FirstAssignment = 52, @@ -2465,9 +2474,9 @@ declare module "typescript" { >Identifier : Identifier namedBindings?: NamespaceImport | NamedImports; ->namedBindings : NamespaceImport | NamedImports +>namedBindings : NamespaceImport | NamedImportsOrExports >NamespaceImport : NamespaceImport ->NamedImports : NamedImports +>NamedImports : NamedImportsOrExports } interface NamespaceImport extends Declaration { >NamespaceImport : NamespaceImport @@ -2477,17 +2486,38 @@ declare module "typescript" { >name : Identifier >Identifier : Identifier } - interface NamedImports extends Node { ->NamedImports : NamedImports + interface ExportDeclaration extends Statement, ModuleElement { +>ExportDeclaration : ExportDeclaration +>Statement : Statement +>ModuleElement : ModuleElement + + exportClause?: NamedExports; +>exportClause : NamedImportsOrExports +>NamedExports : NamedImportsOrExports + + moduleSpecifier?: Expression; +>moduleSpecifier : Expression +>Expression : Expression + } + interface NamedImportsOrExports extends Node { +>NamedImportsOrExports : NamedImportsOrExports >Node : Node - elements: NodeArray; ->elements : NodeArray + elements: NodeArray; +>elements : NodeArray >NodeArray : NodeArray ->ImportSpecifier : ImportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier } - interface ImportSpecifier extends Declaration { ->ImportSpecifier : ImportSpecifier + type NamedImports = NamedImportsOrExports; +>NamedImports : NamedImportsOrExports +>NamedImportsOrExports : NamedImportsOrExports + + type NamedExports = NamedImportsOrExports; +>NamedExports : NamedImportsOrExports +>NamedImportsOrExports : NamedImportsOrExports + + interface ImportOrExportSpecifier extends Declaration { +>ImportOrExportSpecifier : ImportOrExportSpecifier >Declaration : Declaration propertyName?: Identifier; @@ -2498,6 +2528,14 @@ declare module "typescript" { >name : Identifier >Identifier : Identifier } + type ImportSpecifier = ImportOrExportSpecifier; +>ImportSpecifier : ImportOrExportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier + + type ExportSpecifier = ImportOrExportSpecifier; +>ExportSpecifier : ImportOrExportSpecifier +>ImportOrExportSpecifier : ImportOrExportSpecifier + interface ExportAssignment extends Statement, ModuleElement { >ExportAssignment : ExportAssignment >Statement : Statement @@ -3151,12 +3189,13 @@ declare module "typescript" { interface EmitResolver { >EmitResolver : EmitResolver - getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration): string; ->getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration) => string ->node : EnumDeclaration | ModuleDeclaration | ImportDeclaration + getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; +>getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration) => string +>node : EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration >ModuleDeclaration : ModuleDeclaration >EnumDeclaration : EnumDeclaration >ImportDeclaration : ImportDeclaration +>ExportDeclaration : ExportDeclaration getExpressionNameSubstitution(node: Identifier): string; >getExpressionNameSubstitution : (node: Identifier) => string From 6ef6217c1651850876ab7470b00d249e1efd43a5 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 13 Feb 2015 10:07:10 -0800 Subject: [PATCH 3/9] Allow multiple (renaming) exports for same entity --- src/compiler/emitter.ts | 48 ++++++++++++++++++++++------------------- 1 file changed, 26 insertions(+), 22 deletions(-) diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 552c7201279..1344c34d886 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -1568,7 +1568,7 @@ module ts { var tempVariables: Identifier[]; var tempParameters: Identifier[]; var externalImports: ExternalImportInfo[]; - var exportSpecifiers: Map; + var exportSpecifiers: Map; /** write emitted output to disk*/ var writeEmittedFiles = writeJavaScriptFile; @@ -3068,17 +3068,18 @@ module ts { emitEnd(node.name); } - function emitExportMemberAssignment(name: Identifier) { + function emitExportMemberAssignments(name: Identifier) { if (exportSpecifiers && hasProperty(exportSpecifiers, name.text)) { - var exportName = exportSpecifiers[name.text].name; - writeLine(); - emitStart(exportName); - write("exports."); - emitNode(exportName); - emitEnd(exportName); - write(" = "); - emitNode(name); - write(";"); + forEach(exportSpecifiers[name.text], specifier => { + writeLine(); + emitStart(specifier.name); + write("exports."); + emitNode(specifier.name); + emitEnd(specifier.name); + write(" = "); + emitNode(name); + write(";"); + }); } } @@ -3317,7 +3318,7 @@ module ts { function emitExportVariableAssignments(node: VariableDeclaration | BindingElement) { var name = (node).name; if (name.kind === SyntaxKind.Identifier) { - emitExportMemberAssignment(name); + emitExportMemberAssignments(name); } else if (isBindingPattern(name)) { forEach((name).elements, emitExportVariableAssignments); @@ -3466,7 +3467,7 @@ module ts { } emitSignatureAndBody(node); if (languageVersion < ScriptTarget.ES6 && node.kind === SyntaxKind.FunctionDeclaration && node.parent === currentSourceFile) { - emitExportMemberAssignment((node).name); + emitExportMemberAssignments((node).name); } if (node.kind !== SyntaxKind.MethodDeclaration && node.kind !== SyntaxKind.MethodSignature) { emitTrailingComments(node); @@ -3805,7 +3806,7 @@ module ts { write(";"); } if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) { - emitExportMemberAssignment(node.name); + emitExportMemberAssignments(node.name); } function emitConstructorOfClass() { @@ -3934,7 +3935,7 @@ module ts { write(";"); } if (languageVersion < ScriptTarget.ES6 && node.parent === currentSourceFile) { - emitExportMemberAssignment(node.name); + emitExportMemberAssignments(node.name); } } @@ -4035,7 +4036,7 @@ module ts { write(" = {}));"); emitEnd(node); if (languageVersion < ScriptTarget.ES6 && node.name.kind === SyntaxKind.Identifier && node.parent === currentSourceFile) { - emitExportMemberAssignment(node.name); + emitExportMemberAssignments(node.name); } } @@ -4119,10 +4120,12 @@ module ts { if (node.exportClause && node.moduleSpecifier) { var generatedName = resolver.getGeneratedNameForNode(node); emitStart(node); - write("var "); - write(generatedName); - write(" = "); - emitRequire(getExternalModuleName(node)); + if (compilerOptions.module !== ModuleKind.AMD) { + write("var "); + write(generatedName); + write(" = "); + emitRequire(getExternalModuleName(node)); + } forEach(node.exportClause.elements, specifier => { writeLine(); emitStart(specifier); @@ -4187,8 +4190,9 @@ module ts { exportSpecifiers = {}; forEach(sourceFile.statements, node => { if (node.kind === SyntaxKind.ExportDeclaration && !(node).moduleSpecifier) { - forEach((node).exportClause.elements, e => { - exportSpecifiers[(e.propertyName || e.name).text] = e; + forEach((node).exportClause.elements, specifier => { + var name = (specifier.propertyName || specifier.name).text; + (exportSpecifiers[name] || (exportSpecifiers[name] = [])).push(specifier); }); } else { From 0df69ed1b62945bacf7cb269c9c54501703e1764 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 13 Feb 2015 10:07:37 -0800 Subject: [PATCH 4/9] 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", From e52ddcb0aa11fdbd8fa2ef9db6463565bebed6d2 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 13 Feb 2015 10:18:58 -0800 Subject: [PATCH 5/9] Accepting new baselines --- ...rnalModuleWithRelativeExternalImportDeclaration.errors.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/baselines/reference/ambientExternalModuleWithRelativeExternalImportDeclaration.errors.txt b/tests/baselines/reference/ambientExternalModuleWithRelativeExternalImportDeclaration.errors.txt index 4ebae64b0b8..72d7145969f 100644 --- a/tests/baselines/reference/ambientExternalModuleWithRelativeExternalImportDeclaration.errors.txt +++ b/tests/baselines/reference/ambientExternalModuleWithRelativeExternalImportDeclaration.errors.txt @@ -1,4 +1,4 @@ -tests/cases/compiler/ambientExternalModuleWithRelativeExternalImportDeclaration.ts(2,5): error TS2439: Import declaration in an ambient external module declaration cannot reference external module through relative external module name. +tests/cases/compiler/ambientExternalModuleWithRelativeExternalImportDeclaration.ts(2,5): error TS2439: Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name. tests/cases/compiler/ambientExternalModuleWithRelativeExternalImportDeclaration.ts(2,25): error TS2307: Cannot find external module './SubModule'. @@ -6,7 +6,7 @@ tests/cases/compiler/ambientExternalModuleWithRelativeExternalImportDeclaration. declare module "OuterModule" { import m2 = require("./SubModule"); ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -!!! error TS2439: Import declaration in an ambient external module declaration cannot reference external module through relative external module name. +!!! error TS2439: Import or export declaration in an ambient external module declaration cannot reference external module through relative external module name. ~~~~~~~~~~~~~ !!! error TS2307: Cannot find external module './SubModule'. class SubModule { From c60121064a19beef4afcfaa28fe8991cd8398263 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 13 Feb 2015 14:07:20 -0800 Subject: [PATCH 6/9] Re-exported symbols should not be in scope --- src/compiler/checker.ts | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index b72797daa4a..a97b2090442 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -316,7 +316,10 @@ module ts { if (!isExternalModule(location)) break; case SyntaxKind.ModuleDeclaration: if (result = getSymbol(getSymbolOfNode(location).exports, name, meaning & SymbolFlags.ModuleMember)) { - break loop; + if (!(result.flags & SymbolFlags.Import && getDeclarationOfImportSymbol(result).kind === SyntaxKind.ExportSpecifier)) { + break loop; + } + result = undefined; } break; case SyntaxKind.EnumDeclaration: From a8152b6e503cf681f02941b6cd03313b89cab29b Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 15 Feb 2015 08:25:24 -0800 Subject: [PATCH 7/9] Support for 'export *' declarations --- src/compiler/binder.ts | 10 +++++++ src/compiler/checker.ts | 61 +++++++++++++++++++++++++++++++++++------ src/compiler/emitter.ts | 51 +++++++++++++++++++++++----------- src/compiler/types.ts | 11 ++++++-- 4 files changed, 105 insertions(+), 28 deletions(-) diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 4bd562291d5..d13d7289b9e 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -316,6 +316,13 @@ module ts { } } + function bindExportDeclaration(node: ExportDeclaration) { + if (!node.exportClause) { + ((container).exportStars || ((container).exportStars = [])).push(node); + } + bindChildren(node, 0, /*isBlockScopeContainer*/ false); + } + function bindFunctionOrConstructorType(node: SignatureDeclaration) { // For a given function symbol "<...>(...) => T" we want to generate a symbol identical // to the one we would get for: { <...>(...): T } @@ -477,6 +484,9 @@ module ts { case SyntaxKind.ExportSpecifier: bindDeclaration(node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false); break; + case SyntaxKind.ExportDeclaration: + bindExportDeclaration(node); + break; case SyntaxKind.ImportClause: if ((node).name) { bindDeclaration(node, SymbolFlags.Import, SymbolFlags.ImportExcludes, /*isBlockScopeContainer*/ false); diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a97b2090442..828b03c91d7 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -179,7 +179,7 @@ module ts { return result; } - function extendSymbol(target: Symbol, source: Symbol) { + function mergeSymbol(target: Symbol, source: Symbol) { if (!(target.flags & getExcludedSymbolFlags(source.flags))) { if (source.flags & SymbolFlags.ValueModule && target.flags & SymbolFlags.ValueModule && target.constEnumOnlyModule && !source.constEnumOnlyModule) { // reset flag when merging instantiated module into value module that has only const enums @@ -192,11 +192,11 @@ module ts { }); if (source.members) { if (!target.members) target.members = {}; - extendSymbolTable(target.members, source.members); + mergeSymbolTable(target.members, source.members); } if (source.exports) { if (!target.exports) target.exports = {}; - extendSymbolTable(target.exports, source.exports); + mergeSymbolTable(target.exports, source.exports); } recordMergedSymbol(target, source); } @@ -222,7 +222,7 @@ module ts { return result; } - function extendSymbolTable(target: SymbolTable, source: SymbolTable) { + function mergeSymbolTable(target: SymbolTable, source: SymbolTable) { for (var id in source) { if (hasProperty(source, id)) { if (!hasProperty(target, id)) { @@ -233,12 +233,20 @@ module ts { if (!(symbol.flags & SymbolFlags.Merged)) { target[id] = symbol = cloneSymbol(symbol); } - extendSymbol(symbol, source[id]); + mergeSymbol(symbol, source[id]); } } } } + function extendSymbolTable(target: SymbolTable, source: SymbolTable) { + for (var id in source) { + if (!hasProperty(target, id)) { + target[id] = source[id]; + } + } + } + function getSymbolLinks(symbol: Symbol): SymbolLinks { if (symbol.flags & SymbolFlags.Transient) return symbol; if (!symbol.id) symbol.id = nextSymbolId++; @@ -486,7 +494,7 @@ module ts { if (moduleSymbol) { var name = specifier.propertyName || specifier.name; if (name.text) { - var symbol = getSymbol(moduleSymbol.exports, name.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace); + var symbol = getSymbol(getExportsOfSymbol(moduleSymbol), name.text, SymbolFlags.Value | SymbolFlags.Type | SymbolFlags.Namespace); if (!symbol) { error(name, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(moduleSymbol), declarationNameToString(name)); return; @@ -587,7 +595,7 @@ module ts { else if (name.kind === SyntaxKind.QualifiedName) { var namespace = resolveEntityName(location,(name).left, SymbolFlags.Namespace); if (!namespace || namespace === unknownSymbol || getFullWidth((name).right) === 0) return; - var symbol = getSymbol(namespace.exports,(name).right.text, meaning); + var symbol = getSymbol(getExportsOfSymbol(namespace), (name).right.text, meaning); if (!symbol) { error(location, Diagnostics.Module_0_has_no_exported_member_1, getFullyQualifiedName(namespace), declarationNameToString((name).right)); @@ -708,6 +716,41 @@ module ts { }; } + function getExportsOfSymbol(symbol: Symbol): SymbolTable { + return symbol.flags & SymbolFlags.Module ? getExportsOfModule(symbol) : symbol.exports; + } + + function getExportsOfModule(symbol: Symbol): SymbolTable { + var links = getSymbolLinks(symbol); + return links.resolvedExports || (links.resolvedExports = getExportsForModule(symbol)); + } + + function getExportsForModule(symbol: Symbol): SymbolTable { + var result: SymbolTable; + var visitedSymbols: Symbol[] = []; + visit(symbol); + return result; + + function visit(symbol: Symbol) { + if (!contains(visitedSymbols, symbol)) { + visitedSymbols.push(symbol); + if (!result) { + result = symbol.exports; + } + else { + extendSymbolTable(result, symbol.exports); + } + forEach(symbol.declarations, node => { + if (node.kind === SyntaxKind.SourceFile || node.kind === SyntaxKind.ModuleDeclaration) { + forEach((node).exportStars, exportStar => { + visit(resolveExternalModuleName(exportStar, exportStar.moduleSpecifier)); + }); + } + }); + } + } + } + function getMergedSymbol(symbol: Symbol): Symbol { var merged: Symbol; return symbol && symbol.mergeId && (merged = mergedSymbols[symbol.mergeId]) ? merged : symbol; @@ -2475,7 +2518,7 @@ module ts { var callSignatures: Signature[] = emptyArray; var constructSignatures: Signature[] = emptyArray; if (symbol.flags & SymbolFlags.HasExports) { - members = symbol.exports; + members = getExportsOfSymbol(symbol); } if (symbol.flags & (SymbolFlags.Function | SymbolFlags.Method)) { callSignatures = getSignaturesOfSymbol(symbol); @@ -10468,7 +10511,7 @@ module ts { // Initialize global symbol table forEach(host.getSourceFiles(), file => { if (!isExternalModule(file)) { - extendSymbolTable(globals, file.locals); + mergeSymbolTable(globals, file.locals); } }); diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 1344c34d886..e060d6fcbb8 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3057,11 +3057,15 @@ module ts { return node; } + function emitContainingModuleName(node: Node) { + var container = getContainingModule(node); + write(container ? resolver.getGeneratedNameForNode(container) : "exports"); + } + function emitModuleMemberName(node: Declaration) { emitStart(node.name); if (getCombinedNodeFlags(node) & NodeFlags.Export) { - var container = getContainingModule(node); - write(container ? resolver.getGeneratedNameForNode(container) : "exports"); + emitContainingModuleName(node); write("."); } emitNode(node.name); @@ -3073,7 +3077,8 @@ module ts { forEach(exportSpecifiers[name.text], specifier => { writeLine(); emitStart(specifier.name); - write("exports."); + emitContainingModuleName(specifier); + write("."); emitNode(specifier.name); emitEnd(specifier.name); write(" = "); @@ -4117,27 +4122,41 @@ module ts { } function emitExportDeclaration(node: ExportDeclaration) { - if (node.exportClause && node.moduleSpecifier) { - var generatedName = resolver.getGeneratedNameForNode(node); + if (node.moduleSpecifier) { emitStart(node); + var generatedName = resolver.getGeneratedNameForNode(node); if (compilerOptions.module !== ModuleKind.AMD) { write("var "); write(generatedName); write(" = "); emitRequire(getExternalModuleName(node)); } - forEach(node.exportClause.elements, specifier => { + if (node.exportClause) { + // export { x, y, ... } + forEach(node.exportClause.elements, specifier => { + writeLine(); + emitStart(specifier); + emitContainingModuleName(specifier); + write("."); + emitNode(specifier.name); + write(" = "); + write(generatedName); + write("."); + emitNode(specifier.propertyName || specifier.name); + write(";"); + emitEnd(specifier); + }); + } + else { + // export * + var tempName = createTempVariable(node).text; writeLine(); - emitStart(specifier); - write("exports."); - emitNode(specifier.name); - write(" = "); - write(generatedName); - write("."); - emitNode(specifier.propertyName || specifier.name); - write(";"); - emitEnd(specifier); - }); + write("for (var " + tempName + " in " + generatedName + ") if (!"); + emitContainingModuleName(node); + write(".hasOwnProperty(" + tempName + ")) "); + emitContainingModuleName(node); + write("[" + tempName + "] = " + generatedName + "[" + tempName + "];"); + } emitEnd(node); } } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 53aa08dae77..810bca9fd56 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -352,13 +352,13 @@ module ts { // Specific context the parser was in when this node was created. Normally undefined. // Only set when the parser was in some interesting context (like async/yield). parserContextFlags?: ParserContextFlags; + modifiers?: ModifiersArray; // Array of modifiers id?: number; // Unique id (used to look up NodeLinks) parent?: Node; // Parent node (initialized by binding) symbol?: Symbol; // Symbol declared by node (initialized by binding) locals?: SymbolTable; // Locals associated with node (initialized by binding) nextContainer?: Node; // Next container in declaration order (initialized by binding) localSymbol?: Symbol; // Local symbol declared by node (initialized by binding only for exported nodes) - modifiers?: ModifiersArray; // Array of modifiers } export interface NodeArray extends Array, TextRange { @@ -856,7 +856,11 @@ module ts { members: NodeArray; } - export interface ModuleDeclaration extends Declaration, ModuleElement { + export interface ExportContainer { + exportStars?: ExportDeclaration[]; // List of 'export *' statements (initialized by binding) + } + + export interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer { name: Identifier | LiteralExpression; body: ModuleBlock | ModuleDeclaration; } @@ -934,7 +938,7 @@ module ts { } // Source files are declarations when they are external modules. - export interface SourceFile extends Declaration { + export interface SourceFile extends Declaration, ExportContainer { statements: NodeArray; endOfFileToken: Node; @@ -1297,6 +1301,7 @@ module ts { exportAssignmentChecked?: boolean; // True if export assignment was checked exportAssignmentSymbol?: Symbol; // Symbol exported from external module unionType?: UnionType; // Containing union type for union property + resolvedExports?: SymbolTable; // Resolved exports of module } export interface TransientSymbol extends Symbol, SymbolLinks { } From cc52dcec49fa5af41e0ab8d88bcde55fcf3c2c23 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 15 Feb 2015 08:30:39 -0800 Subject: [PATCH 8/9] Accepting new baselines --- .../baselines/reference/APISample_compile.js | 10 +++++-- .../reference/APISample_compile.types | 29 ++++++++++++++----- tests/baselines/reference/APISample_linter.js | 10 +++++-- .../reference/APISample_linter.types | 29 ++++++++++++++----- .../reference/APISample_transform.js | 10 +++++-- .../reference/APISample_transform.types | 29 ++++++++++++++----- .../baselines/reference/APISample_watcher.js | 10 +++++-- .../reference/APISample_watcher.types | 29 ++++++++++++++----- 8 files changed, 112 insertions(+), 44 deletions(-) diff --git a/tests/baselines/reference/APISample_compile.js b/tests/baselines/reference/APISample_compile.js index 9f75f86dc1c..49eed12dc70 100644 --- a/tests/baselines/reference/APISample_compile.js +++ b/tests/baselines/reference/APISample_compile.js @@ -339,13 +339,13 @@ declare module "typescript" { kind: SyntaxKind; flags: NodeFlags; parserContextFlags?: ParserContextFlags; + modifiers?: ModifiersArray; id?: number; parent?: Node; symbol?: Symbol; locals?: SymbolTable; nextContainer?: Node; localSymbol?: Symbol; - modifiers?: ModifiersArray; } interface NodeArray extends Array, TextRange { hasTrailingComma?: boolean; @@ -705,7 +705,10 @@ declare module "typescript" { name: Identifier; members: NodeArray; } - interface ModuleDeclaration extends Declaration, ModuleElement { + interface ExportContainer { + exportStars?: ExportDeclaration[]; + } + interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer { name: Identifier | LiteralExpression; body: ModuleBlock | ModuleDeclaration; } @@ -754,7 +757,7 @@ declare module "typescript" { interface CommentRange extends TextRange { hasTrailingNewLine?: boolean; } - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, ExportContainer { statements: NodeArray; endOfFileToken: Node; fileName: string; @@ -1015,6 +1018,7 @@ declare module "typescript" { exportAssignmentChecked?: boolean; exportAssignmentSymbol?: Symbol; unionType?: UnionType; + resolvedExports?: SymbolTable; } interface TransientSymbol extends Symbol, SymbolLinks { } diff --git a/tests/baselines/reference/APISample_compile.types b/tests/baselines/reference/APISample_compile.types index b992b3ba119..9232f281940 100644 --- a/tests/baselines/reference/APISample_compile.types +++ b/tests/baselines/reference/APISample_compile.types @@ -1025,6 +1025,10 @@ declare module "typescript" { >parserContextFlags : ParserContextFlags >ParserContextFlags : ParserContextFlags + modifiers?: ModifiersArray; +>modifiers : ModifiersArray +>ModifiersArray : ModifiersArray + id?: number; >id : number @@ -1047,10 +1051,6 @@ declare module "typescript" { localSymbol?: Symbol; >localSymbol : Symbol >Symbol : Symbol - - modifiers?: ModifiersArray; ->modifiers : ModifiersArray ->ModifiersArray : ModifiersArray } interface NodeArray extends Array, TextRange { >NodeArray : NodeArray @@ -2136,10 +2136,18 @@ declare module "typescript" { >NodeArray : NodeArray >EnumMember : EnumMember } - interface ModuleDeclaration extends Declaration, ModuleElement { + interface ExportContainer { +>ExportContainer : ExportContainer + + exportStars?: ExportDeclaration[]; +>exportStars : ExportDeclaration[] +>ExportDeclaration : ExportDeclaration + } + interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer { >ModuleDeclaration : ModuleDeclaration >Declaration : Declaration >ModuleElement : ModuleElement +>ExportContainer : ExportContainer name: Identifier | LiteralExpression; >name : Identifier | LiteralExpression @@ -2290,9 +2298,10 @@ declare module "typescript" { hasTrailingNewLine?: boolean; >hasTrailingNewLine : boolean } - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, ExportContainer { >SourceFile : SourceFile >Declaration : Declaration +>ExportContainer : ExportContainer statements: NodeArray; >statements : NodeArray @@ -2921,8 +2930,8 @@ declare module "typescript" { >EmitResolver : EmitResolver getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; ->getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration) => string ->node : EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration +>getGeneratedNameForNode : (node: EnumDeclaration | ExportDeclaration | ModuleDeclaration | ImportDeclaration) => string +>node : EnumDeclaration | ExportDeclaration | ModuleDeclaration | ImportDeclaration >ModuleDeclaration : ModuleDeclaration >EnumDeclaration : EnumDeclaration >ImportDeclaration : ImportDeclaration @@ -3285,6 +3294,10 @@ declare module "typescript" { unionType?: UnionType; >unionType : UnionType >UnionType : UnionType + + resolvedExports?: SymbolTable; +>resolvedExports : SymbolTable +>SymbolTable : SymbolTable } interface TransientSymbol extends Symbol, SymbolLinks { >TransientSymbol : TransientSymbol diff --git a/tests/baselines/reference/APISample_linter.js b/tests/baselines/reference/APISample_linter.js index 0ec2bf4f77c..9af13574ae6 100644 --- a/tests/baselines/reference/APISample_linter.js +++ b/tests/baselines/reference/APISample_linter.js @@ -370,13 +370,13 @@ declare module "typescript" { kind: SyntaxKind; flags: NodeFlags; parserContextFlags?: ParserContextFlags; + modifiers?: ModifiersArray; id?: number; parent?: Node; symbol?: Symbol; locals?: SymbolTable; nextContainer?: Node; localSymbol?: Symbol; - modifiers?: ModifiersArray; } interface NodeArray extends Array, TextRange { hasTrailingComma?: boolean; @@ -736,7 +736,10 @@ declare module "typescript" { name: Identifier; members: NodeArray; } - interface ModuleDeclaration extends Declaration, ModuleElement { + interface ExportContainer { + exportStars?: ExportDeclaration[]; + } + interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer { name: Identifier | LiteralExpression; body: ModuleBlock | ModuleDeclaration; } @@ -785,7 +788,7 @@ declare module "typescript" { interface CommentRange extends TextRange { hasTrailingNewLine?: boolean; } - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, ExportContainer { statements: NodeArray; endOfFileToken: Node; fileName: string; @@ -1046,6 +1049,7 @@ declare module "typescript" { exportAssignmentChecked?: boolean; exportAssignmentSymbol?: Symbol; unionType?: UnionType; + resolvedExports?: SymbolTable; } interface TransientSymbol extends Symbol, SymbolLinks { } diff --git a/tests/baselines/reference/APISample_linter.types b/tests/baselines/reference/APISample_linter.types index 3bb894b55de..dc30fedce35 100644 --- a/tests/baselines/reference/APISample_linter.types +++ b/tests/baselines/reference/APISample_linter.types @@ -1169,6 +1169,10 @@ declare module "typescript" { >parserContextFlags : ParserContextFlags >ParserContextFlags : ParserContextFlags + modifiers?: ModifiersArray; +>modifiers : ModifiersArray +>ModifiersArray : ModifiersArray + id?: number; >id : number @@ -1191,10 +1195,6 @@ declare module "typescript" { localSymbol?: Symbol; >localSymbol : Symbol >Symbol : Symbol - - modifiers?: ModifiersArray; ->modifiers : ModifiersArray ->ModifiersArray : ModifiersArray } interface NodeArray extends Array, TextRange { >NodeArray : NodeArray @@ -2280,10 +2280,18 @@ declare module "typescript" { >NodeArray : NodeArray >EnumMember : EnumMember } - interface ModuleDeclaration extends Declaration, ModuleElement { + interface ExportContainer { +>ExportContainer : ExportContainer + + exportStars?: ExportDeclaration[]; +>exportStars : ExportDeclaration[] +>ExportDeclaration : ExportDeclaration + } + interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer { >ModuleDeclaration : ModuleDeclaration >Declaration : Declaration >ModuleElement : ModuleElement +>ExportContainer : ExportContainer name: Identifier | LiteralExpression; >name : Identifier | LiteralExpression @@ -2434,9 +2442,10 @@ declare module "typescript" { hasTrailingNewLine?: boolean; >hasTrailingNewLine : boolean } - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, ExportContainer { >SourceFile : SourceFile >Declaration : Declaration +>ExportContainer : ExportContainer statements: NodeArray; >statements : NodeArray @@ -3065,8 +3074,8 @@ declare module "typescript" { >EmitResolver : EmitResolver getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; ->getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration) => string ->node : EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration +>getGeneratedNameForNode : (node: EnumDeclaration | ExportDeclaration | ModuleDeclaration | ImportDeclaration) => string +>node : EnumDeclaration | ExportDeclaration | ModuleDeclaration | ImportDeclaration >ModuleDeclaration : ModuleDeclaration >EnumDeclaration : EnumDeclaration >ImportDeclaration : ImportDeclaration @@ -3429,6 +3438,10 @@ declare module "typescript" { unionType?: UnionType; >unionType : UnionType >UnionType : UnionType + + resolvedExports?: SymbolTable; +>resolvedExports : SymbolTable +>SymbolTable : SymbolTable } interface TransientSymbol extends Symbol, SymbolLinks { >TransientSymbol : TransientSymbol diff --git a/tests/baselines/reference/APISample_transform.js b/tests/baselines/reference/APISample_transform.js index 1627415c834..4b556d8db0e 100644 --- a/tests/baselines/reference/APISample_transform.js +++ b/tests/baselines/reference/APISample_transform.js @@ -371,13 +371,13 @@ declare module "typescript" { kind: SyntaxKind; flags: NodeFlags; parserContextFlags?: ParserContextFlags; + modifiers?: ModifiersArray; id?: number; parent?: Node; symbol?: Symbol; locals?: SymbolTable; nextContainer?: Node; localSymbol?: Symbol; - modifiers?: ModifiersArray; } interface NodeArray extends Array, TextRange { hasTrailingComma?: boolean; @@ -737,7 +737,10 @@ declare module "typescript" { name: Identifier; members: NodeArray; } - interface ModuleDeclaration extends Declaration, ModuleElement { + interface ExportContainer { + exportStars?: ExportDeclaration[]; + } + interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer { name: Identifier | LiteralExpression; body: ModuleBlock | ModuleDeclaration; } @@ -786,7 +789,7 @@ declare module "typescript" { interface CommentRange extends TextRange { hasTrailingNewLine?: boolean; } - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, ExportContainer { statements: NodeArray; endOfFileToken: Node; fileName: string; @@ -1047,6 +1050,7 @@ declare module "typescript" { exportAssignmentChecked?: boolean; exportAssignmentSymbol?: Symbol; unionType?: UnionType; + resolvedExports?: SymbolTable; } interface TransientSymbol extends Symbol, SymbolLinks { } diff --git a/tests/baselines/reference/APISample_transform.types b/tests/baselines/reference/APISample_transform.types index 9d0dbdb0768..8eb0fd5c34d 100644 --- a/tests/baselines/reference/APISample_transform.types +++ b/tests/baselines/reference/APISample_transform.types @@ -1121,6 +1121,10 @@ declare module "typescript" { >parserContextFlags : ParserContextFlags >ParserContextFlags : ParserContextFlags + modifiers?: ModifiersArray; +>modifiers : ModifiersArray +>ModifiersArray : ModifiersArray + id?: number; >id : number @@ -1143,10 +1147,6 @@ declare module "typescript" { localSymbol?: Symbol; >localSymbol : Symbol >Symbol : Symbol - - modifiers?: ModifiersArray; ->modifiers : ModifiersArray ->ModifiersArray : ModifiersArray } interface NodeArray extends Array, TextRange { >NodeArray : NodeArray @@ -2232,10 +2232,18 @@ declare module "typescript" { >NodeArray : NodeArray >EnumMember : EnumMember } - interface ModuleDeclaration extends Declaration, ModuleElement { + interface ExportContainer { +>ExportContainer : ExportContainer + + exportStars?: ExportDeclaration[]; +>exportStars : ExportDeclaration[] +>ExportDeclaration : ExportDeclaration + } + interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer { >ModuleDeclaration : ModuleDeclaration >Declaration : Declaration >ModuleElement : ModuleElement +>ExportContainer : ExportContainer name: Identifier | LiteralExpression; >name : Identifier | LiteralExpression @@ -2386,9 +2394,10 @@ declare module "typescript" { hasTrailingNewLine?: boolean; >hasTrailingNewLine : boolean } - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, ExportContainer { >SourceFile : SourceFile >Declaration : Declaration +>ExportContainer : ExportContainer statements: NodeArray; >statements : NodeArray @@ -3017,8 +3026,8 @@ declare module "typescript" { >EmitResolver : EmitResolver getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; ->getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration) => string ->node : EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration +>getGeneratedNameForNode : (node: EnumDeclaration | ExportDeclaration | ModuleDeclaration | ImportDeclaration) => string +>node : EnumDeclaration | ExportDeclaration | ModuleDeclaration | ImportDeclaration >ModuleDeclaration : ModuleDeclaration >EnumDeclaration : EnumDeclaration >ImportDeclaration : ImportDeclaration @@ -3381,6 +3390,10 @@ declare module "typescript" { unionType?: UnionType; >unionType : UnionType >UnionType : UnionType + + resolvedExports?: SymbolTable; +>resolvedExports : SymbolTable +>SymbolTable : SymbolTable } interface TransientSymbol extends Symbol, SymbolLinks { >TransientSymbol : TransientSymbol diff --git a/tests/baselines/reference/APISample_watcher.js b/tests/baselines/reference/APISample_watcher.js index 6c4c0977aac..c97effc3458 100644 --- a/tests/baselines/reference/APISample_watcher.js +++ b/tests/baselines/reference/APISample_watcher.js @@ -408,13 +408,13 @@ declare module "typescript" { kind: SyntaxKind; flags: NodeFlags; parserContextFlags?: ParserContextFlags; + modifiers?: ModifiersArray; id?: number; parent?: Node; symbol?: Symbol; locals?: SymbolTable; nextContainer?: Node; localSymbol?: Symbol; - modifiers?: ModifiersArray; } interface NodeArray extends Array, TextRange { hasTrailingComma?: boolean; @@ -774,7 +774,10 @@ declare module "typescript" { name: Identifier; members: NodeArray; } - interface ModuleDeclaration extends Declaration, ModuleElement { + interface ExportContainer { + exportStars?: ExportDeclaration[]; + } + interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer { name: Identifier | LiteralExpression; body: ModuleBlock | ModuleDeclaration; } @@ -823,7 +826,7 @@ declare module "typescript" { interface CommentRange extends TextRange { hasTrailingNewLine?: boolean; } - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, ExportContainer { statements: NodeArray; endOfFileToken: Node; fileName: string; @@ -1084,6 +1087,7 @@ declare module "typescript" { exportAssignmentChecked?: boolean; exportAssignmentSymbol?: Symbol; unionType?: UnionType; + resolvedExports?: SymbolTable; } interface TransientSymbol extends Symbol, SymbolLinks { } diff --git a/tests/baselines/reference/APISample_watcher.types b/tests/baselines/reference/APISample_watcher.types index fb342d09cdd..cb46e45347e 100644 --- a/tests/baselines/reference/APISample_watcher.types +++ b/tests/baselines/reference/APISample_watcher.types @@ -1294,6 +1294,10 @@ declare module "typescript" { >parserContextFlags : ParserContextFlags >ParserContextFlags : ParserContextFlags + modifiers?: ModifiersArray; +>modifiers : ModifiersArray +>ModifiersArray : ModifiersArray + id?: number; >id : number @@ -1316,10 +1320,6 @@ declare module "typescript" { localSymbol?: Symbol; >localSymbol : Symbol >Symbol : Symbol - - modifiers?: ModifiersArray; ->modifiers : ModifiersArray ->ModifiersArray : ModifiersArray } interface NodeArray extends Array, TextRange { >NodeArray : NodeArray @@ -2405,10 +2405,18 @@ declare module "typescript" { >NodeArray : NodeArray >EnumMember : EnumMember } - interface ModuleDeclaration extends Declaration, ModuleElement { + interface ExportContainer { +>ExportContainer : ExportContainer + + exportStars?: ExportDeclaration[]; +>exportStars : ExportDeclaration[] +>ExportDeclaration : ExportDeclaration + } + interface ModuleDeclaration extends Declaration, ModuleElement, ExportContainer { >ModuleDeclaration : ModuleDeclaration >Declaration : Declaration >ModuleElement : ModuleElement +>ExportContainer : ExportContainer name: Identifier | LiteralExpression; >name : Identifier | LiteralExpression @@ -2559,9 +2567,10 @@ declare module "typescript" { hasTrailingNewLine?: boolean; >hasTrailingNewLine : boolean } - interface SourceFile extends Declaration { + interface SourceFile extends Declaration, ExportContainer { >SourceFile : SourceFile >Declaration : Declaration +>ExportContainer : ExportContainer statements: NodeArray; >statements : NodeArray @@ -3190,8 +3199,8 @@ declare module "typescript" { >EmitResolver : EmitResolver getGeneratedNameForNode(node: ModuleDeclaration | EnumDeclaration | ImportDeclaration | ExportDeclaration): string; ->getGeneratedNameForNode : (node: EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration) => string ->node : EnumDeclaration | ModuleDeclaration | ImportDeclaration | ExportDeclaration +>getGeneratedNameForNode : (node: EnumDeclaration | ExportDeclaration | ModuleDeclaration | ImportDeclaration) => string +>node : EnumDeclaration | ExportDeclaration | ModuleDeclaration | ImportDeclaration >ModuleDeclaration : ModuleDeclaration >EnumDeclaration : EnumDeclaration >ImportDeclaration : ImportDeclaration @@ -3554,6 +3563,10 @@ declare module "typescript" { unionType?: UnionType; >unionType : UnionType >UnionType : UnionType + + resolvedExports?: SymbolTable; +>resolvedExports : SymbolTable +>SymbolTable : SymbolTable } interface TransientSymbol extends Symbol, SymbolLinks { >TransientSymbol : TransientSymbol From 7cca6519ef5eeccedd45536d7555c547961503ac Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 15 Feb 2015 18:46:41 -0800 Subject: [PATCH 9/9] Include globals in check for existing identifiers --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 828b03c91d7..bb250c3f9d5 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10260,7 +10260,7 @@ module ts { } function isExistingName(name: string) { - return hasProperty(sourceFile.identifiers, name) || hasProperty(generatedNames, name); + return hasProperty(globals, name) || hasProperty(sourceFile.identifiers, name) || hasProperty(generatedNames, name); } function makeUniqueName(baseName: string): string {