diff --git a/bin/typescriptServices.d.ts b/bin/typescriptServices.d.ts index 3114c56b789b8..20f26d1179b76 100644 --- a/bin/typescriptServices.d.ts +++ b/bin/typescriptServices.d.ts @@ -1116,6 +1116,8 @@ declare module ts { watch?: boolean; separateCompilation?: boolean; emitDecoratorMetadata?: boolean; + emitVerboseMetadata?: boolean; + skipEmitVarForModule?: boolean; [option: string]: string | number | boolean; } const enum ModuleKind { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 9d81e3f35ac1f..3cae25e3d5279 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -446,7 +446,7 @@ module ts { } break; case SyntaxKind.Decorator: - // Decorators are resolved at the class declaration. Resolving at the parameter + // Decorators are resolved at the class declaration. Resolving at the parameter // or member would result in looking up locals in the method. // // function y() {} @@ -803,9 +803,7 @@ module ts { let symbol: Symbol; if (name.kind === SyntaxKind.Identifier) { - let message = meaning === SymbolFlags.Namespace ? Diagnostics.Cannot_find_namespace_0 : Diagnostics.Cannot_find_name_0; - - symbol = resolveName(name, (name).text, meaning, message, name); + symbol = resolveName(name, (name).text, meaning, Diagnostics.Cannot_find_name_0, name); if (!symbol) { return undefined; } @@ -857,11 +855,10 @@ module ts { return symbol; } } - let fileName: string; let sourceFile: SourceFile; while (true) { - fileName = normalizePath(combinePaths(searchPath, moduleName)); - sourceFile = forEach(supportedExtensions, extension => host.getSourceFile(fileName + extension)); + let fileName = normalizePath(combinePaths(searchPath, moduleName)); + sourceFile = host.getSourceFile(fileName + ".ts") || host.getSourceFile(fileName + ".d.ts"); if (sourceFile || isRelative) { break; } @@ -1954,7 +1951,7 @@ module ts { case SyntaxKind.ParenthesizedType: return isDeclarationVisible(node.parent); - // Default binding, import specifier and namespace import is visible + // Default binding, import specifier and namespace import is visible // only on demand so by default it is not visible case SyntaxKind.ImportClause: case SyntaxKind.NamespaceImport: @@ -5385,43 +5382,20 @@ module ts { if (!isTypeSubtypeOf(rightType, globalFunctionType)) { return type; } - - let targetType: Type; + // Target type is type of prototype property let prototypeProperty = getPropertyOfType(rightType, "prototype"); - if (prototypeProperty) { - // Target type is type of the protoype property - let prototypePropertyType = getTypeOfSymbol(prototypeProperty); - if (prototypePropertyType !== anyType) { - targetType = prototypePropertyType; - } + if (!prototypeProperty) { + return type; } - - if (!targetType) { - // Target type is type of construct signature - let constructSignatures: Signature[]; - if (rightType.flags & TypeFlags.Interface) { - constructSignatures = resolveDeclaredMembers(rightType).declaredConstructSignatures; - } - else if (rightType.flags & TypeFlags.Anonymous) { - constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct); - } - - if (constructSignatures && constructSignatures.length) { - targetType = getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature)))); - } + let targetType = getTypeOfSymbol(prototypeProperty); + // Narrow to target type if it is a subtype of current type + if (isTypeSubtypeOf(targetType, type)) { + return targetType; } - - if (targetType) { - // Narrow to the target type if it's a subtype of the current type - if (isTypeSubtypeOf(targetType, type)) { - return targetType; - } - // If the current type is a union type, remove all constituents that aren't subtypes of the target. - if (type.flags & TypeFlags.Union) { - return getUnionType(filter((type).types, t => isTypeSubtypeOf(t, targetType))); - } + // If current type is a union type, remove all constituents that aren't subtypes of target type + if (type.flags & TypeFlags.Union) { + return getUnionType(filter((type).types, t => isTypeSubtypeOf(t, targetType))); } - return type; } @@ -6089,7 +6063,7 @@ module ts { // c is represented in the tree as a spread element in an array literal. // But c really functions as a rest element, and its purpose is to provide // a contextual type for the right hand side of the assignment. Therefore, - // instead of calling checkExpression on "...c", which will give an error + // instead of calling checkExpression on "...c", which will give an error // if c is not iterable/array-like, we need to act as if we are trying to // get the contextual element type from it. So we do something similar to // getContextualTypeForElementExpression, which will crucially not error @@ -6097,7 +6071,7 @@ module ts { let restArrayType = checkExpression((e).expression, contextualMapper); let restElementType = getIndexTypeOfType(restArrayType, IndexKind.Number) || (languageVersion >= ScriptTarget.ES6 ? checkIteratedType(restArrayType, /*expressionForError*/ undefined) : undefined); - + if (restElementType) { elementTypes.push(restElementType); } @@ -6998,7 +6972,7 @@ module ts { if (!hasCorrectArity(node, args, originalCandidate)) { continue; } - + let candidate: Signature; let typeArgumentsAreValid: boolean; let inferenceContext = originalCandidate.typeParameters @@ -8195,7 +8169,7 @@ module ts { if (node.questionToken && isBindingPattern(node.name) && func.body) { error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature); } - + // Only check rest parameter type if it's not a binding pattern. Since binding patterns are // not allowed in a rest parameter, we already have an error from checkGrammarParameterList. if (node.dotDotDotToken && !isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) { @@ -8863,7 +8837,7 @@ module ts { /** Checks a type reference node as an expression. */ function checkTypeNodeAsExpression(node: TypeNode) { // 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 + // 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 = getTypeFromTypeNode(node); @@ -8878,7 +8852,7 @@ module ts { } /** - * Checks the type annotation of an accessor declaration or property declaration as + * 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) { @@ -8900,7 +8874,7 @@ module ts { 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 @@ -9513,7 +9487,7 @@ module ts { if (allowStringInput) { return checkElementTypeOfArrayOrString(inputType, errorNode); } - + if (isArrayLikeType(inputType)) { let indexType = getIndexTypeOfType(inputType, IndexKind.Number); if (indexType) { @@ -10550,9 +10524,9 @@ module ts { } } - // if the module merges with a class declaration in the same lexical scope, + // if the module merges with a class declaration in the same lexical scope, // we need to track this to ensure the correct emit. - let mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration); + let mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration); if (mergedClass && inSameLexicalScope(node, mergedClass)) { getNodeLinks(node).flags |= NodeCheckFlags.LexicalModuleMergesWithClass; @@ -11713,6 +11687,7 @@ module ts { /** 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) { + //getResolvedSymbol(node); var substitution = getExpressionNameSubstitution(node, getGeneratedNameForNode); var text = substitution || (node).text; if (fallbackPath) { @@ -11731,6 +11706,30 @@ module ts { } } + /** Serializes an Entity. Used by the __metadata decorator. */ + function serializeEntityFull(node: any, getGeneratedNameForNode: (Node: Node) => string): string { + var text: string; + if (node.kind === SyntaxKind.ArrayType) { + text = "{kind: 'Array'"; + text += ", elementType: " + serializeTypeNode(node.elementType, getGeneratedNameForNode); + } + else { + text = "{kind: '" + serializeEntityName(node.typeName, getGeneratedNameForNode) + "'"; + if (node.typeArguments) { + text += ', typeArguments: ['; + node.typeArguments.forEach(function(node: any, i: any) { + if (i) { + text += ', '; + } + text += serializeTypeNode(node, getGeneratedNameForNode); + }); + text += ']'; + } + } + text += '}'; + return text; + } + /** 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: @@ -11752,7 +11751,12 @@ module ts { return "Boolean"; } else if (type.flags & TypeFlags.NumberLike) { - return "Number"; + if (compilerOptions.emitVerboseMetadata && type.flags & TypeFlags.Enum) { + return 'function Enum(){return ' + serializeEntityName(node.typeName, getGeneratedNameForNode) + '}'; + } + else { + return "Number"; + } } else if (type.flags & TypeFlags.StringLike) { return "String"; @@ -11769,7 +11773,12 @@ module ts { return fallbackPath; } else if (type.symbol && type.symbol.valueDeclaration) { - return serializeEntityName(node.typeName, getGeneratedNameForNode); + if (compilerOptions.emitVerboseMetadata) { + return serializeEntityFull(node, getGeneratedNameForNode); + } + else { + return serializeEntityName(node.typeName, getGeneratedNameForNode); + } } else if (typeHasCallOrConstructSignatures(type)) { return "Function"; @@ -11801,7 +11810,12 @@ module ts { return "Function"; case SyntaxKind.ArrayType: case SyntaxKind.TupleType: - return "Array"; + if (compilerOptions.emitVerboseMetadata) { + return serializeTypeReferenceNode(node, getGeneratedNameForNode); + } + else { + return "Array"; + } case SyntaxKind.BooleanKeyword: return "Boolean"; case SyntaxKind.StringKeyword: @@ -11821,7 +11835,7 @@ module ts { break; } } - + return "Object"; } @@ -11835,7 +11849,7 @@ module ts { // * 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"; @@ -11849,14 +11863,27 @@ module ts { } return "void 0"; } - + + /** Serializes the module of a declaration to a strong value. Used by the __metadata decorator for a class member. */ + function serializeModuleOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[] { + var moduleDeclaration = node.parent.parent; + var text = moduleDeclaration.name.text; + if (moduleDeclaration.parent && moduleDeclaration.parent.kind === SyntaxKind.ModuleBlock) { + text = '.' + serializeModuleOfNode(moduleDeclaration, getGeneratedNameForNode); + } + if (moduleDeclaration.parent && moduleDeclaration.parent.kind === SyntaxKind.ModuleDeclaration) { + text = serializeModuleOfNode(node.parent, getGeneratedNameForNode) + '.' + text; + } + return text; + } + /** 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; @@ -11949,7 +11976,7 @@ module ts { let isVariableDeclarationOrBindingElement = n.parent.kind === SyntaxKind.BindingElement || (n.parent.kind === SyntaxKind.VariableDeclaration && (n.parent).name === n); - let symbol = + let symbol = (isVariableDeclarationOrBindingElement ? getSymbolOfNode(n.parent) : undefined) || getNodeLinks(n).resolvedSymbol || resolveName(n, n.text, SymbolFlags.Value | SymbolFlags.Alias, /*nodeNotFoundMessage*/ undefined, /*nameArg*/ undefined); @@ -11977,7 +12004,7 @@ module ts { if (!signature) { return unknownType; } - + let instantiatedSignature = getSignatureInstantiation(signature, typeArguments); return getOrCreateTypeFromSignature(instantiatedSignature); } @@ -12002,9 +12029,10 @@ module ts { collectLinkedAliases, getBlockScopedVariableId, getReferencedValueDeclaration, + serializeModuleOfNode, serializeTypeOfNode, serializeParameterTypesOfNode, - serializeReturnTypeOfNode, + serializeReturnTypeOfNode }; } diff --git a/src/compiler/commandLineParser.ts b/src/compiler/commandLineParser.ts index 6a055aebf6a5a..7a5bae6789460 100644 --- a/src/compiler/commandLineParser.ts +++ b/src/compiler/commandLineParser.ts @@ -192,6 +192,16 @@ module ts { name: "emitDecoratorMetadata", type: "boolean", experimental: true + }, + { + name: "emitVerboseMetadata", + type: "boolean", + experimental: true + }, + { + name: "skipEmitVarForModule", + type: "boolean", + experimental: true } ]; @@ -336,7 +346,7 @@ module ts { * Parse the contents of a config file (tsconfig.json). * @param json The contents of the config file to parse * @param basePath A root directory to resolve relative path entries in the config - * file to. e.g. outDir + * file to. e.g. outDir */ export function parseConfigFile(json: any, host: ParseConfigHost, basePath: string): ParsedCommandLine { var errors: Diagnostic[] = []; diff --git a/src/compiler/emitter.ts b/src/compiler/emitter.ts index 6d5146a680172..65c0eaffaa385 100644 --- a/src/compiler/emitter.ts +++ b/src/compiler/emitter.ts @@ -3,6 +3,23 @@ /* @internal */ module ts { + + //function __stack() { + // var orig = (Error).prepareStackTrace; + // (Error).prepareStackTrace = function (_: any, stack: any) { + // return stack; + // }; + // var err = new Error; + // (Error).captureStackTrace(err, arguments.callee); + // var stack = (err).stack; + // (Error).prepareStackTrace = orig; + // return stack; + //} + // + //function __line() { + // return __stack()[1].getLineNumber(); + //} + export function isExternalModuleOrDeclarationFile(sourceFile: SourceFile) { return isExternalModule(sourceFile) || isDeclarationFile(sourceFile); } @@ -913,13 +930,13 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { if (languageVersion < ScriptTarget.ES6 && (isTemplateLiteralKind(node.kind) || node.hasExtendedUnicodeEscape)) { return getQuotedEscapedLiteralText('"', node.text, '"'); } - + // If we don't need to downlevel and we can reach the original source text using // the node's parent reference, then simply get the text as it was originally written. if (node.parent) { return getSourceTextOfNodeFromSourceFile(currentSourceFile, node); } - + // If we can't reach the original source text, use the canonical form if it's a number, // or an escaped quoted form of the original text if it's string-like. switch (node.kind) { @@ -949,14 +966,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // The raw strings contain the (escaped) strings of what the user wrote. // Examples: `\n` is converted to "\\n", a template string with a newline to "\n". let text = getSourceTextOfNodeFromSourceFile(currentSourceFile, node); - + // text contains the original source, it will also contain quotes ("`"), dolar signs and braces ("${" and "}"), // thus we need to remove those characters. // First template piece starts with "`", others with "}" // Last template piece ends with "`", others with "${" let isLast = node.kind === SyntaxKind.NoSubstitutionTemplateLiteral || node.kind === SyntaxKind.TemplateTail; text = text.substring(1, text.length - (isLast ? 1 : 2)); - + // Newline normalization: // ES6 Spec 11.8.6.1 - Static Semantics of TV's and TRV's // and LineTerminatorSequences are normalized to for both TV and TRV. @@ -997,7 +1014,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitParenthesizedIf(node.tag, needsParenthesisForPropertyAccessOrInvocation(node.tag)); write("("); emit(tempVariable); - + // Now we emit the expressions if (node.template.kind === SyntaxKind.TemplateExpression) { forEach((node.template).templateSpans, templateSpan => { @@ -1156,7 +1173,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } else if (node.kind === SyntaxKind.ComputedPropertyName) { // if this is a decorated computed property, we will need to capture the result - // of the property expression so that we can apply decorators later. This is to ensure + // of the property expression so that we can apply decorators later. This is to ensure // we don't introduce unintended side effects: // // class C { @@ -1731,8 +1748,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return false; } - // Returns 'true' if the code was actually indented, false otherwise. - // If the code is not indented, an optional valueToWriteWhenNotIndenting will be + // Returns 'true' if the code was actually indented, false otherwise. + // If the code is not indented, an optional valueToWriteWhenNotIndenting will be // emitted instead. function indentIfOnDifferentLines(parent: Node, node1: Node, node2: Node, valueToWriteWhenNotIndenting?: string): boolean { let realNodesAreOnDifferentLines = !nodeIsSynthesized(parent) && !nodeEndIsOnSameLineAsNodeStart(node1, node2); @@ -2046,14 +2063,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return isSourceFileLevelDeclarationInSystemJsModule(node, /*isExported*/ false); } - /* + /* * Checks if given node is a source file level declaration (not nested in module/function). * If 'isExported' is true - then declaration must also be exported. * This function is used in two cases: - * - check if node is a exported source file level value to determine + * - check if node is a exported source file level value to determine * if we should also export the value after its it changed - * - check if node is a source level declaration to emit it differently, - * i.e non-exported variable statement 'var x = 1' is hoisted so + * - check if node is a source level declaration to emit it differently, + * i.e non-exported variable statement 'var x = 1' is hoisted so * we we emit variable statement 'var' should be dropped. */ function isSourceFileLevelDeclarationInSystemJsModule(node: Node, isExported: boolean): boolean { @@ -2122,7 +2139,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { decreaseIndentIf(indentedBeforeColon, indentedAfterColon); } - // Helper function to decrease the indent if we previously indented. Allows multiple + // Helper function to decrease the indent if we previously indented. Allows multiple // previous indent values to be considered at a time. This also allows caller to just // call this once, passing in all their appropriate indent values, instead of needing // to call this helper function multiple times. @@ -2363,13 +2380,13 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // all destructuring. // Note also that because an extra statement is needed to assign to the LHS, // for-of bodies are always emitted as blocks. - + let endPos = emitToken(SyntaxKind.ForKeyword, node.pos); write(" "); endPos = emitToken(SyntaxKind.OpenParenToken, endPos); - + // Do not emit the LHS let declaration yet, because it might contain destructuring. - + // Do not call recordTempDeclaration because we are declaring the temps // right here. Recording means they will be declared later. // In the case where the user wrote an identifier as the RHS, like this: @@ -2385,7 +2402,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // the LHS will be emitted inside the body. emitStart(node.expression); write("var "); - + // _i = 0 emitNodeWithoutSourceMap(counter); write(" = 0"); @@ -2402,7 +2419,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } write("; "); - + // _i < _a.length; emitStart(node.initializer); emitNodeWithoutSourceMap(counter); @@ -2413,19 +2430,19 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitEnd(node.initializer); write("; "); - + // _i++) emitStart(node.initializer); emitNodeWithoutSourceMap(counter); write("++"); emitEnd(node.initializer); emitToken(SyntaxKind.CloseParenToken, node.expression.end); - + // Body write(" {"); writeLine(); increaseIndent(); - + // Initialize LHS // let v = _a[_i]; let rhsIterationValue = createElementAccessExpression(rhsReference, counter); @@ -2730,7 +2747,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } renameNonTopLevelLetAndConst(name); - + const isVariableDeclarationOrBindingElement = name.parent && (name.parent.kind === SyntaxKind.VariableDeclaration || name.parent.kind === SyntaxKind.BindingElement); @@ -3005,7 +3022,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // - language version is ES6+ // - node is synthesized // - node is not identifier (can happen when tree is malformed) - // - node is definitely not name of variable declaration. + // - node is definitely not name of variable declaration. // it still can be part of parameter declaration, this check will be done next if (languageVersion >= ScriptTarget.ES6 || nodeIsSynthesized(node) || @@ -3301,7 +3318,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } if (!node.body) { - // There can be no body when there are parse errors. Just emit an empty block + // There can be no body when there are parse errors. Just emit an empty block // in that case. write(" { }"); } @@ -3334,7 +3351,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return; } - // For es6 and higher we can emit the expression as is. However, in the case + // For es6 and higher we can emit the expression as is. However, in the case // where the expression might end up looking like a block when emitted, we'll // also wrap it in parentheses first. For example if you have: a => {} // then we need to generate: a => ({}) @@ -3777,7 +3794,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitClassLikeDeclarationForES6AndHigher(node); } } - + function emitClassLikeDeclarationForES6AndHigher(node: ClassLikeDeclaration) { let thisNodeIsDecorated = nodeIsDecorated(node); if (node.kind === SyntaxKind.ClassDeclaration) { @@ -3851,9 +3868,9 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } // 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: + // to specialize the emit a bit. for a class expression of the form: // - // class C { static a = 1; static b = 2; ... } + // class C { static a = 1; static b = 2; ... } // // We'll emit: // @@ -3899,7 +3916,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { scopeEmitEnd(); // TODO(rbuckton): Need to go back to `let _a = class C {}` approach, removing the defineProperty call for now. - + // For a decorated class, we need to assign its name (if it has one). This is because we emit // the class as a class expression to avoid the double-binding of the identifier: // @@ -4036,7 +4053,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { write(".prototype"); } } - + function emitDecoratorsOfClass(node: ClassLikeDeclaration) { emitDecoratorsOfMembers(node, /*staticFlag*/ 0); emitDecoratorsOfMembers(node, NodeFlags.Static); @@ -4144,7 +4161,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // // The emit for a method is: // - // Object.defineProperty(C.prototype, "method", + // Object.defineProperty(C.prototype, "method", // __decorate([ // dec, // __param(0, dec2), @@ -4152,10 +4169,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // __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", + // Object.defineProperty(C.prototype, "accessor", // __decorate([ // dec // ], C.prototype, "accessor", Object.getOwnPropertyDescriptor(C.prototype, "accessor"))); @@ -4243,9 +4260,25 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return argumentsWritten; } + function shouldEmitModuleMetadata(node: Declaration): boolean { + // This method determines whether to emit the "design:module" 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.ModuleDeclaration: + case SyntaxKind.FunctionDeclaration: + case SyntaxKind.VariableDeclaration: + case SyntaxKind.ClassDeclaration: + case SyntaxKind.EnumDeclaration: + return node.parent && node.parent.kind === SyntaxKind.ModuleBlock; + } + + return false; + } + 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 + // 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: @@ -4260,7 +4293,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { 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 + // 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: @@ -4271,7 +4304,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { 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 + // 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: @@ -4287,6 +4320,19 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // The caller should have already tested whether the node has decorators. let argumentsWritten = 0; if (compilerOptions.emitDecoratorMetadata) { + if (compilerOptions.emitVerboseMetadata && shouldEmitModuleMetadata(node)) { + var serializedModule = resolver.serializeModuleOfNode(node, getGeneratedNameForNode); + if (serializedModule) { + if (writeComma) { + write(", "); + } + writeLine(); + write("__metadata('design:module', '"); + emitSerializedType(node, serializedModule); + write("')"); + argumentsWritten++; + } + } if (shouldEmitTypeMetadata(node)) { var serializedType = resolver.serializeTypeOfNode(node, getGeneratedNameForNode); if (serializedType) { @@ -4471,7 +4517,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return emitOnlyPinnedOrTripleSlashComments(node); } let hoistedInDeclarationScope = shouldHoistDeclarationInSystemJsModule(node); - let emitVarForModule = !hoistedInDeclarationScope && !isModuleMergedWithES6Class(node); + let emitVarForModule = !compilerOptions.skipEmitVarForModule && !hoistedInDeclarationScope && !isModuleMergedWithES6Class(node); if (emitVarForModule) { emitStart(node); @@ -4932,7 +4978,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { let started = false; for (let importNode of externalImports) { // do not create variable declaration for exports and imports that lack import clause - let skipNode = + let skipNode = importNode.kind === SyntaxKind.ExportDeclaration || (importNode.kind === SyntaxKind.ImportDeclaration && !(importNode).importClause) @@ -5029,7 +5075,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { write("};"); return emitExportStarFunction(exportedNamesStorageRef); - + function emitExportStarFunction(localNames: string): string { const exportStarFunction = makeUniqueName("exportStar"); @@ -5056,10 +5102,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return exportStarFunction; } - + function writeExportedName(node: Identifier | Declaration): void { // do not record default exports - // they are local to module and never overwritten (explicitly skipped) by star export + // they are local to module and never overwritten (explicitly skipped) by star export if (node.kind !== SyntaxKind.Identifier && node.flags & NodeFlags.Default) { return; } @@ -5085,7 +5131,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { } function processTopLevelVariableAndFunctionDeclarations(node: SourceFile): (Identifier | Declaration)[] { - // per ES6 spec: + // per ES6 spec: // 15.2.1.16.4 ModuleDeclarationInstantiation() Concrete Method // - var declarations are initialized to undefined - 14.a.ii // - function/generator declarations are instantiated - 16.a.iv @@ -5206,7 +5252,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // hoist variable if // - it is not block scoped // - it is top level block scoped - // if block scoped variables are nested in some another block then + // if block scoped variables are nested in some another block then // no other functions can use them except ones that are defined at least in the same block return (getCombinedNodeFlags(node) & NodeFlags.BlockScoped) === 0 || getEnclosingBlockScopeContainer(node).kind === SyntaxKind.SourceFile; @@ -5318,7 +5364,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { if (importNode.kind === SyntaxKind.ImportDeclaration && (importNode).importClause.namedBindings) { - + let namedBindings = (importNode).importClause.namedBindings; if (namedBindings.kind === SyntaxKind.NamespaceImport) { // emit re-export for namespace @@ -5406,10 +5452,10 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // System modules has the following shape // System.register(['dep-1', ... 'dep-n'], function(exports) {/* module body function */}) // 'exports' here is a function 'exports(name: string, value: T): T' that is used to publish exported values. - // 'exports' returns its 'value' argument so in most cases expressions + // 'exports' returns its 'value' argument so in most cases expressions // that mutate exported values can be rewritten as: - // expr -> exports('name', expr). - // The only exception in this rule is postfix unary operators, + // expr -> exports('name', expr). + // The only exception in this rule is postfix unary operators, // see comment to 'emitPostfixUnaryExpression' for more details Debug.assert(!exportFunctionForFile); // make sure that name of 'exports' function does not conflict with existing identifiers @@ -5449,8 +5495,8 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { // factory function. let unaliasedModuleNames: string[] = []; // names of modules with no corresponding parameters in // factory function. - let importAliasNames: string[] = []; // names of the parameters in the factory function; these - // parameters need to match the indexes of the corresponding + let importAliasNames: string[] = []; // names of the parameters in the factory function; these + // parameters need to match the indexes of the corresponding // module names in aliasedModuleNames. // Fill in amd-dependency tags @@ -5558,7 +5604,7 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { emitCaptureThisForNodeIfNecessary(node); emitLinesStartingAt(node.statements, startIndex); emitTempDeclarations(/*newLine*/ true); - // Emit exportDefault if it exists will happen as part + // Emit exportDefault if it exists will happen as part // or normal statement emit. } @@ -5705,14 +5751,14 @@ var __param = (this && this.__param) || function (paramIndex, decorator) { return shouldEmitEnumDeclaration(node); } - // If this is the expression body of an arrow function that we're down-leveling, + // If this is the expression body of an arrow function that we're down-leveling, // then we don't want to emit comments when we emit the body. It will have already // been taken care of when we emitted the 'return' statement for the function // expression body. if (node.kind !== SyntaxKind.Block && node.parent && node.parent.kind === SyntaxKind.ArrowFunction && - (node.parent).body === node && + (node.parent).body === node && compilerOptions.target <= ScriptTarget.ES5) { return false; diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 86e680ca8b047..8e6b8e25dd3c4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -1010,7 +1010,7 @@ module ts { // The first node that causes this file to be an external module /* @internal */ externalModuleIndicator: Node; - + /* @internal */ identifiers: Map; /* @internal */ nodeCount: number; /* @internal */ identifierCount: number; @@ -1065,7 +1065,7 @@ module ts { getSemanticDiagnostics(sourceFile?: SourceFile): Diagnostic[]; getDeclarationDiagnostics(sourceFile?: SourceFile): Diagnostic[]; - /** + /** * Gets a type checker that can be used to semantically analyze source fils in the program. */ getTypeChecker(): TypeChecker; @@ -1084,15 +1084,15 @@ module ts { export interface SourceMapSpan { /** Line number in the .js file. */ - emittedLine: number; + emittedLine: number; /** Column number in the .js file. */ - emittedColumn: number; + emittedColumn: number; /** Line number in the .ts file. */ - sourceLine: number; + sourceLine: number; /** Column number in the .ts file. */ - sourceColumn: number; + sourceColumn: number; /** Optional name (index into names array) associated with this span. */ - nameIndex?: number; + nameIndex?: number; /** .ts file (index into sources array) associated with this span */ sourceIndex: number; } @@ -1282,6 +1282,7 @@ module ts { getBlockScopedVariableId(node: Identifier): number; getReferencedValueDeclaration(reference: Identifier): Declaration; serializeTypeOfNode(node: Node, getGeneratedNameForNode: (Node: Node) => string): string | string[]; + serializeModuleOfNode(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[]; } @@ -1379,7 +1380,7 @@ module ts { /* @internal */ constEnumOnlyModule?: boolean; // True if module contains only const enums or other modules with only const enums } - /* @internal */ + /* @internal */ export interface SymbolLinks { target?: Symbol; // Resolved (non-alias) target of an alias type?: Type; // Type of value symbol @@ -1391,14 +1392,14 @@ module ts { exportsChecked?: boolean; // True if exports of external module have been checked } - /* @internal */ + /* @internal */ export interface TransientSymbol extends Symbol, SymbolLinks { } export interface SymbolTable { [index: string]: Symbol; } - /* @internal */ + /* @internal */ export const enum NodeCheckFlags { TypeChecked = 0x00000001, // Node has been type checked LexicalThis = 0x00000002, // Lexical 'this' reference @@ -1416,7 +1417,7 @@ module ts { LexicalModuleMergesWithClass = 0x00000800, // Instantiated lexical module declaration is merged with a previous class declaration. } - /* @internal */ + /* @internal */ export interface NodeLinks { resolvedType?: Type; // Cached type of type node resolvedSignature?: Signature; // Cached signature of signature node or call expression @@ -1449,23 +1450,23 @@ module ts { Tuple = 0x00002000, // Tuple Union = 0x00004000, // Union Anonymous = 0x00008000, // Anonymous - /* @internal */ + /* @internal */ FromSignature = 0x00010000, // Created for signature assignment check ObjectLiteral = 0x00020000, // Originates in an object literal - /* @internal */ + /* @internal */ ContainsUndefinedOrNull = 0x00040000, // Type is or contains Undefined or Null type - /* @internal */ + /* @internal */ ContainsObjectLiteral = 0x00080000, // Type is or contains object literal type ESSymbol = 0x00100000, // Type of symbol primitive introduced in ES6 - /* @internal */ + /* @internal */ Intrinsic = Any | String | Number | Boolean | ESSymbol | Void | Undefined | Null, - /* @internal */ + /* @internal */ Primitive = String | Number | Boolean | ESSymbol | Void | Undefined | Null | StringLiteral | Enum, StringLike = String | StringLiteral, NumberLike = Number | Enum, ObjectType = Class | Interface | Reference | Tuple | Anonymous, - /* @internal */ + /* @internal */ RequiresWidening = ContainsUndefinedOrNull | ContainsObjectLiteral } @@ -1476,7 +1477,7 @@ module ts { symbol?: Symbol; // Symbol associated with type (if any) } - /* @internal */ + /* @internal */ // Intrinsic types (TypeFlags.Intrinsic) export interface IntrinsicType extends Type { intrinsicName: string; // Name of intrinsic type @@ -1678,6 +1679,8 @@ module ts { watch?: boolean; separateCompilation?: boolean; emitDecoratorMetadata?: boolean; + emitVerboseMetadata?: boolean; + skipEmitVarForModule?: boolean; /* @internal */ stripInternal?: boolean; [option: string]: string | number | boolean; } @@ -1694,7 +1697,7 @@ module ts { CarriageReturnLineFeed = 0, LineFeed = 1, } - + export interface LineAndCharacter { line: number; /*