Skip to content

Commit 33f72c7

Browse files
Merge pull request #8636 from RyanCavanaugh/classOrdering
Issue an error when a derived class precedes its base class
2 parents c696030 + 5e86a10 commit 33f72c7

Some content is hidden

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

41 files changed

+1483
-27766
lines changed

src/compiler/checker.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16227,6 +16227,12 @@ namespace ts {
1622716227
checkTypeAssignableTo(staticType, getTypeWithoutSignatures(staticBaseType), node.name || node,
1622816228
Diagnostics.Class_static_side_0_incorrectly_extends_base_class_static_side_1);
1622916229

16230+
if (baseType.symbol.valueDeclaration && !(baseType.symbol.valueDeclaration.flags & NodeFlags.Ambient)) {
16231+
if (!isBlockScopedNameDeclaredBeforeUse(baseType.symbol.valueDeclaration, node)) {
16232+
error(baseTypeNode, Diagnostics.A_class_must_be_declared_after_its_base_class);
16233+
}
16234+
}
16235+
1623016236
if (!(staticBaseType.symbol && staticBaseType.symbol.flags & SymbolFlags.Class)) {
1623116237
// When the static base type is a "class-like" constructor function (but not actually a class), we verify
1623216238
// that all instantiated base constructor signatures return the same type. We can simply compare the type

src/compiler/diagnosticMessages.json

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1947,6 +1947,10 @@
19471947
"category": "Error",
19481948
"code": 2689
19491949
},
1950+
"A class must be declared after its base class.": {
1951+
"category": "Error",
1952+
"code": 2690
1953+
},
19501954
"Import declaration '{0}' is using private name '{1}'.": {
19511955
"category": "Error",
19521956
"code": 4000
Lines changed: 33 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -1,63 +1,50 @@
11
//// [baseTypeWrappingInstantiationChain.ts]
2-
class C<T1> extends CBase<T1> {
3-
public works() {
4-
new CBaseBase<Wrapper<T1>>(this);
5-
}
6-
public alsoWorks() {
7-
new CBase<T1>(this); // Should not error, parameter is of type Parameter<Wrapper<T1>>
8-
}
9-
10-
public method(t: Wrapper<T1>) { }
2+
class CBaseBase<T3> {
3+
constructor(x: Parameter<T3>) { }
114
}
125

136
class CBase<T2> extends CBaseBase<Wrapper<T2>> {
147

158
}
169

17-
class CBaseBase<T3> {
18-
constructor(x: Parameter<T3>) { }
19-
}
20-
2110
class Parameter<T4> {
2211
method(t: T4) { }
2312
}
2413

2514
class Wrapper<T5> {
2615
property: T5;
27-
}
16+
}
17+
18+
class C<T1> extends CBase<T1> {
19+
public works() {
20+
new CBaseBase<Wrapper<T1>>(this);
21+
}
22+
public alsoWorks() {
23+
new CBase<T1>(this); // Should not error, parameter is of type Parameter<Wrapper<T1>>
24+
}
25+
26+
public method(t: Wrapper<T1>) { }
27+
}
28+
2829

2930
//// [baseTypeWrappingInstantiationChain.js]
3031
var __extends = (this && this.__extends) || function (d, b) {
3132
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
3233
function __() { this.constructor = d; }
3334
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
3435
};
35-
var C = (function (_super) {
36-
__extends(C, _super);
37-
function C() {
38-
_super.apply(this, arguments);
36+
var CBaseBase = (function () {
37+
function CBaseBase(x) {
3938
}
40-
C.prototype.works = function () {
41-
new CBaseBase(this);
42-
};
43-
C.prototype.alsoWorks = function () {
44-
new CBase(this); // Should not error, parameter is of type Parameter<Wrapper<T1>>
45-
};
46-
C.prototype.method = function (t) { };
47-
return C;
48-
}(CBase));
39+
return CBaseBase;
40+
}());
4941
var CBase = (function (_super) {
5042
__extends(CBase, _super);
5143
function CBase() {
5244
_super.apply(this, arguments);
5345
}
5446
return CBase;
5547
}(CBaseBase));
56-
var CBaseBase = (function () {
57-
function CBaseBase(x) {
58-
}
59-
return CBaseBase;
60-
}());
6148
var Parameter = (function () {
6249
function Parameter() {
6350
}
@@ -69,3 +56,17 @@ var Wrapper = (function () {
6956
}
7057
return Wrapper;
7158
}());
59+
var C = (function (_super) {
60+
__extends(C, _super);
61+
function C() {
62+
_super.apply(this, arguments);
63+
}
64+
C.prototype.works = function () {
65+
new CBaseBase(this);
66+
};
67+
C.prototype.alsoWorks = function () {
68+
new CBase(this); // Should not error, parameter is of type Parameter<Wrapper<T1>>
69+
};
70+
C.prototype.method = function (t) { };
71+
return C;
72+
}(CBase));
Lines changed: 53 additions & 52 deletions
Original file line numberDiff line numberDiff line change
@@ -1,69 +1,70 @@
11
=== tests/cases/compiler/baseTypeWrappingInstantiationChain.ts ===
2-
class C<T1> extends CBase<T1> {
3-
>C : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
4-
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8))
5-
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 9, 1))
6-
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8))
7-
8-
public works() {
9-
>works : Symbol(C.works, Decl(baseTypeWrappingInstantiationChain.ts, 0, 31))
10-
11-
new CBaseBase<Wrapper<T1>>(this);
12-
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 13, 1))
13-
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 21, 1))
14-
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8))
15-
>this : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
16-
}
17-
public alsoWorks() {
18-
>alsoWorks : Symbol(C.alsoWorks, Decl(baseTypeWrappingInstantiationChain.ts, 3, 5))
19-
20-
new CBase<T1>(this); // Should not error, parameter is of type Parameter<Wrapper<T1>>
21-
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 9, 1))
22-
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8))
23-
>this : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
24-
}
2+
class CBaseBase<T3> {
3+
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
4+
>T3 : Symbol(T3, Decl(baseTypeWrappingInstantiationChain.ts, 0, 16))
255

26-
public method(t: Wrapper<T1>) { }
27-
>method : Symbol(C.method, Decl(baseTypeWrappingInstantiationChain.ts, 6, 5))
28-
>t : Symbol(t, Decl(baseTypeWrappingInstantiationChain.ts, 8, 18))
29-
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 21, 1))
30-
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 0, 8))
6+
constructor(x: Parameter<T3>) { }
7+
>x : Symbol(x, Decl(baseTypeWrappingInstantiationChain.ts, 1, 16))
8+
>Parameter : Symbol(Parameter, Decl(baseTypeWrappingInstantiationChain.ts, 6, 1))
9+
>T3 : Symbol(T3, Decl(baseTypeWrappingInstantiationChain.ts, 0, 16))
3110
}
3211

