Adds type predicate signature display and addresses CR feedback
This commit is contained in:
parent
08a7744254
commit
28976a0e34
|
@ -25,12 +25,12 @@ namespace ts {
|
||||||
// Cancellation that controls whether or not we can cancel in the middle of type checking.
|
// 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
|
// 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
|
// 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.
|
// should throw away and create a new TypeChecker.
|
||||||
//
|
//
|
||||||
// Currently we only support setting the cancellation token when getting diagnostics. This
|
// 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
|
// 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 cancellationToken: CancellationToken;
|
||||||
|
|
||||||
let Symbol = objectAllocator.getSymbolConstructor();
|
let Symbol = objectAllocator.getSymbolConstructor();
|
||||||
|
@ -117,7 +117,7 @@ namespace ts {
|
||||||
let globals: SymbolTable = {};
|
let globals: SymbolTable = {};
|
||||||
|
|
||||||
let globalESSymbolConstructorSymbol: Symbol;
|
let globalESSymbolConstructorSymbol: Symbol;
|
||||||
|
|
||||||
let getGlobalPromiseConstructorSymbol: () => Symbol;
|
let getGlobalPromiseConstructorSymbol: () => Symbol;
|
||||||
|
|
||||||
let globalObjectType: ObjectType;
|
let globalObjectType: ObjectType;
|
||||||
|
@ -148,7 +148,7 @@ namespace ts {
|
||||||
let getInstantiatedGlobalPromiseLikeType: () => ObjectType;
|
let getInstantiatedGlobalPromiseLikeType: () => ObjectType;
|
||||||
let getGlobalPromiseConstructorLikeType: () => ObjectType;
|
let getGlobalPromiseConstructorLikeType: () => ObjectType;
|
||||||
let getGlobalThenableType: () => ObjectType;
|
let getGlobalThenableType: () => ObjectType;
|
||||||
|
|
||||||
let tupleTypes: Map<TupleType> = {};
|
let tupleTypes: Map<TupleType> = {};
|
||||||
let unionTypes: Map<UnionType> = {};
|
let unionTypes: Map<UnionType> = {};
|
||||||
let intersectionTypes: Map<IntersectionType> = {};
|
let intersectionTypes: Map<IntersectionType> = {};
|
||||||
|
@ -158,7 +158,7 @@ namespace ts {
|
||||||
let emitParam = false;
|
let emitParam = false;
|
||||||
let emitAwaiter = false;
|
let emitAwaiter = false;
|
||||||
let emitGenerator = false;
|
let emitGenerator = false;
|
||||||
|
|
||||||
let resolutionTargets: Object[] = [];
|
let resolutionTargets: Object[] = [];
|
||||||
let resolutionResults: boolean[] = [];
|
let resolutionResults: boolean[] = [];
|
||||||
|
|
||||||
|
@ -406,7 +406,7 @@ namespace ts {
|
||||||
let moduleExports = getSymbolOfNode(location).exports;
|
let moduleExports = getSymbolOfNode(location).exports;
|
||||||
if (location.kind === SyntaxKind.SourceFile ||
|
if (location.kind === SyntaxKind.SourceFile ||
|
||||||
(location.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>location).name.kind === SyntaxKind.StringLiteral)) {
|
(location.kind === SyntaxKind.ModuleDeclaration && (<ModuleDeclaration>location).name.kind === SyntaxKind.StringLiteral)) {
|
||||||
|
|
||||||
// It's an external module. Because of module/namespace merging, a module's exports are in scope,
|
// 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,
|
// 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.
|
// if the name we find is purely an export specifier, it is not actually considered in scope.
|
||||||
|
@ -526,7 +526,7 @@ namespace ts {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case SyntaxKind.Decorator:
|
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.
|
// or member would result in looking up locals in the method.
|
||||||
//
|
//
|
||||||
// function y() {}
|
// function y() {}
|
||||||
|
@ -1948,7 +1948,19 @@ namespace ts {
|
||||||
writePunctuation(writer, SyntaxKind.ColonToken);
|
writePunctuation(writer, SyntaxKind.ColonToken);
|
||||||
}
|
}
|
||||||
writeSpace(writer);
|
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[]) {
|
function buildSignatureDisplay(signature: Signature, writer: SymbolWriter, enclosingDeclaration?: Node, flags?: TypeFormatFlags, symbolStack?: Symbol[]) {
|
||||||
|
@ -2098,7 +2110,7 @@ namespace ts {
|
||||||
case SyntaxKind.ParenthesizedType:
|
case SyntaxKind.ParenthesizedType:
|
||||||
return isDeclarationVisible(<Declaration>node.parent);
|
return isDeclarationVisible(<Declaration>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
|
// only on demand so by default it is not visible
|
||||||
case SyntaxKind.ImportClause:
|
case SyntaxKind.ImportClause:
|
||||||
case SyntaxKind.NamespaceImport:
|
case SyntaxKind.NamespaceImport:
|
||||||
|
@ -3864,7 +3876,7 @@ namespace ts {
|
||||||
function getGlobalType(name: string, arity = 0): ObjectType {
|
function getGlobalType(name: string, arity = 0): ObjectType {
|
||||||
return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity);
|
return getTypeOfGlobalSymbol(getGlobalTypeSymbol(name), arity);
|
||||||
}
|
}
|
||||||
|
|
||||||
function tryGetGlobalType(name: string, arity = 0): ObjectType {
|
function tryGetGlobalType(name: string, arity = 0): ObjectType {
|
||||||
return getTypeOfGlobalSymbol(getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined), arity);
|
return getTypeOfGlobalSymbol(getGlobalSymbol(name, SymbolFlags.Type, /*diagnostic*/ undefined), arity);
|
||||||
}
|
}
|
||||||
|
@ -3892,7 +3904,7 @@ namespace ts {
|
||||||
? createTypeReference(<GenericType>globalTypedPropertyDescriptorType, [propertyType])
|
? createTypeReference(<GenericType>globalTypedPropertyDescriptorType, [propertyType])
|
||||||
: emptyObjectType;
|
: emptyObjectType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates a global type that is generic with some element type, and returns that instantiation.
|
* Instantiates a global type that is generic with some element type, and returns that instantiation.
|
||||||
*/
|
*/
|
||||||
|
@ -4117,7 +4129,7 @@ namespace ts {
|
||||||
}
|
}
|
||||||
return links.resolvedType;
|
return links.resolvedType;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTypeFromTypeNode(node: TypeNode): Type {
|
function getTypeFromTypeNode(node: TypeNode): Type {
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
case SyntaxKind.AnyKeyword:
|
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);
|
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) {
|
if (node.parserContextFlags & ParserContextFlags.Await) {
|
||||||
getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
|
getNodeLinks(container).flags |= NodeCheckFlags.CaptureArguments;
|
||||||
getNodeLinks(node).flags |= NodeCheckFlags.LexicalArguments;
|
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.
|
// 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
|
// 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,
|
// 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
|
// 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
|
// get the contextual element type from it. So we do something similar to
|
||||||
// getContextualTypeForElementExpression, which will crucially not error
|
// getContextualTypeForElementExpression, which will crucially not error
|
||||||
|
@ -7399,7 +7411,7 @@ namespace ts {
|
||||||
|
|
||||||
if (flags & NodeFlags.Abstract) {
|
if (flags & NodeFlags.Abstract) {
|
||||||
// A method cannot be accessed in a super property access if the method is 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
|
// cannot simultaneously be private and abstract, so this will trigger an
|
||||||
// additional error elsewhere.
|
// additional error elsewhere.
|
||||||
|
|
||||||
|
@ -7478,7 +7490,7 @@ namespace ts {
|
||||||
}
|
}
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
getNodeLinks(node).resolvedSymbol = prop;
|
getNodeLinks(node).resolvedSymbol = prop;
|
||||||
|
|
||||||
if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
|
if (prop.parent && prop.parent.flags & SymbolFlags.Class) {
|
||||||
|
@ -7875,7 +7887,7 @@ namespace ts {
|
||||||
let paramType = getTypeAtPosition(signature, i);
|
let paramType = getTypeAtPosition(signature, i);
|
||||||
let argType = getEffectiveArgumentType(node, i, arg);
|
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.
|
// for the argument. In that case, we should check the argument.
|
||||||
if (argType === undefined) {
|
if (argType === undefined) {
|
||||||
// For context sensitive arguments we pass the identityMapper, which is a signal to treat all
|
// 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)
|
// Check spread elements against rest type (from arity check we know spread argument corresponds to a rest parameter)
|
||||||
let paramType = getTypeAtPosition(signature, i);
|
let paramType = getTypeAtPosition(signature, i);
|
||||||
let argType = getEffectiveArgumentType(node, i, arg);
|
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.
|
// for the argument. In that case, we should check the argument.
|
||||||
if (argType === undefined) {
|
if (argType === undefined) {
|
||||||
argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors
|
argType = arg.kind === SyntaxKind.StringLiteral && !reportErrors
|
||||||
|
@ -8001,18 +8013,18 @@ namespace ts {
|
||||||
return args;
|
return args;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the effective argument count for a node that works like a function invocation.
|
* 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
|
* If 'node' is a Decorator, the number of arguments is derived from the decoration
|
||||||
* target and the signature:
|
* 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.
|
* count is 1.
|
||||||
* If 'node.target' is a parameter declaration, the effective argument count is 3.
|
* 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 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
|
* 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.
|
* Otherwise, the argument count is the length of the 'args' array.
|
||||||
*/
|
*/
|
||||||
function getEffectiveArgumentCount(node: CallLikeExpression, args: Expression[], signature: Signature) {
|
function getEffectiveArgumentCount(node: CallLikeExpression, args: Expression[], signature: Signature) {
|
||||||
|
@ -8024,7 +8036,7 @@ namespace ts {
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
case SyntaxKind.PropertyDeclaration:
|
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)
|
// `PropertyDecorator` in core.d.ts)
|
||||||
return 2;
|
return 2;
|
||||||
|
|
||||||
|
@ -8033,12 +8045,12 @@ namespace ts {
|
||||||
case SyntaxKind.SetAccessor:
|
case SyntaxKind.SetAccessor:
|
||||||
// A method or accessor declaration decorator will have two or three arguments (see
|
// A method or accessor declaration decorator will have two or three arguments (see
|
||||||
// `PropertyDecorator` and `MethodDecorator` in core.d.ts)
|
// `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.
|
// type check those arguments.
|
||||||
return signature.parameters.length >= 3 ? 3 : 2;
|
return signature.parameters.length >= 3 ? 3 : 2;
|
||||||
|
|
||||||
case SyntaxKind.Parameter:
|
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)
|
// `ParameterDecorator` in core.d.ts)
|
||||||
|
|
||||||
return 3;
|
return 3;
|
||||||
|
@ -8048,47 +8060,47 @@ namespace ts {
|
||||||
return args.length;
|
return args.length;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the effective type of the first argument to a decorator.
|
* Returns the effective type of the first argument to a decorator.
|
||||||
* If 'node' is a class declaration or class expression, the effective argument type
|
* If 'node' is a class declaration or class expression, the effective argument type
|
||||||
* is the type of the static side of the class.
|
* is the type of the static side of the class.
|
||||||
* If 'node' is a parameter declaration, the effective argument type is either the type
|
* 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.
|
* depending on whether the method is declared static.
|
||||||
* For a constructor, the type is always the type of the static side of the class.
|
* 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
|
* 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
|
* 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.
|
* element, depending on whether the element is declared static.
|
||||||
*/
|
*/
|
||||||
function getEffectiveDecoratorFirstArgumentType(node: Node): Type {
|
function getEffectiveDecoratorFirstArgumentType(node: Node): Type {
|
||||||
// The first argument to a decorator is its `target`.
|
// The first argument to a decorator is its `target`.
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
case SyntaxKind.ClassDeclaration:
|
case SyntaxKind.ClassDeclaration:
|
||||||
case SyntaxKind.ClassExpression:
|
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)
|
// "static" or "constructor" side of the class)
|
||||||
let classSymbol = getSymbolOfNode(node);
|
let classSymbol = getSymbolOfNode(node);
|
||||||
return getTypeOfSymbol(classSymbol);
|
return getTypeOfSymbol(classSymbol);
|
||||||
|
|
||||||
case SyntaxKind.Parameter:
|
case SyntaxKind.Parameter:
|
||||||
// For a parameter decorator, the `target` is the parent type of the
|
// For a parameter decorator, the `target` is the parent type of the
|
||||||
// parameter's containing method.
|
// parameter's containing method.
|
||||||
node = node.parent;
|
node = node.parent;
|
||||||
if (node.kind === SyntaxKind.Constructor) {
|
if (node.kind === SyntaxKind.Constructor) {
|
||||||
let classSymbol = getSymbolOfNode(node);
|
let classSymbol = getSymbolOfNode(node);
|
||||||
return getTypeOfSymbol(classSymbol);
|
return getTypeOfSymbol(classSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// fall-through
|
// fall-through
|
||||||
|
|
||||||
case SyntaxKind.PropertyDeclaration:
|
case SyntaxKind.PropertyDeclaration:
|
||||||
case SyntaxKind.MethodDeclaration:
|
case SyntaxKind.MethodDeclaration:
|
||||||
case SyntaxKind.GetAccessor:
|
case SyntaxKind.GetAccessor:
|
||||||
case SyntaxKind.SetAccessor:
|
case SyntaxKind.SetAccessor:
|
||||||
// For a property or method decorator, the `target` is the
|
// For a property or method decorator, the `target` is the
|
||||||
// "static"-side type of the parent of the member if the member is
|
// "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.
|
// parent of the member.
|
||||||
return getParentTypeOfClassElement(<ClassElement>node);
|
return getParentTypeOfClassElement(<ClassElement>node);
|
||||||
|
|
||||||
|
@ -8097,19 +8109,19 @@ namespace ts {
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the effective type for the second argument to a decorator.
|
* 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' 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`.
|
* 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.
|
* 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.
|
* 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.
|
* 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.
|
* be a symbol type or the string type.
|
||||||
* A class decorator does not have a second argument 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`.
|
// For a constructor parameter decorator, the `propertyKey` will be `undefined`.
|
||||||
return anyType;
|
return anyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// For a non-constructor parameter decorator, the `propertyKey` will be either
|
// 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.
|
// a string or a symbol, based on the name of the parameter's containing method.
|
||||||
|
|
||||||
// fall-through
|
// fall-through
|
||||||
|
|
||||||
case SyntaxKind.PropertyDeclaration:
|
case SyntaxKind.PropertyDeclaration:
|
||||||
case SyntaxKind.MethodDeclaration:
|
case SyntaxKind.MethodDeclaration:
|
||||||
case SyntaxKind.GetAccessor:
|
case SyntaxKind.GetAccessor:
|
||||||
case SyntaxKind.SetAccessor:
|
case SyntaxKind.SetAccessor:
|
||||||
// The `propertyKey` for a property or method decorator will be a
|
// 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
|
// otherwise, if the member name is a computed property name it will
|
||||||
// be either string or symbol.
|
// be either string or symbol.
|
||||||
let element = <ClassElement>node;
|
let element = <ClassElement>node;
|
||||||
|
@ -8167,11 +8179,11 @@ namespace ts {
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the effective argument type for the third argument to a decorator.
|
* 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 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<T>` instantiated with the type of the member.
|
* `TypedPropertyDescriptor<T>` instantiated with the type of the member.
|
||||||
* Class and property decorators do not have a third effective argument.
|
* Class and property decorators do not have a third effective argument.
|
||||||
*/
|
*/
|
||||||
|
@ -8204,7 +8216,7 @@ namespace ts {
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the effective argument type for the provided argument to a decorator.
|
* 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.");
|
Debug.fail("Decorators should not have a fourth synthetic argument.");
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the effective argument type for an argument in a call expression.
|
* Gets the effective argument type for an argument in a call expression.
|
||||||
*/
|
*/
|
||||||
function getEffectiveArgumentType(node: CallLikeExpression, argIndex: number, arg: Expression): Type {
|
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
|
// a special first argument, and string literals get string literal types
|
||||||
// unless we're reporting errors
|
// unless we're reporting errors
|
||||||
if (node.kind === SyntaxKind.Decorator) {
|
if (node.kind === SyntaxKind.Decorator) {
|
||||||
|
@ -8238,12 +8250,12 @@ namespace ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
// This is not a synthetic argument, so we return 'undefined'
|
// 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;
|
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) {
|
function getEffectiveArgument(node: CallLikeExpression, args: Expression[], argIndex: number) {
|
||||||
// For a decorator or the first argument of a tagged template expression we return undefined.
|
// 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
|
// For a tagged template, then the first argument be 'undefined' if necessary
|
||||||
// because it represents a TemplateStringsArray.
|
// 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.
|
// decorators are applied to a declaration by the emitter, and not to an expression.
|
||||||
let excludeArgument: boolean[];
|
let excludeArgument: boolean[];
|
||||||
if (!isDecorator) {
|
if (!isDecorator) {
|
||||||
|
@ -8651,7 +8663,7 @@ namespace ts {
|
||||||
|
|
||||||
return resolveCall(node, callSignatures, candidatesOutArray);
|
return resolveCall(node, callSignatures, candidatesOutArray);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the localized diagnostic head message to use for errors when resolving a decorator as a call expression.
|
* 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);
|
links.type = instantiateType(getTypeOfSymbol(lastOrUndefined(context.parameters)), mapper);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function createPromiseType(promisedType: Type): Type {
|
function createPromiseType(promisedType: Type): Type {
|
||||||
// creates a `Promise<T>` type where `T` is the promisedType argument
|
// creates a `Promise<T>` type where `T` is the promisedType argument
|
||||||
let globalPromiseType = getGlobalPromiseType();
|
let globalPromiseType = getGlobalPromiseType();
|
||||||
|
@ -8806,7 +8818,7 @@ namespace ts {
|
||||||
promisedType = getAwaitedType(promisedType);
|
promisedType = getAwaitedType(promisedType);
|
||||||
return createTypeReference(<GenericType>globalPromiseType, [promisedType]);
|
return createTypeReference(<GenericType>globalPromiseType, [promisedType]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return emptyObjectType;
|
return emptyObjectType;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8815,15 +8827,15 @@ namespace ts {
|
||||||
if (!func.body) {
|
if (!func.body) {
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
let isAsync = isAsyncFunctionLike(func);
|
let isAsync = isAsyncFunctionLike(func);
|
||||||
let type: Type;
|
let type: Type;
|
||||||
if (func.body.kind !== SyntaxKind.Block) {
|
if (func.body.kind !== SyntaxKind.Block) {
|
||||||
type = checkExpressionCached(<Expression>func.body, contextualMapper);
|
type = checkExpressionCached(<Expression>func.body, contextualMapper);
|
||||||
if (isAsync) {
|
if (isAsync) {
|
||||||
// From within an async function you can return either a non-promise value or a promise. Any
|
// 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
|
// 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
|
// return type of the body should be unwrapped to its awaited type, which we will wrap in
|
||||||
// the native Promise<T> type later in this function.
|
// the native Promise<T> type later in this function.
|
||||||
type = checkAwaitedType(type, func, Diagnostics.Return_expression_in_async_function_does_not_have_a_valid_callable_then_member);
|
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);
|
error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return promiseType;
|
return promiseType;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return voidType;
|
return voidType;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// When yield/return statements are contextually typed we allow the return type to be a union type.
|
// 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.
|
// Otherwise we require the yield/return expressions to have a best common supertype.
|
||||||
|
@ -8881,19 +8893,19 @@ namespace ts {
|
||||||
if (!contextualSignature) {
|
if (!contextualSignature) {
|
||||||
reportErrorsFromWidening(func, type);
|
reportErrorsFromWidening(func, type);
|
||||||
}
|
}
|
||||||
|
|
||||||
let widenedType = getWidenedType(type);
|
let widenedType = getWidenedType(type);
|
||||||
if (isAsync) {
|
if (isAsync) {
|
||||||
// From within an async function you can return either a non-promise value or a promise. Any
|
// 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
|
// 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<T> type.
|
// return type of the body is awaited type of the body, wrapped in a native Promise<T> type.
|
||||||
let promiseType = createPromiseType(widenedType);
|
let promiseType = createPromiseType(widenedType);
|
||||||
if (promiseType === emptyObjectType) {
|
if (promiseType === emptyObjectType) {
|
||||||
error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
|
error(func, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return promiseType;
|
return promiseType;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return widenedType;
|
return widenedType;
|
||||||
|
@ -8928,13 +8940,13 @@ namespace ts {
|
||||||
forEachReturnStatement(body, returnStatement => {
|
forEachReturnStatement(body, returnStatement => {
|
||||||
let expr = returnStatement.expression;
|
let expr = returnStatement.expression;
|
||||||
if (expr) {
|
if (expr) {
|
||||||
let type = checkExpressionCached(expr, contextualMapper);
|
let type = checkExpressionCached(expr, contextualMapper);
|
||||||
if (isAsync) {
|
if (isAsync) {
|
||||||
// From within an async function you can return either a non-promise value or a promise. Any
|
// 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
|
// 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
|
// return type of the body should be unwrapped to its awaited type, which should be wrapped in
|
||||||
// the native Promise<T> type by the caller.
|
// the native Promise<T> 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)) {
|
if (!contains(aggregatedTypes, type)) {
|
||||||
|
@ -9006,12 +9018,12 @@ namespace ts {
|
||||||
if (contextualMapper === identityMapper && isContextSensitive(node)) {
|
if (contextualMapper === identityMapper && isContextSensitive(node)) {
|
||||||
return anyFunctionType;
|
return anyFunctionType;
|
||||||
}
|
}
|
||||||
|
|
||||||
let isAsync = isAsyncFunctionLike(node);
|
let isAsync = isAsyncFunctionLike(node);
|
||||||
if (isAsync) {
|
if (isAsync) {
|
||||||
emitAwaiter = true;
|
emitAwaiter = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let links = getNodeLinks(node);
|
let links = getNodeLinks(node);
|
||||||
let type = getTypeOfSymbol(node.symbol);
|
let type = getTypeOfSymbol(node.symbol);
|
||||||
// Check if function expression is contextually typed and assign parameter types if so
|
// Check if function expression is contextually typed and assign parameter types if so
|
||||||
|
@ -9048,7 +9060,7 @@ namespace ts {
|
||||||
|
|
||||||
function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) {
|
function checkFunctionExpressionOrObjectLiteralMethodBody(node: FunctionExpression | MethodDeclaration) {
|
||||||
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
|
Debug.assert(node.kind !== SyntaxKind.MethodDeclaration || isObjectLiteralMethod(node));
|
||||||
|
|
||||||
let isAsync = isAsyncFunctionLike(node);
|
let isAsync = isAsyncFunctionLike(node);
|
||||||
if (isAsync) {
|
if (isAsync) {
|
||||||
emitAwaiter = true;
|
emitAwaiter = true;
|
||||||
|
@ -9059,7 +9071,7 @@ namespace ts {
|
||||||
if (returnType && isAsync) {
|
if (returnType && isAsync) {
|
||||||
promisedType = checkAsyncFunctionReturnType(node);
|
promisedType = checkAsyncFunctionReturnType(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (returnType && !node.asteriskToken) {
|
if (returnType && !node.asteriskToken) {
|
||||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType);
|
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType);
|
||||||
}
|
}
|
||||||
|
@ -9078,10 +9090,10 @@ namespace ts {
|
||||||
checkSourceElement(node.body);
|
checkSourceElement(node.body);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// From within an async function you can return either a non-promise value or a promise. Any
|
// 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
|
// 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
|
// 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
|
// check assignability of the awaited type of the expression body against the promised type of
|
||||||
// its return type annotation.
|
// its return type annotation.
|
||||||
let exprType = checkExpression(<Expression>node.body);
|
let exprType = checkExpression(<Expression>node.body);
|
||||||
if (returnType) {
|
if (returnType) {
|
||||||
|
@ -9093,7 +9105,7 @@ namespace ts {
|
||||||
checkTypeAssignableTo(exprType, returnType, node.body);
|
checkTypeAssignableTo(exprType, returnType, node.body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
checkFunctionAndClassExpressionBodies(node.body);
|
checkFunctionAndClassExpressionBodies(node.body);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -9215,7 +9227,7 @@ namespace ts {
|
||||||
let operandType = checkExpression(node.expression);
|
let operandType = checkExpression(node.expression);
|
||||||
return checkAwaitedType(operandType, node);
|
return checkAwaitedType(operandType, node);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
|
function checkPrefixUnaryExpression(node: PrefixUnaryExpression): Type {
|
||||||
let operandType = checkExpression(node.operand);
|
let operandType = checkExpression(node.operand);
|
||||||
switch (node.operator) {
|
switch (node.operator) {
|
||||||
|
@ -9688,7 +9700,7 @@ namespace ts {
|
||||||
node.contextualType = saveContextualType;
|
node.contextualType = saveContextualType;
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
|
function checkExpressionCached(node: Expression, contextualMapper?: TypeMapper): Type {
|
||||||
let links = getNodeLinks(node);
|
let links = getNodeLinks(node);
|
||||||
if (!links.resolvedType) {
|
if (!links.resolvedType) {
|
||||||
|
@ -9895,7 +9907,7 @@ namespace ts {
|
||||||
if (node.questionToken && isBindingPattern(node.name) && func.body) {
|
if (node.questionToken && isBindingPattern(node.name) && func.body) {
|
||||||
error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature);
|
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
|
// 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.
|
// not allowed in a rest parameter, we already have an error from checkGrammarParameterList.
|
||||||
if (node.dotDotDotToken && !isBindingPattern(node.name) && !isArrayType(getTypeOfSymbol(node.symbol))) {
|
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
|
// Grammar checking for modifiers is done inside the function checkGrammarFunctionLikeDeclaration
|
||||||
checkFunctionLikeDeclaration(node);
|
checkFunctionLikeDeclaration(node);
|
||||||
|
|
||||||
// Abstract methods cannot have an implementation.
|
// Abstract methods cannot have an implementation.
|
||||||
// Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node.
|
// Extra checks are to avoid reporting multiple errors relating to the "abstractness" of the node.
|
||||||
if(node.flags & NodeFlags.Abstract && node.body) {
|
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.
|
// 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) ) {
|
!(lastSeenNonAmbientDeclaration.flags & NodeFlags.Abstract) ) {
|
||||||
reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
|
reportImplementationExpectedError(lastSeenNonAmbientDeclaration);
|
||||||
}
|
}
|
||||||
|
@ -10666,13 +10678,13 @@ namespace ts {
|
||||||
if (!message) {
|
if (!message) {
|
||||||
message = Diagnostics.Operand_for_await_does_not_have_a_valid_callable_then_member;
|
message = Diagnostics.Operand_for_await_does_not_have_a_valid_callable_then_member;
|
||||||
}
|
}
|
||||||
|
|
||||||
error(location, message);
|
error(location, message);
|
||||||
}
|
}
|
||||||
|
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -10690,16 +10702,16 @@ namespace ts {
|
||||||
// ) => any
|
// ) => any
|
||||||
// ): any;
|
// ): any;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
|
|
||||||
if (promise.flags & TypeFlags.Any) {
|
if (promise.flags & TypeFlags.Any) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((promise.flags & TypeFlags.Reference) && (<GenericType>promise).target === tryGetGlobalPromiseType()) {
|
if ((promise.flags & TypeFlags.Reference) && (<GenericType>promise).target === tryGetGlobalPromiseType()) {
|
||||||
return (<GenericType>promise).typeArguments[0];
|
return (<GenericType>promise).typeArguments[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
let globalPromiseLikeType = getInstantiatedGlobalPromiseLikeType();
|
let globalPromiseLikeType = getInstantiatedGlobalPromiseLikeType();
|
||||||
if (globalPromiseLikeType === emptyObjectType || !isTypeAssignableTo(promise, globalPromiseLikeType)) {
|
if (globalPromiseLikeType === emptyObjectType || !isTypeAssignableTo(promise, globalPromiseLikeType)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
|
@ -10709,58 +10721,58 @@ namespace ts {
|
||||||
if (thenFunction && (thenFunction.flags & TypeFlags.Any)) {
|
if (thenFunction && (thenFunction.flags & TypeFlags.Any)) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, SignatureKind.Call) : emptyArray;
|
let thenSignatures = thenFunction ? getSignaturesOfType(thenFunction, SignatureKind.Call) : emptyArray;
|
||||||
if (thenSignatures.length === 0) {
|
if (thenSignatures.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let onfulfilledParameterType = getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature));
|
let onfulfilledParameterType = getUnionType(map(thenSignatures, getTypeOfFirstParameterOfSignature));
|
||||||
if (onfulfilledParameterType.flags & TypeFlags.Any) {
|
if (onfulfilledParameterType.flags & TypeFlags.Any) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, SignatureKind.Call);
|
let onfulfilledParameterSignatures = getSignaturesOfType(onfulfilledParameterType, SignatureKind.Call);
|
||||||
if (onfulfilledParameterSignatures.length === 0) {
|
if (onfulfilledParameterSignatures.length === 0) {
|
||||||
return undefined;
|
return undefined;
|
||||||
}
|
}
|
||||||
|
|
||||||
let valueParameterType = getUnionType(map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature));
|
let valueParameterType = getUnionType(map(onfulfilledParameterSignatures, getTypeOfFirstParameterOfSignature));
|
||||||
return valueParameterType;
|
return valueParameterType;
|
||||||
}
|
}
|
||||||
|
|
||||||
function getTypeOfFirstParameterOfSignature(signature: Signature) {
|
function getTypeOfFirstParameterOfSignature(signature: Signature) {
|
||||||
return getTypeAtPosition(signature, 0);
|
return getTypeAtPosition(signature, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the "awaited type" of a type.
|
* Gets the "awaited type" of a type.
|
||||||
* @param type The type to await.
|
* @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
|
* Promise-like type; otherwise, it is the type of the expression. This is used to reflect
|
||||||
* The runtime behavior of the `await` keyword.
|
* The runtime behavior of the `await` keyword.
|
||||||
*/
|
*/
|
||||||
function getAwaitedType(type: Type) {
|
function getAwaitedType(type: Type) {
|
||||||
return checkAwaitedType(type, /*location*/ undefined, /*message*/ undefined);
|
return checkAwaitedType(type, /*location*/ undefined, /*message*/ undefined);
|
||||||
}
|
}
|
||||||
|
|
||||||
function checkAwaitedType(type: Type, location?: Node, message?: DiagnosticMessage) {
|
function checkAwaitedType(type: Type, location?: Node, message?: DiagnosticMessage) {
|
||||||
return checkAwaitedTypeWorker(type);
|
return checkAwaitedTypeWorker(type);
|
||||||
|
|
||||||
function checkAwaitedTypeWorker(type: Type): Type {
|
function checkAwaitedTypeWorker(type: Type): Type {
|
||||||
if (type.flags & TypeFlags.Union) {
|
if (type.flags & TypeFlags.Union) {
|
||||||
let types: Type[] = [];
|
let types: Type[] = [];
|
||||||
for (let constituentType of (<UnionType>type).types) {
|
for (let constituentType of (<UnionType>type).types) {
|
||||||
types.push(checkAwaitedTypeWorker(constituentType));
|
types.push(checkAwaitedTypeWorker(constituentType));
|
||||||
}
|
}
|
||||||
|
|
||||||
return getUnionType(types);
|
return getUnionType(types);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
let promisedType = getPromisedType(type);
|
let promisedType = getPromisedType(type);
|
||||||
if (promisedType === undefined) {
|
if (promisedType === undefined) {
|
||||||
// The type was not a PromiseLike, so it could not be unwrapped any further.
|
// 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
|
// safe to return the type; otherwise, an error will have been reported in
|
||||||
// the call to checkNonThenableType and we will return unknownType.
|
// 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
|
// 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
|
// 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
|
// 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
|
// 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 <any>.
|
// be treated as a promise, they can cast to <any>.
|
||||||
return checkNonThenableType(type, location, message);
|
return checkNonThenableType(type, location, message);
|
||||||
|
@ -10779,70 +10791,70 @@ namespace ts {
|
||||||
else {
|
else {
|
||||||
if (type.id === promisedType.id || awaitedTypeStack.indexOf(promisedType.id) >= 0) {
|
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
|
// 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
|
// the same promise type, or a mutually recursive promise. Return the
|
||||||
// unknown type as we cannot guess the shape. If this were the actual
|
// unknown type as we cannot guess the shape. If this were the actual
|
||||||
// case in the JavaScript, this Promise would never resolve.
|
// 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:
|
// be:
|
||||||
//
|
//
|
||||||
// interface BadPromise {
|
// interface BadPromise {
|
||||||
// then(
|
// then(
|
||||||
// onfulfilled: (value: BadPromise) => any,
|
// onfulfilled: (value: BadPromise) => any,
|
||||||
// onrejected: (error: any) => any): BadPromise;
|
// onrejected: (error: any) => any): BadPromise;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// The above interface will pass the PromiseLike check, and return a
|
// The above interface will pass the PromiseLike check, and return a
|
||||||
// promised type of `BadPromise`. Since this is a self reference, we
|
// promised type of `BadPromise`. Since this is a self reference, we
|
||||||
// don't want to keep recursing ad infinitum.
|
// 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:
|
// promise type might be:
|
||||||
//
|
//
|
||||||
// interface BadPromiseA {
|
// interface BadPromiseA {
|
||||||
// then(
|
// then(
|
||||||
// onfulfilled: (value: BadPromiseB) => any,
|
// onfulfilled: (value: BadPromiseB) => any,
|
||||||
// onrejected: (error: any) => any): BadPromiseB;
|
// onrejected: (error: any) => any): BadPromiseB;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
// interface BadPromiseB {
|
// interface BadPromiseB {
|
||||||
// then(
|
// then(
|
||||||
// onfulfilled: (value: BadPromiseA) => any,
|
// onfulfilled: (value: BadPromiseA) => any,
|
||||||
// onrejected: (error: any) => any): BadPromiseA;
|
// onrejected: (error: any) => any): BadPromiseA;
|
||||||
// }
|
// }
|
||||||
//
|
//
|
||||||
if (location) {
|
if (location) {
|
||||||
error(
|
error(
|
||||||
location,
|
location,
|
||||||
Diagnostics._0_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method,
|
Diagnostics._0_is_referenced_directly_or_indirectly_in_the_fulfillment_callback_of_its_own_then_method,
|
||||||
symbolToString(type.symbol));
|
symbolToString(type.symbol));
|
||||||
}
|
}
|
||||||
|
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Keep track of the type we're about to unwrap to avoid bad recursive promise types.
|
// Keep track of the type we're about to unwrap to avoid bad recursive promise types.
|
||||||
// See the comments above for more information.
|
// See the comments above for more information.
|
||||||
awaitedTypeStack.push(type.id);
|
awaitedTypeStack.push(type.id);
|
||||||
let awaitedType = checkAwaitedTypeWorker(promisedType);
|
let awaitedType = checkAwaitedTypeWorker(promisedType);
|
||||||
awaitedTypeStack.pop();
|
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.
|
* Promise implementation.
|
||||||
* @param node The signature to check
|
* @param node The signature to check
|
||||||
* @param returnType The return type for the function
|
* @param returnType The return type for the function
|
||||||
* @remarks
|
* @remarks
|
||||||
* This checks that an async function has a valid Promise-compatible return type,
|
* 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
|
* 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
|
* 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
|
* 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.
|
* callable `then` signature.
|
||||||
*/
|
*/
|
||||||
function checkAsyncFunctionReturnType(node: FunctionLikeDeclaration): Type {
|
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
|
// 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
|
// 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`.
|
// side or "constructor" of the promise type) is compatible `PromiseConstructorLike`.
|
||||||
//
|
//
|
||||||
// An example might be (from lib.es6.d.ts):
|
// An example might be (from lib.es6.d.ts):
|
||||||
|
@ -10863,11 +10875,11 @@ namespace ts {
|
||||||
// interface Promise<T> { ... }
|
// interface Promise<T> { ... }
|
||||||
// interface PromiseConstructor {
|
// interface PromiseConstructor {
|
||||||
// new <T>(...): Promise<T>;
|
// new <T>(...): Promise<T>;
|
||||||
// }
|
// }
|
||||||
// declare var Promise: PromiseConstructor;
|
// declare var Promise: PromiseConstructor;
|
||||||
//
|
//
|
||||||
// When an async function declares a return type annotation of `Promise<T>`, we
|
// When an async function declares a return type annotation of `Promise<T>`, we
|
||||||
// need to get the type of the `Promise` variable declaration above, which would
|
// need to get the type of the `Promise` variable declaration above, which would
|
||||||
// be `PromiseConstructor`.
|
// be `PromiseConstructor`.
|
||||||
//
|
//
|
||||||
// The same case applies to a class:
|
// 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
|
// 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 <T>(...): Promise<T> }`.
|
// side of the `Promise` class, which would be `{ new <T>(...): Promise<T> }`.
|
||||||
|
|
||||||
let promiseType = getTypeFromTypeNode(node.type);
|
let promiseType = getTypeFromTypeNode(node.type);
|
||||||
if (promiseType === unknownType && compilerOptions.isolatedModules) {
|
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;
|
// type as a value. As such, we will just return unknownType;
|
||||||
return unknownType;
|
return unknownType;
|
||||||
}
|
}
|
||||||
|
|
||||||
let promiseConstructor = getMergedSymbol(promiseType.symbol);
|
let promiseConstructor = getMergedSymbol(promiseType.symbol);
|
||||||
if (!promiseConstructor || !symbolIsValue(promiseConstructor)) {
|
if (!promiseConstructor || !symbolIsValue(promiseConstructor)) {
|
||||||
error(node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeToString(promiseType));
|
error(node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type, typeToString(promiseType));
|
||||||
return unknownType
|
return unknownType
|
||||||
}
|
}
|
||||||
|
|
||||||
// Validate the promise constructor type.
|
// Validate the promise constructor type.
|
||||||
let promiseConstructorType = getTypeOfSymbol(promiseConstructor);
|
let promiseConstructorType = getTypeOfSymbol(promiseConstructor);
|
||||||
if (!checkTypeAssignableTo(promiseConstructorType, globalPromiseConstructorLikeType, node, Diagnostics.Type_0_is_not_a_valid_async_function_return_type)) {
|
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.
|
// 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);
|
return checkAwaitedType(promiseType, node, Diagnostics.An_async_function_or_method_must_have_a_valid_awaitable_return_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Check a decorator */
|
/** Check a decorator */
|
||||||
function checkDecorator(node: Decorator): void {
|
function checkDecorator(node: Decorator): void {
|
||||||
let signature = getResolvedSignature(node);
|
let signature = getResolvedSignature(node);
|
||||||
|
@ -10963,11 +10975,11 @@ namespace ts {
|
||||||
headMessage,
|
headMessage,
|
||||||
errorInfo);
|
errorInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks a type reference node as an expression. */
|
/** Checks a type reference node as an expression. */
|
||||||
function checkTypeNodeAsExpression(node: TypeNode) {
|
function checkTypeNodeAsExpression(node: TypeNode) {
|
||||||
// When we are emitting type metadata for decorators, we need to try to check the type
|
// 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.
|
// serialize the type metadata.
|
||||||
if (node && node.kind === SyntaxKind.TypeReference) {
|
if (node && node.kind === SyntaxKind.TypeReference) {
|
||||||
let type = getTypeFromTypeNode(node);
|
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.
|
* an expression if it is a type reference to a type with a value declaration.
|
||||||
*/
|
*/
|
||||||
function checkTypeAnnotationAsExpression(node: AccessorDeclaration | PropertyDeclaration | ParameterDeclaration | MethodDeclaration) {
|
function checkTypeAnnotationAsExpression(node: AccessorDeclaration | PropertyDeclaration | ParameterDeclaration | MethodDeclaration) {
|
||||||
|
@ -11004,7 +11016,7 @@ namespace ts {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
|
/** Checks the type annotation of the parameters of a function/method or the constructor of a class as expressions */
|
||||||
function checkParameterTypeAnnotationsAsExpressions(node: FunctionLikeDeclaration) {
|
function checkParameterTypeAnnotationsAsExpressions(node: FunctionLikeDeclaration) {
|
||||||
// ensure all type annotations with a value declaration are checked as an expression
|
// ensure all type annotations with a value declaration are checked as an expression
|
||||||
|
@ -11078,9 +11090,9 @@ namespace ts {
|
||||||
if (!compilerOptions.experimentalAsyncFunctions) {
|
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);
|
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;
|
emitAwaiter = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not use hasDynamicName here, because that returns false for well known symbols.
|
// Do not use hasDynamicName here, because that returns false for well known symbols.
|
||||||
// We want to perform checkComputedPropertyName for all computed properties, including
|
// We want to perform checkComputedPropertyName for all computed properties, including
|
||||||
|
@ -11120,7 +11132,7 @@ namespace ts {
|
||||||
if (isAsync) {
|
if (isAsync) {
|
||||||
promisedType = checkAsyncFunctionReturnType(node);
|
promisedType = checkAsyncFunctionReturnType(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
checkIfNonVoidFunctionHasReturnExpressionsOrSingleThrowStatment(node, isAsync ? promisedType : returnType);
|
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
|
// Check that a parameter initializer contains no references to parameters declared to the right of itself
|
||||||
function checkParameterInitializer(node: VariableLikeDeclaration): void {
|
function checkParameterInitializer(node: VariableLikeDeclaration): void {
|
||||||
if (getRootDeclaration(node).kind !== SyntaxKind.Parameter) {
|
if (getRootDeclaration(node).kind !== SyntaxKind.Parameter) {
|
||||||
|
@ -11653,7 +11665,7 @@ namespace ts {
|
||||||
|
|
||||||
return elementType || anyType;
|
return elementType || anyType;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* We want to treat type as an iterable, and get the type it is an iterable of. The iterable
|
* 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):
|
* 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,
|
// 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*
|
// 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.
|
// 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
|
// derived class inherits base without override/redeclaration
|
||||||
|
|
||||||
let derivedClassDecl = getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration);
|
let derivedClassDecl = getDeclarationOfKind(type.symbol, SyntaxKind.ClassDeclaration);
|
||||||
|
|
||||||
// It is an error to inherit an abstract member without implementing it or being declared abstract.
|
// 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),
|
// If there is no declaration for the derived class (as in the case of class expressions),
|
||||||
// then the class cannot be declared abstract.
|
// then the class cannot be declared abstract.
|
||||||
if ( baseDeclarationFlags & NodeFlags.Abstract && (!derivedClassDecl || !(derivedClassDecl.flags & NodeFlags.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,
|
error(derivedClassDecl, Diagnostics.Non_abstract_class_0_does_not_implement_inherited_abstract_member_1_from_class_2,
|
||||||
typeToString(type), symbolToString(baseProperty), typeToString(baseType));
|
typeToString(type), symbolToString(baseProperty), typeToString(baseType));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
// derived overrides base.
|
// derived overrides base.
|
||||||
let derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived);
|
let derivedDeclarationFlags = getDeclarationFlagsFromSymbol(derived);
|
||||||
if ((baseDeclarationFlags & NodeFlags.Private) || (derivedDeclarationFlags & NodeFlags.Private)) {
|
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.
|
// we need to track this to ensure the correct emit.
|
||||||
let mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration);
|
let mergedClass = getDeclarationOfKind(symbol, SyntaxKind.ClassDeclaration);
|
||||||
if (mergedClass &&
|
if (mergedClass &&
|
||||||
|
@ -13298,7 +13310,7 @@ namespace ts {
|
||||||
forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
|
forEach(potentialThisCollisions, checkIfThisIsCapturedInEnclosingScope);
|
||||||
potentialThisCollisions.length = 0;
|
potentialThisCollisions.length = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emitExtends) {
|
if (emitExtends) {
|
||||||
links.flags |= NodeCheckFlags.EmitExtends;
|
links.flags |= NodeCheckFlags.EmitExtends;
|
||||||
}
|
}
|
||||||
|
@ -13310,11 +13322,11 @@ namespace ts {
|
||||||
if (emitParam) {
|
if (emitParam) {
|
||||||
links.flags |= NodeCheckFlags.EmitParam;
|
links.flags |= NodeCheckFlags.EmitParam;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emitAwaiter) {
|
if (emitAwaiter) {
|
||||||
links.flags |= NodeCheckFlags.EmitAwaiter;
|
links.flags |= NodeCheckFlags.EmitAwaiter;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (emitGenerator || (emitAwaiter && languageVersion < ScriptTarget.ES6)) {
|
if (emitGenerator || (emitAwaiter && languageVersion < ScriptTarget.ES6)) {
|
||||||
links.flags |= NodeCheckFlags.EmitGenerator;
|
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".
|
* whether the element is declared as "static".
|
||||||
*/
|
*/
|
||||||
function getParentTypeOfClassElement(node: ClassElement) {
|
function getParentTypeOfClassElement(node: ClassElement) {
|
||||||
|
@ -13722,7 +13734,7 @@ namespace ts {
|
||||||
? getTypeOfSymbol(classSymbol)
|
? getTypeOfSymbol(classSymbol)
|
||||||
: getDeclaredTypeOfSymbol(classSymbol);
|
: getDeclaredTypeOfSymbol(classSymbol);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Return the list of properties of the given type, augmented with properties from Function
|
// Return the list of properties of the given type, augmented with properties from Function
|
||||||
// if the type has call or construct signatures
|
// if the type has call or construct signatures
|
||||||
function getAugmentedPropertiesOfType(type: Type): Symbol[] {
|
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 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 FunctionLikeDeclaration is "Function".
|
||||||
// * The serialized type of any other node is "void 0".
|
// * The serialized type of any other node is "void 0".
|
||||||
//
|
//
|
||||||
// For rules on serializing type annotations, see `serializeTypeNode`.
|
// For rules on serializing type annotations, see `serializeTypeNode`.
|
||||||
switch (node.kind) {
|
switch (node.kind) {
|
||||||
case SyntaxKind.ClassDeclaration: return "Function";
|
case SyntaxKind.ClassDeclaration: return "Function";
|
||||||
|
@ -14075,14 +14087,14 @@ namespace ts {
|
||||||
}
|
}
|
||||||
return "void 0";
|
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. */
|
/** 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[])[] {
|
function serializeParameterTypesOfNode(node: Node): (string | string[])[] {
|
||||||
// serialization of parameter types uses the following rules:
|
// 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 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.
|
// * 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`.
|
// For the rules on serializing the type of each parameter declaration, see `serializeTypeOfDeclaration`.
|
||||||
if (node) {
|
if (node) {
|
||||||
var valueDeclaration: FunctionLikeDeclaration;
|
var valueDeclaration: FunctionLikeDeclaration;
|
||||||
|
@ -14299,21 +14311,21 @@ namespace ts {
|
||||||
|
|
||||||
anyArrayType = createArrayType(anyType);
|
anyArrayType = createArrayType(anyType);
|
||||||
}
|
}
|
||||||
|
|
||||||
function createInstantiatedPromiseLikeType(): ObjectType {
|
function createInstantiatedPromiseLikeType(): ObjectType {
|
||||||
let promiseLikeType = getGlobalPromiseLikeType();
|
let promiseLikeType = getGlobalPromiseLikeType();
|
||||||
if (promiseLikeType !== emptyObjectType) {
|
if (promiseLikeType !== emptyObjectType) {
|
||||||
return createTypeReference(<GenericType>promiseLikeType, [anyType]);
|
return createTypeReference(<GenericType>promiseLikeType, [anyType]);
|
||||||
}
|
}
|
||||||
|
|
||||||
return emptyObjectType;
|
return emptyObjectType;
|
||||||
}
|
}
|
||||||
|
|
||||||
function createThenableType() {
|
function createThenableType() {
|
||||||
// build the thenable type that is used to verify against a non-promise "thenable" operand to `await`.
|
// 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");
|
let thenPropertySymbol = createSymbol(SymbolFlags.Transient | SymbolFlags.Property, "then");
|
||||||
getSymbolLinks(thenPropertySymbol).type = globalFunctionType;
|
getSymbolLinks(thenPropertySymbol).type = globalFunctionType;
|
||||||
|
|
||||||
let thenableType = <ResolvedType>createObjectType(TypeFlags.Anonymous);
|
let thenableType = <ResolvedType>createObjectType(TypeFlags.Anonymous);
|
||||||
thenableType.properties = [thenPropertySymbol];
|
thenableType.properties = [thenPropertySymbol];
|
||||||
thenableType.members = createSymbolTable(thenableType.properties);
|
thenableType.members = createSymbolTable(thenableType.properties);
|
||||||
|
|
|
@ -401,7 +401,7 @@ namespace ts {
|
||||||
}
|
}
|
||||||
|
|
||||||
function emitTypePredicate(type: TypePredicateNode) {
|
function emitTypePredicate(type: TypePredicateNode) {
|
||||||
writeEntityName(type.parameterName);
|
writeTextOfNode(currentSourceFile, type.parameterName);
|
||||||
write(" is ");
|
write(" is ");
|
||||||
emitType(type.type);
|
emitType(type.type);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,6 +31,15 @@ export function fooWithSingleOverload(a: any) {
|
||||||
export function fooWithTypePredicate(a: any): a is number {
|
export function fooWithTypePredicate(a: any): a is number {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
export function fooWithTypePredicateAndMulitpleParams(a: any, b: any, c: any): a is number {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
export function fooWithTypeTypePredicateAndGeneric<T>(a: any): a is T {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
export function fooWithTypeTypePredicateAndRestParam(a: any, ...rest): a is number {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/** This comment should appear for nonExportedFoo*/
|
/** This comment should appear for nonExportedFoo*/
|
||||||
function nonExportedFoo() {
|
function nonExportedFoo() {
|
||||||
|
|
20
tests/cases/fourslash/signatureHelpOnTypePredicates.ts
Normal file
20
tests/cases/fourslash/signatureHelpOnTypePredicates.ts
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
/// <reference path="fourslash.ts" />
|
||||||
|
|
||||||
|
//// function f1(a: any): a is number {}
|
||||||
|
//// function f2<T>(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<T>(a: any): a is T");
|
||||||
|
|
||||||
|
goTo.marker("3");
|
||||||
|
verify.signatureHelpCountIs(1);
|
||||||
|
verify.currentSignatureHelpIs("f3(a: any, ...b: any[]): a is number");
|
Loading…
Reference in a new issue