Skip to content

Commit e67f7bc

Browse files
committed
Merge pull request microsoft#6763 from Microsoft/classInterfaceCrossFileMerge
properly handle merged declarations across files
1 parent b4bb5f3 commit e67f7bc

9 files changed

Lines changed: 241 additions & 4 deletions

src/compiler/checker.ts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2495,7 +2495,7 @@ namespace ts {
24952495
// Every class automatically contains a static property member named 'prototype',
24962496
// the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter.
24972497
// It is an error to explicitly declare a static property member with the name 'prototype'.
2498-
const classType = <InterfaceType>getDeclaredTypeOfSymbol(getMergedSymbol(prototype.parent));
2498+
const classType = <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(prototype));
24992499
return classType.typeParameters ? createTypeReference(<GenericType>classType, map(classType.typeParameters, _ => anyType)) : classType;
25002500
}
25012501

@@ -5782,8 +5782,8 @@ namespace ts {
57825782
}
57835783
else if (targetPropFlags & NodeFlags.Protected) {
57845784
const sourceDeclaredInClass = sourceProp.parent && sourceProp.parent.flags & SymbolFlags.Class;
5785-
const sourceClass = sourceDeclaredInClass ? <InterfaceType>getDeclaredTypeOfSymbol(sourceProp.parent) : undefined;
5786-
const targetClass = <InterfaceType>getDeclaredTypeOfSymbol(targetProp.parent);
5785+
const sourceClass = sourceDeclaredInClass ? <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(sourceProp)) : undefined;
5786+
const targetClass = <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(targetProp));
57875787
if (!sourceClass || !hasBaseType(sourceClass, targetClass)) {
57885788
if (reportErrors) {
57895789
reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2,
@@ -8770,7 +8770,7 @@ namespace ts {
87708770
*/
87718771
function checkClassPropertyAccess(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, type: Type, prop: Symbol): boolean {
87728772
const flags = getDeclarationFlagsFromSymbol(prop);
8773-
const declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(getMergedSymbol(prop.parent));
8773+
const declaringClass = <InterfaceType>getDeclaredTypeOfSymbol(getParentOfSymbol(prop));
87748774

87758775
if (left.kind === SyntaxKind.SuperKeyword) {
87768776
const errorNode = node.kind === SyntaxKind.PropertyAccessExpression ?
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
//// [tests/cases/compiler/mergedDeclarations5.ts] ////
2+
3+
//// [a.ts]
4+
class A {
5+
protected foo() {}
6+
}
7+
//// [b.ts]
8+
interface A { }
9+
10+
class B extends A {
11+
protected foo() {}
12+
}
13+
14+
//// [a.js]
15+
var A = (function () {
16+
function A() {
17+
}
18+
A.prototype.foo = function () { };
19+
return A;
20+
}());
21+
//// [b.js]
22+
var __extends = (this && this.__extends) || function (d, b) {
23+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
24+
function __() { this.constructor = d; }
25+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
26+
};
27+
var B = (function (_super) {
28+
__extends(B, _super);
29+
function B() {
30+
_super.apply(this, arguments);
31+
}
32+
B.prototype.foo = function () { };
33+
return B;
34+
}(A));
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class A {
3+
>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 0, 0))
4+
5+
protected foo() {}
6+
>foo : Symbol(foo, Decl(a.ts, 0, 9))
7+
}
8+
=== tests/cases/compiler/b.ts ===
9+
interface A { }
10+
>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 0, 0))
11+
12+
class B extends A {
13+
>B : Symbol(B, Decl(b.ts, 0, 15))
14+
>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 0, 0))
15+
16+
protected foo() {}
17+
>foo : Symbol(foo, Decl(b.ts, 2, 19))
18+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
=== tests/cases/compiler/a.ts ===
2+
class A {
3+
>A : A
4+
5+
protected foo() {}
6+
>foo : () => void
7+
}
8+
=== tests/cases/compiler/b.ts ===
9+
interface A { }
10+
>A : A
11+
12+
class B extends A {
13+
>B : B
14+
>A : A
15+
16+
protected foo() {}
17+
>foo : () => void
18+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
//// [tests/cases/compiler/mergedDeclarations6.ts] ////
2+
3+
//// [a.ts]
4+
5+
export class A {
6+
protected protected: any;
7+
8+
protected setProtected(val: any) {
9+
this.protected = val;
10+
}
11+
}
12+
13+
//// [b.ts]
14+
import {A} from './a';
15+
16+
declare module "./a" {
17+
interface A { }
18+
}
19+
20+
export class B extends A {
21+
protected setProtected() {
22+
23+
}
24+
}
25+
26+
//// [a.js]
27+
define(["require", "exports"], function (require, exports) {
28+
"use strict";
29+
var A = (function () {
30+
function A() {
31+
}
32+
A.prototype.setProtected = function (val) {
33+
this.protected = val;
34+
};
35+
return A;
36+
}());
37+
exports.A = A;
38+
});
39+
//// [b.js]
40+
var __extends = (this && this.__extends) || function (d, b) {
41+
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
42+
function __() { this.constructor = d; }
43+
d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __());
44+
};
45+
define(["require", "exports", './a'], function (require, exports, a_1) {
46+
"use strict";
47+
var B = (function (_super) {
48+
__extends(B, _super);
49+
function B() {
50+
_super.apply(this, arguments);
51+
}
52+
B.prototype.setProtected = function () {
53+
};
54+
return B;
55+
}(a_1.A));
56+
exports.B = B;
57+
});
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
=== tests/cases/compiler/a.ts ===
2+
3+
export class A {
4+
>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 2, 22))
5+
6+
protected protected: any;
7+
>protected : Symbol(protected, Decl(a.ts, 1, 16))
8+
9+
protected setProtected(val: any) {
10+
>setProtected : Symbol(setProtected, Decl(a.ts, 2, 29))
11+
>val : Symbol(val, Decl(a.ts, 4, 27))
12+
13+
this.protected = val;
14+
>this.protected : Symbol(protected, Decl(a.ts, 1, 16))
15+
>this : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 2, 22))
16+
>protected : Symbol(protected, Decl(a.ts, 1, 16))
17+
>val : Symbol(val, Decl(a.ts, 4, 27))
18+
}
19+
}
20+
21+
=== tests/cases/compiler/b.ts ===
22+
import {A} from './a';
23+
>A : Symbol(A, Decl(b.ts, 0, 8))
24+
25+
declare module "./a" {
26+
interface A { }
27+
>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 2, 22))
28+
}
29+
30+
export class B extends A {
31+
>B : Symbol(B, Decl(b.ts, 4, 1))
32+
>A : Symbol(A, Decl(b.ts, 0, 8))
33+
34+
protected setProtected() {
35+
>setProtected : Symbol(setProtected, Decl(b.ts, 6, 26))
36+
37+
}
38+
}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
=== tests/cases/compiler/a.ts ===
2+
3+
export class A {
4+
>A : A
5+
6+
protected protected: any;
7+
>protected : any
8+
9+
protected setProtected(val: any) {
10+
>setProtected : (val: any) => void
11+
>val : any
12+
13+
this.protected = val;
14+
>this.protected = val : any
15+
>this.protected : any
16+
>this : this
17+
>protected : any
18+
>val : any
19+
}
20+
}
21+
22+
=== tests/cases/compiler/b.ts ===
23+
import {A} from './a';
24+
>A : typeof A
25+
26+
declare module "./a" {
27+
interface A { }
28+
>A : A
29+
}
30+
31+
export class B extends A {
32+
>B : B
33+
>A : A
34+
35+
protected setProtected() {
36+
>setProtected : () => void
37+
38+
}
39+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @filename: a.ts
2+
class A {
3+
protected foo() {}
4+
}
5+
// @filename: b.ts
6+
interface A { }
7+
8+
class B extends A {
9+
protected foo() {}
10+
}
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// @module: amd
2+
3+
// @filename: a.ts
4+
export class A {
5+
protected protected: any;
6+
7+
protected setProtected(val: any) {
8+
this.protected = val;
9+
}
10+
}
11+
12+
// @filename: b.ts
13+
import {A} from './a';
14+
15+
declare module "./a" {
16+
interface A { }
17+
}
18+
19+
export class B extends A {
20+
protected setProtected() {
21+
22+
}
23+
}

0 commit comments

Comments
 (0)