From b3ed46f0dfe5b6ade7d8f3570e40f99883e7bf58 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Fri, 13 Nov 2015 14:26:48 -0800 Subject: [PATCH 1/2] port 5662 into release-1.7 --- src/compiler/checker.ts | 12 ++++--- ...edStaticAndInstanceClassMembers.errors.txt | 27 +++++++++++++++ .../mixedStaticAndInstanceClassMembers.js | 34 +++++++++++++++++++ ...nMergedDeclarationsAndOverloads.errors.txt | 23 +++++++++++++ .../nonMergedDeclarationsAndOverloads.js | 19 +++++++++++ .../mixedStaticAndInstanceClassMembers.ts | 15 ++++++++ .../nonMergedDeclarationsAndOverloads.ts | 8 +++++ 7 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt create mode 100644 tests/baselines/reference/mixedStaticAndInstanceClassMembers.js create mode 100644 tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt create mode 100644 tests/baselines/reference/nonMergedDeclarationsAndOverloads.js create mode 100644 tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts create mode 100644 tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f55d4eb9d27c1..f2176993a51e9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11172,11 +11172,15 @@ namespace ts { let errorNode: Node = (subsequentNode).name || subsequentNode; // TODO(jfreeman): These are methods, so handle computed name case if (node.name && (subsequentNode).name && (node.name).text === ((subsequentNode).name).text) { - // the only situation when this is possible (same kind\same name but different symbol) - mixed static and instance class members Debug.assert(node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature); - Debug.assert((node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static)); - let diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; - error(errorNode, diagnostic); + // we can get here in two cases + // 1. mixed static and instance class members + // 2. something with the same name was defined before the set of overloads that prevents them from merging + // here we'll report error only for the first case since for second we should already report error in binder + if ((node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static)) { + const diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; + error(errorNode, diagnostic); + } return; } else if (nodeIsPresent((subsequentNode).body)) { diff --git a/tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt new file mode 100644 index 0000000000000..d52b17a58a034 --- /dev/null +++ b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.errors.txt @@ -0,0 +1,27 @@ +tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts(4,5): error TS2387: Function overload must be static. +tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts(12,12): error TS2388: Function overload must not be static. +tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts(13,5): error TS2387: Function overload must be static. + + +==== tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts (3 errors) ==== + class A { + f() {} + static m1 (a: string): void; + m1 (a: number): void; + ~~ +!!! error TS2387: Function overload must be static. + m1 (a: any): void { + } + } + + class B { + f() {} + m1 (a: string): void; + static m1 (a: number): void; + ~~ +!!! error TS2388: Function overload must not be static. + m1 (a: any): void { + ~~ +!!! error TS2387: Function overload must be static. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/mixedStaticAndInstanceClassMembers.js b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.js new file mode 100644 index 0000000000000..427bbf65aa19b --- /dev/null +++ b/tests/baselines/reference/mixedStaticAndInstanceClassMembers.js @@ -0,0 +1,34 @@ +//// [mixedStaticAndInstanceClassMembers.ts] +class A { + f() {} + static m1 (a: string): void; + m1 (a: number): void; + m1 (a: any): void { + } +} + +class B { + f() {} + m1 (a: string): void; + static m1 (a: number): void; + m1 (a: any): void { + } +} + +//// [mixedStaticAndInstanceClassMembers.js] +var A = (function () { + function A() { + } + A.prototype.f = function () { }; + A.prototype.m1 = function (a) { + }; + return A; +})(); +var B = (function () { + function B() { + } + B.prototype.f = function () { }; + B.prototype.m1 = function (a) { + }; + return B; +})(); diff --git a/tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt new file mode 100644 index 0000000000000..252cd6880d47c --- /dev/null +++ b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.errors.txt @@ -0,0 +1,23 @@ +tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(2,5): error TS2300: Duplicate identifier 'm1'. +tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(4,5): error TS2300: Duplicate identifier 'm1'. +tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(5,5): error TS2300: Duplicate identifier 'm1'. +tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts(6,5): error TS2300: Duplicate identifier 'm1'. + + +==== tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts (4 errors) ==== + class A { + m1: string; + ~~ +!!! error TS2300: Duplicate identifier 'm1'. + f() {} + m1 (a: string): void; + ~~ +!!! error TS2300: Duplicate identifier 'm1'. + m1 (a: number): void; + ~~ +!!! error TS2300: Duplicate identifier 'm1'. + m1 (a: any): void { + ~~ +!!! error TS2300: Duplicate identifier 'm1'. + } + } \ No newline at end of file diff --git a/tests/baselines/reference/nonMergedDeclarationsAndOverloads.js b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.js new file mode 100644 index 0000000000000..3ca6a96351523 --- /dev/null +++ b/tests/baselines/reference/nonMergedDeclarationsAndOverloads.js @@ -0,0 +1,19 @@ +//// [nonMergedDeclarationsAndOverloads.ts] +class A { + m1: string; + f() {} + m1 (a: string): void; + m1 (a: number): void; + m1 (a: any): void { + } +} + +//// [nonMergedDeclarationsAndOverloads.js] +var A = (function () { + function A() { + } + A.prototype.f = function () { }; + A.prototype.m1 = function (a) { + }; + return A; +})(); diff --git a/tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts b/tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts new file mode 100644 index 0000000000000..6395813b65892 --- /dev/null +++ b/tests/cases/compiler/mixedStaticAndInstanceClassMembers.ts @@ -0,0 +1,15 @@ +class A { + f() {} + static m1 (a: string): void; + m1 (a: number): void; + m1 (a: any): void { + } +} + +class B { + f() {} + m1 (a: string): void; + static m1 (a: number): void; + m1 (a: any): void { + } +} \ No newline at end of file diff --git a/tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts b/tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts new file mode 100644 index 0000000000000..6ec4c6076f22a --- /dev/null +++ b/tests/cases/compiler/nonMergedDeclarationsAndOverloads.ts @@ -0,0 +1,8 @@ +class A { + m1: string; + f() {} + m1 (a: string): void; + m1 (a: number): void; + m1 (a: any): void { + } +} \ No newline at end of file From a7fb3e4e705c627c559d6e4cd7903d3b63297d43 Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 14 Nov 2015 12:08:47 -0800 Subject: [PATCH 2/2] do not crash when variable and function declarations collide --- src/compiler/checker.ts | 6 ++++-- .../reference/nonMergedOverloads.errors.txt | 20 +++++++++++++++++++ .../baselines/reference/nonMergedOverloads.js | 12 +++++++++++ tests/cases/compiler/nonMergedOverloads.ts | 5 +++++ 4 files changed, 41 insertions(+), 2 deletions(-) create mode 100644 tests/baselines/reference/nonMergedOverloads.errors.txt create mode 100644 tests/baselines/reference/nonMergedOverloads.js create mode 100644 tests/cases/compiler/nonMergedOverloads.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index f2176993a51e9..1273fd50a4a20 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -11172,12 +11172,14 @@ namespace ts { let errorNode: Node = (subsequentNode).name || subsequentNode; // TODO(jfreeman): These are methods, so handle computed name case if (node.name && (subsequentNode).name && (node.name).text === ((subsequentNode).name).text) { - Debug.assert(node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature); + const reportError = + (node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature) && + (node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static); // we can get here in two cases // 1. mixed static and instance class members // 2. something with the same name was defined before the set of overloads that prevents them from merging // here we'll report error only for the first case since for second we should already report error in binder - if ((node.flags & NodeFlags.Static) !== (subsequentNode.flags & NodeFlags.Static)) { + if (reportError) { const diagnostic = node.flags & NodeFlags.Static ? Diagnostics.Function_overload_must_be_static : Diagnostics.Function_overload_must_not_be_static; error(errorNode, diagnostic); } diff --git a/tests/baselines/reference/nonMergedOverloads.errors.txt b/tests/baselines/reference/nonMergedOverloads.errors.txt new file mode 100644 index 0000000000000..9a38ebdc3b311 --- /dev/null +++ b/tests/baselines/reference/nonMergedOverloads.errors.txt @@ -0,0 +1,20 @@ +tests/cases/compiler/nonMergedOverloads.ts(1,5): error TS2300: Duplicate identifier 'f'. +tests/cases/compiler/nonMergedOverloads.ts(3,17): error TS1148: Cannot compile modules unless the '--module' flag is provided. +tests/cases/compiler/nonMergedOverloads.ts(3,17): error TS2300: Duplicate identifier 'f'. +tests/cases/compiler/nonMergedOverloads.ts(4,17): error TS2300: Duplicate identifier 'f'. + + +==== tests/cases/compiler/nonMergedOverloads.ts (4 errors) ==== + var f = 10; + ~ +!!! error TS2300: Duplicate identifier 'f'. + + export function f(); + ~ +!!! error TS1148: Cannot compile modules unless the '--module' flag is provided. + ~ +!!! error TS2300: Duplicate identifier 'f'. + export function f() { + ~ +!!! error TS2300: Duplicate identifier 'f'. + } \ No newline at end of file diff --git a/tests/baselines/reference/nonMergedOverloads.js b/tests/baselines/reference/nonMergedOverloads.js new file mode 100644 index 0000000000000..2e7f7f67ee67d --- /dev/null +++ b/tests/baselines/reference/nonMergedOverloads.js @@ -0,0 +1,12 @@ +//// [nonMergedOverloads.ts] +var f = 10; + +export function f(); +export function f() { +} + +//// [nonMergedOverloads.js] +var f = 10; +function f() { +} +exports.f = f; diff --git a/tests/cases/compiler/nonMergedOverloads.ts b/tests/cases/compiler/nonMergedOverloads.ts new file mode 100644 index 0000000000000..582cd72e1f4c1 --- /dev/null +++ b/tests/cases/compiler/nonMergedOverloads.ts @@ -0,0 +1,5 @@ +var f = 10; + +export function f(); +export function f() { +} \ No newline at end of file