diff --git a/package.json b/package.json index bf07aadce..fd4d70853 100644 --- a/package.json +++ b/package.json @@ -127,7 +127,6 @@ "@eslint-react/eslint-plugin": "2.3.9", "@eslint/js": "9.39.1", "@stylistic/eslint-plugin": "5.6.1", - "@types/estree": "1.0.8", "@types/jsesc": "3.0.3", "@typescript-eslint/eslint-plugin": "8.48.1", "@typescript-eslint/parser": "8.48.1", diff --git a/scripts/generate-flow-estree-type-definition.js b/scripts/generate-flow-estree-type-definition.js new file mode 100644 index 000000000..e80ba4a26 --- /dev/null +++ b/scripts/generate-flow-estree-type-definition.js @@ -0,0 +1,38 @@ +import fs from "node:fs/promises"; +import * as prettier from "../index.js"; + +const PROJECT_ROOT = new URL("../", import.meta.url); +const FLOW_TYPES = new URL( + "./node_modules/hermes-estree/dist/types.js.flow", + PROJECT_ROOT, +); +const FLOW_TYPES_DTS = new URL( + "./src/language-js/types/flow-estree.d.ts", + PROJECT_ROOT, +); + +let text = await fs.readFile(FLOW_TYPES, "utf8"); + +text = text.replaceAll("'use strict';", " "); +text = text.replaceAll(/(?<=\n) {2,}\+/gu, " "); +text = text.replaceAll("interface {", "{"); +text = text.replaceAll(/: interface extends (\w+)/gu, ": $1 & "); + +const getRelativePath = (url) => + new URL(url).href.slice(PROJECT_ROOT.href.length); +text = ` +// ! Do NOT edit ! +// Generated from '${getRelativePath(FLOW_TYPES)}' +// Run \`node ${getRelativePath(import.meta.url)}\` to update +// spell-checker: disable + +${text} +`; + +text = await prettier.format(text, { + // Bug? should accept URL + filepath: "flow-estree.d.ts", + parser: "typescript", +}); + +await fs.writeFile(FLOW_TYPES_DTS, text); diff --git a/src/language-js/comments/can-attach-comment.js b/src/language-js/comments/can-attach-comment.js index ef7bfe821..93e142670 100644 --- a/src/language-js/comments/can-attach-comment.js +++ b/src/language-js/comments/can-attach-comment.js @@ -8,9 +8,9 @@ import { } from "../utilities/index.js"; /** - * @import {Node} from "../types/estree.js" - * @import AstPath from "../../common/ast-path.js" - */ +@import {Node} from "../types/estree.js"; +@import AstPath from "../../common/ast-path.js"; +*/ const isNodeCantAttachComment = createTypeCheckFunction([ // Babel only @@ -30,7 +30,7 @@ const isNodeCantAttachComment = createTypeCheckFunction([ /** @param {Node} node -@param {any[]} param1 +@param {Node[]} param1 @returns {boolean} */ const isChildWontPrint = (node, [parent]) => @@ -40,8 +40,7 @@ const isChildWontPrint = (node, [parent]) => parent.local !== parent.name) || (parent?.type === "MatchObjectPatternProperty" && parent.shorthand && - parent.key === node && - parent.value !== parent.key) || + parent.key === node) || (parent?.type === "ObjectProperty" && parent.shorthand && parent.key === node && @@ -52,7 +51,7 @@ const isChildWontPrint = (node, [parent]) => !isMethod(parent) && parent.value !== parent.key); -/* +/** Prevent attaching comments to FunctionExpression in this case: ``` class Foo { @@ -64,7 +63,7 @@ class Foo { ``` @param {Node} node -@param {any[]} param1 +@param {Node[]} param1 @returns {boolean} */ const isClassMethodCantAttachComment = (node, [parent]) => @@ -109,7 +108,6 @@ function canAttachComment(node, ancestors) { if ( isNodeCantAttachComment(node) || isChildWontPrint(node, ancestors) || - // @ts-expect-error -- safe isClassMethodCantAttachComment(node, ancestors) ) { return false; diff --git a/src/language-js/comments/handle-comments.js b/src/language-js/comments/handle-comments.js index ee62a416f..79fd4d761 100644 --- a/src/language-js/comments/handle-comments.js +++ b/src/language-js/comments/handle-comments.js @@ -27,20 +27,28 @@ import isBlockComment from "../utilities/is-block-comment.js"; import isLineComment from "../utilities/is-line-comment.js"; import isTypeCastComment from "../utilities/is-type-cast-comment.js"; -/** @import * as Estree from "../types/estree.js" */ +/** +@import {Node, Comment, Nodes} from "../types/estree.js"; +*/ /** - * @typedef {Object} CommentContext - * @property {Estree.Comment} comment - * @property {Estree.Node} precedingNode - * @property {Estree.Node} enclosingNode - * @property {Estree.Node} followingNode - * @property {string} text - * @property {any} options - * @property {Estree.Node} ast - * @property {boolean} isLastComment - */ +@typedef {{ + comment: Comment, + precedingNode: Node, + enclosingNode: Node, + followingNode: Node, + text: string, + options: any, + ast: Nodes["File"] | Nodes["Program"], + isLastComment: boolean, +}} CommentContext +*/ +/** +@param {Comment} comment +@param {string} text +@returns {boolean} +*/ const isSingleLineComment = (comment, text) => isLineComment(comment) || !hasNewlineInRange(text, locStart(comment), locEnd(comment)); @@ -127,7 +135,7 @@ function handleRemainingComment(context) { } /** - * @param {Estree.Node} node + * @param {Node} node * @returns {void} */ function addBlockStatementFirstComment(node, comment) { @@ -143,7 +151,7 @@ function addBlockStatementFirstComment(node, comment) { } /** - * @param {Estree.Node} node + * @param {Node} node * @returns {void} */ function addBlockOrNotComment(node, comment) { @@ -466,11 +474,10 @@ function handleClassComments({ followingNode, }) { if (isClassLikeNode(enclosingNode)) { - if ( - isNonEmptyArray(enclosingNode.decorators) && - !(followingNode?.type === "Decorator") - ) { - addTrailingComment(enclosingNode.decorators.at(-1), comment); + // @ts-expect-error -- Safe + const { decorators } = enclosingNode; + if (isNonEmptyArray(decorators) && !(followingNode?.type === "Decorator")) { + addTrailingComment(decorators.at(-1), comment); return true; } @@ -482,9 +489,11 @@ function handleClassComments({ // Don't add leading comments to `implements`, `extends`, `mixins` to // avoid printing the comment after the keyword. if (followingNode) { + // @ts-expect-error -- Safe + const { superClass } = enclosingNode; if ( - enclosingNode.superClass && - followingNode === enclosingNode.superClass && + superClass && + followingNode === superClass && precedingNode && (precedingNode === enclosingNode.id || precedingNode === enclosingNode.typeParameters) @@ -499,7 +508,7 @@ function handleClassComments({ precedingNode && (precedingNode === enclosingNode.id || precedingNode === enclosingNode.typeParameters || - precedingNode === enclosingNode.superClass) + precedingNode === superClass) ) { addTrailingComment(precedingNode, comment); } else { @@ -1025,7 +1034,6 @@ function handleLastUnionElementInExpression({ !followingNode) || isIntersectionType(enclosingNode)) ) { - // @ts-expect-error -- types exits in TSUnionType and UnionTypeAnnotation addTrailingComment(precedingNode.types.at(-1), comment); return true; } @@ -1174,7 +1182,6 @@ function handleCommentAfterArrowExpression({ if ( enclosingNode.type === "ArrowFunctionExpression" && - // @ts-expect-error -- Safe enclosingNode.returnType === precedingNode && (precedingNode.type === "TSTypeAnnotation" || precedingNode.type === "TypeAnnotation") diff --git a/src/language-js/comments/will-print-own-comments.js b/src/language-js/comments/will-print-own-comments.js index 962694f1e..8fbca67e7 100644 --- a/src/language-js/comments/will-print-own-comments.js +++ b/src/language-js/comments/will-print-own-comments.js @@ -7,9 +7,9 @@ import { } from "../utilities/index.js"; /** - * @import {Node} from "../types/estree.js" - * @import AstPath from "../../common/ast-path.js" - */ +@import {Node} from "../types/estree.js"; +@import AstPath from "../../common/ast-path.js"; +*/ const isClassOrInterface = createTypeCheckFunction([ "ClassDeclaration", diff --git a/src/language-js/loc.js b/src/language-js/loc.js index 22321563d..fe55ddec0 100644 --- a/src/language-js/loc.js +++ b/src/language-js/loc.js @@ -1,6 +1,6 @@ /** - * @import {Node} from "./types/estree.js" - */ +@import {Node} from "./types/estree.js"; +*/ const isIndex = (value) => Number.isInteger(value) && value >= 0; diff --git a/src/language-js/print/binaryish.js b/src/language-js/print/binaryish.js index e1673f630..99b756ac7 100644 --- a/src/language-js/print/binaryish.js +++ b/src/language-js/print/binaryish.js @@ -224,6 +224,7 @@ function printBinaryishExpressions( // precedence level and should be treated as a separate group, so // print them normally. (This doesn't hold for the `**` operator, // which is unique in that it is right-associative.) + // @ts-expect-error -- FIXME if (shouldFlatten(node.operator, node.left.operator)) { // Flatten them out by recursively calling this function. parts = path.call( @@ -245,8 +246,8 @@ function printBinaryishExpressions( const rightNodeToCheckComments = node.right.type === "ChainExpression" ? node.right.expression : node.right; const lineBeforeOperator = - (node.operator === "|>" || - node.type === "NGPipeExpression" || + (node.type === "NGPipeExpression" || + node.operator === "|>" || isVueFilterSequenceExpression(path, options)) && !hasLeadingOwnLineComment(options.originalText, rightNodeToCheckComments); const hasTypeCastComment = hasComment( diff --git a/src/language-js/print/class-body.js b/src/language-js/print/class-body.js index 3c292110d..a063a1f5e 100644 --- a/src/language-js/print/class-body.js +++ b/src/language-js/print/class-body.js @@ -297,8 +297,10 @@ function shouldPrintSemicolonAfterClassProperty( // "declare" or "static" keyword before it. if ( isClassProperty(nextNode) && - nextNode.variance && !nextNode.static && + // @ts-expect-error -- Safe + nextNode.variance && + // @ts-expect-error -- Safe !nextNode.declare ) { return true; diff --git a/src/language-js/print/jsx.js b/src/language-js/print/jsx.js index b60e84ff8..42dfc0ac1 100644 --- a/src/language-js/print/jsx.js +++ b/src/language-js/print/jsx.js @@ -36,6 +36,12 @@ import { isStringLiteral, } from "../utilities/index.js"; +/** +@import AstPath from "../../common/ast-path.js"; +@import {Node, Nodes} from "../types/estree.js"; +@import {Doc} from "../../document/index.js"; +*/ + /* Only the following are treated as whitespace inside JSX. @@ -49,12 +55,6 @@ const jsxWhitespace = new WhitespaceUtilities(" \n\r\t"); const isEmptyStringOrAnyLine = (doc) => doc === "" || doc === line || doc === hardline || doc === softline; -/** - * @import AstPath from "../../common/ast-path.js" - * @import {Node, JSXElement} from "../types/estree.js" - * @import {Doc} from "../../document/index.js" - */ - // JSX expands children from the inside-out, instead of the outside-in. // This is both to break children before attributes, // and to ensure that when children break, their parents do as well. @@ -837,7 +837,7 @@ function printJsx(path, options, print) { } /** - * @param {JSXElement} node + * @param {Nodes["JSXElement"]} node * @returns {boolean} */ function isEmptyJsxElement(node) { diff --git a/src/language-js/print/literal.js b/src/language-js/print/literal.js index bd10f9a97..1c6dae145 100644 --- a/src/language-js/print/literal.js +++ b/src/language-js/print/literal.js @@ -3,8 +3,8 @@ import printNumber from "../../utilities/print-number.js"; import printString from "../../utilities/print-string.js"; /** - * @import {Node} from "../types/estree.js" - */ +@import {Node} from "../types/estree.js"; +*/ function printLiteral(path, options /* , print*/) { const { node } = path; diff --git a/src/language-js/types/estree.d.ts b/src/language-js/types/estree.d.ts index 1945e04b6..a7acb7bed 100644 --- a/src/language-js/types/estree.d.ts +++ b/src/language-js/types/estree.d.ts @@ -1,99 +1,53 @@ -import * as ESTree from "estree"; -import * as Babel from "@babel/types"; -import { TSESTree } from "@typescript-eslint/typescript-estree"; -import { ESTree as Meriyah } from "meriyah"; -import { NGTree } from "angular-estree-parser"; +import { Identifier } from "./flow-estree.d"; +import type * as Babel from "@babel/types"; +import type * as TSESTree from "./typescript-estree.ts"; +import type { ESTree as MeriyahESTree } from "meriyah"; +import type { NGTree } from "angular-estree-parser"; +import type * as FlowESTree from "./flow-estree.js"; -type AdditionalFields = { +type FlowAdditionalNode = + | { + type: "SatisfiesExpression"; + expression: FlowESTree.Expression; + typeAnnotation: FlowESTree.TypeAnnotationType; + } + | { type: "NeverTypeAnnotation" } + | { type: "UndefinedTypeAnnotation" } + | { type: "UnknownTypeAnnotation" }; + +type PrettierNode = { type: "JsExpressionRoot"; node: Babel.Expression }; + +type Node = ( + | PrettierNode + | Babel.Node + | TSESTree.Node + | NGTree.NGNode + | FlowESTree.ESNode + | FlowAdditionalNode +) & { extra?: { parenthesized?: boolean; raw?: string; }; comments?: Comment[]; - trailingComments?: ReadonlyArray | Comment[]; - leadingComments?: ReadonlyArray | Comment[]; +}; + +export type Nodes = { + [NodeType in Node["type"]]: { type: NodeType } & Node; }; export type Comment = ( - | ESTree.Comment | Babel.Comment | TSESTree.Comment - | Meriyah.Comment + | MeriyahESTree.Comment + | { type: "Hashbang"; value: string } + | Babel.InterpreterDirective ) & { printed?: boolean; trailing?: boolean; leading?: boolean; }; -type FlowAdditionalNode = - | { type: "AsExpression"; expression: Node; typeAnnotation: Node } - | { type: "AsConstExpression"; expression: Node } - | { type: "SatisfiesExpression"; expression: Node; typeAnnotation: Node }; - -export type Node = ( - | ESTree.Node - | Babel.Node - | TSESTree.Node - | NGTree.NGNode - | FlowAdditionalNode -) & - AdditionalFields; - -export type TemplateLiteral = ( - | ESTree.TemplateLiteral - | Babel.TemplateLiteral - | TSESTree.TemplateLiteral -) & - AdditionalFields; - -export type CallExpression = ( - | ESTree.CallExpression - | Babel.CallExpression - | TSESTree.CallExpression -) & - AdditionalFields; - -export type OptionalCallExpression = Babel.OptionalCallExpression & - AdditionalFields; - -export type MemberExpression = ( - | ESTree.MemberExpression - | Babel.MemberExpression - | TSESTree.MemberExpression -) & - AdditionalFields; - -export type OptionalMemberExpression = Babel.OptionalMemberExpression & - AdditionalFields; - -export type Expression = ( - | ESTree.Expression - | Babel.Expression - | TSESTree.Expression -) & - AdditionalFields; - -export type BindExpression = Babel.BindExpression & AdditionalFields; - -export type Property = (ESTree.Property | Babel.Property | TSESTree.Property) & - AdditionalFields; - -export type ClassPrivateProperty = Babel.ClassPrivateProperty & - AdditionalFields; - -export type ObjectTypeProperty = Babel.ObjectTypeProperty & AdditionalFields; - -export type JSXElement = (Babel.JSXElement | TSESTree.JSXElement) & - AdditionalFields; - -export type TaggedTemplateExpression = ( - | ESTree.TaggedTemplateExpression - | Babel.TaggedTemplateExpression - | TSESTree.TaggedTemplateExpression -) & - AdditionalFields; - -export type Literal = (ESTree.Literal | Babel.Literal | TSESTree.Literal) & - AdditionalFields; - -export { ESTree, Babel, TSESTree, NGTree }; +export type Comments = { + [CommentType in Comment["type"]]: { type: CommentType } & Comment; +}; diff --git a/src/language-js/types/flow-estree.d.ts b/src/language-js/types/flow-estree.d.ts new file mode 100644 index 000000000..1d629811f --- /dev/null +++ b/src/language-js/types/flow-estree.d.ts @@ -0,0 +1,2107 @@ +// ! Do NOT edit ! +// Generated from 'node_modules/hermes-estree/dist/types.js.flow' +// Run `node scripts/generate-flow-estree-type-definition.js` to update +// spell-checker: disable + +/** + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + * + * @flow strict + * @format + */ + +/** + * + * IMPORTANT NOTE + * + * This file intentionally uses interfaces and `+` for readonly. + * + * - `$ReadOnly` is an "evaluated" utility type in flow; meaning that flow does + * not actually calculate the resulting type until it is used. This creates + * a copy of the type at each usage site - ballooning memory and processing + * times. + * Usually this isn't a problem as a type might only be used one or two times + * - but in this giant circular-referencing graph that is the AST types, this + * causes check times for consumers to be awful. + * + * Thus instead we manually annotate properties with `+` to avoid the `$ReadOnly` type. + * + * - `...Type` spreads do not preserve the readonly-ness of the properties. If + * we used object literal types then we would have to `$ReadOnly` all spreads + * (see point 1). On the other hand extending an interface does preserve + * readonlyness of properties. + * + * Thus instead of object literals, we use interfaces. + * + *** Please ensure all properties are marked as readonly! *** + */ + +export type Range = [number, number]; + +export interface ObjectWithLoc { + loc: SourceLocation; +} +export interface BaseToken extends ObjectWithLoc { + loc: SourceLocation; + range: Range; +} +export interface BaseNode extends BaseToken { + // this is added by ESLint and is not part of the ESTree spec + parent: ESNode; +} + +/* + * Token and Comment are pseudo-nodes to represent pieces of source code + * + * NOTE: + * They are not included in the `ESNode` union below on purpose because they + * are not ever included as part of the standard AST tree. + */ + +export interface MostTokens extends BaseToken { + type: + | "Boolean" + | "Identifier" + | "JSXIdentifier" + | "JSXText" + | "Keyword" + | "Null" + | "Numeric" + | "BigInt" + | "Punctuator" + | "RegularExpression" + | "String" + | "Template" + // comment types + | "Block" + | "Line"; + value: string; +} +export interface RegexToken extends BaseToken { + type: "RegularExpression"; + value: string; + regex: { + pattern: string; + flags: string; + }; +} +export interface LineComment extends BaseToken { + type: "Line"; + value: string; +} +export interface BlockComment extends BaseToken { + type: "Block"; + value: string; +} +export type Comment = LineComment | BlockComment; +export type Token = MostTokens | RegexToken | Comment; + +export interface SourceLocation { + start: Position; + end: Position; +} + +export interface Position { + /** >= 1 */ + line: number; + /** >= 0 */ + column: number; +} + +// note: this is only ever present on Program.interpreter, never in the body +export interface InterpreterDirective extends BaseNode { + type: "InterpreterDirective"; + value: string; +} + +export type DocblockDirectives = $ReadOnly<{ + // some well-known tags + flow?: $ReadOnlyArray | void; + format?: $ReadOnlyArray | void; + noflow?: $ReadOnlyArray | void; + noformat?: $ReadOnlyArray | void; + [string]: $ReadOnlyArray | void; +}>; + +export type DocblockMetadata = $ReadOnly<{ + directives: DocblockDirectives; + comment: BlockComment; +}>; + +export interface Program extends BaseNode { + type: "Program"; + sourceType: "script" | "module"; + body: $ReadOnlyArray; + tokens: $ReadOnlyArray; + comments: $ReadOnlyArray; + loc: SourceLocation; + interpreter: null | InterpreterDirective; + docblock: null | DocblockMetadata; + // program is the only node without a parent - but typing it as such is _super_ annoying and difficult + parent: ESNode; +} + +// Flow declares a "Node" type as part of its HTML typedefs. +// Because this file declares global types - we can't clash with it +export type ESNode = + | Identifier + | PrivateIdentifier + | Literal + | Program + | AFunction + | SwitchCase + | CatchClause + | VariableDeclarator + | Statement + | Expression + | Property + | Super + | TemplateElement + | SpreadElement + | BindingName + | RestElement + | AssignmentPattern + | MemberExpression + | ClassBody + | AClass + | MethodDefinition + | PropertyDefinition + | ModuleDeclaration + | ModuleSpecifier + | ImportAttribute + // flow nodes + | TypeAnnotation + | TypeAnnotationType + | Variance + | FunctionTypeParam + | ComponentTypeParameter + | InferredPredicate + | ObjectTypeProperty + | ObjectTypeCallProperty + | ObjectTypeIndexer + | ObjectTypeSpreadProperty + | ObjectTypeMappedTypeProperty + | InterfaceExtends + | ClassImplements + | Decorator + | TypeParameterDeclaration + | TypeParameter + | TypeParameterInstantiation + | ComponentDeclaration + | ComponentParameter + | HookDeclaration + | EnumDeclaration + | EnumNumberBody + | EnumBigIntBody + | EnumStringBody + | EnumStringMember + | EnumDefaultedMember + | EnumNumberMember + | EnumBigIntMember + | EnumBooleanBody + | EnumBooleanMember + | EnumSymbolBody + | DeclaredNode + | ObjectTypeInternalSlot + // Match + | MatchPattern + | MatchRestPattern + | MatchObjectPatternProperty + | MatchExpressionCase + | MatchStatementCase + // JSX + | JSXNode; + +export type BindingName = Identifier | BindingPattern; +export type BindingPattern = ArrayPattern | ObjectPattern; +export type RestElementPattern = AssignmentPattern | BindingName | RestElement; +export type FunctionParameter = AssignmentPattern | BindingName | RestElement; +export type DestructuringPattern = + | BindingName + | AssignmentPattern + | MemberExpression + | RestElement; + +interface BaseFunction extends BaseNode { + params: $ReadOnlyArray; + async: boolean; + + predicate: null | InferredPredicate; + returnType: null | TypeAnnotation; + typeParameters: null | TypeParameterDeclaration; +} + +export type AFunction = + | FunctionDeclaration + | FunctionExpression + | ArrowFunctionExpression; + +export type Statement = + | BlockStatement + | BreakStatement + | ClassDeclaration + | ComponentDeclaration + | ContinueStatement + | DebuggerStatement + | DeclareClass + | DeclareComponent + | DeclareHook + | DeclareVariable + | DeclareEnum + | DeclareFunction + | DeclareInterface + | DeclareModule + | DeclareNamespace + | DeclareOpaqueType + | DeclareTypeAlias + | DoWhileStatement + | EmptyStatement + | EnumDeclaration + | ExpressionStatement + | ForInStatement + | ForOfStatement + | ForStatement + | FunctionDeclaration + | HookDeclaration + | IfStatement + | InterfaceDeclaration + | LabeledStatement + | OpaqueType + | ReturnStatement + | StaticBlock + | SwitchStatement + | ThrowStatement + | TryStatement + | TypeAlias + | VariableDeclaration + | WhileStatement + | WithStatement + | MatchStatement; + +// nodes that can be the direct parent of a statement +export type StatementParentSingle = + | IfStatement + | LabeledStatement + | WithStatement + | WhileStatement + | DoWhileStatement + | ForStatement + | ForInStatement + | ForOfStatement; +// nodes that can be the parent of a statement that store the statements in an array +export type StatementParentArray = + | SwitchCase + | Program + | BlockStatement + | StaticBlock; +export type StatementParent = StatementParentSingle | StatementParentArray; + +export interface EmptyStatement extends BaseNode { + type: "EmptyStatement"; +} + +export interface BlockStatement extends BaseNode { + type: "BlockStatement"; + body: $ReadOnlyArray; +} + +export interface StaticBlock extends BaseNode { + type: "StaticBlock"; + body: $ReadOnlyArray; +} + +export interface ExpressionStatement extends BaseNode { + type: "ExpressionStatement"; + expression: Expression; + directive: string | null; +} + +export interface IfStatement extends BaseNode { + type: "IfStatement"; + test: Expression; + consequent: Statement; + alternate?: Statement | null; +} + +export interface LabeledStatement extends BaseNode { + type: "LabeledStatement"; + label: Identifier; + body: Statement; +} + +export interface BreakStatement extends BaseNode { + type: "BreakStatement"; + label?: Identifier | null; +} + +export interface ContinueStatement extends BaseNode { + type: "ContinueStatement"; + label?: Identifier | null; +} + +export interface WithStatement extends BaseNode { + type: "WithStatement"; + object: Expression; + body: Statement; +} + +export interface SwitchStatement extends BaseNode { + type: "SwitchStatement"; + discriminant: Expression; + cases: $ReadOnlyArray; +} + +export interface ReturnStatement extends BaseNode { + type: "ReturnStatement"; + argument?: Expression | null; +} + +export interface ThrowStatement extends BaseNode { + type: "ThrowStatement"; + argument: Expression; +} + +export interface TryStatement extends BaseNode { + type: "TryStatement"; + block: BlockStatement; + handler?: CatchClause | null; + finalizer?: BlockStatement | null; +} + +export interface WhileStatement extends BaseNode { + type: "WhileStatement"; + test: Expression; + body: Statement; +} + +export interface DoWhileStatement extends BaseNode { + type: "DoWhileStatement"; + body: Statement; + test: Expression; +} + +export interface ForStatement extends BaseNode { + type: "ForStatement"; + init?: VariableDeclaration | Expression | null; + test?: Expression | null; + update?: Expression | null; + body: Statement; +} + +interface BaseForXStatement extends BaseNode { + left: VariableDeclaration | BindingName | MemberExpression; + right: Expression; + body: Statement; +} + +export interface ForInStatement extends BaseForXStatement { + type: "ForInStatement"; +} + +export interface ForOfStatement extends BaseForXStatement { + type: "ForOfStatement"; + await: boolean; +} + +export interface DebuggerStatement extends BaseNode { + type: "DebuggerStatement"; +} + +type ComponentParameterAndRestElement = ComponentParameter | RestElement; + +export interface ComponentParameter extends BaseNode { + type: "ComponentParameter"; + name: Identifier | StringLiteral; + local: BindingName | AssignmentPattern; + shorthand: boolean; +} + +export interface ComponentDeclaration extends BaseNode { + type: "ComponentDeclaration"; + body: BlockStatement; + id: Identifier; + params: $ReadOnlyArray; + rendersType: null | RendersType; + typeParameters: null | TypeParameterDeclaration; +} + +export interface HookDeclaration extends BaseNode { + type: "HookDeclaration"; + id: Identifier; + body: BlockStatement; + params: $ReadOnlyArray; + returnType: null | TypeAnnotation; + typeParameters: null | TypeParameterDeclaration; +} + +export interface FunctionDeclaration extends BaseFunction { + type: "FunctionDeclaration"; + /** It is null when a function declaration is a part of the `export default function` statement */ + id: Identifier | null; + body: BlockStatement; + generator: boolean; +} + +export interface VariableDeclaration extends BaseNode { + type: "VariableDeclaration"; + declarations: $ReadOnlyArray; + kind: "var" | "let" | "const"; +} + +export interface VariableDeclarator extends BaseNode { + type: "VariableDeclarator"; + id: BindingName; + init?: Expression | null; + + parent: VariableDeclaration; +} + +export type Expression = + | ThisExpression + | ArrayExpression + | ObjectExpression + | FunctionExpression + | ArrowFunctionExpression + | YieldExpression + | Literal + | UnaryExpression + | UpdateExpression + | BinaryExpression + | AssignmentExpression + | LogicalExpression + | MemberExpression + | ConditionalExpression + | CallExpression + | NewExpression + | SequenceExpression + | TemplateLiteral + | TaggedTemplateExpression + | ClassExpression + | MetaProperty + | Identifier + | AwaitExpression + | ImportExpression + | ChainExpression + | TypeCastExpression + | AsExpression + | AsConstExpression + | MatchExpression + | JSXFragment + | JSXElement; + +export interface ThisExpression extends BaseNode { + type: "ThisExpression"; +} + +export interface ArrayExpression extends BaseNode { + type: "ArrayExpression"; + elements: $ReadOnlyArray; + // this is not part of the ESTree spec, but hermes emits it + trailingComma: boolean; +} + +export interface ObjectExpression extends BaseNode { + type: "ObjectExpression"; + properties: $ReadOnlyArray; +} + +// This is the complete type of a "Property" +// This same node (unfortunately) covers both object literal properties +// and object desturcturing properties. +export type Property = ObjectProperty | DestructuringObjectProperty; + +export type ObjectProperty = + | ObjectPropertyWithNonShorthandStaticName + | ObjectPropertyWithShorthandStaticName + | ObjectPropertyWithComputedName; +interface ObjectPropertyBase extends BaseNode { + parent: ObjectExpression | ObjectPattern; +} +export interface ObjectPropertyWithNonShorthandStaticName extends ObjectPropertyBase { + type: "Property"; + computed: false; + // non-computed, non-shorthand names are constrained significantly + key: Identifier | StringLiteral | NumericLiteral; + value: Expression; + kind: "init" | "get" | "set"; + method: boolean; + shorthand: false; +} +export interface ObjectPropertyWithShorthandStaticName extends ObjectPropertyBase { + type: "Property"; + computed: false; + // shorthand keys *must* be identifiers + key: Identifier; + // shorthand values *must* be identifiers (that look the same as the key) + value: Identifier; + kind: "init"; + method: false; + shorthand: true; +} +export interface ObjectPropertyWithComputedName extends ObjectPropertyBase { + type: "Property"; + computed: true; + // computed names can be any expression + key: Expression; + value: Expression; + kind: "init" | "get" | "set"; + method: boolean; + // cannot have a shorthand computed name + shorthand: false; +} + +export type DestructuringObjectProperty = + | DestructuringObjectPropertyWithNonShorthandStaticName + | DestructuringObjectPropertyWithShorthandStaticName + | DestructuringObjectPropertyWithComputedName; +interface DestructuringObjectPropertyBase extends BaseNode { + // destructuring properties cannot be methods + kind: "init"; + method: false; + + parent: ObjectExpression | ObjectPattern; +} +export interface DestructuringObjectPropertyWithNonShorthandStaticName extends DestructuringObjectPropertyBase { + type: "Property"; + computed: false; + // non-computed, non-shorthand names are constrained significantly + key: Identifier | StringLiteral | NumericLiteral; + // destructuring properties cannot have any value + value: DestructuringPattern; + shorthand: false; +} +export interface DestructuringObjectPropertyWithShorthandStaticName extends DestructuringObjectPropertyBase { + type: "Property"; + computed: false; + // shorthand keys *must* be identifiers + key: Identifier; + // shorthand values *must* be identifiers or assignments (that look the same as the key) + value: Identifier | AssignmentPattern; + shorthand: true; +} +export interface DestructuringObjectPropertyWithComputedName extends DestructuringObjectPropertyBase { + type: "Property"; + computed: true; + // computed names can be any expression + key: Expression; + // destructuring properties cannot have any value + value: DestructuringPattern; + // cannot have a shorthand computed name + shorthand: false; +} + +export interface FunctionExpression extends BaseFunction { + id?: Identifier | null; + type: "FunctionExpression"; + body: BlockStatement; + generator: boolean; +} + +export interface SequenceExpression extends BaseNode { + type: "SequenceExpression"; + expressions: $ReadOnlyArray; +} + +export interface UnaryExpression extends BaseNode { + type: "UnaryExpression"; + operator: UnaryOperator; + prefix: true; + argument: Expression; +} + +export interface BinaryExpressionWithoutIn extends BaseNode { + type: "BinaryExpression"; + operator: BinaryOperatorWithoutIn; + left: Expression; + right: Expression; +} + +// Private brand checks (#foo in bar) are a special case +// other binary expressions do not allow PrivateIdentifier in the left +export interface BinaryExpressionIn extends BaseNode { + type: "BinaryExpression"; + operator: "in"; + left: Expression | PrivateIdentifier; + right: Expression; +} + +export type BinaryExpression = BinaryExpressionWithoutIn | BinaryExpressionIn; + +export interface AssignmentExpression extends BaseNode { + type: "AssignmentExpression"; + operator: AssignmentOperator; + left: BindingName | MemberExpression; + right: Expression; +} + +export interface UpdateExpression extends BaseNode { + type: "UpdateExpression"; + operator: UpdateOperator; + argument: Expression; + prefix: boolean; +} + +export interface LogicalExpression extends BaseNode { + type: "LogicalExpression"; + operator: LogicalOperator; + left: Expression; + right: Expression; +} + +export interface ConditionalExpression extends BaseNode { + type: "ConditionalExpression"; + test: Expression; + alternate: Expression; + consequent: Expression; +} + +interface BaseCallExpression extends BaseNode { + callee: Expression | Super; + arguments: $ReadOnlyArray; + typeArguments: null | TypeParameterInstantiation; +} +export interface CallExpression extends BaseCallExpression { + type: "CallExpression"; + optional: boolean; +} + +export interface NewExpression extends BaseCallExpression { + type: "NewExpression"; +} + +export type MemberExpression = + | MemberExpressionWithComputedName + | MemberExpressionWithNonComputedName; +export interface MemberExpressionWithComputedName extends BaseNode { + type: "MemberExpression"; + object: Expression | Super; + property: Expression; + computed: true; + optional: boolean; +} +export interface MemberExpressionWithNonComputedName extends BaseNode { + type: "MemberExpression"; + object: Expression | Super; + property: Identifier | PrivateIdentifier; + computed: false; + optional: boolean; +} + +export type ChainElement = CallExpression | MemberExpression; + +export interface ChainExpression extends BaseNode { + type: "ChainExpression"; + expression: ChainElement; +} + +export interface SwitchCase extends BaseNode { + type: "SwitchCase"; + test?: Expression | null; + consequent: $ReadOnlyArray; +} + +export interface CatchClause extends BaseNode { + type: "CatchClause"; + param: BindingName | null; + body: BlockStatement; +} + +export interface Identifier extends BaseNode { + type: "Identifier"; + name: string; + + typeAnnotation: TypeAnnotation | null; + // only applies to function arguments + optional: boolean; +} + +export interface PrivateIdentifier extends BaseNode { + type: "PrivateIdentifier"; + name: string; +} + +export type Literal = + | BigIntLiteral + | BooleanLiteral + | NullLiteral + | NumericLiteral + | RegExpLiteral + | StringLiteral; + +export interface BigIntLiteral extends BaseNode { + type: "Literal"; + value: bigint; + bigint: string; + raw: string; + literalType: "bigint"; +} + +export interface BooleanLiteral extends BaseNode { + type: "Literal"; + value: boolean; + raw: "true" | "false"; + literalType: "boolean"; +} + +export interface NullLiteral extends BaseNode { + type: "Literal"; + value: null; + raw: "null"; + literalType: "null"; +} + +export interface NumericLiteral extends BaseNode { + type: "Literal"; + value: number; + raw: string; + literalType: "numeric"; +} + +export interface RegExpLiteral extends BaseNode { + type: "Literal"; + value: RegExp | null; + regex: { + pattern: string; + flags: string; + }; + raw: string; + literalType: "regexp"; +} + +export interface StringLiteral extends BaseNode { + type: "Literal"; + value: string; + raw: string; + literalType: "string"; +} + +export type UnaryOperator = + | "-" + | "+" + | "!" + | "~" + | "typeof" + | "void" + | "delete"; + +export type BinaryOperatorWithoutIn = + | "==" + | "!=" + | "===" + | "!==" + | "<" + | "<=" + | ">" + | ">=" + | "<<" + | ">>" + | ">>>" + | "+" + | "-" + | "*" + | "/" + | "%" + | "**" + | "|" + | "^" + | "&" + | "instanceof"; + +export type BinaryOperator = BinaryOperatorWithoutIn | "in"; + +export type LogicalOperator = "||" | "&&" | "??"; + +export type AssignmentOperator = + | "=" + | "+=" + | "-=" + | "*=" + | "/=" + | "%=" + | "**=" + | "<<=" + | ">>=" + | ">>>=" + | "|=" + | "^=" + | "&=" + // not yet supported, but future proofing + | "||=" + | "&&=" + | "??="; + +export type UpdateOperator = "++" | "--"; + +export interface Super extends BaseNode { + type: "Super"; +} + +export interface SpreadElement extends BaseNode { + type: "SpreadElement"; + argument: Expression; +} + +export interface ArrowFunctionExpression extends BaseFunction { + type: "ArrowFunctionExpression"; + expression: boolean; + body: BlockStatement | Expression; + // hermes emits this - but it's always null + id: null; + // note - arrow functions cannot be generators +} + +export interface YieldExpression extends BaseNode { + type: "YieldExpression"; + argument?: Expression | null; + delegate: boolean; +} + +export interface TemplateLiteral extends BaseNode { + type: "TemplateLiteral"; + quasis: $ReadOnlyArray; + expressions: $ReadOnlyArray; +} + +export interface TaggedTemplateExpression extends BaseNode { + type: "TaggedTemplateExpression"; + tag: Expression; + quasi: TemplateLiteral; +} + +export interface TemplateElement extends BaseNode { + type: "TemplateElement"; + tail: boolean; + value: { + cooked: string; + raw: string; + }; +} + +export interface ObjectPattern extends BaseNode { + type: "ObjectPattern"; + properties: $ReadOnlyArray; + // if used as a VariableDeclarator.id + typeAnnotation: TypeAnnotation | null; +} + +export interface ArrayPattern extends BaseNode { + type: "ArrayPattern"; + // an element will be null if the pattern contains a hole: `[a,,b]` + elements: $ReadOnlyArray; + typeAnnotation: TypeAnnotation | null; +} + +export interface RestElement extends BaseNode { + type: "RestElement"; + argument: RestElementPattern; + // the Pattern owns the typeAnnotation +} + +export interface AssignmentPattern extends BaseNode { + type: "AssignmentPattern"; + left: BindingName; + right: Expression; +} + +export type AClass = ClassDeclaration | ClassExpression; +interface BaseClass extends BaseNode { + superClass?: Expression | null; + body: ClassBody; + + typeParameters: null | TypeParameterDeclaration; + superTypeParameters: null | TypeParameterInstantiation; + implements: $ReadOnlyArray; + decorators: $ReadOnlyArray; +} + +export type PropertyName = + | ClassPropertyNameComputed + | ClassPropertyNameNonComputed; +export type ClassPropertyNameComputed = Expression; +export type ClassPropertyNameNonComputed = + | PrivateIdentifier + | Identifier + | StringLiteral; + +export type ClassMember = PropertyDefinition | MethodDefinition | StaticBlock; +export type ClassMemberWithNonComputedName = + | PropertyDefinitionWithNonComputedName + | MethodDefinitionConstructor + | MethodDefinitionWithNonComputedName; +export interface ClassBody extends BaseNode { + type: "ClassBody"; + body: $ReadOnlyArray; + + parent: AClass; +} + +export type MethodDefinition = + | MethodDefinitionConstructor + | MethodDefinitionWithComputedName + | MethodDefinitionWithNonComputedName; +interface MethodDefinitionBase extends BaseNode { + value: FunctionExpression; + + parent: ClassBody; +} +export interface MethodDefinitionConstructor extends MethodDefinitionBase { + type: "MethodDefinition"; + key: Identifier | StringLiteral; + kind: "constructor"; + computed: false; + static: false; +} +export interface MethodDefinitionWithComputedName extends MethodDefinitionBase { + type: "MethodDefinition"; + key: ClassPropertyNameComputed; + kind: "method" | "get" | "set"; + computed: true; + static: boolean; +} +export interface MethodDefinitionWithNonComputedName extends MethodDefinitionBase { + type: "MethodDefinition"; + key: ClassPropertyNameNonComputed; + kind: "method" | "get" | "set"; + computed: false; + static: boolean; +} + +// `PropertyDefinition` is the new standard for all class properties +export type PropertyDefinition = + | PropertyDefinitionWithComputedName + | PropertyDefinitionWithNonComputedName; +interface PropertyDefinitionBase extends BaseNode { + value: null | Expression; + typeAnnotation: null | TypeAnnotation; + static: boolean; + variance: null | Variance; + declare: boolean; + // hermes always emit this as false + optional: false; + + parent: ClassBody; +} +export interface PropertyDefinitionWithComputedName extends PropertyDefinitionBase { + type: "PropertyDefinition"; + key: ClassPropertyNameComputed; + computed: true; +} +export interface PropertyDefinitionWithNonComputedName extends PropertyDefinitionBase { + type: "PropertyDefinition"; + key: ClassPropertyNameNonComputed; + computed: false; +} + +export interface ClassDeclaration extends BaseClass { + type: "ClassDeclaration"; + /** It is null when a class declaration is a part of the `export default class` statement */ + id: Identifier | null; +} + +export interface ClassExpression extends BaseClass { + type: "ClassExpression"; + id?: Identifier | null; +} + +export interface MetaProperty extends BaseNode { + type: "MetaProperty"; + meta: Identifier; + property: Identifier; +} + +export type ModuleDeclaration = + | ImportDeclaration + | ExportNamedDeclaration + | ExportDefaultDeclaration + | ExportAllDeclaration + | DeclareExportDeclaration + | DeclareExportAllDeclaration + | DeclareModuleExports; + +export type ModuleSpecifier = + | ImportSpecifier + | ImportDefaultSpecifier + | ImportNamespaceSpecifier + | ExportSpecifier; + +export interface ImportDeclaration extends BaseNode { + type: "ImportDeclaration"; + specifiers: $ReadOnlyArray< + ImportSpecifier | ImportDefaultSpecifier | ImportNamespaceSpecifier + >; + source: StringLiteral; + assertions: $ReadOnlyArray; + + importKind: "value" | "type" | "typeof"; +} +export interface ImportAttribute extends BaseNode { + type: "ImportAttribute"; + key: Identifier; + value: StringLiteral; + + parent: ImportDeclaration; +} + +export interface ImportSpecifier extends BaseNode { + type: "ImportSpecifier"; + imported: Identifier; + local: Identifier; + importKind: null | "type" | "typeof"; + + parent: ImportDeclaration; +} + +export interface ImportExpression extends BaseNode { + type: "ImportExpression"; + source: Expression; + options: Expression | null; +} + +export interface ImportDefaultSpecifier extends BaseNode { + type: "ImportDefaultSpecifier"; + local: Identifier; + + parent: ImportDeclaration; +} + +export interface ImportNamespaceSpecifier extends BaseNode { + type: "ImportNamespaceSpecifier"; + local: Identifier; + + parent: ImportDeclaration; +} + +export type DefaultDeclaration = + | FunctionDeclaration + | ClassDeclaration + | ComponentDeclaration + | HookDeclaration; +export type NamedDeclaration = + | DefaultDeclaration + | VariableDeclaration + | TypeAlias + | OpaqueType + | InterfaceDeclaration + | EnumDeclaration; + +interface ExportNamedDeclarationBase extends BaseNode { + type: "ExportNamedDeclaration"; + declaration?: NamedDeclaration | null; + specifiers: $ReadOnlyArray; + source?: StringLiteral | null; + exportKind: "value" | "type"; +} +export interface ExportNamedDeclarationWithSpecifiers extends ExportNamedDeclarationBase { + type: "ExportNamedDeclaration"; + declaration: null; + source?: StringLiteral | null; + specifiers: $ReadOnlyArray; +} +export interface ExportNamedDeclarationWithDeclaration extends ExportNamedDeclarationBase { + type: "ExportNamedDeclaration"; + declaration: NamedDeclaration; + source: null; + specifiers: []; +} +export type ExportNamedDeclaration = + | ExportNamedDeclarationWithSpecifiers + | ExportNamedDeclarationWithDeclaration; + +export interface ExportSpecifier extends BaseNode { + type: "ExportSpecifier"; + exported: Identifier; + local: Identifier; +} + +export interface ExportDefaultDeclaration extends BaseNode { + type: "ExportDefaultDeclaration"; + declaration: DefaultDeclaration | Expression; +} + +export interface ExportAllDeclaration extends BaseNode { + type: "ExportAllDeclaration"; + source: StringLiteral; + exportKind: "value" | "type"; + exported?: Identifier | null; +} + +export interface AwaitExpression extends BaseNode { + type: "AwaitExpression"; + argument: Expression; +} + +/*********************** + * Flow specific nodes * + ***********************/ + +export type TypeAnnotationType = + | NumberTypeAnnotation + | StringTypeAnnotation + | BigIntTypeAnnotation + | BooleanTypeAnnotation + | NullLiteralTypeAnnotation + | AnyTypeAnnotation + | EmptyTypeAnnotation + | SymbolTypeAnnotation + | ThisTypeAnnotation + | MixedTypeAnnotation + | VoidTypeAnnotation + | StringLiteralTypeAnnotation + | NumberLiteralTypeAnnotation + | BigIntLiteralTypeAnnotation + | BooleanLiteralTypeAnnotation + | ArrayTypeAnnotation + | NullableTypeAnnotation + | ExistsTypeAnnotation + | GenericTypeAnnotation + | QualifiedTypeIdentifier + | QualifiedTypeofIdentifier + | TypeofTypeAnnotation + | KeyofTypeAnnotation + | TupleTypeAnnotation + | TupleTypeSpreadElement + | TupleTypeLabeledElement + | InferTypeAnnotation + | InterfaceTypeAnnotation + | UnionTypeAnnotation + | IntersectionTypeAnnotation + | ConditionalTypeAnnotation + | TypeOperator + | TypePredicate + | FunctionTypeAnnotation + | HookTypeAnnotation + | ComponentTypeAnnotation + | ObjectTypeAnnotation + | IndexedAccessType + | OptionalIndexedAccessType; + +export interface Variance extends BaseNode { + type: "Variance"; + kind: "plus" | "minus"; +} + +interface BaseTypeAlias extends BaseNode { + id: Identifier; + typeParameters: null | TypeParameterDeclaration; + right: TypeAnnotationType; +} + +export interface TypeAnnotation extends BaseNode { + type: "TypeAnnotation"; + typeAnnotation: TypeAnnotationType; +} + +export interface TypeAlias extends BaseTypeAlias { + type: "TypeAlias"; +} + +interface BaseOpaqueType extends BaseNode { + id: Identifier; + supertype: TypeAnnotationType | null; + lowerBound: TypeAnnotationType | null; + upperBound: TypeAnnotationType | null; + typeParameters: TypeParameterDeclaration | null; +} +export interface OpaqueType extends BaseOpaqueType { + type: "OpaqueType"; + impltype: TypeAnnotationType; +} + +export interface NumberTypeAnnotation extends BaseNode { + type: "NumberTypeAnnotation"; +} +export interface StringTypeAnnotation extends BaseNode { + type: "StringTypeAnnotation"; +} +export interface BigIntTypeAnnotation extends BaseNode { + type: "BigIntTypeAnnotation"; +} +export interface BooleanTypeAnnotation extends BaseNode { + type: "BooleanTypeAnnotation"; +} +export interface NullLiteralTypeAnnotation extends BaseNode { + type: "NullLiteralTypeAnnotation"; +} +export interface AnyTypeAnnotation extends BaseNode { + type: "AnyTypeAnnotation"; +} +export interface EmptyTypeAnnotation extends BaseNode { + type: "EmptyTypeAnnotation"; +} +export interface SymbolTypeAnnotation extends BaseNode { + type: "SymbolTypeAnnotation"; +} +export interface ThisTypeAnnotation extends BaseNode { + type: "ThisTypeAnnotation"; +} +export interface MixedTypeAnnotation extends BaseNode { + type: "MixedTypeAnnotation"; +} +export interface VoidTypeAnnotation extends BaseNode { + type: "VoidTypeAnnotation"; +} +export interface StringLiteralTypeAnnotation extends BaseNode { + type: "StringLiteralTypeAnnotation"; + value: string; + raw: string; +} +export interface NumberLiteralTypeAnnotation extends BaseNode { + type: "NumberLiteralTypeAnnotation"; + value: number; + raw: string; +} +export interface BigIntLiteralTypeAnnotation extends BaseNode { + type: "BigIntLiteralTypeAnnotation"; + bigint: string; + value: bigint; + raw: string; +} +export interface BooleanLiteralTypeAnnotation extends BaseNode { + type: "BooleanLiteralTypeAnnotation"; + value: boolean; + raw: "true" | "false"; +} +export interface ArrayTypeAnnotation extends BaseNode { + type: "ArrayTypeAnnotation"; + elementType: TypeAnnotationType; +} +export interface NullableTypeAnnotation extends BaseNode { + type: "NullableTypeAnnotation"; + typeAnnotation: TypeAnnotationType; +} +export interface ExistsTypeAnnotation extends BaseNode { + type: "ExistsTypeAnnotation"; +} +export interface GenericTypeAnnotation extends BaseNode { + type: "GenericTypeAnnotation"; + id: Identifier | QualifiedTypeIdentifier; + typeParameters: null | TypeParameterInstantiation; +} +export interface QualifiedTypeIdentifier extends BaseNode { + type: "QualifiedTypeIdentifier"; + id: Identifier; + qualification: QualifiedTypeIdentifier | Identifier; +} +export interface QualifiedTypeofIdentifier extends BaseNode { + type: "QualifiedTypeofIdentifier"; + id: Identifier; + qualification: QualifiedTypeofIdentifier | Identifier; +} +export interface TypeofTypeAnnotation extends BaseNode { + type: "TypeofTypeAnnotation"; + argument: QualifiedTypeofIdentifier | Identifier; + typeArguments?: TypeParameterInstantiation; +} +export interface KeyofTypeAnnotation extends BaseNode { + type: "KeyofTypeAnnotation"; + argument: TypeAnnotationType; +} +export interface TupleTypeAnnotation extends BaseNode { + type: "TupleTypeAnnotation"; + types: $ReadOnlyArray; + inexact: boolean; +} +export interface TupleTypeSpreadElement extends BaseNode { + type: "TupleTypeSpreadElement"; + label?: Identifier | null; + typeAnnotation: TypeAnnotationType; +} +export interface TupleTypeLabeledElement extends BaseNode { + type: "TupleTypeLabeledElement"; + label: Identifier; + elementType: TypeAnnotationType; + optional: boolean; + variance: Variance | null; +} + +export interface InferTypeAnnotation extends BaseNode { + type: "InferTypeAnnotation"; + typeParameter: TypeParameter; +} + +// type T = { [[foo]]: number }; +export interface ObjectTypeInternalSlot extends BaseNode { + type: "ObjectTypeInternalSlot"; + id: Identifier; + optional: boolean; + static: boolean; + method: boolean; + value: TypeAnnotation; + + parent: ObjectTypeAnnotation; +} + +export interface InterfaceTypeAnnotation extends BaseInterfaceNode { + type: "InterfaceTypeAnnotation"; +} + +export interface UnionTypeAnnotation extends BaseNode { + type: "UnionTypeAnnotation"; + types: $ReadOnlyArray; +} +export interface IntersectionTypeAnnotation extends BaseNode { + type: "IntersectionTypeAnnotation"; + types: $ReadOnlyArray; +} + +export interface ConditionalTypeAnnotation extends BaseNode { + type: "ConditionalTypeAnnotation"; + checkType: TypeAnnotationType; + extendsType: TypeAnnotationType; + trueType: TypeAnnotationType; + falseType: TypeAnnotationType; +} + +export type TypeOperator = + | RendersTypeOperator + | RendersStarTypeOperator + | RendersQuestionTypeOperator; + +export type RendersType = + | RendersTypeOperator + | RendersStarTypeOperator + | RendersQuestionTypeOperator; + +interface TypeOperatorBase extends BaseNode { + type: "TypeOperator"; + typeAnnotation: TypeAnnotationType; +} +export interface RendersTypeOperator extends TypeOperatorBase { + type: "TypeOperator"; + operator: "renders"; +} +export interface RendersStarTypeOperator extends TypeOperatorBase { + type: "TypeOperator"; + operator: "renders*"; +} +export interface RendersQuestionTypeOperator extends TypeOperatorBase { + type: "TypeOperator"; + operator: "renders?"; +} + +export interface TypePredicate extends BaseNode { + type: "TypePredicate"; + parameterName: Identifier; + typeAnnotation: TypeAnnotationType | null; + kind: null | "asserts" | "implies"; +} + +export interface FunctionTypeAnnotation extends BaseNode { + type: "FunctionTypeAnnotation"; + params: $ReadOnlyArray; + returnType: TypeAnnotationType; + rest: null | FunctionTypeParam; + typeParameters: null | TypeParameterDeclaration; + this: FunctionTypeParam | null; +} +export interface FunctionTypeParam extends BaseNode { + type: "FunctionTypeParam"; + name: Identifier | null; + typeAnnotation: TypeAnnotationType; + optional: boolean; + + parent: FunctionTypeAnnotation; +} +export interface HookTypeAnnotation extends BaseNode { + type: "HookTypeAnnotation"; + params: $ReadOnlyArray; + returnType: TypeAnnotationType; + rest: null | FunctionTypeParam; + typeParameters: null | TypeParameterDeclaration; +} + +export interface ComponentTypeAnnotation extends BaseNode { + type: "ComponentTypeAnnotation"; + params: $ReadOnlyArray; + rest: null | ComponentTypeParameter; + typeParameters: null | TypeParameterDeclaration; + rendersType: null | RendersType; +} +export interface ComponentTypeParameter extends BaseNode { + type: "ComponentTypeParameter"; + name: Identifier | StringLiteral | null; + typeAnnotation: TypeAnnotationType; + optional: boolean; + + parent: ComponentTypeAnnotation | DeclareComponent; +} + +export interface InferredPredicate extends BaseNode { + type: "InferredPredicate"; + + parent: AFunction | DeclareFunction; +} + +export interface ObjectTypeAnnotation extends BaseNode { + type: "ObjectTypeAnnotation"; + inexact: boolean; + exact: boolean; + properties: $ReadOnlyArray< + ObjectTypeProperty | ObjectTypeSpreadProperty | ObjectTypeMappedTypeProperty + >; + indexers: $ReadOnlyArray; + callProperties: $ReadOnlyArray; + internalSlots: $ReadOnlyArray; +} +interface ObjectTypePropertyBase extends BaseNode { + type: "ObjectTypeProperty"; + key: Identifier | StringLiteral; + value: TypeAnnotationType; + method: boolean; + optional: boolean; + static: boolean; // only applies to the "declare class" case + proto: boolean; // only applies to the "declare class" case + variance: Variance | null; + kind: "init" | "get" | "set"; + + parent: ObjectTypeAnnotation; +} +export interface ObjectTypeMethodSignature extends ObjectTypePropertyBase { + type: "ObjectTypeProperty"; + value: FunctionTypeAnnotation; + method: true; + optional: false; + variance: null; + kind: "init"; + + parent: ObjectTypeAnnotation; +} +export interface ObjectTypePropertySignature extends ObjectTypePropertyBase { + type: "ObjectTypeProperty"; + value: TypeAnnotationType; + method: false; + optional: boolean; + variance: Variance | null; + kind: "init"; + + parent: ObjectTypeAnnotation; +} +export interface ObjectTypeAccessorSignature extends ObjectTypePropertyBase { + type: "ObjectTypeProperty"; + value: FunctionTypeAnnotation; + method: false; + optional: false; + variance: null; + kind: "get" | "set"; + + parent: ObjectTypeAnnotation; +} +export type ObjectTypeProperty = + | ObjectTypeMethodSignature + | ObjectTypePropertySignature + | ObjectTypeAccessorSignature; + +export interface ObjectTypeCallProperty extends BaseNode { + type: "ObjectTypeCallProperty"; + value: FunctionTypeAnnotation; + static: boolean; // can only be static when defined on a declare class + + parent: ObjectTypeAnnotation; +} +export interface ObjectTypeIndexer extends BaseNode { + type: "ObjectTypeIndexer"; + id: null | Identifier; + key: TypeAnnotationType; + value: TypeAnnotationType; + static: boolean; // can only be static when defined on a declare class + variance: null | Variance; + + parent: ObjectTypeAnnotation; +} +export interface ObjectTypeMappedTypeProperty extends BaseNode { + type: "ObjectTypeMappedTypeProperty"; + keyTparam: TypeParameter; + propType: TypeAnnotationType; + sourceType: TypeAnnotationType; + variance: null | Variance; + optional: null | "PlusOptional" | "MinusOptional" | "Optional"; + + parent: ObjectTypeAnnotation; +} + +export interface ObjectTypeSpreadProperty extends BaseNode { + type: "ObjectTypeSpreadProperty"; + argument: TypeAnnotationType; + + parent: ObjectTypeAnnotation; +} + +export interface IndexedAccessType extends BaseNode { + type: "IndexedAccessType"; + objectType: TypeAnnotationType; + indexType: TypeAnnotationType; +} +export interface OptionalIndexedAccessType extends BaseNode { + type: "OptionalIndexedAccessType"; + objectType: TypeAnnotationType; + indexType: TypeAnnotationType; + optional: boolean; +} + +export interface TypeCastExpression extends BaseNode { + type: "TypeCastExpression"; + expression: Expression; + typeAnnotation: TypeAnnotation; +} +export interface AsExpression extends BaseNode { + type: "AsExpression"; + expression: Expression; + typeAnnotation: TypeAnnotationType; +} +export interface AsConstExpression extends BaseNode { + type: "AsConstExpression"; + expression: Expression; +} + +interface BaseInterfaceNode extends BaseNode { + body: ObjectTypeAnnotation; + extends: $ReadOnlyArray; +} +interface BaseInterfaceDeclaration extends BaseInterfaceNode { + id: Identifier; + typeParameters: null | TypeParameterDeclaration; +} + +export interface InterfaceDeclaration extends BaseInterfaceDeclaration { + type: "InterfaceDeclaration"; +} + +export interface InterfaceExtends extends BaseNode { + type: "InterfaceExtends"; + id: Identifier | QualifiedTypeIdentifier; + typeParameters: null | TypeParameterInstantiation; + + parent: InterfaceDeclaration | DeclareInterface; +} + +export interface ClassImplements extends BaseNode { + type: "ClassImplements"; + id: Identifier; + typeParameters: null | TypeParameterInstantiation; + + parent: AClass | DeclareClass; +} + +export interface Decorator extends BaseNode { + type: "Decorator"; + expression: Expression; + + parent: AClass; +} + +export interface TypeParameterDeclaration extends BaseNode { + type: "TypeParameterDeclaration"; + params: $ReadOnlyArray; +} +export interface TypeParameter extends BaseNode { + type: "TypeParameter"; + name: string; + const: boolean; + bound: null | TypeAnnotation; + variance: null | Variance; + default: null | TypeAnnotationType; + usesExtendsBound: boolean; + parent: TypeParameterDeclaration; +} +export interface TypeParameterInstantiation extends BaseNode { + type: "TypeParameterInstantiation"; + params: $ReadOnlyArray; + + parent: GenericTypeAnnotation | CallExpression | NewExpression; +} + +export interface EnumDeclaration extends BaseNode { + type: "EnumDeclaration"; + id: Identifier; + body: + | EnumNumberBody + | EnumBigIntBody + | EnumStringBody + | EnumBooleanBody + | EnumSymbolBody; +} + +interface BaseEnumBody extends BaseNode { + hasUnknownMembers: boolean; +} +interface BaseInferrableEnumBody extends BaseEnumBody { + explicitType: boolean; +} + +export interface EnumNumberBody extends BaseInferrableEnumBody { + type: "EnumNumberBody"; + // enum number members cannot be defaulted + members: $ReadOnlyArray; + explicitType: boolean; + + parent: EnumDeclaration; +} + +export interface EnumNumberMember extends BaseNode { + type: "EnumNumberMember"; + id: Identifier; + init: NumericLiteral; + + parent: EnumNumberBody; +} + +export interface EnumBigIntBody extends BaseInferrableEnumBody { + type: "EnumBigIntBody"; + // enum bigint members cannot be defaulted + members: $ReadOnlyArray; + explicitType: boolean; + + parent: EnumDeclaration; +} + +export interface EnumBigIntMember extends BaseNode { + type: "EnumBigIntMember"; + id: Identifier; + init: BigIntLiteral; + + parent: EnumBigIntBody; +} + +export interface EnumStringBody extends BaseInferrableEnumBody { + type: "EnumStringBody"; + members: $ReadOnlyArray; + + parent: EnumDeclaration; +} + +export interface EnumStringMember extends BaseNode { + type: "EnumStringMember"; + id: Identifier; + init: StringLiteral; + + parent: EnumStringBody; +} + +export interface EnumBooleanBody extends BaseInferrableEnumBody { + type: "EnumBooleanBody"; + // enum boolean members cannot be defaulted + members: $ReadOnlyArray; + + parent: EnumDeclaration; +} + +export interface EnumBooleanMember extends BaseNode { + type: "EnumBooleanMember"; + id: Identifier; + init: BooleanLiteral; + + parent: EnumBooleanBody; +} + +export interface EnumSymbolBody extends BaseEnumBody { + type: "EnumSymbolBody"; + // enum symbol members can only be defaulted + members: $ReadOnlyArray; + + parent: EnumDeclaration; +} + +export interface EnumDefaultedMember extends BaseNode { + type: "EnumDefaultedMember"; + id: Identifier; + + parent: EnumStringBody | EnumSymbolBody; +} + +/***************** + * Declare nodes * + *****************/ + +export type DeclaredNode = + | DeclareClass + | DeclareComponent + | DeclareHook + | DeclareVariable + | DeclareEnum + | DeclareFunction + | DeclareModule + | DeclareInterface + | DeclareTypeAlias + | DeclareOpaqueType + | DeclareExportAllDeclaration + | DeclareExportDeclaration + | DeclareModuleExports + | DeclaredPredicate; + +export interface DeclareClass extends BaseNode { + type: "DeclareClass"; + id: Identifier; + typeParameters: null | TypeParameterDeclaration; + extends: $ReadOnlyArray; + implements: $ReadOnlyArray; + body: ObjectTypeAnnotation; + mixins: $ReadOnlyArray; +} + +export interface DeclareComponent extends BaseNode { + type: "DeclareComponent"; + id: Identifier; + params: Array; + rest: null | ComponentTypeParameter; + typeParameters: null | TypeParameterDeclaration; + rendersType: null | RendersType; +} + +export interface DeclareHook extends BaseNode { + type: "DeclareHook"; + // the hook signature is stored as a type annotation on the ID + id: Identifier & { + typeAnnotation: TypeAnnotation & { + typeAnnotation: HookTypeAnnotation; + }; + }; +} + +export interface DeclareVariable extends BaseNode { + type: "DeclareVariable"; + id: Identifier; + kind: "var" | "let" | "const"; +} + +export interface DeclareEnum extends BaseNode { + type: "DeclareEnum"; + id: Identifier; + body: EnumNumberBody | EnumStringBody | EnumBooleanBody | EnumSymbolBody; +} + +export interface DeclareFunction extends BaseNode { + type: "DeclareFunction"; + // the function signature is stored as a type annotation on the ID + id: Identifier & { + typeAnnotation: TypeAnnotation & { + typeAnnotation: FunctionTypeAnnotation; + }; + }; + predicate: InferredPredicate | DeclaredPredicate | null; +} + +export interface DeclareModule extends BaseNode { + type: "DeclareModule"; + id: StringLiteral | Identifier; + body: BlockStatement; +} + +export interface DeclareNamespace extends BaseNode { + type: "DeclareNamespace"; + id: Identifier; + body: BlockStatement; +} + +export interface DeclareInterface extends BaseInterfaceDeclaration { + type: "DeclareInterface"; +} + +export interface DeclareTypeAlias extends BaseTypeAlias { + type: "DeclareTypeAlias"; +} + +export interface DeclareOpaqueType extends BaseOpaqueType { + type: "DeclareOpaqueType"; + impltype: null; +} + +export interface DeclareExportAllDeclaration extends BaseNode { + type: "DeclareExportAllDeclaration"; + source: StringLiteral; +} + +interface DeclareExportDeclarationBase extends BaseNode { + type: "DeclareExportDeclaration"; + specifiers: $ReadOnlyArray; + source: StringLiteral | null; + default: boolean; +} +export interface DeclareExportDefaultDeclaration extends DeclareExportDeclarationBase { + type: "DeclareExportDeclaration"; + declaration: + | DeclareClass + | DeclareFunction + | DeclareComponent + | DeclareHook + | TypeAnnotationType; + default: true; + // default cannot have a source + source: null; + // default cannot have specifiers + specifiers: []; +} +export interface DeclareExportDeclarationNamedWithDeclaration extends DeclareExportDeclarationBase { + type: "DeclareExportDeclaration"; + declaration: + | DeclareClass + | DeclareFunction + | DeclareComponent + | DeclareHook + | DeclareInterface + | DeclareOpaqueType + | DeclareVariable + | DeclareEnum; + default: false; + source: null; + // default cannot have specifiers and a declaration + specifiers: []; +} +export interface DeclareExportDeclarationNamedWithSpecifiers extends DeclareExportDeclarationBase { + type: "DeclareExportDeclaration"; + // with a source you can't have a declaration + declaration: null; + default: false; + source: StringLiteral; + specifiers: $ReadOnlyArray; +} +export type DeclareExportDeclaration = + | DeclareExportDefaultDeclaration + | DeclareExportDeclarationNamedWithDeclaration + | DeclareExportDeclarationNamedWithSpecifiers; + +export interface DeclareModuleExports extends BaseNode { + type: "DeclareModuleExports"; + typeAnnotation: TypeAnnotation; +} + +export interface DeclaredPredicate extends BaseNode { + type: "DeclaredPredicate"; + value: Expression; +} + +/********************** + * JSX specific nodes * + **********************/ + +export type JSXChild = + | JSXElement + | JSXExpression + | JSXFragment + | JSXText + | JSXSpreadChild; +export type JSXExpression = JSXEmptyExpression | JSXExpressionContainer; +export type JSXTagNameExpression = + | JSXIdentifier + | JSXMemberExpression + | JSXNamespacedName; + +export type JSXNode = + | JSXAttribute + | JSXClosingElement + | JSXClosingFragment + | JSXElement + | JSXEmptyExpression + | JSXExpressionContainer + | JSXFragment + | JSXIdentifier + | JSXMemberExpression + | JSXNamespacedName + | JSXOpeningElement + | JSXOpeningFragment + | JSXSpreadAttribute + | JSXText + | JSXSpreadChild; + +export interface JSXAttribute extends BaseNode { + type: "JSXAttribute"; + name: JSXIdentifier; + value: Literal | JSXExpression | null; + + parent: JSXOpeningElement; +} + +export interface JSXClosingElement extends BaseNode { + type: "JSXClosingElement"; + name: JSXTagNameExpression; + + parent: JSXElement; +} + +export interface JSXClosingFragment extends BaseNode { + type: "JSXClosingFragment"; + + parent: JSXFragment; +} + +export interface JSXElement extends BaseNode { + type: "JSXElement"; + openingElement: JSXOpeningElement; + closingElement: JSXClosingElement | null; + children: $ReadOnlyArray; +} + +export interface JSXEmptyExpression extends BaseNode { + type: "JSXEmptyExpression"; +} + +export interface JSXExpressionContainer extends BaseNode { + type: "JSXExpressionContainer"; + expression: Expression | JSXEmptyExpression; +} + +export interface JSXFragment extends BaseNode { + type: "JSXFragment"; + openingFragment: JSXOpeningFragment; + closingFragment: JSXClosingFragment; + children: $ReadOnlyArray; +} + +export interface JSXIdentifier extends BaseNode { + type: "JSXIdentifier"; + name: string; +} + +export interface JSXMemberExpression extends BaseNode { + type: "JSXMemberExpression"; + object: JSXTagNameExpression; + property: JSXIdentifier; +} + +export interface JSXNamespacedName extends BaseNode { + type: "JSXNamespacedName"; + namespace: JSXIdentifier; + name: JSXIdentifier; +} + +export interface JSXOpeningElement extends BaseNode { + type: "JSXOpeningElement"; + selfClosing: boolean; + name: JSXTagNameExpression; + attributes: $ReadOnlyArray; + typeArguments?: TypeParameterInstantiation | null; + + parent: JSXElement; +} + +export interface JSXOpeningFragment extends BaseNode { + type: "JSXOpeningFragment"; + + parent: JSXFragment; +} + +export interface JSXSpreadAttribute extends BaseNode { + type: "JSXSpreadAttribute"; + argument: Expression; + + parent: JSXOpeningElement; +} + +export interface JSXText extends BaseNode { + type: "JSXText"; + value: string; + raw: string; +} + +export interface JSXSpreadChild extends BaseNode { + type: "JSXSpreadChild"; + expression: Expression; +} + +/************************************ + * Match expressions and statements * + ************************************/ + +export interface MatchExpression extends BaseNode { + type: "MatchExpression"; + argument: Expression; + cases: $ReadOnlyArray; +} +export interface MatchExpressionCase extends BaseNode { + type: "MatchExpressionCase"; + pattern: MatchPattern; + body: Expression; + guard: Expression | null; +} + +export interface MatchStatement extends BaseNode { + type: "MatchStatement"; + argument: Expression; + cases: $ReadOnlyArray; +} +export interface MatchStatementCase extends BaseNode { + type: "MatchStatementCase"; + pattern: MatchPattern; + body: BlockStatement; + guard: Expression | null; +} + +/****************** + * Match patterns * + ******************/ + +export type MatchPattern = + | MatchOrPattern + | MatchAsPattern + | MatchWildcardPattern + | MatchLiteralPattern + | MatchUnaryPattern + | MatchIdentifierPattern + | MatchMemberPattern + | MatchBindingPattern + | MatchObjectPattern + | MatchArrayPattern; + +export interface MatchOrPattern extends BaseNode { + type: "MatchOrPattern"; + patterns: $ReadOnlyArray; +} +export interface MatchAsPattern extends BaseNode { + type: "MatchAsPattern"; + pattern: MatchPattern; + target: Identifier | MatchBindingPattern; +} +export interface MatchWildcardPattern extends BaseNode { + type: "MatchWildcardPattern"; +} +export interface MatchLiteralPattern extends BaseNode { + type: "MatchLiteralPattern"; + literal: Literal; +} +export interface MatchUnaryPattern extends BaseNode { + type: "MatchUnaryPattern"; + argument: Literal; + operator: "-" | "+"; +} +export interface MatchIdentifierPattern extends BaseNode { + type: "MatchIdentifierPattern"; + id: Identifier; +} +export interface MatchMemberPattern extends BaseNode { + type: "MatchMemberPattern"; + base: MatchIdentifierPattern | MatchMemberPattern; + property: Identifier | StringLiteral | NumericLiteral | BigIntLiteral; +} +export interface MatchBindingPattern extends BaseNode { + type: "MatchBindingPattern"; + id: Identifier; + kind: "let" | "const" | "var"; +} +export interface MatchObjectPattern extends BaseNode { + type: "MatchObjectPattern"; + properties: $ReadOnlyArray; + rest: MatchRestPattern | null; +} +export interface MatchObjectPatternProperty extends BaseNode { + type: "MatchObjectPatternProperty"; + key: Identifier | StringLiteral | NumericLiteral | BigIntLiteral; + pattern: MatchPattern; + shorthand: boolean; +} +export interface MatchArrayPattern extends BaseNode { + type: "MatchArrayPattern"; + elements: $ReadOnlyArray; + rest: MatchRestPattern | null; +} +export interface MatchRestPattern extends BaseNode { + type: "MatchRestPattern"; + argument: MatchBindingPattern | null; +} + +/****************************************************** + * Deprecated spec nodes awaiting migration by Hermes * + ******************************************************/ + +export {}; diff --git a/src/language-js/types/typescript-estree.ts b/src/language-js/types/typescript-estree.ts new file mode 100644 index 000000000..6ab22bd09 --- /dev/null +++ b/src/language-js/types/typescript-estree.ts @@ -0,0 +1,10 @@ +import type { TSESTree } from "@typescript-eslint/typescript-estree"; + +type NodeOrComment = TSESTree.Node | TSESTree.Comment; + +type ConvertTypeToString = { + [Key in keyof Node]: Key extends "type" ? `${Node[Key]}` : Node[Key]; +}; + +export type Node = ConvertTypeToString; +export type Comment = ConvertTypeToString; diff --git a/src/language-js/utilities/create-type-check-function.js b/src/language-js/utilities/create-type-check-function.js index 5491983e9..68be5a537 100644 --- a/src/language-js/utilities/create-type-check-function.js +++ b/src/language-js/utilities/create-type-check-function.js @@ -1,11 +1,13 @@ import * as assert from "#universal/assert"; -/** @import {Node, Comment} from "../types/estree.js" */ +/** +@import {Node, Comment, Nodes, Comments} from "../types/estree.js"; +*/ /** - * @param {string[]} typesArray - * @returns {(node: Node | Comment) => Boolean} - */ +@template {(Node | Comment)["type"][]} InputNodeTypes +@param {InputNodeTypes} typesArray +*/ function createTypeCheckFunction(typesArray) { const types = new Set(typesArray); @@ -17,6 +19,14 @@ function createTypeCheckFunction(typesArray) { ); } + /** + @param {Node | Comment | undefined | null} node + @returns { + node is InputNodeTypes extends Node["type"][] + ? Nodes[InputNodeTypes[number]] + : Comments[InputNodeTypes[number]] + } + */ return (node) => types.has(node?.type); } diff --git a/src/language-js/utilities/index.js b/src/language-js/utilities/index.js index 056f4d82d..388b769b5 100644 --- a/src/language-js/utilities/index.js +++ b/src/language-js/utilities/index.js @@ -16,13 +16,13 @@ import isNodeMatches from "./is-node-matches.js"; import isTsKeywordType from "./is-ts-keyword-type.js"; /** -@import * as Estree from "../types/estree.js" -@import AstPath from "../../common/ast-path.js" +@import {Node, Nodes, Comment} from "../types/estree.js"; +@import AstPath from "../../common/ast-path.js"; */ /** - * @param {Estree.Node} node - * @param {(node: Estree.Node) => boolean} predicate + * @param {Node} node + * @param {(node: Node) => boolean} predicate * @returns {boolean} */ function hasNode(node, predicate) { @@ -30,7 +30,7 @@ function hasNode(node, predicate) { } /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function hasNakedLeftSide(node) { @@ -110,7 +110,7 @@ const isArrayExpression = createTypeCheckFunction(["ArrayExpression"]); const isObjectExpression = createTypeCheckFunction(["ObjectExpression"]); /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function isNullishCoalescing(node) { @@ -118,7 +118,7 @@ function isNullishCoalescing(node) { } /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function isNumericLiteral(node) { @@ -144,7 +144,7 @@ function isSignedNumericLiteral(node) { } /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function isStringLiteral(node) { @@ -193,7 +193,7 @@ const isFunctionOrArrowExpression = createTypeCheckFunction([ ]); /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function isFunctionOrArrowExpressionWithBody(node) { @@ -211,7 +211,7 @@ function isFunctionOrArrowExpressionWithBody(node) { * * example: https://docs.angularjs.org/guide/unit-testing#using-beforeall- * - * @param {Estree.CallExpression} node + * @param {Nodes["CallExpression"]} node * @returns {boolean} */ function isAngularTestWrapper(node) { @@ -233,7 +233,7 @@ function isMethod(node) { } /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function isFlowObjectTypePropertyAFunction(node) { @@ -269,7 +269,7 @@ const isBinaryish = createTypeCheckFunction([ ]); /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function isMemberish(node) { @@ -291,7 +291,7 @@ const isSimpleTypeAnnotation = createTypeCheckFunction([ "TSTemplateLiteralType", ]); /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function isSimpleType(node) { @@ -387,7 +387,10 @@ function isTestCall(node, parent) { return false; } -/** @return {(node: Estree.Node) => boolean} */ +/** +@template {ReturnType} TypeCheckFunction +@param {TypeCheckFunction} fn +@return {(node: Node) => boolean} */ const skipChainExpression = (fn) => (node) => { if (node?.type === "ChainExpression") { node = node.expression; @@ -486,7 +489,7 @@ function isLoneShortArgument(node, options) { /** * @param {string} text - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function hasLeadingOwnLineComment(text, node) { @@ -500,7 +503,7 @@ function hasLeadingOwnLineComment(text, node) { } /** - * @param {Estree.TemplateLiteral} template + * @param {Nodes["TemplateLiteral"]} template * @returns {boolean} */ function templateLiteralHasNewLines(template) { @@ -508,7 +511,7 @@ function templateLiteralHasNewLines(template) { } /** - * @param {Estree.TemplateLiteral | Estree.TaggedTemplateExpression} node + * @param {Nodes["TemplateLiteral"] | Nodes["TaggedTemplateExpression"]} node * @param {string} text * @returns {boolean} */ @@ -522,7 +525,7 @@ function isTemplateOnItsOwnLine(node, text) { } /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ function needsHardlineAfterDanglingComment(node) { @@ -681,8 +684,8 @@ function shouldPrintComma(options, level = "es5") { * * Will be overzealous if there already are necessary grouping parentheses. * - * @param {Estree.Node} node - * @param {(leftmostNode: Estree.Node) => boolean} predicate + * @param {Node} node + * @param {(leftmostNode: Node) => boolean} predicate * @returns {boolean} */ function startsWithNoLookaheadToken(node, predicate) { @@ -999,7 +1002,7 @@ const getCommentTestFunction = (flags, fn) => { } }; /** - * @param {Estree.Node} node + * @param {Node} node * @param {number | function} [flags] * @param {function} [fn] * @returns {boolean} @@ -1013,10 +1016,10 @@ function hasComment(node, flags, fn) { } /** - * @param {Estree.Node} node + * @param {Node} node * @param {number | function} [flags] * @param {function} [fn] - * @returns {Estree.Comment[]} + * @returns {Comment[]} */ function getComments(node, flags, fn) { if (!Array.isArray(node?.comments)) { @@ -1027,7 +1030,7 @@ function getComments(node, flags, fn) { } /** - * @param {Estree.Node} node + * @param {Node} node * @returns {boolean} */ const isNextLineEmpty = (node, { originalText }) => diff --git a/src/language-js/utilities/is-block-comment.js b/src/language-js/utilities/is-block-comment.js index 16aeddcb9..eb01ca2ce 100644 --- a/src/language-js/utilities/is-block-comment.js +++ b/src/language-js/utilities/is-block-comment.js @@ -1,7 +1,8 @@ import createTypeCheckFunction from "./create-type-check-function.js"; + /** - * @import {Comment} from "../types/estree.js" - */ +@import {Comment} from "../types/estree.js"; +*/ /** * @param {Comment} comment diff --git a/src/language-js/utilities/is-line-comment.js b/src/language-js/utilities/is-line-comment.js index 79aedac05..8c70b4494 100644 --- a/src/language-js/utilities/is-line-comment.js +++ b/src/language-js/utilities/is-line-comment.js @@ -1,13 +1,9 @@ import createTypeCheckFunction from "./create-type-check-function.js"; /** - * @import {Comment} from "../types/estree.js" - */ +@import {Comment} from "../types/estree.js"; +*/ -/** - * @param {Comment} comment - * @returns {boolean} - */ const isLineComment = createTypeCheckFunction([ "Line", "CommentLine", diff --git a/src/language-js/utilities/is-type-cast-comment.js b/src/language-js/utilities/is-type-cast-comment.js index 0a9588fba..41f5d4ec2 100644 --- a/src/language-js/utilities/is-type-cast-comment.js +++ b/src/language-js/utilities/is-type-cast-comment.js @@ -1,8 +1,8 @@ import isBlockComment from "./is-block-comment.js"; /** - * @import {Comment} from "../types/estree.js" - */ +@import {Comment} from "../types/estree.js" +*/ const cache = new WeakMap(); diff --git a/yarn.lock b/yarn.lock index d9b1427d9..fc5b7c16b 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2438,7 +2438,7 @@ __metadata: languageName: node linkType: hard -"@types/estree@npm:1.0.8, @types/estree@npm:^1.0.6": +"@types/estree@npm:^1.0.6": version: 1.0.8 resolution: "@types/estree@npm:1.0.8" checksum: 10/25a4c16a6752538ffde2826c2cc0c6491d90e69cd6187bef4a006dd2c3c45469f049e643d7e516c515f21484dc3d48fd5c870be158a5beb72f5baf3dc43e4099 @@ -7523,7 +7523,6 @@ __metadata: "@prettier/html-tags": "npm:2.0.0" "@prettier/parse-srcset": "npm:3.1.0" "@stylistic/eslint-plugin": "npm:5.6.1" - "@types/estree": "npm:1.0.8" "@types/jsesc": "npm:3.0.3" "@typescript-eslint/eslint-plugin": "npm:8.48.1" "@typescript-eslint/parser": "npm:8.48.1"