mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Merge branch 'master' into APISamples
Conflicts: tests/baselines/reference/APISample_compile.js tests/baselines/reference/APISample_compile.types tests/baselines/reference/APISample_linter.js tests/baselines/reference/APISample_linter.types tests/baselines/reference/APISample_transform.js tests/baselines/reference/APISample_transform.types tests/baselines/reference/APISample_watcher.js tests/baselines/reference/APISample_watcher.types
This commit is contained in:
+306
-16
@@ -126,6 +126,7 @@ module ts {
|
||||
let stringLiteralTypes: Map<StringLiteralType> = {};
|
||||
let emitExtends = false;
|
||||
let emitDecorate = false;
|
||||
let emitParam = false;
|
||||
|
||||
let mergedSymbols: Symbol[] = [];
|
||||
let symbolLinks: SymbolLinks[] = [];
|
||||
@@ -3000,6 +3001,16 @@ module ts {
|
||||
return getSignaturesOfObjectOrUnionType(getApparentType(type), kind);
|
||||
}
|
||||
|
||||
function typeHasCallOrConstructSignatures(type: Type): boolean {
|
||||
let apparentType = getApparentType(type);
|
||||
if (apparentType.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
||||
return resolved.callSignatures.length > 0
|
||||
|| resolved.constructSignatures.length > 0;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function getIndexTypeOfObjectOrUnionType(type: Type, kind: IndexKind): Type {
|
||||
if (type.flags & (TypeFlags.ObjectType | TypeFlags.Union)) {
|
||||
let resolved = resolveObjectOrUnionTypeMembers(<ObjectType>type);
|
||||
@@ -8727,24 +8738,92 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks a type reference node as an expression. */
|
||||
function checkTypeNodeAsExpression(node: TypeNode | LiteralExpression) {
|
||||
// When we are emitting type metadata for decorators, we need to try to check the type
|
||||
// as if it were an expression so that we can emit the type in a value position when we
|
||||
// serialize the type metadata.
|
||||
if (node && node.kind === SyntaxKind.TypeReference) {
|
||||
let type = getTypeFromTypeNodeOrHeritageClauseElement(node);
|
||||
let shouldCheckIfUnknownType = type === unknownType && compilerOptions.separateCompilation;
|
||||
if (!type || (!shouldCheckIfUnknownType && type.flags & (TypeFlags.Intrinsic | TypeFlags.NumberLike | TypeFlags.StringLike))) {
|
||||
return;
|
||||
}
|
||||
if (shouldCheckIfUnknownType || type.symbol.valueDeclaration) {
|
||||
checkExpressionOrQualifiedName((<TypeReferenceNode>node).typeName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the type annotation of an accessor declaration or property declaration as
|
||||
* an expression if it is a type reference to a type with a value declaration.
|
||||
*/
|
||||
function checkTypeAnnotationAsExpression(node: AccessorDeclaration | PropertyDeclaration | ParameterDeclaration | MethodDeclaration) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
checkTypeNodeAsExpression((<PropertyDeclaration>node).type);
|
||||
break;
|
||||
case SyntaxKind.Parameter: checkTypeNodeAsExpression((<ParameterDeclaration>node).type);
|
||||
break;
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
checkTypeNodeAsExpression((<MethodDeclaration>node).type);
|
||||
break;
|
||||
case SyntaxKind.GetAccessor:
|
||||
checkTypeNodeAsExpression((<AccessorDeclaration>node).type);
|
||||
break;
|
||||
case SyntaxKind.SetAccessor:
|
||||
checkTypeNodeAsExpression(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
|
||||
function checkParameterTypeAnnotationsAsExpressions(node: FunctionLikeDeclaration) {
|
||||
// ensure all type annotations with a value declaration are checked as an expression
|
||||
for (let parameter of node.parameters) {
|
||||
checkTypeAnnotationAsExpression(parameter);
|
||||
}
|
||||
}
|
||||
|
||||
/** Check the decorators of a node */
|
||||
function checkDecorators(node: Node): void {
|
||||
if (!node.decorators) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
emitDecorate = true;
|
||||
break;
|
||||
// skip this check for nodes that cannot have decorators. These should have already had an error reported by
|
||||
// checkGrammarDecorators.
|
||||
if (!nodeCanBeDecorated(node)) {
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
// we only need to perform these checks if we are emitting serialized type metadata for the target of a decorator.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
var constructor = getFirstConstructorWithBody(<ClassDeclaration>node);
|
||||
if (constructor) {
|
||||
checkParameterTypeAnnotationsAsExpressions(constructor);
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
checkParameterTypeAnnotationsAsExpressions(<FunctionLikeDeclaration>node);
|
||||
// fall-through
|
||||
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
case SyntaxKind.Parameter:
|
||||
checkTypeAnnotationAsExpression(<PropertyDeclaration | ParameterDeclaration>node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
emitDecorate = true;
|
||||
if (node.kind === SyntaxKind.Parameter) {
|
||||
emitParam = true;
|
||||
}
|
||||
|
||||
forEach(node.decorators, checkDecorator);
|
||||
@@ -10764,6 +10843,10 @@ module ts {
|
||||
links.flags |= NodeCheckFlags.EmitDecorate;
|
||||
}
|
||||
|
||||
if (emitParam) {
|
||||
links.flags |= NodeCheckFlags.EmitParam;
|
||||
}
|
||||
|
||||
links.flags |= NodeCheckFlags.TypeChecked;
|
||||
}
|
||||
}
|
||||
@@ -11442,6 +11525,201 @@ module ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
/** Serializes an EntityName (with substitutions) to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function serializeEntityName(node: EntityName, getGeneratedNameForNode: (Node: Node) => string, fallbackPath?: string[]): string {
|
||||
if (node.kind === SyntaxKind.Identifier) {
|
||||
var substitution = getExpressionNameSubstitution(<Identifier>node, getGeneratedNameForNode);
|
||||
var text = substitution || (<Identifier>node).text;
|
||||
if (fallbackPath) {
|
||||
fallbackPath.push(text);
|
||||
}
|
||||
else {
|
||||
return text;
|
||||
}
|
||||
}
|
||||
else {
|
||||
var left = serializeEntityName((<QualifiedName>node).left, getGeneratedNameForNode, fallbackPath);
|
||||
var right = serializeEntityName((<QualifiedName>node).right, getGeneratedNameForNode, fallbackPath);
|
||||
if (!fallbackPath) {
|
||||
return left + "." + right;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** Serializes a TypeReferenceNode to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function serializeTypeReferenceNode(node: TypeReferenceNode, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
|
||||
// serialization of a TypeReferenceNode uses the following rules:
|
||||
//
|
||||
// * The serialized type of a TypeReference that is `void` is "void 0".
|
||||
// * The serialized type of a TypeReference that is a `boolean` is "Boolean".
|
||||
// * The serialized type of a TypeReference that is an enum or `number` is "Number".
|
||||
// * The serialized type of a TypeReference that is a string literal or `string` is "String".
|
||||
// * The serialized type of a TypeReference that is a tuple is "Array".
|
||||
// * The serialized type of a TypeReference that is a `symbol` is "Symbol".
|
||||
// * The serialized type of a TypeReference with a value declaration is its entity name.
|
||||
// * The serialized type of a TypeReference with a call or construct signature is "Function".
|
||||
// * The serialized type of any other type is "Object".
|
||||
let type = getTypeFromTypeReference(node);
|
||||
if (type.flags & TypeFlags.Void) {
|
||||
return "void 0";
|
||||
}
|
||||
else if (type.flags & TypeFlags.Boolean) {
|
||||
return "Boolean";
|
||||
}
|
||||
else if (type.flags & TypeFlags.NumberLike) {
|
||||
return "Number";
|
||||
}
|
||||
else if (type.flags & TypeFlags.StringLike) {
|
||||
return "String";
|
||||
}
|
||||
else if (type.flags & TypeFlags.Tuple) {
|
||||
return "Array";
|
||||
}
|
||||
else if (type.flags & TypeFlags.ESSymbol) {
|
||||
return "Symbol";
|
||||
}
|
||||
else if (type === unknownType) {
|
||||
var fallbackPath: string[] = [];
|
||||
serializeEntityName(node.typeName, getGeneratedNameForNode, fallbackPath);
|
||||
return fallbackPath;
|
||||
}
|
||||
else if (type.symbol && type.symbol.valueDeclaration) {
|
||||
return serializeEntityName(node.typeName, getGeneratedNameForNode);
|
||||
}
|
||||
else if (typeHasCallOrConstructSignatures(type)) {
|
||||
return "Function";
|
||||
}
|
||||
|
||||
return "Object";
|
||||
}
|
||||
|
||||
/** Serializes a TypeNode to an appropriate JS constructor value. Used by the __metadata decorator. */
|
||||
function serializeTypeNode(node: TypeNode | LiteralExpression, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
|
||||
// serialization of a TypeNode uses the following rules:
|
||||
//
|
||||
// * The serialized type of `void` is "void 0" (undefined).
|
||||
// * The serialized type of a parenthesized type is the serialized type of its nested type.
|
||||
// * The serialized type of a Function or Constructor type is "Function".
|
||||
// * The serialized type of an Array or Tuple type is "Array".
|
||||
// * The serialized type of `boolean` is "Boolean".
|
||||
// * The serialized type of `string` or a string-literal type is "String".
|
||||
// * The serialized type of a type reference is handled by `serializeTypeReferenceNode`.
|
||||
// * The serialized type of any other type node is "Object".
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.VoidKeyword:
|
||||
return "void 0";
|
||||
case SyntaxKind.ParenthesizedType:
|
||||
return serializeTypeNode((<ParenthesizedTypeNode>node).type, getGeneratedNameForNode);
|
||||
case SyntaxKind.FunctionType:
|
||||
case SyntaxKind.ConstructorType:
|
||||
return "Function";
|
||||
case SyntaxKind.ArrayType:
|
||||
case SyntaxKind.TupleType:
|
||||
return "Array";
|
||||
case SyntaxKind.BooleanKeyword:
|
||||
return "Boolean";
|
||||
case SyntaxKind.StringKeyword:
|
||||
case SyntaxKind.StringLiteral:
|
||||
return "String";
|
||||
case SyntaxKind.NumberKeyword:
|
||||
return "Number";
|
||||
case SyntaxKind.TypeReference:
|
||||
return serializeTypeReferenceNode(<TypeReferenceNode>node, getGeneratedNameForNode);
|
||||
case SyntaxKind.TypeQuery:
|
||||
case SyntaxKind.TypeLiteral:
|
||||
case SyntaxKind.UnionType:
|
||||
case SyntaxKind.AnyKeyword:
|
||||
break;
|
||||
default:
|
||||
Debug.fail("Cannot serialize unexpected type node.");
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return "Object";
|
||||
}
|
||||
|
||||
/** Serializes the type of a declaration to an appropriate JS constructor value. Used by the __metadata decorator for a class member. */
|
||||
function serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
|
||||
// serialization of the type of a declaration uses the following rules:
|
||||
//
|
||||
// * The serialized type of a ClassDeclaration is "Function"
|
||||
// * The serialized type of a ParameterDeclaration is the serialized type of its type annotation.
|
||||
// * The serialized type of a PropertyDeclaration is the serialized type of its type annotation.
|
||||
// * The serialized type of an AccessorDeclaration is the serialized type of the return type annotation of its getter or parameter type annotation of its setter.
|
||||
// * The serialized type of any other FunctionLikeDeclaration is "Function".
|
||||
// * The serialized type of any other node is "void 0".
|
||||
//
|
||||
// For rules on serializing type annotations, see `serializeTypeNode`.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration: return "Function";
|
||||
case SyntaxKind.PropertyDeclaration: return serializeTypeNode((<PropertyDeclaration>node).type, getGeneratedNameForNode);
|
||||
case SyntaxKind.Parameter: return serializeTypeNode((<ParameterDeclaration>node).type, getGeneratedNameForNode);
|
||||
case SyntaxKind.GetAccessor: return serializeTypeNode((<AccessorDeclaration>node).type, getGeneratedNameForNode);
|
||||
case SyntaxKind.SetAccessor: return serializeTypeNode(getSetAccessorTypeAnnotationNode(<AccessorDeclaration>node), getGeneratedNameForNode);
|
||||
}
|
||||
if (isFunctionLike(node)) {
|
||||
return "Function";
|
||||
}
|
||||
return "void 0";
|
||||
}
|
||||
|
||||
/** Serializes the parameter types of a function or the constructor of a class. Used by the __metadata decorator for a method or set accessor. */
|
||||
function serializeParameterTypesOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[] {
|
||||
// serialization of parameter types uses the following rules:
|
||||
//
|
||||
// * If the declaration is a class, the parameters of the first constructor with a body are used.
|
||||
// * If the declaration is function-like and has a body, the parameters of the function are used.
|
||||
//
|
||||
// For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`.
|
||||
if (node) {
|
||||
var valueDeclaration: FunctionLikeDeclaration;
|
||||
if (node.kind === SyntaxKind.ClassDeclaration) {
|
||||
valueDeclaration = getFirstConstructorWithBody(<ClassDeclaration>node);
|
||||
}
|
||||
else if (isFunctionLike(node) && nodeIsPresent((<FunctionLikeDeclaration>node).body)) {
|
||||
valueDeclaration = <FunctionLikeDeclaration>node;
|
||||
}
|
||||
if (valueDeclaration) {
|
||||
var result: (string | string[])[];
|
||||
var parameters = valueDeclaration.parameters;
|
||||
var parameterCount = parameters.length;
|
||||
if (parameterCount > 0) {
|
||||
result = new Array<string>(parameterCount);
|
||||
for (var i = 0; i < parameterCount; i++) {
|
||||
if (parameters[i].dotDotDotToken) {
|
||||
var parameterType = parameters[i].type;
|
||||
if (parameterType.kind === SyntaxKind.ArrayType) {
|
||||
parameterType = (<ArrayTypeNode>parameterType).elementType;
|
||||
}
|
||||
else if (parameterType.kind === SyntaxKind.TypeReference && (<TypeReferenceNode>parameterType).typeArguments && (<TypeReferenceNode>parameterType).typeArguments.length === 1) {
|
||||
parameterType = (<TypeReferenceNode>parameterType).typeArguments[0];
|
||||
}
|
||||
else {
|
||||
parameterType = undefined;
|
||||
}
|
||||
result[i] = serializeTypeNode(parameterType, getGeneratedNameForNode);
|
||||
}
|
||||
else {
|
||||
result[i] = serializeTypeOfNode(parameters[i], getGeneratedNameForNode);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
return emptyArray;
|
||||
}
|
||||
|
||||
/** Serializes the return type of function. Used by the __metadata decorator for a method. */
|
||||
function serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] {
|
||||
if (node && isFunctionLike(node)) {
|
||||
return serializeTypeNode((<FunctionLikeDeclaration>node).type, getGeneratedNameForNode);
|
||||
}
|
||||
return "void 0";
|
||||
}
|
||||
|
||||
function writeTypeOfDeclaration(declaration: AccessorDeclaration | VariableLikeDeclaration, enclosingDeclaration: Node, flags: TypeFormatFlags, writer: SymbolWriter) {
|
||||
// Get type of the symbol if this is the valid symbol otherwise get type at location
|
||||
let symbol = getSymbolOfNode(declaration);
|
||||
@@ -11529,6 +11807,9 @@ module ts {
|
||||
resolvesToSomeValue,
|
||||
collectLinkedAliases,
|
||||
getBlockScopedVariableId,
|
||||
serializeTypeOfNode,
|
||||
serializeParameterTypesOfNode,
|
||||
serializeReturnTypeOfNode,
|
||||
};
|
||||
}
|
||||
|
||||
@@ -11593,15 +11874,15 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
if (!nodeCanBeDecorated(node)) {
|
||||
return grammarErrorOnNode(node, Diagnostics.Decorators_are_not_valid_here);
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_not_valid_here);
|
||||
}
|
||||
else if (languageVersion < ScriptTarget.ES5) {
|
||||
return grammarErrorOnNode(node, Diagnostics.Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher);
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.Decorators_are_only_available_when_targeting_ECMAScript_5_and_higher);
|
||||
}
|
||||
else if (node.kind === SyntaxKind.GetAccessor || node.kind === SyntaxKind.SetAccessor) {
|
||||
let accessors = getAllAccessorDeclarations((<ClassDeclaration>node.parent).members, <AccessorDeclaration>node);
|
||||
if (accessors.firstAccessor.decorators && node === accessors.secondAccessor) {
|
||||
return grammarErrorOnNode(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name);
|
||||
return grammarErrorOnFirstToken(node, Diagnostics.Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
@@ -12445,7 +12726,16 @@ module ts {
|
||||
let identifier = <Identifier>name;
|
||||
if (contextNode && (contextNode.parserContextFlags & ParserContextFlags.StrictMode) && isEvalOrArgumentsIdentifier(identifier)) {
|
||||
let nameText = declarationNameToString(identifier);
|
||||
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
|
||||
|
||||
// We are checking if this name is inside class declaration or class expression (which are under class definitions inside ES6 spec.)
|
||||
// if so, we would like to give more explicit invalid usage error.
|
||||
// This will be particularly helpful in the case of "arguments" as such case is very common mistake.
|
||||
if (getAncestor(name, SyntaxKind.ClassDeclaration) || getAncestor(name, SyntaxKind.ClassExpression)) {
|
||||
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode, nameText);
|
||||
}
|
||||
else {
|
||||
return grammarErrorOnNode(identifier, Diagnostics.Invalid_use_of_0_in_strict_mode, nameText);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,6 +156,11 @@ module ts {
|
||||
shortName: "w",
|
||||
type: "boolean",
|
||||
description: Diagnostics.Watch_input_files,
|
||||
},
|
||||
{
|
||||
name: "emitDecoratorMetadata",
|
||||
type: "boolean",
|
||||
experimental: true
|
||||
}
|
||||
];
|
||||
|
||||
|
||||
@@ -167,7 +167,8 @@ module ts {
|
||||
Decorators_cannot_be_applied_to_multiple_get_Slashset_accessors_of_the_same_name: { code: 1207, category: DiagnosticCategory.Error, key: "Decorators cannot be applied to multiple get/set accessors of the same name." },
|
||||
Cannot_compile_non_external_modules_when_the_separateCompilation_flag_is_provided: { code: 1208, category: DiagnosticCategory.Error, key: "Cannot compile non-external modules when the '--separateCompilation' flag is provided." },
|
||||
Ambient_const_enums_are_not_allowed_when_the_separateCompilation_flag_is_provided: { code: 1209, category: DiagnosticCategory.Error, key: "Ambient const enums are not allowed when the '--separateCompilation' flag is provided." },
|
||||
A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1210, category: DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" },
|
||||
Invalid_use_of_0_Class_definitions_are_automatically_in_strict_mode: { code: 1210, category: DiagnosticCategory.Error, key: "Invalid use of '{0}'. Class definitions are automatically in strict mode." },
|
||||
A_class_declaration_without_the_default_modifier_must_have_a_name: { code: 1211, category: DiagnosticCategory.Error, key: "A class declaration without the 'default' modifier must have a name" },
|
||||
Duplicate_identifier_0: { code: 2300, category: DiagnosticCategory.Error, key: "Duplicate identifier '{0}'." },
|
||||
Initializer_of_instance_member_variable_0_cannot_reference_identifier_1_declared_in_the_constructor: { code: 2301, category: DiagnosticCategory.Error, key: "Initializer of instance member variable '{0}' cannot reference identifier '{1}' declared in the constructor." },
|
||||
Static_members_cannot_reference_class_type_parameters: { code: 2302, category: DiagnosticCategory.Error, key: "Static members cannot reference class type parameters." },
|
||||
|
||||
@@ -659,9 +659,13 @@
|
||||
"category": "Error",
|
||||
"code": 1209
|
||||
},
|
||||
"Invalid use of '{0}'. Class definitions are automatically in strict mode.": {
|
||||
"category": "Error",
|
||||
"code": 1210
|
||||
},
|
||||
"A class declaration without the 'default' modifier must have a name": {
|
||||
"category": "Error",
|
||||
"code": 1210
|
||||
"code": 1211
|
||||
},
|
||||
"Duplicate identifier '{0}'.": {
|
||||
"category": "Error",
|
||||
|
||||
+376
-183
@@ -23,6 +23,33 @@ module ts {
|
||||
// @internal
|
||||
// targetSourceFile is when users only want one file in entire project to be emitted. This is used in compileOnSave feature
|
||||
export function emitFiles(resolver: EmitResolver, host: EmitHost, targetSourceFile: SourceFile): EmitResult {
|
||||
// emit output for the __extends helper function
|
||||
const extendsHelper = `
|
||||
var __extends = this.__extends || function (d, b) {
|
||||
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
|
||||
function __() { this.constructor = d; }
|
||||
__.prototype = b.prototype;
|
||||
d.prototype = new __();
|
||||
};`;
|
||||
|
||||
// emit output for the __decorate helper function
|
||||
const decorateHelper = `
|
||||
var __decorate = this.__decorate || (typeof Reflect === "object" && Reflect.decorate) || function (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);
|
||||
}
|
||||
};`;
|
||||
|
||||
// emit output for the __metadata helper function
|
||||
const metadataHelper = `
|
||||
var __metadata = this.__metadata || (typeof Reflect === "object" && Reflect.metadata) || function () { };`;
|
||||
|
||||
// emit output for the __param helper function
|
||||
const paramHelper = `
|
||||
var __param = this.__param || function(index, decorator) { return function (target, key) { decorator(target, key, index); } };`;
|
||||
|
||||
let compilerOptions = host.getCompilerOptions();
|
||||
let languageVersion = compilerOptions.target || ScriptTarget.ES3;
|
||||
let sourceMapDataList: SourceMapData[] = compilerOptions.sourceMap ? [] : undefined;
|
||||
@@ -98,6 +125,7 @@ module ts {
|
||||
|
||||
let extendsEmitted = false;
|
||||
let decorateEmitted = false;
|
||||
let paramEmitted = false;
|
||||
let tempFlags = 0;
|
||||
let tempVariables: Identifier[];
|
||||
let tempParameters: Identifier[];
|
||||
@@ -769,27 +797,34 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitList(nodes: Node[], start: number, count: number, multiLine: boolean, trailingComma: boolean) {
|
||||
function emitList<TNode extends Node>(nodes: TNode[], start: number, count: number, multiLine: boolean, trailingComma: boolean, leadingComma?: boolean, noTrailingNewLine?: boolean, emitNode?: (node: TNode) => void): number {
|
||||
if (!emitNode) {
|
||||
emitNode = emit;
|
||||
}
|
||||
|
||||
for (let i = 0; i < count; i++) {
|
||||
if (multiLine) {
|
||||
if (i) {
|
||||
if (i || leadingComma) {
|
||||
write(",");
|
||||
}
|
||||
writeLine();
|
||||
}
|
||||
else {
|
||||
if (i) {
|
||||
if (i || leadingComma) {
|
||||
write(", ");
|
||||
}
|
||||
}
|
||||
emit(nodes[start + i]);
|
||||
emitNode(nodes[start + i]);
|
||||
leadingComma = true;
|
||||
}
|
||||
if (trailingComma) {
|
||||
write(",");
|
||||
}
|
||||
if (multiLine) {
|
||||
if (multiLine && !noTrailingNewLine) {
|
||||
writeLine();
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
function emitCommaList(nodes: Node[]) {
|
||||
@@ -1109,9 +1144,7 @@ module ts {
|
||||
return;
|
||||
}
|
||||
|
||||
let generatedVariable = createTempVariable(TempFlags.Auto);
|
||||
generatedName = generatedVariable.text;
|
||||
recordTempDeclaration(generatedVariable);
|
||||
generatedName = createAndRecordTempVariable(TempFlags.Auto).text;
|
||||
computedPropertyNamesToGeneratedNames[node.id] = generatedName;
|
||||
write(generatedName);
|
||||
write(" = ");
|
||||
@@ -3199,28 +3232,49 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
function emitMemberAssignments(node: ClassLikeDeclaration, staticFlag: NodeFlags) {
|
||||
forEach(node.members, member => {
|
||||
if (member.kind === SyntaxKind.PropertyDeclaration && (member.flags & NodeFlags.Static) === staticFlag && (<PropertyDeclaration>member).initializer) {
|
||||
writeLine();
|
||||
emitLeadingComments(member);
|
||||
emitStart(member);
|
||||
emitStart((<PropertyDeclaration>member).name);
|
||||
if (staticFlag) {
|
||||
emitDeclarationName(node);
|
||||
}
|
||||
else {
|
||||
write("this");
|
||||
}
|
||||
emitMemberAccessForPropertyName((<PropertyDeclaration>member).name);
|
||||
emitEnd((<PropertyDeclaration>member).name);
|
||||
write(" = ");
|
||||
emit((<PropertyDeclaration>member).initializer);
|
||||
write(";");
|
||||
emitEnd(member);
|
||||
emitTrailingComments(member);
|
||||
function getInitializedProperties(node: ClassLikeDeclaration, static: boolean) {
|
||||
let properties: PropertyDeclaration[] = [];
|
||||
for (let member of node.members) {
|
||||
if (member.kind === SyntaxKind.PropertyDeclaration && static === ((member.flags & NodeFlags.Static) !== 0) && (<PropertyDeclaration>member).initializer) {
|
||||
properties.push(<PropertyDeclaration>member);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return properties;
|
||||
}
|
||||
|
||||
function emitPropertyDeclarations(node: ClassLikeDeclaration, properties: PropertyDeclaration[]) {
|
||||
for (let property of properties) {
|
||||
emitPropertyDeclaration(node, property);
|
||||
}
|
||||
}
|
||||
|
||||
function emitPropertyDeclaration(node: ClassLikeDeclaration, property: PropertyDeclaration, receiver?: Identifier, isExpression?: boolean) {
|
||||
writeLine();
|
||||
emitLeadingComments(property);
|
||||
emitStart(property);
|
||||
emitStart(property.name);
|
||||
if (receiver) {
|
||||
emit(receiver);
|
||||
}
|
||||
else {
|
||||
if (property.flags & NodeFlags.Static) {
|
||||
emitDeclarationName(node);
|
||||
}
|
||||
else {
|
||||
write("this");
|
||||
}
|
||||
}
|
||||
emitMemberAccessForPropertyName(property.name);
|
||||
emitEnd(property.name);
|
||||
write(" = ");
|
||||
emit(property.initializer);
|
||||
if (!isExpression) {
|
||||
write(";");
|
||||
}
|
||||
|
||||
emitEnd(property);
|
||||
emitTrailingComments(property);
|
||||
}
|
||||
|
||||
function emitMemberFunctionsForES5AndLower(node: ClassLikeDeclaration) {
|
||||
@@ -3338,6 +3392,14 @@ module ts {
|
||||
tempVariables = undefined;
|
||||
tempParameters = undefined;
|
||||
|
||||
emitConstructorWorker(node, baseTypeElement);
|
||||
|
||||
tempFlags = saveTempFlags;
|
||||
tempVariables = saveTempVariables;
|
||||
tempParameters = saveTempParameters;
|
||||
}
|
||||
|
||||
function emitConstructorWorker(node: ClassLikeDeclaration, baseTypeElement: HeritageClauseElement) {
|
||||
// Check if we have property assignment inside class declaration.
|
||||
// If there is property assignment, we need to emit constructor whether users define it or not
|
||||
// If there is no property assignment, we can omit constructor if users do not define it
|
||||
@@ -3425,7 +3487,7 @@ module ts {
|
||||
emitEnd(baseTypeElement);
|
||||
}
|
||||
}
|
||||
emitMemberAssignments(node, /*staticFlag*/0);
|
||||
emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ false));
|
||||
if (ctor) {
|
||||
var statements: Node[] = (<Block>ctor.body).statements;
|
||||
if (superCall) {
|
||||
@@ -3445,10 +3507,6 @@ module ts {
|
||||
if (ctor) {
|
||||
emitTrailingComments(ctor);
|
||||
}
|
||||
|
||||
tempFlags = saveTempFlags;
|
||||
tempVariables = saveTempVariables;
|
||||
tempParameters = saveTempParameters;
|
||||
}
|
||||
|
||||
function emitClassExpression(node: ClassExpression) {
|
||||
@@ -3540,6 +3598,29 @@ module ts {
|
||||
}
|
||||
}
|
||||
|
||||
// If the class has static properties, and it's a class expression, then we'll need
|
||||
// to specialize the emit a bit. for a class expression of the form:
|
||||
//
|
||||
// class C { static a = 1; static b = 2; ... }
|
||||
//
|
||||
// We'll emit:
|
||||
//
|
||||
// (_temp = class C { ... }, _temp.a = 1, _temp.b = 2, _temp)
|
||||
//
|
||||
// This keeps the expression as an expression, while ensuring that the static parts
|
||||
// of it have been initialized by the time it is used.
|
||||
let staticProperties = getInitializedProperties(node, /*static:*/ true);
|
||||
let isClassExpressionWithStaticProperties = staticProperties.length > 0 && node.kind === SyntaxKind.ClassExpression;
|
||||
let tempVariable: Identifier;
|
||||
|
||||
if (isClassExpressionWithStaticProperties) {
|
||||
tempVariable = createAndRecordTempVariable(TempFlags.Auto);
|
||||
write("(");
|
||||
increaseIndent();
|
||||
emit(tempVariable);
|
||||
write(" = ")
|
||||
}
|
||||
|
||||
write("class");
|
||||
|
||||
// check if this is an "export default class" as it may not have a name. Do not emit the name if the class is decorated.
|
||||
@@ -3590,9 +3671,24 @@ module ts {
|
||||
// From ES6 specification:
|
||||
// HasLexicalDeclaration (N) : Determines if the argument identifier has a binding in this environment record that was created using
|
||||
// a lexical declaration such as a LexicalDeclaration or a ClassDeclaration.
|
||||
writeLine();
|
||||
emitMemberAssignments(node, NodeFlags.Static);
|
||||
emitDecoratorsOfClass(node);
|
||||
|
||||
if (isClassExpressionWithStaticProperties) {
|
||||
for (var property of staticProperties) {
|
||||
write(",");
|
||||
writeLine();
|
||||
emitPropertyDeclaration(node, property, /*receiver:*/ tempVariable, /*isExpression:*/ true);
|
||||
}
|
||||
write(",");
|
||||
writeLine();
|
||||
emit(tempVariable);
|
||||
decreaseIndent();
|
||||
write(")");
|
||||
}
|
||||
else {
|
||||
writeLine();
|
||||
emitPropertyDeclarations(node, staticProperties);
|
||||
emitDecoratorsOfClass(node);
|
||||
}
|
||||
|
||||
// If this is an exported class, but not on the top level (i.e. on an internal
|
||||
// module), export it
|
||||
@@ -3648,7 +3744,7 @@ module ts {
|
||||
writeLine();
|
||||
emitConstructor(node, baseTypeNode);
|
||||
emitMemberFunctionsForES5AndLower(node);
|
||||
emitMemberAssignments(node, NodeFlags.Static);
|
||||
emitPropertyDeclarations(node, getInitializedProperties(node, /*static:*/ true));
|
||||
writeLine();
|
||||
emitDecoratorsOfClass(node);
|
||||
writeLine();
|
||||
@@ -3700,12 +3796,12 @@ module ts {
|
||||
}
|
||||
|
||||
function emitDecoratorsOfConstructor(node: ClassLikeDeclaration) {
|
||||
let decorators = node.decorators;
|
||||
let constructor = getFirstConstructorWithBody(node);
|
||||
if (constructor) {
|
||||
emitDecoratorsOfParameters(node, constructor);
|
||||
}
|
||||
let hasDecoratedParameters = constructor && forEach(constructor.parameters, nodeIsDecorated);
|
||||
|
||||
if (!nodeIsDecorated(node)) {
|
||||
// skip decoration of the constructor if neither it nor its parameters are decorated
|
||||
if (!decorators && !hasDecoratedParameters) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -3723,8 +3819,23 @@ module ts {
|
||||
writeLine();
|
||||
emitStart(node);
|
||||
emitDeclarationName(node);
|
||||
write(" = ");
|
||||
emitDecorateStart(node.decorators);
|
||||
write(" = __decorate([");
|
||||
increaseIndent();
|
||||
writeLine();
|
||||
|
||||
let decoratorCount = decorators ? decorators.length : 0;
|
||||
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
|
||||
emitStart(decorator);
|
||||
emit(decorator.expression);
|
||||
emitEnd(decorator);
|
||||
});
|
||||
|
||||
argumentsWritten += emitDecoratorsOfParameters(constructor, /*leadingComma*/ argumentsWritten > 0);
|
||||
emitSerializedTypeMetadata(node, /*leadingComma*/ argumentsWritten >= 0);
|
||||
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("], ");
|
||||
emitDeclarationName(node);
|
||||
write(");");
|
||||
emitEnd(node);
|
||||
@@ -3732,72 +3843,80 @@ module ts {
|
||||
}
|
||||
|
||||
function emitDecoratorsOfMembers(node: ClassLikeDeclaration, staticFlag: NodeFlags) {
|
||||
forEach(node.members, member => {
|
||||
for (let member of node.members) {
|
||||
// only emit members in the correct group
|
||||
if ((member.flags & NodeFlags.Static) !== staticFlag) {
|
||||
return;
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip members that cannot be decorated (such as the constructor)
|
||||
if (!nodeCanBeDecorated(member)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip a member if it or any of its parameters are not decorated
|
||||
if (!nodeOrChildIsDecorated(member)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// skip an accessor declaration if it is not the first accessor
|
||||
let decorators: NodeArray<Decorator>;
|
||||
switch (member.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
// emit decorators of the method's parameters
|
||||
emitDecoratorsOfParameters(node, <MethodDeclaration>member);
|
||||
decorators = member.decorators;
|
||||
break;
|
||||
let functionLikeMember: FunctionLikeDeclaration;
|
||||
if (isAccessor(member)) {
|
||||
let accessors = getAllAccessorDeclarations(node.members, <AccessorDeclaration>member);
|
||||
if (member !== accessors.firstAccessor) {
|
||||
continue;
|
||||
}
|
||||
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
let accessors = getAllAccessorDeclarations(node.members, <AccessorDeclaration>member);
|
||||
if (member !== accessors.firstAccessor) {
|
||||
// skip the second accessor as we processed it with the first.
|
||||
return;
|
||||
}
|
||||
// get the decorators from the first accessor with decorators
|
||||
decorators = accessors.firstAccessor.decorators;
|
||||
if (!decorators && accessors.secondAccessor) {
|
||||
decorators = accessors.secondAccessor.decorators;
|
||||
}
|
||||
|
||||
if (accessors.setAccessor) {
|
||||
// emit decorators of the set accessor parameter
|
||||
emitDecoratorsOfParameters(node, <AccessorDeclaration>accessors.setAccessor);
|
||||
}
|
||||
|
||||
// get the decorators from the first decorated accessor.
|
||||
decorators = accessors.firstAccessor.decorators;
|
||||
if (!decorators && accessors.secondAccessor) {
|
||||
decorators = accessors.secondAccessor.decorators;
|
||||
}
|
||||
break;
|
||||
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
decorators = member.decorators;
|
||||
break;
|
||||
|
||||
default:
|
||||
// Constructor cannot be decorated, and its parameters are handled in emitDecoratorsOfConstructor
|
||||
// Other members (i.e. IndexSignature) cannot be decorated.
|
||||
return;
|
||||
// we only decorate parameters of the set accessor
|
||||
functionLikeMember = accessors.setAccessor;
|
||||
}
|
||||
else {
|
||||
decorators = member.decorators;
|
||||
|
||||
if (!decorators) {
|
||||
return;
|
||||
// we only decorate the parameters here if this is a method
|
||||
if (member.kind === SyntaxKind.MethodDeclaration) {
|
||||
functionLikeMember = <MethodDeclaration>member;
|
||||
}
|
||||
}
|
||||
|
||||
// Emit the call to __decorate. Given the following:
|
||||
//
|
||||
// class C {
|
||||
// @dec method() {}
|
||||
// @dec method(@dec2 x) {}
|
||||
// @dec get accessor() {}
|
||||
// @dec prop;
|
||||
// }
|
||||
//
|
||||
// The emit for a method is:
|
||||
//
|
||||
// Object.defineProperty(C.prototype, "method", __decorate([dec], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
|
||||
// Object.defineProperty(C.prototype, "method",
|
||||
// __decorate([
|
||||
// dec,
|
||||
// __param(0, dec2),
|
||||
// __metadata("design:type", Function),
|
||||
// __metadata("design:paramtypes", [Object]),
|
||||
// __metadata("design:returntype", void 0)
|
||||
// ], C.prototype, "method", Object.getOwnPropertyDescriptor(C.prototype, "method")));
|
||||
//
|
||||
// The emit for an accessor is:
|
||||
//
|
||||
// Object.defineProperty(C.prototype, "accessor", __decorate([dec], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor")));
|
||||
// Object.defineProperty(C.prototype, "accessor",
|
||||
// __decorate([
|
||||
// dec
|
||||
// ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor")));
|
||||
//
|
||||
// The emit for a property is:
|
||||
//
|
||||
// __decorate([dec], C.prototype, "prop");
|
||||
// __decorate([
|
||||
// dec
|
||||
// ], C.prototype, "prop");
|
||||
//
|
||||
|
||||
writeLine();
|
||||
@@ -3809,10 +3928,28 @@ module ts {
|
||||
write(", ");
|
||||
emitExpressionForPropertyName(member.name);
|
||||
emitEnd(member.name);
|
||||
write(", ");
|
||||
write(",");
|
||||
increaseIndent();
|
||||
writeLine();
|
||||
}
|
||||
|
||||
emitDecorateStart(decorators);
|
||||
write("__decorate([");
|
||||
increaseIndent();
|
||||
writeLine();
|
||||
|
||||
let decoratorCount = decorators ? decorators.length : 0;
|
||||
let argumentsWritten = emitList(decorators, 0, decoratorCount, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ false, /*noTrailingNewLine*/ true, decorator => {
|
||||
emitStart(decorator);
|
||||
emit(decorator.expression);
|
||||
emitEnd(decorator);
|
||||
});
|
||||
|
||||
argumentsWritten += emitDecoratorsOfParameters(functionLikeMember, argumentsWritten > 0);
|
||||
emitSerializedTypeMetadata(member, argumentsWritten > 0);
|
||||
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("], ");
|
||||
emitStart(member.name);
|
||||
emitClassMemberPrefix(node, member);
|
||||
write(", ");
|
||||
@@ -3827,78 +3964,150 @@ module ts {
|
||||
emitExpressionForPropertyName(member.name);
|
||||
emitEnd(member.name);
|
||||
write("))");
|
||||
decreaseIndent();
|
||||
}
|
||||
|
||||
write(");");
|
||||
emitEnd(member);
|
||||
writeLine();
|
||||
});
|
||||
}
|
||||
|
||||
function emitDecoratorsOfParameters(node: ClassLikeDeclaration, member: FunctionLikeDeclaration) {
|
||||
forEach(member.parameters, (parameter, parameterIndex) => {
|
||||
if (!nodeIsDecorated(parameter)) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Emit the decorators for a parameter. Given the following:
|
||||
//
|
||||
// class C {
|
||||
// constructor(@dec p) { }
|
||||
// method(@dec p) { }
|
||||
// set accessor(@dec value) { }
|
||||
// }
|
||||
//
|
||||
// The emit for a constructor is:
|
||||
//
|
||||
// __decorate([dec], C, void 0, 0);
|
||||
//
|
||||
// The emit for a parameter is:
|
||||
//
|
||||
// __decorate([dec], C.prototype, "method", 0);
|
||||
//
|
||||
// The emit for an accessor is:
|
||||
//
|
||||
// __decorate([dec], C.prototype, "accessor", 0);
|
||||
//
|
||||
|
||||
writeLine();
|
||||
emitStart(parameter);
|
||||
emitDecorateStart(parameter.decorators);
|
||||
emitStart(parameter.name);
|
||||
|
||||
if (member.kind === SyntaxKind.Constructor) {
|
||||
emitDeclarationName(node);
|
||||
write(", void 0");
|
||||
}
|
||||
else {
|
||||
emitClassMemberPrefix(node, member);
|
||||
write(", ");
|
||||
emitExpressionForPropertyName(member.name);
|
||||
}
|
||||
|
||||
write(", ");
|
||||
write(String(parameterIndex));
|
||||
emitEnd(parameter.name);
|
||||
write(");");
|
||||
emitEnd(parameter);
|
||||
writeLine();
|
||||
});
|
||||
}
|
||||
|
||||
function emitDecorateStart(decorators: Decorator[]): void {
|
||||
write("__decorate([");
|
||||
let decoratorCount = decorators.length;
|
||||
for (let i = 0; i < decoratorCount; i++) {
|
||||
if (i > 0) {
|
||||
write(", ");
|
||||
}
|
||||
let decorator = decorators[i];
|
||||
emitStart(decorator);
|
||||
emit(decorator.expression);
|
||||
emitEnd(decorator);
|
||||
}
|
||||
write("], ");
|
||||
}
|
||||
|
||||
function emitDecoratorsOfParameters(node: FunctionLikeDeclaration, leadingComma: boolean): number {
|
||||
let argumentsWritten = 0;
|
||||
if (node) {
|
||||
let parameterIndex = 0;
|
||||
for (let parameter of node.parameters) {
|
||||
if (nodeIsDecorated(parameter)) {
|
||||
let decorators = parameter.decorators;
|
||||
argumentsWritten += emitList(decorators, 0, decorators.length, /*multiLine*/ true, /*trailingComma*/ false, /*leadingComma*/ leadingComma, /*noTrailingNewLine*/ true, decorator => {
|
||||
emitStart(decorator);
|
||||
write(`__param(${parameterIndex}, `);
|
||||
emit(decorator.expression);
|
||||
write(")");
|
||||
emitEnd(decorator);
|
||||
});
|
||||
leadingComma = true;
|
||||
}
|
||||
++parameterIndex;
|
||||
}
|
||||
}
|
||||
return argumentsWritten;
|
||||
}
|
||||
|
||||
function shouldEmitTypeMetadata(node: Declaration): boolean {
|
||||
// This method determines whether to emit the "design:type" metadata based on the node's kind.
|
||||
// The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata
|
||||
// compiler option is set.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
case SyntaxKind.PropertyDeclaration:
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
function shouldEmitReturnTypeMetadata(node: Declaration): boolean {
|
||||
// This method determines whether to emit the "design:returntype" metadata based on the node's kind.
|
||||
// The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata
|
||||
// compiler option is set.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function shouldEmitParamTypesMetadata(node: Declaration): boolean {
|
||||
// This method determines whether to emit the "design:paramtypes" metadata based on the node's kind.
|
||||
// The caller should have already tested whether the node has decorators and whether the emitDecoratorMetadata
|
||||
// compiler option is set.
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.ClassDeclaration:
|
||||
case SyntaxKind.MethodDeclaration:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function emitSerializedTypeMetadata(node: Declaration, writeComma: boolean): number {
|
||||
// This method emits the serialized type metadata for a decorator target.
|
||||
// The caller should have already tested whether the node has decorators.
|
||||
let argumentsWritten = 0;
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
if (shouldEmitTypeMetadata(node)) {
|
||||
var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode);
|
||||
if (serializedType) {
|
||||
if (writeComma) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:type', ");
|
||||
emitSerializedType(node, serializedType);
|
||||
write(")");
|
||||
argumentsWritten++;
|
||||
}
|
||||
}
|
||||
if (shouldEmitParamTypesMetadata(node)) {
|
||||
var serializedTypes = resolver.serializeParameterTypesOfNode(node, getGeneratedNameForNode);
|
||||
if (serializedTypes) {
|
||||
if (writeComma || argumentsWritten) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:paramtypes', [");
|
||||
for (var i = 0; i < serializedTypes.length; ++i) {
|
||||
if (i > 0) {
|
||||
write(", ");
|
||||
}
|
||||
emitSerializedType(node, serializedTypes[i]);
|
||||
}
|
||||
write("])");
|
||||
argumentsWritten++;
|
||||
}
|
||||
}
|
||||
if (shouldEmitReturnTypeMetadata(node)) {
|
||||
var serializedType = resolver.serializeReturnTypeOfNode(node, getGeneratedNameForNode);
|
||||
if (serializedType) {
|
||||
if (writeComma || argumentsWritten) {
|
||||
write(", ");
|
||||
}
|
||||
writeLine();
|
||||
write("__metadata('design:returntype', ");
|
||||
emitSerializedType(node, serializedType);
|
||||
write(")");
|
||||
argumentsWritten++;
|
||||
}
|
||||
}
|
||||
}
|
||||
return argumentsWritten;
|
||||
}
|
||||
|
||||
function serializeTypeNameSegment(location: Node, path: string[], index: number): string {
|
||||
switch (index) {
|
||||
case 0:
|
||||
return `typeof ${path[index]} !== 'undefined' && ${path[index]}`;
|
||||
case 1:
|
||||
return `${serializeTypeNameSegment(location, path, index - 1) }.${path[index]}`;
|
||||
default:
|
||||
let temp = createAndRecordTempVariable(TempFlags.Auto).text;
|
||||
return `(${temp} = ${serializeTypeNameSegment(location, path, index - 1) }) && ${temp}.${path[index]}`;
|
||||
}
|
||||
}
|
||||
|
||||
function emitSerializedType(location: Node, name: string | string[]): void {
|
||||
if (typeof name === "string") {
|
||||
write(name);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
Debug.assert(name.length > 0, "Invalid serialized type name");
|
||||
write(`(${serializeTypeNameSegment(location, name, name.length - 1) }) || Object`);
|
||||
}
|
||||
}
|
||||
|
||||
function emitInterfaceDeclaration(node: InterfaceDeclaration) {
|
||||
@@ -4531,7 +4740,7 @@ module ts {
|
||||
return statements.length;
|
||||
}
|
||||
|
||||
function writeHelper(text: string): void {
|
||||
function writeLines(text: string): void {
|
||||
let lines = text.split(/\r\n|\r|\n/g);
|
||||
for (let i = 0; i < lines.length; ++i) {
|
||||
let line = lines[i];
|
||||
@@ -4550,41 +4759,25 @@ module ts {
|
||||
// emit prologue directives prior to __extends
|
||||
var startIndex = emitDirectivePrologues(node.statements, /*startWithNewLine*/ false);
|
||||
// Only Emit __extends function when target ES5.
|
||||
// For target ES6 and above, we can emit classDeclaration as if.
|
||||
// For target ES6 and above, we can emit classDeclaration as is.
|
||||
if ((languageVersion < ScriptTarget.ES6) && (!extendsEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitExtends)) {
|
||||
writeLine();
|
||||
write("var __extends = this.__extends || function (d, b) {");
|
||||
increaseIndent();
|
||||
writeLine();
|
||||
write("for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];");
|
||||
writeLine();
|
||||
write("function __() { this.constructor = d; }");
|
||||
writeLine();
|
||||
write("__.prototype = b.prototype;");
|
||||
writeLine();
|
||||
write("d.prototype = new __();");
|
||||
decreaseIndent();
|
||||
writeLine();
|
||||
write("};");
|
||||
writeLines(extendsHelper);
|
||||
extendsEmitted = true;
|
||||
}
|
||||
|
||||
if (!decorateEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitDecorate) {
|
||||
writeHelper(`
|
||||
var __decorate = this.__decorate || function (decorators, target, key, value) {
|
||||
var kind = typeof (arguments.length == 2 ? value = target : value);
|
||||
for (var i = decorators.length - 1; i >= 0; --i) {
|
||||
var decorator = decorators[i];
|
||||
switch (kind) {
|
||||
case "function": value = decorator(value) || value; break;
|
||||
case "number": decorator(target, key, value); break;
|
||||
case "undefined": decorator(target, key); break;
|
||||
case "object": value = decorator(target, key, value) || value; break;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
};`);
|
||||
writeLines(decorateHelper);
|
||||
if (compilerOptions.emitDecoratorMetadata) {
|
||||
writeLines(metadataHelper);
|
||||
}
|
||||
decorateEmitted = true;
|
||||
}
|
||||
|
||||
if (!paramEmitted && resolver.getNodeCheckFlags(node) & NodeCheckFlags.EmitParam) {
|
||||
writeLines(paramHelper);
|
||||
paramEmitted = true;
|
||||
}
|
||||
|
||||
if (isExternalModule(node)) {
|
||||
if (languageVersion >= ScriptTarget.ES6) {
|
||||
emitES6Module(node, startIndex);
|
||||
|
||||
@@ -4756,9 +4756,7 @@ module ts {
|
||||
function parseClassDeclarationOrExpression(fullStart: number, decorators: NodeArray<Decorator>, modifiers: ModifiersArray, kind: SyntaxKind): ClassLikeDeclaration {
|
||||
// In ES6 specification, All parts of a ClassDeclaration or a ClassExpression are strict mode code
|
||||
let savedStrictModeContext = inStrictModeContext();
|
||||
if (languageVersion >= ScriptTarget.ES6) {
|
||||
setStrictModeContext(true);
|
||||
}
|
||||
setStrictModeContext(true);
|
||||
|
||||
var node = <ClassLikeDeclaration>createNode(kind, fullStart);
|
||||
node.decorators = decorators;
|
||||
|
||||
@@ -1255,6 +1255,9 @@ module ts {
|
||||
getConstantValue(node: EnumMember | PropertyAccessExpression | ElementAccessExpression): number;
|
||||
resolvesToSomeValue(location: Node, name: string): boolean;
|
||||
getBlockScopedVariableId(node: Identifier): number;
|
||||
serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[];
|
||||
serializeParameterTypesOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): (string | string[])[];
|
||||
serializeReturnTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[];
|
||||
}
|
||||
|
||||
export const enum SymbolFlags {
|
||||
@@ -1380,6 +1383,7 @@ module ts {
|
||||
EnumValuesComputed = 0x00000080,
|
||||
BlockScopedBindingInLoop = 0x00000100,
|
||||
EmitDecorate = 0x00000200, // Emit __decorate
|
||||
EmitParam = 0x00000400, // Emit __param helper for decorators
|
||||
}
|
||||
|
||||
export interface NodeLinks {
|
||||
@@ -1605,6 +1609,7 @@ module ts {
|
||||
version?: boolean;
|
||||
watch?: boolean;
|
||||
separateCompilation?: boolean;
|
||||
emitDecoratorMetadata?: boolean;
|
||||
/* @internal */ stripInternal?: boolean;
|
||||
[option: string]: string | number | boolean;
|
||||
}
|
||||
|
||||
@@ -449,6 +449,18 @@ module ts {
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isAccessor(node: Node): boolean {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
case SyntaxKind.GetAccessor:
|
||||
case SyntaxKind.SetAccessor:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
export function isFunctionLike(node: Node): boolean {
|
||||
if (node) {
|
||||
switch (node.kind) {
|
||||
|
||||
Vendored
+1
-1
@@ -1168,4 +1168,4 @@ interface TypedPropertyDescriptor<T> {
|
||||
declare type ClassDecorator = <TFunction extends Function>(target: TFunction) => TFunction | void;
|
||||
declare type PropertyDecorator = (target: Object, propertyKey: string | symbol) => void;
|
||||
declare type MethodDecorator = <T>(target: Object, propertyKey: string | symbol, descriptor: TypedPropertyDescriptor<T>) => TypedPropertyDescriptor<T> | void;
|
||||
declare type ParameterDecorator = (target: Function, propertyKey: string | symbol, parameterIndex: number) => void;
|
||||
declare type ParameterDecorator = (target: Object, propertyKey: string | symbol, parameterIndex: number) => void;
|
||||
|
||||
Vendored
+18
-18
@@ -3513,27 +3513,27 @@ interface ProxyHandler<T> {
|
||||
|
||||
interface ProxyConstructor {
|
||||
revocable<T>(target: T, handler: ProxyHandler<T>): { proxy: T; revoke: () => void; };
|
||||
new <T>(target: T, handeler: ProxyHandler<T>): T
|
||||
new <T>(target: T, handler: ProxyHandler<T>): T
|
||||
}
|
||||
declare var Proxy: ProxyConstructor;
|
||||
|
||||
declare var Reflect: {
|
||||
apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;
|
||||
construct(target: Function, argumentsList: ArrayLike<any>): any;
|
||||
defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean;
|
||||
deleteProperty(target: any, propertyKey: PropertyKey): boolean;
|
||||
enumerate(target: any): IterableIterator<any>;
|
||||
get(target: any, propertyKey: PropertyKey, receiver?: any): any;
|
||||
getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor;
|
||||
getPrototypeOf(target: any): any;
|
||||
has(target: any, propertyKey: string): boolean;
|
||||
has(target: any, propertyKey: symbol): boolean;
|
||||
isExtensible(target: any): boolean;
|
||||
ownKeys(target: any): Array<PropertyKey>;
|
||||
preventExtensions(target: any): boolean;
|
||||
set(target: any, propertyKey: PropertyKey, value: any, receiver? :any): boolean;
|
||||
setPrototypeOf(target: any, proto: any): boolean;
|
||||
};
|
||||
declare module Reflect {
|
||||
function apply(target: Function, thisArgument: any, argumentsList: ArrayLike<any>): any;
|
||||
function construct(target: Function, argumentsList: ArrayLike<any>): any;
|
||||
function defineProperty(target: any, propertyKey: PropertyKey, attributes: PropertyDescriptor): boolean;
|
||||
function deleteProperty(target: any, propertyKey: PropertyKey): boolean;
|
||||
function enumerate(target: any): IterableIterator<any>;
|
||||
function get(target: any, propertyKey: PropertyKey, receiver?: any): any;
|
||||
function getOwnPropertyDescriptor(target: any, propertyKey: PropertyKey): PropertyDescriptor;
|
||||
function getPrototypeOf(target: any): any;
|
||||
function has(target: any, propertyKey: string): boolean;
|
||||
function has(target: any, propertyKey: symbol): boolean;
|
||||
function isExtensible(target: any): boolean;
|
||||
function ownKeys(target: any): Array<PropertyKey>;
|
||||
function preventExtensions(target: any): boolean;
|
||||
function set(target: any, propertyKey: PropertyKey, value: any, receiver? :any): boolean;
|
||||
function setPrototypeOf(target: any, proto: any): boolean;
|
||||
}
|
||||
|
||||
/**
|
||||
* Represents the completion of an asynchronous operation
|
||||
|
||||
@@ -68,12 +68,12 @@ module ts.server {
|
||||
};
|
||||
}
|
||||
|
||||
private processRequest<T extends protocol.Request>(command: string, arguments?: any): T {
|
||||
private processRequest<T extends protocol.Request>(command: string, args?: any): T {
|
||||
var request: protocol.Request = {
|
||||
seq: this.sequence++,
|
||||
type: "request",
|
||||
command: command,
|
||||
arguments: arguments
|
||||
arguments: args,
|
||||
command
|
||||
};
|
||||
|
||||
this.writeMessage(JSON.stringify(request));
|
||||
|
||||
Reference in New Issue
Block a user