From 2e36faed2862d575356086701660e3c0addde9ea Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Wed, 22 Oct 2014 10:23:15 -0700 Subject: [PATCH 1/2] Fix the crash in declaration file emit when alias is used before its declaration Fixes #938 --- src/compiler/emitter.ts | 21 ++++++++++---- .../declFileAliasUseBeforeDeclaration.js | 29 +++++++++++++++++++ .../declFileAliasUseBeforeDeclaration.types | 15 ++++++++++ .../declFileAliasUseBeforeDeclaration.ts | 9 ++++++ 4 files changed, 68 insertions(+), 6 deletions(-) create mode 100644 tests/baselines/reference/declFileAliasUseBeforeDeclaration.js create mode 100644 tests/baselines/reference/declFileAliasUseBeforeDeclaration.types create mode 100644 tests/cases/compiler/declFileAliasUseBeforeDeclaration.ts diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 008f4f49331..b5919472fc6 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -345,13 +345,22 @@ module ts { var oldWriter = writer; forEach(importDeclarations, aliasToWrite => { var aliasEmitInfo = forEach(aliasDeclarationEmitInfo, declEmitInfo => declEmitInfo.declaration === aliasToWrite ? declEmitInfo : undefined); - writer = createTextWriter(newLine, trackSymbol); - for (var declarationIndent = aliasEmitInfo.indent; declarationIndent; declarationIndent--) { - writer.increaseIndent(); - } + // If the alias was marked as not visible when we saw its declaration, we would have saved the aliasEmitInfo, but if we haven't yet visited the alias declaration + // then we don't need to write it at this point. We will write it when we actually see its declaration + // Eg. + // export function bar(a: foo.Foo) { } + // import foo = require("foo"); + // Writing of function bar would mark alias declaration foo as visible but we haven't yet visited that declaration so do nothing, + // we would write alias foo declaration when we visit it since it would now be marked as visible + if (aliasEmitInfo) { + writer = createTextWriter(newLine, trackSymbol); + for (var declarationIndent = aliasEmitInfo.indent; declarationIndent; declarationIndent--) { + writer.increaseIndent(); + } - writeImportDeclaration(aliasToWrite); - aliasEmitInfo.asynchronousOutput = writer.getText(); + writeImportDeclaration(aliasToWrite); + aliasEmitInfo.asynchronousOutput = writer.getText(); + } }); writer = oldWriter; } diff --git a/tests/baselines/reference/declFileAliasUseBeforeDeclaration.js b/tests/baselines/reference/declFileAliasUseBeforeDeclaration.js new file mode 100644 index 00000000000..30ba24ed405 --- /dev/null +++ b/tests/baselines/reference/declFileAliasUseBeforeDeclaration.js @@ -0,0 +1,29 @@ +//// [tests/cases/compiler/declFileAliasUseBeforeDeclaration.ts] //// + +//// [declFileAliasUseBeforeDeclaration_foo.ts] + +export class Foo { } + +//// [declFileAliasUseBeforeDeclaration_test.ts] +export function bar(a: foo.Foo) { } +import foo = require("declFileAliasUseBeforeDeclaration_foo"); + +//// [declFileAliasUseBeforeDeclaration_foo.js] +var Foo = (function () { + function Foo() { + } + return Foo; +})(); +exports.Foo = Foo; +//// [declFileAliasUseBeforeDeclaration_test.js] +function bar(a) { +} +exports.bar = bar; + + +//// [declFileAliasUseBeforeDeclaration_foo.d.ts] +export declare class Foo { +} +//// [declFileAliasUseBeforeDeclaration_test.d.ts] +export declare function bar(a: foo.Foo): void; +import foo = require("declFileAliasUseBeforeDeclaration_foo"); diff --git a/tests/baselines/reference/declFileAliasUseBeforeDeclaration.types b/tests/baselines/reference/declFileAliasUseBeforeDeclaration.types new file mode 100644 index 00000000000..800df4ada49 --- /dev/null +++ b/tests/baselines/reference/declFileAliasUseBeforeDeclaration.types @@ -0,0 +1,15 @@ +=== tests/cases/compiler/declFileAliasUseBeforeDeclaration_test.ts === +export function bar(a: foo.Foo) { } +>bar : (a: foo.Foo) => void +>a : foo.Foo +>foo : unknown +>Foo : foo.Foo + +import foo = require("declFileAliasUseBeforeDeclaration_foo"); +>foo : typeof foo + +=== tests/cases/compiler/declFileAliasUseBeforeDeclaration_foo.ts === + +export class Foo { } +>Foo : Foo + diff --git a/tests/cases/compiler/declFileAliasUseBeforeDeclaration.ts b/tests/cases/compiler/declFileAliasUseBeforeDeclaration.ts new file mode 100644 index 00000000000..c803f65cf7c --- /dev/null +++ b/tests/cases/compiler/declFileAliasUseBeforeDeclaration.ts @@ -0,0 +1,9 @@ +//@module: commonjs +//@declaration: true + +// @Filename: declFileAliasUseBeforeDeclaration_foo.ts +export class Foo { } + +// @Filename: declFileAliasUseBeforeDeclaration_test.ts +export function bar(a: foo.Foo) { } +import foo = require("declFileAliasUseBeforeDeclaration_foo"); \ No newline at end of file From eebc8f903dd191ed2a6a249e3be1bba41d67460b Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Thu, 23 Oct 2014 10:20:33 -0700 Subject: [PATCH 2/2] Added another test case (#948) --- .../declFileAliasUseBeforeDeclaration2.js | 25 +++++++++++++++++++ .../declFileAliasUseBeforeDeclaration2.types | 19 ++++++++++++++ .../declFileAliasUseBeforeDeclaration2.ts | 12 +++++++++ 3 files changed, 56 insertions(+) create mode 100644 tests/baselines/reference/declFileAliasUseBeforeDeclaration2.js create mode 100644 tests/baselines/reference/declFileAliasUseBeforeDeclaration2.types create mode 100644 tests/cases/compiler/declFileAliasUseBeforeDeclaration2.ts diff --git a/tests/baselines/reference/declFileAliasUseBeforeDeclaration2.js b/tests/baselines/reference/declFileAliasUseBeforeDeclaration2.js new file mode 100644 index 00000000000..905a298bd32 --- /dev/null +++ b/tests/baselines/reference/declFileAliasUseBeforeDeclaration2.js @@ -0,0 +1,25 @@ +//// [declFileAliasUseBeforeDeclaration2.ts] + +declare module "test" { + module A { + class C { + } + } + class B extends E { + } + import E = A.C; +} + +//// [declFileAliasUseBeforeDeclaration2.js] + + +//// [declFileAliasUseBeforeDeclaration2.d.ts] +declare module "test" { + module A { + class C { + } + } + class B extends E { + } + import E = A.C; +} diff --git a/tests/baselines/reference/declFileAliasUseBeforeDeclaration2.types b/tests/baselines/reference/declFileAliasUseBeforeDeclaration2.types new file mode 100644 index 00000000000..362dd031e09 --- /dev/null +++ b/tests/baselines/reference/declFileAliasUseBeforeDeclaration2.types @@ -0,0 +1,19 @@ +=== tests/cases/compiler/declFileAliasUseBeforeDeclaration2.ts === + +declare module "test" { + module A { +>A : typeof A + + class C { +>C : C + } + } + class B extends E { +>B : B +>E : E + } + import E = A.C; +>E : typeof E +>A : typeof A +>C : E +} diff --git a/tests/cases/compiler/declFileAliasUseBeforeDeclaration2.ts b/tests/cases/compiler/declFileAliasUseBeforeDeclaration2.ts new file mode 100644 index 00000000000..25f19ec276e --- /dev/null +++ b/tests/cases/compiler/declFileAliasUseBeforeDeclaration2.ts @@ -0,0 +1,12 @@ +//@module: commonjs +//@declaration: true + +declare module "test" { + module A { + class C { + } + } + class B extends E { + } + import E = A.C; +} \ No newline at end of file