Skip to content

Commit f2719f9

Browse files
authored
Allow functions and ambient classes to merge (#32584)
1 parent b84e65d commit f2719f9

File tree

78 files changed

+488
-445
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

78 files changed

+488
-445
lines changed

Diff for: src/compiler/checker.ts

+17-2
Original file line numberDiff line numberDiff line change
@@ -26276,8 +26276,9 @@ namespace ts {
2627626276

2627726277
let duplicateFunctionDeclaration = false;
2627826278
let multipleConstructorImplementation = false;
26279+
let hasNonAmbientClass = false;
2627926280
for (const current of declarations) {
26280-
const node = <SignatureDeclaration>current;
26281+
const node = <SignatureDeclaration | ClassDeclaration | ClassExpression>current;
2628126282
const inAmbientContext = node.flags & NodeFlags.Ambient;
2628226283
const inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext;
2628326284
if (inAmbientContextOrInterface) {
@@ -26291,6 +26292,10 @@ namespace ts {
2629126292
previousDeclaration = undefined;
2629226293
}
2629326294

26295+
if ((node.kind === SyntaxKind.ClassDeclaration || node.kind === SyntaxKind.ClassExpression) && !inAmbientContext) {
26296+
hasNonAmbientClass = true;
26297+
}
26298+
2629426299
if (node.kind === SyntaxKind.FunctionDeclaration || node.kind === SyntaxKind.MethodDeclaration || node.kind === SyntaxKind.MethodSignature || node.kind === SyntaxKind.Constructor) {
2629526300
const currentNodeFlags = getEffectiveDeclarationFlags(node, flagsToCheck);
2629626301
someNodeFlags |= currentNodeFlags;
@@ -26339,6 +26344,16 @@ namespace ts {
2633926344
});
2634026345
}
2634126346

26347+
if (hasNonAmbientClass && !isConstructor && symbol.flags & SymbolFlags.Function) {
26348+
// A non-ambient class cannot be an implementation for a non-constructor function/class merge
26349+
// TODO: The below just replicates our older error from when classes and functions were
26350+
// entirely unable to merge - a more helpful message like "Class declaration cannot implement overload list"
26351+
// might be warranted. :shrug:
26352+
forEach(declarations, declaration => {
26353+
addDuplicateDeclarationError(getNameOfDeclaration(declaration) || declaration, Diagnostics.Duplicate_identifier_0, symbolName(symbol), filter(declarations, d => d !== declaration));
26354+
});
26355+
}
26356+
2634226357
// Abstract methods can't have an implementation -- in particular, they don't need one.
2634326358
if (lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body &&
2634426359
!hasModifier(lastSeenNonAmbientDeclaration, ModifierFlags.Abstract) && !lastSeenNonAmbientDeclaration.questionToken) {
@@ -31650,7 +31665,7 @@ namespace ts {
3165031665
if (!symbol || !(symbol.flags & SymbolFlags.Function)) {
3165131666
return false;
3165231667
}
31653-
return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && isPropertyAccessExpression(p.valueDeclaration));
31668+
return !!forEachEntry(getExportsOfSymbol(symbol), p => p.flags & SymbolFlags.Value && p.valueDeclaration && isPropertyAccessExpression(p.valueDeclaration));
3165431669
}
3165531670

3165631671
function getPropertiesOfContainerFunction(node: Declaration): Symbol[] {

Diff for: src/compiler/types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -3678,8 +3678,8 @@ namespace ts {
36783678
ParameterExcludes = Value,
36793679
PropertyExcludes = None,
36803680
EnumMemberExcludes = Value | Type,
3681-
FunctionExcludes = Value & ~(Function | ValueModule),
3682-
ClassExcludes = (Value | Type) & ~(ValueModule | Interface), // class-interface mergability done in checker.ts
3681+
FunctionExcludes = Value & ~(Function | ValueModule | Class),
3682+
ClassExcludes = (Value | Type) & ~(ValueModule | Interface | Function), // class-interface mergability done in checker.ts
36833683
InterfaceExcludes = Type & ~(Interface | Class),
36843684
RegularEnumExcludes = (Value | Type) & ~(RegularEnum | ValueModule), // regular enums merge only with regular enums and modules
36853685
ConstEnumExcludes = (Value | Type) & ~ConstEnum, // const enums merge only with const enums

Diff for: tests/baselines/reference/ambientClassOverloadForFunction.errors.txt

-12
This file was deleted.
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
=== tests/cases/compiler/ambientClassOverloadForFunction.ts ===
22
declare class foo{};
3-
>foo : Symbol(foo, Decl(ambientClassOverloadForFunction.ts, 0, 0))
3+
>foo : Symbol(foo, Decl(ambientClassOverloadForFunction.ts, 0, 20), Decl(ambientClassOverloadForFunction.ts, 0, 0))
44

55
function foo() { return null; }
6-
>foo : Symbol(foo, Decl(ambientClassOverloadForFunction.ts, 0, 20))
6+
>foo : Symbol(foo, Decl(ambientClassOverloadForFunction.ts, 0, 20), Decl(ambientClassOverloadForFunction.ts, 0, 0))
77

Diff for: tests/baselines/reference/ambientClassOverloadForFunction.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,6 @@ declare class foo{};
33
>foo : foo
44

55
function foo() { return null; }
6-
>foo : () => any
6+
>foo : typeof foo
77
>null : null
88

Diff for: tests/baselines/reference/api/tsserverlibrary.d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2137,8 +2137,8 @@ declare namespace ts {
21372137
ParameterExcludes = 111551,
21382138
PropertyExcludes = 0,
21392139
EnumMemberExcludes = 900095,
2140-
FunctionExcludes = 111023,
2141-
ClassExcludes = 899519,
2140+
FunctionExcludes = 110991,
2141+
ClassExcludes = 899503,
21422142
InterfaceExcludes = 788872,
21432143
RegularEnumExcludes = 899327,
21442144
ConstEnumExcludes = 899967,

Diff for: tests/baselines/reference/api/typescript.d.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2137,8 +2137,8 @@ declare namespace ts {
21372137
ParameterExcludes = 111551,
21382138
PropertyExcludes = 0,
21392139
EnumMemberExcludes = 900095,
2140-
FunctionExcludes = 111023,
2141-
ClassExcludes = 899519,
2140+
FunctionExcludes = 110991,
2141+
ClassExcludes = 899503,
21422142
InterfaceExcludes = 788872,
21432143
RegularEnumExcludes = 899327,
21442144
ConstEnumExcludes = 899967,

Diff for: tests/baselines/reference/augmentedTypesClass2a.errors.txt

+9-1
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,23 @@
11
tests/cases/compiler/augmentedTypesClass2a.ts(2,7): error TS2300: Duplicate identifier 'c2'.
2+
tests/cases/compiler/augmentedTypesClass2a.ts(2,7): error TS2300: Duplicate identifier 'c2'.
3+
tests/cases/compiler/augmentedTypesClass2a.ts(3,10): error TS2300: Duplicate identifier 'c2'.
24
tests/cases/compiler/augmentedTypesClass2a.ts(3,10): error TS2300: Duplicate identifier 'c2'.
35
tests/cases/compiler/augmentedTypesClass2a.ts(4,5): error TS2300: Duplicate identifier 'c2'.
46

57

6-
==== tests/cases/compiler/augmentedTypesClass2a.ts (3 errors) ====
8+
==== tests/cases/compiler/augmentedTypesClass2a.ts (5 errors) ====
79
//// class then function
810
class c2 { public foo() { } } // error
911
~~
12+
!!! error TS2300: Duplicate identifier 'c2'.
13+
!!! related TS6203 tests/cases/compiler/augmentedTypesClass2a.ts:3:10: 'c2' was also declared here.
14+
~~
1015
!!! error TS2300: Duplicate identifier 'c2'.
1116
function c2() { } // error
1217
~~
18+
!!! error TS2300: Duplicate identifier 'c2'.
19+
!!! related TS6203 tests/cases/compiler/augmentedTypesClass2a.ts:2:7: 'c2' was also declared here.
20+
~~
1321
!!! error TS2300: Duplicate identifier 'c2'.
1422
var c2 = () => { }
1523
~~

Diff for: tests/baselines/reference/augmentedTypesClass2a.symbols

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
11
=== tests/cases/compiler/augmentedTypesClass2a.ts ===
22
//// class then function
33
class c2 { public foo() { } } // error
4-
>c2 : Symbol(c2, Decl(augmentedTypesClass2a.ts, 0, 0))
4+
>c2 : Symbol(c2, Decl(augmentedTypesClass2a.ts, 1, 29), Decl(augmentedTypesClass2a.ts, 0, 0))
55
>foo : Symbol(c2.foo, Decl(augmentedTypesClass2a.ts, 1, 10))
66

77
function c2() { } // error
8-
>c2 : Symbol(c2, Decl(augmentedTypesClass2a.ts, 1, 29))
8+
>c2 : Symbol(c2, Decl(augmentedTypesClass2a.ts, 1, 29), Decl(augmentedTypesClass2a.ts, 0, 0))
99

1010
var c2 = () => { }
1111
>c2 : Symbol(c2, Decl(augmentedTypesClass2a.ts, 3, 3))

Diff for: tests/baselines/reference/augmentedTypesClass2a.types

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ class c2 { public foo() { } } // error
55
>foo : () => void
66

77
function c2() { } // error
8-
>c2 : () => void
8+
>c2 : typeof c2
99

1010
var c2 = () => { }
1111
>c2 : () => void

Diff for: tests/baselines/reference/augmentedTypesFunction.errors.txt

+4
Original file line numberDiff line numberDiff line change
@@ -40,16 +40,20 @@ tests/cases/compiler/augmentedTypesFunction.ts(21,6): error TS2567: Enum declara
4040
function y3() { } // error
4141
~~
4242
!!! error TS2300: Duplicate identifier 'y3'.
43+
!!! related TS6203 tests/cases/compiler/augmentedTypesFunction.ts:14:7: 'y3' was also declared here.
4344
class y3 { } // error
4445
~~
4546
!!! error TS2300: Duplicate identifier 'y3'.
47+
!!! related TS6203 tests/cases/compiler/augmentedTypesFunction.ts:13:10: 'y3' was also declared here.
4648

4749
function y3a() { } // error
4850
~~~
4951
!!! error TS2300: Duplicate identifier 'y3a'.
52+
!!! related TS6203 tests/cases/compiler/augmentedTypesFunction.ts:17:7: 'y3a' was also declared here.
5053
class y3a { public foo() { } } // error
5154
~~~
5255
!!! error TS2300: Duplicate identifier 'y3a'.
56+
!!! related TS6203 tests/cases/compiler/augmentedTypesFunction.ts:16:10: 'y3a' was also declared here.
5357

5458
// function then enum
5559
function y4() { } // error

Diff for: tests/baselines/reference/augmentedTypesFunction.symbols

+4-4
Original file line numberDiff line numberDiff line change
@@ -21,16 +21,16 @@ var y2a = () => { } // error
2121

2222
// function then class
2323
function y3() { } // error
24-
>y3 : Symbol(y3, Decl(augmentedTypesFunction.ts, 9, 19))
24+
>y3 : Symbol(y3, Decl(augmentedTypesFunction.ts, 9, 19), Decl(augmentedTypesFunction.ts, 12, 17))
2525

2626
class y3 { } // error
27-
>y3 : Symbol(y3, Decl(augmentedTypesFunction.ts, 12, 17))
27+
>y3 : Symbol(y3, Decl(augmentedTypesFunction.ts, 9, 19), Decl(augmentedTypesFunction.ts, 12, 17))
2828

2929
function y3a() { } // error
30-
>y3a : Symbol(y3a, Decl(augmentedTypesFunction.ts, 13, 12))
30+
>y3a : Symbol(y3a, Decl(augmentedTypesFunction.ts, 13, 12), Decl(augmentedTypesFunction.ts, 15, 18))
3131

3232
class y3a { public foo() { } } // error
33-
>y3a : Symbol(y3a, Decl(augmentedTypesFunction.ts, 15, 18))
33+
>y3a : Symbol(y3a, Decl(augmentedTypesFunction.ts, 13, 12), Decl(augmentedTypesFunction.ts, 15, 18))
3434
>foo : Symbol(y3a.foo, Decl(augmentedTypesFunction.ts, 16, 11))
3535

3636
// function then enum

Diff for: tests/baselines/reference/augmentedTypesFunction.types

+2-2
Original file line numberDiff line numberDiff line change
@@ -23,13 +23,13 @@ var y2a = () => { } // error
2323

2424
// function then class
2525
function y3() { } // error
26-
>y3 : () => void
26+
>y3 : typeof y3
2727

2828
class y3 { } // error
2929
>y3 : y3
3030

3131
function y3a() { } // error
32-
>y3a : () => void
32+
>y3a : typeof y3a
3333

3434
class y3a { public foo() { } } // error
3535
>y3a : y3a

Diff for: tests/baselines/reference/callOnInstance.errors.txt

+6-10
Original file line numberDiff line numberDiff line change
@@ -1,24 +1,20 @@
1-
tests/cases/compiler/callOnInstance.ts(1,18): error TS2300: Duplicate identifier 'D'.
2-
tests/cases/compiler/callOnInstance.ts(3,15): error TS2300: Duplicate identifier 'D'.
3-
tests/cases/compiler/callOnInstance.ts(7,25): error TS2554: Expected 0 arguments, but got 1.
1+
tests/cases/compiler/callOnInstance.ts(7,18): error TS2349: This expression is not callable.
2+
Type 'D' has no call signatures.
43
tests/cases/compiler/callOnInstance.ts(10,1): error TS2349: This expression is not callable.
54
Type 'C' has no call signatures.
65

76

8-
==== tests/cases/compiler/callOnInstance.ts (4 errors) ====
7+
==== tests/cases/compiler/callOnInstance.ts (2 errors) ====
98
declare function D(): string; // error
10-
~
11-
!!! error TS2300: Duplicate identifier 'D'.
129

1310
declare class D { constructor (value: number); } // error
14-
~
15-
!!! error TS2300: Duplicate identifier 'D'.
1611

1712
var s1: string = D(); // OK
1813

1914
var s2: string = (new D(1))();
20-
~
21-
!!! error TS2554: Expected 0 arguments, but got 1.
15+
~~~~~~~~~~
16+
!!! error TS2349: This expression is not callable.
17+
!!! error TS2349: Type 'D' has no call signatures.
2218

2319
declare class C { constructor(value: number); }
2420
(new C(1))(); // Error for calling an instance

Diff for: tests/baselines/reference/callOnInstance.symbols

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,18 +1,18 @@
11
=== tests/cases/compiler/callOnInstance.ts ===
22
declare function D(): string; // error
3-
>D : Symbol(D, Decl(callOnInstance.ts, 0, 0))
3+
>D : Symbol(D, Decl(callOnInstance.ts, 0, 0), Decl(callOnInstance.ts, 0, 29))
44

55
declare class D { constructor (value: number); } // error
6-
>D : Symbol(D, Decl(callOnInstance.ts, 0, 29))
6+
>D : Symbol(D, Decl(callOnInstance.ts, 0, 0), Decl(callOnInstance.ts, 0, 29))
77
>value : Symbol(value, Decl(callOnInstance.ts, 2, 31))
88

99
var s1: string = D(); // OK
1010
>s1 : Symbol(s1, Decl(callOnInstance.ts, 4, 3))
11-
>D : Symbol(D, Decl(callOnInstance.ts, 0, 0))
11+
>D : Symbol(D, Decl(callOnInstance.ts, 0, 0), Decl(callOnInstance.ts, 0, 29))
1212

1313
var s2: string = (new D(1))();
1414
>s2 : Symbol(s2, Decl(callOnInstance.ts, 6, 3))
15-
>D : Symbol(D, Decl(callOnInstance.ts, 0, 0))
15+
>D : Symbol(D, Decl(callOnInstance.ts, 0, 0), Decl(callOnInstance.ts, 0, 29))
1616

1717
declare class C { constructor(value: number); }
1818
>C : Symbol(C, Decl(callOnInstance.ts, 6, 30))

Diff for: tests/baselines/reference/callOnInstance.types

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
=== tests/cases/compiler/callOnInstance.ts ===
22
declare function D(): string; // error
3-
>D : () => string
3+
>D : typeof D
44

55
declare class D { constructor (value: number); } // error
66
>D : D
@@ -9,14 +9,14 @@ declare class D { constructor (value: number); } // error
99
var s1: string = D(); // OK
1010
>s1 : string
1111
>D() : string
12-
>D : () => string
12+
>D : typeof D
1313

1414
var s2: string = (new D(1))();
1515
>s2 : string
1616
>(new D(1))() : any
17-
>(new D(1)) : any
18-
>new D(1) : any
19-
>D : () => string
17+
>(new D(1)) : D
18+
>new D(1) : D
19+
>D : typeof D
2020
>1 : 1
2121

2222
declare class C { constructor(value: number); }

Diff for: tests/baselines/reference/callOverloads1.errors.txt

+3-4
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,13 @@
11
tests/cases/compiler/callOverloads1.ts(1,7): error TS2300: Duplicate identifier 'Foo'.
22
tests/cases/compiler/callOverloads1.ts(9,10): error TS2300: Duplicate identifier 'Foo'.
33
tests/cases/compiler/callOverloads1.ts(9,10): error TS2391: Function implementation is missing or not immediately following the declaration.
4-
tests/cases/compiler/callOverloads1.ts(13,18): error TS2554: Expected 0 arguments, but got 1.
54

65

7-
==== tests/cases/compiler/callOverloads1.ts (4 errors) ====
6+
==== tests/cases/compiler/callOverloads1.ts (3 errors) ====
87
class Foo { // error
98
~~~
109
!!! error TS2300: Duplicate identifier 'Foo'.
10+
!!! related TS6203 tests/cases/compiler/callOverloads1.ts:9:10: 'Foo' was also declared here.
1111
bar1() { /*WScript.Echo("bar1");*/ }
1212

1313
constructor(x: any) {
@@ -18,14 +18,13 @@ tests/cases/compiler/callOverloads1.ts(13,18): error TS2554: Expected 0 argument
1818
function Foo(); // error
1919
~~~
2020
!!! error TS2300: Duplicate identifier 'Foo'.
21+
!!! related TS6203 tests/cases/compiler/callOverloads1.ts:1:7: 'Foo' was also declared here.
2122
~~~
2223
!!! error TS2391: Function implementation is missing or not immediately following the declaration.
2324
function F1(s:string);
2425
function F1(a:any) { return a;}
2526

2627
var f1 = new Foo("hey");
27-
~~~~~
28-
!!! error TS2554: Expected 0 arguments, but got 1.
2928

3029

3130
f1.bar1();

Diff for: tests/baselines/reference/callOverloads1.symbols

+6-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
=== tests/cases/compiler/callOverloads1.ts ===
22
class Foo { // error
3-
>Foo : Symbol(Foo, Decl(callOverloads1.ts, 0, 0))
3+
>Foo : Symbol(Foo, Decl(callOverloads1.ts, 6, 1), Decl(callOverloads1.ts, 0, 0))
44

55
bar1() { /*WScript.Echo("bar1");*/ }
66
>bar1 : Symbol(Foo.bar1, Decl(callOverloads1.ts, 0, 11))
@@ -13,7 +13,7 @@ class Foo { // error
1313
}
1414

1515
function Foo(); // error
16-
>Foo : Symbol(Foo, Decl(callOverloads1.ts, 6, 1))
16+
>Foo : Symbol(Foo, Decl(callOverloads1.ts, 6, 1), Decl(callOverloads1.ts, 0, 0))
1717

1818
function F1(s:string);
1919
>F1 : Symbol(F1, Decl(callOverloads1.ts, 8, 15), Decl(callOverloads1.ts, 9, 22))
@@ -26,12 +26,14 @@ function F1(a:any) { return a;}
2626

2727
var f1 = new Foo("hey");
2828
>f1 : Symbol(f1, Decl(callOverloads1.ts, 12, 3))
29-
>Foo : Symbol(Foo, Decl(callOverloads1.ts, 6, 1))
29+
>Foo : Symbol(Foo, Decl(callOverloads1.ts, 6, 1), Decl(callOverloads1.ts, 0, 0))
3030

3131

3232
f1.bar1();
33+
>f1.bar1 : Symbol(Foo.bar1, Decl(callOverloads1.ts, 0, 11))
3334
>f1 : Symbol(f1, Decl(callOverloads1.ts, 12, 3))
35+
>bar1 : Symbol(Foo.bar1, Decl(callOverloads1.ts, 0, 11))
3436

3537
Foo();
36-
>Foo : Symbol(Foo, Decl(callOverloads1.ts, 6, 1))
38+
>Foo : Symbol(Foo, Decl(callOverloads1.ts, 6, 1), Decl(callOverloads1.ts, 0, 0))
3739

0 commit comments

Comments
 (0)