From e5aa9cbc6f29fb2da2d9bf9a7852faaec83c8c1c Mon Sep 17 00:00:00 2001 From: Vladimir Matveev Date: Sat, 30 Jan 2016 19:58:29 -0800 Subject: [PATCH] properly handle merged declarations across files --- src/compiler/checker.ts | 8 +-- .../reference/mergedDeclarations5.js | 34 +++++++++++ .../reference/mergedDeclarations5.symbols | 18 ++++++ .../reference/mergedDeclarations5.types | 18 ++++++ .../reference/mergedDeclarations6.js | 57 +++++++++++++++++++ .../reference/mergedDeclarations6.symbols | 38 +++++++++++++ .../reference/mergedDeclarations6.types | 39 +++++++++++++ tests/cases/compiler/mergedDeclarations5.ts | 10 ++++ tests/cases/compiler/mergedDeclarations6.ts | 23 ++++++++ 9 files changed, 241 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/mergedDeclarations5.js create mode 100644 tests/baselines/reference/mergedDeclarations5.symbols create mode 100644 tests/baselines/reference/mergedDeclarations5.types create mode 100644 tests/baselines/reference/mergedDeclarations6.js create mode 100644 tests/baselines/reference/mergedDeclarations6.symbols create mode 100644 tests/baselines/reference/mergedDeclarations6.types create mode 100644 tests/cases/compiler/mergedDeclarations5.ts create mode 100644 tests/cases/compiler/mergedDeclarations6.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index db3517970d9..9ac7241f14c 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -2487,7 +2487,7 @@ namespace ts { // Every class automatically contains a static property member named 'prototype', // the type of which is an instantiation of the class type with type Any supplied as a type argument for each type parameter. // It is an error to explicitly declare a static property member with the name 'prototype'. - const classType = getDeclaredTypeOfSymbol(getMergedSymbol(prototype.parent)); + const classType = getDeclaredTypeOfSymbol(getParentOfSymbol(prototype)); return classType.typeParameters ? createTypeReference(classType, map(classType.typeParameters, _ => anyType)) : classType; } @@ -5803,8 +5803,8 @@ namespace ts { } else if (targetPropFlags & NodeFlags.Protected) { const sourceDeclaredInClass = sourceProp.parent && sourceProp.parent.flags & SymbolFlags.Class; - const sourceClass = sourceDeclaredInClass ? getDeclaredTypeOfSymbol(sourceProp.parent) : undefined; - const targetClass = getDeclaredTypeOfSymbol(targetProp.parent); + const sourceClass = sourceDeclaredInClass ? getDeclaredTypeOfSymbol(getParentOfSymbol(sourceProp)) : undefined; + const targetClass = getDeclaredTypeOfSymbol(getParentOfSymbol(targetProp)); if (!sourceClass || !hasBaseType(sourceClass, targetClass)) { if (reportErrors) { reportError(Diagnostics.Property_0_is_protected_but_type_1_is_not_a_class_derived_from_2, @@ -8797,7 +8797,7 @@ namespace ts { */ function checkClassPropertyAccess(node: PropertyAccessExpression | QualifiedName, left: Expression | QualifiedName, type: Type, prop: Symbol): boolean { const flags = getDeclarationFlagsFromSymbol(prop); - const declaringClass = getDeclaredTypeOfSymbol(getMergedSymbol(prop.parent)); + const declaringClass = getDeclaredTypeOfSymbol(getParentOfSymbol(prop)); if (left.kind === SyntaxKind.SuperKeyword) { const errorNode = node.kind === SyntaxKind.PropertyAccessExpression ? diff --git a/tests/baselines/reference/mergedDeclarations5.js b/tests/baselines/reference/mergedDeclarations5.js new file mode 100644 index 00000000000..ce4b929c7f9 --- /dev/null +++ b/tests/baselines/reference/mergedDeclarations5.js @@ -0,0 +1,34 @@ +//// [tests/cases/compiler/mergedDeclarations5.ts] //// + +//// [a.ts] +class A { + protected foo() {} +} +//// [b.ts] +interface A { } + +class B extends A { + protected foo() {} +} + +//// [a.js] +var A = (function () { + function A() { + } + A.prototype.foo = function () { }; + return A; +}()); +//// [b.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +var B = (function (_super) { + __extends(B, _super); + function B() { + _super.apply(this, arguments); + } + B.prototype.foo = function () { }; + return B; +}(A)); diff --git a/tests/baselines/reference/mergedDeclarations5.symbols b/tests/baselines/reference/mergedDeclarations5.symbols new file mode 100644 index 00000000000..abe1743de1c --- /dev/null +++ b/tests/baselines/reference/mergedDeclarations5.symbols @@ -0,0 +1,18 @@ +=== tests/cases/compiler/a.ts === +class A { +>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 0, 0)) + + protected foo() {} +>foo : Symbol(foo, Decl(a.ts, 0, 9)) +} +=== tests/cases/compiler/b.ts === +interface A { } +>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 0, 0)) + +class B extends A { +>B : Symbol(B, Decl(b.ts, 0, 15)) +>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 0, 0)) + + protected foo() {} +>foo : Symbol(foo, Decl(b.ts, 2, 19)) +} diff --git a/tests/baselines/reference/mergedDeclarations5.types b/tests/baselines/reference/mergedDeclarations5.types new file mode 100644 index 00000000000..5c31617a92b --- /dev/null +++ b/tests/baselines/reference/mergedDeclarations5.types @@ -0,0 +1,18 @@ +=== tests/cases/compiler/a.ts === +class A { +>A : A + + protected foo() {} +>foo : () => void +} +=== tests/cases/compiler/b.ts === +interface A { } +>A : A + +class B extends A { +>B : B +>A : A + + protected foo() {} +>foo : () => void +} diff --git a/tests/baselines/reference/mergedDeclarations6.js b/tests/baselines/reference/mergedDeclarations6.js new file mode 100644 index 00000000000..696ad27b2a6 --- /dev/null +++ b/tests/baselines/reference/mergedDeclarations6.js @@ -0,0 +1,57 @@ +//// [tests/cases/compiler/mergedDeclarations6.ts] //// + +//// [a.ts] + +export class A { + protected protected: any; + + protected setProtected(val: any) { + this.protected = val; + } +} + +//// [b.ts] +import {A} from './a'; + +declare module "./a" { + interface A { } +} + +export class B extends A { + protected setProtected() { + + } +} + +//// [a.js] +define(["require", "exports"], function (require, exports) { + "use strict"; + var A = (function () { + function A() { + } + A.prototype.setProtected = function (val) { + this.protected = val; + }; + return A; + }()); + exports.A = A; +}); +//// [b.js] +var __extends = (this && this.__extends) || function (d, b) { + for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p]; + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); +}; +define(["require", "exports", './a'], function (require, exports, a_1) { + "use strict"; + var B = (function (_super) { + __extends(B, _super); + function B() { + _super.apply(this, arguments); + } + B.prototype.setProtected = function () { + }; + return B; + }(a_1.A)); + exports.B = B; +}); diff --git a/tests/baselines/reference/mergedDeclarations6.symbols b/tests/baselines/reference/mergedDeclarations6.symbols new file mode 100644 index 00000000000..b0d49532384 --- /dev/null +++ b/tests/baselines/reference/mergedDeclarations6.symbols @@ -0,0 +1,38 @@ +=== tests/cases/compiler/a.ts === + +export class A { +>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 2, 22)) + + protected protected: any; +>protected : Symbol(protected, Decl(a.ts, 1, 16)) + + protected setProtected(val: any) { +>setProtected : Symbol(setProtected, Decl(a.ts, 2, 29)) +>val : Symbol(val, Decl(a.ts, 4, 27)) + + this.protected = val; +>this.protected : Symbol(protected, Decl(a.ts, 1, 16)) +>this : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 2, 22)) +>protected : Symbol(protected, Decl(a.ts, 1, 16)) +>val : Symbol(val, Decl(a.ts, 4, 27)) + } +} + +=== tests/cases/compiler/b.ts === +import {A} from './a'; +>A : Symbol(A, Decl(b.ts, 0, 8)) + +declare module "./a" { + interface A { } +>A : Symbol(A, Decl(a.ts, 0, 0), Decl(b.ts, 2, 22)) +} + +export class B extends A { +>B : Symbol(B, Decl(b.ts, 4, 1)) +>A : Symbol(A, Decl(b.ts, 0, 8)) + + protected setProtected() { +>setProtected : Symbol(setProtected, Decl(b.ts, 6, 26)) + + } +} diff --git a/tests/baselines/reference/mergedDeclarations6.types b/tests/baselines/reference/mergedDeclarations6.types new file mode 100644 index 00000000000..6198c08f6b5 --- /dev/null +++ b/tests/baselines/reference/mergedDeclarations6.types @@ -0,0 +1,39 @@ +=== tests/cases/compiler/a.ts === + +export class A { +>A : A + + protected protected: any; +>protected : any + + protected setProtected(val: any) { +>setProtected : (val: any) => void +>val : any + + this.protected = val; +>this.protected = val : any +>this.protected : any +>this : this +>protected : any +>val : any + } +} + +=== tests/cases/compiler/b.ts === +import {A} from './a'; +>A : typeof A + +declare module "./a" { + interface A { } +>A : A +} + +export class B extends A { +>B : B +>A : A + + protected setProtected() { +>setProtected : () => void + + } +} diff --git a/tests/cases/compiler/mergedDeclarations5.ts b/tests/cases/compiler/mergedDeclarations5.ts new file mode 100644 index 00000000000..df5734453d3 --- /dev/null +++ b/tests/cases/compiler/mergedDeclarations5.ts @@ -0,0 +1,10 @@ +// @filename: a.ts +class A { + protected foo() {} +} +// @filename: b.ts +interface A { } + +class B extends A { + protected foo() {} +} \ No newline at end of file diff --git a/tests/cases/compiler/mergedDeclarations6.ts b/tests/cases/compiler/mergedDeclarations6.ts new file mode 100644 index 00000000000..406bed518c1 --- /dev/null +++ b/tests/cases/compiler/mergedDeclarations6.ts @@ -0,0 +1,23 @@ +// @module: amd + +// @filename: a.ts +export class A { + protected protected: any; + + protected setProtected(val: any) { + this.protected = val; + } +} + +// @filename: b.ts +import {A} from './a'; + +declare module "./a" { + interface A { } +} + +export class B extends A { + protected setProtected() { + + } +} \ No newline at end of file