Skip to content

Commit

Permalink
Add parsing support for Flow Enums of bigints - JS changes
Browse files Browse the repository at this point in the history
Summary: Add parsing support for Flow Enums of bigints - JS changes split out as requested.

Reviewed By: SamChou19815

Differential Revision: D56495696

fbshipit-source-id: 1c695a362a6f4d613a3005320c8476f37fba5805
  • Loading branch information
gkz authored and facebook-github-bot committed Apr 25, 2024
1 parent 1e10ba3 commit 0d57cfe
Show file tree
Hide file tree
Showing 9 changed files with 199 additions and 1 deletion.
12 changes: 12 additions & 0 deletions tools/hermes-parser/js/hermes-estree/src/generated/predicates.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,8 @@ import type {
DoWhileStatement,
EmptyStatement,
EmptyTypeAnnotation,
EnumBigIntBody,
EnumBigIntMember,
EnumBooleanBody,
EnumBooleanMember,
EnumDeclaration,
Expand Down Expand Up @@ -477,6 +479,16 @@ export function isEmptyTypeAnnotation(node /*: ESNode | Token */) /*: node is Em
}


export function isEnumBigIntBody(node /*: ESNode | Token */) /*: node is EnumBigIntBody */ {
return node.type === 'EnumBigIntBody';
}


export function isEnumBigIntMember(node /*: ESNode | Token */) /*: node is EnumBigIntMember */ {
return node.type === 'EnumBigIntMember';
}


