diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 3ac4e8e512d74..84087ac415f21 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -183,8 +183,8 @@ namespace ts { return declaration ? getSignatureFromDeclaration(declaration) : undefined; }, isImplementationOfOverload: node => { - node = getParseTreeNode(node, isFunctionLike); - return node ? isImplementationOfOverload(node) : undefined; + const parsed = getParseTreeNode(node, isFunctionLike); + return parsed ? isImplementationOfOverload(parsed) : undefined; }, getImmediateAliasedSymbol: symbol => { Debug.assert((symbol.flags & SymbolFlags.Alias) !== 0, "Should only get Alias here."); @@ -12575,7 +12575,7 @@ namespace ts { } } - function getContainingObjectLiteral(func: FunctionLikeDeclaration) { + function getContainingObjectLiteral(func: FunctionLike) { return (func.kind === SyntaxKind.MethodDeclaration || func.kind === SyntaxKind.GetAccessor || func.kind === SyntaxKind.SetAccessor) && func.parent.kind === SyntaxKind.ObjectLiteralExpression ? func.parent : @@ -12593,7 +12593,7 @@ namespace ts { }); } - function getContextualThisParameterType(func: FunctionLikeDeclaration): Type { + function getContextualThisParameterType(func: FunctionLike): Type { if (func.kind === SyntaxKind.ArrowFunction) { return undefined; } @@ -12770,7 +12770,7 @@ namespace ts { return false; } - function getContextualReturnType(functionDecl: FunctionLikeDeclaration): Type { + function getContextualReturnType(functionDecl: FunctionLike): Type { // If the containing function has a return type annotation, is a constructor, or is a get accessor whose // corresponding set accessor has a type annotation, return statements in the function are contextually typed if (functionDecl.kind === SyntaxKind.Constructor || @@ -17866,7 +17866,7 @@ namespace ts { error(node, Diagnostics.A_parameter_property_is_only_allowed_in_a_constructor_implementation); } } - if (node.questionToken && isBindingPattern(node.name) && func.body) { + if (node.questionToken && isBindingPattern(node.name) && (func as FunctionLikeDeclaration).body) { error(node, Diagnostics.A_binding_pattern_parameter_cannot_be_optional_in_an_implementation_signature); } if ((node.name).text === "this") { @@ -18624,12 +18624,12 @@ namespace ts { let hasOverloads = false; let bodyDeclaration: FunctionLikeDeclaration; let lastSeenNonAmbientDeclaration: FunctionLikeDeclaration; - let previousDeclaration: FunctionLikeDeclaration; + let previousDeclaration: FunctionLike; const declarations = symbol.declarations; const isConstructor = (symbol.flags & SymbolFlags.Constructor) !== 0; - function reportImplementationExpectedError(node: FunctionLikeDeclaration): void { + function reportImplementationExpectedError(node: FunctionLike): void { if (node.name && nodeIsMissing(node.name)) { return; } @@ -18688,7 +18688,7 @@ namespace ts { let duplicateFunctionDeclaration = false; let multipleConstructorImplementation = false; for (const current of declarations) { - const node = current; + const node = current; const inAmbientContext = isInAmbientContext(node); const inAmbientContextOrInterface = node.parent.kind === SyntaxKind.InterfaceDeclaration || node.parent.kind === SyntaxKind.TypeLiteral || inAmbientContext; if (inAmbientContextOrInterface) { @@ -18709,7 +18709,7 @@ namespace ts { someHaveQuestionToken = someHaveQuestionToken || hasQuestionToken(node); allHaveQuestionToken = allHaveQuestionToken && hasQuestionToken(node); - if (nodeIsPresent(node.body) && bodyDeclaration) { + if (nodeIsPresent((node as FunctionLikeDeclaration).body) && bodyDeclaration) { if (isConstructor) { multipleConstructorImplementation = true; } @@ -18721,9 +18721,9 @@ namespace ts { reportImplementationExpectedError(previousDeclaration); } - if (nodeIsPresent(node.body)) { + if (nodeIsPresent((node as FunctionLikeDeclaration).body)) { if (!bodyDeclaration) { - bodyDeclaration = node; + bodyDeclaration = node as FunctionLikeDeclaration; } } else { @@ -18733,7 +18733,7 @@ namespace ts { previousDeclaration = node; if (!inAmbientContextOrInterface) { - lastSeenNonAmbientDeclaration = node; + lastSeenNonAmbientDeclaration = node as FunctionLikeDeclaration; } } } @@ -19930,7 +19930,7 @@ namespace ts { forEach((node.name).elements, checkSourceElement); } // For a parameter declaration with an initializer, error and exit if the containing function doesn't have a body - if (node.initializer && getRootDeclaration(node).kind === SyntaxKind.Parameter && nodeIsMissing(getContainingFunction(node).body)) { + if (node.initializer && getRootDeclaration(node).kind === SyntaxKind.Parameter && nodeIsMissing((getContainingFunction(node) as FunctionLikeDeclaration).body)) { error(node, Diagnostics.A_parameter_initializer_is_only_allowed_in_a_function_or_constructor_implementation); return; } @@ -20529,12 +20529,12 @@ namespace ts { // TODO: Check that target label is valid } - function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLikeDeclaration) { + function isGetAccessorWithAnnotatedSetAccessor(node: FunctionLike) { return node.kind === SyntaxKind.GetAccessor && getEffectiveSetAccessorTypeAnnotationNode(getDeclarationOfKind(node.symbol, SyntaxKind.SetAccessor)) !== undefined; } - function isUnwrappedReturnTypeVoidOrAny(func: FunctionLikeDeclaration, returnType: Type): boolean { + function isUnwrappedReturnTypeVoidOrAny(func: FunctionLike, returnType: Type): boolean { const unwrappedReturnType = (getFunctionFlags(func) & FunctionFlags.AsyncGenerator) === FunctionFlags.Async ? getPromisedTypeOfPromise(returnType) // Async function : returnType; // AsyncGenerator function, Generator function, or normal function @@ -23054,8 +23054,8 @@ namespace ts { return false; } - function isImplementationOfOverload(node: FunctionLikeDeclaration) { - if (nodeIsPresent(node.body)) { + function isImplementationOfOverload(node: FunctionLike) { + if (nodeIsPresent((node as FunctionLikeDeclaration).body)) { const symbol = getSymbolOfNode(node); const signaturesOfSymbol = getSignaturesOfSymbol(symbol); // If this function body corresponds to function with multiple signature, it is implementation of overload diff --git a/src/compiler/transformers/ts.ts b/src/compiler/transformers/ts.ts index acfd465ff998f..845b240d7b3e9 100644 --- a/src/compiler/transformers/ts.ts +++ b/src/compiler/transformers/ts.ts @@ -1682,7 +1682,7 @@ namespace ts { const valueDeclaration = isClassLike(node) ? getFirstConstructorWithBody(node) - : isFunctionLike(node) && nodeIsPresent(node.body) + : isFunctionLike(node) && nodeIsPresent((node as FunctionLikeDeclaration).body) ? node : undefined; @@ -1707,7 +1707,7 @@ namespace ts { return createArrayLiteral(expressions); } - function getParametersOfDecoratedDeclaration(node: FunctionLikeDeclaration, container: ClassLikeDeclaration) { + function getParametersOfDecoratedDeclaration(node: FunctionLike, container: ClassLikeDeclaration) { if (container && node.kind === SyntaxKind.GetAccessor) { const { setAccessor } = getAllAccessorDeclarations(container.members, node); if (setAccessor) { diff --git a/src/compiler/types.ts b/src/compiler/types.ts index e2e14c9fd6b3b..750186e3fb928 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -705,14 +705,24 @@ namespace ts { initializer?: Expression; // Optional initializer } - export interface PropertySignature extends TypeElement { - kind: SyntaxKind.PropertySignature | SyntaxKind.JSDocRecordMember; + export interface TSPropertySignature extends TypeElement { + kind: SyntaxKind.PropertySignature; name: PropertyName; // Declared property name questionToken?: QuestionToken; // Present on optional property type?: TypeNode; // Optional type annotation initializer?: Expression; // Optional initializer } + export interface JSDocPropertySignature extends TypeElement { + kind: SyntaxKind.JSDocRecordMember; + name: PropertyName; // Declared property name + questionToken?: QuestionToken; // Present on optional property + type?: TypeNode; // Optional type annotation + initializer?: Expression; // Optional initializer + } + + export type PropertySignature = TSPropertySignature | JSDocPropertySignature; + export interface PropertyDeclaration extends ClassElement { kind: SyntaxKind.PropertyDeclaration; questionToken?: QuestionToken; // Present for use with reporting a grammar error @@ -796,13 +806,13 @@ namespace ts { /** * Several node kinds share function-like features such as a signature, - * a name, and a body. These nodes should extend FunctionLikeDeclaration. + * a name, and a body. These nodes should extend FunctionLikeDeclarationBase. * Examples: * - FunctionDeclaration * - MethodDeclaration * - AccessorDeclaration */ - export interface FunctionLikeDeclaration extends SignatureDeclaration { + export interface FunctionLikeDeclarationBase extends SignatureDeclaration { _functionLikeDeclarationBrand: any; asteriskToken?: AsteriskToken; @@ -810,7 +820,24 @@ namespace ts { body?: Block | Expression; } - export interface FunctionDeclaration extends FunctionLikeDeclaration, DeclarationStatement { + export type FunctionLikeDeclaration = + | FunctionDeclaration + | MethodDeclaration + | ConstructorDeclaration + | GetAccessorDeclaration + | SetAccessorDeclaration + | FunctionExpression + | ArrowFunction; + export type FunctionLike = + | FunctionLikeDeclaration + | FunctionTypeNode + | ConstructorTypeNode + | IndexSignatureDeclaration + | MethodSignature + | ConstructSignatureDeclaration + | CallSignatureDeclaration; + + export interface FunctionDeclaration extends FunctionLikeDeclarationBase, DeclarationStatement { kind: SyntaxKind.FunctionDeclaration; name?: Identifier; body?: FunctionBody; @@ -830,13 +857,13 @@ namespace ts { // Because of this, it may be necessary to determine what sort of MethodDeclaration you have // at later stages of the compiler pipeline. In that case, you can either check the parent kind // of the method, or use helpers like isObjectLiteralMethodDeclaration - export interface MethodDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { + export interface MethodDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement { kind: SyntaxKind.MethodDeclaration; name: PropertyName; body?: FunctionBody; } - export interface ConstructorDeclaration extends FunctionLikeDeclaration, ClassElement { + export interface ConstructorDeclaration extends FunctionLikeDeclarationBase, ClassElement { kind: SyntaxKind.Constructor; parent?: ClassDeclaration | ClassExpression; body?: FunctionBody; @@ -850,7 +877,7 @@ namespace ts { // See the comment on MethodDeclaration for the intuition behind GetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. - export interface GetAccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { + export interface GetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement { kind: SyntaxKind.GetAccessor; parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression; name: PropertyName; @@ -859,7 +886,7 @@ namespace ts { // See the comment on MethodDeclaration for the intuition behind SetAccessorDeclaration being a // ClassElement and an ObjectLiteralElement. - export interface SetAccessorDeclaration extends FunctionLikeDeclaration, ClassElement, ObjectLiteralElement { + export interface SetAccessorDeclaration extends FunctionLikeDeclarationBase, ClassElement, ObjectLiteralElement { kind: SyntaxKind.SetAccessor; parent?: ClassDeclaration | ClassExpression | ObjectLiteralExpression; name: PropertyName; @@ -1323,13 +1350,13 @@ namespace ts { export type FunctionBody = Block; export type ConciseBody = FunctionBody | Expression; - export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclaration { + export interface FunctionExpression extends PrimaryExpression, FunctionLikeDeclarationBase { kind: SyntaxKind.FunctionExpression; name?: Identifier; body: FunctionBody; // Required, whereas the member inherited from FunctionDeclaration is optional } - export interface ArrowFunction extends Expression, FunctionLikeDeclaration { + export interface ArrowFunction extends Expression, FunctionLikeDeclarationBase { kind: SyntaxKind.ArrowFunction; equalsGreaterThanToken: EqualsGreaterThanToken; body: ConciseBody; @@ -2110,7 +2137,7 @@ namespace ts { export type JSDocTypeReferencingNode = JSDocThisType | JSDocConstructorType | JSDocVariadicType | JSDocOptionalType | JSDocNullableType | JSDocNonNullableType; - export interface JSDocRecordMember extends PropertySignature { + export interface JSDocRecordMember extends JSDocPropertySignature { kind: SyntaxKind.JSDocRecordMember; name: Identifier | StringLiteral | NumericLiteral; type?: JSDocType; @@ -2600,7 +2627,7 @@ namespace ts { */ getResolvedSignature(node: CallLikeExpression, candidatesOutArray?: Signature[], argumentCount?: number): Signature | undefined; getSignatureFromDeclaration(declaration: SignatureDeclaration): Signature | undefined; - isImplementationOfOverload(node: FunctionLikeDeclaration): boolean | undefined; + isImplementationOfOverload(node: FunctionLike): boolean | undefined; isUndefinedSymbol(symbol: Symbol): boolean; isArgumentsSymbol(symbol: Symbol): boolean; isUnknownSymbol(symbol: Symbol): boolean; diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 3d7e8c529b894..0f0af2de105c5 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -899,11 +899,11 @@ namespace ts { }); } - export function getContainingFunction(node: Node): FunctionLikeDeclaration { + export function getContainingFunction(node: Node): FunctionLike { while (true) { node = node.parent; if (!node || isFunctionLike(node)) { - return node; + return node; } } } @@ -1885,7 +1885,7 @@ namespace ts { AsyncGenerator = Async | Generator, // Function is an async generator function } - export function getFunctionFlags(node: FunctionLikeDeclaration | undefined) { + export function getFunctionFlags(node: FunctionLike | undefined) { if (!node) { return FunctionFlags.Invalid; } @@ -1906,7 +1906,7 @@ namespace ts { break; } - if (!node.body) { + if (!(node as FunctionLikeDeclaration).body) { flags |= FunctionFlags.Invalid; } @@ -4810,7 +4810,7 @@ namespace ts { // Functions - export function isFunctionLike(node: Node): node is FunctionLikeDeclaration { + export function isFunctionLike(node: Node): node is FunctionLike { return node && isFunctionLikeKind(node.kind); } diff --git a/src/services/findAllReferences.ts b/src/services/findAllReferences.ts index 192895cde591c..1bb746b5c0f5f 100644 --- a/src/services/findAllReferences.ts +++ b/src/services/findAllReferences.ts @@ -1049,16 +1049,17 @@ namespace ts.FindAllReferences.Core { if (isVariableLike(parent) && parent.type === containingTypeReference && parent.initializer && isImplementationExpression(parent.initializer)) { addReference(parent.initializer); } - else if (isFunctionLike(parent) && parent.type === containingTypeReference && parent.body) { - if (parent.body.kind === SyntaxKind.Block) { - forEachReturnStatement(parent.body, returnStatement => { + else if (isFunctionLike(parent) && parent.type === containingTypeReference && (parent as FunctionLikeDeclaration).body) { + const body = (parent as FunctionLikeDeclaration).body; + if (body.kind === SyntaxKind.Block) { + forEachReturnStatement(body, returnStatement => { if (returnStatement.expression && isImplementationExpression(returnStatement.expression)) { addReference(returnStatement.expression); } }); } - else if (isImplementationExpression(parent.body)) { - addReference(parent.body); + else if (isImplementationExpression(body)) { + addReference(body); } } else if (isAssertionExpression(parent) && isImplementationExpression(parent.expression)) { @@ -1643,7 +1644,7 @@ namespace ts.FindAllReferences.Core { } } else if (isFunctionLike(node)) { - return !!node.body || hasModifier(node, ModifierFlags.Ambient); + return !!(node as FunctionLikeDeclaration).body || hasModifier(node, ModifierFlags.Ambient); } else { switch (node.kind) { diff --git a/src/services/symbolDisplay.ts b/src/services/symbolDisplay.ts index 345f0718fe315..b599839cfd302 100644 --- a/src/services/symbolDisplay.ts +++ b/src/services/symbolDisplay.ts @@ -201,7 +201,7 @@ namespace ts.SymbolDisplay { else if ((isNameOfFunctionDeclaration(location) && !(symbol.flags & SymbolFlags.Accessor)) || // name of function declaration (location.kind === SyntaxKind.ConstructorKeyword && location.parent.kind === SyntaxKind.Constructor)) { // At constructor keyword of constructor declaration // get the signature from the declaration and write it - const functionDeclaration = location.parent; + const functionDeclaration = location.parent; // Use function declaration to write the signatures only if the symbol corresponding to this declaration const locationIsSymbolDeclaration = findDeclaration(symbol, declaration => declaration === (location.kind === SyntaxKind.ConstructorKeyword ? functionDeclaration.parent : functionDeclaration));