Skip to content

Commit b59824a

Browse files
authored
Merge pull request microsoft#25190 from mprobst/fix-generic-type-emit
Fix decorator design:types emit for type variables.
2 parents cb6325d + a7be62f commit b59824a

16 files changed

+254
-10
lines changed

src/compiler/transformers/ts.ts

Lines changed: 18 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,8 @@ namespace ts {
6161
let currentSourceFile: SourceFile;
6262
let currentNamespace: ModuleDeclaration;
6363
let currentNamespaceContainerName: Identifier;
64-
let currentScope: SourceFile | Block | ModuleBlock | CaseBlock;
64+
let currentLexicalScope: SourceFile | Block | ModuleBlock | CaseBlock;
65+
let currentNameScope: ClassDeclaration | undefined;
6566
let currentScopeFirstDeclarationsOfName: UnderscoreEscapedMap<Node> | undefined;
6667

6768
/**
@@ -132,7 +133,8 @@ namespace ts {
132133
*/
133134
function saveStateAndInvoke<T>(node: Node, f: (node: Node) => T): T {
134135
// Save state
135-
const savedCurrentScope = currentScope;
136+
const savedCurrentScope = currentLexicalScope;
137+
const savedCurrentNameScope = currentNameScope;
136138
const savedCurrentScopeFirstDeclarationsOfName = currentScopeFirstDeclarationsOfName;
137139

138140
// Handle state changes before visiting a node.
@@ -141,11 +143,12 @@ namespace ts {
141143
const visited = f(node);
142144

143145
// Restore state
144-
if (currentScope !== savedCurrentScope) {
146+
if (currentLexicalScope !== savedCurrentScope) {
145147
currentScopeFirstDeclarationsOfName = savedCurrentScopeFirstDeclarationsOfName;
146148
}
147149

148-
currentScope = savedCurrentScope;
150+
currentLexicalScope = savedCurrentScope;
151+
currentNameScope = savedCurrentNameScope;
149152
return visited;
150153
}
151154

@@ -160,7 +163,8 @@ namespace ts {
160163
case SyntaxKind.CaseBlock:
161164
case SyntaxKind.ModuleBlock:
162165
case SyntaxKind.Block:
163-
currentScope = <SourceFile | CaseBlock | ModuleBlock | Block>node;
166+
currentLexicalScope = <SourceFile | CaseBlock | ModuleBlock | Block>node;
167+
currentNameScope = undefined;
164168
currentScopeFirstDeclarationsOfName = undefined;
165169
break;
166170

@@ -180,6 +184,10 @@ namespace ts {
180184
// programs may also have an undefined name.
181185
Debug.assert(node.kind === SyntaxKind.ClassDeclaration || hasModifier(node, ModifierFlags.Default));
182186
}
187+
if (isClassDeclaration(node)) {
188+
// XXX: should probably also cover interfaces and type aliases that can have type variables?
189+
currentNameScope = node;
190+
}
183191

184192
break;
185193
}
@@ -1971,7 +1979,7 @@ namespace ts {
19711979
* @param node The type reference node.
19721980
*/
19731981
function serializeTypeReferenceNode(node: TypeReferenceNode): SerializedTypeNode {
1974-
const kind = resolver.getTypeReferenceSerializationKind(node.typeName, currentScope);
1982+
const kind = resolver.getTypeReferenceSerializationKind(node.typeName, currentNameScope || currentLexicalScope);
19751983
switch (kind) {
19761984
case TypeReferenceSerializationKind.Unknown:
19771985
const serialized = serializeEntityNameAsExpression(node.typeName, /*useFallback*/ true);
@@ -2035,7 +2043,7 @@ namespace ts {
20352043
const name = getMutableClone(node);
20362044
name.flags &= ~NodeFlags.Synthesized;
20372045
name.original = undefined;
2038-
name.parent = getParseTreeNode(currentScope); // ensure the parent is set to a parse tree node.
2046+
name.parent = getParseTreeNode(currentLexicalScope); // ensure the parent is set to a parse tree node.
20392047
if (useFallback) {
20402048
return createLogicalAnd(
20412049
createStrictInequality(
@@ -2622,7 +2630,7 @@ namespace ts {
26222630
// enum body.
26232631
if (addVarForEnumOrModuleDeclaration(statements, node)) {
26242632
// We should still emit the comments if we are emitting a system module.
2625-
if (moduleKind !== ModuleKind.System || currentScope !== currentSourceFile) {
2633+
if (moduleKind !== ModuleKind.System || currentLexicalScope !== currentSourceFile) {
26262634
emitFlags |= EmitFlags.NoLeadingComments;
26272635
}
26282636
}
@@ -2835,7 +2843,7 @@ namespace ts {
28352843
createVariableDeclaration(
28362844
getLocalName(node, /*allowComments*/ false, /*allowSourceMaps*/ true)
28372845
)
2838-
], currentScope.kind === SyntaxKind.SourceFile ? NodeFlags.None : NodeFlags.Let)
2846+
], currentLexicalScope.kind === SyntaxKind.SourceFile ? NodeFlags.None : NodeFlags.Let)
28392847
);
28402848

28412849
setOriginalNode(statement, node);
@@ -2911,7 +2919,7 @@ namespace ts {
29112919
// module body.
29122920
if (addVarForEnumOrModuleDeclaration(statements, node)) {
29132921
// We should still emit the comments if we are emitting a system module.
2914-
if (moduleKind !== ModuleKind.System || currentScope !== currentSourceFile) {
2922+
if (moduleKind !== ModuleKind.System || currentLexicalScope !== currentSourceFile) {
29152923
emitFlags |= EmitFlags.NoLeadingComments;
29162924
}
29172925
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
tests/cases/compiler/decoratorMetadataGenericTypeVariable.ts(2,4): error TS2304: Cannot find name 'Decorate'.
2+
3+
4+
==== tests/cases/compiler/decoratorMetadataGenericTypeVariable.ts (1 errors) ====
5+
export class C<TypeVariable> {
6+
@Decorate
7+
~~~~~~~~
8+
!!! error TS2304: Cannot find name 'Decorate'.
9+
member: TypeVariable;
10+
}
11+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [decoratorMetadataGenericTypeVariable.ts]
2+
export class C<TypeVariable> {
3+
@Decorate
4+
member: TypeVariable;
5+
}
6+
7+
8+
//// [decoratorMetadataGenericTypeVariable.js]
9+
"use strict";
10+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
11+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
12+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
13+
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;
14+
return c > 3 && r && Object.defineProperty(target, key, r), r;
15+
};
16+
var __metadata = (this && this.__metadata) || function (k, v) {
17+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
18+
};
19+
exports.__esModule = true;
20+
var C = /** @class */ (function () {
21+
function C() {
22+
}
23+
__decorate([
24+
Decorate,
25+
__metadata("design:type", Object)
26+
], C.prototype, "member");
27+
return C;
28+
}());
29+
exports.C = C;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/decoratorMetadataGenericTypeVariable.ts ===
2+
export class C<TypeVariable> {
3+
>C : Symbol(C, Decl(decoratorMetadataGenericTypeVariable.ts, 0, 0))
4+
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariable.ts, 0, 15))
5+
6+
@Decorate
7+
member: TypeVariable;
8+
>member : Symbol(C.member, Decl(decoratorMetadataGenericTypeVariable.ts, 0, 30))
9+
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariable.ts, 0, 15))
10+
}
11+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/compiler/decoratorMetadataGenericTypeVariable.ts ===
2+
export class C<TypeVariable> {
3+
>C : C<TypeVariable>
4+
>TypeVariable : TypeVariable
5+
6+
@Decorate
7+
>Decorate : any
8+
9+
member: TypeVariable;
10+
>member : TypeVariable
11+
>TypeVariable : TypeVariable
12+
}
13+
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
tests/cases/compiler/decoratorMetadataGenericTypeVariableDefault.ts(2,4): error TS2304: Cannot find name 'Decorate'.
2+
3+
4+
==== tests/cases/compiler/decoratorMetadataGenericTypeVariableDefault.ts (1 errors) ====
5+
export class C<TypeVariable = string> {
6+
@Decorate
7+
~~~~~~~~
8+
!!! error TS2304: Cannot find name 'Decorate'.
9+
member: TypeVariable;
10+
}
11+
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
//// [decoratorMetadataGenericTypeVariableDefault.ts]
2+
export class C<TypeVariable = string> {
3+
@Decorate
4+
member: TypeVariable;
5+
}
6+
7+
8+
//// [decoratorMetadataGenericTypeVariableDefault.js]
9+
"use strict";
10+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
11+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
12+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
13+
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;
14+
return c > 3 && r && Object.defineProperty(target, key, r), r;
15+
};
16+
var __metadata = (this && this.__metadata) || function (k, v) {
17+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
18+
};
19+
exports.__esModule = true;
20+
var C = /** @class */ (function () {
21+
function C() {
22+
}
23+
__decorate([
24+
Decorate,
25+
__metadata("design:type", Object)
26+
], C.prototype, "member");
27+
return C;
28+
}());
29+
exports.C = C;
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
=== tests/cases/compiler/decoratorMetadataGenericTypeVariableDefault.ts ===
2+
export class C<TypeVariable = string> {
3+
>C : Symbol(C, Decl(decoratorMetadataGenericTypeVariableDefault.ts, 0, 0))
4+
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableDefault.ts, 0, 15))
5+
6+
@Decorate
7+
member: TypeVariable;
8+
>member : Symbol(C.member, Decl(decoratorMetadataGenericTypeVariableDefault.ts, 0, 39))
9+
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableDefault.ts, 0, 15))
10+
}
11+
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
=== tests/cases/compiler/decoratorMetadataGenericTypeVariableDefault.ts ===
2+
export class C<TypeVariable = string> {
3+
>C : C<TypeVariable>
4+
>TypeVariable : TypeVariable
5+
6+
@Decorate
7+
>Decorate : any
8+
9+
member: TypeVariable;
10+
>member : TypeVariable
11+
>TypeVariable : TypeVariable
12+
}
13+
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
tests/cases/compiler/decoratorMetadataGenericTypeVariableInScope.ts(5,4): error TS2304: Cannot find name 'Decorate'.
2+
3+
4+
==== tests/cases/compiler/decoratorMetadataGenericTypeVariableInScope.ts (1 errors) ====
5+
// Unused, but could collide with the named type argument below.
6+
class TypeVariable {}
7+
8+
export class C<TypeVariable> {
9+
@Decorate
10+
~~~~~~~~
11+
!!! error TS2304: Cannot find name 'Decorate'.
12+
member: TypeVariable;
13+
}
14+
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
//// [decoratorMetadataGenericTypeVariableInScope.ts]
2+
// Unused, but could collide with the named type argument below.
3+
class TypeVariable {}
4+
5+
export class C<TypeVariable> {
6+
@Decorate
7+
member: TypeVariable;
8+
}
9+
10+
11+
//// [decoratorMetadataGenericTypeVariableInScope.js]
12+
"use strict";
13+
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
14+
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
15+
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
16+
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;
17+
return c > 3 && r && Object.defineProperty(target, key, r), r;
18+
};
19+
var __metadata = (this && this.__metadata) || function (k, v) {
20+
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
21+
};
22+
exports.__esModule = true;
23+
// Unused, but could collide with the named type argument below.
24+
var TypeVariable = /** @class */ (function () {
25+
function TypeVariable() {
26+
}
27+
return TypeVariable;
28+
}());
29+
var C = /** @class */ (function () {
30+
function C() {
31+
}
32+
__decorate([
33+
Decorate,
34+
__metadata("design:type", Object)
35+
], C.prototype, "member");
36+
return C;
37+
}());
38+
exports.C = C;
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
=== tests/cases/compiler/decoratorMetadataGenericTypeVariableInScope.ts ===
2+
// Unused, but could collide with the named type argument below.
3+
class TypeVariable {}
4+
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 0, 0))
5+
6+
export class C<TypeVariable> {
7+
>C : Symbol(C, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 1, 21))
8+
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 3, 15))
9+
10+
@Decorate
11+
member: TypeVariable;
12+
>member : Symbol(C.member, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 3, 30))
13+
>TypeVariable : Symbol(TypeVariable, Decl(decoratorMetadataGenericTypeVariableInScope.ts, 3, 15))
14+
}
15+
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
=== tests/cases/compiler/decoratorMetadataGenericTypeVariableInScope.ts ===
2+
// Unused, but could collide with the named type argument below.
3+
class TypeVariable {}
4+
>TypeVariable : TypeVariable
5+
6+
export class C<TypeVariable> {
7+
>C : C<TypeVariable>
8+
>TypeVariable : TypeVariable
9+
10+
@Decorate
11+
>Decorate : any
12+
13+
member: TypeVariable;
14+
>member : TypeVariable
15+
>TypeVariable : TypeVariable
16+
}
17+
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @experimentalDecorators: true
2+
// @emitDecoratorMetadata: true
3+
4+
export class C<TypeVariable> {
5+
@Decorate
6+
member: TypeVariable;
7+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
// @experimentalDecorators: true
2+
// @emitDecoratorMetadata: true
3+
4+
export class C<TypeVariable = string> {
5+
@Decorate
6+
member: TypeVariable;
7+
}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
// @experimentalDecorators: true
2+
// @emitDecoratorMetadata: true
3+
4+
// Unused, but could collide with the named type argument below.
5+
class TypeVariable {}
6+
7+
export class C<TypeVariable> {
8+
@Decorate
9+
member: TypeVariable;
10+
}

0 commit comments

Comments
 (0)