Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Emit of union type metadata for decorator to use constituent serialized type if its identifier and same across all constituent types #11391

Merged
merged 5 commits into from Oct 6, 2016
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
35 changes: 33 additions & 2 deletions src/compiler/transformers/ts.ts
Expand Up @@ -1801,10 +1801,41 @@ namespace ts {
case SyntaxKind.TypeReference:
return serializeTypeReferenceNode(<TypeReferenceNode>node);

case SyntaxKind.IntersectionType:
case SyntaxKind.UnionType:
{
const unionOrIntersection = <UnionOrIntersectionTypeNode>node;
let serializedUnion: Identifier;
for (const typeNode of unionOrIntersection.types) {
const serializedIndividual = serializeTypeNode(typeNode) as Identifier;
// Non identifier
if (serializedIndividual.kind !== SyntaxKind.Identifier) {
serializedUnion = undefined;
break;
}

// One of the individual is global object, return immediately
if (serializedIndividual.text === "Object") {
return serializedIndividual;
}

// Different types
if (serializedUnion && serializedUnion.text !== serializedIndividual.text) {
serializedUnion = undefined;
break;
}

serializedUnion = serializedIndividual;
}

// If we were able to find common type
if (serializedUnion) {
return serializedUnion;
}
}
// Fallthrough
case SyntaxKind.TypeQuery:
case SyntaxKind.TypeLiteral:
case SyntaxKind.UnionType:
case SyntaxKind.IntersectionType:
case SyntaxKind.AnyKeyword:
case SyntaxKind.ThisType:
break;
Expand Down
28 changes: 28 additions & 0 deletions tests/baselines/reference/metadataOfStringLiteral.js
@@ -0,0 +1,28 @@
//// [metadataOfStringLiteral.ts]
function PropDeco(target: Object, propKey: string | symbol) { }

class Foo {
@PropDeco
public foo: "foo" | "bar";
}

//// [metadataOfStringLiteral.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
function PropDeco(target, propKey) { }
var Foo = (function () {
function Foo() {
}
return Foo;
}());
__decorate([
PropDeco,
__metadata("design:type", String)
], Foo.prototype, "foo");
16 changes: 16 additions & 0 deletions tests/baselines/reference/metadataOfStringLiteral.symbols
@@ -0,0 +1,16 @@
=== tests/cases/compiler/metadataOfStringLiteral.ts ===
function PropDeco(target: Object, propKey: string | symbol) { }
>PropDeco : Symbol(PropDeco, Decl(metadataOfStringLiteral.ts, 0, 0))
>target : Symbol(target, Decl(metadataOfStringLiteral.ts, 0, 18))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>propKey : Symbol(propKey, Decl(metadataOfStringLiteral.ts, 0, 33))

class Foo {
>Foo : Symbol(Foo, Decl(metadataOfStringLiteral.ts, 0, 63))

@PropDeco
>PropDeco : Symbol(PropDeco, Decl(metadataOfStringLiteral.ts, 0, 0))

public foo: "foo" | "bar";
>foo : Symbol(Foo.foo, Decl(metadataOfStringLiteral.ts, 2, 11))
}
16 changes: 16 additions & 0 deletions tests/baselines/reference/metadataOfStringLiteral.types
@@ -0,0 +1,16 @@
=== tests/cases/compiler/metadataOfStringLiteral.ts ===
function PropDeco(target: Object, propKey: string | symbol) { }
>PropDeco : (target: Object, propKey: string | symbol) => void
>target : Object
>Object : Object
>propKey : string | symbol

class Foo {
>Foo : Foo

@PropDeco
>PropDeco : (target: Object, propKey: string | symbol) => void

public foo: "foo" | "bar";
>foo : "foo" | "bar"
}
50 changes: 50 additions & 0 deletions tests/baselines/reference/metadataOfUnion.js
@@ -0,0 +1,50 @@
//// [metadataOfUnion.ts]
function PropDeco(target: Object, propKey: string | symbol) { }

class A {
}

class B {
@PropDeco
x: "foo" | A;

@PropDeco
y: true | boolean;

@PropDeco
z: "foo" | boolean;
}

//// [metadataOfUnion.js]
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
function PropDeco(target, propKey) { }
var A = (function () {
function A() {
}
return A;
}());
var B = (function () {
function B() {
}
return B;
}());
__decorate([
PropDeco,
__metadata("design:type", Object)
], B.prototype, "x");
__decorate([
PropDeco,
__metadata("design:type", Boolean)
], B.prototype, "y");
__decorate([
PropDeco,
__metadata("design:type", Object)
], B.prototype, "z");
33 changes: 33 additions & 0 deletions tests/baselines/reference/metadataOfUnion.symbols
@@ -0,0 +1,33 @@
=== tests/cases/compiler/metadataOfUnion.ts ===
function PropDeco(target: Object, propKey: string | symbol) { }
>PropDeco : Symbol(PropDeco, Decl(metadataOfUnion.ts, 0, 0))
>target : Symbol(target, Decl(metadataOfUnion.ts, 0, 18))
>Object : Symbol(Object, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
>propKey : Symbol(propKey, Decl(metadataOfUnion.ts, 0, 33))

class A {
>A : Symbol(A, Decl(metadataOfUnion.ts, 0, 63))
}

class B {
>B : Symbol(B, Decl(metadataOfUnion.ts, 3, 1))

@PropDeco
>PropDeco : Symbol(PropDeco, Decl(metadataOfUnion.ts, 0, 0))

x: "foo" | A;
>x : Symbol(B.x, Decl(metadataOfUnion.ts, 5, 9))
>A : Symbol(A, Decl(metadataOfUnion.ts, 0, 63))

@PropDeco
>PropDeco : Symbol(PropDeco, Decl(metadataOfUnion.ts, 0, 0))

y: true | boolean;
>y : Symbol(B.y, Decl(metadataOfUnion.ts, 7, 17))

@PropDeco
>PropDeco : Symbol(PropDeco, Decl(metadataOfUnion.ts, 0, 0))

z: "foo" | boolean;
>z : Symbol(B.z, Decl(metadataOfUnion.ts, 10, 22))
}
34 changes: 34 additions & 0 deletions tests/baselines/reference/metadataOfUnion.types
@@ -0,0 +1,34 @@
=== tests/cases/compiler/metadataOfUnion.ts ===
function PropDeco(target: Object, propKey: string | symbol) { }
>PropDeco : (target: Object, propKey: string | symbol) => void
>target : Object
>Object : Object
>propKey : string | symbol

class A {
>A : A
}

class B {
>B : B

@PropDeco
>PropDeco : (target: Object, propKey: string | symbol) => void

x: "foo" | A;
>x : A | "foo"
>A : A

@PropDeco
>PropDeco : (target: Object, propKey: string | symbol) => void

y: true | boolean;
>y : boolean
>true : true

@PropDeco
>PropDeco : (target: Object, propKey: string | symbol) => void

z: "foo" | boolean;
>z : boolean | "foo"
}
8 changes: 8 additions & 0 deletions tests/cases/compiler/metadataOfStringLiteral.ts
@@ -0,0 +1,8 @@
// @experimentalDecorators: true
// @emitDecoratorMetadata: true
function PropDeco(target: Object, propKey: string | symbol) { }

class Foo {
@PropDeco
public foo: "foo" | "bar";
}
17 changes: 17 additions & 0 deletions tests/cases/compiler/metadataOfUnion.ts
@@ -0,0 +1,17 @@
// @experimentalDecorators: true
// @emitDecoratorMetadata: true
function PropDeco(target: Object, propKey: string | symbol) { }

class A {
}

class B {
@PropDeco
x: "foo" | A;

@PropDeco
y: true | boolean;

@PropDeco
z: "foo" | boolean;
}