Skip to content

Commit

Permalink
add support for const type parameter
Browse files Browse the repository at this point in the history
Summary:
Adds support for [`const` modifier on type parameters](microsoft/TypeScript#51865). E.g.
```
function foo<const T>(x: T): [T] {...}
```
We parse an optional `const` keyword right before parsing the variance of a type parameter.

```
cd ~/fbsource/xplat/hermes/unsupported/tools/rustgen
buck run //xplat/hermes/unsupported/tools/rustgen:rustgen -- ffi > ../../juno/crates/hermes/src/parser/generated_ffi.rs
buck run //xplat/hermes/unsupported/tools/rustgen:rustgen -- cvt > ../../juno/crates/juno/src/hparser/generated_cvt.rs
```

Reviewed By: avp

Differential Revision: D66739150

fbshipit-source-id: 66411ee424cea3ab19a1f8c2ab09d80abdf2737a
  • Loading branch information
panagosg7 authored and facebook-github-bot committed Dec 18, 2024
1 parent 468be6b commit 3a24531
Show file tree
Hide file tree
Showing 8 changed files with 123 additions and 5 deletions.
4 changes: 3 additions & 1 deletion include/hermes/AST/ESTree.def
Original file line number Diff line number Diff line change
Expand Up @@ -1109,14 +1109,16 @@ ESTREE_NODE_1_ARGS(
ESTREE_NODE_1_ARGS(
TypeParameterDeclaration, Flow,
NodeList, params, false)
ESTREE_NODE_5_ARGS(
ESTREE_NODE_6_ARGS(
TypeParameter, Flow,
NodeLabel, name, false,
NodeBoolean, const, false,
NodePtr, bound, true,
NodePtr, variance, true,
NodePtr, default, true,
NodeBoolean, usesExtendsBound, false)
ESTREE_IGNORE_IF_EMPTY(TypeParameter, usesExtendsBound)
ESTREE_IGNORE_IF_EMPTY(TypeParameter, const)
ESTREE_NODE_1_ARGS(
TypeParameterInstantiation, Flow,
NodeList, params, false)
Expand Down
13 changes: 9 additions & 4 deletions lib/Parser/JSParserImpl-flow.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -2894,7 +2894,7 @@ Optional<ESTree::Node *> JSParserImpl::parsePrimaryTypeAnnotationFlow() {
start,
getPrevTokenEndLoc(),
new (context_) ESTree::TypeParameterNode(
name, bound, nullptr, nullptr, true))));
name, false, bound, nullptr, nullptr, true))));
}