export function isEnumBooleanBody(node /*: ESNode | Token */) /*: node is EnumBooleanBody */ {
return node.type === 'EnumBooleanBody';
}
Expand Down
26 changes: 25 additions & 1 deletion tools/hermes-parser/js/hermes-estree/src/types.js
Original file line number Diff line number Diff line change
Expand Up @@ -192,10 +192,12 @@ export type ESNode =
| HookDeclaration
| EnumDeclaration
| EnumNumberBody
| EnumBigIntBody
| EnumStringBody
| EnumStringMember
| EnumDefaultedMember
| EnumNumberMember
| EnumBigIntMember
| EnumBooleanBody
| EnumBooleanMember
| EnumSymbolBody
Expand Down Expand Up @@ -1602,7 +1604,12 @@ export interface TypeParameterInstantiation extends BaseNode {
export interface EnumDeclaration extends BaseNode {
+type: 'EnumDeclaration';
+id: Identifier;
+body: EnumNumberBody | EnumStringBody | EnumBooleanBody | EnumSymbolBody;
+body:
| EnumNumberBody
| EnumBigIntBody
| EnumStringBody
| EnumBooleanBody
| EnumSymbolBody;
}

interface BaseEnumBody extends BaseNode {
Expand All @@ -1629,6 +1636,23 @@ export interface EnumNumberMember extends BaseNode {
+parent: EnumNumberBody;
}

export interface EnumBigIntBody extends BaseInferrableEnumBody {
+type: 'EnumBigIntBody';
// enum bigint members cannot be defaulted
+members: $ReadOnlyArray<EnumBigIntMember>;
+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<EnumStringMember | EnumDefaultedMember>;
Expand Down
89 changes: 89 additions & 0 deletions tools/hermes-parser/js/hermes-parser/__tests__/Enum-test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,89 @@
/**
* 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 {AlignmentCase} from '../__test_utils__/alignment-utils';

import {expectEspreeAlignment} from '../__test_utils__/alignment-utils';
import {parseForSnapshot} from '../__test_utils__/parse';

describe('Enum', () => {
const testCase: AlignmentCase = {
code: `
enum T1 { A = 1n, B = 2n}
`,
espree: {
expectToFail: 'espree-exception',
expectedExceptionMessage: `The keyword 'enum' is reserved`,
},
babel: {
expectToFail: 'babel-exception',
expectedExceptionMessage: 'Unexpected token',
},
};

test('ESTree', () => {
expect(parseForSnapshot(testCase.code)).toMatchInlineSnapshot(`
{
"body": [
{
"body": {
"explicitType": false,
"hasUnknownMembers": false,
"members": [
{
"id": {
"name": "A",
"optional": false,
"type": "Identifier",
"typeAnnotation": null,
},
"init": {
"bigint": "1",
"literalType": "bigint",
"raw": "1n",
"type": "Literal",
"value": 1n,
},
"type": "EnumBigIntMember",
},
{
"id": {
"name": "B",
"optional": false,
"type": "Identifier",
"typeAnnotation": null,
},
"init": {
"bigint": "2",
"literalType": "bigint",
"raw": "2n",
"type": "Literal",
"value": 2n,
},
"type": "EnumBigIntMember",
},
],
"type": "EnumBigIntBody",
},
"id": {
"name": "T1",
"optional": false,
"type": "Identifier",
"typeAnnotation": null,
},
"type": "EnumDeclaration",
},
],
"type": "Program",
}
`);
expectEspreeAlignment(testCase);
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -1512,6 +1512,15 @@ function deserializeEnumNumberBody() {
hasUnknownMembers: this.deserializeBoolean(),
};
}
function deserializeEnumBigIntBody() {
return {
type: 'EnumBigIntBody',
loc: this.addEmptyLoc(),
members: this.deserializeNodeList(),
explicitType: this.deserializeBoolean(),
hasUnknownMembers: this.deserializeBoolean(),
};
}
function deserializeEnumBooleanBody() {
return {
type: 'EnumBooleanBody',
Expand Down Expand Up @@ -1552,6 +1561,14 @@ function deserializeEnumNumberMember() {
init: this.deserializeNode(),
};
}
function deserializeEnumBigIntMember() {
return {
type: 'EnumBigIntMember',
loc: this.addEmptyLoc(),
id: this.deserializeNode(),
init: this.deserializeNode(),
};
}
function deserializeEnumBooleanMember() {
return {
type: 'EnumBooleanMember',
Expand Down Expand Up @@ -2146,11 +2163,13 @@ module.exports = [
deserializeEnumDeclaration,
deserializeEnumStringBody,
deserializeEnumNumberBody,
deserializeEnumBigIntBody,
deserializeEnumBooleanBody,
deserializeEnumSymbolBody,
deserializeEnumDefaultedMember,
deserializeEnumStringMember,
deserializeEnumNumberMember,
deserializeEnumBigIntMember,
deserializeEnumBooleanMember,
deserializeComponentParameter,
deserializeFlowLast,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,6 +113,8 @@ module.exports = {
DoWhileStatement: ['body', 'test'],
EmptyStatement: [],
EmptyTypeAnnotation: [],
EnumBigIntBody: ['members'],
EnumBigIntMember: ['id', 'init'],
EnumBooleanBody: ['members'],
EnumBooleanMember: ['id', 'init'],
EnumDeclaration: ['id', 'body'],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -224,6 +224,13 @@ export const HERMES_AST_VISITOR_KEYS = {
},
EmptyStatement: {},
EmptyTypeAnnotation: {},
EnumBigIntBody: {
members: 'NodeList',
},
EnumBigIntMember: {
id: 'Node',
init: 'Node',
},
EnumBooleanBody: {
members: 'NodeList',
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,8 @@ import type {
DoWhileStatement as DoWhileStatementType,
EmptyStatement as EmptyStatementType,
EmptyTypeAnnotation as EmptyTypeAnnotationType,
EnumBigIntBody as EnumBigIntBodyType,
EnumBigIntMember as EnumBigIntMemberType,
EnumBooleanBody as EnumBooleanBodyType,
EnumBooleanMember as EnumBooleanMemberType,
EnumDeclaration as EnumDeclarationType,
Expand Down Expand Up @@ -453,6 +455,19 @@ export type EmptyStatementProps = {};

export type EmptyTypeAnnotationProps = {};

export type EnumBigIntBodyProps = {
+members: $ReadOnlyArray<
MaybeDetachedNode<EnumBigIntBodyType['members'][number]>,
>,
+explicitType: EnumBigIntBodyType['explicitType'],
+hasUnknownMembers: EnumBigIntBodyType['hasUnknownMembers'],
};

export type EnumBigIntMemberProps = {
+id: MaybeDetachedNode<EnumBigIntMemberType['id']>,
+init: MaybeDetachedNode<EnumBigIntMemberType['init']>,
};

export type EnumBooleanBodyProps = {
+members: $ReadOnlyArray<
MaybeDetachedNode<EnumBooleanBodyType['members'][number]>,
Expand Down Expand Up @@ -1781,6 +1796,33 @@ export function EmptyTypeAnnotation(
});
}

export function EnumBigIntBody(props: {
...EnumBigIntBodyProps,
+parent?: ESNode,
}): DetachedNode<EnumBigIntBodyType> {
const node = detachedProps<EnumBigIntBodyType>((props.parent: $FlowFixMe), {
type: 'EnumBigIntBody',
members: props.members.map(n => asDetachedNodeForCodeGen(n)),
explicitType: props.explicitType,
hasUnknownMembers: props.hasUnknownMembers,
});
setParentPointersInDirectChildren((node: $FlowFixMe));
return node;
}

export function EnumBigIntMember(props: {
...EnumBigIntMemberProps,
+parent?: ESNode,
}): DetachedNode<EnumBigIntMemberType> {
const node = detachedProps<EnumBigIntMemberType>((props.parent: $FlowFixMe), {
type: 'EnumBigIntMember',
id: asDetachedNodeForCodeGen(props.id),
init: asDetachedNodeForCodeGen(props.init),
});
setParentPointersInDirectChildren((node: $FlowFixMe));
return node;
}

export function EnumBooleanBody(props: {
...EnumBooleanBodyProps,
+parent?: ESNode,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@ export function createRemoveNodeMutation(
const VALID_ENUM_MEMBER_PARENTS: $ReadOnlyArray<string> = [
'EnumBooleanBody',
'EnumNumberBody',
'EnumBigIntBody',
'EnumStringBody',
'EnumSymbolBody',
];
Expand Down
2 changes: 2 additions & 0 deletions tools/hermes-parser/js/scripts/utils/aliases.js
Original file line number Diff line number Diff line change
Expand Up @@ -257,10 +257,12 @@ export default ({
EnumDeclaration: ['Statement', 'Declaration'],
EnumBooleanBody: ['EnumBody'],
EnumNumberBody: ['EnumBody'],
EnumBigIntBody: ['EnumBody'],
EnumStringBody: ['EnumBody'],
EnumSymbolBody: ['EnumBody'],
EnumBooleanMember: ['EnumMember'],
EnumNumberMember: ['EnumMember'],
EnumBigIntMember: ['EnumMember'],
EnumStringMember: ['EnumMember'],
EnumDefaultedMember: ['EnumMember'],
IndexedAccessType: ['Flow', 'FlowType'],
Expand Down

0 comments on commit 0d57cfe

Please sign in to comment.