3312
class CBase<T2> extends CBaseBase<Wrapper<T2>> {
34-
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 9, 1))
35-
>T2 : Symbol(T2, Decl(baseTypeWrappingInstantiationChain.ts, 11, 12))
36-
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 13, 1))
37-
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 21, 1))
38-
>T2 : Symbol(T2, Decl(baseTypeWrappingInstantiationChain.ts, 11, 12))
13+
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 2, 1))
14+
>T2 : Symbol(T2, Decl(baseTypeWrappingInstantiationChain.ts, 4, 12))
15+
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
16+
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 10, 1))
17+
>T2 : Symbol(T2, Decl(baseTypeWrappingInstantiationChain.ts, 4, 12))
3918

4019
}
4120

42-
class CBaseBase<T3> {
43-
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 13, 1))
44-
>T3 : Symbol(T3, Decl(baseTypeWrappingInstantiationChain.ts, 15, 16))
45-
46-
constructor(x: Parameter<T3>) { }
47-
>x : Symbol(x, Decl(baseTypeWrappingInstantiationChain.ts, 16, 16))
48-
>Parameter : Symbol(Parameter, Decl(baseTypeWrappingInstantiationChain.ts, 17, 1))
49-
>T3 : Symbol(T3, Decl(baseTypeWrappingInstantiationChain.ts, 15, 16))
50-
}
51-
5221
class Parameter<T4> {
53-
>Parameter : Symbol(Parameter, Decl(baseTypeWrappingInstantiationChain.ts, 17, 1))
54-
>T4 : Symbol(T4, Decl(baseTypeWrappingInstantiationChain.ts, 19, 16))
22+
>Parameter : Symbol(Parameter, Decl(baseTypeWrappingInstantiationChain.ts, 6, 1))
23+
>T4 : Symbol(T4, Decl(baseTypeWrappingInstantiationChain.ts, 8, 16))
5524

5625
method(t: T4) { }
57-
>method : Symbol(Parameter.method, Decl(baseTypeWrappingInstantiationChain.ts, 19, 21))
58-
>t : Symbol(t, Decl(baseTypeWrappingInstantiationChain.ts, 20, 11))
59-
>T4 : Symbol(T4, Decl(baseTypeWrappingInstantiationChain.ts, 19, 16))
26+
>method : Symbol(Parameter.method, Decl(baseTypeWrappingInstantiationChain.ts, 8, 21))
27+
>t : Symbol(t, Decl(baseTypeWrappingInstantiationChain.ts, 9, 11))
28+
>T4 : Symbol(T4, Decl(baseTypeWrappingInstantiationChain.ts, 8, 16))
6029
}
6130

