From d6ae55708d993852a8dd81d6978c81b4bb4203ed Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 12 Oct 2015 14:25:39 -0700 Subject: [PATCH 1/3] Do not mark class members as ambient or export. Even members of ambient classes. These flags have no useful semantics there, and it prevents ambient classes from merging properly with interfaces. --- src/compiler/checker.ts | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 228b1067bb0..cf8a2d676b4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10992,7 +10992,13 @@ namespace ts { function getEffectiveDeclarationFlags(n: Node, flagsToCheck: NodeFlags): NodeFlags { let flags = getCombinedNodeFlags(n); - if (n.parent.kind !== SyntaxKind.InterfaceDeclaration && isInAmbientContext(n)) { + + // children of classes (even ambient classes) should not be marked as ambient or export + // because those flags have no useful semantics there. + if (n.parent.kind !== SyntaxKind.InterfaceDeclaration && + n.parent.kind !== SyntaxKind.ClassDeclaration && + n.parent.kind !== SyntaxKind.ClassExpression && + isInAmbientContext(n)) { if (!(flags & NodeFlags.Ambient)) { // It is nested in an ambient context, which means it is automatically exported flags |= NodeFlags.Export; From 3a55c849c7bb2107492eb3c98c04d33af943bf8e Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 12 Oct 2015 14:26:45 -0700 Subject: [PATCH 2/3] Assert that ambient classes merge with interfaces Specifically, overloads are recognised as having the same export/ambient flags when merging the two. --- ...mbientClassMergesOverloadsWithInterface.js | 12 ++++++++++ ...tClassMergesOverloadsWithInterface.symbols | 22 +++++++++++++++++++ ...entClassMergesOverloadsWithInterface.types | 22 +++++++++++++++++++ ...mbientClassMergesOverloadsWithInterface.ts | 8 +++++++ 4 files changed, 64 insertions(+) create mode 100644 tests/baselines/reference/ambientClassMergesOverloadsWithInterface.js create mode 100644 tests/baselines/reference/ambientClassMergesOverloadsWithInterface.symbols create mode 100644 tests/baselines/reference/ambientClassMergesOverloadsWithInterface.types create mode 100644 tests/cases/compiler/ambientClassMergesOverloadsWithInterface.ts diff --git a/tests/baselines/reference/ambientClassMergesOverloadsWithInterface.js b/tests/baselines/reference/ambientClassMergesOverloadsWithInterface.js new file mode 100644 index 00000000000..417aedc4abc --- /dev/null +++ b/tests/baselines/reference/ambientClassMergesOverloadsWithInterface.js @@ -0,0 +1,12 @@ +//// [ambientClassMergesOverloadsWithInterface.ts] +declare class C { + baz(): any; + foo(n: number): any; +} +interface C { + foo(n: number): any; + bar(): any; +} + + +//// [ambientClassMergesOverloadsWithInterface.js] diff --git a/tests/baselines/reference/ambientClassMergesOverloadsWithInterface.symbols b/tests/baselines/reference/ambientClassMergesOverloadsWithInterface.symbols new file mode 100644 index 00000000000..9a5eb13d21d --- /dev/null +++ b/tests/baselines/reference/ambientClassMergesOverloadsWithInterface.symbols @@ -0,0 +1,22 @@ +=== tests/cases/compiler/ambientClassMergesOverloadsWithInterface.ts === +declare class C { +>C : Symbol(C, Decl(ambientClassMergesOverloadsWithInterface.ts, 0, 0), Decl(ambientClassMergesOverloadsWithInterface.ts, 3, 1)) + + baz(): any; +>baz : Symbol(baz, Decl(ambientClassMergesOverloadsWithInterface.ts, 0, 17)) + + foo(n: number): any; +>foo : Symbol(foo, Decl(ambientClassMergesOverloadsWithInterface.ts, 1, 15), Decl(ambientClassMergesOverloadsWithInterface.ts, 4, 13)) +>n : Symbol(n, Decl(ambientClassMergesOverloadsWithInterface.ts, 2, 8)) +} +interface C { +>C : Symbol(C, Decl(ambientClassMergesOverloadsWithInterface.ts, 0, 0), Decl(ambientClassMergesOverloadsWithInterface.ts, 3, 1)) + + foo(n: number): any; +>foo : Symbol(foo, Decl(ambientClassMergesOverloadsWithInterface.ts, 1, 15), Decl(ambientClassMergesOverloadsWithInterface.ts, 4, 13)) +>n : Symbol(n, Decl(ambientClassMergesOverloadsWithInterface.ts, 5, 8)) + + bar(): any; +>bar : Symbol(bar, Decl(ambientClassMergesOverloadsWithInterface.ts, 5, 24)) +} + diff --git a/tests/baselines/reference/ambientClassMergesOverloadsWithInterface.types b/tests/baselines/reference/ambientClassMergesOverloadsWithInterface.types new file mode 100644 index 00000000000..7a271b82865 --- /dev/null +++ b/tests/baselines/reference/ambientClassMergesOverloadsWithInterface.types @@ -0,0 +1,22 @@ +=== tests/cases/compiler/ambientClassMergesOverloadsWithInterface.ts === +declare class C { +>C : C + + baz(): any; +>baz : () => any + + foo(n: number): any; +>foo : { (n: number): any; (n: number): any; } +>n : number +} +interface C { +>C : C + + foo(n: number): any; +>foo : { (n: number): any; (n: number): any; } +>n : number + + bar(): any; +>bar : () => any +} + diff --git a/tests/cases/compiler/ambientClassMergesOverloadsWithInterface.ts b/tests/cases/compiler/ambientClassMergesOverloadsWithInterface.ts new file mode 100644 index 00000000000..6a6d3658b63 --- /dev/null +++ b/tests/cases/compiler/ambientClassMergesOverloadsWithInterface.ts @@ -0,0 +1,8 @@ +declare class C { + baz(): any; + foo(n: number): any; +} +interface C { + foo(n: number): any; + bar(): any; +} From 92c2d4846559403dee053a1fad04e55e21a0868c Mon Sep 17 00:00:00 2001 From: Nathan Shively-Sanders Date: Mon, 12 Oct 2015 14:37:10 -0700 Subject: [PATCH 3/3] Lint: remove trailing whitespace --- 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 cf8a2d676b4..188b09d4898 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -10992,7 +10992,7 @@ namespace ts { function getEffectiveDeclarationFlags(n: Node, flagsToCheck: NodeFlags): NodeFlags { let flags = getCombinedNodeFlags(n); - + // children of classes (even ambient classes) should not be marked as ambient or export // because those flags have no useful semantics there. if (n.parent.kind !== SyntaxKind.InterfaceDeclaration &&