From 951084fc853107b4d8e3dd616545fb34fba52ac3 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 7 Jul 2015 11:01:49 +0800 Subject: [PATCH 1/5] Fixes emit of type predicated in delcaration files --- src/compiler/declarationEmitter.ts | 46 +++++++++++++---------- tests/cases/compiler/declFileFunctions.ts | 4 ++ 2 files changed, 31 insertions(+), 19 deletions(-) diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 8c012f2678e..3db032b8d0d 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -188,7 +188,7 @@ namespace ts { if (!moduleElementEmitInfo && asynchronousSubModuleDeclarationEmitInfo) { moduleElementEmitInfo = forEach(asynchronousSubModuleDeclarationEmitInfo, declEmitInfo => declEmitInfo.node === nodeToCheck ? declEmitInfo : undefined); } - + // If the alias was marked as not visible when we saw its declaration, we would have saved the aliasEmitInfo, but if we haven't yet visited the alias declaration // then we don't need to write it at this point. We will write it when we actually see its declaration // Eg. @@ -198,7 +198,7 @@ namespace ts { // we would write alias foo declaration when we visit it since it would now be marked as visible if (moduleElementEmitInfo) { if (moduleElementEmitInfo.node.kind === SyntaxKind.ImportDeclaration) { - // we have to create asynchronous output only after we have collected complete information + // we have to create asynchronous output only after we have collected complete information // because it is possible to enable multiple bindings as asynchronously visible moduleElementEmitInfo.isVisible = true; } @@ -353,6 +353,21 @@ namespace ts { return emitEntityName(type); case SyntaxKind.QualifiedName: return emitEntityName(type); + case SyntaxKind.TypePredicate: + return emitTypePredicate(type); + } + + function writeEntityName(entityName: EntityName | Expression) { + if (entityName.kind === SyntaxKind.Identifier) { + writeTextOfNode(currentSourceFile, entityName); + } + else { + let left = entityName.kind === SyntaxKind.QualifiedName ? (entityName).left : (entityName).expression; + let right = entityName.kind === SyntaxKind.QualifiedName ? (entityName).right : (entityName).name; + writeEntityName(left); + write("."); + writeTextOfNode(currentSourceFile, right); + } } function emitEntityName(entityName: EntityName | PropertyAccessExpression) { @@ -362,19 +377,6 @@ namespace ts { handleSymbolAccessibilityError(visibilityResult); writeEntityName(entityName); - - function writeEntityName(entityName: EntityName | Expression) { - if (entityName.kind === SyntaxKind.Identifier) { - writeTextOfNode(currentSourceFile, entityName); - } - else { - let left = entityName.kind === SyntaxKind.QualifiedName ? (entityName).left : (entityName).expression; - let right = entityName.kind === SyntaxKind.QualifiedName ? (entityName).right : (entityName).name; - writeEntityName(left); - write("."); - writeTextOfNode(currentSourceFile, right); - } - } } function emitExpressionWithTypeArguments(node: ExpressionWithTypeArguments) { @@ -398,6 +400,12 @@ namespace ts { } } + function emitTypePredicate(type: TypePredicateNode) { + writeEntityName(type.parameterName); + write(" is "); + emitType(type.type); + } + function emitTypeQuery(type: TypeQueryNode) { write("typeof "); emitEntityName(type.exprName); @@ -600,7 +608,7 @@ namespace ts { } function writeImportEqualsDeclaration(node: ImportEqualsDeclaration) { - // note usage of writer. methods instead of aliases created, just to make sure we are using + // note usage of writer. methods instead of aliases created, just to make sure we are using // correct writer especially to handle asynchronous alias writing emitJsDocComments(node); if (node.flags & NodeFlags.Export) { @@ -642,7 +650,7 @@ namespace ts { function writeImportDeclaration(node: ImportDeclaration) { if (!node.importClause && !(node.flags & NodeFlags.Export)) { - // do not write non-exported import declarations that don't have import clauses + // do not write non-exported import declarations that don't have import clauses return; } emitJsDocComments(node); @@ -1517,7 +1525,7 @@ namespace ts { } } } - } + } } function emitNode(node: Node) { @@ -1577,7 +1585,7 @@ namespace ts { referencePathsOutput += "/// " + newLine; } } - + /* @internal */ export function writeDeclarationFile(jsFilePath: string, sourceFile: SourceFile, host: EmitHost, resolver: EmitResolver, diagnostics: Diagnostic[]) { let emitDeclarationResult = emitDeclarations(host, resolver, diagnostics, jsFilePath, sourceFile); diff --git a/tests/cases/compiler/declFileFunctions.ts b/tests/cases/compiler/declFileFunctions.ts index e7ce3d07f82..36972d427f0 100644 --- a/tests/cases/compiler/declFileFunctions.ts +++ b/tests/cases/compiler/declFileFunctions.ts @@ -28,6 +28,10 @@ export function fooWithSingleOverload(a: any) { return a; } +export function fooWithTypePredicate(a: any): a is number { + return true; +} + /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { } From 08a774425452b7a24219fbdf3564b8642ce5f20c Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Tue, 7 Jul 2015 11:11:56 +0800 Subject: [PATCH 2/5] Accepts baselines --- .../baselines/reference/declFileFunctions.js | 9 ++++ .../reference/declFileFunctions.symbols | 44 +++++++++++-------- .../reference/declFileFunctions.types | 9 ++++ 3 files changed, 44 insertions(+), 18 deletions(-) diff --git a/tests/baselines/reference/declFileFunctions.js b/tests/baselines/reference/declFileFunctions.js index da1917163e1..d3debf4d50c 100644 --- a/tests/baselines/reference/declFileFunctions.js +++ b/tests/baselines/reference/declFileFunctions.js @@ -26,6 +26,10 @@ export function fooWithSingleOverload(a: any) { return a; } +export function fooWithTypePredicate(a: any): a is number { + return true; +} + /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { } @@ -92,6 +96,10 @@ function fooWithSingleOverload(a) { return a; } exports.fooWithSingleOverload = fooWithSingleOverload; +function fooWithTypePredicate(a) { + return true; +} +exports.fooWithTypePredicate = fooWithTypePredicate; /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { } @@ -144,6 +152,7 @@ export declare function fooWithRestParameters(a: string, ...rests: string[]): st export declare function fooWithOverloads(a: string): string; export declare function fooWithOverloads(a: number): number; export declare function fooWithSingleOverload(a: string): string; +export declare function fooWithTypePredicate(a: any): a is number; //// [declFileFunctions_1.d.ts] /** This comment should appear for foo*/ declare function globalfoo(): void; diff --git a/tests/baselines/reference/declFileFunctions.symbols b/tests/baselines/reference/declFileFunctions.symbols index ff04d211557..1d62cc29d28 100644 --- a/tests/baselines/reference/declFileFunctions.symbols +++ b/tests/baselines/reference/declFileFunctions.symbols @@ -57,49 +57,57 @@ export function fooWithSingleOverload(a: any) { >a : Symbol(a, Decl(declFileFunctions_0.ts, 21, 38)) } +export function fooWithTypePredicate(a: any): a is number { +>fooWithTypePredicate : Symbol(fooWithTypePredicate, Decl(declFileFunctions_0.ts, 23, 1)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 25, 37)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 25, 37)) + + return true; +} + /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { ->nonExportedFoo : Symbol(nonExportedFoo, Decl(declFileFunctions_0.ts, 23, 1)) +>nonExportedFoo : Symbol(nonExportedFoo, Decl(declFileFunctions_0.ts, 27, 1)) } /** This is comment for function signature*/ function nonExportedFooWithParameters(/** this is comment about a*/a: string, ->nonExportedFooWithParameters : Symbol(nonExportedFooWithParameters, Decl(declFileFunctions_0.ts, 27, 1)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 29, 38)) +>nonExportedFooWithParameters : Symbol(nonExportedFooWithParameters, Decl(declFileFunctions_0.ts, 31, 1)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 33, 38)) /** this is comment for b*/ b: number) { ->b : Symbol(b, Decl(declFileFunctions_0.ts, 29, 77)) +>b : Symbol(b, Decl(declFileFunctions_0.ts, 33, 77)) var d = a; ->d : Symbol(d, Decl(declFileFunctions_0.ts, 32, 7)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 29, 38)) +>d : Symbol(d, Decl(declFileFunctions_0.ts, 36, 7)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 33, 38)) } function nonExportedFooWithRestParameters(a: string, ...rests: string[]) { ->nonExportedFooWithRestParameters : Symbol(nonExportedFooWithRestParameters, Decl(declFileFunctions_0.ts, 33, 1)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 42)) ->rests : Symbol(rests, Decl(declFileFunctions_0.ts, 34, 52)) +>nonExportedFooWithRestParameters : Symbol(nonExportedFooWithRestParameters, Decl(declFileFunctions_0.ts, 37, 1)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 38, 42)) +>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 38, 52)) return a + rests.join(""); ->a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 42)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 38, 42)) >rests.join : Symbol(Array.join, Decl(lib.d.ts, 1035, 31)) ->rests : Symbol(rests, Decl(declFileFunctions_0.ts, 34, 52)) +>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 38, 52)) >join : Symbol(Array.join, Decl(lib.d.ts, 1035, 31)) } function nonExportedFooWithOverloads(a: string): string; ->nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 36, 1), Decl(declFileFunctions_0.ts, 38, 56), Decl(declFileFunctions_0.ts, 39, 56)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 38, 37)) +>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 40, 1), Decl(declFileFunctions_0.ts, 42, 56), Decl(declFileFunctions_0.ts, 43, 56)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 42, 37)) function nonExportedFooWithOverloads(a: number): number; ->nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 36, 1), Decl(declFileFunctions_0.ts, 38, 56), Decl(declFileFunctions_0.ts, 39, 56)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 39, 37)) +>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 40, 1), Decl(declFileFunctions_0.ts, 42, 56), Decl(declFileFunctions_0.ts, 43, 56)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 43, 37)) function nonExportedFooWithOverloads(a: any): any { ->nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 36, 1), Decl(declFileFunctions_0.ts, 38, 56), Decl(declFileFunctions_0.ts, 39, 56)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 40, 37)) +>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 40, 1), Decl(declFileFunctions_0.ts, 42, 56), Decl(declFileFunctions_0.ts, 43, 56)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 44, 37)) return a; ->a : Symbol(a, Decl(declFileFunctions_0.ts, 40, 37)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 44, 37)) } === tests/cases/compiler/declFileFunctions_1.ts === diff --git a/tests/baselines/reference/declFileFunctions.types b/tests/baselines/reference/declFileFunctions.types index b9e94f7ffcd..e6ecc53b043 100644 --- a/tests/baselines/reference/declFileFunctions.types +++ b/tests/baselines/reference/declFileFunctions.types @@ -60,6 +60,15 @@ export function fooWithSingleOverload(a: any) { >a : any } +export function fooWithTypePredicate(a: any): a is number { +>fooWithTypePredicate : (a: any) => boolean +>a : any +>a : any + + return true; +>true : boolean +} + /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { >nonExportedFoo : () => void From 28976a0e344258605e777d4d75217084bcb9dc0d Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Thu, 9 Jul 2015 11:13:32 +0800 Subject: [PATCH 3/5] Adds type predicate signature display and addresses CR feedback --- src/compiler/checker.ts | 340 +++++++++--------- src/compiler/declarationEmitter.ts | 2 +- tests/cases/compiler/declFileFunctions.ts | 9 + .../signatureHelpOnTypePredicates.ts | 20 ++ 4 files changed, 206 insertions(+), 165 deletions(-) create mode 100644 tests/cases/fourslash/signatureHelpOnTypePredicates.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 1b34952f3ae..03a3f7efa9b 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -25,12 +25,12 @@ namespace ts { // Cancellation that controls whether or not we can cancel in the middle of type checking. // In general cancelling is *not* safe for the type checker. We might be in the middle of // computing something, and we will leave our internals in an inconsistent state. Callers - // who set the cancellation token should catch if a cancellation exception occurs, and + // who set the cancellation token should catch if a cancellation exception occurs, and // should throw away and create a new TypeChecker. // // Currently we only support setting the cancellation token when getting diagnostics. This // is because diagnostics can be quite expensive, and we want to allow hosts to bail out if - // they no longer need the information (for example, if the user started editing again). + // they no longer need the information (for example, if the user started editing again). let cancellationToken: CancellationToken; let Symbol = objectAllocator.getSymbolConstructor(); @@ -117,7 +117,7 @@ namespace ts { let globals: SymbolTable = {}; let globalESSymbolConstructorSymbol: Symbol; - + let getGlobalPromiseConstructorSymbol: () => Symbol; let globalObjectType: ObjectType; @@ -148,7 +148,7 @@ namespace ts { let getInstantiatedGlobalPromiseLikeType: () => ObjectType; let getGlobalPromiseConstructorLikeType: () => ObjectType; let getGlobalThenableType: () => ObjectType; - + let tupleTypes: Map = {}; let unionTypes: Map = {}; let intersectionTypes: Map = {}; @@ -158,7 +158,7 @@ namespace ts { let emitParam = false; let emitAwaiter = false; let emitGenerator = false; - + let resolutionTargets: Object[] = []; let resolutionResults: boolean[] = []; @@ -406,7 +406,7 @@ namespace ts { let moduleExports = getSymbolOfNode(location).exports; if (location.kind === SyntaxKind.SourceFile || (location.kind === SyntaxKind.ModuleDeclaration && (location).name.kind === SyntaxKind.StringLiteral)) { - + // It's an external module. Because of module/namespace merging, a module's exports are in scope, // yet we never want to treat an export specifier as putting a member in scope. Therefore, // if the name we find is purely an export specifier, it is not actually considered in scope. @@ -526,7 +526,7 @@ namespace 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() {} @@ -1948,7 +1948,19 @@ namespace ts { writePunctuation(writer, SyntaxKind.ColonToken); } writeSpace(writer); - buildTypeDisplay(getReturnTypeOfSignature(signature), writer, enclosingDeclaration, flags, symbolStack); + + let returnType: Type; + if (signature.typePredicate) { + writer.writeParameter(signature.typePredicate.parameterName); + writeSpace(writer); + writeKeyword(writer, SyntaxKind.IsKeyword); + writeSpace(writer); + returnType = signature.typePredicate.type; + } + else { + returnType = getReturnTypeOfSignature(signature); + } + buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack); } function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) { @@ -2098,7 +2110,7 @@ namespace 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: @@ -3864,7 +3876,7 @@ namespace ts { function getGlobalType(name: string, arity = 0): ObjectType { return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity); } - + function tryGetGlobalType(name: string, arity = 0): ObjectType { return getTypeOfGlobalSymbol(getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined), arity); } @@ -3892,7 +3904,7 @@ namespace ts { ? createTypeReference(globalTypedPropertyDescriptorType, [propertyType]) : emptyObjectType; } - + /** * Instantiates a global type that is generic with some element type, and returns that instantiation. */ @@ -4117,7 +4129,7 @@ namespace ts { } return links.resolvedType; } - + function getTypeFromTypeNode(node: TypeNode): Type { switch (node.kind) { case SyntaxKind.AnyKeyword: @@ -6053,7 +6065,7 @@ namespace ts { error(node, Diagnostics.The_arguments_object_cannot_be_referenced_in_an_arrow_function_in_ES3_and_ES5_Consider_using_a_standard_function_expression); } } - + if (node.parserContextFlags & ParserContextFlags.Await) { getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments; getNodeLinks(node).flags |= NodeCheckFlags.LexicalArguments; @@ -6746,7 +6758,7 @@ namespace 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 @@ -7399,7 +7411,7 @@ namespace ts { if (flags & NodeFlags.Abstract) { // A method cannot be accessed in a super property access if the method is abstract. - // This error could mask a private property access error. But, a member + // This error could mask a private property access error. But, a member // cannot simultaneously be private and abstract, so this will trigger an // additional error elsewhere. @@ -7478,7 +7490,7 @@ namespace ts { } return unknownType; } - + getNodeLinks(node).resolvedSymbol = prop; if (prop.parent && prop.parent.flags & SymbolFlags.Class) { @@ -7875,7 +7887,7 @@ namespace ts { let paramType = getTypeAtPosition(signature, i); let argType = getEffectiveArgumentType(node, i, arg); - // If the effective argument type is 'undefined', there is no synthetic type + // If the effective argument type is 'undefined', there is no synthetic type // for the argument. In that case, we should check the argument. if (argType === undefined) { // For context sensitive arguments we pass the identityMapper, which is a signal to treat all @@ -7947,8 +7959,8 @@ namespace ts { // Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter) let paramType = getTypeAtPosition(signature, i); let argType = getEffectiveArgumentType(node, i, arg); - - // If the effective argument type is 'undefined', there is no synthetic type + + // If the effective argument type is 'undefined', there is no synthetic type // for the argument. In that case, we should check the argument. if (argType === undefined) { argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors @@ -8001,18 +8013,18 @@ namespace ts { return args; } - + /** * Returns the effective argument count for a node that works like a function invocation. * If 'node' is a Decorator, the number of arguments is derived from the decoration * target and the signature: - * If 'node.target' is a class declaration or class expression, the effective argument + * If 'node.target' is a class declaration or class expression, the effective argument * count is 1. * If 'node.target' is a parameter declaration, the effective argument count is 3. * If 'node.target' is a property declaration, the effective argument count is 2. - * If 'node.target' is a method or accessor declaration, the effective argument count + * If 'node.target' is a method or accessor declaration, the effective argument count * is 3, although it can be 2 if the signature only accepts two arguments, allowing - * us to match a property decorator. + * us to match a property decorator. * Otherwise, the argument count is the length of the 'args' array. */ function getEffectiveArgumentCount(node: CallLikeExpression, args: Expression[], signature: Signature) { @@ -8024,7 +8036,7 @@ namespace ts { return 1; case SyntaxKind.PropertyDeclaration: - // A property declaration decorator will have two arguments (see + // A property declaration decorator will have two arguments (see // `PropertyDecorator` in core.d.ts) return 2; @@ -8033,12 +8045,12 @@ namespace ts { case SyntaxKind.SetAccessor: // A method or accessor declaration decorator will have two or three arguments (see // `PropertyDecorator` and `MethodDecorator` in core.d.ts) - // If the method decorator signature only accepts a target and a key, we will only + // If the method decorator signature only accepts a target and a key, we will only // type check those arguments. return signature.parameters.length >= 3 ? 3 : 2; case SyntaxKind.Parameter: - // A parameter declaration decorator will have three arguments (see + // A parameter declaration decorator will have three arguments (see // `ParameterDecorator` in core.d.ts) return 3; @@ -8048,47 +8060,47 @@ namespace ts { return args.length; } } - + /** * Returns the effective type of the first argument to a decorator. * If 'node' is a class declaration or class expression, the effective argument type * is the type of the static side of the class. * If 'node' is a parameter declaration, the effective argument type is either the type - * of the static or instance side of the class for the parameter's parent method, + * of the static or instance side of the class for the parameter's parent method, * depending on whether the method is declared static. * For a constructor, the type is always the type of the static side of the class. - * If 'node' is a property, method, or accessor declaration, the effective argument - * type is the type of the static or instance side of the parent class for class - * element, depending on whether the element is declared static. + * If 'node' is a property, method, or accessor declaration, the effective argument + * type is the type of the static or instance side of the parent class for class + * element, depending on whether the element is declared static. */ function getEffectiveDecoratorFirstArgumentType(node: Node): Type { // The first argument to a decorator is its `target`. switch (node.kind) { case SyntaxKind.ClassDeclaration: case SyntaxKind.ClassExpression: - // For a class decorator, the `target` is the type of the class (e.g. the + // For a class decorator, the `target` is the type of the class (e.g. the // "static" or "constructor" side of the class) let classSymbol = getSymbolOfNode(node); return getTypeOfSymbol(classSymbol); case SyntaxKind.Parameter: - // For a parameter decorator, the `target` is the parent type of the - // parameter's containing method. + // For a parameter decorator, the `target` is the parent type of the + // parameter's containing method. node = node.parent; if (node.kind === SyntaxKind.Constructor) { let classSymbol = getSymbolOfNode(node); return getTypeOfSymbol(classSymbol); } - + // fall-through - + case SyntaxKind.PropertyDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: // For a property or method decorator, the `target` is the // "static"-side type of the parent of the member if the member is - // declared "static"; otherwise, it is the "instance"-side type of the + // declared "static"; otherwise, it is the "instance"-side type of the // parent of the member. return getParentTypeOfClassElement(node); @@ -8097,19 +8109,19 @@ namespace ts { return unknownType; } } - + /** * Returns the effective type for the second argument to a decorator. * If 'node' is a parameter, its effective argument type is one of the following: - * If 'node.parent' is a constructor, the effective argument type is 'any', as we + * If 'node.parent' is a constructor, the effective argument type is 'any', as we * will emit `undefined`. - * If 'node.parent' is a member with an identifier, numeric, or string literal name, + * If 'node.parent' is a member with an identifier, numeric, or string literal name, * the effective argument type will be a string literal type for the member name. - * If 'node.parent' is a computed property name, the effective argument type will + * If 'node.parent' is a computed property name, the effective argument type will * either be a symbol type or the string type. - * If 'node' is a member with an identifier, numeric, or string literal name, the + * If 'node' is a member with an identifier, numeric, or string literal name, the * effective argument type will be a string literal type for the member name. - * If 'node' is a computed property name, the effective argument type will either + * If 'node' is a computed property name, the effective argument type will either * be a symbol type or the string type. * A class decorator does not have a second argument type. */ @@ -8126,18 +8138,18 @@ namespace ts { // For a constructor parameter decorator, the `propertyKey` will be `undefined`. return anyType; } - + // For a non-constructor parameter decorator, the `propertyKey` will be either // a string or a symbol, based on the name of the parameter's containing method. - + // fall-through - + case SyntaxKind.PropertyDeclaration: case SyntaxKind.MethodDeclaration: case SyntaxKind.GetAccessor: case SyntaxKind.SetAccessor: // The `propertyKey` for a property or method decorator will be a - // string literal type if the member name is an identifier, number, or string; + // string literal type if the member name is an identifier, number, or string; // otherwise, if the member name is a computed property name it will // be either string or symbol. let element = node; @@ -8167,11 +8179,11 @@ namespace ts { return unknownType; } } - + /** * Returns the effective argument type for the third argument to a decorator. * If 'node' is a parameter, the effective argument type is the number type. - * If 'node' is a method or accessor, the effective argument type is a + * If 'node' is a method or accessor, the effective argument type is a * `TypedPropertyDescriptor` instantiated with the type of the member. * Class and property decorators do not have a third effective argument. */ @@ -8204,7 +8216,7 @@ namespace ts { return unknownType; } } - + /** * Returns the effective argument type for the provided argument to a decorator. */ @@ -8222,12 +8234,12 @@ namespace ts { Debug.fail("Decorators should not have a fourth synthetic argument."); return unknownType; } - + /** * Gets the effective argument type for an argument in a call expression. */ function getEffectiveArgumentType(node: CallLikeExpression, argIndex: number, arg: Expression): Type { - // Decorators provide special arguments, a tagged template expression provides + // Decorators provide special arguments, a tagged template expression provides // a special first argument, and string literals get string literal types // unless we're reporting errors if (node.kind === SyntaxKind.Decorator) { @@ -8238,12 +8250,12 @@ namespace ts { } // This is not a synthetic argument, so we return 'undefined' - // to signal that the caller needs to check the argument. + // to signal that the caller needs to check the argument. return undefined; } - + /** - * Gets the effective argument expression for an argument in a call expression. + * Gets the effective argument expression for an argument in a call expression. */ function getEffectiveArgument(node: CallLikeExpression, args: Expression[], argIndex: number) { // For a decorator or the first argument of a tagged template expression we return undefined. @@ -8309,7 +8321,7 @@ namespace ts { // For a tagged template, then the first argument be 'undefined' if necessary // because it represents a TemplateStringsArray. // - // For a decorator, no arguments are susceptible to contextual typing due to the fact + // For a decorator, no arguments are susceptible to contextual typing due to the fact // decorators are applied to a declaration by the emitter, and not to an expression. let excludeArgument: boolean[]; if (!isDecorator) { @@ -8651,7 +8663,7 @@ namespace ts { return resolveCall(node, callSignatures, candidatesOutArray); } - + /** * Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression. */ @@ -8797,7 +8809,7 @@ namespace ts { links.type = instantiateType(getTypeOfSymbol(lastOrUndefined(context.parameters)), mapper); } } - + function createPromiseType(promisedType: Type): Type { // creates a `Promise` type where `T` is the promisedType argument let globalPromiseType = getGlobalPromiseType(); @@ -8806,7 +8818,7 @@ namespace ts { promisedType = getAwaitedType(promisedType); return createTypeReference(globalPromiseType, [promisedType]); } - + return emptyObjectType; } @@ -8815,15 +8827,15 @@ namespace ts { if (!func.body) { return unknownType; } - + let isAsync = isAsyncFunctionLike(func); let type: Type; if (func.body.kind !== SyntaxKind.Block) { - type = checkExpressionCached(func.body, contextualMapper); + type = checkExpressionCached(func.body, contextualMapper); if (isAsync) { - // From within an async function you can return either a non-promise value or a promise. Any - // Promise/A+ compatible implementation will always assimilate any foreign promise, so the - // return type of the body should be unwrapped to its awaited type, which we will wrap in + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so the + // return type of the body should be unwrapped to its awaited type, which we will wrap in // the native Promise type later in this function. type = checkAwaitedType(type, func, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); } @@ -8852,13 +8864,13 @@ namespace ts { error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type); return unknownType; } - + return promiseType; } else { return voidType; } - } + } } // When yield/return statements are contextually typed we allow the return type to be a union type. // Otherwise we require the yield/return expressions to have a best common supertype. @@ -8881,19 +8893,19 @@ namespace ts { if (!contextualSignature) { reportErrorsFromWidening(func, type); } - + let widenedType = getWidenedType(type); if (isAsync) { - // From within an async function you can return either a non-promise value or a promise. Any - // Promise/A+ compatible implementation will always assimilate any foreign promise, so the + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so the // return type of the body is awaited type of the body, wrapped in a native Promise type. let promiseType = createPromiseType(widenedType); if (promiseType === emptyObjectType) { error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type); return unknownType; } - - return promiseType; + + return promiseType; } else { return widenedType; @@ -8928,13 +8940,13 @@ namespace ts { forEachReturnStatement(body, returnStatement => { let expr = returnStatement.expression; if (expr) { - let type = checkExpressionCached(expr, contextualMapper); + let type = checkExpressionCached(expr, contextualMapper); if (isAsync) { - // From within an async function you can return either a non-promise value or a promise. Any - // Promise/A+ compatible implementation will always assimilate any foreign promise, so the - // return type of the body should be unwrapped to its awaited type, which should be wrapped in + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so the + // return type of the body should be unwrapped to its awaited type, which should be wrapped in // the native Promise type by the caller. - type = checkAwaitedType(type, body.parent, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); + type = checkAwaitedType(type, body.parent, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member); } if (!contains(aggregatedTypes, type)) { @@ -9006,12 +9018,12 @@ namespace ts { if (contextualMapper === identityMapper && isContextSensitive(node)) { return anyFunctionType; } - + let isAsync = isAsyncFunctionLike(node); if (isAsync) { emitAwaiter = true; } - + let links = getNodeLinks(node); let type = getTypeOfSymbol(node.symbol); // Check if function expression is contextually typed and assign parameter types if so @@ -9048,7 +9060,7 @@ namespace ts { function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) { Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node)); - + let isAsync = isAsyncFunctionLike(node); if (isAsync) { emitAwaiter = true; @@ -9059,7 +9071,7 @@ namespace ts { if (returnType && isAsync) { promisedType = checkAsyncFunctionReturnType(node); } - + if (returnType && !node.asteriskToken) { checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType); } @@ -9078,10 +9090,10 @@ namespace ts { checkSourceElement(node.body); } else { - // From within an async function you can return either a non-promise value or a promise. Any - // Promise/A+ compatible implementation will always assimilate any foreign promise, so we - // should not be checking assignability of a promise to the return type. Instead, we need to - // check assignability of the awaited type of the expression body against the promised type of + // From within an async function you can return either a non-promise value or a promise. Any + // Promise/A+ compatible implementation will always assimilate any foreign promise, so we + // should not be checking assignability of a promise to the return type. Instead, we need to + // check assignability of the awaited type of the expression body against the promised type of // its return type annotation. let exprType = checkExpression(node.body); if (returnType) { @@ -9093,7 +9105,7 @@ namespace ts { checkTypeAssignableTo(exprType, returnType, node.body); } } - + checkFunctionAndClassExpressionBodies(node.body); } } @@ -9215,7 +9227,7 @@ namespace ts { let operandType = checkExpression(node.expression); return checkAwaitedType(operandType, node); } - + function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type { let operandType = checkExpression(node.operand); switch (node.operator) { @@ -9688,7 +9700,7 @@ namespace ts { node.contextualType = saveContextualType; return result; } - + function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type { let links = getNodeLinks(node); if (!links.resolvedType) { @@ -9895,7 +9907,7 @@ namespace 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))) { @@ -10113,7 +10125,7 @@ namespace ts { // Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration checkFunctionLikeDeclaration(node); - + // Abstract methods cannot have an implementation. // Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node. if(node.flags & NodeFlags.Abstract && node.body) { @@ -10548,7 +10560,7 @@ namespace ts { } // Abstract methods can't have an implementation -- in particular, they don't need one. - if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && + if (!isExportSymbolInsideModule && lastSeenNonAmbientDeclaration && !lastSeenNonAmbientDeclaration.body && !(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) ) { reportImplementationExpectedError(lastSeenNonAmbientDeclaration); } @@ -10666,13 +10678,13 @@ namespace ts { if (!message) { message = Diagnostics.Operand_for_await_does_not_have_a_valid_callable_then_member; } - + error(location, message); } - + return unknownType; } - + return type; } @@ -10690,16 +10702,16 @@ namespace ts { // ) => any // ): any; // } - // - + // + if (promise.flags & TypeFlags.Any) { return undefined; } - + if ((promise.flags & TypeFlags.Reference) && (promise).target === tryGetGlobalPromiseType()) { return (promise).typeArguments[0]; } - + let globalPromiseLikeType = getInstantiatedGlobalPromiseLikeType(); if (globalPromiseLikeType === emptyObjectType || !isTypeAssignableTo(promise, globalPromiseLikeType)) { return undefined; @@ -10709,58 +10721,58 @@ namespace ts { if (thenFunction && (thenFunction.flags & TypeFlags.Any)) { return undefined; } - + let thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, SignatureKind.Call) : emptyArray; if (thenSignatures.length === 0) { return undefined; } - + let onfulfilledParameterType = getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature)); if (onfulfilledParameterType.flags & TypeFlags.Any) { return undefined; } - + let onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, SignatureKind.Call); if (onfulfilledParameterSignatures.length === 0) { return undefined; } - + let valueParameterType = getUnionType(map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature)); return valueParameterType; } - + function getTypeOfFirstParameterOfSignature(signature: Signature) { return getTypeAtPosition(signature, 0); } - + /** * Gets the "awaited type" of a type. * @param type The type to await. - * @remarks The "awaited type" of an expression is its "promised type" if the expression is a + * @remarks The "awaited type" of an expression is its "promised type" if the expression is a * Promise-like type; otherwise, it is the type of the expression. This is used to reflect * The runtime behavior of the `await` keyword. */ function getAwaitedType(type: Type) { return checkAwaitedType(type, /*location*/ undefined, /*message*/ undefined); } - + function checkAwaitedType(type: Type, location?: Node, message?: DiagnosticMessage) { return checkAwaitedTypeWorker(type); - + function checkAwaitedTypeWorker(type: Type): Type { if (type.flags & TypeFlags.Union) { let types: Type[] = []; for (let constituentType of (type).types) { types.push(checkAwaitedTypeWorker(constituentType)); } - + return getUnionType(types); } else { let promisedType = getPromisedType(type); if (promisedType === undefined) { // The type was not a PromiseLike, so it could not be unwrapped any further. - // As long as the type does not have a callable "then" property, it is + // As long as the type does not have a callable "then" property, it is // safe to return the type; otherwise, an error will have been reported in // the call to checkNonThenableType and we will return unknownType. // @@ -10771,7 +10783,7 @@ namespace ts { // The "thenable" does not match the minimal definition for a PromiseLike. When // a Promise/A+-compatible or ES6 promise tries to adopt this value, the promise // will never settle. We treat this as an error to help flag an early indicator - // of a runtime problem. If the user wants to return this value from an async + // of a runtime problem. If the user wants to return this value from an async // function, they would need to wrap it in some other value. If they want it to // be treated as a promise, they can cast to . return checkNonThenableType(type, location, message); @@ -10779,70 +10791,70 @@ namespace ts { else { if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) { // We have a bad actor in the form of a promise whose promised type is - // the same promise type, or a mutually recursive promise. Return the - // unknown type as we cannot guess the shape. If this were the actual + // the same promise type, or a mutually recursive promise. Return the + // unknown type as we cannot guess the shape. If this were the actual // case in the JavaScript, this Promise would never resolve. // - // An example of a bad actor with a singly-recursive promise type might + // An example of a bad actor with a singly-recursive promise type might // be: // // interface BadPromise { // then( - // onfulfilled: (value: BadPromise) => any, + // onfulfilled: (value: BadPromise) => any, // onrejected: (error: any) => any): BadPromise; // } // - // The above interface will pass the PromiseLike check, and return a - // promised type of `BadPromise`. Since this is a self reference, we + // The above interface will pass the PromiseLike check, and return a + // promised type of `BadPromise`. Since this is a self reference, we // don't want to keep recursing ad infinitum. // - // An example of a bad actor in the form of a mutually-recursive + // An example of a bad actor in the form of a mutually-recursive // promise type might be: // // interface BadPromiseA { // then( - // onfulfilled: (value: BadPromiseB) => any, + // onfulfilled: (value: BadPromiseB) => any, // onrejected: (error: any) => any): BadPromiseB; // } // // interface BadPromiseB { // then( - // onfulfilled: (value: BadPromiseA) => any, + // onfulfilled: (value: BadPromiseA) => any, // onrejected: (error: any) => any): BadPromiseA; // } // if (location) { error( - location, - Diagnostics._0_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method, + location, + Diagnostics._0_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method, symbolToString(type.symbol)); } - + return unknownType; } - + // Keep track of the type we're about to unwrap to avoid bad recursive promise types. // See the comments above for more information. awaitedTypeStack.push(type.id); let awaitedType = checkAwaitedTypeWorker(promisedType); awaitedTypeStack.pop(); - return awaitedType; + return awaitedType; } } } } /** - * Checks the return type of an async function to ensure it is a compatible + * Checks the return type of an async function to ensure it is a compatible * Promise implementation. * @param node The signature to check * @param returnType The return type for the function - * @remarks - * This checks that an async function has a valid Promise-compatible return type, - * and returns the *awaited type* of the promise. An async function has a valid - * Promise-compatible return type if the resolved value of the return type has a + * @remarks + * This checks that an async function has a valid Promise-compatible return type, + * and returns the *awaited type* of the promise. An async function has a valid + * Promise-compatible return type if the resolved value of the return type has a * construct signature that takes in an `initializer` function that in turn supplies - * a `resolve` function as one of its arguments and results in an object with a + * a `resolve` function as one of its arguments and results in an object with a * callable `then` signature. */ function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type { @@ -10855,7 +10867,7 @@ namespace ts { // As part of our emit for an async function, we will need to emit the entity name of // the return type annotation as an expression. To meet the necessary runtime semantics - // for __awaiter, we must also check that the type of the declaration (e.g. the static + // for __awaiter, we must also check that the type of the declaration (e.g. the static // side or "constructor" of the promise type) is compatible `PromiseConstructorLike`. // // An example might be (from lib.es6.d.ts): @@ -10863,11 +10875,11 @@ namespace ts { // interface Promise { ... } // interface PromiseConstructor { // new (...): Promise; - // } + // } // declare var Promise: PromiseConstructor; // - // When an async function declares a return type annotation of `Promise`, we - // need to get the type of the `Promise` variable declaration above, which would + // When an async function declares a return type annotation of `Promise`, we + // need to get the type of the `Promise` variable declaration above, which would // be `PromiseConstructor`. // // The same case applies to a class: @@ -10879,20 +10891,20 @@ namespace ts { // // When we get the type of the `Promise` symbol here, we get the type of the static // side of the `Promise` class, which would be `{ new (...): Promise }`. - + let promiseType = getTypeFromTypeNode(node.type); if (promiseType === unknownType && compilerOptions.isolatedModules) { - // If we are compiling with isolatedModules, we may not be able to resolve the + // If we are compiling with isolatedModules, we may not be able to resolve the // type as a value. As such, we will just return unknownType; return unknownType; } - + let promiseConstructor = getMergedSymbol(promiseType.symbol); if (!promiseConstructor || !symbolIsValue(promiseConstructor)) { error(node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeToString(promiseType)); return unknownType } - + // Validate the promise constructor type. let promiseConstructorType = getTypeOfSymbol(promiseConstructor); if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) { @@ -10913,7 +10925,7 @@ namespace ts { // Get and return the awaited type of the return type. return checkAwaitedType(promiseType, node, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type); } - + /** Check a decorator */ function checkDecorator(node: Decorator): void { let signature = getResolvedSignature(node); @@ -10963,11 +10975,11 @@ namespace ts { headMessage, errorInfo); } - + /** 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); @@ -10982,7 +10994,7 @@ namespace 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) { @@ -11004,7 +11016,7 @@ namespace 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 @@ -11078,9 +11090,9 @@ namespace ts { if (!compilerOptions.experimentalAsyncFunctions) { error(node, Diagnostics.Experimental_support_for_async_functions_is_a_feature_that_is_subject_to_change_in_a_future_release_Specify_experimentalAsyncFunctions_to_remove_this_warning); } - + emitAwaiter = true; - } + } // Do not use hasDynamicName here, because that returns false for well known symbols. // We want to perform checkComputedPropertyName for all computed properties, including @@ -11120,7 +11132,7 @@ namespace ts { if (isAsync) { promisedType = checkAsyncFunctionReturnType(node); } - + checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType); } @@ -11332,7 +11344,7 @@ namespace ts { } } } - + // Check that a parameter initializer contains no references to parameters declared to the right of itself function checkParameterInitializer(node: VariableLikeDeclaration): void { if (getRootDeclaration(node).kind !== SyntaxKind.Parameter) { @@ -11653,7 +11665,7 @@ namespace ts { return elementType || anyType; } - + /** * We want to treat type as an iterable, and get the type it is an iterable of. The iterable * must have the following structure (annotated with the names of the variables below): @@ -12280,20 +12292,20 @@ namespace ts { // In order to resolve whether the inherited method was overriden in the base class or not, // we compare the Symbols obtained. Since getTargetSymbol returns the symbol on the *uninstantiated* // type declaration, derived and base resolve to the same symbol even in the case of generic classes. - if (derived === base) { + if (derived === base) { // derived class inherits base without override/redeclaration let derivedClassDecl = getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration); // It is an error to inherit an abstract member without implementing it or being declared abstract. - // If there is no declaration for the derived class (as in the case of class expressions), - // then the class cannot be declared abstract. + // If there is no declaration for the derived class (as in the case of class expressions), + // then the class cannot be declared abstract. if ( baseDeclarationFlags & NodeFlags.Abstract && (!derivedClassDecl || !(derivedClassDecl.flags & NodeFlags.Abstract))) { error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2, typeToString(type), symbolToString(baseProperty), typeToString(baseType)); } } - else { + else { // derived overrides base. let derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived); if ((baseDeclarationFlags & NodeFlags.Private) || (derivedDeclarationFlags & NodeFlags.Private)) { @@ -12764,7 +12776,7 @@ namespace 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); if (mergedClass && @@ -13298,7 +13310,7 @@ namespace ts { forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope); potentialThisCollisions.length = 0; } - + if (emitExtends) { links.flags |= NodeCheckFlags.EmitExtends; } @@ -13310,11 +13322,11 @@ namespace ts { if (emitParam) { links.flags |= NodeCheckFlags.EmitParam; } - + if (emitAwaiter) { links.flags |= NodeCheckFlags.EmitAwaiter; } - + if (emitGenerator || (emitAwaiter && languageVersion < ScriptTarget.ES6)) { links.flags |= NodeCheckFlags.EmitGenerator; } @@ -13713,7 +13725,7 @@ namespace ts { } /** - * Gets either the static or instance type of a class element, based on + * Gets either the static or instance type of a class element, based on * whether the element is declared as "static". */ function getParentTypeOfClassElement(node: ClassElement) { @@ -13722,7 +13734,7 @@ namespace ts { ? getTypeOfSymbol(classSymbol) : getDeclaredTypeOfSymbol(classSymbol); } - + // Return the list of properties of the given type, augmented with properties from Function // if the type has call or construct signatures function getAugmentedPropertiesOfType(type: Type): Symbol[] { @@ -14061,7 +14073,7 @@ namespace 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"; @@ -14075,14 +14087,14 @@ namespace ts { } 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): (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; @@ -14299,21 +14311,21 @@ namespace ts { anyArrayType = createArrayType(anyType); } - + function createInstantiatedPromiseLikeType(): ObjectType { let promiseLikeType = getGlobalPromiseLikeType(); if (promiseLikeType !== emptyObjectType) { return createTypeReference(promiseLikeType, [anyType]); } - + return emptyObjectType; } - + function createThenableType() { // build the thenable type that is used to verify against a non-promise "thenable" operand to `await`. let thenPropertySymbol = createSymbol(SymbolFlags.Transient | SymbolFlags.Property, "then"); getSymbolLinks(thenPropertySymbol).type = globalFunctionType; - + let thenableType = createObjectType(TypeFlags.Anonymous); thenableType.properties = [thenPropertySymbol]; thenableType.members = createSymbolTable(thenableType.properties); diff --git a/src/compiler/declarationEmitter.ts b/src/compiler/declarationEmitter.ts index 3db032b8d0d..97c85c70de1 100644 --- a/src/compiler/declarationEmitter.ts +++ b/src/compiler/declarationEmitter.ts @@ -401,7 +401,7 @@ namespace ts { } function emitTypePredicate(type: TypePredicateNode) { - writeEntityName(type.parameterName); + writeTextOfNode(currentSourceFile, type.parameterName); write(" is "); emitType(type.type); } diff --git a/tests/cases/compiler/declFileFunctions.ts b/tests/cases/compiler/declFileFunctions.ts index 36972d427f0..7b9c55e9214 100644 --- a/tests/cases/compiler/declFileFunctions.ts +++ b/tests/cases/compiler/declFileFunctions.ts @@ -31,6 +31,15 @@ export function fooWithSingleOverload(a: any) { export function fooWithTypePredicate(a: any): a is number { return true; } +export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number { + return true; +} +export function fooWithTypeTypePredicateAndGeneric(a: any): a is T { + return true; +} +export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number { + return true; +} /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { diff --git a/tests/cases/fourslash/signatureHelpOnTypePredicates.ts b/tests/cases/fourslash/signatureHelpOnTypePredicates.ts new file mode 100644 index 00000000000..bfaa7df2502 --- /dev/null +++ b/tests/cases/fourslash/signatureHelpOnTypePredicates.ts @@ -0,0 +1,20 @@ +/// + +//// function f1(a: any): a is number {} +//// function f2(a: any): a is T {} +//// function f3(a: any, ...b): a is number {} +//// f1(/*1*/) +//// f2(/*2*/) +//// f3(/*3*/) + +goTo.marker("1"); +verify.signatureHelpCountIs(1); +verify.currentSignatureHelpIs("f1(a: any): a is number"); + +goTo.marker("2"); +verify.signatureHelpCountIs(1); +verify.currentSignatureHelpIs("f2(a: any): a is T"); + +goTo.marker("3"); +verify.signatureHelpCountIs(1); +verify.currentSignatureHelpIs("f3(a: any, ...b: any[]): a is number"); \ No newline at end of file From 52b1496a64d0e2ece12834668b295e519b2d9e25 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Thu, 9 Jul 2015 11:48:42 +0800 Subject: [PATCH 4/5] Accepts baselines --- .../baselines/reference/declFileFunctions.js | 28 +++++++++ .../reference/declFileFunctions.symbols | 62 +++++++++++++------ .../reference/declFileFunctions.types | 31 +++++++++- tests/baselines/reference/isArray.types | 4 +- .../reference/typeGuardFunction.types | 46 +++++++------- .../typeGuardFunctionErrors.errors.txt | 16 ++--- .../reference/typeGuardFunctionGenerics.types | 34 +++++----- .../reference/typeGuardOfFormIsType.types | 22 +++---- .../typeGuardOfFormIsTypeOnInterfaces.types | 22 +++---- 9 files changed, 174 insertions(+), 91 deletions(-) diff --git a/tests/baselines/reference/declFileFunctions.js b/tests/baselines/reference/declFileFunctions.js index d3debf4d50c..163fa1905c8 100644 --- a/tests/baselines/reference/declFileFunctions.js +++ b/tests/baselines/reference/declFileFunctions.js @@ -29,6 +29,15 @@ export function fooWithSingleOverload(a: any) { export function fooWithTypePredicate(a: any): a is number { return true; } +export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number { + return true; +} +export function fooWithTypeTypePredicateAndGeneric(a: any): a is T { + return true; +} +export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number { + return true; +} /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { @@ -100,6 +109,22 @@ function fooWithTypePredicate(a) { return true; } exports.fooWithTypePredicate = fooWithTypePredicate; +function fooWithTypePredicateAndMulitpleParams(a, b, c) { + return true; +} +exports.fooWithTypePredicateAndMulitpleParams = fooWithTypePredicateAndMulitpleParams; +function fooWithTypeTypePredicateAndGeneric(a) { + return true; +} +exports.fooWithTypeTypePredicateAndGeneric = fooWithTypeTypePredicateAndGeneric; +function fooWithTypeTypePredicateAndRestParam(a) { + var rest = []; + for (var _i = 1; _i < arguments.length; _i++) { + rest[_i - 1] = arguments[_i]; + } + return true; +} +exports.fooWithTypeTypePredicateAndRestParam = fooWithTypeTypePredicateAndRestParam; /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { } @@ -153,6 +178,9 @@ export declare function fooWithOverloads(a: string): string; export declare function fooWithOverloads(a: number): number; export declare function fooWithSingleOverload(a: string): string; export declare function fooWithTypePredicate(a: any): a is number; +export declare function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number; +export declare function fooWithTypeTypePredicateAndGeneric(a: any): a is T; +export declare function fooWithTypeTypePredicateAndRestParam(a: any, ...rest: any[]): a is number; //// [declFileFunctions_1.d.ts] /** This comment should appear for foo*/ declare function globalfoo(): void; diff --git a/tests/baselines/reference/declFileFunctions.symbols b/tests/baselines/reference/declFileFunctions.symbols index 1d62cc29d28..1853da94a46 100644 --- a/tests/baselines/reference/declFileFunctions.symbols +++ b/tests/baselines/reference/declFileFunctions.symbols @@ -64,50 +64,76 @@ export function fooWithTypePredicate(a: any): a is number { return true; } +export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number { +>fooWithTypePredicateAndMulitpleParams : Symbol(fooWithTypePredicateAndMulitpleParams, Decl(declFileFunctions_0.ts, 27, 1)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 28, 54)) +>b : Symbol(b, Decl(declFileFunctions_0.ts, 28, 61)) +>c : Symbol(c, Decl(declFileFunctions_0.ts, 28, 69)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 28, 54)) + + return true; +} +export function fooWithTypeTypePredicateAndGeneric(a: any): a is T { +>fooWithTypeTypePredicateAndGeneric : Symbol(fooWithTypeTypePredicateAndGeneric, Decl(declFileFunctions_0.ts, 30, 1)) +>T : Symbol(T, Decl(declFileFunctions_0.ts, 31, 51)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 31, 54)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 31, 54)) +>T : Symbol(T, Decl(declFileFunctions_0.ts, 31, 51)) + + return true; +} +export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number { +>fooWithTypeTypePredicateAndRestParam : Symbol(fooWithTypeTypePredicateAndRestParam, Decl(declFileFunctions_0.ts, 33, 1)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 53)) +>rest : Symbol(rest, Decl(declFileFunctions_0.ts, 34, 60)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 34, 53)) + + return true; +} /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { ->nonExportedFoo : Symbol(nonExportedFoo, Decl(declFileFunctions_0.ts, 27, 1)) +>nonExportedFoo : Symbol(nonExportedFoo, Decl(declFileFunctions_0.ts, 36, 1)) } /** This is comment for function signature*/ function nonExportedFooWithParameters(/** this is comment about a*/a: string, ->nonExportedFooWithParameters : Symbol(nonExportedFooWithParameters, Decl(declFileFunctions_0.ts, 31, 1)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 33, 38)) +>nonExportedFooWithParameters : Symbol(nonExportedFooWithParameters, Decl(declFileFunctions_0.ts, 40, 1)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 42, 38)) /** this is comment for b*/ b: number) { ->b : Symbol(b, Decl(declFileFunctions_0.ts, 33, 77)) +>b : Symbol(b, Decl(declFileFunctions_0.ts, 42, 77)) var d = a; ->d : Symbol(d, Decl(declFileFunctions_0.ts, 36, 7)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 33, 38)) +>d : Symbol(d, Decl(declFileFunctions_0.ts, 45, 7)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 42, 38)) } function nonExportedFooWithRestParameters(a: string, ...rests: string[]) { ->nonExportedFooWithRestParameters : Symbol(nonExportedFooWithRestParameters, Decl(declFileFunctions_0.ts, 37, 1)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 38, 42)) ->rests : Symbol(rests, Decl(declFileFunctions_0.ts, 38, 52)) +>nonExportedFooWithRestParameters : Symbol(nonExportedFooWithRestParameters, Decl(declFileFunctions_0.ts, 46, 1)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 47, 42)) +>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 47, 52)) return a + rests.join(""); ->a : Symbol(a, Decl(declFileFunctions_0.ts, 38, 42)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 47, 42)) >rests.join : Symbol(Array.join, Decl(lib.d.ts, 1035, 31)) ->rests : Symbol(rests, Decl(declFileFunctions_0.ts, 38, 52)) +>rests : Symbol(rests, Decl(declFileFunctions_0.ts, 47, 52)) >join : Symbol(Array.join, Decl(lib.d.ts, 1035, 31)) } function nonExportedFooWithOverloads(a: string): string; ->nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 40, 1), Decl(declFileFunctions_0.ts, 42, 56), Decl(declFileFunctions_0.ts, 43, 56)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 42, 37)) +>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 49, 1), Decl(declFileFunctions_0.ts, 51, 56), Decl(declFileFunctions_0.ts, 52, 56)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 51, 37)) function nonExportedFooWithOverloads(a: number): number; ->nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 40, 1), Decl(declFileFunctions_0.ts, 42, 56), Decl(declFileFunctions_0.ts, 43, 56)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 43, 37)) +>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 49, 1), Decl(declFileFunctions_0.ts, 51, 56), Decl(declFileFunctions_0.ts, 52, 56)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 52, 37)) function nonExportedFooWithOverloads(a: any): any { ->nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 40, 1), Decl(declFileFunctions_0.ts, 42, 56), Decl(declFileFunctions_0.ts, 43, 56)) ->a : Symbol(a, Decl(declFileFunctions_0.ts, 44, 37)) +>nonExportedFooWithOverloads : Symbol(nonExportedFooWithOverloads, Decl(declFileFunctions_0.ts, 49, 1), Decl(declFileFunctions_0.ts, 51, 56), Decl(declFileFunctions_0.ts, 52, 56)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 53, 37)) return a; ->a : Symbol(a, Decl(declFileFunctions_0.ts, 44, 37)) +>a : Symbol(a, Decl(declFileFunctions_0.ts, 53, 37)) } === tests/cases/compiler/declFileFunctions_1.ts === diff --git a/tests/baselines/reference/declFileFunctions.types b/tests/baselines/reference/declFileFunctions.types index e6ecc53b043..9ad974463b7 100644 --- a/tests/baselines/reference/declFileFunctions.types +++ b/tests/baselines/reference/declFileFunctions.types @@ -61,13 +61,42 @@ export function fooWithSingleOverload(a: any) { } export function fooWithTypePredicate(a: any): a is number { ->fooWithTypePredicate : (a: any) => boolean +>fooWithTypePredicate : (a: any) => a is number >a : any >a : any return true; >true : boolean } +export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number { +>fooWithTypePredicateAndMulitpleParams : (a: any, b: any, c: any) => a is number +>a : any +>b : any +>c : any +>a : any + + return true; +>true : boolean +} +export function fooWithTypeTypePredicateAndGeneric(a: any): a is T { +>fooWithTypeTypePredicateAndGeneric : (a: any) => a is T +>T : T +>a : any +>a : any +>T : T + + return true; +>true : boolean +} +export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number { +>fooWithTypeTypePredicateAndRestParam : (a: any, ...rest: any[]) => a is number +>a : any +>rest : any[] +>a : any + + return true; +>true : boolean +} /** This comment should appear for nonExportedFoo*/ function nonExportedFoo() { diff --git a/tests/baselines/reference/isArray.types b/tests/baselines/reference/isArray.types index 8865ff73bc0..bc452b12bef 100644 --- a/tests/baselines/reference/isArray.types +++ b/tests/baselines/reference/isArray.types @@ -5,9 +5,9 @@ var maybeArray: number | number[]; if (Array.isArray(maybeArray)) { >Array.isArray(maybeArray) : boolean ->Array.isArray : (arg: any) => boolean +>Array.isArray : (arg: any) => arg is any[] >Array : ArrayConstructor ->isArray : (arg: any) => boolean +>isArray : (arg: any) => arg is any[] >maybeArray : number | number[] maybeArray.length; // OK diff --git a/tests/baselines/reference/typeGuardFunction.types b/tests/baselines/reference/typeGuardFunction.types index cf673f965f9..6cc278f122f 100644 --- a/tests/baselines/reference/typeGuardFunction.types +++ b/tests/baselines/reference/typeGuardFunction.types @@ -23,19 +23,19 @@ class C extends A { } declare function isA(p1: any): p1 is A; ->isA : (p1: any) => boolean +>isA : (p1: any) => p1 is A >p1 : any >p1 : any >A : A declare function isB(p1: any): p1 is B; ->isB : (p1: any) => boolean +>isB : (p1: any) => p1 is B >p1 : any >p1 : any >B : B declare function isC(p1: any): p1 is C; ->isC : (p1: any) => boolean +>isC : (p1: any) => p1 is C >p1 : any >p1 : any >C : C @@ -55,7 +55,7 @@ var b: B; // Basic if (isC(a)) { >isC(a) : boolean ->isC : (p1: any) => boolean +>isC : (p1: any) => p1 is C >a : A a.propC; @@ -71,7 +71,7 @@ var subType: C; if(isA(subType)) { >isA(subType) : boolean ->isA : (p1: any) => boolean +>isA : (p1: any) => p1 is A >subType : C subType.propC; @@ -88,7 +88,7 @@ var union: A | B; if(isA(union)) { >isA(union) : boolean ->isA : (p1: any) => boolean +>isA : (p1: any) => p1 is A >union : A | B union.propA; @@ -111,7 +111,7 @@ interface I1 { // The parameter index and argument index for the type guard target is matching. // The type predicate type is assignable to the parameter type. declare function isC_multipleParams(p1, p2): p1 is C; ->isC_multipleParams : (p1: any, p2: any) => boolean +>isC_multipleParams : (p1: any, p2: any) => p1 is C >p1 : any >p2 : any >p1 : any @@ -119,7 +119,7 @@ declare function isC_multipleParams(p1, p2): p1 is C; if (isC_multipleParams(a, 0)) { >isC_multipleParams(a, 0) : boolean ->isC_multipleParams : (p1: any, p2: any) => boolean +>isC_multipleParams : (p1: any, p2: any) => p1 is C >a : A >0 : number @@ -131,10 +131,10 @@ if (isC_multipleParams(a, 0)) { // Methods var obj: { ->obj : { func1(p1: A): boolean; } +>obj : { func1(p1: A): p1 is C; } func1(p1: A): p1 is C; ->func1 : (p1: A) => boolean +>func1 : (p1: A) => p1 is C >p1 : A >A : A >p1 : any @@ -144,7 +144,7 @@ class D { >D : D method1(p1: A): p1 is C { ->method1 : (p1: A) => boolean +>method1 : (p1: A) => p1 is C >p1 : A >A : A >p1 : any @@ -157,8 +157,8 @@ class D { // Arrow function let f1 = (p1: A): p1 is C => false; ->f1 : (p1: A) => boolean ->(p1: A): p1 is C => false : (p1: A) => boolean +>f1 : (p1: A) => p1 is C +>(p1: A): p1 is C => false : (p1: A) => p1 is C >p1 : A >A : A >p1 : any @@ -167,8 +167,8 @@ let f1 = (p1: A): p1 is C => false; // Function type declare function f2(p1: (p1: A) => p1 is C); ->f2 : (p1: (p1: A) => boolean) => any ->p1 : (p1: A) => boolean +>f2 : (p1: (p1: A) => p1 is C) => any +>p1 : (p1: A) => p1 is C >p1 : A >A : A >p1 : any @@ -177,8 +177,8 @@ declare function f2(p1: (p1: A) => p1 is C); // Function expressions f2(function(p1: A): p1 is C { >f2(function(p1: A): p1 is C { return true;}) : any ->f2 : (p1: (p1: A) => boolean) => any ->function(p1: A): p1 is C { return true;} : (p1: A) => boolean +>f2 : (p1: (p1: A) => p1 is C) => any +>function(p1: A): p1 is C { return true;} : (p1: A) => p1 is C >p1 : A >A : A >p1 : any @@ -198,21 +198,21 @@ acceptingBoolean(isA(a)); >acceptingBoolean(isA(a)) : any >acceptingBoolean : (a: boolean) => any >isA(a) : boolean ->isA : (p1: any) => boolean +>isA : (p1: any) => p1 is A >a : A // Type predicates with different parameter name. declare function acceptingTypeGuardFunction(p1: (item) => item is A); ->acceptingTypeGuardFunction : (p1: (item: any) => boolean) => any ->p1 : (item: any) => boolean +>acceptingTypeGuardFunction : (p1: (item: any) => item is A) => any +>p1 : (item: any) => item is A >item : any >item : any >A : A acceptingTypeGuardFunction(isA); >acceptingTypeGuardFunction(isA) : any ->acceptingTypeGuardFunction : (p1: (item: any) => boolean) => any ->isA : (p1: any) => boolean +>acceptingTypeGuardFunction : (p1: (item: any) => item is A) => any +>isA : (p1: any) => p1 is A // Binary expressions let union2: C | B; @@ -225,7 +225,7 @@ let union3: boolean | B = isA(union2) || union2; >B : B >isA(union2) || union2 : boolean | B >isA(union2) : boolean ->isA : (p1: any) => boolean +>isA : (p1: any) => p1 is A >union2 : B | C >union2 : B diff --git a/tests/baselines/reference/typeGuardFunctionErrors.errors.txt b/tests/baselines/reference/typeGuardFunctionErrors.errors.txt index 499a51035f2..b178b02c6b4 100644 --- a/tests/baselines/reference/typeGuardFunctionErrors.errors.txt +++ b/tests/baselines/reference/typeGuardFunctionErrors.errors.txt @@ -12,15 +12,15 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(46,56) tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(60,7): error TS2339: Property 'propB' does not exist on type 'A'. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(65,7): error TS2339: Property 'propB' does not exist on type 'A'. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(70,7): error TS2339: Property 'propB' does not exist on type 'A'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(75,46): error TS2345: Argument of type '(p1: any) => boolean' is not assignable to parameter of type '(p1: any) => boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(75,46): error TS2345: Argument of type '(p1: any) => p1 is C' is not assignable to parameter of type '(p1: any) => p1 is B'. Type predicate 'p1 is C' is not assignable to 'p1 is B'. Type 'C' is not assignable to type 'B'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(79,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(79,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => p1 is A'. Signature '(p1: any, p2: any): boolean' must have a type predicate. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(85,1): error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(85,1): error TS2322: Type '(p1: any, p2: any) => p2 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'. Type predicate 'p2 is A' is not assignable to 'p1 is A'. Parameter 'p2' is not in the same position as parameter 'p1'. -tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(91,1): error TS2322: Type '(p1: any, p2: any, p3: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. +tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(91,1): error TS2322: Type '(p1: any, p2: any, p3: any) => p1 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(96,9): error TS1228: A type predicate is only allowed in return type position for functions and methods. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(97,16): error TS1228: A type predicate is only allowed in return type position for functions and methods. tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(98,20): error TS1228: A type predicate is only allowed in return type position for functions and methods. @@ -141,7 +141,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39 declare function acceptingDifferentSignatureTypeGuardFunction(p1: (p1) => p1 is B); acceptingDifferentSignatureTypeGuardFunction(isC); ~~~ -!!! error TS2345: Argument of type '(p1: any) => boolean' is not assignable to parameter of type '(p1: any) => boolean'. +!!! error TS2345: Argument of type '(p1: any) => p1 is C' is not assignable to parameter of type '(p1: any) => p1 is B'. !!! error TS2345: Type predicate 'p1 is C' is not assignable to 'p1 is B'. !!! error TS2345: Type 'C' is not assignable to type 'B'. @@ -149,7 +149,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39 var assign1: (p1, p2) => p1 is A; assign1 = function(p1, p2): boolean { ~~~~~~~ -!!! error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. +!!! error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => p1 is A'. !!! error TS2322: Signature '(p1: any, p2: any): boolean' must have a type predicate. return true; }; @@ -158,7 +158,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39 var assign2: (p1, p2) => p1 is A; assign2 = function(p1, p2): p2 is A { ~~~~~~~ -!!! error TS2322: Type '(p1: any, p2: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. +!!! error TS2322: Type '(p1: any, p2: any) => p2 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'. !!! error TS2322: Type predicate 'p2 is A' is not assignable to 'p1 is A'. !!! error TS2322: Parameter 'p2' is not in the same position as parameter 'p1'. return true; @@ -168,7 +168,7 @@ tests/cases/conformance/expressions/typeGuards/typeGuardFunctionErrors.ts(137,39 var assign3: (p1, p2) => p1 is A; assign3 = function(p1, p2, p3): p1 is A { ~~~~~~~ -!!! error TS2322: Type '(p1: any, p2: any, p3: any) => boolean' is not assignable to type '(p1: any, p2: any) => boolean'. +!!! error TS2322: Type '(p1: any, p2: any, p3: any) => p1 is A' is not assignable to type '(p1: any, p2: any) => p1 is A'. return true; }; diff --git a/tests/baselines/reference/typeGuardFunctionGenerics.types b/tests/baselines/reference/typeGuardFunctionGenerics.types index 77162e55a40..c4655e71f0c 100644 --- a/tests/baselines/reference/typeGuardFunctionGenerics.types +++ b/tests/baselines/reference/typeGuardFunctionGenerics.types @@ -23,13 +23,13 @@ class C extends A { } declare function isB(p1): p1 is B; ->isB : (p1: any) => boolean +>isB : (p1: any) => p1 is B >p1 : any >p1 : any >B : B declare function isC(p1): p1 is C; ->isC : (p1: any) => boolean +>isC : (p1: any) => p1 is C >p1 : any >p1 : any >C : C @@ -48,7 +48,7 @@ declare function funA(p1: (p1) => T): T; >T : T declare function funB(p1: (p1) => T, p2: any): p2 is T; ->funB : (p1: (p1: any) => T, p2: any) => boolean +>funB : (p1: (p1: any) => T, p2: any) => p2 is T >T : T >p1 : (p1: any) => T >p1 : any @@ -58,18 +58,18 @@ declare function funB(p1: (p1) => T, p2: any): p2 is T; >T : T declare function funC(p1: (p1) => p1 is T): T; ->funC : (p1: (p1: any) => boolean) => T +>funC : (p1: (p1: any) => p1 is T) => T >T : T ->p1 : (p1: any) => boolean +>p1 : (p1: any) => p1 is T >p1 : any >p1 : any >T : T >T : T declare function funD(p1: (p1) => p1 is T, p2: any): p2 is T; ->funD : (p1: (p1: any) => boolean, p2: any) => boolean +>funD : (p1: (p1: any) => p1 is T, p2: any) => p2 is T >T : T ->p1 : (p1: any) => boolean +>p1 : (p1: any) => p1 is T >p1 : any >p1 : any >T : T @@ -78,10 +78,10 @@ declare function funD(p1: (p1) => p1 is T, p2: any): p2 is T; >T : T declare function funE(p1: (p1) => p1 is T, p2: U): T; ->funE : (p1: (p1: any) => boolean, p2: U) => T +>funE : (p1: (p1: any) => p1 is T, p2: U) => T >T : T >U : U ->p1 : (p1: any) => boolean +>p1 : (p1: any) => p1 is T >p1 : any >p1 : any >T : T @@ -97,11 +97,11 @@ let test1: boolean = funA(isB); >test1 : boolean >funA(isB) : boolean >funA : (p1: (p1: any) => T) => T ->isB : (p1: any) => boolean +>isB : (p1: any) => p1 is B if (funB(retC, a)) { >funB(retC, a) : boolean ->funB : (p1: (p1: any) => T, p2: any) => boolean +>funB : (p1: (p1: any) => T, p2: any) => p2 is T >retC : (x: any) => C >a : A @@ -114,13 +114,13 @@ let test2: B = funC(isB); >test2 : B >B : B >funC(isB) : B ->funC : (p1: (p1: any) => boolean) => T ->isB : (p1: any) => boolean +>funC : (p1: (p1: any) => p1 is T) => T +>isB : (p1: any) => p1 is B if (funD(isC, a)) { >funD(isC, a) : boolean ->funD : (p1: (p1: any) => boolean, p2: any) => boolean ->isC : (p1: any) => boolean +>funD : (p1: (p1: any) => p1 is T, p2: any) => p2 is T +>isC : (p1: any) => p1 is C >a : A a.propC; @@ -132,7 +132,7 @@ let test3: B = funE(isB, 1); >test3 : B >B : B >funE(isB, 1) : B ->funE : (p1: (p1: any) => boolean, p2: U) => T ->isB : (p1: any) => boolean +>funE : (p1: (p1: any) => p1 is T, p2: U) => T +>isB : (p1: any) => p1 is B >1 : number diff --git a/tests/baselines/reference/typeGuardOfFormIsType.types b/tests/baselines/reference/typeGuardOfFormIsType.types index b14e5e22910..e2059be7b63 100644 --- a/tests/baselines/reference/typeGuardOfFormIsType.types +++ b/tests/baselines/reference/typeGuardOfFormIsType.types @@ -29,7 +29,7 @@ var strOrNum: string | number; >strOrNum : string | number function isC1(x: any): x is C1 { ->isC1 : (x: any) => boolean +>isC1 : (x: any) => x is C1 >x : any >x : any >C1 : C1 @@ -39,7 +39,7 @@ function isC1(x: any): x is C1 { } function isC2(x: any): x is C2 { ->isC2 : (x: any) => boolean +>isC2 : (x: any) => x is C2 >x : any >x : any >C2 : C2 @@ -49,7 +49,7 @@ function isC2(x: any): x is C2 { } function isD1(x: any): x is D1 { ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >x : any >x : any >D1 : D1 @@ -68,7 +68,7 @@ str = isC1(c1Orc2) && c1Orc2.p1; // C1 >str : string >isC1(c1Orc2) && c1Orc2.p1 : string >isC1(c1Orc2) : boolean ->isC1 : (x: any) => boolean +>isC1 : (x: any) => x is C1 >c1Orc2 : C1 | C2 >c1Orc2.p1 : string >c1Orc2 : C1 @@ -79,7 +79,7 @@ num = isC2(c1Orc2) && c1Orc2.p2; // C2 >num : number >isC2(c1Orc2) && c1Orc2.p2 : number >isC2(c1Orc2) : boolean ->isC2 : (x: any) => boolean +>isC2 : (x: any) => x is C2 >c1Orc2 : C1 | C2 >c1Orc2.p2 : number >c1Orc2 : C2 @@ -90,7 +90,7 @@ str = isD1(c1Orc2) && c1Orc2.p1; // D1 >str : string >isD1(c1Orc2) && c1Orc2.p1 : string >isD1(c1Orc2) : boolean ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >c1Orc2 : C1 | C2 >c1Orc2.p1 : string >c1Orc2 : D1 @@ -101,7 +101,7 @@ num = isD1(c1Orc2) && c1Orc2.p3; // D1 >num : number >isD1(c1Orc2) && c1Orc2.p3 : number >isD1(c1Orc2) : boolean ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >c1Orc2 : C1 | C2 >c1Orc2.p3 : number >c1Orc2 : D1 @@ -117,7 +117,7 @@ num = isC2(c2Ord1) && c2Ord1.p2; // C2 >num : number >isC2(c2Ord1) && c2Ord1.p2 : number >isC2(c2Ord1) : boolean ->isC2 : (x: any) => boolean +>isC2 : (x: any) => x is C2 >c2Ord1 : C2 | D1 >c2Ord1.p2 : number >c2Ord1 : C2 @@ -128,7 +128,7 @@ num = isD1(c2Ord1) && c2Ord1.p3; // D1 >num : number >isD1(c2Ord1) && c2Ord1.p3 : number >isD1(c2Ord1) : boolean ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >c2Ord1 : C2 | D1 >c2Ord1.p3 : number >c2Ord1 : D1 @@ -139,7 +139,7 @@ str = isD1(c2Ord1) && c2Ord1.p1; // D1 >str : string >isD1(c2Ord1) && c2Ord1.p1 : string >isD1(c2Ord1) : boolean ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >c2Ord1 : C2 | D1 >c2Ord1.p1 : string >c2Ord1 : D1 @@ -151,7 +151,7 @@ var r2: C2 | D1 = isC1(c2Ord1) && c2Ord1; // C2 | D1 >D1 : D1 >isC1(c2Ord1) && c2Ord1 : D1 >isC1(c2Ord1) : boolean ->isC1 : (x: any) => boolean +>isC1 : (x: any) => x is C1 >c2Ord1 : C2 | D1 >c2Ord1 : D1 diff --git a/tests/baselines/reference/typeGuardOfFormIsTypeOnInterfaces.types b/tests/baselines/reference/typeGuardOfFormIsTypeOnInterfaces.types index 3a659d71163..ea169e95413 100644 --- a/tests/baselines/reference/typeGuardOfFormIsTypeOnInterfaces.types +++ b/tests/baselines/reference/typeGuardOfFormIsTypeOnInterfaces.types @@ -48,7 +48,7 @@ var strOrNum: string | number; function isC1(x: any): x is C1 { ->isC1 : (x: any) => boolean +>isC1 : (x: any) => x is C1 >x : any >x : any >C1 : C1 @@ -58,7 +58,7 @@ function isC1(x: any): x is C1 { } function isC2(x: any): x is C2 { ->isC2 : (x: any) => boolean +>isC2 : (x: any) => x is C2 >x : any >x : any >C2 : C2 @@ -68,7 +68,7 @@ function isC2(x: any): x is C2 { } function isD1(x: any): x is D1 { ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >x : any >x : any >D1 : D1 @@ -99,7 +99,7 @@ str = isC1(c1Orc2) && c1Orc2.p1; // C1 >str : string >isC1(c1Orc2) && c1Orc2.p1 : string >isC1(c1Orc2) : boolean ->isC1 : (x: any) => boolean +>isC1 : (x: any) => x is C1 >c1Orc2 : C1 | C2 >c1Orc2.p1 : string >c1Orc2 : C1 @@ -110,7 +110,7 @@ num = isC2(c1Orc2) && c1Orc2.p2; // C2 >num : number >isC2(c1Orc2) && c1Orc2.p2 : number >isC2(c1Orc2) : boolean ->isC2 : (x: any) => boolean +>isC2 : (x: any) => x is C2 >c1Orc2 : C1 | C2 >c1Orc2.p2 : number >c1Orc2 : C2 @@ -121,7 +121,7 @@ str = isD1(c1Orc2) && c1Orc2.p1; // D1 >str : string >isD1(c1Orc2) && c1Orc2.p1 : string >isD1(c1Orc2) : boolean ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >c1Orc2 : C1 | C2 >c1Orc2.p1 : string >c1Orc2 : D1 @@ -132,7 +132,7 @@ num = isD1(c1Orc2) && c1Orc2.p3; // D1 >num : number >isD1(c1Orc2) && c1Orc2.p3 : number >isD1(c1Orc2) : boolean ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >c1Orc2 : C1 | C2 >c1Orc2.p3 : number >c1Orc2 : D1 @@ -148,7 +148,7 @@ num = isC2(c2Ord1) && c2Ord1.p2; // C2 >num : number >isC2(c2Ord1) && c2Ord1.p2 : number >isC2(c2Ord1) : boolean ->isC2 : (x: any) => boolean +>isC2 : (x: any) => x is C2 >c2Ord1 : C2 | D1 >c2Ord1.p2 : number >c2Ord1 : C2 @@ -159,7 +159,7 @@ num = isD1(c2Ord1) && c2Ord1.p3; // D1 >num : number >isD1(c2Ord1) && c2Ord1.p3 : number >isD1(c2Ord1) : boolean ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >c2Ord1 : C2 | D1 >c2Ord1.p3 : number >c2Ord1 : D1 @@ -170,7 +170,7 @@ str = isD1(c2Ord1) && c2Ord1.p1; // D1 >str : string >isD1(c2Ord1) && c2Ord1.p1 : string >isD1(c2Ord1) : boolean ->isD1 : (x: any) => boolean +>isD1 : (x: any) => x is D1 >c2Ord1 : C2 | D1 >c2Ord1.p1 : string >c2Ord1 : D1 @@ -182,7 +182,7 @@ var r2: C2 | D1 = isC1(c2Ord1) && c2Ord1; // C2 | D1 >D1 : D1 >isC1(c2Ord1) && c2Ord1 : D1 >isC1(c2Ord1) : boolean ->isC1 : (x: any) => boolean +>isC1 : (x: any) => x is C1 >c2Ord1 : C2 | D1 >c2Ord1 : D1 From 4e644e5ab849e98da526f733b2ce938d981d2719 Mon Sep 17 00:00:00 2001 From: Tingan Ho Date: Fri, 10 Jul 2015 03:27:31 +0800 Subject: [PATCH 5/5] Fixes spacing issue --- src/compiler/checker.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 03a3f7efa9b..08f4605ebe2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -1958,7 +1958,7 @@ namespace ts { returnType = signature.typePredicate.type; } else { - returnType = getReturnTypeOfSignature(signature); + returnType = getReturnTypeOfSignature(signature); } buildTypeDisplay(returnType, writer, enclosingDeclaration, flags, symbolStack); }