6231
class Wrapper<T5> {
63-
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 21, 1))
64-
>T5 : Symbol(T5, Decl(baseTypeWrappingInstantiationChain.ts, 23, 14))
32+
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 10, 1))
33+
>T5 : Symbol(T5, Decl(baseTypeWrappingInstantiationChain.ts, 12, 14))
6534

6635
property: T5;
67-
>property : Symbol(Wrapper.property, Decl(baseTypeWrappingInstantiationChain.ts, 23, 19))
68-
>T5 : Symbol(T5, Decl(baseTypeWrappingInstantiationChain.ts, 23, 14))
36+
>property : Symbol(Wrapper.property, Decl(baseTypeWrappingInstantiationChain.ts, 12, 19))
37+
>T5 : Symbol(T5, Decl(baseTypeWrappingInstantiationChain.ts, 12, 14))
38+
}
39+
40+
class C<T1> extends CBase<T1> {
41+
>C : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 14, 1))
42+
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
43+
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 2, 1))
44+
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
45+
46+
public works() {
47+
>works : Symbol(C.works, Decl(baseTypeWrappingInstantiationChain.ts, 16, 31))
48+
49+
new CBaseBase<Wrapper<T1>>(this);
50+
>CBaseBase : Symbol(CBaseBase, Decl(baseTypeWrappingInstantiationChain.ts, 0, 0))
51+
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 10, 1))
52+
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
53+
>this : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 14, 1))
54+
}
55+
public alsoWorks() {
56+
>alsoWorks : Symbol(C.alsoWorks, Decl(baseTypeWrappingInstantiationChain.ts, 19, 5))
57+
58+
new CBase<T1>(this); // Should not error, parameter is of type Parameter<Wrapper<T1>>
59+
>CBase : Symbol(CBase, Decl(baseTypeWrappingInstantiationChain.ts, 2, 1))
60+
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
61+
>this : Symbol(C, Decl(baseTypeWrappingInstantiationChain.ts, 14, 1))
62+
}
63+
64+
public method(t: Wrapper<T1>) { }
65+
>method : Symbol(C.method, Decl(baseTypeWrappingInstantiationChain.ts, 22, 5))
66+
>t : Symbol(t, Decl(baseTypeWrappingInstantiationChain.ts, 24, 18))
67+
>Wrapper : Symbol(Wrapper, Decl(baseTypeWrappingInstantiationChain.ts, 10, 1))
68+
>T1 : Symbol(T1, Decl(baseTypeWrappingInstantiationChain.ts, 16, 8))
6969
}
70+

