From b44ac91de932012d54b576e9ae343aac7ce8c940 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 4 Aug 2017 23:45:09 -0700 Subject: [PATCH 01/12] Added failing test for a before-transform that indirectly replaces a namespace declaration. --- src/harness/unittests/transform.ts | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/src/harness/unittests/transform.ts b/src/harness/unittests/transform.ts index 537235f2f6776..5799de1bfbd36 100644 --- a/src/harness/unittests/transform.ts +++ b/src/harness/unittests/transform.ts @@ -74,6 +74,32 @@ namespace ts { } }).outputText; }); + + testBaseline("synthesizedNamespace", () => { + return ts.transpileModule(`namespace Reflect { const x = 1; }`, { + transformers: { + before: [forceSyntheticModuleDeclaration], + }, + compilerOptions: { + newLine: NewLineKind.CarriageReturnLineFeed, + } + }).outputText; + + function forceSyntheticModuleDeclaration(context: ts.TransformationContext) { + return (sourceFile: ts.SourceFile): ts.SourceFile => { + return visitNode(sourceFile); + + function visitNode(node: T): T { + if (node.kind === ts.SyntaxKind.ModuleBlock) { + const block = node as T & ts.ModuleBlock; + const statements = ts.createNodeArray([...block.statements]); + return ts.updateModuleBlock(block, statements) as typeof block; + } + return ts.visitEachChild(node, visitNode, context); + } + }; + } + }) }); } From 5cb5cf14de2cc46613214b258eb5c5e52881c632 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 4 Aug 2017 23:48:45 -0700 Subject: [PATCH 02/12] Accepted baselines. --- .../transformApi/transformsCorrectly.synthesizedNamespace.js | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js new file mode 100644 index 0000000000000..5897d293ff5fd --- /dev/null +++ b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js @@ -0,0 +1,3 @@ +(function (Reflect) { + var x = 1; +})(Reflect || (Reflect = {})); From 9f1b7471139f3ed91b2b987dcb2cacb66b9de0cb Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sat, 5 Aug 2017 00:12:54 -0700 Subject: [PATCH 03/12] Made the first-declaration check conservative in the TypeScript transform. --- src/compiler/transformers/ts.ts | 17 +++++++++-------- src/harness/unittests/transform.ts | 2 +- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 19ba8b1f2d25f..89693c0d22ab8 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2639,9 +2639,6 @@ namespace ts { /** * Records that a declaration was emitted in the current scope, if it was the first * declaration for the provided symbol. - * - * NOTE: if there is ever a transformation above this one, we may not be able to rely - * on symbol names. */ function recordEmittedDeclarationInScope(node: Node) { const name = node.symbol && node.symbol.escapedName; @@ -2657,10 +2654,13 @@ namespace ts { } /** - * Determines whether a declaration is the first declaration with the same name emitted - * in the current scope. + * Determines whether a declaration is *could* be the first declaration with + * the same name emitted in the current scope. Only returns false if we are absolutely + * certain a previous declaration has been emitted. */ - function isFirstEmittedDeclarationInScope(node: Node) { + function isPotentiallyFirstEmittedDeclarationInScope(node: Node) { + // If the node has a named symbol, then we have enough knowledge to determine + // whether a prior declaration has been emitted. if (currentScopeFirstDeclarationsOfName) { const name = node.symbol && node.symbol.escapedName; if (name) { @@ -2668,7 +2668,8 @@ namespace ts { } } - return false; + // Otherwise, we can't be sure. For example, this node could be synthetic. + return true; } /** @@ -2690,7 +2691,7 @@ namespace ts { setOriginalNode(statement, node); recordEmittedDeclarationInScope(node); - if (isFirstEmittedDeclarationInScope(node)) { + if (isPotentiallyFirstEmittedDeclarationInScope(node)) { // Adjust the source map emit to match the old emitter. if (node.kind === SyntaxKind.EnumDeclaration) { setSourceMapRange(statement.declarationList, node); diff --git a/src/harness/unittests/transform.ts b/src/harness/unittests/transform.ts index 5799de1bfbd36..74b92f7c5a73c 100644 --- a/src/harness/unittests/transform.ts +++ b/src/harness/unittests/transform.ts @@ -99,7 +99,7 @@ namespace ts { } }; } - }) + }); }); } From 22e0d9f7911124f23ee7cfd6e67dc1cf063a4e75 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Sat, 5 Aug 2017 00:14:23 -0700 Subject: [PATCH 04/12] Accepted baselines. --- tests/baselines/reference/parserEnumDeclaration4.js | 1 + tests/baselines/reference/reservedWords2.js | 1 + .../transformApi/transformsCorrectly.synthesizedNamespace.js | 1 + 3 files changed, 3 insertions(+) diff --git a/tests/baselines/reference/parserEnumDeclaration4.js b/tests/baselines/reference/parserEnumDeclaration4.js index d5b1e696a3d7a..47450d419e157 100644 --- a/tests/baselines/reference/parserEnumDeclaration4.js +++ b/tests/baselines/reference/parserEnumDeclaration4.js @@ -3,6 +3,7 @@ enum void { } //// [parserEnumDeclaration4.js] +var ; (function () { })( || ( = {})); void {}; diff --git a/tests/baselines/reference/reservedWords2.js b/tests/baselines/reference/reservedWords2.js index f172f37d05396..da6a35bba82b3 100644 --- a/tests/baselines/reference/reservedWords2.js +++ b/tests/baselines/reference/reservedWords2.js @@ -35,6 +35,7 @@ debugger; if () ; [1, 2]; +var ; (function () { })( || ( = {})); void {}; diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js index 5897d293ff5fd..76d5d9a4dab86 100644 --- a/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js +++ b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js @@ -1,3 +1,4 @@ +var Reflect; (function (Reflect) { var x = 1; })(Reflect || (Reflect = {})); From 6ef27a4e1e2d7daf77c21bdd2148ee4459be1420 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 10 Aug 2017 08:28:25 -0700 Subject: [PATCH 05/12] Added test for class/namespace merging with an ESNext target. --- src/harness/unittests/transform.ts | 43 ++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 14 deletions(-) diff --git a/src/harness/unittests/transform.ts b/src/harness/unittests/transform.ts index 74b92f7c5a73c..dc90638afd130 100644 --- a/src/harness/unittests/transform.ts +++ b/src/harness/unittests/transform.ts @@ -78,28 +78,43 @@ namespace ts { testBaseline("synthesizedNamespace", () => { return ts.transpileModule(`namespace Reflect { const x = 1; }`, { transformers: { - before: [forceSyntheticModuleDeclaration], + before: [forceNamespaceRewrite], }, compilerOptions: { newLine: NewLineKind.CarriageReturnLineFeed, } }).outputText; + }); - function forceSyntheticModuleDeclaration(context: ts.TransformationContext) { - return (sourceFile: ts.SourceFile): ts.SourceFile => { - return visitNode(sourceFile); + testBaseline("synthesizedNamespaceFollowingClass", () => { + return ts.transpileModule(` + class C { foo = 10; static bar = 20 } + namespace C { export let x = 10; } + `, { + transformers: { + before: [forceNamespaceRewrite], + }, + compilerOptions: { + target: ts.ScriptTarget.ESNext, + newLine: NewLineKind.CarriageReturnLineFeed, + } + }).outputText; + }); + + function forceNamespaceRewrite(context: ts.TransformationContext) { + return (sourceFile: ts.SourceFile): ts.SourceFile => { + return visitNode(sourceFile); - function visitNode(node: T): T { - if (node.kind === ts.SyntaxKind.ModuleBlock) { - const block = node as T & ts.ModuleBlock; - const statements = ts.createNodeArray([...block.statements]); - return ts.updateModuleBlock(block, statements) as typeof block; - } - return ts.visitEachChild(node, visitNode, context); + function visitNode(node: T): T { + if (node.kind === ts.SyntaxKind.ModuleBlock) { + const block = node as T & ts.ModuleBlock; + const statements = ts.createNodeArray([...block.statements]); + return ts.updateModuleBlock(block, statements) as typeof block; } - }; - } - }); + return ts.visitEachChild(node, visitNode, context); + } + }; + } }); } From 66e2a0bb943538f3496e41f55a80899f0cfd78e1 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Thu, 10 Aug 2017 08:28:43 -0700 Subject: [PATCH 06/12] Accepted baselines. --- ...ormsCorrectly.synthesizedNamespaceFollowingClass.js | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespaceFollowingClass.js diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespaceFollowingClass.js b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespaceFollowingClass.js new file mode 100644 index 0000000000000..9dedde29f8b78 --- /dev/null +++ b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespaceFollowingClass.js @@ -0,0 +1,10 @@ +class C { + constructor() { + this.foo = 10; + } +} +C.bar = 20; +var C; +(function (C) { + C.x = 10; +})(C || (C = {})); From 18cced9abd97005b5c139bd97ac41e892f0c3b9d Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Aug 2017 18:35:31 -0400 Subject: [PATCH 07/12] Added test. --- src/harness/unittests/transform.ts | 27 +++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/harness/unittests/transform.ts b/src/harness/unittests/transform.ts index dc90638afd130..6edd174da23d4 100644 --- a/src/harness/unittests/transform.ts +++ b/src/harness/unittests/transform.ts @@ -75,7 +75,7 @@ namespace ts { }).outputText; }); - testBaseline("synthesizedNamespace", () => { + testBaseline("rewrittenNamespace", () => { return ts.transpileModule(`namespace Reflect { const x = 1; }`, { transformers: { before: [forceNamespaceRewrite], @@ -86,7 +86,7 @@ namespace ts { }).outputText; }); - testBaseline("synthesizedNamespaceFollowingClass", () => { + testBaseline("rewrittenNamespaceFollowingClass", () => { return ts.transpileModule(` class C { foo = 10; static bar = 20 } namespace C { export let x = 10; } @@ -101,6 +101,29 @@ namespace ts { }).outputText; }); + testBaseline("synthesizedClassAndNamespaceCombination", () => { + return ts.transpileModule("", { + transformers: { + before: [replaceWithClassAndNamespace], + }, + compilerOptions: { + target: ts.ScriptTarget.ESNext, + newLine: NewLineKind.CarriageReturnLineFeed, + } + }).outputText; + + function replaceWithClassAndNamespace() { + return (sourceFile: ts.SourceFile) => { + const result = getMutableClone(sourceFile); + result.statements = ts.createNodeArray([ + ts.createClassDeclaration(undefined, undefined, "Foo", undefined, undefined, undefined), + ts.createModuleDeclaration(undefined, undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()])) + ]); + return result; + } + } + }); + function forceNamespaceRewrite(context: ts.TransformationContext) { return (sourceFile: ts.SourceFile): ts.SourceFile => { return visitNode(sourceFile); From 33a036b6799f297fcf7b913c3a56385e47026cd6 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Fri, 11 Aug 2017 18:47:21 -0400 Subject: [PATCH 08/12] Accepted baselines. --- ...mespace.js => transformsCorrectly.rewrittenNamespace.js} | 0 ...transformsCorrectly.rewrittenNamespaceFollowingClass.js} | 0 ...ormsCorrectly.synthesizedClassAndNamespaceCombination.js | 6 ++++++ 3 files changed, 6 insertions(+) rename tests/baselines/reference/transformApi/{transformsCorrectly.synthesizedNamespace.js => transformsCorrectly.rewrittenNamespace.js} (100%) rename tests/baselines/reference/transformApi/{transformsCorrectly.synthesizedNamespaceFollowingClass.js => transformsCorrectly.rewrittenNamespaceFollowingClass.js} (100%) create mode 100644 tests/baselines/reference/transformApi/transformsCorrectly.synthesizedClassAndNamespaceCombination.js diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js b/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespace.js similarity index 100% rename from tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespace.js rename to tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespace.js diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespaceFollowingClass.js b/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js similarity index 100% rename from tests/baselines/reference/transformApi/transformsCorrectly.synthesizedNamespaceFollowingClass.js rename to tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedClassAndNamespaceCombination.js b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedClassAndNamespaceCombination.js new file mode 100644 index 0000000000000..ad11068a5127c --- /dev/null +++ b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedClassAndNamespaceCombination.js @@ -0,0 +1,6 @@ +class Foo { +} +var Foo; +(function (Foo) { + ; +})(Foo || (Foo = {})); From a51397e339c35cf8466460ee014c7100ea266c95 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 14 Aug 2017 21:24:30 -0400 Subject: [PATCH 09/12] Just track the local names of identifiers instead of ever using symbols. --- src/compiler/transformers/ts.ts | 47 +++++++++++++++++++++------------ src/compiler/types.ts | 2 +- 2 files changed, 31 insertions(+), 18 deletions(-) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index 89693c0d22ab8..df07082766743 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -151,7 +151,17 @@ namespace ts { break; } - recordEmittedDeclarationInScope(node); + // Record these declarations provided that they have a name. + if ((node as ClassDeclaration | FunctionDeclaration).name) { + recordEmittedDeclarationInScope(node as ClassDeclaration | FunctionDeclaration); + } + else { + // These nodes should always have names unless they are default-exports; + // however, class declaration parsing allows for undefined names, so syntactically invalid + // programs may also have an undefined name. + Debug.assert(node.kind === SyntaxKind.ClassDeclaration || hasModifier(node, ModifierFlags.Default)); + } + break; } } @@ -2640,16 +2650,14 @@ namespace ts { * Records that a declaration was emitted in the current scope, if it was the first * declaration for the provided symbol. */ - function recordEmittedDeclarationInScope(node: Node) { - const name = node.symbol && node.symbol.escapedName; - if (name) { - if (!currentScopeFirstDeclarationsOfName) { - currentScopeFirstDeclarationsOfName = createUnderscoreEscapedMap(); - } + function recordEmittedDeclarationInScope(node: FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration) { + if (!currentScopeFirstDeclarationsOfName) { + currentScopeFirstDeclarationsOfName = createUnderscoreEscapedMap(); + } - if (!currentScopeFirstDeclarationsOfName.has(name)) { - currentScopeFirstDeclarationsOfName.set(name, node); - } + const name = declaredNameInScope(node); + if (!currentScopeFirstDeclarationsOfName.has(name)) { + currentScopeFirstDeclarationsOfName.set(name, node); } } @@ -2658,20 +2666,25 @@ namespace ts { * the same name emitted in the current scope. Only returns false if we are absolutely * certain a previous declaration has been emitted. */ - function isPotentiallyFirstEmittedDeclarationInScope(node: Node) { + function isFirstEmittedDeclarationInScope(node: ModuleDeclaration | EnumDeclaration) { // If the node has a named symbol, then we have enough knowledge to determine // whether a prior declaration has been emitted. if (currentScopeFirstDeclarationsOfName) { - const name = node.symbol && node.symbol.escapedName; - if (name) { - return currentScopeFirstDeclarationsOfName.get(name) === node; - } + const name = declaredNameInScope(node); + return currentScopeFirstDeclarationsOfName.get(name) === node; } // Otherwise, we can't be sure. For example, this node could be synthetic. return true; } + function declaredNameInScope(node: FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration): __String { + if (node.name.kind !== SyntaxKind.Identifier) { + Debug.fail(formatSyntaxKind(node.kind) + " should have an identifier name."); + } + return (node.name as Identifier).escapedText; + } + /** * Adds a leading VariableStatement for a enum or module declaration. */ @@ -2691,7 +2704,7 @@ namespace ts { setOriginalNode(statement, node); recordEmittedDeclarationInScope(node); - if (isPotentiallyFirstEmittedDeclarationInScope(node)) { + if (isFirstEmittedDeclarationInScope(node)) { // Adjust the source map emit to match the old emitter. if (node.kind === SyntaxKind.EnumDeclaration) { setSourceMapRange(statement.declarationList, node); @@ -2747,7 +2760,7 @@ namespace ts { return createNotEmittedStatement(node); } - Debug.assert(isIdentifier(node.name), "TypeScript module should have an Identifier name."); + Debug.assert(isIdentifier(node.name), "A TypeScript namespace should have an Identifier name."); enableSubstitutionForNamespaceExports(); const statements: Statement[] = []; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 09f1b5cfcc53c..b0580956a4b44 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -2896,7 +2896,7 @@ namespace ts { export interface Symbol { flags: SymbolFlags; // Symbol flags - escapedName: __String; // Name of symbol + escapedName: __String; // Name of symbol declarations?: Declaration[]; // Declarations associated with this symbol valueDeclaration?: Declaration; // First value declaration of the symbol members?: SymbolTable; // Class, interface or literal instance members From 6e60a017bbc187d10c76ca7c392623f8b4060dd9 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Mon, 14 Aug 2017 21:24:51 -0400 Subject: [PATCH 10/12] Accepted baselines. --- tests/baselines/reference/defaultExportsCannotMerge01.js | 1 - tests/baselines/reference/defaultExportsCannotMerge04.js | 1 - tests/baselines/reference/reservedWords2.js | 1 - .../transformsCorrectly.rewrittenNamespaceFollowingClass.js | 1 - ...ransformsCorrectly.synthesizedClassAndNamespaceCombination.js | 1 - 5 files changed, 5 deletions(-) diff --git a/tests/baselines/reference/defaultExportsCannotMerge01.js b/tests/baselines/reference/defaultExportsCannotMerge01.js index c7091371d3612..9c433ce3a2b11 100644 --- a/tests/baselines/reference/defaultExportsCannotMerge01.js +++ b/tests/baselines/reference/defaultExportsCannotMerge01.js @@ -36,7 +36,6 @@ function Decl() { return 0; } exports.default = Decl; -var Decl; (function (Decl) { Decl.x = 10; Decl.y = 20; diff --git a/tests/baselines/reference/defaultExportsCannotMerge04.js b/tests/baselines/reference/defaultExportsCannotMerge04.js index de32618d8cce7..f8f375377ebdb 100644 --- a/tests/baselines/reference/defaultExportsCannotMerge04.js +++ b/tests/baselines/reference/defaultExportsCannotMerge04.js @@ -18,6 +18,5 @@ Object.defineProperty(exports, "__esModule", { value: true }); function Foo() { } exports.default = Foo; -var Foo; (function (Foo) { })(Foo || (Foo = {})); diff --git a/tests/baselines/reference/reservedWords2.js b/tests/baselines/reference/reservedWords2.js index da6a35bba82b3..f172f37d05396 100644 --- a/tests/baselines/reference/reservedWords2.js +++ b/tests/baselines/reference/reservedWords2.js @@ -35,7 +35,6 @@ debugger; if () ; [1, 2]; -var ; (function () { })( || ( = {})); void {}; diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js b/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js index 9dedde29f8b78..3f2dd6cdb56fb 100644 --- a/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js +++ b/tests/baselines/reference/transformApi/transformsCorrectly.rewrittenNamespaceFollowingClass.js @@ -4,7 +4,6 @@ class C { } } C.bar = 20; -var C; (function (C) { C.x = 10; })(C || (C = {})); diff --git a/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedClassAndNamespaceCombination.js b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedClassAndNamespaceCombination.js index ad11068a5127c..ababb49d717a5 100644 --- a/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedClassAndNamespaceCombination.js +++ b/tests/baselines/reference/transformApi/transformsCorrectly.synthesizedClassAndNamespaceCombination.js @@ -1,6 +1,5 @@ class Foo { } -var Foo; (function (Foo) { ; })(Foo || (Foo = {})); From 281d821fe812f171ae94fa77503514ec0edb8521 Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Tue, 15 Aug 2017 12:16:54 -0700 Subject: [PATCH 11/12] Fix lint errors. --- src/harness/unittests/transform.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/harness/unittests/transform.ts b/src/harness/unittests/transform.ts index 6edd174da23d4..27e41a96dfcfa 100644 --- a/src/harness/unittests/transform.ts +++ b/src/harness/unittests/transform.ts @@ -116,11 +116,11 @@ namespace ts { return (sourceFile: ts.SourceFile) => { const result = getMutableClone(sourceFile); result.statements = ts.createNodeArray([ - ts.createClassDeclaration(undefined, undefined, "Foo", undefined, undefined, undefined), - ts.createModuleDeclaration(undefined, undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()])) + ts.createClassDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, "Foo", /*typeParameters*/ undefined, /*heritageClauses*/ undefined, /*members*/ undefined), + ts.createModuleDeclaration(/*decorators*/ undefined, /*modifiers*/ undefined, createIdentifier("Foo"), createModuleBlock([createEmptyStatement()])) ]); return result; - } + }; } }); From b7020628c14284dfcb1df8525ac61a22f945c0ab Mon Sep 17 00:00:00 2001 From: Daniel Rosenwasser Date: Wed, 16 Aug 2017 15:06:51 -0700 Subject: [PATCH 12/12] Addressed code review feedback. --- src/compiler/transformers/ts.ts | 15 ++++----------- 1 file changed, 4 insertions(+), 11 deletions(-) diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index df07082766743..4c679ea1eee84 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -2662,26 +2662,19 @@ namespace ts { } /** - * Determines whether a declaration is *could* be the first declaration with - * the same name emitted in the current scope. Only returns false if we are absolutely - * certain a previous declaration has been emitted. + * Determines whether a declaration is the first declaration with + * the same name emitted in the current scope. */ function isFirstEmittedDeclarationInScope(node: ModuleDeclaration | EnumDeclaration) { - // If the node has a named symbol, then we have enough knowledge to determine - // whether a prior declaration has been emitted. if (currentScopeFirstDeclarationsOfName) { const name = declaredNameInScope(node); return currentScopeFirstDeclarationsOfName.get(name) === node; } - - // Otherwise, we can't be sure. For example, this node could be synthetic. return true; } function declaredNameInScope(node: FunctionDeclaration | ClassDeclaration | ModuleDeclaration | EnumDeclaration): __String { - if (node.name.kind !== SyntaxKind.Identifier) { - Debug.fail(formatSyntaxKind(node.kind) + " should have an identifier name."); - } + Debug.assertNode(node.name, isIdentifier); return (node.name as Identifier).escapedText; } @@ -2760,7 +2753,7 @@ namespace ts { return createNotEmittedStatement(node); } - Debug.assert(isIdentifier(node.name), "A TypeScript namespace should have an Identifier name."); + Debug.assertNode(node.name, isIdentifier, "A TypeScript namespace should have an Identifier name."); enableSubstitutionForNamespaceExports(); const statements: Statement[] = [];