{
Expand Down Expand Up @@ -3938,8 +3938,8 @@ Optional<ESTree::Node *> JSParserImpl::parseTypeMappedTypePropertyFlow(
ESTree::Node *keyTparam = setLocation(
left,
left,
new (context_)
ESTree::TypeParameterNode(id, nullptr, nullptr, nullptr, false));
new (context_) ESTree::TypeParameterNode(
id, false, nullptr, nullptr, nullptr, false));

auto optSourceType = parseTypeAnnotationFlow();
if (!optSourceType)
Expand Down Expand Up @@ -4098,7 +4098,12 @@ Optional<ESTree::Node *> JSParserImpl::parseTypeParamsFlow() {

Optional<ESTree::Node *> JSParserImpl::parseTypeParamFlow() {
SMLoc start = tok_->getStartLoc();
bool isConst = false;
ESTree::Node *variance = nullptr;
if (check(TokenKind::rw_const)) {
isConst = true;
advance(JSLexer::GrammarContext::Type);
}

if (check(TokenKind::plus, TokenKind::minus)) {
variance = setLocation(
Expand Down Expand Up @@ -4149,7 +4154,7 @@ Optional<ESTree::Node *> JSParserImpl::parseTypeParamFlow() {
start,
getPrevTokenEndLoc(),
new (context_) ESTree::TypeParameterNode(
name, bound, variance, initializer, usesExtendsBound));
name, isConst, bound, variance, initializer, usesExtendsBound));
}

Optional<ESTree::Node *> JSParserImpl::parseTypeArgsFlow() {
Expand Down
11 changes: 11 additions & 0 deletions test/Parser/flow/const-type-param-error1.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* 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.
*/

// RUN: (! %hermesc -parse-flow -dump-ast -pretty-json %s 2>&1) | %FileCheck %s --match-full-lines

function foo<const>() {}
// CHECK: {{.*}}:10:19: error: 'identifier' expected in type parameter
11 changes: 11 additions & 0 deletions test/Parser/flow/const-type-param-error2.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* 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.
*/

// RUN: (! %hermesc -parse-flow -dump-ast -pretty-json %s 2>&1) | %FileCheck %s --match-full-lines

function foo<const + const>() {}
// CHECK: {{.*}}:10:22: error: 'identifier' expected in type parameter
75 changes: 75 additions & 0 deletions test/Parser/flow/function-typeparams.js
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,81 @@ function foo<T>(x: number): number {}
// CHECK-NEXT: "async": false
// CHECK-NEXT: },
// CHECK-NEXT: "directive": null
// CHECK-NEXT: },

(function<const T>(): void {});
// CHECK-NEXT: {
// CHECK-NEXT: "type": "ExpressionStatement",
// CHECK-NEXT: "expression": {
// CHECK-NEXT: "type": "FunctionExpression",
// CHECK-NEXT: "id": null,
// CHECK-NEXT: "params": [],
// CHECK-NEXT: "body": {
// CHECK-NEXT: "type": "BlockStatement",
// CHECK-NEXT: "body": []
// CHECK-NEXT: },
// CHECK-NEXT: "typeParameters": {
// CHECK-NEXT: "type": "TypeParameterDeclaration",
// CHECK-NEXT: "params": [
// CHECK-NEXT: {
// CHECK-NEXT: "type": "TypeParameter",
// CHECK-NEXT: "name": "T",
// CHECK-NEXT: "const": true,
// CHECK-NEXT: "bound": null,
// CHECK-NEXT: "variance": null,
// CHECK-NEXT: "default": null
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: "returnType": {
// CHECK-NEXT: "type": "TypeAnnotation",
// CHECK-NEXT: "typeAnnotation": {
// CHECK-NEXT: "type": "VoidTypeAnnotation"
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: "generator": false,
// CHECK-NEXT: "async": false
// CHECK-NEXT: },
// CHECK-NEXT: "directive": null
// CHECK-NEXT: },

(function<const +T>(): void {});
// CHECK-NEXT: {
// CHECK-NEXT: "type": "ExpressionStatement",
// CHECK-NEXT: "expression": {
// CHECK-NEXT: "type": "FunctionExpression",
// CHECK-NEXT: "id": null,
// CHECK-NEXT: "params": [],
// CHECK-NEXT: "body": {
// CHECK-NEXT: "type": "BlockStatement",
// CHECK-NEXT: "body": []
// CHECK-NEXT: },
// CHECK-NEXT: "typeParameters": {
// CHECK-NEXT: "type": "TypeParameterDeclaration",
// CHECK-NEXT: "params": [
// CHECK-NEXT: {
// CHECK-NEXT: "type": "TypeParameter",
// CHECK-NEXT: "name": "T",
// CHECK-NEXT: "const": true,
// CHECK-NEXT: "bound": null,
// CHECK-NEXT: "variance": {
// CHECK-NEXT: "type": "Variance",
// CHECK-NEXT: "kind": "plus"
// CHECK-NEXT: },
// CHECK-NEXT: "default": null
// CHECK-NEXT: }
// CHECK-NEXT: ]
// CHECK-NEXT: },
// CHECK-NEXT: "returnType": {
// CHECK-NEXT: "type": "TypeAnnotation",
// CHECK-NEXT: "typeAnnotation": {
// CHECK-NEXT: "type": "VoidTypeAnnotation"
// CHECK-NEXT: }
// CHECK-NEXT: },
// CHECK-NEXT: "generator": false,
// CHECK-NEXT: "async": false
// CHECK-NEXT: },
// CHECK-NEXT: "directive": null
// CHECK-NEXT: }

// CHECK-NEXT: ]
Expand Down
11 changes: 11 additions & 0 deletions test/Parser/flow/type-param-error-const-name.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
/**
* 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.
*/

// RUN: (! %hermesc -parse-flow -dump-ast -pretty-json %s 2>&1) | %FileCheck %s --match-full-lines

function foo<const>() {}
// CHECK: {{.*}}:10:19: error: 'identifier' expected in type parameter
1 change: 1 addition & 0 deletions unsupported/juno/crates/hermes/src/parser/generated_ffi.rs
Original file line number Diff line number Diff line change
Expand Up @@ -882,6 +882,7 @@ extern "C" {
pub fn hermes_get_TypeParameterDeclaration_params(node: NodePtr) -> NodeListRef;
// TypeParameter
pub fn hermes_get_TypeParameter_name(node: NodePtr) -> NodeLabel;
pub fn hermes_get_TypeParameter_const(node: NodePtr) -> bool;
pub fn hermes_get_TypeParameter_bound(node: NodePtr) -> NodePtrOpt;
pub fn hermes_get_TypeParameter_variance(node: NodePtr) -> NodePtrOpt;
pub fn hermes_get_TypeParameter_default(node: NodePtr) -> NodePtrOpt;
Expand Down
2 changes: 2 additions & 0 deletions unsupported/juno/crates/juno/src/hparser/generated_cvt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2172,13 +2172,15 @@ pub unsafe fn cvt_node_ptr<'parser, 'gc>(
}
NodeKind::TypeParameter => {
let name = cvt.cvt_label(gc, hermes_get_TypeParameter_name(n));
let const = hermes_get_TypeParameter_const(n);
let bound = cvt_node_ptr_opt(cvt, gc, hermes_get_TypeParameter_bound(n));
let variance = cvt_node_ptr_opt(cvt, gc, hermes_get_TypeParameter_variance(n));
let default = cvt_node_ptr_opt(cvt, gc, hermes_get_TypeParameter_default(n));
let uses_extends_bound = hermes_get_TypeParameter_usesExtendsBound(n);
let mut template = ast::template::TypeParameter {
metadata: ast::TemplateMetadata {range, ..Default::default()},
name,
const,
bound,
variance,
default,
Expand Down

0 comments on commit 3a24531

Please sign in to comment.