tests/baselines/reference/baseTypeWrappingInstantiationChain.types

Lines changed: 38 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,42 @@
11
=== tests/cases/compiler/baseTypeWrappingInstantiationChain.ts ===
2+
class CBaseBase<T3> {
3+
>CBaseBase : CBaseBase<T3>
4+
>T3 : T3
5+
6+
constructor(x: Parameter<T3>) { }
7+
>x : Parameter<T3>
8+
>Parameter : Parameter<T4>
9+
>T3 : T3
10+
}
11+
12+
class CBase<T2> extends CBaseBase<Wrapper<T2>> {
13+
>CBase : CBase<T2>
14+
>T2 : T2
15+
>CBaseBase : CBaseBase<Wrapper<T2>>
16+
>Wrapper : Wrapper<T5>
17+
>T2 : T2
18+
19+
}
20+
21+
class Parameter<T4> {
22+
>Parameter : Parameter<T4>
23+
>T4 : T4
24+
25+
method(t: T4) { }
26+
>method : (t: T4) => void
27+
>t : T4
28+
>T4 : T4
29+
}
30+
31+
class Wrapper<T5> {
32+
>Wrapper : Wrapper<T5>
33+
>T5 : T5
34+
35+
property: T5;
36+
>property : T5
37+
>T5 : T5
38+
}
39+
240
class C<T1> extends CBase<T1> {
341
>C : C<T1>
442
>T1 : T1
@@ -32,40 +70,3 @@ class C<T1> extends CBase<T1> {
3270
>T1 : T1
3371
}
3472

35-
class CBase<T2> extends CBaseBase<Wrapper<T2>> {
36-
>CBase : CBase<T2>
37-
>T2 : T2
38-
>CBaseBase : CBaseBase<Wrapper<T2>>
39-
>Wrapper : Wrapper<T5>
40-
>T2 : T2
41-
42-
}
43-
44-
class CBaseBase<T3> {
45-
>CBaseBase : CBaseBase<T3>
46-
>T3 : T3
47-
48-
constructor(x: Parameter<T3>) { }
49-
>x : Parameter<T3>
50-
>Parameter : Parameter<T4>
51-
>T3 : T3
52-
}
53-
54-
class Parameter<T4> {
55-
>Parameter : Parameter<T4>
56-
>T4 : T4
57-
58-
method(t: T4) { }
59-
>method : (t: T4) => void
60-
>t : T4
61-
>T4 : T4
62-
}
63-
64-
class Wrapper<T5> {
65-
>Wrapper : Wrapper<T5>
66-
>T5 : T5
67-
68-
property: T5;
69-
>property : T5
70-
>T5 : T5
71-
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
tests/cases/conformance/internalModules/importDeclarations/circularImportAlias.ts(5,28): error TS2690: A class must be declared after its base class.
2+
3+
4+
==== tests/cases/conformance/internalModules/importDeclarations/circularImportAlias.ts (1 errors) ====
5+
// expected no error
6+
7+
module B {
8+
export import a = A;
9+
export class D extends a.C {
10+
~~~
11+
!!! error TS2690: A class must be declared after its base class.
12+
id: number;
13+
}
14+
}
15+
16+
module A {
17+
export class C { name: string }
18+
export import b = B;
19+
}
20+
21+
var c: { name: string };
22+
var c = new B.a.C();
23+
24+
25+

0 commit comments

Comments
 (0)