mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-14 19:16:17 -06:00
Fixes an issue when resolving a type name as an expression when emitting type metadata for decorators
This commit is contained in:
parent
81711f9388
commit
b620cace92
@ -14016,15 +14016,17 @@ namespace ts {
|
||||
return type.flags & TypeFlags.ObjectType && getSignaturesOfType(type, SignatureKind.Call).length > 0;
|
||||
}
|
||||
|
||||
function getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind {
|
||||
function getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind {
|
||||
// Resolve the symbol as a value to ensure the type can be reached at runtime during emit.
|
||||
let symbol = resolveEntityName(node.typeName, SymbolFlags.Value, /*ignoreErrors*/ true);
|
||||
let constructorType = symbol ? getTypeOfSymbol(symbol) : undefined;
|
||||
let valueSymbol = resolveEntityName(typeName, SymbolFlags.Value, /*ignoreErrors*/ true);
|
||||
let constructorType = valueSymbol ? getTypeOfSymbol(valueSymbol) : undefined;
|
||||
if (constructorType && isConstructorType(constructorType)) {
|
||||
return TypeReferenceSerializationKind.TypeWithConstructSignatureAndValue;
|
||||
}
|
||||
|
||||
let type = getTypeFromTypeNode(node);
|
||||
// Resolve the symbol as a type so that we can provide a more useful hint for the type serializer.
|
||||
let typeSymbol = resolveEntityName(typeName, SymbolFlags.Type, /*ignoreErrors*/ true);
|
||||
let type = getDeclaredTypeOfSymbol(typeSymbol);
|
||||
if (type === unknownType) {
|
||||
return TypeReferenceSerializationKind.Unknown;
|
||||
}
|
||||
|
||||
@ -4897,8 +4897,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
|
||||
/** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function emitSerializedTypeReferenceNode(node: TypeReferenceNode) {
|
||||
let typeName = node.typeName;
|
||||
let result = resolver.getTypeReferenceSerializationKind(node);
|
||||
let location: Node = node.parent;
|
||||
while (isDeclaration(location) || isTypeNode(location)) {
|
||||
location = location.parent;
|
||||
}
|
||||
|
||||
// Clone the type name and parent it to a location outside of the current declaration.
|
||||
let typeName = cloneEntityName(node.typeName);
|
||||
typeName.parent = location;
|
||||
|
||||
let result = resolver.getTypeReferenceSerializationKind(typeName);
|
||||
switch (result) {
|
||||
case TypeReferenceSerializationKind.Unknown:
|
||||
let temp = createAndRecordTempVariable(TempFlags.Auto);
|
||||
@ -5030,6 +5038,7 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, Promi
|
||||
argumentsWritten++;
|
||||
}
|
||||
if (shouldEmitParamTypesMetadata(node)) {
|
||||
debugger;
|
||||
if (writeComma || argumentsWritten) {
|
||||
write(", ");
|
||||
}
|
||||
|
||||
@ -1573,7 +1573,7 @@ namespace ts {
|
||||
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
|
||||
getBlockScopedVariableId(node: Identifier): number;
|
||||
getReferencedValueDeclaration(reference: Identifier): Declaration;
|
||||
getTypeReferenceSerializationKind(node: TypeReferenceNode): TypeReferenceSerializationKind;
|
||||
getTypeReferenceSerializationKind(typeName: EntityName): TypeReferenceSerializationKind;
|
||||
}
|
||||
|
||||
export const enum SymbolFlags {
|
||||
|
||||
@ -1424,6 +1424,22 @@ namespace ts {
|
||||
return isFunctionLike(n) || n.kind === SyntaxKind.ModuleDeclaration || n.kind === SyntaxKind.SourceFile;
|
||||
}
|
||||
|
||||
export function cloneEntityName(node: EntityName): EntityName {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
let clone = <Identifier>createSynthesizedNode(SyntaxKind.Identifier);
|
||||
clone.text = (<Identifier>node).text;
|
||||
return clone;
|
||||
}
|
||||
else {
|
||||
let clone = <QualifiedName>createSynthesizedNode(SyntaxKind.QualifiedName);
|
||||
clone.left = cloneEntityName((<QualifiedName>node).left);
|
||||
clone.left.parent = clone;
|
||||
clone.right = <Identifier>cloneEntityName((<QualifiedName>node).right);
|
||||
clone.right.parent = clone;
|
||||
return clone;
|
||||
}
|
||||
}
|
||||
|
||||
export function nodeIsSynthesized(node: Node): boolean {
|
||||
return node.pos === -1;
|
||||
}
|
||||
|
||||
45
tests/baselines/reference/decoratorMetadata.js
Normal file
45
tests/baselines/reference/decoratorMetadata.js
Normal file
@ -0,0 +1,45 @@
|
||||
//// [tests/cases/conformance/decorators/decoratorMetadata.ts] ////
|
||||
|
||||
//// [service.ts]
|
||||
export default class Service {
|
||||
}
|
||||
//// [component.ts]
|
||||
import Service from "./service";
|
||||
|
||||
declare var decorator: any;
|
||||
|
||||
@decorator
|
||||
class MyComponent {
|
||||
constructor(public Service: Service) {
|
||||
}
|
||||
}
|
||||
|
||||
//// [service.js]
|
||||
var Service = (function () {
|
||||
function Service() {
|
||||
}
|
||||
return Service;
|
||||
})();
|
||||
exports.default = Service;
|
||||
//// [component.js]
|
||||
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") return Reflect.decorate(decorators, target, key, desc);
|
||||
switch (arguments.length) {
|
||||
case 2: return decorators.reduceRight(function(o, d) { return (d && d(o)) || o; }, target);
|
||||
case 3: return decorators.reduceRight(function(o, d) { return (d && d(target, key)), void 0; }, void 0);
|
||||
case 4: return decorators.reduceRight(function(o, d) { return (d && d(target, key, o)) || o; }, desc);
|
||||
}
|
||||
};
|
||||
var __metadata = (this && this.__metadata) || function (k, v) {
|
||||
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
|
||||
};
|
||||
var MyComponent = (function () {
|
||||
function MyComponent(Service) {
|
||||
this.Service = Service;
|
||||
}
|
||||
MyComponent = __decorate([
|
||||
decorator,
|
||||
__metadata('design:paramtypes', [service_1.default])
|
||||
], MyComponent);
|
||||
return MyComponent;
|
||||
})();
|
||||
22
tests/baselines/reference/decoratorMetadata.symbols
Normal file
22
tests/baselines/reference/decoratorMetadata.symbols
Normal file
@ -0,0 +1,22 @@
|
||||
=== tests/cases/conformance/decorators/service.ts ===
|
||||
export default class Service {
|
||||
>Service : Symbol(Service, Decl(service.ts, 0, 0))
|
||||
}
|
||||
=== tests/cases/conformance/decorators/component.ts ===
|
||||
import Service from "./service";
|
||||
>Service : Symbol(Service, Decl(component.ts, 0, 6))
|
||||
|
||||
declare var decorator: any;
|
||||
>decorator : Symbol(decorator, Decl(component.ts, 2, 11))
|
||||
|
||||
@decorator
|
||||
>decorator : Symbol(decorator, Decl(component.ts, 2, 11))
|
||||
|
||||
class MyComponent {
|
||||
>MyComponent : Symbol(MyComponent, Decl(component.ts, 2, 27))
|
||||
|
||||
constructor(public Service: Service) {
|
||||
>Service : Symbol(Service, Decl(component.ts, 6, 16))
|
||||
>Service : Symbol(Service, Decl(component.ts, 0, 6))
|
||||
}
|
||||
}
|
||||
22
tests/baselines/reference/decoratorMetadata.types
Normal file
22
tests/baselines/reference/decoratorMetadata.types
Normal file
@ -0,0 +1,22 @@
|
||||
=== tests/cases/conformance/decorators/service.ts ===
|
||||
export default class Service {
|
||||
>Service : Service
|
||||
}
|
||||
=== tests/cases/conformance/decorators/component.ts ===
|
||||
import Service from "./service";
|
||||
>Service : typeof Service
|
||||
|
||||
declare var decorator: any;
|
||||
>decorator : any
|
||||
|
||||
@decorator
|
||||
>decorator : any
|
||||
|
||||
class MyComponent {
|
||||
>MyComponent : MyComponent
|
||||
|
||||
constructor(public Service: Service) {
|
||||
>Service : Service
|
||||
>Service : Service
|
||||
}
|
||||
}
|
||||
17
tests/cases/conformance/decorators/decoratorMetadata.ts
Normal file
17
tests/cases/conformance/decorators/decoratorMetadata.ts
Normal file
@ -0,0 +1,17 @@
|
||||
// @experimentalDecorators: true
|
||||
// @emitDecoratorMetadata: true
|
||||
// @target: es5
|
||||
// @module: commonjs
|
||||
// @filename: service.ts
|
||||
export default class Service {
|
||||
}
|
||||
// @filename: component.ts
|
||||
import Service from "./service";
|
||||
|
||||
declare var decorator: any;
|
||||
|
||||
@decorator
|
||||
class MyComponent {
|
||||
constructor(public Service: Service) {
|
||||
}
|
||||
}
|
||||
Loading…
x
Reference in New Issue
Block a user