diff --git a/tools/hermes-parser/js/__tests__/types-include-all-nodes-test.js b/tools/hermes-parser/js/__tests__/types-include-all-nodes-test.js index 7d8ff795423..60900f288f6 100644 --- a/tools/hermes-parser/js/__tests__/types-include-all-nodes-test.js +++ b/tools/hermes-parser/js/__tests__/types-include-all-nodes-test.js @@ -101,11 +101,14 @@ function getInterfaces(): $ReadOnlyMap< const typesThatShouldBeSkipped = new Set([ // These types have a special union type declared to allow consumers to refine on `.computed` - 'PropertyDefinition', - 'MethodDefinition', + 'BinaryExpression', + 'DeclareExportDeclaration', + 'ExportNamedDeclaration', 'MemberExpression', + 'MethodDefinition', + 'ObjectTypeProperty', 'Property', - 'BinaryExpression', + 'PropertyDefinition', ]); const propertiesThatShouldBeSkipped = new Map([ [ diff --git a/tools/hermes-parser/js/hermes-eslint/__tests__/eslint-scope/get-declared-variables-test.js b/tools/hermes-parser/js/hermes-eslint/__tests__/eslint-scope/get-declared-variables-test.js index 9a52f73de2b..d466c265e97 100644 --- a/tools/hermes-parser/js/hermes-eslint/__tests__/eslint-scope/get-declared-variables-test.js +++ b/tools/hermes-parser/js/hermes-eslint/__tests__/eslint-scope/get-declared-variables-test.js @@ -35,7 +35,7 @@ import type {Program, ESNode} from 'hermes-estree'; -// $FlowExpectedError[untyped-import] +// $FlowExpectedError import {visit} from 'esrecurse'; import {parse} from '../../src'; import {analyze} from '../../src/scope-manager'; diff --git a/tools/hermes-parser/js/hermes-estree/src/types.js b/tools/hermes-parser/js/hermes-estree/src/types.js index a629b65c30b..17737b714a5 100644 --- a/tools/hermes-parser/js/hermes-estree/src/types.js +++ b/tools/hermes-parser/js/hermes-estree/src/types.js @@ -853,7 +853,7 @@ interface BaseClass extends BaseNode { +body: ClassBody; +typeParameters: null | TypeParameterDeclaration; - +superTypeParameters: null | TypeParameterDeclaration; + +superTypeParameters: null | TypeParameterInstantiation; +implements: $ReadOnlyArray; +decorators: $ReadOnlyArray; } @@ -1027,13 +1027,30 @@ export type NamedDeclaration = | InterfaceDeclaration | EnumDeclaration; -export interface ExportNamedDeclaration extends BaseNode { +interface ExportNamedDeclarationBase extends BaseNode { +type: 'ExportNamedDeclaration'; +declaration?: NamedDeclaration | null; +specifiers: $ReadOnlyArray; - +source?: Literal | null; + +source?: StringLiteral | null; +exportKind: 'value' | 'type'; } +export interface ExportNamedDeclarationWithSpecifiers + extends ExportNamedDeclarationBase { + +type: 'ExportNamedDeclaration'; + +declaration: null; + +source: 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'; @@ -1065,6 +1082,7 @@ export interface AwaitExpression extends BaseNode { export type TypeAnnotationType = | NumberTypeAnnotation | StringTypeAnnotation + | BigIntTypeAnnotation | BooleanTypeAnnotation | NullLiteralTypeAnnotation | AnyTypeAnnotation @@ -1128,6 +1146,9 @@ export interface NumberTypeAnnotation extends BaseNode { export interface StringTypeAnnotation extends BaseNode { +type: 'StringTypeAnnotation'; } +export interface BigIntTypeAnnotation extends BaseNode { + +type: 'BigIntTypeAnnotation'; +} export interface BooleanTypeAnnotation extends BaseNode { +type: 'BooleanTypeAnnotation'; } @@ -1170,7 +1191,7 @@ export interface BigIntLiteralTypeAnnotation extends BaseNode { export interface BooleanLiteralTypeAnnotation extends BaseNode { +type: 'BooleanLiteralTypeAnnotation'; +value: boolean; - +raw: string; + +raw: 'true' | 'false'; } export interface ArrayTypeAnnotation extends BaseNode { +type: 'ArrayTypeAnnotation'; @@ -1199,7 +1220,7 @@ export interface TypeofTypeAnnotation extends BaseNode { } export interface TupleTypeAnnotation extends BaseNode { +type: 'TupleTypeAnnotation'; - +types: TypeAnnotationType; + +types: $ReadOnlyArray; } // type T = { [[foo]]: number }; @@ -1258,23 +1279,58 @@ export interface ObjectTypeAnnotation extends BaseNode { +callProperties: $ReadOnlyArray; +internalSlots: $ReadOnlyArray; } -export interface ObjectTypeProperty extends BaseNode { +interface ObjectTypePropertyBase extends BaseNode { +type: 'ObjectTypeProperty'; +key: Identifier | StringLiteral; +value: TypeAnnotationType; +method: boolean; +optional: boolean; - +static: boolean; - +proto: false; // ??? + +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: false; // can't be static + +static: boolean; // can only be static when defined on a declare class +parent: ObjectTypeAnnotation; } @@ -1283,7 +1339,7 @@ export interface ObjectTypeIndexer extends BaseNode { +id: null | Identifier; +key: TypeAnnotationType; +value: TypeAnnotationType; - +static: false; // can't be static + +static: boolean; // can only be static when defined on a declare class +variance: null | Variance; +parent: ObjectTypeAnnotation; @@ -1329,7 +1385,7 @@ export interface InterfaceDeclaration extends BaseInterfaceDeclaration { export interface InterfaceExtends extends BaseNode { +type: 'InterfaceExtends'; +id: Identifier; - +typeParameters: null | TypeParameterDeclaration; + +typeParameters: null | TypeParameterInstantiation; +parent: InterfaceDeclaration | DeclareInterface; } @@ -1337,7 +1393,7 @@ export interface InterfaceExtends extends BaseNode { export interface ClassImplements extends BaseNode { +type: 'ClassImplements'; +id: Identifier; - +typeParameters: null | TypeParameterDeclaration; + +typeParameters: null | TypeParameterInstantiation; +parent: AClass | DeclareClass; } @@ -1479,7 +1535,12 @@ export interface DeclareVariable extends BaseNode { export interface DeclareFunction extends BaseNode { +type: 'DeclareFunction'; - +id: Identifier; + // the function signature is stored as a type annotation on the ID + +id: interface extends Identifier { + +typeAnnotation: interface extends TypeAnnotation { + +typeAnnotation: FunctionTypeAnnotation, + }, + }; +predicate: InferredPredicate | DeclaredPredicate | null; } @@ -1508,21 +1569,49 @@ export interface DeclareExportAllDeclaration extends BaseNode { +source: StringLiteral; } -export interface DeclareExportDeclaration extends BaseNode { +interface DeclareExportDeclarationBase extends BaseNode { +type: 'DeclareExportDeclaration'; +specifiers: $ReadOnlyArray; + +source: StringLiteral | null; + +default: boolean; +} +export interface DeclareExportDefaultDeclaration + extends DeclareExportDeclarationBase { + +type: 'DeclareExportDeclaration'; + +declaration: DeclareClass | DeclareFunction | TypeAnnotationType; + +default: true; + // default cannot have a source + +source: null; + // default cannot have specifiers + +specifiers: []; +} +export interface DeclareExportDeclarationNamedWithDeclaration + extends DeclareExportDeclarationBase { + +type: 'DeclareExportDeclaration'; +declaration: - | TypeAlias - | DeclareVariable | DeclareClass | DeclareFunction - | DeclareOpaqueType | DeclareInterface - | TypeAnnotationType - | null; - +source: StringLiteral | null; - +default: boolean; + | DeclareOpaqueType + | DeclareVariable; + +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'; diff --git a/tools/hermes-parser/js/hermes-transform/__tests__/transform/transform-test.js b/tools/hermes-parser/js/hermes-transform/__tests__/transform/transform-test.js index df31c880563..27ebf914068 100644 --- a/tools/hermes-parser/js/hermes-transform/__tests__/transform/transform-test.js +++ b/tools/hermes-parser/js/hermes-transform/__tests__/transform/transform-test.js @@ -1296,32 +1296,47 @@ x?.(); }); context.modifyNodeInPlace(node, { properties: [ - t.ObjectTypeProperty({ + t.ObjectTypeMethodSignature({ key: t.Identifier({name: 'a'}), value: func, - method: true, - optional: false, - static: false, - proto: false, - variance: null, - kind: 'init', }), - t.ObjectTypeProperty({ + t.ObjectTypePropertySignature({ key: t.Identifier({name: 'b'}), value: func, - method: false, optional: false, - static: false, - proto: false, variance: null, - kind: 'init', + }), + t.ObjectTypeAccessorSignature({ + key: t.Identifier({name: 'c'}), + value: func, + kind: 'get', + }), + t.ObjectTypeAccessorSignature({ + key: t.Identifier({name: 'd'}), + // setters must have a param hence new func + value: t.FunctionTypeAnnotation({ + params: [ + t.FunctionTypeParam({ + name: t.Identifier({ + name: 'param', + }), + optional: false, + typeAnnotation: t.StringTypeAnnotation(), + }), + ], + returnType: t.VoidTypeAnnotation(), + rest: null, + typeParameters: null, + this: null, + }), + kind: 'set', }), ], }); }, })); expect(result).toBe(`\ -type A = {a(): void, b: () => void}; +type A = {a(): void, b: () => void, get c(): void, set d(param: string): void}; `); }); }); diff --git a/tools/hermes-parser/js/hermes-transform/src/generated/node-types.js b/tools/hermes-parser/js/hermes-transform/src/generated/node-types.js index 71d05a8ce82..7dbb5d2283a 100644 --- a/tools/hermes-parser/js/hermes-transform/src/generated/node-types.js +++ b/tools/hermes-parser/js/hermes-transform/src/generated/node-types.js @@ -48,8 +48,6 @@ import type { DeclareClass as DeclareClassType, DeclaredPredicate as DeclaredPredicateType, DeclareExportAllDeclaration as DeclareExportAllDeclarationType, - DeclareExportDeclaration as DeclareExportDeclarationType, - DeclareFunction as DeclareFunctionType, DeclareInterface as DeclareInterfaceType, DeclareModule as DeclareModuleType, DeclareModuleExports as DeclareModuleExportsType, @@ -71,7 +69,6 @@ import type { ExistsTypeAnnotation as ExistsTypeAnnotationType, ExportAllDeclaration as ExportAllDeclarationType, ExportDefaultDeclaration as ExportDefaultDeclarationType, - ExportNamedDeclaration as ExportNamedDeclarationType, ExportSpecifier as ExportSpecifierType, ExpressionStatement as ExpressionStatementType, ForInStatement as ForInStatementType, @@ -127,7 +124,6 @@ import type { ObjectTypeCallProperty as ObjectTypeCallPropertyType, ObjectTypeIndexer as ObjectTypeIndexerType, ObjectTypeInternalSlot as ObjectTypeInternalSlotType, - ObjectTypeProperty as ObjectTypePropertyType, ObjectTypeSpreadProperty as ObjectTypeSpreadPropertyType, OpaqueType as OpaqueTypeType, OptionalIndexedAccessType as OptionalIndexedAccessTypeType, @@ -315,22 +311,6 @@ export type DeclareExportAllDeclarationProps = { +source: MaybeDetachedNode, }; -export type DeclareExportDeclarationProps = { - +declaration?: ?MaybeDetachedNode< - DeclareExportDeclarationType['declaration'], - >, - +specifiers: $ReadOnlyArray< - MaybeDetachedNode, - >, - +source?: ?MaybeDetachedNode, - +default: DeclareExportDeclarationType['default'], -}; - -export type DeclareFunctionProps = { - +id: MaybeDetachedNode, - +predicate?: ?MaybeDetachedNode, -}; - export type DeclareInterfaceProps = { +id: MaybeDetachedNode, +typeParameters?: ?MaybeDetachedNode, @@ -445,15 +425,6 @@ export type ExportDefaultDeclarationProps = { +declaration: MaybeDetachedNode, }; -export type ExportNamedDeclarationProps = { - +declaration?: ?MaybeDetachedNode, - +specifiers: $ReadOnlyArray< - MaybeDetachedNode, - >, - +source?: ?MaybeDetachedNode, - +exportKind: ExportNamedDeclarationType['exportKind'], -}; - export type ExportSpecifierProps = { +exported: MaybeDetachedNode, +local: MaybeDetachedNode, @@ -792,17 +763,6 @@ export type ObjectTypeInternalSlotProps = { +method: ObjectTypeInternalSlotType['method'], }; -export type ObjectTypePropertyProps = { - +key: MaybeDetachedNode, - +value: MaybeDetachedNode, - +method: ObjectTypePropertyType['method'], - +optional: ObjectTypePropertyType['optional'], - +static: ObjectTypePropertyType['static'], - +proto: ObjectTypePropertyType['proto'], - +variance?: ?MaybeDetachedNode, - +kind: ObjectTypePropertyType['kind'], -}; - export type ObjectTypeSpreadPropertyProps = { +argument: MaybeDetachedNode, }; @@ -1338,34 +1298,6 @@ export function DeclareExportAllDeclaration(props: { return node; } -export function DeclareExportDeclaration(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const node = detachedProps(props.parent, { - type: 'DeclareExportDeclaration', - declaration: asDetachedNode(props.declaration), - specifiers: props.specifiers.map(n => asDetachedNode(n)), - source: asDetachedNode(props.source), - default: props.default, - }); - setParentPointersInDirectChildren(node); - return node; -} - -export function DeclareFunction(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const node = detachedProps(props.parent, { - type: 'DeclareFunction', - id: asDetachedNode(props.id), - predicate: asDetachedNode(props.predicate), - }); - setParentPointersInDirectChildren(node); - return node; -} - export function DeclareInterface(props: { ...$ReadOnly, +parent?: ESNode, @@ -1636,21 +1568,6 @@ export function ExportDefaultDeclaration(props: { return node; } -export function ExportNamedDeclaration(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const node = detachedProps(props.parent, { - type: 'ExportNamedDeclaration', - declaration: asDetachedNode(props.declaration), - specifiers: props.specifiers.map(n => asDetachedNode(n)), - source: asDetachedNode(props.source), - exportKind: props.exportKind, - }); - setParentPointersInDirectChildren(node); - return node; -} - export function ExportSpecifier(props: { ...$ReadOnly, +parent?: ESNode, @@ -2381,25 +2298,6 @@ export function ObjectTypeInternalSlot(props: { return node; } -export function ObjectTypeProperty(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const node = detachedProps(props.parent, { - type: 'ObjectTypeProperty', - key: asDetachedNode(props.key), - value: asDetachedNode(props.value), - method: props.method, - optional: props.optional, - static: props.static, - proto: props.proto, - variance: asDetachedNode(props.variance), - kind: props.kind, - }); - setParentPointersInDirectChildren(node); - return node; -} - export function ObjectTypeSpreadProperty(props: { ...$ReadOnly, +parent?: ESNode, diff --git a/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types.js b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types.js index 74b3967d479..81beeb55c53 100644 --- a/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types.js +++ b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types.js @@ -14,508 +14,10 @@ The list of exported functions here must be kept in sync with the `NODES_WITH_SP list in `scripts/genTransformNodeTypes` to ensure there's no duplicates */ -import type { - ArrowFunctionExpression as ArrowFunctionExpressionType, - BigIntLiteral as BigIntLiteralType, - BlockComment as BlockCommentType, - BooleanLiteral as BooleanLiteralType, - ClassDeclaration as ClassDeclarationType, - DestructuringObjectProperty as DestructuringObjectPropertyType, - DestructuringObjectPropertyWithComputedName as DestructuringObjectPropertyWithComputedNameType, - DestructuringObjectPropertyWithNonShorthandStaticName as DestructuringObjectPropertyWithNonShorthandStaticNameType, - DestructuringObjectPropertyWithShorthandStaticName as DestructuringObjectPropertyWithShorthandStaticNameType, - ESNode, - Identifier as IdentifierType, - Token as TokenType, - Comment as CommentType, - LineComment as LineCommentType, - NullLiteral as NullLiteralType, - NumericLiteral as NumericLiteralType, - ObjectProperty as ObjectPropertyType, - ObjectPropertyWithComputedName as ObjectPropertyWithComputedNameType, - ObjectPropertyWithNonShorthandStaticName as ObjectPropertyWithNonShorthandStaticNameType, - ObjectPropertyWithShorthandStaticName as ObjectPropertyWithShorthandStaticNameType, - RegExpLiteral as RegExpLiteralType, - StringLiteral as StringLiteralType, - TemplateElement as TemplateElementType, - Program as ProgramType, - DocblockMetadata as DocblockMetadataType, -} from 'hermes-estree'; -import type {DetachedNode, MaybeDetachedNode} from '../detachedNode'; - -import { - asDetachedNode, - detachedProps, - setParentPointersInDirectChildren, -} from '../detachedNode'; - -// hermes adds an `id` prop which is always null, and it adds an `expression` -// boolean which is true when the body isn't a BlockStatement. -// No need to make consumers set these -export type ArrowFunctionExpressionProps = { - +params: $ReadOnlyArray< - MaybeDetachedNode, - >, - +body: MaybeDetachedNode, - +typeParameters?: ?MaybeDetachedNode< - ArrowFunctionExpressionType['typeParameters'], - >, - +returnType?: ?MaybeDetachedNode, - +predicate?: ?MaybeDetachedNode, - +async: ArrowFunctionExpressionType['async'], -}; -export function ArrowFunctionExpression(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const node = detachedProps(props.parent, { - type: 'ArrowFunctionExpression', - id: null, - // $FlowExpectedError[incompatible-use] - expression: props.body.type !== 'BlockStatement', - params: props.params.map(n => asDetachedNode(n)), - body: asDetachedNode(props.body), - typeParameters: asDetachedNode(props.typeParameters), - returnType: asDetachedNode(props.returnType), - predicate: asDetachedNode(props.predicate), - async: props.async, - }); - setParentPointersInDirectChildren(node); - return node; -} - -export type ClassDeclarationProps = { - +id?: ?MaybeDetachedNode, - +typeParameters?: ?MaybeDetachedNode, - +superClass?: ?MaybeDetachedNode, - +superTypeParameters?: ?MaybeDetachedNode< - ClassDeclarationType['superTypeParameters'], - >, - // make this optional as it's rarer that people would want to include them - +implements?: $ReadOnlyArray< - MaybeDetachedNode, - >, - // make this optional as it's rarer that people would want to include them - +decorators?: $ReadOnlyArray< - MaybeDetachedNode, - >, - +body: MaybeDetachedNode, -}; -export function ClassDeclaration(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const node = detachedProps(props.parent, { - type: 'ClassDeclaration', - id: asDetachedNode(props.id), - typeParameters: asDetachedNode(props.typeParameters), - superClass: asDetachedNode(props.superClass), - superTypeParameters: asDetachedNode(props.superTypeParameters), - decorators: (props.decorators ?? []).map(n => asDetachedNode(n)), - implements: (props.implements ?? []).map(n => asDetachedNode(n)), - body: asDetachedNode(props.body), - }); - setParentPointersInDirectChildren(node); - return node; -} - -// pattern/flags are on a subobject in the estree spec, but are flat on the hermes types -// also the value is supposed to be a RegExp instance -export type RegExpLiteralProps = { - +pattern: RegExpLiteralType['regex']['pattern'], - +flags: RegExpLiteralType['regex']['flags'], -}; -export function RegExpLiteral(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const value = new RegExp(props.pattern, props.flags); - return detachedProps(props.parent, { - type: 'Literal', - value, - raw: value.toString(), - regex: { - pattern: props.pattern, - flags: props.flags, - }, - }); -} - -// raw/cooked are on a subobject in the estree spec, but are flat on the hermes types -export type TemplateElementProps = { - +tail: TemplateElementType['tail'], - +cooked: TemplateElementType['value']['cooked'], - +raw: TemplateElementType['value']['raw'], -}; -export function TemplateElement(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps(props.parent, { - type: 'TemplateElement', - tail: props.tail, - value: { - cooked: props.cooked, - raw: props.raw, - }, - }); -} - -// Identifier has a bunch of stuff that usually you don't want to provide - so we have -// this manual def to allow us to default some values -export type IdentifierProps = { - +name: IdentifierType['name'], - +typeAnnotation?: ?MaybeDetachedNode, - +optional?: IdentifierType['optional'], -}; -export function Identifier(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const node = detachedProps(props.parent, { - type: 'Identifier', - name: props.name, - optional: props.optional ?? false, - typeAnnotation: asDetachedNode(props.typeAnnotation), - }); - setParentPointersInDirectChildren(node); - return node; -} - -// -// Literals require a "raw" which is added by the estree transform, not hermes. -// - -export type BigIntLiteralProps = { - +value: $FlowFixMe /* bigint | null */, - /** - * Only set this if you want to use a source-code representation like 1_1n, etc. - * By default "raw" will just be the exact number you've given. - */ - +raw?: NumericLiteralType['raw'], -}; -export function BigIntLiteral(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const node = detachedProps(props.parent, { - type: 'Literal', - value: props.value, - raw: props.raw ?? `${props.value}n`, - bigint: `${props.value}`, - }); - setParentPointersInDirectChildren(node); - return node; -} - -export type BooleanLiteralProps = { - +value: BooleanLiteralType['value'], -}; -export function BooleanLiteral(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps(props.parent, { - type: 'Literal', - raw: props.value ? 'true' : 'false', - value: props.value, - }); -} - -export type NumericLiteralProps = { - +value: NumericLiteralType['value'], - /** - * Only set this if you want to use a source-code representation like 1e100, 0x11, 1_1, etc. - * By default "raw" will just be the exact number you've given. - */ - +raw?: NumericLiteralType['raw'], -}; -export function NumericLiteral(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps(props.parent, { - type: 'Literal', - value: props.value, - raw: props.raw ?? `${props.value}`, - }); -} - -export type NullLiteralProps = {}; -export function NullLiteral( - props: { - +parent?: ESNode, - } = {...null}, -): DetachedNode { - return detachedProps(props.parent, { - type: 'Literal', - value: null, - raw: 'null', - }); -} - -export type StringLiteralProps = { - +value: StringLiteralType['value'], - +raw?: StringLiteralType['raw'], -}; -export function StringLiteral(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - const hasSingleQuote = props.value.includes('"'); - const hasDoubleQuote = props.value.includes("'"); - let raw = props.raw; - if (raw == null) { - if (hasSingleQuote && hasDoubleQuote) { - raw = `'${props.value.replace(/'/g, "\\'")}'`; - } else if (hasSingleQuote) { - raw = `"${props.value}"`; - } else { - raw = `'${props.value}'`; - } - } - return detachedProps(props.parent, { - type: 'Literal', - raw, - value: props.value, - }); -} - -export type LineCommentProps = {+value: string}; -export function LineComment(props: LineCommentProps): LineCommentType { - // $FlowExpectedError[prop-missing] - // $FlowExpectedError[incompatible-return] - return detachedProps(undefined, { - type: 'Line', - value: props.value, - }); -} - -export type BlockCommentProps = {+value: string}; -export function BlockComment(props: BlockCommentProps): BlockCommentType { - // $FlowExpectedError[prop-missing] - // $FlowExpectedError[incompatible-return] - return detachedProps(undefined, { - type: 'Block', - value: props.value, - }); -} - -export type DestructuringObjectPropertyProps = { - +key: MaybeDetachedNode, - +value: MaybeDetachedNode, - +computed: DestructuringObjectPropertyType['computed'], - +shorthand: DestructuringObjectPropertyType['shorthand'], -}; -export function DestructuringObjectProperty(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps(props.parent, { - type: 'Property', - kind: 'init', - method: false, - key: asDetachedNode(props.key), - value: asDetachedNode(props.value), - computed: props.computed, - shorthand: props.shorthand, - }); -} - -export type DestructuringObjectPropertyWithNonShorthandStaticNameProps = { - +key: MaybeDetachedNode< - DestructuringObjectPropertyWithNonShorthandStaticNameType['key'], - >, - +value: MaybeDetachedNode< - DestructuringObjectPropertyWithNonShorthandStaticNameType['value'], - >, -}; -export function DestructuringObjectPropertyWithNonShorthandStaticName(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps( - props.parent, - { - type: 'Property', - kind: 'init', - method: false, - key: asDetachedNode(props.key), - value: asDetachedNode(props.value), - computed: false, - shorthand: false, - }, - ); -} - -export type DestructuringObjectPropertyWithShorthandStaticNameProps = { - +key: MaybeDetachedNode< - DestructuringObjectPropertyWithShorthandStaticNameType['key'], - >, - +value: MaybeDetachedNode< - DestructuringObjectPropertyWithShorthandStaticNameType['value'], - >, -}; -export function DestructuringObjectPropertyWithShorthandStaticName(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps( - props.parent, - { - type: 'Property', - kind: 'init', - method: false, - key: asDetachedNode(props.key), - value: asDetachedNode(props.value), - computed: false, - shorthand: true, - }, - ); -} - -export type DestructuringObjectPropertyWithComputedNameProps = { - +key: MaybeDetachedNode< - DestructuringObjectPropertyWithComputedNameType['key'], - >, - +value: MaybeDetachedNode< - DestructuringObjectPropertyWithComputedNameType['value'], - >, -}; -export function DestructuringObjectPropertyWithComputedName(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps( - props.parent, - { - type: 'Property', - kind: 'init', - method: false, - key: asDetachedNode(props.key), - value: asDetachedNode(props.value), - computed: true, - shorthand: false, - }, - ); -} - -export type ObjectPropertyProps = { - +key: MaybeDetachedNode, - +value: MaybeDetachedNode, - +kind: ObjectPropertyType['kind'], - +computed: ObjectPropertyType['computed'], - +method: ObjectPropertyType['method'], - +shorthand: ObjectPropertyType['shorthand'], -}; -export function ObjectProperty(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps(props.parent, { - type: 'Property', - key: asDetachedNode(props.key), - kind: props.kind, - value: asDetachedNode(props.value), - computed: props.computed, - method: props.method, - shorthand: props.shorthand, - }); -} - -export type ObjectPropertyWithNonShorthandStaticNameProps = { - +key: MaybeDetachedNode, - +value: MaybeDetachedNode< - ObjectPropertyWithNonShorthandStaticNameType['value'], - >, - +kind: ObjectPropertyWithNonShorthandStaticNameType['kind'], - +method: ObjectPropertyWithNonShorthandStaticNameType['method'], -}; -export function ObjectPropertyWithNonShorthandStaticName(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps( - props.parent, - { - type: 'Property', - key: asDetachedNode(props.key), - kind: props.kind, - value: asDetachedNode(props.value), - computed: false, - method: props.method, - shorthand: false, - }, - ); -} - -export type ObjectPropertyWithShorthandStaticNameProps = { - +key: MaybeDetachedNode, - +value: MaybeDetachedNode, -}; -export function ObjectPropertyWithShorthandStaticName(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps( - props.parent, - { - type: 'Property', - key: asDetachedNode(props.key), - kind: 'init', - value: asDetachedNode(props.value), - computed: false, - method: false, - shorthand: true, - }, - ); -} - -export type ObjectPropertyWithComputedNameProps = { - +key: MaybeDetachedNode, - +value: MaybeDetachedNode, - +kind: ObjectPropertyWithComputedNameType['kind'], - +method: ObjectPropertyWithComputedNameType['method'], -}; -export function ObjectPropertyWithComputedName(props: { - ...$ReadOnly, - +parent?: ESNode, -}): DetachedNode { - return detachedProps(props.parent, { - type: 'Property', - key: asDetachedNode(props.key), - kind: props.kind, - value: asDetachedNode(props.value), - computed: true, - method: props.method, - shorthand: false, - }); -} - -export type ProgramProps = { - +sourceType: ProgramType['sourceType'], - +body: $ReadOnlyArray>, - +tokens: $ReadOnlyArray>, - +comments: $ReadOnlyArray>, - +interpreter: null | string, - +docblock: null | DocblockMetadataType, -}; -export function Program(props: { - ...$ReadOnly, -}): DetachedNode { - return detachedProps(null, { - type: 'Program', - sourceType: props.sourceType, - body: props.body.map(n => asDetachedNode(n)), - tokens: props.tokens, - comments: props.comments, - interpreter: - props.interpreter != null - ? asDetachedNode({ - type: 'InterpreterDirective', - value: props.interpreter, - }) - : null, - docblock: props.docblock, - }); -} +export * from './special-case-node-types/Comment'; +export * from './special-case-node-types/DeclareExportDeclaration'; +export * from './special-case-node-types/ExportNamedDeclaration'; +export * from './special-case-node-types/Literal'; +export * from './special-case-node-types/ObjectTypeProperty'; +export * from './special-case-node-types/misc'; +export * from './special-case-node-types/Property'; diff --git a/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/Comment.js b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/Comment.js new file mode 100644 index 00000000000..e6905d39b9e --- /dev/null +++ b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/Comment.js @@ -0,0 +1,36 @@ +/** + * 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-local + * @format + */ + +import type { + BlockComment as BlockCommentType, + LineComment as LineCommentType, +} from 'hermes-estree'; + +import {detachedProps} from '../../detachedNode'; + +export type LineCommentProps = {+value: string}; +export function LineComment(props: LineCommentProps): LineCommentType { + // $FlowExpectedError[prop-missing] + // $FlowExpectedError[incompatible-return] + return detachedProps(undefined, { + type: 'Line', + value: props.value, + }); +} + +export type BlockCommentProps = {+value: string}; +export function BlockComment(props: BlockCommentProps): BlockCommentType { + // $FlowExpectedError[prop-missing] + // $FlowExpectedError[incompatible-return] + return detachedProps(undefined, { + type: 'Block', + value: props.value, + }); +} diff --git a/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/DeclareExportDeclaration.js b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/DeclareExportDeclaration.js new file mode 100644 index 00000000000..8703b2411d3 --- /dev/null +++ b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/DeclareExportDeclaration.js @@ -0,0 +1,97 @@ +/** + * 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-local + * @format + */ + +import type { + DeclareExportDefaultDeclaration as DeclareExportDefaultDeclarationType, + ESNode, + DeclareExportDeclarationNamedWithDeclaration as DeclareExportDeclarationNamedWithDeclarationType, + DeclareExportDeclarationNamedWithSpecifiers as DeclareExportDeclarationNamedWithSpecifiersType, +} from 'hermes-estree'; +import type {DetachedNode, MaybeDetachedNode} from '../../detachedNode'; + +import { + asDetachedNode, + detachedProps, + setParentPointersInDirectChildren, +} from '../../detachedNode'; + +export type DeclareExportDefaultDeclarationProps = { + +declaration?: ?MaybeDetachedNode< + DeclareExportDefaultDeclarationType['declaration'], + >, +}; +export function DeclareExportDefaultDeclaration(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps( + props.parent, + { + type: 'DeclareExportDeclaration', + declaration: asDetachedNode(props.declaration), + specifiers: [], + source: null, + default: true, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} + +export type DeclareExportDeclarationNamedWithDeclarationProps = { + +declaration?: ?MaybeDetachedNode< + DeclareExportDeclarationNamedWithDeclarationType['declaration'], + >, +}; +export function DeclareExportDeclarationNamedWithDeclaration(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps( + props.parent, + { + type: 'DeclareExportDeclaration', + declaration: asDetachedNode(props.declaration), + specifiers: [], + source: null, + default: false, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} + +export type DeclareExportDeclarationNamedWithSpecifiersProps = { + +specifiers: $ReadOnlyArray< + MaybeDetachedNode< + DeclareExportDeclarationNamedWithSpecifiersType['specifiers'][number], + >, + >, + +source?: ?MaybeDetachedNode< + DeclareExportDeclarationNamedWithSpecifiersType['source'], + >, +}; +export function DeclareExportDeclarationNamedWithSpecifiers(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps( + props.parent, + { + type: 'DeclareExportDeclaration', + declaration: null, + specifiers: props.specifiers.map(n => asDetachedNode(n)), + source: asDetachedNode(props.source), + default: false, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} diff --git a/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/ExportNamedDeclaration.js b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/ExportNamedDeclaration.js new file mode 100644 index 00000000000..0c35fb44f96 --- /dev/null +++ b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/ExportNamedDeclaration.js @@ -0,0 +1,75 @@ +/** + * 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-local + * @format + */ + +import type { + ESNode, + ExportNamedDeclarationWithDeclaration as ExportNamedDeclarationWithDeclarationType, + ExportNamedDeclarationWithSpecifiers as ExportNamedDeclarationWithSpecifiersType, +} from 'hermes-estree'; +import type {DetachedNode, MaybeDetachedNode} from '../../detachedNode'; + +import { + asDetachedNode, + detachedProps, + setParentPointersInDirectChildren, +} from '../../detachedNode'; + +export type ExportNamedDeclarationWithDeclarationProps = { + +declaration?: ?MaybeDetachedNode< + ExportNamedDeclarationWithDeclarationType['declaration'], + >, + +exportKind: ExportNamedDeclarationWithDeclarationType['exportKind'], +}; +export function ExportNamedDeclarationWithDeclaration(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps( + props.parent, + { + type: 'ExportNamedDeclaration', + declaration: asDetachedNode(props.declaration), + specifiers: [], + source: null, + exportKind: props.exportKind, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} + +export type ExportNamedDeclarationWithSpecifiersProps = { + +specifiers: $ReadOnlyArray< + MaybeDetachedNode< + ExportNamedDeclarationWithSpecifiersType['specifiers'][number], + >, + >, + +source?: ?MaybeDetachedNode< + ExportNamedDeclarationWithSpecifiersType['source'], + >, + +exportKind: ExportNamedDeclarationWithSpecifiersType['exportKind'], +}; +export function ExportNamedDeclarationWithSpecifiers(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps( + props.parent, + { + type: 'ExportNamedDeclaration', + declaration: null, + specifiers: props.specifiers.map(n => asDetachedNode(n)), + source: asDetachedNode(props.source), + exportKind: props.exportKind, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} diff --git a/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/Literal.js b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/Literal.js new file mode 100644 index 00000000000..03179e091dd --- /dev/null +++ b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/Literal.js @@ -0,0 +1,139 @@ +/** + * 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-local + * @format + */ + +import type { + BigIntLiteral as BigIntLiteralType, + BooleanLiteral as BooleanLiteralType, + ESNode, + NullLiteral as NullLiteralType, + NumericLiteral as NumericLiteralType, + RegExpLiteral as RegExpLiteralType, + StringLiteral as StringLiteralType, +} from 'hermes-estree'; +import type {DetachedNode} from '../../detachedNode'; + +import {detachedProps} from '../../detachedNode'; + +// Literals require a "raw" which is added by the estree transform, not hermes. + +export type BigIntLiteralProps = { + +value: $FlowFixMe /* bigint | null */, + /** + * Only set this if you want to use a source-code representation like 1_1n, etc. + * By default "raw" will just be the exact number you've given. + */ + +raw?: NumericLiteralType['raw'], +}; +export function BigIntLiteral(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + return detachedProps(props.parent, { + type: 'Literal', + value: props.value, + raw: props.raw ?? `${props.value}n`, + bigint: `${props.value}`, + }); +} + +export type BooleanLiteralProps = { + +value: BooleanLiteralType['value'], +}; +export function BooleanLiteral(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + return detachedProps(props.parent, { + type: 'Literal', + raw: props.value ? 'true' : 'false', + value: props.value, + }); +} + +export type NumericLiteralProps = { + +value: NumericLiteralType['value'], + /** + * Only set this if you want to use a source-code representation like 1e100, 0x11, 1_1, etc. + * By default "raw" will just be the exact number you've given. + */ + +raw?: NumericLiteralType['raw'], +}; +export function NumericLiteral(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + return detachedProps(props.parent, { + type: 'Literal', + value: props.value, + raw: props.raw ?? `${props.value}`, + }); +} + +export type NullLiteralProps = {}; +export function NullLiteral( + props: { + +parent?: ESNode, + } = {...null}, +): DetachedNode { + return detachedProps(props.parent, { + type: 'Literal', + value: null, + raw: 'null', + }); +} + +// pattern/flags are on a subobject in the estree spec, but are flat on the hermes types +// also the value is supposed to be a RegExp instance +export type RegExpLiteralProps = { + +pattern: RegExpLiteralType['regex']['pattern'], + +flags: RegExpLiteralType['regex']['flags'], +}; +export function RegExpLiteral(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const value = new RegExp(props.pattern, props.flags); + return detachedProps(props.parent, { + type: 'Literal', + value, + raw: value.toString(), + regex: { + pattern: props.pattern, + flags: props.flags, + }, + }); +} + +export type StringLiteralProps = { + +value: StringLiteralType['value'], + +raw?: StringLiteralType['raw'], +}; +export function StringLiteral(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const hasSingleQuote = props.value.includes('"'); + const hasDoubleQuote = props.value.includes("'"); + let raw = props.raw; + if (raw == null) { + if (hasSingleQuote && hasDoubleQuote) { + raw = `'${props.value.replace(/'/g, "\\'")}'`; + } else if (hasSingleQuote) { + raw = `"${props.value}"`; + } else { + raw = `'${props.value}'`; + } + } + return detachedProps(props.parent, { + type: 'Literal', + raw, + value: props.value, + }); +} diff --git a/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/ObjectTypeProperty.js b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/ObjectTypeProperty.js new file mode 100644 index 00000000000..f442eaad8b8 --- /dev/null +++ b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/ObjectTypeProperty.js @@ -0,0 +1,107 @@ +/** + * 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-local + * @format + */ + +import type { + ESNode, + ObjectTypeAccessorSignature as ObjectTypeAccessorSignatureType, + ObjectTypeMethodSignature as ObjectTypeMethodSignatureType, + ObjectTypePropertySignature as ObjectTypePropertySignatureType, +} from 'hermes-estree'; +import type {DetachedNode, MaybeDetachedNode} from '../../detachedNode'; + +import { + asDetachedNode, + detachedProps, + setParentPointersInDirectChildren, +} from '../../detachedNode'; + +export type ObjectTypeMethodSignatureProps = { + +key: MaybeDetachedNode, + +value: MaybeDetachedNode, + + // optional because they only apply to the class decl case + +static?: ObjectTypeMethodSignatureType['static'], + +proto?: ObjectTypeMethodSignatureType['proto'], +}; +export function ObjectTypeMethodSignature(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'ObjectTypeProperty', + key: asDetachedNode(props.key), + kind: 'init', + method: true, + optional: false, + proto: props.proto ?? false, + static: props.static ?? false, + value: asDetachedNode(props.value), + variance: null, + }); + setParentPointersInDirectChildren(node); + return node; +} + +export type ObjectTypePropertySignatureProps = { + +key: MaybeDetachedNode, + +value: MaybeDetachedNode, + +optional: ObjectTypePropertySignatureType['optional'], + +variance?: ?MaybeDetachedNode, + + // optional because they only apply to the class decl case + +static?: ObjectTypeMethodSignatureType['static'], + +proto?: ObjectTypeMethodSignatureType['proto'], +}; +export function ObjectTypePropertySignature(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'ObjectTypeProperty', + key: asDetachedNode(props.key), + kind: 'init', + method: false, + optional: props.optional, + proto: props.proto ?? false, + static: props.static ?? false, + value: asDetachedNode(props.value), + variance: asDetachedNode(props.variance), + }); + setParentPointersInDirectChildren(node); + return node; +} + +export type ObjectTypeAccessorSignatureProps = { + +key: MaybeDetachedNode, + +value: MaybeDetachedNode, + +kind: ObjectTypeAccessorSignatureType['kind'], + + // optional because they only apply to the class decl case + +static?: ObjectTypeMethodSignatureType['static'], + +proto?: ObjectTypeMethodSignatureType['proto'], +}; +export function ObjectTypeAccessorSignature(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'ObjectTypeProperty', + key: asDetachedNode(props.key), + kind: props.kind, + method: false, + optional: false, + proto: props.proto ?? false, + static: props.static ?? false, + value: asDetachedNode(props.value), + variance: null, + }); + setParentPointersInDirectChildren(node); + return node; +} diff --git a/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/Property.js b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/Property.js new file mode 100644 index 00000000000..fae82a5cce0 --- /dev/null +++ b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/Property.js @@ -0,0 +1,237 @@ +/** + * 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-local + * @format + */ + +import type { + DestructuringObjectProperty as DestructuringObjectPropertyType, + DestructuringObjectPropertyWithComputedName as DestructuringObjectPropertyWithComputedNameType, + DestructuringObjectPropertyWithNonShorthandStaticName as DestructuringObjectPropertyWithNonShorthandStaticNameType, + DestructuringObjectPropertyWithShorthandStaticName as DestructuringObjectPropertyWithShorthandStaticNameType, + ESNode, + ObjectProperty as ObjectPropertyType, + ObjectPropertyWithComputedName as ObjectPropertyWithComputedNameType, + ObjectPropertyWithNonShorthandStaticName as ObjectPropertyWithNonShorthandStaticNameType, + ObjectPropertyWithShorthandStaticName as ObjectPropertyWithShorthandStaticNameType, +} from 'hermes-estree'; +import type {DetachedNode, MaybeDetachedNode} from '../../detachedNode'; + +import { + asDetachedNode, + detachedProps, + setParentPointersInDirectChildren, +} from '../../detachedNode'; + +export type DestructuringObjectPropertyProps = { + +key: MaybeDetachedNode, + +value: MaybeDetachedNode, + +computed: DestructuringObjectPropertyType['computed'], + +shorthand: DestructuringObjectPropertyType['shorthand'], +}; +export function DestructuringObjectProperty(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'Property', + kind: 'init', + method: false, + key: asDetachedNode(props.key), + value: asDetachedNode(props.value), + computed: props.computed, + shorthand: props.shorthand, + }); + setParentPointersInDirectChildren(node); + return node; +} + +export type DestructuringObjectPropertyWithNonShorthandStaticNameProps = { + +key: MaybeDetachedNode< + DestructuringObjectPropertyWithNonShorthandStaticNameType['key'], + >, + +value: MaybeDetachedNode< + DestructuringObjectPropertyWithNonShorthandStaticNameType['value'], + >, +}; +export function DestructuringObjectPropertyWithNonShorthandStaticName(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = + detachedProps( + props.parent, + { + type: 'Property', + kind: 'init', + method: false, + key: asDetachedNode(props.key), + value: asDetachedNode(props.value), + computed: false, + shorthand: false, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} + +export type DestructuringObjectPropertyWithShorthandStaticNameProps = { + +key: MaybeDetachedNode< + DestructuringObjectPropertyWithShorthandStaticNameType['key'], + >, + +value: MaybeDetachedNode< + DestructuringObjectPropertyWithShorthandStaticNameType['value'], + >, +}; +export function DestructuringObjectPropertyWithShorthandStaticName(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = + detachedProps( + props.parent, + { + type: 'Property', + kind: 'init', + method: false, + key: asDetachedNode(props.key), + value: asDetachedNode(props.value), + computed: false, + shorthand: true, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} + +export type DestructuringObjectPropertyWithComputedNameProps = { + +key: MaybeDetachedNode< + DestructuringObjectPropertyWithComputedNameType['key'], + >, + +value: MaybeDetachedNode< + DestructuringObjectPropertyWithComputedNameType['value'], + >, +}; +export function DestructuringObjectPropertyWithComputedName(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps( + props.parent, + { + type: 'Property', + kind: 'init', + method: false, + key: asDetachedNode(props.key), + value: asDetachedNode(props.value), + computed: true, + shorthand: false, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} + +export type ObjectPropertyProps = { + +key: MaybeDetachedNode, + +value: MaybeDetachedNode, + +kind: ObjectPropertyType['kind'], + +computed: ObjectPropertyType['computed'], + +method: ObjectPropertyType['method'], + +shorthand: ObjectPropertyType['shorthand'], +}; +export function ObjectProperty(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'Property', + key: asDetachedNode(props.key), + kind: props.kind, + value: asDetachedNode(props.value), + computed: props.computed, + method: props.method, + shorthand: props.shorthand, + }); + setParentPointersInDirectChildren(node); + return node; +} + +export type ObjectPropertyWithNonShorthandStaticNameProps = { + +key: MaybeDetachedNode, + +value: MaybeDetachedNode< + ObjectPropertyWithNonShorthandStaticNameType['value'], + >, + +kind: ObjectPropertyWithNonShorthandStaticNameType['kind'], + +method: ObjectPropertyWithNonShorthandStaticNameType['method'], +}; +export function ObjectPropertyWithNonShorthandStaticName(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps( + props.parent, + { + type: 'Property', + key: asDetachedNode(props.key), + kind: props.kind, + value: asDetachedNode(props.value), + computed: false, + method: props.method, + shorthand: false, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} + +export type ObjectPropertyWithShorthandStaticNameProps = { + +key: MaybeDetachedNode, + +value: MaybeDetachedNode, +}; +export function ObjectPropertyWithShorthandStaticName(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps( + props.parent, + { + type: 'Property', + key: asDetachedNode(props.key), + kind: 'init', + value: asDetachedNode(props.value), + computed: false, + method: false, + shorthand: true, + }, + ); + setParentPointersInDirectChildren(node); + return node; +} + +export type ObjectPropertyWithComputedNameProps = { + +key: MaybeDetachedNode, + +value: MaybeDetachedNode, + +kind: ObjectPropertyWithComputedNameType['kind'], + +method: ObjectPropertyWithComputedNameType['method'], +}; +export function ObjectPropertyWithComputedName(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'Property', + key: asDetachedNode(props.key), + kind: props.kind, + value: asDetachedNode(props.value), + computed: true, + method: props.method, + shorthand: false, + }); + setParentPointersInDirectChildren(node); + return node; +} diff --git a/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/misc.js b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/misc.js new file mode 100644 index 00000000000..0ca3c8bfbad --- /dev/null +++ b/tools/hermes-parser/js/hermes-transform/src/generated/special-case-node-types/misc.js @@ -0,0 +1,203 @@ +/** + * 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-local + * @format + */ + +import type { + ArrowFunctionExpression as ArrowFunctionExpressionType, + ClassDeclaration as ClassDeclarationType, + DeclareFunction as DeclareFunctionType, + ESNode, + FunctionTypeAnnotation as FunctionTypeAnnotationType, + Identifier as IdentifierType, + Token as TokenType, + Comment as CommentType, + TemplateElement as TemplateElementType, + Program as ProgramType, + DocblockMetadata as DocblockMetadataType, +} from 'hermes-estree'; +import type {DetachedNode, MaybeDetachedNode} from '../../detachedNode'; + +import { + asDetachedNode, + detachedProps, + setParentPointersInDirectChildren, +} from '../../detachedNode'; + +/********************************************************************* + * this file should only contain one-off variant node type functions * + * if you are creating multiple variants for the same "type", then * + * put them in their own file to help keep things organised * + *********************************************************************/ + +// hermes adds an `id` prop which is always null, and it adds an `expression` +// boolean which is true when the body isn't a BlockStatement. +// No need to make consumers set these +export type ArrowFunctionExpressionProps = { + +params: $ReadOnlyArray< + MaybeDetachedNode, + >, + +body: MaybeDetachedNode, + +typeParameters?: ?MaybeDetachedNode< + ArrowFunctionExpressionType['typeParameters'], + >, + +returnType?: ?MaybeDetachedNode, + +predicate?: ?MaybeDetachedNode, + +async: ArrowFunctionExpressionType['async'], +}; +export function ArrowFunctionExpression(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'ArrowFunctionExpression', + id: null, + // $FlowExpectedError[incompatible-use] + expression: props.body.type !== 'BlockStatement', + params: props.params.map(n => asDetachedNode(n)), + body: asDetachedNode(props.body), + typeParameters: asDetachedNode(props.typeParameters), + returnType: asDetachedNode(props.returnType), + predicate: asDetachedNode(props.predicate), + async: props.async, + }); + setParentPointersInDirectChildren(node); + return node; +} + +export type ClassDeclarationProps = { + +id?: ?MaybeDetachedNode, + +typeParameters?: ?MaybeDetachedNode, + +superClass?: ?MaybeDetachedNode, + +superTypeParameters?: ?MaybeDetachedNode< + ClassDeclarationType['superTypeParameters'], + >, + // make this optional as it's rarer that people would want to include them + +implements?: $ReadOnlyArray< + MaybeDetachedNode, + >, + // make this optional as it's rarer that people would want to include them + +decorators?: $ReadOnlyArray< + MaybeDetachedNode, + >, + +body: MaybeDetachedNode, +}; +export function ClassDeclaration(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'ClassDeclaration', + id: asDetachedNode(props.id), + typeParameters: asDetachedNode(props.typeParameters), + superClass: asDetachedNode(props.superClass), + superTypeParameters: asDetachedNode(props.superTypeParameters), + decorators: (props.decorators ?? []).map(n => asDetachedNode(n)), + implements: (props.implements ?? []).map(n => asDetachedNode(n)), + body: asDetachedNode(props.body), + }); + setParentPointersInDirectChildren(node); + return node; +} + +// raw/cooked are on a subobject in the estree spec, but are flat on the hermes types +export type TemplateElementProps = { + +tail: TemplateElementType['tail'], + +cooked: TemplateElementType['value']['cooked'], + +raw: TemplateElementType['value']['raw'], +}; +export function TemplateElement(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + return detachedProps(props.parent, { + type: 'TemplateElement', + tail: props.tail, + value: { + cooked: props.cooked, + raw: props.raw, + }, + }); +} + +// Identifier has a bunch of stuff that usually you don't want to provide - so we have +// this manual def to allow us to default some values +export type IdentifierProps = { + +name: IdentifierType['name'], + +typeAnnotation?: ?MaybeDetachedNode, + +optional?: IdentifierType['optional'], +}; +export function Identifier(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'Identifier', + name: props.name, + optional: props.optional ?? false, + typeAnnotation: asDetachedNode(props.typeAnnotation), + }); + setParentPointersInDirectChildren(node); + return node; +} + +export type ProgramProps = { + +sourceType: ProgramType['sourceType'], + +body: $ReadOnlyArray>, + +tokens: $ReadOnlyArray>, + +comments: $ReadOnlyArray>, + +interpreter: null | string, + +docblock: null | DocblockMetadataType, +}; +export function Program(props: { + ...$ReadOnly, +}): DetachedNode { + return detachedProps(null, { + type: 'Program', + sourceType: props.sourceType, + body: props.body.map(n => asDetachedNode(n)), + tokens: props.tokens, + comments: props.comments, + interpreter: + props.interpreter != null + ? asDetachedNode({ + type: 'InterpreterDirective', + value: props.interpreter, + }) + : null, + docblock: props.docblock, + }); +} + +// the type annotation is stored on the Identifier's typeAnnotation +// which is super awkward to work with and type - so we flatten the input +// and put it in the right spot after +export type DeclareFunctionProps = { + +name: string, + +functionType: MaybeDetachedNode, + +predicate?: ?MaybeDetachedNode, +}; +export function DeclareFunction(props: { + ...$ReadOnly, + +parent?: ESNode, +}): DetachedNode { + const node = detachedProps(props.parent, { + type: 'DeclareFunction', + id: detachedProps(null, { + type: 'Identifier', + name: props.name, + typeAnnotation: detachedProps(null, { + type: 'TypeAnnotation', + typeAnnotation: asDetachedNode(props.functionType), + }), + }), + predicate: asDetachedNode(props.predicate), + }); + setParentPointersInDirectChildren(node); + return node; +} diff --git a/tools/hermes-parser/js/hermes-transform/src/transform/print.js b/tools/hermes-parser/js/hermes-transform/src/transform/print.js index ecf56a9ef47..26037481fe3 100644 --- a/tools/hermes-parser/js/hermes-transform/src/transform/print.js +++ b/tools/hermes-parser/js/hermes-transform/src/transform/print.js @@ -67,7 +67,7 @@ export function print( // position. if (node.type === 'ObjectTypeProperty') { if ( - !node.method && + node.method === false && node.kind === 'init' && node.range[0] === 1 && node.value.range[0] === 1 diff --git a/tools/hermes-parser/js/hermes-translate/src/flowToFlowDef.js b/tools/hermes-parser/js/hermes-translate/src/flowToFlowDef.js index 7617fd5f107..3c23255deb1 100644 --- a/tools/hermes-parser/js/hermes-translate/src/flowToFlowDef.js +++ b/tools/hermes-parser/js/hermes-translate/src/flowToFlowDef.js @@ -44,6 +44,7 @@ import type { TypeAnnotationType, TypeCastExpression, TypeParameterDeclaration, + TypeParameterInstantiation, VariableDeclaration, } from 'hermes-estree'; import type {ScopeManager} from 'hermes-eslint'; @@ -415,20 +416,64 @@ function convertObjectExpression( context, ); } + + if (prop.method === true) { + if ( + prop.value.type !== 'ArrowFunctionExpression' && + prop.value.type !== 'FunctionExpression' + ) { + throw translationError( + prop.key, + `ObjectExpression Property: Expected method to have a function value, but got ${prop.value.type}`, + context, + ); + } + + const [resultExpr, deps] = convertAFunction(prop.value, context); + return [ + t.ObjectTypeMethodSignature({ + key: asDetachedNode(prop.key), + value: resultExpr, + }), + deps, + ]; + } + + if (prop.kind === 'get' || prop.kind === 'set') { + if ( + prop.value.type !== 'ArrowFunctionExpression' && + prop.value.type !== 'FunctionExpression' + ) { + throw translationError( + prop.key, + `ObjectExpression Property: Expected accessor to have a function value, but got ${prop.value.type}`, + context, + ); + } + + const kind = prop.kind; + const [resultExpr, deps] = convertAFunction(prop.value, context); + return [ + t.ObjectTypeAccessorSignature({ + key: asDetachedNode(prop.key), + kind, + value: resultExpr, + }), + deps, + ]; + } + const [resultExpr, deps] = convertExpressionToTypeAnnotation( prop.value, context, ); + return [ - t.ObjectTypeProperty({ + t.ObjectTypePropertySignature({ key: asDetachedNode(prop.key), value: resultExpr, - method: prop.method, optional: false, - static: false, - proto: false, variance: null, - kind: prop.kind, }), deps, ]; @@ -504,46 +549,60 @@ function convertExportDeclaration( case 'FunctionDeclaration': { const [declDecl, deps] = convertFunctionDeclation(decl, context); return [ - t.DeclareExportDeclaration({ - specifiers: [], - declaration: declDecl, - default: opts.default, - source: null, - }), + opts.default + ? t.DeclareExportDefaultDeclaration({ + declaration: declDecl, + }) + : t.DeclareExportDeclarationNamedWithDeclaration({ + declaration: declDecl, + }), deps, ]; } case 'ClassDeclaration': { const [declDecl, deps] = convertClassDeclaration(decl, context); return [ - t.DeclareExportDeclaration({ - specifiers: [], - declaration: declDecl, - default: opts.default, - source: null, - }), + opts.default + ? t.DeclareExportDefaultDeclaration({ + declaration: declDecl, + }) + : t.DeclareExportDeclarationNamedWithDeclaration({ + declaration: declDecl, + }), deps, ]; } case 'InterfaceDeclaration': { + if (opts.default) { + throw translationError( + decl, + 'ExportDeclaration: Default interface found, invalid AST.', + context, + ); + } + const [declDecl, deps] = convertInterfaceDeclaration(decl, context); return [ - t.ExportNamedDeclaration({ + t.ExportNamedDeclarationWithDeclaration({ exportKind: 'type', - source: null, - specifiers: [], declaration: declDecl, }), deps, ]; } case 'TypeAlias': { + if (opts.default) { + throw translationError( + decl, + 'ExportDeclaration: Default type alias found, invalid AST.', + context, + ); + } + const [declDecl, deps] = convertTypeAlias(decl, context); return [ - t.ExportNamedDeclaration({ + t.ExportNamedDeclarationWithDeclaration({ exportKind: 'type', - source: null, - specifiers: [], declaration: declDecl, }), deps, @@ -559,11 +618,8 @@ function convertExportDeclaration( } const [declDecl, deps] = convertOpaqueType(decl, context); return [ - t.DeclareExportDeclaration({ - specifiers: [], + t.DeclareExportDeclarationNamedWithDeclaration({ declaration: declDecl, - default: false, - source: null, }), deps, ]; @@ -578,21 +634,16 @@ function convertExportDeclaration( } const [declDecl, deps] = convertVariableDeclaration(decl, context); return [ - t.DeclareExportDeclaration({ - specifiers: [], + t.DeclareExportDeclarationNamedWithDeclaration({ declaration: declDecl, - default: false, - source: null, }), deps, ]; } case 'EnumDeclaration': { return [ - t.ExportNamedDeclaration({ + t.ExportNamedDeclarationWithDeclaration({ exportKind: 'value', - source: null, - specifiers: [], declaration: asDetachedNode(decl), }), [], @@ -612,11 +663,8 @@ function convertExportDeclaration( context, ); return [ - t.DeclareExportDeclaration({ - specifiers: [], + t.DeclareExportDefaultDeclaration({ declaration: declDecl, - default: true, - source: null, }), deps, ]; @@ -654,11 +702,10 @@ function convertExportNamedDeclaration( analyzeTypeDependencies(local, context), ); return [ - t.ExportNamedDeclaration({ + t.ExportNamedDeclarationWithSpecifiers({ exportKind: stmt.exportKind, source: asDetachedNode(stmt.source), specifiers: resultSpecfiers, - declaration: null, }), specifiersDeps, ]; @@ -791,7 +838,7 @@ function convertClassDeclaration( function convertSuperClass( superClass: ?Expression, - superTypeParameters: ?TypeParameterDeclaration, + superTypeParameters: ?TypeParameterInstantiation, context: TranslationContext, ): TranslatedResultOrNull { if (superClass == null) { @@ -806,7 +853,7 @@ function convertSuperClass( ); } const [resultTypeParams, typeParamsDeps] = - convertTypeParameterDeclarationOrNull(superTypeParameters, context); + convertTypeParameterInstantiationOrNull(superTypeParameters, context); const superDeps = analyzeTypeDependencies(superClass, context); return [ t.InterfaceExtends({ @@ -866,15 +913,12 @@ function convertClassMember( ); return [ - t.ObjectTypeProperty({ + t.ObjectTypePropertySignature({ key: asDetachedNode(member.key), value: resultTypeAnnotation, - method: false, optional: member.optional, static: member.static, - proto: false, variance: member.variance, - kind: 'init', }), deps, ]; @@ -897,16 +941,25 @@ function convertClassMember( const [resultValue, deps] = convertAFunction(member.value, context); + if (member.kind === 'get' || member.kind === 'set') { + // accessors are methods - but flow accessor signatures are properties + const kind = member.kind; + return [ + t.ObjectTypeAccessorSignature({ + key: asDetachedNode(member.key), + value: resultValue, + static: member.static, + kind, + }), + deps, + ]; + } + return [ - t.ObjectTypeProperty({ + t.ObjectTypeMethodSignature({ key: asDetachedNode(member.key), value: resultValue, - method: true, - optional: false, static: member.static, - proto: false, - variance: null, - kind: 'init', }), deps, ]; @@ -958,12 +1011,8 @@ function convertFunctionDeclation( return [ t.DeclareFunction({ - id: t.Identifier({ - name: id.name, - typeAnnotation: t.TypeAnnotation({ - typeAnnotation: resultFunc, - }), - }), + name: id.name, + functionType: resultFunc, predicate: resultPredicate, }), [...funcDeps, ...predicateDeps], @@ -1169,3 +1218,12 @@ function convertTypeParameterDeclarationOrNull( } return [asDetachedNode(decl), analyzeTypeDependencies(decl, context)]; } +function convertTypeParameterInstantiationOrNull( + inst: ?TypeParameterInstantiation, + context: TranslationContext, +): TranslatedResultOrNull { + if (inst == null) { + return EMPTY_TRANSLATION_RESULT; + } + return [asDetachedNode(inst), analyzeTypeDependencies(inst, context)]; +} diff --git a/tools/hermes-parser/js/scripts/genTransformNodeTypes.js b/tools/hermes-parser/js/scripts/genTransformNodeTypes.js index 598d1f63221..f16037e6801 100644 --- a/tools/hermes-parser/js/scripts/genTransformNodeTypes.js +++ b/tools/hermes-parser/js/scripts/genTransformNodeTypes.js @@ -25,13 +25,17 @@ const NODES_WITH_SPECIAL_HANDLING = new Set([ 'BigIntLiteral', 'BooleanLiteral', 'ClassDeclaration', + 'DeclareExportDeclaration', + 'DeclareFunction', + 'ExportNamedDeclaration', 'Identifier', 'NullLiteral', 'NumericLiteral', + 'ObjectTypeProperty', + 'Program', 'RegExpLiteral', 'StringLiteral', 'TemplateElement', - 'Program', ]); for (const node of GetHermesESTreeJSON()) {