Coverage Report

Created: 2025-01-28 06:38

/src/hermes/lib/Parser/JSParserImpl-flow.cpp
Line
Count
Source (jump to first uncovered line)
1
/*
2
 * Copyright (c) Meta Platforms, Inc. and affiliates.
3
 *
4
 * This source code is licensed under the MIT license found in the
5
 * LICENSE file in the root directory of this source tree.
6
 */
7
8
#include "JSParserImpl.h"
9
10
#include "llvh/Support/SaveAndRestore.h"
11
12
using llvh::dyn_cast;
13
using llvh::isa;
14
15
namespace hermes {
16
namespace parser {
17
namespace detail {
18
19
#if HERMES_PARSE_FLOW
20
21
0
Optional<ESTree::Node *> JSParserImpl::parseFlowDeclaration() {
22
0
  assert(checkDeclaration());
23
0
  SMLoc start = tok_->getStartLoc();
24
25
0
  if (context_.getParseFlowComponentSyntax() &&
26
0
      checkComponentDeclarationFlow()) {
27
0
    return parseComponentDeclarationFlow(start, /* declare */ false);
28
0
  }
29
30
0
  if (context_.getParseFlowComponentSyntax() && checkHookDeclarationFlow()) {
31
0
    return parseHookDeclarationFlow(start);
32
0
  }
33
34
0
  if (check(TokenKind::rw_enum)) {
35
0
    auto optEnum = parseEnumDeclarationFlow(start, /* declare */ false);
36
0
    if (!optEnum)
37
0
      return None;
38
0
    return *optEnum;
39
0
  }
40
41
0
  TypeAliasKind kind = TypeAliasKind::None;
42
0
  if (checkAndEat(declareIdent_))
43
0
    kind = TypeAliasKind::Declare;
44
0
  else if (checkAndEat(opaqueIdent_))
45
0
    kind = TypeAliasKind::Opaque;
46
47
0
  if (kind == TypeAliasKind::Declare &&
48
0
      !checkN(typeIdent_, interfaceIdent_, TokenKind::rw_interface)) {
49
0
    error(tok_->getSourceRange(), "invalid token in type declaration");
50
0
    return None;
51
0
  }
52
0
  if (kind == TypeAliasKind::Opaque && !check(typeIdent_)) {
53
0
    error(tok_->getSourceRange(), "invalid token in opaque type declaration");
54
0
    return None;
55
0
  }
56
57
0
  if (checkAndEat(typeIdent_)) {
58
0
    auto optType = parseTypeAliasFlow(start, kind);
59
0
    if (!optType)
60
0
      return None;
61
0
    return *optType;
62
0
  }
63
64
0
  if (checkN(interfaceIdent_, TokenKind::rw_interface)) {
65
0
    auto optType = parseInterfaceDeclarationFlow(
66
0
        kind == TypeAliasKind::Declare ? Optional<SMLoc>(start) : None);
67
0
    if (!optType)
68
0
      return None;
69
0
    return *optType;
70
0
  }
71
72
0
  assert(
73
0
      kind == TypeAliasKind::None &&
74
0
      "checkDeclaration() returned true without 'type' or 'interface'");
75
0
  return None;
76
0
}
77
78
0
Optional<ESTree::Node *> JSParserImpl::parseDeclareFLow(SMLoc start) {
79
0
  if (checkAndEat(typeIdent_)) {
80
0
    return parseTypeAliasFlow(start, TypeAliasKind::Declare);
81
0
  }
82
0
  if (checkAndEat(opaqueIdent_)) {
83
0
    if (!check(typeIdent_)) {
84
0
      error(tok_->getStartLoc(), "'type' required in opaque type declaration");
85
0
      return None;
86
0
    }
87
0
    advance(JSLexer::GrammarContext::Type);
88
0
    return parseTypeAliasFlow(start, TypeAliasKind::DeclareOpaque);
89
0
  }
90
0
  if (checkN(TokenKind::rw_interface, interfaceIdent_)) {
91
0
    return parseInterfaceDeclarationFlow(start);
92
0
  }
93
0
  if (check(TokenKind::rw_class)) {
94
0
    return parseDeclareClassFlow(start);
95
0
  }
96
0
  if (check(TokenKind::rw_function)) {
97
0
    return parseDeclareFunctionFlow(start);
98
0
  }
99
100
0
  if (context_.getParseFlowComponentSyntax() && checkHookDeclarationFlow()) {
101
0
    return parseDeclareHookFlow(start);
102
0
  }
103
104
0
  if (context_.getParseFlowComponentSyntax() &&
105
0
      checkComponentDeclarationFlow()) {
106
0
    return parseComponentDeclarationFlow(start, /* declare */ true);
107
0
  }
108
0
  if (check(TokenKind::rw_enum)) {
109
0
    return parseEnumDeclarationFlow(start, /* declare */ true);
110
0
  }
111
0
  if (check(moduleIdent_)) {
112
0
    return parseDeclareModuleFlow(start);
113
0
  }
114
0
  if (check(namespaceIdent_)) {
115
0
    return parseDeclareNamespaceFlow(start);
116
0
  }
117
0
  if (check(TokenKind::rw_var, TokenKind::rw_const) || check(letIdent_)) {
118
0
    ESTree::NodeLabel kind = tok_->getResWordOrIdentifier();
119
0
    advance();
120
0
    auto optIdent = parseBindingIdentifier(Param{});
121
0
    if (!optIdent) {
122
0
      errorExpected(
123
0
          TokenKind::identifier,
124
0
          "in var declaration",
125
0
          "start of declaration",
126
0
          start);
127
0
      return None;
128
0
    }
129
0
    if (!(*optIdent)->_typeAnnotation) {
130
0
      error(
131
0
          (*optIdent)->getSourceRange(),
132
0
          "expected type annotation on declared var");
133
0
    }
134
0
    if (!eatSemi())
135
0
      return None;
136
0
    return setLocation(
137
0
        start,
138
0
        getPrevTokenEndLoc(),
139
0
        new (context_) ESTree::DeclareVariableNode(*optIdent, kind));
140
0
  }
141
142
0
  if (!check(TokenKind::rw_export)) {
143
0
    errorExpected(
144
0
        {TokenKind::rw_export,
145
0
         TokenKind::rw_interface,
146
0
         TokenKind::rw_function,
147
0
         TokenKind::rw_class,
148
0
         TokenKind::rw_var},
149
0
        "in declared type",
150
0
        "start of declare",
151
0
        start);
152
0
    return None;
153
0
  }
154
155
0
  return parseDeclareExportFlow(start);
156
0
}
157
158
0
bool JSParserImpl::checkComponentDeclarationFlow() {
159
0
  if (!check(componentIdent_))
160
0
    return false;
161
162
  // Don't pass an `expectedToken` so we don't advance on a match. This allows
163
  // `parseComponentDeclarationFlow` to reparse the token and store useful
164
  // information. Additionally to be used within `checkDeclaration` this
165
  // function must be idempotent.
166
0
  OptValue<TokenKind> optNext = lexer_.lookahead1(None);
167
0
  return optNext.hasValue() && *optNext == TokenKind::identifier;
168
0
}
169
170
Optional<ESTree::Node *> JSParserImpl::parseComponentDeclarationFlow(
171
    SMLoc start,
172
0
    bool declare) {
173
  // component
174
0
  assert(check(componentIdent_));
175
0
  advance();
176
177
  // identifier
178
0
  auto optId = parseBindingIdentifier(Param{});
179
180
  // Components always require a name identifier
181
0
  if (!optId) {
182
0
    errorExpected(
183
0
        TokenKind::identifier,
184
0
        "after 'component'",
185
0
        "location of 'component'",
186
0
        start);
187
0
    return None;
188
0
  }
189
190
0
  ESTree::Node *typeParams = nullptr;
191
192
0
  if (check(TokenKind::less)) {
193
0
    auto optTypeParams = parseTypeParamsFlow();
194
0
    if (!optTypeParams)
195
0
      return None;
196
0
    typeParams = *optTypeParams;
197
0
  }
198
199
0
  if (!need(
200
0
          TokenKind::l_paren,
201
0
          "at start of component parameter list",
202
0
          "component declaration starts here",
203
0
          start)) {
204
0
    return None;
205
0
  }
206
207
0
  ESTree::NodeList paramList;
208
0
  ESTree::Node *rest = nullptr;
209
210
0
  if (declare) {
211
0
    auto restOpt = parseComponentTypeParametersFlow(Param{}, paramList);
212
0
    if (!restOpt)
213
0
      return None;
214
0
    rest = *restOpt;
215
0
  } else {
216
0
    if (!parseComponentParametersFlow(Param{}, paramList))
217
0
      return None;
218
0
  }
219
220
0
  ESTree::Node *rendersType = nullptr;
221
0
  if (check(rendersIdent_)) {
222
0
    auto optRenders = parseComponentRenderTypeFlow(false);
223
0
    if (!optRenders)
224
0
      return None;
225
0
    rendersType = *optRenders;
226
0
  }
227
228
0
  if (declare) {
229
0
    if (!eatSemi())
230
0
      return None;
231
232
0
    return setLocation(
233
0
        start,
234
0
        getPrevTokenEndLoc(),
235
0
        new (context_) ESTree::DeclareComponentNode(
236
0
            *optId, std::move(paramList), rest, typeParams, rendersType));
237
0
  }
238
239
0
  if (!need(
240
0
          TokenKind::l_brace,
241
0
          "in component declaration",
242
0
          "start of component declaration",
243
0
          start)) {
244
0
    return None;
245
0
  }
246
247
0
  SaveStrictModeAndSeenDirectives saveStrictModeAndSeenDirectives{this};
248
249
0
  auto parsedBody = parseFunctionBody(
250
0
      Param{}, false, false, false, JSLexer::AllowRegExp, true);
251
0
  if (!parsedBody)
252
0
    return None;
253
0
  auto *body = parsedBody.getValue();
254
255
0
  return setLocation(
256
0
      start,
257
0
      body,
258
0
      new (context_) ESTree::ComponentDeclarationNode(
259
0
          *optId, std::move(paramList), body, typeParams, rendersType));
260
0
}
261
262
bool JSParserImpl::parseComponentParametersFlow(
263
    Param param,
264
0
    ESTree::NodeList &paramList) {
265
0
  assert(
266
0
      check(TokenKind::l_paren) && "ComponentParameters must start with '('");
267
  // (
268
0
  SMLoc lparenLoc = advance().Start;
269
270
0
  while (!check(TokenKind::r_paren)) {
271
0
    if (check(TokenKind::dotdotdot)) {
272
      // BindingRestElement.
273
0
      auto optRestElem = parseBindingRestElement(param);
274
0
      if (!optRestElem)
275
0
        return false;
276
0
      paramList.push_back(*optRestElem.getValue());
277
0
      checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type);
278
0
      break;
279
0
    }
280
281
    // ComponentParameter.
282
0
    auto optParam = parseComponentParameterFlow(param);
283
0
    if (!optParam)
284
0
      return false;
285
286
0
    paramList.push_back(*optParam.getValue());
287
288
0
    if (!checkAndEat(TokenKind::comma))
289
0
      break;
290
0
  }
291
292
  // )
293
0
  if (!eat(
294
0
          TokenKind::r_paren,
295
0
          JSLexer::AllowRegExp,
296
0
          "at end of component parameter list",
297
0
          "start of component parameter list",
298
0
          lparenLoc)) {
299
0
    return false;
300
0
  }
301
302
0
  return true;
303
0
}
304
305
Optional<ESTree::Node *> JSParserImpl::parseComponentParameterFlow(
306
0
    Param param) {
307
  // ComponentParameter:
308
  //   StringLiteral as BindingElement
309
  //   IdentifierName
310
  //   IdentifierName as BindingElement
311
312
0
  SMLoc paramStart = tok_->getStartLoc();
313
0
  ESTree::Node *nameElem;
314
0
  if (check(TokenKind::string_literal)) {
315
    // StringLiteral as BindingElement
316
    // ^
317
0
    nameElem = setLocation(
318
0
        tok_,
319
0
        tok_,
320
0
        new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
321
0
    advance();
322
323
0
    if (!checkAndEat(asIdent_)) {
324
0
      error(
325
0
          nameElem->getSourceRange(),
326
0
          "string literal names require a local via `as`");
327
0
      return None;
328
0
    }
329
330
0
    auto optBinding = parseBindingElement(Param{});
331
0
    if (!optBinding)
332
0
      return None;
333
334
0
    return setLocation(
335
0
        paramStart,
336
0
        getPrevTokenEndLoc(),
337
0
        new (context_)
338
0
            ESTree::ComponentParameterNode(nameElem, *optBinding, false));
339
0
  }
340
341
0
  if (check(TokenKind::identifier) || tok_->isResWord()) {
342
0
    UniqueString *id = tok_->getResWordOrIdentifier();
343
0
    SMRange identRng = tok_->getSourceRange();
344
0
    TokenKind identKind = tok_->getKind();
345
0
    nameElem = setLocation(
346
0
        identRng,
347
0
        identRng,
348
0
        new (context_) ESTree::IdentifierNode(id, nullptr, false));
349
350
0
    advance();
351
0
    if (checkAndEat(asIdent_)) {
352
      // IdentifierName as BindingElement
353
      //                   ^
354
0
      auto optBinding = parseBindingElement(Param{});
355
0
      if (!optBinding)
356
0
        return None;
357
358
0
      return setLocation(
359
0
          paramStart,
360
0
          getPrevTokenEndLoc(),
361
0
          new (context_)
362
0
              ESTree::ComponentParameterNode(nameElem, *optBinding, false));
363
0
    }
364
365
0
    if (!validateBindingIdentifier(Param{}, identRng, id, identKind)) {
366
0
      error(identRng, "Invalid local name for component");
367
0
    }
368
369
0
    ESTree::Node *type = nullptr;
370
0
    bool optional = false;
371
372
    // IdentifierName?: TypeParam
373
    //               ^
374
0
    if (check(TokenKind::question)) {
375
0
      optional = true;
376
0
      advance(JSLexer::GrammarContext::Type);
377
0
    }
378
379
    // IdentifierName?: TypeParam
380
    //                ^
381
0
    if (check(TokenKind::colon)) {
382
0
      SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
383
0
      auto optType = parseTypeAnnotation(annotStart);
384
0
      if (!optType)
385
0
        return None;
386
0
      type = *optType;
387
0
    }
388
389
0
    auto elem = setLocation(
390
0
        identRng,
391
0
        getPrevTokenEndLoc(),
392
0
        new (context_) ESTree::IdentifierNode(id, type, optional));
393
0
    ESTree::Node *localElem;
394
395
    // IdentifierName?: TypeParam = expr
396
    //                            ^
397
0
    if (check(TokenKind::equal)) {
398
0
      auto optInit = parseBindingInitializer(param, elem);
399
0
      if (!optInit)
400
0
        return None;
401
0
      localElem = *optInit;
402
0
    } else {
403
0
      localElem = elem;
404
0
    }
405
406
0
    return setLocation(
407
0
        paramStart,
408
0
        getPrevTokenEndLoc(),
409
0
        new (context_)
410
0
            ESTree::ComponentParameterNode(nameElem, localElem, true));
411
0
  }
412
413
0
  error(
414
0
      tok_->getStartLoc(),
415
0
      "identifier or string literal expected in component parameter name");
416
0
  return None;
417
0
}
418
419
0
Optional<UniqueString *> JSParserImpl::parseRenderTypeOperator() {
420
0
  assert(tok_->getResWordOrIdentifier() == rendersIdent_);
421
0
  auto typeOperator = rendersIdent_;
422
0
  if (tok_->checkFollowingCharacter('?')) {
423
0
    SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
424
0
    if (!eat(
425
0
            TokenKind::question,
426
0
            JSLexer::GrammarContext::Type,
427
0
            "in render type annotation",
428
0
            "start of render type",
429
0
            start)) {
430
0
      return None;
431
0
    }
432
0
    typeOperator = rendersMaybeOperator_;
433
0
  } else if (tok_->checkFollowingCharacter('*')) {
434
0
    SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
435
0
    if (!eat(
436
0
            TokenKind::star,
437
0
            JSLexer::GrammarContext::Type,
438
0
            "in render type annotation",
439
0
            "start of render type",
440
0
            start)) {
441
0
      return None;
442
0
    }
443
0
    typeOperator = rendersStarOperator_;
444
0
  } else {
445
    // Normal renders, but we must still eat the renders token. We don't just
446
    // eat unconditionally above because the checkFollowingCharacter calls must
447
    // have the renders ident as the current token, so we can't advance until
448
    // after those calls
449
0
    advance(JSLexer::GrammarContext::Type);
450
0
  }
451
452
0
  return typeOperator;
453
0
}
454
455
Optional<ESTree::Node *> JSParserImpl::parseComponentRenderTypeFlow(
456
0
    bool componentType) {
457
0
  SMLoc annotStart = tok_->getStartLoc();
458
0
  auto optTypeOperator = parseRenderTypeOperator();
459
0
  Optional<ESTree::Node *> optBody;
460
  // This is a weird part of the Flow render syntax design that we should
461
  // reconsider. Because unions have higher precedence than renders, we
462
  // parse `component() renders null | number` as
463
  // `(component() renders null) | number. But with declared components
464
  // and component declarations we parse the entirety of the RHS of
465
  // `renders` as a single type, so
466
  // `component A() renders null | number { ... }` parses the render type
467
  // as a union of null | number. This was an intentional decision, and
468
  // prettier will make the discrepancy obvious, but it still feels
469
  // weird. If we give `renders` higher precedence than unions then this
470
  // is no longer a problem, but `keyof` has similar syntax and lower
471
  // precedence than a union type.
472
0
  if (componentType) {
473
0
    optBody = parsePrefixTypeAnnotationFlow();
474
0
  } else {
475
0
    optBody = parseTypeAnnotationFlow();
476
0
  }
477
0
  if (!optBody || !optTypeOperator)
478
0
    return None;
479
0
  return setLocation(
480
0
      annotStart,
481
0
      getPrevTokenEndLoc(),
482
0
      new (context_) ESTree::TypeOperatorNode(*optTypeOperator, *optBody));
483
0
}
484
485
0
Optional<ESTree::Node *> JSParserImpl::parseComponentTypeAnnotationFlow() {
486
  // component
487
0
  assert(check(componentIdent_));
488
0
  SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
489
490
  // identifier
491
0
  if (check(TokenKind::identifier)) {
492
0
    error(
493
0
        tok_->getSourceRange(),
494
0
        "component type annotations should not contain a name");
495
0
    advance(JSLexer::GrammarContext::Type);
496
0
  }
497
498
0
  ESTree::Node *typeParams = nullptr;
499
500
0
  if (check(TokenKind::less)) {
501
0
    auto optTypeParams = parseTypeParamsFlow();
502
0
    if (!optTypeParams)
503
0
      return None;
504
0
    typeParams = *optTypeParams;
505
0
  }
506
507
0
  if (!need(
508
0
          TokenKind::l_paren,
509
0
          "at start of component parameter list",
510
0
          "component type annotation starts here",
511
0
          start)) {
512
0
    return None;
513
0
  }
514
515
0
  ESTree::NodeList paramList;
516
0
  auto restOpt = parseComponentTypeParametersFlow(Param{}, paramList);
517
0
  if (!restOpt)
518
0
    return None;
519
0
  ESTree::Node *rest = *restOpt;
520
521
0
  ESTree::Node *rendersType = nullptr;
522
0
  if (check(rendersIdent_)) {
523
0
    auto optRenders = parseComponentRenderTypeFlow(true);
524
0
    if (!optRenders)
525
0
      return None;
526
0
    rendersType = *optRenders;
527
0
  }
528
529
0
  return setLocation(
530
0
      start,
531
0
      getPrevTokenEndLoc(),
532
0
      new (context_) ESTree::ComponentTypeAnnotationNode(
533
0
          std::move(paramList), rest, typeParams, rendersType));
534
0
}
535
536
Optional<ESTree::Node *> JSParserImpl::parseComponentTypeParametersFlow(
537
    Param param,
538
0
    ESTree::NodeList &paramList) {
539
0
  assert(
540
0
      check(TokenKind::l_paren) &&
541
0
      "ComponentTypeParameters must start with '('");
542
  // (
543
0
  SMLoc lparenLoc = advance(JSLexer::GrammarContext::Type).Start;
544
0
  ESTree::Node *rest = nullptr;
545
546
0
  while (!check(TokenKind::r_paren)) {
547
0
    if (check(TokenKind::dotdotdot)) {
548
      // ComponentTypeRestParameter.
549
0
      auto optRest = parseComponentTypeRestParameterFlow(param);
550
0
      if (!optRest)
551
0
        return None;
552
0
      rest = *optRest;
553
0
      break;
554
0
    }
555
556
    // ComponentTypeParameter.
557
0
    auto optParam = parseComponentTypeParameterFlow(param);
558
0
    if (!optParam)
559
0
      return None;
560
561
0
    paramList.push_back(*optParam.getValue());
562
563
0
    if (!checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type))
564
0
      break;
565
0
  }
566
567
  // )
568
0
  if (!eat(
569
0
          TokenKind::r_paren,
570
0
          JSLexer::GrammarContext::Type,
571
0
          "at end of component type parameter list",
572
0
          "start of component type parameter list",
573
0
          lparenLoc)) {
574
0
    return None;
575
0
  }
576
577
0
  return rest;
578
0
}
579
580
Optional<ESTree::Node *> JSParserImpl::parseComponentTypeRestParameterFlow(
581
0
    Param param) {
582
  // ComponentTypeRestParameter:
583
  //   ...IdentifierName: TypeParam
584
  //   ...IdentifierName?: TypeParam
585
  //   ...TypeParam
586
587
0
  assert(check(TokenKind::dotdotdot));
588
589
0
  SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
590
591
0
  auto optLeft = parseTypeAnnotationBeforeColonFlow();
592
0
  if (!optLeft)
593
0
    return None;
594
595
0
  ESTree::Node *name = nullptr;
596
0
  ESTree::Node *typeAnnotation = nullptr;
597
0
  bool optional = false;
598
599
0
  if (check(TokenKind::colon, TokenKind::question)) {
600
    // The node is actually supposed to be an identifier, not a TypeAnnotation.
601
0
    auto optName = reparseTypeAnnotationAsIdentifierFlow(*optLeft);
602
0
    if (!optName)
603
0
      return None;
604
0
    name = *optName;
605
0
    optional = checkAndEat(TokenKind::question, JSLexer::GrammarContext::Type);
606
0
    if (!eat(
607
0
            TokenKind::colon,
608
0
            JSLexer::GrammarContext::Type,
609
0
            "in component parameter type annotation",
610
0
            "start of parameter",
611
0
            start))
612
0
      return None;
613
0
    auto optType = parseTypeAnnotationFlow();
614
0
    if (!optType)
615
0
      return None;
616
0
    typeAnnotation = *optType;
617
0
  } else {
618
0
    typeAnnotation = *optLeft;
619
0
  }
620
621
0
  checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type);
622
623
0
  return setLocation(
624
0
      start,
625
0
      getPrevTokenEndLoc(),
626
0
      new (context_)
627
0
          ESTree::ComponentTypeParameterNode(name, typeAnnotation, optional));
628
0
}
629
630
Optional<ESTree::Node *> JSParserImpl::parseComponentTypeParameterFlow(
631
0
    Param param) {
632
  // ComponentTypeParameter:
633
  //   StringLiteral?: TypeParam
634
  //   IdentifierName?: TypeParam
635
636
0
  SMLoc paramStart = tok_->getStartLoc();
637
0
  ESTree::Node *nameElem;
638
0
  if (check(TokenKind::string_literal)) {
639
    // StringLiteral: TypeParam
640
    // ^
641
0
    nameElem = setLocation(
642
0
        tok_,
643
0
        tok_,
644
0
        new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
645
0
    advance(JSLexer::GrammarContext::Type);
646
0
  } else if (check(TokenKind::identifier) || tok_->isResWord()) {
647
    // IdentifierName: TypeParam
648
    // ^
649
0
    nameElem = setLocation(
650
0
        tok_,
651
0
        tok_,
652
0
        new (context_) ESTree::IdentifierNode(
653
0
            tok_->getResWordOrIdentifier(), nullptr, false));
654
0
    advance(JSLexer::GrammarContext::Type);
655
0
  } else {
656
0
    error(
657
0
        tok_->getStartLoc(),
658
0
        "identifier or string literal expected in component type parameter name");
659
0
    return None;
660
0
  }
661
662
0
  if (check(asIdent_)) {
663
0
    error(tok_->getStartLoc(), "'as' not allowed in component type parameter");
664
0
    return None;
665
0
  }
666
667
0
  bool optional = false;
668
669
  // Name?: TypeParam
670
  //     ^
671
0
  if (checkAndEat(TokenKind::question, JSLexer::GrammarContext::Type)) {
672
0
    optional = true;
673
0
  }
674
675
  // Name?: TypeParam
676
  //      ^
677
0
  if (!eat(
678
0
          TokenKind::colon,
679
0
          JSLexer::GrammarContext::Type,
680
0
          "in component type parameter",
681
0
          "start of parameter",
682
0
          paramStart))
683
0
    return None;
684
685
  // Name?: TypeParam
686
  //        ^
687
0
  auto optType = parseTypeAnnotation();
688
0
  if (!optType)
689
0
    return None;
690
691
0
  return setLocation(
692
0
      paramStart,
693
0
      getPrevTokenEndLoc(),
694
0
      new (context_)
695
0
          ESTree::ComponentTypeParameterNode(nameElem, *optType, optional));
696
0
}
697
698
0
bool JSParserImpl::checkHookDeclarationFlow() {
699
0
  if (!check(hookIdent_))
700
0
    return false;
701
702
  // Don't pass an `expectedToken` so we don't advance on a match. This allows
703
  // `parseHookDeclarationFlow` to reparse the token and store useful
704
  // information. Additionally to be used within `checkDeclaration` this
705
  // function must be idempotent.
706
0
  OptValue<TokenKind> optNext = lexer_.lookahead1(None);
707
0
  return optNext.hasValue() && *optNext == TokenKind::identifier;
708
0
}
709
710
0
Optional<ESTree::Node *> JSParserImpl::parseHookDeclarationFlow(SMLoc start) {
711
  // hook
712
0
  assert(check(hookIdent_));
713
0
  advance();
714
715
  // identifier
716
0
  auto optId = parseBindingIdentifier(Param{});
717
718
  // Hooks always require a name identifier
719
0
  if (!optId) {
720
0
    errorExpected(
721
0
        TokenKind::identifier, "after 'hook'", "location of 'hook'", start);
722
0
    return None;
723
0
  }
724
725
0
  ESTree::Node *typeParams = nullptr;
726
727
0
  if (check(TokenKind::less)) {
728
0
    auto optTypeParams = parseTypeParamsFlow();
729
0
    if (!optTypeParams)
730
0
      return None;
731
0
    typeParams = *optTypeParams;
732
0
  }
733
734
0
  if (!need(
735
0
          TokenKind::l_paren,
736
0
          "at start of hook parameter list",
737
0
          "hook declaration starts here",
738
0
          start)) {
739
0
    return None;
740
0
  }
741
742
0
  ESTree::NodeList paramList;
743
744
0
  if (!parseFormalParameters(Param{}, paramList))
745
0
    return None;
746
747
0
  ESTree::Node *returnType = nullptr;
748
749
0
  if (check(TokenKind::colon)) {
750
0
    SMLoc annotStart = advance(JSLexer::GrammarContext::Type).Start;
751
    // %checks predicates are unsupported in hooks.
752
0
    if (!check(checksIdent_)) {
753
0
      auto optRet = parseReturnTypeAnnotationFlow(annotStart);
754
0
      if (!optRet)
755
0
        return None;
756
0
      returnType = *optRet;
757
0
    } else {
758
0
      error(tok_->getStartLoc(), "checks predicates unsupported with hooks");
759
0
      return None;
760
0
    }
761
0
  }
762
763
0
  if (!need(
764
0
          TokenKind::l_brace,
765
0
          "in hook declaration",
766
0
          "start of hook declaration",
767
0
          start)) {
768
0
    return None;
769
0
  }
770
771
0
  SaveStrictModeAndSeenDirectives saveStrictModeAndSeenDirectives{this};
772
773
0
  auto parsedBody = parseFunctionBody(
774
0
      Param{}, false, false, false, JSLexer::AllowRegExp, true);
775
0
  if (!parsedBody)
776
0
    return None;
777
0
  auto *body = parsedBody.getValue();
778
779
0
  return setLocation(
780
0
      start,
781
0
      body,
782
0
      new (context_) ESTree::HookDeclarationNode(
783
0
          *optId, std::move(paramList), body, typeParams, returnType));
784
0
}
785
786
0
bool JSParserImpl::checkMaybeFlowMatchSlowPath() {
787
0
  assert(check(matchIdent_));
788
0
  OptValue<TokenKind> optNext = lexer_.lookahead1(None);
789
0
  return optNext.hasValue() && *optNext == TokenKind::l_paren;
790
0
}
791
792
ESTree::Node *JSParserImpl::reparseArgumentsAsMatchArgumentFlow(
793
    SMRange range,
794
0
    ESTree::NodeList &&argList) {
795
0
  if (argList.empty()) {
796
0
    error(range, "'match' argument must not be empty");
797
0
  }
798
0
  for (const ESTree::Node &arg : argList) {
799
0
    if (isa<ESTree::SpreadElementNode>(arg)) {
800
0
      error(
801
0
          arg.getSourceRange(),
802
0
          "'match' argument cannot contain spread elements");
803
0
    }
804
0
  }
805
0
  if (argList.size() == 1) {
806
0
    auto expr = &argList.front();
807
0
    argList.clear();
808
0
    return expr;
809
0
  }
810
0
  return setLocation(
811
0
      range,
812
0
      range,
813
0
      new (context_) ESTree::SequenceExpressionNode(std::move(argList)));
814
0
}
815
816
0
Optional<ESTree::Node *> JSParserImpl::tryParseMatchStatementFlow(Param param) {
817
0
  SMLoc startLoc;
818
0
  SMLoc argsStartLoc;
819
0
  SMLoc argsEndLoc;
820
0
  ESTree::NodeList argList;
821
0
  {
822
    // This save point is required because Flow supports both match statements
823
    // and match expressions, and we do not reserve `match` as a keyword. If
824
    // either of those points change in the future, this could be removed - see
825
    // blame for discussion.
826
    // We don't need to suppress errors as the only place that could error
827
    // in this section is `parseArguments`, and it would equivalently error
828
    // if this was parsed as an expression.
829
0
    JSLexer::SavePoint savePoint{&lexer_};
830
831
    // Checked already by `checkMaybeFlowMatch`
832
0
    assert(check(matchIdent_));
833
0
    startLoc = advance().Start;
834
    // Checked already by `checkMaybeFlowMatch`
835
0
    assert(!lexer_.isNewLineBeforeCurrentToken());
836
837
0
    argsStartLoc = tok_->getStartLoc();
838
0
    if (!parseArguments(argList, argsEndLoc))
839
0
      return None;
840
841
0
    if (lexer_.isNewLineBeforeCurrentToken() || !check(TokenKind::l_brace)) {
842
      // This is not a match statement.
843
0
      savePoint.restore();
844
0
      return nullptr;
845
0
    }
846
0
  }
847
  // We are unambiguously parsing a match statement now.
848
849
0
  auto arg = reparseArgumentsAsMatchArgumentFlow(
850
0
      SMRange{argsStartLoc, argsEndLoc}, std::move(argList));
851
852
0
  assert(check(TokenKind::l_brace));
853
0
  SMLoc lbraceLoc = advance().Start;
854
855
0
  ESTree::NodeList cases;
856
857
0
  while (!check(TokenKind::r_brace)) {
858
0
    SMLoc caseStartLoc = tok_->getStartLoc();
859
860
0
    auto optPattern = parseMatchPatternFlow();
861
0
    if (!optPattern)
862
0
      return None;
863
864
0
    ESTree::Node *guard = nullptr;
865
0
    if (checkAndEat(TokenKind::rw_if)) {
866
0
      auto optGuard = parseExpression(ParamIn, CoverTypedParameters::No);
867
0
      if (!optGuard)
868
0
        return None;
869
0
      guard = optGuard.getValue();
870
0
    }
871
872
0
    if (!eat(
873
0
            TokenKind::colon,
874
0
            JSLexer::AllowRegExp,
875
0
            "after match pattern",
876
0
            "location of pattern",
877
0
            caseStartLoc))
878
0
      return None;
879
880
0
    auto optBody = parseBlock(param.get(ParamReturn));
881
0
    if (!optBody)
882
0
      return None;
883
884
0
    cases.push_back(*setLocation(
885
0
        caseStartLoc,
886
0
        *optBody,
887
0
        new (context_) ESTree::MatchStatementCaseNode(
888
0
            optPattern.getValue(), optBody.getValue(), guard)));
889
890
0
    if (check(TokenKind::comma, TokenKind::semi)) {
891
0
      advance();
892
0
    }
893
0
  }
894
895
0
  SMLoc endLoc = tok_->getEndLoc();
896
0
  if (!eat(
897
0
          TokenKind::r_brace,
898
0
          JSLexer::AllowRegExp,
899
0
          "at end of 'match' statement",
900
0
          "location of '{'",
901
0
          lbraceLoc))
902
0
    return None;
903
904
0
  return setLocation(
905
0
      startLoc,
906
0
      endLoc,
907
0
      new (context_) ESTree::MatchStatementNode(arg, std::move(cases)));
908
0
}
909
910
0
Optional<ESTree::Node *> JSParserImpl::parseMatchCallOrMatchExpressionFlow() {
911
0
  SMLoc startLoc = tok_->getStartLoc();
912
0
  ESTree::Node *matchIdentNode = setLocation(
913
0
      tok_,
914
0
      tok_,
915
0
      new (context_)
916
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
917
0
  advance();
918
919
0
  auto parenLoc = tok_->getStartLoc();
920
0
  ESTree::NodeList argList;
921
0
  SMLoc endLoc;
922
923
0
  if (!parseArguments(argList, endLoc))
924
0
    return None;
925
926
0
  if (!lexer_.isNewLineBeforeCurrentToken() && check(TokenKind::l_brace)) {
927
0
    auto arg = reparseArgumentsAsMatchArgumentFlow(
928
0
        SMRange{parenLoc, endLoc}, std::move(argList));
929
0
    return parseMatchExpressionFlow(startLoc, arg);
930
0
  }
931
932
0
  auto callNode = setLocation(
933
0
      startLoc,
934
0
      endLoc,
935
0
      parenLoc,
936
0
      new (context_) ESTree::CallExpressionNode(
937
0
          matchIdentNode, nullptr, std::move(argList)));
938
0
  auto optExpr = parseOptionalExpressionExceptNew_tail(
939
0
      IsConstructorCall::No, startLoc, callNode);
940
0
  if (!optExpr) {
941
0
    return None;
942
0
  }
943
0
  return parseLeftHandSideExpressionTail(startLoc, optExpr.getValue());
944
0
}
945
946
Optional<ESTree::Node *> JSParserImpl::parseMatchExpressionFlow(
947
    SMLoc startLoc,
948
0
    ESTree::Node *argument) {
949
0
  assert(check(TokenKind::l_brace));
950
0
  SMLoc lbraceLoc = advance().Start;
951
952
0
  ESTree::NodeList cases;
953
954
0
  while (!check(TokenKind::r_brace)) {
955
0
    SMLoc caseStartLoc = tok_->getStartLoc();
956
957
0
    auto optPattern = parseMatchPatternFlow();
958
0
    if (!optPattern)
959
0
      return None;
960
961
0
    ESTree::Node *guard = nullptr;
962
0
    if (checkAndEat(TokenKind::rw_if)) {
963
0
      auto optGuard = parseExpression(ParamIn, CoverTypedParameters::No);
964
0
      if (!optGuard)
965
0
        return None;
966
0
      guard = optGuard.getValue();
967
0
    }
968
969
0
    if (!eat(
970
0
            TokenKind::colon,
971
0
            JSLexer::AllowRegExp,
972
0
            "after match pattern",
973
0
            "location of pattern",
974
0
            caseStartLoc))
975
0
      return None;
976
977
0
    auto optBody = parseAssignmentExpression();
978
0
    if (!optBody)
979
0
      return None;
980
981
0
    cases.push_back(*setLocation(
982
0
        caseStartLoc,
983
0
        *optBody,
984
0
        new (context_) ESTree::MatchExpressionCaseNode(
985
0
            optPattern.getValue(), optBody.getValue(), guard)));
986
987
0
    if (!(checkAndEat(TokenKind::comma) || checkAndEat(TokenKind::semi)))
988
0
      break;
989
0
  }
990
991
0
  SMLoc endLoc = tok_->getEndLoc();
992
0
  if (!eat(
993
0
          TokenKind::r_brace,
994
0
          JSLexer::AllowRegExp,
995
0
          "at end of 'match' expression",
996
0
          "location of '{'",
997
0
          lbraceLoc))
998
0
    return None;
999
1000
0
  return setLocation(
1001
0
      startLoc,
1002
0
      endLoc,
1003
0
      new (context_) ESTree::MatchExpressionNode(argument, std::move(cases)));
1004
0
}
1005
1006
0
Optional<ESTree::Node *> JSParserImpl::parseMatchPatternFlow() {
1007
0
  SMLoc startLoc = tok_->getStartLoc();
1008
0
  auto optFirstPattern = parseMatchSubpatternFlow();
1009
0
  if (!optFirstPattern)
1010
0
    return None;
1011
0
  ESTree::Node *pattern = optFirstPattern.getValue();
1012
0
  if (check(TokenKind::pipe)) {
1013
0
    ESTree::NodeList patterns{};
1014
0
    patterns.push_back(*optFirstPattern.getValue());
1015
0
    while (checkAndEat(TokenKind::pipe)) {
1016
0
      auto optPattern = parseMatchSubpatternFlow();
1017
0
      if (!optPattern)
1018
0
        return None;
1019
0
      patterns.push_back(*optPattern.getValue());
1020
0
    }
1021
0
    pattern = setLocation(
1022
0
        startLoc,
1023
0
        getPrevTokenEndLoc(),
1024
0
        new (context_) ESTree::MatchOrPatternNode(std::move(patterns)));
1025
0
  }
1026
0
  if (checkAndEat(asIdent_)) {
1027
0
    ESTree::Node *target = nullptr;
1028
0
    if (checkN(TokenKind::rw_const, TokenKind::rw_var, letIdent_)) {
1029
0
      auto optTarget = parseMatchBindingPatternFlow();
1030
0
      if (!optTarget)
1031
0
        return None;
1032
0
      target = optTarget.getValue();
1033
0
    } else if (check(TokenKind::identifier) || tok_->isResWord()) {
1034
0
      auto optTarget = parseMatchBindingIdentifierFlow();
1035
0
      if (!optTarget)
1036
0
        return None;
1037
0
      target = optTarget.getValue();
1038
0
    } else {
1039
0
      error(tok_->getSourceRange(), "expected identifier or binding pattern");
1040
0
      return None;
1041
0
    }
1042
0
    pattern = setLocation(
1043
0
        startLoc,
1044
0
        getPrevTokenEndLoc(),
1045
0
        new (context_) ESTree::MatchAsPatternNode(pattern, target));
1046
0
  }
1047
0
  return pattern;
1048
0
}
1049
1050
0
Optional<ESTree::Node *> JSParserImpl::parseMatchSubpatternFlow() {
1051
0
  switch (tok_->getKind()) {
1052
0
    case TokenKind::rw_null: {
1053
0
      auto *lit =
1054
0
          setLocation(tok_, tok_, new (context_) ESTree::NullLiteralNode());
1055
0
      auto *pat = setLocation(
1056
0
          tok_, tok_, new (context_) ESTree::MatchLiteralPatternNode(lit));
1057
0
      advance(JSLexer::AllowDiv);
1058
0
      return pat;
1059
0
    }
1060
1061
0
    case TokenKind::rw_true:
1062
0
    case TokenKind::rw_false: {
1063
0
      auto *lit = setLocation(
1064
0
          tok_,
1065
0
          tok_,
1066
0
          new (context_) ESTree::BooleanLiteralNode(
1067
0
              tok_->getKind() == TokenKind::rw_true));
1068
0
      auto *pat = setLocation(
1069
0
          tok_, tok_, new (context_) ESTree::MatchLiteralPatternNode(lit));
1070
0
      advance(JSLexer::AllowDiv);
1071
0
      return pat;
1072
0
    }
1073
1074
0
    case TokenKind::numeric_literal: {
1075
0
      auto *lit = setLocation(
1076
0
          tok_,
1077
0
          tok_,
1078
0
          new (context_) ESTree::NumericLiteralNode(tok_->getNumericLiteral()));
1079
0
      auto *pat = setLocation(
1080
0
          tok_, tok_, new (context_) ESTree::MatchLiteralPatternNode(lit));
1081
0
      advance(JSLexer::AllowDiv);
1082
0
      return pat;
1083
0
    }
1084
1085
0
    case TokenKind::bigint_literal: {
1086
0
      auto *lit = setLocation(
1087
0
          tok_,
1088
0
          tok_,
1089
0
          new (context_) ESTree::BigIntLiteralNode(tok_->getBigIntLiteral()));
1090
0
      auto *pat = setLocation(
1091
0
          tok_, tok_, new (context_) ESTree::MatchLiteralPatternNode(lit));
1092
0
      advance(JSLexer::AllowDiv);
1093
0
      return pat;
1094
0
    }
1095
1096
0
    case TokenKind::string_literal: {
1097
0
      auto *lit = setLocation(
1098
0
          tok_,
1099
0
          tok_,
1100
0
          new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
1101
0
      auto *pat = setLocation(
1102
0
          tok_, tok_, new (context_) ESTree::MatchLiteralPatternNode(lit));
1103
0
      advance(JSLexer::AllowDiv);
1104
0
      return pat;
1105
0
    }
1106
1107
0
    case TokenKind::identifier: {
1108
0
      if (check(underscoreIdent_)) {
1109
0
        auto *pat = setLocation(
1110
0
            tok_, tok_, new (context_) ESTree::MatchWildcardPatternNode());
1111
0
        advance(JSLexer::AllowDiv);
1112
0
        return pat;
1113
0
      }
1114
0
      if (check(letIdent_)) {
1115
0
        auto pat = parseMatchBindingPatternFlow();
1116
0
        if (!pat)
1117
0
          return None;
1118
0
        return pat.getValue();
1119
0
      }
1120
0
      SMLoc start_loc = tok_->getStartLoc();
1121
0
      auto *ident = setLocation(
1122
0
          tok_,
1123
0
          tok_,
1124
0
          new (context_)
1125
0
              ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
1126
0
      ESTree::Node *pat = setLocation(
1127
0
          tok_, tok_, new (context_) ESTree::MatchIdentifierPatternNode(ident));
1128
0
      advance(JSLexer::AllowDiv);
1129
1130
0
      while (check(TokenKind::period, TokenKind::l_square)) {
1131
0
        if (checkAndEat(TokenKind::period)) {
1132
0
          if (!need(
1133
0
                  TokenKind::identifier,
1134
0
                  "in match member pattern",
1135
0
                  nullptr,
1136
0
                  {}))
1137
0
            return None;
1138
0
          auto *property = setLocation(
1139
0
              tok_,
1140
0
              tok_,
1141
0
              new (context_) ESTree::IdentifierNode(
1142
0
                  tok_->getIdentifier(), nullptr, false));
1143
0
          advance(JSLexer::AllowDiv);
1144
0
          pat = setLocation(
1145
0
              start_loc,
1146
0
              getPrevTokenEndLoc(),
1147
0
              new (context_) ESTree::MatchMemberPatternNode(pat, property));
1148
0
        } else {
1149
0
          SMLoc computedStartLoc = advance().Start; // Eat `[`
1150
0
          ESTree::Node *property = nullptr;
1151
0
          switch (tok_->getKind()) {
1152
0
            case TokenKind::numeric_literal: {
1153
0
              property = setLocation(
1154
0
                  tok_,
1155
0
                  tok_,
1156
0
                  new (context_)
1157
0
                      ESTree::NumericLiteralNode(tok_->getNumericLiteral()));
1158
0
              advance(JSLexer::AllowDiv);
1159
0
              break;
1160
0
            }
1161
0
            case TokenKind::bigint_literal: {
1162
0
              property = setLocation(
1163
0
                  tok_,
1164
0
                  tok_,
1165
0
                  new (context_)
1166
0
                      ESTree::BigIntLiteralNode(tok_->getBigIntLiteral()));
1167
0
              advance(JSLexer::AllowDiv);
1168
0
              break;
1169
0
            }
1170
0
            case TokenKind::string_literal: {
1171
0
              property = setLocation(
1172
0
                  tok_,
1173
0
                  tok_,
1174
0
                  new (context_)
1175
0
                      ESTree::StringLiteralNode(tok_->getStringLiteral()));
1176
0
              advance(JSLexer::AllowDiv);
1177
0
              break;
1178
0
            }
1179
0
            default: {
1180
0
              errorExpected(
1181
0
                  {TokenKind::numeric_literal,
1182
0
                   TokenKind::bigint_literal,
1183
0
                   TokenKind::string_literal},
1184
0
                  "in match member pattern computed property",
1185
0
                  "start of computed property",
1186
0
                  computedStartLoc);
1187
0
              return None;
1188
0
            }
1189
0
          }
1190
0
          if (!eat(
1191
0
                  TokenKind::r_square,
1192
0
                  JSLexer::AllowDiv,
1193
0
                  "at end of computed member property",
1194
0
                  "location of '['",
1195
0
                  computedStartLoc))
1196
0
            return None;
1197
0
          pat = setLocation(
1198
0
              start_loc,
1199
0
              getPrevTokenEndLoc(),
1200
0
              new (context_) ESTree::MatchMemberPatternNode(pat, property));
1201
0
        }
1202
0
      }
1203
0
      return pat;
1204
0
    }
1205
1206
0
    case TokenKind::plus:
1207
0
    case TokenKind::minus: {
1208
0
      UniqueString *op = getTokenIdent(tok_->getKind());
1209
0
      SMLoc startLoc = advance().Start;
1210
1211
0
      ESTree::Node *argument;
1212
0
      switch (tok_->getKind()) {
1213
0
        case TokenKind::numeric_literal: {
1214
0
          argument = setLocation(
1215
0
              tok_,
1216
0
              tok_,
1217
0
              new (context_)
1218
0
                  ESTree::NumericLiteralNode(tok_->getNumericLiteral()));
1219
0
          advance(JSLexer::AllowDiv);
1220
0
          break;
1221
0
        }
1222
0
        case TokenKind::bigint_literal: {
1223
0
          argument = setLocation(
1224
0
              tok_,
1225
0
              tok_,
1226
0
              new (context_)
1227
0
                  ESTree::BigIntLiteralNode(tok_->getBigIntLiteral()));
1228
0
          advance(JSLexer::AllowDiv);
1229
0
          break;
1230
0
        }
1231
0
        default:
1232
0
          error(tok_->getStartLoc(), "invalid match unary pattern argument");
1233
0
          return None;
1234
0
      }
1235
0
      return setLocation(
1236
0
          startLoc,
1237
0
          getPrevTokenEndLoc(),
1238
0
          new (context_) ESTree::MatchUnaryPatternNode(argument, op));
1239
0
    }
1240
1241
0
    case TokenKind::rw_const:
1242
0
    case TokenKind::rw_var: {
1243
0
      auto pat = parseMatchBindingPatternFlow();
1244
0
      if (!pat)
1245
0
        return None;
1246
0
      return pat.getValue();
1247
0
    }
1248
1249
0
    case TokenKind::l_paren: {
1250
0
      SMLoc startLoc = advance().Start;
1251
0
      auto optPattern = parseMatchPatternFlow();
1252
0
      if (!optPattern)
1253
0
        return None;
1254
1255
0
      if (!eat(
1256
0
              TokenKind::r_paren,
1257
0
              JSLexer::AllowDiv,
1258
0
              "at end of a match pattern group",
1259
0
              "location of '('",
1260
0
              startLoc))
1261
0
        return None;
1262
1263
0
      return optPattern.getValue();
1264
0
    }
1265
1266
0
    case TokenKind::l_brace:
1267
0
      return parseMatchObjectPatternFlow();
1268
1269
0
    case TokenKind::l_square:
1270
0
      return parseMatchArrayPatternFlow();
1271
1272
0
    default:
1273
0
      error(tok_->getStartLoc(), "invalid match pattern");
1274
0
      return None;
1275
0
  }
1276
0
}
1277
1278
Optional<ESTree::IdentifierNode *>
1279
0
JSParserImpl::parseMatchBindingIdentifierFlow() {
1280
0
  UniqueString *id = tok_->getResWordOrIdentifier();
1281
0
  TokenKind kind = tok_->getKind();
1282
0
  if (!validateBindingIdentifier(Param{}, tok_->getSourceRange(), id, kind))
1283
0
    return None;
1284
0
  advance();
1285
0
  return setLocation(
1286
0
      tok_, tok_, new (context_) ESTree::IdentifierNode(id, nullptr, false));
1287
0
}
1288
1289
Optional<ESTree::MatchBindingPatternNode *>
1290
0
JSParserImpl::parseMatchBindingPatternFlow() {
1291
0
  assert(checkN(TokenKind::rw_const, TokenKind::rw_var, letIdent_));
1292
0
  auto kind = tok_->getResWordOrIdentifier();
1293
0
  SMLoc startLoc = advance().Start;
1294
0
  if (!check(TokenKind::identifier) && !tok_->isResWord()) {
1295
0
    errorExpected(
1296
0
        TokenKind::identifier,
1297
0
        "in match binding pattern",
1298
0
        "start of binding pattern",
1299
0
        startLoc);
1300
0
  }
1301
0
  auto optIdent = parseMatchBindingIdentifierFlow();
1302
0
  if (!optIdent)
1303
0
    return None;
1304
0
  return setLocation(
1305
0
      startLoc,
1306
0
      getPrevTokenEndLoc(),
1307
0
      new (context_)
1308
0
          ESTree::MatchBindingPatternNode(optIdent.getValue(), kind));
1309
0
}
1310
1311
0
Optional<ESTree::Node *> JSParserImpl::parseMatchRestPatternFlow() {
1312
0
  assert(check(TokenKind::dotdotdot));
1313
0
  SMLoc restStartLoc = advance().Start;
1314
0
  ESTree::Node *arg = nullptr;
1315
0
  if (checkN(TokenKind::rw_const, TokenKind::rw_var, letIdent_)) {
1316
0
    auto optArg = parseMatchBindingPatternFlow();
1317
0
    if (!optArg)
1318
0
      return None;
1319
0
    arg = optArg.getValue();
1320
0
  }
1321
0
  return setLocation(
1322
0
      restStartLoc,
1323
0
      getPrevTokenEndLoc(),
1324
0
      new (context_) ESTree::MatchRestPatternNode(arg));
1325
0
}
1326
1327
0
Optional<ESTree::Node *> JSParserImpl::parseMatchObjectPatternFlow() {
1328
0
  assert(check(TokenKind::l_brace));
1329
0
  auto startLoc = advance().Start;
1330
0
  ESTree::NodeList properties{};
1331
0
  ESTree::Node *rest = nullptr;
1332
1333
0
  while (!check(TokenKind::r_brace)) {
1334
0
    if (check(TokenKind::dotdotdot)) {
1335
0
      auto optRest = parseMatchRestPatternFlow();
1336
0
      if (!optRest) {
1337
0
        return None;
1338
0
      }
1339
0
      rest = optRest.getValue();
1340
0
      break;
1341
0
    }
1342
1343
0
    ESTree::Node *prop = nullptr;
1344
0
    auto propStartLoc = tok_->getStartLoc();
1345
0
    if (checkN(TokenKind::rw_const, TokenKind::rw_var, letIdent_)) {
1346
      // Shorthand syntax: e.g. `const x` is shorthand for `x: const x`
1347
0
      auto optBindingPattern = parseMatchBindingPatternFlow();
1348
0
      if (!optBindingPattern)
1349
0
        return None;
1350
0
      auto bindingPattern = optBindingPattern.getValue();
1351
0
      prop = setLocation(
1352
0
          propStartLoc,
1353
0
          getPrevTokenEndLoc(),
1354
0
          new (context_) ESTree::MatchObjectPatternPropertyNode(
1355
0
              bindingPattern->_id, bindingPattern, true));
1356
0
    } else {
1357
      // Normal property
1358
0
      ESTree::Node *key = nullptr;
1359
      // Property key parsing
1360
0
      switch (tok_->getKind()) {
1361
0
        case TokenKind::identifier: {
1362
0
          key = setLocation(
1363
0
              tok_,
1364
0
              tok_,
1365
0
              new (context_) ESTree::IdentifierNode(
1366
0
                  tok_->getIdentifier(), nullptr, false));
1367
0
          advance(JSLexer::AllowDiv);
1368
0
          break;
1369
0
        }
1370
0
        case TokenKind::string_literal: {
1371
0
          key = setLocation(
1372
0
              tok_,
1373
0
              tok_,
1374
0
              new (context_)
1375
0
                  ESTree::StringLiteralNode(tok_->getStringLiteral()));
1376
0
          advance(JSLexer::AllowDiv);
1377
0
          break;
1378
0
        }
1379
0
        case TokenKind::numeric_literal: {
1380
0
          key = setLocation(
1381
0
              tok_,
1382
0
              tok_,
1383
0
              new (context_)
1384
0
                  ESTree::NumericLiteralNode(tok_->getNumericLiteral()));
1385
0
          advance(JSLexer::AllowDiv);
1386
0
          break;
1387
0
        }
1388
0
        case TokenKind::bigint_literal: {
1389
0
          key = setLocation(
1390
0
              tok_,
1391
0
              tok_,
1392
0
              new (context_)
1393
0
                  ESTree::BigIntLiteralNode(tok_->getBigIntLiteral()));
1394
0
          advance(JSLexer::AllowDiv);
1395
0
          break;
1396
0
        }
1397
0
        default: {
1398
0
          errorExpected(
1399
0
              {TokenKind::identifier,
1400
0
               TokenKind::string_literal,
1401
0
               TokenKind::numeric_literal,
1402
0
               TokenKind::bigint_literal},
1403
0
              "in match object pattern property key",
1404
0
              "start of match object pattern property key",
1405
0
              propStartLoc);
1406
0
          return None;
1407
0
        }
1408
0
      }
1409
0
      if (!eat(
1410
0
              TokenKind::colon,
1411
0
              JSLexer::AllowRegExp,
1412
0
              "in match object pattern property",
1413
0
              "start of match object pattern property",
1414
0
              propStartLoc))
1415
0
        return None;
1416
0
      auto optPattern = parseMatchPatternFlow();
1417
0
      prop = setLocation(
1418
0
          propStartLoc,
1419
0
          getPrevTokenEndLoc(),
1420
0
          new (context_) ESTree::MatchObjectPatternPropertyNode(
1421
0
              key, optPattern.getValue(), false));
1422
0
    }
1423
0
    properties.push_back(*prop);
1424
0
    if (!checkAndEat(TokenKind::comma))
1425
0
      break;
1426
0
  }
1427
0
  if (!eat(
1428
0
          TokenKind::r_brace,
1429
0
          JSLexer::AllowDiv,
1430
0
          "at end of object match pattern",
1431
0
          "location of '{'",
1432
0
          startLoc))
1433
0
    return None;
1434
1435
0
  return setLocation(
1436
0
      startLoc,
1437
0
      getPrevTokenEndLoc(),
1438
0
      new (context_)
1439
0
          ESTree::MatchObjectPatternNode(std::move(properties), rest));
1440
0
}
1441
1442
0
Optional<ESTree::Node *> JSParserImpl::parseMatchArrayPatternFlow() {
1443
0
  assert(check(TokenKind::l_square));
1444
0
  auto startLoc = advance().Start;
1445
0
  ESTree::NodeList elements{};
1446
0
  ESTree::Node *rest = nullptr;
1447
1448
0
  while (!check(TokenKind::r_square)) {
1449
0
    if (check(TokenKind::dotdotdot)) {
1450
0
      auto optRest = parseMatchRestPatternFlow();
1451
0
      if (!optRest) {
1452
0
        return None;
1453
0
      }
1454
0
      rest = optRest.getValue();
1455
0
      break;
1456
0
    }
1457
1458
0
    auto optPattern = parseMatchPatternFlow();
1459
0
    if (!optPattern)
1460
0
      return None;
1461
0
    elements.push_back(*optPattern.getValue());
1462
0
    if (!checkAndEat(TokenKind::comma))
1463
0
      break;
1464
0
  }
1465
0
  if (!eat(
1466
0
          TokenKind::r_square,
1467
0
          JSLexer::AllowDiv,
1468
0
          "at end of array match pattern",
1469
0
          "location of '['",
1470
0
          startLoc))
1471
0
    return None;
1472
1473
0
  return setLocation(
1474
0
      startLoc,
1475
0
      getPrevTokenEndLoc(),
1476
0
      new (context_) ESTree::MatchArrayPatternNode(std::move(elements), rest));
1477
0
}
1478
1479
Optional<ESTree::Node *> JSParserImpl::parseTypeAliasFlow(
1480
    SMLoc start,
1481
0
    TypeAliasKind kind) {
1482
0
  if (!need(
1483
0
          TokenKind::identifier, "in type alias", "start of type alias", start))
1484
0
    return None;
1485
1486
0
  ESTree::Node *id = setLocation(
1487
0
      tok_,
1488
0
      tok_,
1489
0
      new (context_)
1490
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
1491
0
  advance(JSLexer::GrammarContext::Type);
1492
1493
0
  ESTree::Node *typeParams = nullptr;
1494
0
  if (check(TokenKind::less)) {
1495
0
    auto optTypeParams = parseTypeParamsFlow();
1496
0
    if (!optTypeParams)
1497
0
      return None;
1498
0
    typeParams = *optTypeParams;
1499
0
  }
1500
1501
0
  ESTree::Node *supertype = nullptr;
1502
0
  if ((kind == TypeAliasKind::Opaque || kind == TypeAliasKind::DeclareOpaque) &&
1503
0
      checkAndEat(TokenKind::colon, JSLexer::GrammarContext::Type)) {
1504
0
    auto optSuper = parseTypeAnnotationFlow();
1505
0
    if (!optSuper)
1506
0
      return None;
1507
0
    supertype = *optSuper;
1508
0
  }
1509
1510
0
  ESTree::Node *right = nullptr;
1511
0
  if (kind != TypeAliasKind::DeclareOpaque) {
1512
0
    if (!eat(
1513
0
            TokenKind::equal,
1514
0
            JSLexer::GrammarContext::Type,
1515
0
            "in type alias",
1516
0
            "start of type alias",
1517
0
            start))
1518
0
      return None;
1519
1520
0
    auto optRight = parseTypeAnnotationFlow();
1521
0
    if (!optRight)
1522
0
      return None;
1523
0
    right = *optRight;
1524
0
  }
1525
1526
0
  if (!eatSemi())
1527
0
    return None;
1528
1529
0
  if (kind == TypeAliasKind::DeclareOpaque) {
1530
0
    return setLocation(
1531
0
        start,
1532
0
        getPrevTokenEndLoc(),
1533
0
        new (context_)
1534
0
            ESTree::DeclareOpaqueTypeNode(id, typeParams, right, supertype));
1535
0
  }
1536
0
  if (kind == TypeAliasKind::Declare) {
1537
0
    return setLocation(
1538
0
        start,
1539
0
        getPrevTokenEndLoc(),
1540
0
        new (context_) ESTree::DeclareTypeAliasNode(id, typeParams, right));
1541
0
  }
1542
0
  if (kind == TypeAliasKind::Opaque) {
1543
0
    return setLocation(
1544
0
        start,
1545
0
        getPrevTokenEndLoc(),
1546
0
        new (context_)
1547
0
            ESTree::OpaqueTypeNode(id, typeParams, right, supertype));
1548
0
  }
1549
0
  return setLocation(
1550
0
      start,
1551
0
      getPrevTokenEndLoc(),
1552
0
      new (context_) ESTree::TypeAliasNode(id, typeParams, right));
1553
0
}
1554
1555
Optional<ESTree::Node *> JSParserImpl::parseInterfaceDeclarationFlow(
1556
0
    Optional<SMLoc> declareStart) {
1557
0
  assert(checkN(TokenKind::rw_interface, interfaceIdent_));
1558
0
  SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
1559
1560
0
  if (!need(
1561
0
          TokenKind::identifier,
1562
0
          "in interface declaration",
1563
0
          "start of interface",
1564
0
          start))
1565
0
    return None;
1566
1567
0
  auto *id = setLocation(
1568
0
      tok_,
1569
0
      tok_,
1570
0
      new (context_)
1571
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
1572
0
  advance(JSLexer::GrammarContext::Type);
1573
1574
0
  ESTree::Node *typeParams = nullptr;
1575
0
  if (check(TokenKind::less)) {
1576
0
    auto optParams = parseTypeParamsFlow();
1577
0
    if (!optParams)
1578
0
      return None;
1579
0
    typeParams = *optParams;
1580
0
  }
1581
1582
0
  ESTree::NodeList extends{};
1583
1584
0
  auto optBody = parseInterfaceTailFlow(start, extends);
1585
0
  if (!optBody)
1586
0
    return None;
1587
1588
0
  if (declareStart.hasValue()) {
1589
0
    return setLocation(
1590
0
        *declareStart,
1591
0
        *optBody,
1592
0
        new (context_) ESTree::DeclareInterfaceNode(
1593
0
            id, typeParams, std::move(extends), *optBody));
1594
0
  }
1595
0
  return setLocation(
1596
0
      start,
1597
0
      *optBody,
1598
0
      new (context_) ESTree::InterfaceDeclarationNode(
1599
0
          id, typeParams, std::move(extends), *optBody));
1600
0
}
1601
1602
Optional<ESTree::Node *> JSParserImpl::parseInterfaceTailFlow(
1603
    SMLoc start,
1604
0
    ESTree::NodeList &extends) {
1605
0
  if (checkAndEat(TokenKind::rw_extends)) {
1606
0
    do {
1607
0
      if (!need(
1608
0
              TokenKind::identifier,
1609
0
              "in extends clause",
1610
0
              "location of interface",
1611
0
              start))
1612
0
        return None;
1613
0
      if (!parseInterfaceExtends(start, extends))
1614
0
        return None;
1615
0
    } while (checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type));
1616
0
  }
1617
1618
0
  if (!need(TokenKind::l_brace, "in interface", "location of interface", start))
1619
0
    return None;
1620
1621
0
  return parseObjectTypeAnnotationFlow(
1622
0
      AllowProtoProperty::No, AllowStaticProperty::No, AllowSpreadProperty::No);
1623
0
}
1624
1625
bool JSParserImpl::parseInterfaceExtends(
1626
    SMLoc start,
1627
0
    ESTree::NodeList &extends) {
1628
0
  assert(check(TokenKind::identifier));
1629
0
  auto optGeneric = parseGenericTypeFlow();
1630
0
  if (!optGeneric)
1631
0
    return false;
1632
0
  ESTree::GenericTypeAnnotationNode *generic = *optGeneric;
1633
0
  extends.push_back(*setLocation(
1634
0
      generic,
1635
0
      generic,
1636
0
      new (context_) ESTree::InterfaceExtendsNode(
1637
0
          generic->_id, generic->_typeParameters)));
1638
0
  return true;
1639
0
}
1640
1641
Optional<ESTree::Node *> JSParserImpl::parseDeclareFunctionOrHookFlow(
1642
    SMLoc start,
1643
0
    bool hook) {
1644
0
  advance(JSLexer::GrammarContext::Type);
1645
1646
0
  if (!need(
1647
0
          TokenKind::identifier,
1648
0
          "in declare function type",
1649
0
          "location of declare",
1650
0
          start))
1651
0
    return None;
1652
1653
0
  UniqueString *id = tok_->getIdentifier();
1654
0
  SMLoc idStart = advance(JSLexer::GrammarContext::Type).Start;
1655
1656
0
  SMLoc funcStart = tok_->getStartLoc();
1657
1658
0
  ESTree::Node *typeParams = nullptr;
1659
0
  if (check(TokenKind::less)) {
1660
0
    auto optParams = parseTypeParamsFlow();
1661
0
    if (!optParams)
1662
0
      return None;
1663
0
    typeParams = *optParams;
1664
0
  }
1665
1666
0
  if (!need(
1667
0
          TokenKind::l_paren,
1668
0
          "in declare function type",
1669
0
          "location of declare",
1670
0
          start))
1671
0
    return None;
1672
1673
0
  ESTree::NodeList params{};
1674
0
  ESTree::Node *thisConstraint = nullptr;
1675
0
  auto optRest =
1676
0
      parseFunctionTypeAnnotationParamsFlow(params, thisConstraint, hook);
1677
0
  if (!optRest)
1678
0
    return None;
1679
1680
0
  if (!eat(
1681
0
          TokenKind::colon,
1682
0
          JSLexer::GrammarContext::Type,
1683
0
          "in declare function type",
1684
0
          "location of declare",
1685
0
          start))
1686
0
    return None;
1687
1688
0
  auto optReturn = parseReturnTypeAnnotationFlow();
1689
0
  if (!optReturn)
1690
0
    return None;
1691
0
  ESTree::Node *returnType = *optReturn;
1692
0
  SMLoc funcEnd = getPrevTokenEndLoc();
1693
1694
0
  ESTree::Node *predicate = nullptr;
1695
0
  if (check(checksIdent_) && !hook) {
1696
0
    auto optPred = parsePredicateFlow();
1697
0
    if (!optPred)
1698
0
      return None;
1699
0
    predicate = *optPred;
1700
0
  }
1701
1702
0
  if (!eatSemi())
1703
0
    return None;
1704
1705
0
  if (!hook) {
1706
0
    auto *func = setLocation(
1707
0
        funcStart,
1708
0
        funcEnd,
1709
0
        new (context_) ESTree::TypeAnnotationNode(setLocation(
1710
0
            funcStart,
1711
0
            funcEnd,
1712
0
            new (context_) ESTree::FunctionTypeAnnotationNode(
1713
0
                std::move(params),
1714
0
                thisConstraint,
1715
0
                returnType,
1716
0
                *optRest,
1717
0
                typeParams))));
1718
0
    auto *ident = setLocation(
1719
0
        idStart, func, new (context_) ESTree::IdentifierNode(id, func, false));
1720
0
    return setLocation(
1721
0
        start,
1722
0
        getPrevTokenEndLoc(),
1723
0
        new (context_) ESTree::DeclareFunctionNode(ident, predicate));
1724
0
  } else {
1725
0
    auto *func = setLocation(
1726
0
        funcStart,
1727
0
        funcEnd,
1728
0
        new (context_) ESTree::TypeAnnotationNode(setLocation(
1729
0
            funcStart,
1730
0
            funcEnd,
1731
0
            new (context_) ESTree::HookTypeAnnotationNode(
1732
0
                std::move(params), returnType, *optRest, typeParams))));
1733
0
    auto *ident = setLocation(
1734
0
        idStart, func, new (context_) ESTree::IdentifierNode(id, func, false));
1735
0
    return setLocation(
1736
0
        start,
1737
0
        getPrevTokenEndLoc(),
1738
0
        new (context_) ESTree::DeclareHookNode(ident));
1739
0
  }
1740
0
}
1741
1742
0
Optional<ESTree::Node *> JSParserImpl::parseDeclareFunctionFlow(SMLoc start) {
1743
0
  assert(check(TokenKind::rw_function));
1744
0
  return parseDeclareFunctionOrHookFlow(start, false);
1745
0
}
1746
1747
0
Optional<ESTree::Node *> JSParserImpl::parseDeclareHookFlow(SMLoc start) {
1748
0
  assert(check(hookIdent_));
1749
0
  return parseDeclareFunctionOrHookFlow(start, true);
1750
0
}
1751
1752
0
Optional<ESTree::Node *> JSParserImpl::parseDeclareModuleFlow(SMLoc start) {
1753
0
  assert(check(moduleIdent_));
1754
0
  advance(JSLexer::GrammarContext::Type);
1755
1756
0
  if (checkAndEat(TokenKind::period, JSLexer::GrammarContext::Type)) {
1757
0
    if (!checkAndEat(exportsIdent_, JSLexer::GrammarContext::Type)) {
1758
0
      error(tok_->getSourceRange(), "expected module.exports declaration");
1759
0
      return None;
1760
0
    }
1761
1762
0
    SMLoc annotStart = tok_->getStartLoc();
1763
0
    if (!eat(
1764
0
            TokenKind::colon,
1765
0
            JSLexer::GrammarContext::Type,
1766
0
            "in module.exports declaration",
1767
0
            "start of declaration",
1768
0
            start))
1769
0
      return None;
1770
0
    auto optType = parseTypeAnnotationFlow(annotStart);
1771
0
    if (!optType)
1772
0
      return None;
1773
0
    eatSemi(true);
1774
0
    return setLocation(
1775
0
        start,
1776
0
        getPrevTokenEndLoc(),
1777
0
        new (context_) ESTree::DeclareModuleExportsNode(*optType));
1778
0
  }
1779
1780
  // declare module Identifier {[opt]
1781
  //                ^
1782
0
  ESTree::Node *id = nullptr;
1783
0
  if (check(TokenKind::string_literal)) {
1784
0
    id = setLocation(
1785
0
        tok_,
1786
0
        tok_,
1787
0
        new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
1788
0
  } else {
1789
0
    if (!need(
1790
0
            TokenKind::identifier,
1791
0
            "in module declaration",
1792
0
            "start of declaration",
1793
0
            start))
1794
0
      return None;
1795
0
    id = setLocation(
1796
0
        tok_,
1797
0
        tok_,
1798
0
        new (context_)
1799
0
            ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
1800
0
  }
1801
0
  advance(JSLexer::GrammarContext::Type);
1802
1803
  // declare module Identifier {
1804
  //                           ^
1805
0
  SMLoc bodyStart = tok_->getStartLoc();
1806
0
  if (!eat(
1807
0
          TokenKind::l_brace,
1808
0
          JSLexer::GrammarContext::Type,
1809
0
          "in module declaration",
1810
0
          "start of declaration",
1811
0
          start))
1812
0
    return None;
1813
1814
0
  ESTree::NodeList declarations{};
1815
1816
0
  while (!check(TokenKind::r_brace)) {
1817
0
    if (!parseStatementListItem(Param{}, AllowImportExport::Yes, declarations))
1818
0
      return None;
1819
0
  }
1820
1821
0
  SMLoc bodyEnd = advance(JSLexer::GrammarContext::Type).End;
1822
1823
0
  ESTree::Node *body = setLocation(
1824
0
      bodyStart,
1825
0
      bodyEnd,
1826
0
      new (context_) ESTree::BlockStatementNode(std::move(declarations)));
1827
1828
0
  return setLocation(
1829
0
      start, body, new (context_) ESTree::DeclareModuleNode(id, body));
1830
0
}
1831
1832
0
Optional<ESTree::Node *> JSParserImpl::parseDeclareNamespaceFlow(SMLoc start) {
1833
0
  assert(check(namespaceIdent_));
1834
0
  advance(JSLexer::GrammarContext::Type);
1835
1836
  // declare namespace Identifier {[opt]
1837
  //                   ^
1838
0
  if (!need(
1839
0
          TokenKind::identifier,
1840
0
          "in namespace declaration",
1841
0
          "start of declaration",
1842
0
          start))
1843
0
    return None;
1844
0
  ESTree::Node *id = setLocation(
1845
0
      tok_,
1846
0
      tok_,
1847
0
      new (context_)
1848
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
1849
0
  advance(JSLexer::GrammarContext::Type);
1850
1851
  // declare namespace Identifier {
1852
  //                              ^
1853
0
  SMLoc bodyStart = tok_->getStartLoc();
1854
0
  if (!eat(
1855
0
          TokenKind::l_brace,
1856
0
          JSLexer::GrammarContext::Type,
1857
0
          "in namespace declaration",
1858
0
          "start of declaration",
1859
0
          start))
1860
0
    return None;
1861
1862
0
  ESTree::NodeList declarations{};
1863
1864
0
  while (!check(TokenKind::r_brace)) {
1865
0
    if (!parseStatementListItem(Param{}, AllowImportExport::Yes, declarations))
1866
0
      return None;
1867
0
  }
1868
1869
0
  SMLoc bodyEnd = advance(JSLexer::GrammarContext::Type).End;
1870
1871
0
  ESTree::Node *body = setLocation(
1872
0
      bodyStart,
1873
0
      bodyEnd,
1874
0
      new (context_) ESTree::BlockStatementNode(std::move(declarations)));
1875
1876
0
  return setLocation(
1877
0
      start, body, new (context_) ESTree::DeclareNamespaceNode(id, body));
1878
0
}
1879
1880
0
Optional<ESTree::Node *> JSParserImpl::parseDeclareClassFlow(SMLoc start) {
1881
0
  assert(check(TokenKind::rw_class));
1882
0
  advance(JSLexer::GrammarContext::Type);
1883
1884
  // NOTE: Class definition is always strict mode code.
1885
0
  SaveStrictModeAndSeenDirectives saveStrictMode{this};
1886
0
  setStrictMode(true);
1887
1888
0
  if (!need(
1889
0
          TokenKind::identifier,
1890
0
          "in class declaration",
1891
0
          "start of declaration",
1892
0
          start))
1893
0
    return None;
1894
1895
0
  auto *id = setLocation(
1896
0
      tok_,
1897
0
      tok_,
1898
0
      new (context_)
1899
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
1900
0
  advance(JSLexer::GrammarContext::Type);
1901
1902
0
  ESTree::Node *typeParams = nullptr;
1903
0
  if (check(TokenKind::less)) {
1904
0
    auto optParams = parseTypeParamsFlow();
1905
0
    if (!optParams)
1906
0
      return None;
1907
0
    typeParams = *optParams;
1908
0
  }
1909
1910
0
  ESTree::NodeList extends{};
1911
0
  if (checkAndEat(TokenKind::rw_extends)) {
1912
0
    if (!need(
1913
0
            TokenKind::identifier,
1914
0
            "in class 'extends'",
1915
0
            "start of declaration",
1916
0
            start))
1917
0
      return None;
1918
0
    if (!parseInterfaceExtends(start, extends))
1919
0
      return None;
1920
0
  }
1921
1922
0
  ESTree::NodeList mixins{};
1923
0
  if (checkAndEat(mixinsIdent_)) {
1924
0
    do {
1925
0
      if (!need(
1926
0
              TokenKind::identifier,
1927
0
              "in class 'mixins'",
1928
0
              "start of declaration",
1929
0
              start))
1930
0
        return None;
1931
0
      if (!parseInterfaceExtends(start, mixins))
1932
0
        return None;
1933
0
    } while (checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type));
1934
0
  }
1935
1936
0
  ESTree::NodeList implements{};
1937
0
  if (checkAndEat(TokenKind::rw_implements)) {
1938
0
    do {
1939
0
      if (!need(
1940
0
              TokenKind::identifier,
1941
0
              "in class 'implements'",
1942
0
              "start of declaration",
1943
0
              start))
1944
0
        return None;
1945
0
      auto optImpl = parseClassImplementsFlow();
1946
0
      if (!optImpl)
1947
0
        return None;
1948
0
      implements.push_back(**optImpl);
1949
0
    } while (checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type));
1950
0
  }
1951
1952
0
  if (!need(
1953
0
          TokenKind::l_brace,
1954
0
          "in declared class",
1955
0
          "start of declaration",
1956
0
          start))
1957
0
    return None;
1958
1959
0
  auto optBody = parseObjectTypeAnnotationFlow(
1960
0
      AllowProtoProperty::Yes,
1961
0
      AllowStaticProperty::Yes,
1962
0
      AllowSpreadProperty::No);
1963
0
  if (!optBody)
1964
0
    return None;
1965
1966
0
  return setLocation(
1967
0
      start,
1968
0
      *optBody,
1969
0
      new (context_) ESTree::DeclareClassNode(
1970
0
          id,
1971
0
          typeParams,
1972
0
          std::move(extends),
1973
0
          std::move(implements),
1974
0
          std::move(mixins),
1975
0
          *optBody));
1976
0
}
1977
1978
Optional<ESTree::Node *> JSParserImpl::parseExportTypeDeclarationFlow(
1979
0
    SMLoc startLoc) {
1980
0
  assert(check(typeIdent_));
1981
0
  SMLoc typeIdentLoc = advance().Start;
1982
1983
0
  if (checkAndEat(TokenKind::star)) {
1984
    // export type * FromClause;
1985
    //               ^
1986
0
    auto optFromClause = parseFromClause();
1987
0
    if (!optFromClause) {
1988
0
      return None;
1989
0
    }
1990
0
    if (!eatSemi()) {
1991
0
      return None;
1992
0
    }
1993
0
    return setLocation(
1994
0
        startLoc,
1995
0
        getPrevTokenEndLoc(),
1996
0
        new (context_)
1997
0
            ESTree::ExportAllDeclarationNode(*optFromClause, typeIdent_));
1998
0
  }
1999
2000
0
  if (check(TokenKind::l_brace)) {
2001
0
    ESTree::NodeList specifiers{};
2002
0
    llvh::SmallVector<SMRange, 2> invalids{};
2003
2004
0
    auto optExportClause = parseExportClause(specifiers, invalids);
2005
0
    if (!optExportClause) {
2006
0
      return None;
2007
0
    }
2008
2009
0
    ESTree::Node *source = nullptr;
2010
0
    if (check(fromIdent_)) {
2011
      // export ExportClause FromClause ;
2012
0
      auto optFromClause = parseFromClause();
2013
0
      if (!optFromClause) {
2014
0
        return None;
2015
0
      }
2016
0
      source = *optFromClause;
2017
0
    } else {
2018
      // export ExportClause ;
2019
      // ES9.0 15.2.3.1
2020
      // When there is no FromClause, any ranges added to invalids are
2021
      // actually invalid, and should be reported as errors.
2022
0
      for (const SMRange &range : invalids) {
2023
0
        error(range, "Invalid exported name");
2024
0
      }
2025
0
    }
2026
2027
0
    if (!eatSemi()) {
2028
0
      return None;
2029
0
    }
2030
2031
0
    return setLocation(
2032
0
        startLoc,
2033
0
        getPrevTokenEndLoc(),
2034
0
        new (context_) ESTree::ExportNamedDeclarationNode(
2035
0
            nullptr, std::move(specifiers), source, typeIdent_));
2036
0
  }
2037
2038
0
  if (check(TokenKind::identifier)) {
2039
0
    auto optAlias = parseTypeAliasFlow(typeIdentLoc, TypeAliasKind::None);
2040
0
    if (!optAlias)
2041
0
      return None;
2042
0
    return setLocation(
2043
0
        startLoc,
2044
0
        *optAlias,
2045
0
        new (context_) ESTree::ExportNamedDeclarationNode(
2046
0
            *optAlias, {}, nullptr, typeIdent_));
2047
0
  }
2048
2049
0
  errorExpected(
2050
0
      {TokenKind::star, TokenKind::l_brace, TokenKind::identifier},
2051
0
      "in export type declaration",
2052
0
      "start of export",
2053
0
      startLoc);
2054
0
  return None;
2055
0
}
2056
2057
0
Optional<ESTree::Node *> JSParserImpl::parseDeclareExportFlow(SMLoc start) {
2058
0
  assert(check(TokenKind::rw_export));
2059
0
  advance(JSLexer::GrammarContext::Type);
2060
0
  SMLoc declareStart = tok_->getStartLoc();
2061
2062
0
  if (checkAndEat(TokenKind::rw_default, JSLexer::GrammarContext::Type)) {
2063
0
    declareStart = tok_->getStartLoc();
2064
0
    if (check(TokenKind::rw_function)) {
2065
0
      auto optFunc = parseDeclareFunctionFlow(declareStart);
2066
0
      if (!optFunc)
2067
0
        return None;
2068
0
      return setLocation(
2069
0
          start,
2070
0
          *optFunc,
2071
0
          new (context_) ESTree::DeclareExportDeclarationNode(
2072
0
              *optFunc, {}, nullptr, true));
2073
0
    }
2074
0
    if (context_.getParseFlowComponentSyntax() && checkHookDeclarationFlow()) {
2075
0
      auto optFunc = parseDeclareHookFlow(declareStart);
2076
0
      if (!optFunc)
2077
0
        return None;
2078
0
      return setLocation(
2079
0
          start,
2080
0
          *optFunc,
2081
0
          new (context_) ESTree::DeclareExportDeclarationNode(
2082
0
              *optFunc, {}, nullptr, true));
2083
0
    }
2084
0
    if (context_.getParseFlowComponentSyntax() &&
2085
0
        checkComponentDeclarationFlow()) {
2086
0
      auto optComponent =
2087
0
          parseComponentDeclarationFlow(start, /* declare */ true);
2088
0
      if (!optComponent)
2089
0
        return None;
2090
0
      return setLocation(
2091
0
          start,
2092
0
          *optComponent,
2093
0
          new (context_) ESTree::DeclareExportDeclarationNode(
2094
0
              *optComponent, {}, nullptr, true));
2095
0
    }
2096
0
    if (check(TokenKind::rw_class)) {
2097
0
      auto optClass = parseDeclareClassFlow(declareStart);
2098
0
      if (!optClass)
2099
0
        return None;
2100
0
      return setLocation(
2101
0
          start,
2102
0
          *optClass,
2103
0
          new (context_) ESTree::DeclareExportDeclarationNode(
2104
0
              *optClass, {}, nullptr, true));
2105
0
    }
2106
0
    auto optType = parseTypeAnnotationFlow();
2107
0
    if (!optType)
2108
0
      return None;
2109
0
    if (!eatSemi())
2110
0
      return None;
2111
0
    return setLocation(
2112
0
        start,
2113
0
        getPrevTokenEndLoc(),
2114
0
        new (context_)
2115
0
            ESTree::DeclareExportDeclarationNode(*optType, {}, nullptr, true));
2116
0
  }
2117
2118
0
  if (check(TokenKind::rw_function)) {
2119
0
    auto optFunc = parseDeclareFunctionFlow(declareStart);
2120
0
    if (!optFunc)
2121
0
      return None;
2122
0
    return setLocation(
2123
0
        start,
2124
0
        *optFunc,
2125
0
        new (context_)
2126
0
            ESTree::DeclareExportDeclarationNode(*optFunc, {}, nullptr, false));
2127
0
  }
2128
2129
0
  if (context_.getParseFlowComponentSyntax() && checkHookDeclarationFlow()) {
2130
0
    auto optFunc = parseDeclareHookFlow(declareStart);
2131
0
    if (!optFunc)
2132
0
      return None;
2133
0
    return setLocation(
2134
0
        start,
2135
0
        *optFunc,
2136
0
        new (context_)
2137
0
            ESTree::DeclareExportDeclarationNode(*optFunc, {}, nullptr, false));
2138
0
  }
2139
2140
0
  if (check(TokenKind::rw_class)) {
2141
0
    auto optClass = parseDeclareClassFlow(declareStart);
2142
0
    if (!optClass)
2143
0
      return None;
2144
0
    return setLocation(
2145
0
        start,
2146
0
        *optClass,
2147
0
        new (context_) ESTree::DeclareExportDeclarationNode(
2148
0
            *optClass, {}, nullptr, false));
2149
0
  }
2150
2151
0
  if (context_.getParseFlowComponentSyntax() &&
2152
0
      checkComponentDeclarationFlow()) {
2153
0
    auto optComponent =
2154
0
        parseComponentDeclarationFlow(start, /* declare */ true);
2155
0
    if (!optComponent)
2156
0
      return None;
2157
0
    return setLocation(
2158
0
        start,
2159
0
        *optComponent,
2160
0
        new (context_) ESTree::DeclareExportDeclarationNode(
2161
0
            *optComponent, {}, nullptr, false));
2162
0
  }
2163
2164
0
  if (check(TokenKind::rw_enum)) {
2165
0
    auto optEnum = parseEnumDeclarationFlow(start, /* declare */ true);
2166
0
    if (!optEnum)
2167
0
      return None;
2168
0
    return setLocation(
2169
0
        start,
2170
0
        *optEnum,
2171
0
        new (context_)
2172
0
            ESTree::DeclareExportDeclarationNode(*optEnum, {}, nullptr, false));
2173
0
  }
2174
2175
0
  if (checkN(TokenKind::rw_var, TokenKind::rw_const, letIdent_)) {
2176
0
    ESTree::NodeLabel kind = tok_->getResWordOrIdentifier();
2177
0
    SMLoc varStart = advance(JSLexer::GrammarContext::Type).Start;
2178
0
    auto optIdent = parseBindingIdentifier(Param{});
2179
0
    if (!optIdent) {
2180
0
      errorExpected(
2181
0
          TokenKind::identifier,
2182
0
          "in var declaration",
2183
0
          "start of declaration",
2184
0
          start);
2185
0
      return None;
2186
0
    }
2187
0
    if (!(*optIdent)->_typeAnnotation) {
2188
0
      error(
2189
0
          (*optIdent)->getSourceRange(),
2190
0
          "expected type annotation on declared var");
2191
0
    }
2192
0
    if (!eatSemi())
2193
0
      return None;
2194
2195
0
    SMLoc end = getPrevTokenEndLoc();
2196
0
    return setLocation(
2197
0
        start,
2198
0
        end,
2199
0
        new (context_) ESTree::DeclareExportDeclarationNode(
2200
0
            setLocation(
2201
0
                varStart,
2202
0
                end,
2203
0
                new (context_) ESTree::DeclareVariableNode(*optIdent, kind)),
2204
0
            {},
2205
0
            nullptr,
2206
0
            false));
2207
0
  }
2208
2209
0
  if (checkAndEat(opaqueIdent_, JSLexer::GrammarContext::Type)) {
2210
0
    if (!check(typeIdent_)) {
2211
0
      error(tok_->getStartLoc(), "'type' required in opaque type declaration");
2212
0
      return None;
2213
0
    }
2214
0
    advance(JSLexer::GrammarContext::Type);
2215
0
    auto optType =
2216
0
        parseTypeAliasFlow(declareStart, TypeAliasKind::DeclareOpaque);
2217
0
    if (!optType)
2218
0
      return None;
2219
0
    return setLocation(
2220
0
        start,
2221
0
        *optType,
2222
0
        new (context_)
2223
0
            ESTree::DeclareExportDeclarationNode(*optType, {}, nullptr, false));
2224
0
  }
2225
2226
0
  if (check(typeIdent_)) {
2227
0
    advance(JSLexer::GrammarContext::Type);
2228
0
    auto optType = parseTypeAliasFlow(declareStart, TypeAliasKind::None);
2229
0
    if (!optType)
2230
0
      return None;
2231
0
    return setLocation(
2232
0
        start,
2233
0
        *optType,
2234
0
        new (context_)
2235
0
            ESTree::DeclareExportDeclarationNode(*optType, {}, nullptr, false));
2236
0
  }
2237
2238
0
  if (checkN(TokenKind::rw_interface, interfaceIdent_)) {
2239
0
    auto optInterface = parseInterfaceDeclarationFlow();
2240
0
    if (!optInterface)
2241
0
      return None;
2242
0
    return setLocation(
2243
0
        start,
2244
0
        *optInterface,
2245
0
        new (context_) ESTree::DeclareExportDeclarationNode(
2246
0
            *optInterface, {}, nullptr, false));
2247
0
  }
2248
2249
0
  if (checkAndEat(TokenKind::star, JSLexer::GrammarContext::Type)) {
2250
    // declare export * from 'foo';
2251
    //                  ^
2252
0
    if (!check(fromIdent_)) {
2253
0
      error(
2254
0
          tok_->getStartLoc(), "expected 'from' clause in export declaration");
2255
0
      return None;
2256
0
    }
2257
0
    auto optSource = parseFromClause();
2258
0
    if (!optSource)
2259
0
      return None;
2260
0
    if (!eatSemi())
2261
0
      return None;
2262
0
    return setLocation(
2263
0
        start,
2264
0
        getPrevTokenEndLoc(),
2265
0
        new (context_) ESTree::DeclareExportAllDeclarationNode(*optSource));
2266
0
  }
2267
2268
0
  if (!need(
2269
0
          TokenKind::l_brace, "in export specifier", "start of declare", start))
2270
0
    return None;
2271
2272
0
  ESTree::NodeList specifiers{};
2273
0
  llvh::SmallVector<SMRange, 2> invalids{};
2274
0
  if (!parseExportClause(specifiers, invalids))
2275
0
    return None;
2276
2277
0
  ESTree::Node *source = nullptr;
2278
0
  if (check(fromIdent_)) {
2279
0
    auto optSource = parseFromClause();
2280
0
    if (!optSource)
2281
0
      return None;
2282
0
    source = *optSource;
2283
0
  }
2284
2285
0
  if (!eatSemi())
2286
0
    return None;
2287
2288
0
  return setLocation(
2289
0
      start,
2290
0
      getPrevTokenEndLoc(),
2291
0
      new (context_) ESTree::DeclareExportDeclarationNode(
2292
0
          nullptr, std::move(specifiers), source, false));
2293
0
}
2294
2295
Optional<ESTree::Node *> JSParserImpl::parseReturnTypeAnnotationFlow(
2296
    Optional<SMLoc> wrappedStart,
2297
0
    AllowAnonFunctionType allowAnonFunctionType) {
2298
0
  SMLoc start = tok_->getStartLoc();
2299
0
  ESTree::Node *returnType = nullptr;
2300
0
  if (check(assertsIdent_)) {
2301
    // TypePredicate (asserts = true) or TypeAnnotation:
2302
    //   TypeAnnotation
2303
    //   asserts IdentifierName
2304
    //   asserts IdentifierName is TypeAnnotation
2305
0
    auto optType = parseTypeAnnotationFlow(None, allowAnonFunctionType);
2306
0
    if (!optType)
2307
0
      return None;
2308
2309
0
    if (check(TokenKind::identifier)) {
2310
      // Validate the "asserts" token was an identifier not a more complex type.
2311
0
      auto optId = reparseTypeAnnotationAsIdentifierFlow(*optType);
2312
0
      if (!optId)
2313
0
        return None;
2314
0
      ESTree::Node *id = setLocation(
2315
0
          tok_,
2316
0
          tok_,
2317
0
          new (context_)
2318
0
              ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
2319
0
      advance(JSLexer::GrammarContext::Type);
2320
0
      ESTree::Node *typeAnnotation = nullptr;
2321
0
      if (checkAndEat(isIdent_, JSLexer::GrammarContext::Type)) {
2322
        // assert IdentifierName is TypeAnnotation
2323
        //                          ^
2324
0
        auto optType = parseTypeAnnotationFlow(None, allowAnonFunctionType);
2325
0
        if (!optType)
2326
0
          return None;
2327
0
        typeAnnotation = *optType;
2328
0
      }
2329
0
      returnType = setLocation(
2330
0
          start,
2331
0
          getPrevTokenEndLoc(),
2332
0
          new (context_)
2333
0
              ESTree::TypePredicateNode(id, typeAnnotation, assertsIdent_));
2334
0
    } else {
2335
0
      returnType = *optType;
2336
0
    }
2337
0
  } else if (check(impliesIdent_)) {
2338
    // TypePredicate (implies = true) or TypeAnnotation:
2339
    //   TypeAnnotation
2340
    //   implies IdentifierName is TypeAnnotation
2341
2342
    //   implies IdentifierName is TypeAnnotation
2343
    //   ^
2344
0
    auto optType = parseTypeAnnotationFlow(None, allowAnonFunctionType);
2345
0
    if (!optType)
2346
0
      return None;
2347
2348
0
    if (check(TokenKind::identifier, TokenKind::rw_this)) {
2349
      // Validate the "implies" token was an identifier not a more complex type.
2350
0
      if (auto *generic = dyn_cast<ESTree::GenericTypeAnnotationNode>(*optType);
2351
0
          !(generic && !generic->_typeParameters)) {
2352
0
        error(
2353
0
            tok_->getStartLoc(),
2354
0
            "invalid return annotation. 'implies' type guard needs to be followed by identifier");
2355
0
        return None;
2356
0
      }
2357
2358
      //   implies IdentifierName is TypeAnnotation
2359
      //           ^
2360
0
      ESTree::Node *id = setLocation(
2361
0
          tok_,
2362
0
          tok_,
2363
0
          new (context_) ESTree::IdentifierNode(
2364
0
              tok_->getResWordOrIdentifier(), nullptr, false));
2365
0
      advance(JSLexer::GrammarContext::Type);
2366
2367
      //   implies IdentifierName is TypeAnnotation
2368
      //                          ^
2369
0
      if (!checkAndEat(isIdent_, JSLexer::GrammarContext::Type)) {
2370
0
        error(
2371
0
            tok_->getStartLoc(),
2372
0
            "expecting 'is' after parameter of 'implies' type guard");
2373
0
        return None;
2374
0
      }
2375
      //   implies IdentifierName is TypeAnnotation
2376
      //                             ^
2377
0
      auto optTypeT = parseTypeAnnotationFlow(None, allowAnonFunctionType);
2378
0
      if (!optTypeT)
2379
0
        return None;
2380
0
      returnType = setLocation(
2381
0
          start,
2382
0
          getPrevTokenEndLoc(),
2383
0
          new (context_)
2384
0
              ESTree::TypePredicateNode(id, *optTypeT, impliesIdent_));
2385
0
    } else {
2386
      // implies (as type -- okay)
2387
0
      returnType = *optType;
2388
0
    }
2389
0
  } else {
2390
    // TypePredicate (asserts = false && implies = false) or TypeAnnotation:
2391
    //   TypeAnnotation
2392
    //   IdentifierName is TypeAnnotation
2393
2394
0
    auto optType = parseTypeAnnotationFlow(None, allowAnonFunctionType);
2395
0
    if (!optType)
2396
0
      return None;
2397
2398
0
    if (checkAndEat(isIdent_, JSLexer::GrammarContext::Type)) {
2399
0
      auto optId = reparseTypeAnnotationAsIdentifierFlow(*optType);
2400
0
      if (!optId)
2401
0
        return None;
2402
0
      auto optType = parseTypeAnnotationFlow(None, allowAnonFunctionType);
2403
0
      if (!optType)
2404
0
        return None;
2405
0
      returnType = setLocation(
2406
0
          start,
2407
0
          getPrevTokenEndLoc(),
2408
0
          new (context_) ESTree::TypePredicateNode(*optId, *optType, nullptr));
2409
0
    } else {
2410
0
      returnType = *optType;
2411
0
    }
2412
0
  }
2413
2414
0
  if (wrappedStart) {
2415
0
    return setLocation(
2416
0
        *wrappedStart,
2417
0
        getPrevTokenEndLoc(),
2418
0
        new (context_) ESTree::TypeAnnotationNode(returnType));
2419
0
  }
2420
0
  return returnType;
2421
0
}
2422
2423
0
Optional<ESTree::Node *> JSParserImpl::parseTypeAnnotationBeforeColonFlow() {
2424
  // If the identifier name is a known keyword we need to lookahead to see if
2425
  // its a type or an identifier otherwise it could fail to parse.
2426
0
  if (check(TokenKind::identifier) &&
2427
0
      (context_.getParseFlowComponentSyntax())) {
2428
0
    if ((tok_->getResWordOrIdentifier() == componentIdent_) ||
2429
0
        (tok_->getResWordOrIdentifier() == hookIdent_) ||
2430
0
        (tok_->getResWordOrIdentifier() == rendersIdent_ &&
2431
0
         !tok_->checkFollowingCharacter('?'))) {
2432
0
      OptValue<TokenKind> optNext = lexer_.lookahead1(None);
2433
0
      if (optNext.hasValue() &&
2434
0
          (*optNext == TokenKind::colon || *optNext == TokenKind::question)) {
2435
0
        auto id = setLocation(
2436
0
            tok_,
2437
0
            tok_,
2438
0
            new (context_) ESTree::GenericTypeAnnotationNode(
2439
0
                setLocation(
2440
0
                    tok_,
2441
0
                    tok_,
2442
0
                    new (context_) ESTree::IdentifierNode(
2443
0
                        tok_->getResWordOrIdentifier(), nullptr, false)),
2444
0
                nullptr));
2445
0
        advance(JSLexer::GrammarContext::Type);
2446
0
        return id;
2447
0
      }
2448
0
    } else if (
2449
0
        tok_->getResWordOrIdentifier() == rendersIdent_ &&
2450
0
        tok_->checkFollowingCharacter('?')) {
2451
0
      SMLoc startLoc = tok_->getStartLoc();
2452
0
      auto id = setLocation(
2453
0
          tok_,
2454
0
          tok_,
2455
0
          new (context_) ESTree::GenericTypeAnnotationNode(
2456
0
              setLocation(
2457
0
                  tok_,
2458
0
                  tok_,
2459
0
                  new (context_) ESTree::IdentifierNode(
2460
0
                      tok_->getResWordOrIdentifier(), nullptr, false)),
2461
0
              nullptr));
2462
0
      advance(JSLexer::GrammarContext::Type);
2463
0
      OptValue<TokenKind> optNext = lexer_.lookahead1(None);
2464
0
      if (optNext.hasValue() && (*optNext == TokenKind::colon)) {
2465
0
        return id;
2466
0
      } else {
2467
0
        if (!eat(
2468
0
                TokenKind::question,
2469
0
                JSLexer::GrammarContext::Type,
2470
0
                "in render type annotation",
2471
0
                "start of render type",
2472
0
                startLoc)) {
2473
0
          return None;
2474
0
        }
2475
0
        auto optBody = parsePrefixTypeAnnotationFlow();
2476
0
        if (!optBody)
2477
0
          return None;
2478
0
        return setLocation(
2479
0
            startLoc,
2480
0
            getPrevTokenEndLoc(),
2481
0
            new (context_)
2482
0
                ESTree::TypeOperatorNode(rendersMaybeOperator_, *optBody));
2483
0
      }
2484
0
    }
2485
0
  }
2486
2487
0
  return parseTypeAnnotationFlow();
2488
0
}
2489
2490
Optional<ESTree::Node *> JSParserImpl::parseTypeAnnotationFlow(
2491
    Optional<SMLoc> wrappedStart,
2492
0
    AllowAnonFunctionType allowAnonFunctionType) {
2493
0
  llvh::SaveAndRestore<bool> saveParam(
2494
0
      allowAnonFunctionType_,
2495
0
      allowAnonFunctionType == AllowAnonFunctionType::Yes);
2496
0
  auto optType = parseConditionalTypeAnnotationFlow();
2497
0
  if (!optType)
2498
0
    return None;
2499
0
  if (wrappedStart) {
2500
0
    return setLocation(
2501
0
        *wrappedStart,
2502
0
        getPrevTokenEndLoc(),
2503
0
        new (context_) ESTree::TypeAnnotationNode(*optType));
2504
0
  }
2505
0
  return *optType;
2506
0
}
2507
2508
0
Optional<ESTree::Node *> JSParserImpl::parseConditionalTypeAnnotationFlow() {
2509
0
  SMLoc start = tok_->getStartLoc();
2510
0
  llvh::SaveAndRestore<bool> saveParam(allowConditionalType_, true);
2511
0
  auto optCheck = parseUnionTypeAnnotationFlow();
2512
0
  if (!optCheck)
2513
0
    return None;
2514
0
  if (!checkAndEat(TokenKind::rw_extends, JSLexer::GrammarContext::Type)) {
2515
0
    return optCheck;
2516
0
  }
2517
0
  Optional<ESTree::Node *> optExtends;
2518
0
  {
2519
    // We need to enter the state of parsing the extends_type disallowing
2520
    // conditional types not wrapped by parantheses, so that the following
2521
    // sequence `A extends infer B extends C ? D : E` will be interpreted
2522
    // as `A extends (infer B extends C) ? D : E`.
2523
0
    llvh::SaveAndRestore<bool> saveParam(allowConditionalType_, false);
2524
0
    optExtends = parseUnionTypeAnnotationFlow();
2525
0
  }
2526
0
  if (!optExtends)
2527
0
    return None;
2528
2529
0
  if (!eat(
2530
0
          TokenKind::question,
2531
0
          JSLexer::GrammarContext::Type,
2532
0
          "in conditional type",
2533
0
          "start of type",
2534
0
          start))
2535
0
    return None;
2536
2537
0
  auto optTrue = parseTypeAnnotationFlow();
2538
0
  if (!optTrue)
2539
0
    return None;
2540
0
  if (!eat(
2541
0
          TokenKind::colon,
2542
0
          JSLexer::GrammarContext::Type,
2543
0
          "in conditional type",
2544
0
          "start of type",
2545
0
          start))
2546
0
    return None;
2547
2548
0
  auto optFalse = parseTypeAnnotationFlow();
2549
0
  if (!optFalse)
2550
0
    return None;
2551
2552
0
  return setLocation(
2553
0
      *optCheck,
2554
0
      getPrevTokenEndLoc(),
2555
0
      new (context_) ESTree::ConditionalTypeAnnotationNode(
2556
0
          *optCheck, *optExtends, *optTrue, *optFalse));
2557
0
}
2558
2559
0
Optional<ESTree::Node *> JSParserImpl::parseUnionTypeAnnotationFlow() {
2560
0
  SMLoc start = tok_->getStartLoc();
2561
0
  checkAndEat(TokenKind::pipe, JSLexer::GrammarContext::Type);
2562
2563
0
  auto optFirst = parseIntersectionTypeAnnotationFlow();
2564
0
  if (!optFirst)
2565
0
    return None;
2566
2567
0
  if (!check(TokenKind::pipe)) {
2568
    // Done with the union, move on.
2569
0
    return *optFirst;
2570
0
  }
2571
2572
0
  ESTree::NodeList types{};
2573
0
  types.push_back(**optFirst);
2574
2575
0
  while (checkAndEat(TokenKind::pipe, JSLexer::GrammarContext::Type)) {
2576
0
    auto optInt = parseIntersectionTypeAnnotationFlow();
2577
0
    if (!optInt)
2578
0
      return None;
2579
0
    types.push_back(**optInt);
2580
0
  }
2581
2582
0
  return setLocation(
2583
0
      start,
2584
0
      getPrevTokenEndLoc(),
2585
0
      new (context_) ESTree::UnionTypeAnnotationNode(std::move(types)));
2586
0
}
2587
2588
0
Optional<ESTree::Node *> JSParserImpl::parseIntersectionTypeAnnotationFlow() {
2589
0
  SMLoc start = tok_->getStartLoc();
2590
0
  checkAndEat(TokenKind::amp, JSLexer::GrammarContext::Type);
2591
2592
0
  auto optFirst = parseAnonFunctionWithoutParensTypeAnnotationFlow();
2593
0
  if (!optFirst)
2594
0
    return None;
2595
2596
0
  if (!check(TokenKind::amp)) {
2597
    // Done with the union, move on.
2598
0
    return *optFirst;
2599
0
  }
2600
2601
0
  ESTree::NodeList types{};
2602
0
  types.push_back(**optFirst);
2603
2604
0
  while (checkAndEat(TokenKind::amp, JSLexer::GrammarContext::Type)) {
2605
0
    auto optInt = parseAnonFunctionWithoutParensTypeAnnotationFlow();
2606
0
    if (!optInt)
2607
0
      return None;
2608
0
    types.push_back(**optInt);
2609
0
  }
2610
2611
0
  return setLocation(
2612
0
      start,
2613
0
      getPrevTokenEndLoc(),
2614
0
      new (context_) ESTree::IntersectionTypeAnnotationNode(std::move(types)));
2615
0
}
2616
2617
Optional<ESTree::Node *>
2618
0
JSParserImpl::parseAnonFunctionWithoutParensTypeAnnotationFlow() {
2619
0
  SMLoc start = tok_->getStartLoc();
2620
0
  auto optParam = parsePrefixTypeAnnotationFlow();
2621
0
  if (!optParam)
2622
0
    return None;
2623
2624
0
  if (allowAnonFunctionType_ && check(TokenKind::equalgreater)) {
2625
    // ParamType => ReturnType
2626
    //           ^
2627
0
    ESTree::NodeList params{};
2628
    // "Reparse" the param into a FunctionTypeParam so it can be used for
2629
    // parseFunctionTypeAnnotationWithParamsFlow.
2630
0
    params.push_back(*setLocation(
2631
0
        *optParam,
2632
0
        *optParam,
2633
0
        new (context_) ESTree::FunctionTypeParamNode(
2634
0
            /* name */ nullptr, *optParam, /* optional */ false)));
2635
0
    ESTree::Node *rest = nullptr;
2636
0
    ESTree::Node *typeParams = nullptr;
2637
0
    return parseFunctionTypeAnnotationWithParamsFlow(
2638
0
        start, std::move(params), nullptr, rest, typeParams, /* hook */ false);
2639
0
  }
2640
2641
0
  return *optParam;
2642
0
}
2643
2644
0
Optional<ESTree::Node *> JSParserImpl::parsePrefixTypeAnnotationFlow() {
2645
0
  SMLoc start = tok_->getStartLoc();
2646
0
  if (checkAndEat(TokenKind::question, JSLexer::GrammarContext::Type)) {
2647
0
    auto optPrefix = parsePrefixTypeAnnotationFlow();
2648
0
    if (!optPrefix)
2649
0
      return None;
2650
0
    return setLocation(
2651
0
        start,
2652
0
        getPrevTokenEndLoc(),
2653
0
        new (context_) ESTree::NullableTypeAnnotationNode(*optPrefix));
2654
0
  }
2655
0
  return parsePostfixTypeAnnotationFlow();
2656
0
}
2657
2658
0
Optional<ESTree::Node *> JSParserImpl::parsePostfixTypeAnnotationFlow() {
2659
0
  SMLoc start = tok_->getStartLoc();
2660
0
  auto optPrimary = parsePrimaryTypeAnnotationFlow();
2661
0
  if (!optPrimary)
2662
0
    return None;
2663
2664
0
  ESTree::Node *result = *optPrimary;
2665
0
  bool seenOptionalIndexedAccess = false;
2666
2667
0
  while (check(TokenKind::l_square, TokenKind::questiondot) &&
2668
0
         !lexer_.isNewLineBeforeCurrentToken()) {
2669
0
    bool optional = checkAndEat(TokenKind::questiondot);
2670
0
    seenOptionalIndexedAccess = seenOptionalIndexedAccess || optional;
2671
2672
0
    if (!eat(
2673
0
            TokenKind::l_square,
2674
0
            JSLexer::GrammarContext::Type,
2675
0
            "in indexed access type or postfix array type syntax",
2676
0
            "start of a type",
2677
0
            start))
2678
0
      return None;
2679
2680
0
    if (!optional &&
2681
0
        checkAndEat(TokenKind::r_square, JSLexer::GrammarContext::Type)) {
2682
      // Legacy Array syntax `T[]`
2683
0
      result = setLocation(
2684
0
          start,
2685
0
          getPrevTokenEndLoc(),
2686
0
          new (context_) ESTree::ArrayTypeAnnotationNode(result));
2687
0
    } else {
2688
      // Indexed Access `T[K]` (`T?.[K]` if `optional`)
2689
0
      auto optIndexType = parseTypeAnnotationFlow();
2690
0
      if (!optIndexType)
2691
0
        return None;
2692
0
      if (!need(
2693
0
              TokenKind::r_square,
2694
0
              "in indexed access type",
2695
0
              "start of type",
2696
0
              start))
2697
0
        return None;
2698
0
      if (seenOptionalIndexedAccess) {
2699
0
        result = setLocation(
2700
0
            start,
2701
0
            advance(JSLexer::GrammarContext::Type).End,
2702
0
            new (context_) ESTree::OptionalIndexedAccessTypeNode(
2703
0
                result, *optIndexType, optional));
2704
0
      } else {
2705
0
        result = setLocation(
2706
0
            start,
2707
0
            advance(JSLexer::GrammarContext::Type).End,
2708
0
            new (context_)
2709
0
                ESTree::IndexedAccessTypeNode(result, *optIndexType));
2710
0
      }
2711
0
    }
2712
0
  }
2713
2714
0
  return result;
2715
0
}
2716
2717
0
Optional<ESTree::Node *> JSParserImpl::parsePrimaryTypeAnnotationFlow() {
2718
0
  SMLoc start = tok_->getStartLoc();
2719
0
  switch (tok_->getKind()) {
2720
0
    case TokenKind::star:
2721
0
      return setLocation(
2722
0
          start,
2723
0
          advance(JSLexer::GrammarContext::Type).End,
2724
0
          new (context_) ESTree::ExistsTypeAnnotationNode());
2725
0
    case TokenKind::less:
2726
0
      return parseFunctionTypeAnnotationFlow();
2727
0
    case TokenKind::l_paren:
2728
0
      return parseFunctionOrGroupTypeAnnotationFlow();
2729
0
    case TokenKind::l_brace:
2730
0
    case TokenKind::l_bracepipe:
2731
0
      return parseObjectTypeAnnotationFlow(
2732
0
          AllowProtoProperty::No,
2733
0
          AllowStaticProperty::No,
2734
0
          AllowSpreadProperty::Yes);
2735
0
    case TokenKind::rw_interface: {
2736
0
      advance(JSLexer::GrammarContext::Type);
2737
0
      ESTree::NodeList extends{};
2738
0
      auto optBody = parseInterfaceTailFlow(start, extends);
2739
0
      if (!optBody)
2740
0
        return None;
2741
0
      return setLocation(
2742
0
          start,
2743
0
          *optBody,
2744
0
          new (context_) ESTree::InterfaceTypeAnnotationNode(
2745
0
              std::move(extends), *optBody));
2746
0
    }
2747
0
    case TokenKind::rw_typeof:
2748
0
      return parseTypeofTypeAnnotationFlow();
2749
2750
0
    case TokenKind::l_square:
2751
0
      return parseTupleTypeAnnotationFlow();
2752
0
    case TokenKind::rw_static:
2753
0
    case TokenKind::rw_this:
2754
0
    case TokenKind::identifier:
2755
0
      if (tok_->getResWordOrIdentifier() == anyIdent_) {
2756
0
        return setLocation(
2757
0
            start,
2758
0
            advance(JSLexer::GrammarContext::Type).End,
2759
0
            new (context_) ESTree::AnyTypeAnnotationNode());
2760
0
      }
2761
0
      if (tok_->getResWordOrIdentifier() == mixedIdent_) {
2762
0
        return setLocation(
2763
0
            start,
2764
0
            advance(JSLexer::GrammarContext::Type).End,
2765
0
            new (context_) ESTree::MixedTypeAnnotationNode());
2766
0
      }
2767
0
      if (tok_->getResWordOrIdentifier() == emptyIdent_) {
2768
0
        return setLocation(
2769
0
            start,
2770
0
            advance(JSLexer::GrammarContext::Type).End,
2771
0
            new (context_) ESTree::EmptyTypeAnnotationNode());
2772
0
      }
2773
0
      if (tok_->getResWordOrIdentifier() == booleanIdent_ ||
2774
0
          tok_->getResWordOrIdentifier() == boolIdent_) {
2775
0
        return setLocation(
2776
0
            start,
2777
0
            advance(JSLexer::GrammarContext::Type).End,
2778
0
            new (context_) ESTree::BooleanTypeAnnotationNode());
2779
0
      }
2780
0
      if (tok_->getResWordOrIdentifier() == numberIdent_) {
2781
0
        return setLocation(
2782
0
            start,
2783
0
            advance(JSLexer::GrammarContext::Type).End,
2784
0
            new (context_) ESTree::NumberTypeAnnotationNode());
2785
0
      }
2786
0
      if (tok_->getResWordOrIdentifier() == symbolIdent_) {
2787
0
        return setLocation(
2788
0
            start,
2789
0
            advance(JSLexer::GrammarContext::Type).End,
2790
0
            new (context_) ESTree::SymbolTypeAnnotationNode());
2791
0
      }
2792
0
      if (tok_->getResWordOrIdentifier() == stringIdent_) {
2793
0
        return setLocation(
2794
0
            start,
2795
0
            advance(JSLexer::GrammarContext::Type).End,
2796
0
            new (context_) ESTree::StringTypeAnnotationNode());
2797
0
      }
2798
0
      if (tok_->getResWordOrIdentifier() == bigintIdent_) {
2799
0
        return setLocation(
2800
0
            start,
2801
0
            advance(JSLexer::GrammarContext::Type).End,
2802
0
            new (context_) ESTree::BigIntTypeAnnotationNode());
2803
0
      }
2804
0
      if (tok_->getResWordOrIdentifier() == keyofIdent_) {
2805
0
        advance(JSLexer::GrammarContext::Type);
2806
0
        auto optBody = parsePrefixTypeAnnotationFlow();
2807
0
        if (!optBody)
2808
0
          return None;
2809
0
        return setLocation(
2810
0
            start,
2811
0
            getPrevTokenEndLoc(),
2812
0
            new (context_) ESTree::KeyofTypeAnnotationNode(*optBody));
2813
0
      }
2814
0
      if (context_.getParseFlowComponentSyntax() &&
2815
0
          tok_->getResWordOrIdentifier() == rendersIdent_) {
2816
0
        auto optTypeOperator = parseRenderTypeOperator();
2817
0
        auto optBody = parsePrefixTypeAnnotationFlow();
2818
0
        if (!optBody || !optTypeOperator)
2819
0
          return None;
2820
0
        return setLocation(
2821
0
            start,
2822
0
            getPrevTokenEndLoc(),
2823
0
            new (context_)
2824
0
                ESTree::TypeOperatorNode(*optTypeOperator, *optBody));
2825
0
      }
2826
0
      if (context_.getParseFlowComponentSyntax() &&
2827
0
          tok_->getResWordOrIdentifier() == componentIdent_) {
2828
0
        auto optComponent = parseComponentTypeAnnotationFlow();
2829
0
        if (!optComponent)
2830
0
          return None;
2831
0
        return *optComponent;
2832
0
      }
2833
0
      if (context_.getParseFlowComponentSyntax() &&
2834
0
          tok_->getResWordOrIdentifier() == hookIdent_) {
2835
0
        auto optHook = parseHookTypeAnnotationFlow();
2836
0
        if (!optHook)
2837
0
          return None;
2838
0
        return *optHook;
2839
0
      }
2840
0
      if (tok_->getResWordOrIdentifier() == interfaceIdent_) {
2841
0
        advance(JSLexer::GrammarContext::Type);
2842
0
        ESTree::NodeList extends{};
2843
0
        auto optBody = parseInterfaceTailFlow(start, extends);
2844
0
        if (!optBody)
2845
0
          return None;
2846
0
        return setLocation(
2847
0
            start,
2848
0
            *optBody,
2849
0
            new (context_) ESTree::InterfaceTypeAnnotationNode(
2850
0
                std::move(extends), *optBody));
2851
0
      }
2852
0
      if (tok_->getResWordOrIdentifier() == inferIdent_) {
2853
0
        advance(JSLexer::GrammarContext::Type);
2854
2855
0
        if (!need(TokenKind::identifier, "in type parameter", nullptr, {}))
2856
0
          return None;
2857
0
        UniqueString *name = tok_->getIdentifier();
2858
0
        advance(JSLexer::GrammarContext::Type);
2859
2860
0
        ESTree::Node *bound = nullptr;
2861
0
        if (check(TokenKind::rw_extends)) {
2862
          // When we see an extends keyword,
2863
          // we enter the parsing logic that might need backtracking.
2864
          //
2865
          // For `infer A extends B ...`, is the `extends B` part of an infer
2866
          // type, or part of a larger conditional type like `infer A extends B
2867
          // ? C : D`?
2868
          //
2869
          // We don't know, so we assume it's part of the infer type for now,
2870
          // and later backtrack if the assumption is wrong.
2871
0
          JSLexer::SavePoint savePoint{&lexer_};
2872
0
          advance(JSLexer::GrammarContext::Type);
2873
0
          auto parsedBound = parseUnionTypeAnnotationFlow();
2874
0
          if ((allowConditionalType_ && check(TokenKind::question)) ||
2875
0
              !parsedBound) {
2876
            // If we look ahead and see `?`, it might be the case that we are
2877
            // parsing a conditional type like `infer A extends B ? C : D`. If
2878
            // the current context allow parsing conditional type, then we must
2879
            // backtrack so that only `infer A` is treated as part of the infer
2880
            // type.
2881
            //
2882
            // Of course, if we fail to parse the type after extends, we also
2883
            // need to backtrack.
2884
0
            savePoint.restore();
2885
0
          } else {
2886
0
            bound = *parsedBound;
2887
0
          }
2888
0
        }
2889
2890
0
        return setLocation(
2891
0
            start,
2892
0
            getPrevTokenEndLoc(),
2893
0
            new (context_) ESTree::InferTypeAnnotationNode(setLocation(
2894
0
                start,
2895
0
                getPrevTokenEndLoc(),
2896
0
                new (context_) ESTree::TypeParameterNode(
2897
0
                    name, false, bound, nullptr, nullptr, true))));
2898
0
      }
2899
2900
0
      {
2901
0
        auto optGeneric = parseGenericTypeFlow();
2902
0
        if (!optGeneric)
2903
0
          return None;
2904
0
        return *optGeneric;
2905
0
      }
2906
2907
0
    case TokenKind::rw_null:
2908
0
      return setLocation(
2909
0
          start,
2910
0
          advance(JSLexer::GrammarContext::Type).End,
2911
0
          new (context_) ESTree::NullLiteralTypeAnnotationNode());
2912
2913
0
    case TokenKind::rw_void:
2914
0
      return setLocation(
2915
0
          start,
2916
0
          advance(JSLexer::GrammarContext::Type).End,
2917
0
          new (context_) ESTree::VoidTypeAnnotationNode());
2918
2919
0
    case TokenKind::string_literal: {
2920
0
      UniqueString *str = tok_->getStringLiteral();
2921
0
      UniqueString *raw = lexer_.getStringLiteral(tok_->inputStr());
2922
0
      return setLocation(
2923
0
          start,
2924
0
          advance(JSLexer::GrammarContext::Type).End,
2925
0
          new (context_) ESTree::StringLiteralTypeAnnotationNode(str, raw));
2926
0
    }
2927
2928
0
    case TokenKind::numeric_literal: {
2929
0
      double value = tok_->getNumericLiteral();
2930
0
      UniqueString *raw = lexer_.getStringLiteral(tok_->inputStr());
2931
0
      return setLocation(
2932
0
          start,
2933
0
          advance(JSLexer::GrammarContext::Type).End,
2934
0
          new (context_) ESTree::NumberLiteralTypeAnnotationNode(value, raw));
2935
0
    }
2936
2937
0
    case TokenKind::bigint_literal: {
2938
0
      UniqueString *raw = tok_->getBigIntLiteral();
2939
0
      return setLocation(
2940
0
          start,
2941
0
          advance(JSLexer::GrammarContext::Type).End,
2942
0
          new (context_) ESTree::BigIntLiteralTypeAnnotationNode(raw));
2943
0
    }
2944
2945
0
    case TokenKind::minus: {
2946
0
      advance(JSLexer::GrammarContext::Type);
2947
0
      if (check(TokenKind::numeric_literal)) {
2948
        // Negate the literal.
2949
0
        double value = -tok_->getNumericLiteral();
2950
0
        UniqueString *raw = lexer_.getStringLiteral(llvh::StringRef(
2951
0
            start.getPointer(),
2952
0
            tok_->getEndLoc().getPointer() - start.getPointer()));
2953
0
        return setLocation(
2954
0
            start,
2955
0
            advance(JSLexer::GrammarContext::Type).End,
2956
0
            new (context_) ESTree::NumberLiteralTypeAnnotationNode(value, raw));
2957
0
      } else if (check(TokenKind::bigint_literal)) {
2958
0
        UniqueString *raw = lexer_.getStringLiteral(llvh::StringRef(
2959
0
            start.getPointer(),
2960
0
            tok_->getEndLoc().getPointer() - start.getPointer()));
2961
0
        return setLocation(
2962
0
            start,
2963
0
            advance(JSLexer::GrammarContext::Type).End,
2964
0
            new (context_) ESTree::BigIntLiteralTypeAnnotationNode(raw));
2965
0
      } else {
2966
0
        errorExpected(
2967
0
            TokenKind::numeric_literal,
2968
0
            "in type annotation",
2969
0
            "start of annotation",
2970
0
            start);
2971
0
        return None;
2972
0
      }
2973
0
    }
2974
2975
0
    case TokenKind::rw_true:
2976
0
    case TokenKind::rw_false: {
2977
0
      bool value = check(TokenKind::rw_true);
2978
0
      auto *raw = tok_->getResWordIdentifier();
2979
0
      return setLocation(
2980
0
          start,
2981
0
          advance(JSLexer::GrammarContext::Type).End,
2982
0
          new (context_) ESTree::BooleanLiteralTypeAnnotationNode(value, raw));
2983
0
    }
2984
0
    default:
2985
0
      if (tok_->isResWord()) {
2986
0
        auto optGeneric = parseGenericTypeFlow();
2987
0
        if (!optGeneric)
2988
0
          return None;
2989
0
        return *optGeneric;
2990
0
      }
2991
0
      error(tok_->getStartLoc(), "unexpected token in type annotation");
2992
0
      return None;
2993
0
  }
2994
0
}
2995
2996
0
Optional<ESTree::Node *> JSParserImpl::parseTypeofTypeAnnotationFlow() {
2997
0
  assert(check(TokenKind::rw_typeof));
2998
0
  SMLoc startLoc = advance().Start;
2999
0
  uint32_t parenCount = 0;
3000
3001
0
  while (checkAndEat(TokenKind::l_paren))
3002
0
    ++parenCount;
3003
3004
0
  if (!need(TokenKind::identifier, "in typeof type", "start of type", startLoc))
3005
0
    return None;
3006
3007
0
  ESTree::Node *ident = setLocation(
3008
0
      tok_,
3009
0
      tok_,
3010
0
      new (context_)
3011
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
3012
0
  advance(JSLexer::GrammarContext::Type);
3013
3014
0
  while (checkAndEat(TokenKind::period)) {
3015
0
    if (!check(TokenKind::identifier) && !tok_->isResWord()) {
3016
0
      errorExpected(
3017
0
          TokenKind::identifier,
3018
0
          "in qualified typeof type",
3019
0
          "start of type",
3020
0
          startLoc);
3021
0
      return None;
3022
0
    }
3023
0
    ESTree::Node *next = setLocation(
3024
0
        tok_,
3025
0
        tok_,
3026
0
        new (context_) ESTree::IdentifierNode(
3027
0
            tok_->getResWordOrIdentifier(), nullptr, false));
3028
0
    advance(JSLexer::GrammarContext::Type);
3029
0
    ident = setLocation(
3030
0
        ident,
3031
0
        next,
3032
0
        new (context_) ESTree::QualifiedTypeofIdentifierNode(ident, next));
3033
0
  }
3034
3035
0
  for (; parenCount > 0; --parenCount) {
3036
0
    if (!eat(
3037
0
            TokenKind::r_paren,
3038
0
            JSLexer::GrammarContext::Type,
3039
0
            "in typeof type",
3040
0
            "start of type",
3041
0
            startLoc))
3042
0
      return None;
3043
0
    ident->incParens();
3044
0
  }
3045
3046
0
  ESTree::Node *typeArguments = nullptr;
3047
0
  if (check(TokenKind::less) && !lexer_.isNewLineBeforeCurrentToken()) {
3048
0
    auto optTypeArgs = parseTypeArgsFlow();
3049
0
    if (!optTypeArgs)
3050
0
      return None;
3051
0
    typeArguments = *optTypeArgs;
3052
0
  }
3053
3054
0
  return setLocation(
3055
0
      startLoc,
3056
0
      getPrevTokenEndLoc(),
3057
0
      new (context_) ESTree::TypeofTypeAnnotationNode(ident, typeArguments));
3058
0
}
3059
3060
0
Optional<ESTree::Node *> JSParserImpl::parseTupleTypeAnnotationFlow() {
3061
0
  assert(check(TokenKind::l_square));
3062
0
  SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
3063
3064
0
  ESTree::NodeList types{};
3065
0
  bool inexact = false;
3066
3067
0
  while (!check(TokenKind::r_square)) {
3068
0
    SMLoc startLoc = tok_->getStartLoc();
3069
0
    bool startsWithDotDotDot =
3070
0
        checkAndEat(TokenKind::dotdotdot, JSLexer::GrammarContext::Type);
3071
3072
    // ...]
3073
0
    if (startsWithDotDotDot && check(TokenKind::r_square)) {
3074
0
      inexact = true;
3075
      // ...,
3076
0
    } else if (startsWithDotDotDot && check(TokenKind::comma)) {
3077
0
      error(
3078
0
          tok_->getSourceRange(),
3079
0
          "trailing commas after inexact tuple types are not allowed");
3080
0
      advance(JSLexer::GrammarContext::Type);
3081
0
    } else {
3082
0
      auto optType = parseTupleElementFlow(startLoc, startsWithDotDotDot);
3083
0
      if (!optType)
3084
0
        return None;
3085
0
      types.push_back(**optType);
3086
3087
0
      if (!checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type))
3088
0
        break;
3089
0
    }
3090
0
  }
3091
3092
0
  if (!need(
3093
0
          TokenKind::r_square,
3094
0
          "at end of tuple type annotation",
3095
0
          "start of tuple",
3096
0
          start))
3097
0
    return None;
3098
3099
0
  return setLocation(
3100
0
      start,
3101
0
      advance(JSLexer::GrammarContext::Type).End,
3102
0
      new (context_)
3103
0
          ESTree::TupleTypeAnnotationNode(std::move(types), inexact));
3104
0
}
3105
3106
Optional<ESTree::Node *> JSParserImpl::parseTupleElementFlow(
3107
    SMLoc startLoc,
3108
0
    bool startsWithDotDotDot) {
3109
0
  ESTree::Node *label = nullptr;
3110
0
  ESTree::Node *elementType = nullptr;
3111
0
  ESTree::Node *variance = nullptr;
3112
3113
  // ...Identifier : Type
3114
  // ...Type
3115
  // ^
3116
0
  if (startsWithDotDotDot) {
3117
0
    auto optType = parseTypeAnnotationBeforeColonFlow();
3118
0
    if (!optType)
3119
0
      return None;
3120
0
    if (checkAndEat(TokenKind::colon, JSLexer::GrammarContext::Type)) {
3121
0
      auto optLabel = reparseTypeAnnotationAsIdentifierFlow(*optType);
3122
0
      if (!optLabel)
3123
0
        return None;
3124
0
      label = *optLabel;
3125
0
      auto optType = parseTypeAnnotationFlow();
3126
0
      if (!optType)
3127
0
        return None;
3128
0
      elementType = *optType;
3129
0
      return setLocation(
3130
0
          startLoc,
3131
0
          getPrevTokenEndLoc(),
3132
0
          new (context_)
3133
0
              ESTree::TupleTypeSpreadElementNode(label, elementType));
3134
0
    }
3135
3136
0
    return setLocation(
3137
0
        startLoc,
3138
0
        getPrevTokenEndLoc(),
3139
0
        new (context_) ESTree::TupleTypeSpreadElementNode(label, *optType));
3140
0
  }
3141
3142
  /// +Identifier : Type
3143
  /// -Identifier : Type
3144
  /// ^
3145
0
  if (check(TokenKind::plus, TokenKind::minus)) {
3146
0
    variance = setLocation(
3147
0
        tok_,
3148
0
        tok_,
3149
0
        new (context_) ESTree::VarianceNode(
3150
0
            check(TokenKind::plus) ? plusIdent_ : minusIdent_));
3151
0
    advance(JSLexer::GrammarContext::Type);
3152
0
  }
3153
3154
  /// Identifier [?] : Type
3155
  /// Type
3156
  /// ^
3157
0
  auto optType = parseTypeAnnotationBeforeColonFlow();
3158
0
  if (!optType)
3159
0
    return None;
3160
3161
  /// Identifier [?] : Type
3162
  ///             ^
3163
0
  if (check(TokenKind::colon, TokenKind::question)) {
3164
0
    bool optional =
3165
0
        checkAndEat(TokenKind::question, JSLexer::GrammarContext::Type);
3166
3167
0
    if (!eat(
3168
0
            TokenKind::colon,
3169
0
            JSLexer::GrammarContext::Type,
3170
0
            "in labeled tuple type element",
3171
0
            "location of tuple",
3172
0
            startLoc))
3173
0
      return None;
3174
3175
0
    auto optLabel = reparseTypeAnnotationAsIdentifierFlow(*optType);
3176
0
    if (!optLabel)
3177
0
      return None;
3178
0
    label = *optLabel;
3179
0
    auto optType = parseTypeAnnotationFlow();
3180
0
    if (!optType)
3181
0
      return None;
3182
0
    elementType = *optType;
3183
3184
0
    return setLocation(
3185
0
        startLoc,
3186
0
        getPrevTokenEndLoc(),
3187
0
        new (context_) ESTree::TupleTypeLabeledElementNode(
3188
0
            label, elementType, optional, variance));
3189
0
  }
3190
3191
0
  if (variance) {
3192
0
    error(
3193
0
        variance->getSourceRange(),
3194
0
        "Variance can only be used with labeled tuple elements");
3195
0
  }
3196
3197
0
  return *optType;
3198
0
}
3199
3200
0
Optional<ESTree::Node *> JSParserImpl::parseHookTypeAnnotationFlow() {
3201
  // hook
3202
0
  assert(check(hookIdent_));
3203
0
  advance(JSLexer::GrammarContext::Type);
3204
0
  return parseFunctionOrHookTypeAnnotationFlow(true);
3205
0
}
3206
3207
0
Optional<ESTree::Node *> JSParserImpl::parseFunctionTypeAnnotationFlow() {
3208
0
  return parseFunctionOrHookTypeAnnotationFlow(false);
3209
0
}
3210
3211
Optional<ESTree::Node *> JSParserImpl::parseFunctionOrHookTypeAnnotationFlow(
3212
0
    bool hook) {
3213
0
  SMLoc start = tok_->getStartLoc();
3214
3215
0
  ESTree::Node *typeParams = nullptr;
3216
0
  if (check(TokenKind::less)) {
3217
0
    auto optParams = parseTypeParamsFlow();
3218
0
    if (!optParams)
3219
0
      return None;
3220
0
    typeParams = *optParams;
3221
0
  }
3222
3223
0
  if (!need(
3224
0
          TokenKind::l_paren,
3225
0
          "in function type annotation",
3226
0
          "start of annotation",
3227
0
          start))
3228
0
    return None;
3229
3230
0
  ESTree::NodeList params{};
3231
0
  ESTree::Node *thisConstraint = nullptr;
3232
0
  auto optRest =
3233
0
      parseFunctionTypeAnnotationParamsFlow(params, thisConstraint, hook);
3234
0
  if (!optRest)
3235
0
    return None;
3236
0
  ESTree::Node *rest = *optRest;
3237
3238
0
  if (!need(
3239
0
          TokenKind::equalgreater,
3240
0
          "in function type annotation",
3241
0
          "start of annotation",
3242
0
          start))
3243
0
    return None;
3244
3245
0
  return parseFunctionTypeAnnotationWithParamsFlow(
3246
0
      start, std::move(params), thisConstraint, rest, typeParams, hook);
3247
0
}
3248
3249
Optional<ESTree::Node *>
3250
JSParserImpl::parseFunctionTypeAnnotationWithParamsFlow(
3251
    SMLoc start,
3252
    ESTree::NodeList &&params,
3253
    ESTree::Node *thisConstraint,
3254
    ESTree::Node *rest,
3255
    ESTree::Node *typeParams,
3256
0
    bool hook) {
3257
0
  assert(check(TokenKind::equalgreater));
3258
0
  advance(JSLexer::GrammarContext::Type);
3259
3260
0
  auto optReturnType = parseReturnTypeAnnotationFlow();
3261
0
  if (!optReturnType)
3262
0
    return None;
3263
3264
0
  if (!hook) {
3265
0
    return setLocation(
3266
0
        start,
3267
0
        getPrevTokenEndLoc(),
3268
0
        new (context_) ESTree::FunctionTypeAnnotationNode(
3269
0
            std::move(params),
3270
0
            thisConstraint,
3271
0
            *optReturnType,
3272
0
            rest,
3273
0
            typeParams));
3274
0
  } else {
3275
0
    return setLocation(
3276
0
        start,
3277
0
        getPrevTokenEndLoc(),
3278
0
        new (context_) ESTree::HookTypeAnnotationNode(
3279
0
            std::move(params), *optReturnType, rest, typeParams));
3280
0
  }
3281
0
}
3282
3283
Optional<ESTree::Node *>
3284
0
JSParserImpl::parseFunctionOrGroupTypeAnnotationFlow() {
3285
0
  assert(check(TokenKind::l_paren));
3286
  // This is either
3287
  // ( Type )
3288
  // ^
3289
  // or
3290
  // ( ParamList ) => Type
3291
  // ^
3292
  // so we use a similar approach to arrow function parameters by keeping track
3293
  // and reparsing in certain cases.
3294
0
  SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
3295
3296
0
  bool isFunction = false;
3297
0
  ESTree::Node *type = nullptr;
3298
0
  ESTree::Node *rest = nullptr;
3299
0
  ESTree::NodeList params{};
3300
0
  ESTree::Node *thisConstraint = nullptr;
3301
3302
0
  if (check(TokenKind::rw_this)) {
3303
0
    OptValue<TokenKind> optNext = lexer_.lookahead1(None);
3304
0
    if (optNext.hasValue() && *optNext == TokenKind::colon) {
3305
0
      SMLoc thisStart = advance(JSLexer::GrammarContext::Type).Start;
3306
0
      advance(JSLexer::GrammarContext::Type);
3307
0
      auto optType = parseTypeAnnotationFlow();
3308
0
      if (!optType)
3309
0
        return None;
3310
0
      ESTree::Node *typeAnnotation = *optType;
3311
3312
0
      thisConstraint = setLocation(
3313
0
          thisStart,
3314
0
          getPrevTokenEndLoc(),
3315
0
          new (context_) ESTree::FunctionTypeParamNode(
3316
0
              /* name */ nullptr, typeAnnotation, /* optional */ false));
3317
0
      checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type);
3318
0
    } else if (optNext.hasValue() && *optNext == TokenKind::question) {
3319
0
      error(tok_->getSourceRange(), "'this' constraint may not be optional");
3320
0
    }
3321
0
  }
3322
3323
0
  if (allowAnonFunctionType_ &&
3324
0
      checkAndEat(TokenKind::dotdotdot, JSLexer::GrammarContext::Type)) {
3325
0
    isFunction = true;
3326
    // Must be parameters, and this must be the last one.
3327
0
    auto optParam = parseFunctionTypeAnnotationParamFlow();
3328
0
    if (!optParam)
3329
0
      return None;
3330
    // Rest param must be the last param.
3331
0
    rest = *optParam;
3332
0
  } else if (check(TokenKind::r_paren)) {
3333
0
    isFunction = true;
3334
    // ( )
3335
    //   ^
3336
    // No parameters, but this must be an empty param list.
3337
0
  } else {
3338
    // Not sure yet whether this is a param or simply a type.
3339
0
    auto optParam = parseFunctionTypeAnnotationParamFlow();
3340
0
    if (!optParam)
3341
0
      return None;
3342
0
    ESTree::FunctionTypeParamNode *param = *optParam;
3343
0
    type = param->_typeAnnotation;
3344
0
    if (param->_name || param->_optional) {
3345
      // Must be a param if it has a name.or if it was optional.
3346
0
      isFunction = true;
3347
0
    }
3348
0
    params.push_back(*param);
3349
0
  }
3350
3351
  // If isFunction was already forced by something previously then we
3352
  // have no choice but to attempt to parse as a function type annotation.
3353
0
  if ((isFunction || allowAnonFunctionType_) &&
3354
0
      checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type)) {
3355
0
    isFunction = true;
3356
0
    while (!check(TokenKind::r_paren)) {
3357
0
      bool isRest = !rest &&
3358
0
          checkAndEat(TokenKind::dotdotdot, JSLexer::GrammarContext::Type);
3359
3360
0
      auto optParam = parseFunctionTypeAnnotationParamFlow();
3361
0
      if (!optParam)
3362
0
        return None;
3363
0
      if (isRest) {
3364
0
        rest = *optParam;
3365
0
        checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type);
3366
0
        break;
3367
0
      } else {
3368
0
        params.push_back(**optParam);
3369
0
      }
3370
3371
0
      if (!checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type))
3372
0
        break;
3373
0
    }
3374
0
  }
3375
3376
0
  if (!eat(
3377
0
          TokenKind::r_paren,
3378
0
          JSLexer::GrammarContext::Type,
3379
0
          "at end of function annotation parameters",
3380
0
          "start of parameters",
3381
0
          start))
3382
0
    return None;
3383
3384
0
  if (isFunction) {
3385
0
    if (!eat(
3386
0
            TokenKind::equalgreater,
3387
0
            JSLexer::GrammarContext::Type,
3388
0
            "in function type annotation",
3389
0
            "start of function",
3390
0
            start))
3391
0
      return None;
3392
0
  } else if (allowAnonFunctionType_) {
3393
0
    if (checkAndEat(TokenKind::equalgreater, JSLexer::GrammarContext::Type)) {
3394
0
      isFunction = true;
3395
0
    }
3396
0
  }
3397
3398
0
  if (!isFunction) {
3399
0
    type->incParens();
3400
0
    return type;
3401
0
  }
3402
3403
0
  auto optReturnType = parseReturnTypeAnnotationFlow(
3404
0
      None,
3405
0
      allowAnonFunctionType_ ? AllowAnonFunctionType::Yes
3406
0
                             : AllowAnonFunctionType::No);
3407
0
  if (!optReturnType)
3408
0
    return None;
3409
3410
0
  ESTree::Node *typeParams = nullptr;
3411
0
  return setLocation(
3412
0
      start,
3413
0
      getPrevTokenEndLoc(),
3414
0
      new (context_) ESTree::FunctionTypeAnnotationNode(
3415
0
          std::move(params), thisConstraint, *optReturnType, rest, typeParams));
3416
0
}
3417
3418
Optional<ESTree::Node *> JSParserImpl::parseObjectTypeAnnotationFlow(
3419
    AllowProtoProperty allowProtoProperty,
3420
    AllowStaticProperty allowStaticProperty,
3421
0
    AllowSpreadProperty allowSpreadProperty) {
3422
0
  assert(check(TokenKind::l_brace, TokenKind::l_bracepipe));
3423
0
  bool exact = check(TokenKind::l_bracepipe);
3424
0
  SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
3425
3426
0
  ESTree::NodeList properties{};
3427
0
  ESTree::NodeList indexers{};
3428
0
  ESTree::NodeList callProperties{};
3429
0
  ESTree::NodeList internalSlots{};
3430
0
  bool inexact = false;
3431
3432
0
  if (!parseObjectTypePropertiesFlow(
3433
0
          allowProtoProperty,
3434
0
          allowStaticProperty,
3435
0
          allowSpreadProperty,
3436
0
          properties,
3437
0
          indexers,
3438
0
          callProperties,
3439
0
          internalSlots,
3440
0
          inexact))
3441
0
    return None;
3442
3443
0
  if (exact && inexact) {
3444
    // Doesn't prevent parsing from continuing, but it is an error.
3445
0
    error(
3446
0
        start,
3447
0
        "Explicit inexact syntax cannot appear inside an explicit exact object type");
3448
0
  }
3449
3450
0
  SMLoc end = tok_->getEndLoc();
3451
0
  if (!eat(
3452
0
          exact ? TokenKind::piper_brace : TokenKind::r_brace,
3453
0
          JSLexer::GrammarContext::Type,
3454
0
          "at end of exact object type annotation",
3455
0
          "start of object",
3456
0
          start))
3457
0
    return None;
3458
3459
0
  return setLocation(
3460
0
      start,
3461
0
      end,
3462
0
      new (context_) ESTree::ObjectTypeAnnotationNode(
3463
0
          std::move(properties),
3464
0
          std::move(indexers),
3465
0
          std::move(callProperties),
3466
0
          std::move(internalSlots),
3467
0
          inexact,
3468
0
          exact));
3469
0
}
3470
3471
bool JSParserImpl::parseObjectTypePropertiesFlow(
3472
    AllowProtoProperty allowProtoProperty,
3473
    AllowStaticProperty allowStaticProperty,
3474
    AllowSpreadProperty allowSpreadProperty,
3475
    ESTree::NodeList &properties,
3476
    ESTree::NodeList &indexers,
3477
    ESTree::NodeList &callProperties,
3478
    ESTree::NodeList &internalSlots,
3479
0
    bool &inexact) {
3480
0
  while (!check(TokenKind::r_brace, TokenKind::piper_brace)) {
3481
0
    SMLoc start = tok_->getStartLoc();
3482
0
    if (check(TokenKind::dotdotdot)) {
3483
      // Spread property or explicit '...' for inexact.
3484
0
      advance(JSLexer::GrammarContext::Type);
3485
0
      if (check(TokenKind::comma, TokenKind::semi)) {
3486
0
        inexact = true;
3487
0
        advance(JSLexer::GrammarContext::Type);
3488
        // Explicit '...' must be the last element in the type annotation.
3489
0
        return true;
3490
0
      } else if (check(TokenKind::r_brace, TokenKind::piper_brace)) {
3491
0
        inexact = true;
3492
0
        return true;
3493
0
      } else {
3494
0
        if (allowSpreadProperty == AllowSpreadProperty::No) {
3495
0
          error(
3496
0
              start, "Spreading a type is only allowed inside an object type");
3497
0
        }
3498
0
        auto optType = parseTypeAnnotationFlow();
3499
0
        if (!optType)
3500
0
          return false;
3501
0
        properties.push_back(*setLocation(
3502
0
            start,
3503
0
            getPrevTokenEndLoc(),
3504
0
            new (context_) ESTree::ObjectTypeSpreadPropertyNode(*optType)));
3505
0
      }
3506
0
    } else {
3507
0
      if (!parsePropertyTypeAnnotationFlow(
3508
0
              allowProtoProperty,
3509
0
              allowStaticProperty,
3510
0
              properties,
3511
0
              indexers,
3512
0
              callProperties,
3513
0
              internalSlots))
3514
0
        return false;
3515
0
    }
3516
3517
0
    if (check(TokenKind::comma, TokenKind::semi)) {
3518
0
      advance(JSLexer::GrammarContext::Type);
3519
0
    } else if (check(TokenKind::r_brace, TokenKind::piper_brace)) {
3520
0
      return true;
3521
0
    } else {
3522
0
      errorExpected(
3523
0
          {TokenKind::comma,
3524
0
           TokenKind::semi,
3525
0
           TokenKind::r_brace,
3526
0
           TokenKind::piper_brace},
3527
0
          "after property",
3528
0
          "start of property",
3529
0
          start);
3530
0
      return false;
3531
0
    }
3532
0
  }
3533
3534
0
  return true;
3535
0
}
3536
3537
bool JSParserImpl::parsePropertyTypeAnnotationFlow(
3538
    AllowProtoProperty allowProtoProperty,
3539
    AllowStaticProperty allowStaticProperty,
3540
    ESTree::NodeList &properties,
3541
    ESTree::NodeList &indexers,
3542
    ESTree::NodeList &callProperties,
3543
0
    ESTree::NodeList &internalSlots) {
3544
0
  SMRange startRange = tok_->getSourceRange();
3545
0
  SMLoc start = startRange.Start;
3546
3547
0
  ESTree::Node *variance = nullptr;
3548
0
  bool isStatic = false;
3549
0
  bool proto = false;
3550
3551
0
  if (check(protoIdent_)) {
3552
0
    proto = true;
3553
0
    advance(JSLexer::GrammarContext::Type);
3554
0
  }
3555
3556
0
  if (!proto && (check(TokenKind::rw_static) || check(staticIdent_))) {
3557
0
    isStatic = true;
3558
0
    advance(JSLexer::GrammarContext::Type);
3559
0
  }
3560
3561
0
  if (check(TokenKind::plus, TokenKind::minus)) {
3562
0
    variance = setLocation(
3563
0
        tok_,
3564
0
        tok_,
3565
0
        new (context_) ESTree::VarianceNode(
3566
0
            check(TokenKind::plus) ? plusIdent_ : minusIdent_));
3567
0
    advance(JSLexer::GrammarContext::Type);
3568
0
  }
3569
3570
0
  if (checkAndEat(TokenKind::l_square, JSLexer::GrammarContext::Type)) {
3571
0
    if (checkAndEat(TokenKind::l_square, JSLexer::GrammarContext::Type)) {
3572
0
      if (variance) {
3573
0
        error(variance->getSourceRange(), "Unexpected variance sigil");
3574
0
      }
3575
0
      if (proto) {
3576
0
        error(startRange, "invalid 'proto' modifier");
3577
0
      }
3578
0
      if (isStatic && allowStaticProperty == AllowStaticProperty::No) {
3579
0
        error(startRange, "invalid 'static' modifier");
3580
0
      }
3581
      // Internal slot
3582
0
      if (!check(TokenKind::identifier) && !tok_->isResWord()) {
3583
0
        errorExpected(
3584
0
            TokenKind::identifier,
3585
0
            "in internal slot",
3586
0
            "start of internal slot",
3587
0
            start);
3588
0
        return false;
3589
0
      }
3590
0
      ESTree::IdentifierNode *id = setLocation(
3591
0
          tok_,
3592
0
          tok_,
3593
0
          new (context_) ESTree::IdentifierNode(
3594
0
              tok_->getResWordOrIdentifier(), nullptr, false));
3595
0
      advance(JSLexer::GrammarContext::Type);
3596
3597
0
      if (!eat(
3598
0
              TokenKind::r_square,
3599
0
              JSLexer::GrammarContext::Type,
3600
0
              "at end of internal slot",
3601
0
              "start of internal slot",
3602
0
              start))
3603
0
        return false;
3604
0
      if (!eat(
3605
0
              TokenKind::r_square,
3606
0
              JSLexer::GrammarContext::Type,
3607
0
              "at end of internal slot",
3608
0
              "start of internal slot",
3609
0
              start))
3610
0
        return false;
3611
3612
0
      bool optional = false;
3613
0
      bool method = false;
3614
0
      ESTree::Node *value = nullptr;
3615
3616
0
      if (check(TokenKind::less, TokenKind::l_paren)) {
3617
        // Type params and method.
3618
0
        method = true;
3619
0
        ESTree::Node *typeParams = nullptr;
3620
0
        if (check(TokenKind::less)) {
3621
0
          auto optParams = parseTypeParamsFlow();
3622
0
          if (!optParams)
3623
0
            return false;
3624
0
          typeParams = *optParams;
3625
0
        }
3626
0
        auto optMethodish = parseMethodishTypeAnnotationFlow(start, typeParams);
3627
0
        if (!optMethodish)
3628
0
          return false;
3629
0
        value = *optMethodish;
3630
0
      } else {
3631
        // Standard type annotation.
3632
0
        optional =
3633
0
            checkAndEat(TokenKind::question, JSLexer::GrammarContext::Type);
3634
0
        if (!eat(
3635
0
                TokenKind::colon,
3636
0
                JSLexer::GrammarContext::Type,
3637
0
                "in type annotation",
3638
0
                "start of annotation",
3639
0
                start))
3640
0
          return false;
3641
0
        auto optValue = parseTypeAnnotationFlow();
3642
0
        if (!optValue)
3643
0
          return false;
3644
0
        value = *optValue;
3645
0
      }
3646
3647
0
      assert(value && "value must be set by a branch");
3648
0
      internalSlots.push_back(*setLocation(
3649
0
          start,
3650
0
          getPrevTokenEndLoc(),
3651
0
          new (context_) ESTree::ObjectTypeInternalSlotNode(
3652
0
              id, value, optional, isStatic, method)));
3653
0
    } else {
3654
      // Indexer or Mapped Type
3655
      // We can have
3656
      // [ Identifier : TypeAnnotation ]
3657
      //   ^
3658
      // or
3659
      // [ TypeAnnotation ]
3660
      //   ^
3661
      // or
3662
      // [ TypeParameter in TypeAnnotation ]
3663
      //   ^
3664
      // Because we cannot differentiate without looking ahead for the `in`
3665
      // or `:`, we call `parseTypeAnnotation`, check for the next token
3666
      // and then convert the TypeAnnotation to the appropriate node.
3667
0
      auto optLeft = parseTypeAnnotationBeforeColonFlow();
3668
0
      if (!optLeft)
3669
0
        return false;
3670
0
      ESTree::Node *left = *optLeft;
3671
3672
0
      if (checkAndEat(TokenKind::rw_in, JSLexer::GrammarContext::Type)) {
3673
0
        auto optProp = parseTypeMappedTypePropertyFlow(start, left, variance);
3674
0
        if (!optProp)
3675
0
          return false;
3676
0
        properties.push_back(**optProp);
3677
0
      } else {
3678
0
        auto optIndexer =
3679
0
            parseTypeIndexerPropertyFlow(start, left, variance, isStatic);
3680
0
        if (!optIndexer)
3681
0
          return false;
3682
0
        indexers.push_back(**optIndexer);
3683
0
      }
3684
3685
0
      if (proto) {
3686
0
        error(startRange, "invalid 'proto' modifier");
3687
0
      }
3688
0
      if (isStatic && allowStaticProperty == AllowStaticProperty::No) {
3689
0
        error(startRange, "invalid 'static' modifier");
3690
0
      }
3691
0
    }
3692
0
    return true;
3693
0
  }
3694
3695
0
  ESTree::Node *key = nullptr;
3696
3697
0
  if (check(TokenKind::less, TokenKind::l_paren)) {
3698
0
    if ((isStatic && allowStaticProperty == AllowStaticProperty::No) ||
3699
0
        (proto && allowProtoProperty == AllowProtoProperty::No)) {
3700
0
      key = setLocation(
3701
0
          startRange,
3702
0
          startRange,
3703
0
          new (context_) ESTree::IdentifierNode(
3704
0
              isStatic ? staticIdent_ : protoIdent_, nullptr, false));
3705
0
      isStatic = false;
3706
0
      proto = false;
3707
0
      if (variance) {
3708
0
        error(variance->getSourceRange(), "Unexpected variance sigil");
3709
0
      }
3710
0
      auto optProp = parseMethodTypePropertyFlow(start, isStatic, key);
3711
0
      if (!optProp)
3712
0
        return false;
3713
0
      properties.push_back(**optProp);
3714
0
      return true;
3715
0
    }
3716
0
    if (variance != nullptr) {
3717
0
      error(
3718
0
          variance->getSourceRange(),
3719
0
          "call property must not specify variance");
3720
0
    }
3721
0
    if (proto) {
3722
0
      error(startRange, "invalid 'proto' modifier");
3723
0
    }
3724
0
    auto optCall = parseTypeCallPropertyFlow(start, isStatic);
3725
0
    if (!optCall)
3726
0
      return false;
3727
0
    callProperties.push_back(**optCall);
3728
0
    return true;
3729
0
  }
3730
3731
0
  if ((isStatic || proto) && check(TokenKind::colon, TokenKind::question)) {
3732
0
    if (variance) {
3733
0
      error(variance->getSourceRange(), "Unexpected variance sigil");
3734
0
    }
3735
0
    key = setLocation(
3736
0
        startRange,
3737
0
        startRange,
3738
0
        new (context_) ESTree::IdentifierNode(
3739
0
            isStatic ? staticIdent_ : protoIdent_, nullptr, false));
3740
0
    isStatic = false;
3741
0
    proto = false;
3742
0
    auto optProp = parseTypePropertyFlow(start, variance, isStatic, proto, key);
3743
0
    if (!optProp)
3744
0
      return false;
3745
0
    properties.push_back(**optProp);
3746
0
    return true;
3747
0
  }
3748
3749
0
  auto optKey = parsePropertyName();
3750
0
  if (!optKey)
3751
0
    return false;
3752
0
  key = *optKey;
3753
3754
0
  if (check(TokenKind::less, TokenKind::l_paren)) {
3755
0
    if (variance) {
3756
0
      error(variance->getSourceRange(), "Unexpected variance sigil");
3757
0
    }
3758
0
    if (proto) {
3759
0
      error(startRange, "invalid 'proto' modifier");
3760
0
    }
3761
0
    if (isStatic && allowStaticProperty == AllowStaticProperty::No) {
3762
0
      error(startRange, "invalid 'static' modifier");
3763
0
    }
3764
0
    auto optProp = parseMethodTypePropertyFlow(start, isStatic, key);
3765
0
    if (!optProp)
3766
0
      return false;
3767
0
    properties.push_back(**optProp);
3768
0
    return true;
3769
0
  }
3770
3771
0
  if (check(TokenKind::colon, TokenKind::question)) {
3772
0
    if (proto && allowProtoProperty == AllowProtoProperty::No) {
3773
0
      error(startRange, "invalid 'proto' modifier");
3774
0
    }
3775
0
    if (isStatic && allowStaticProperty == AllowStaticProperty::No) {
3776
0
      error(startRange, "invalid 'static' modifier");
3777
0
    }
3778
0
    auto optProp = parseTypePropertyFlow(start, variance, isStatic, proto, key);
3779
0
    if (!optProp)
3780
0
      return false;
3781
0
    properties.push_back(**optProp);
3782
0
    return true;
3783
0
  }
3784
3785
0
  if (auto *ident = dyn_cast<ESTree::IdentifierNode>(key)) {
3786
0
    if (ident->_name == getIdent_ || ident->_name == setIdent_) {
3787
0
      if (variance != nullptr) {
3788
0
        error(
3789
0
            variance->getSourceRange(),
3790
0
            "accessor property must not specify variance");
3791
0
      }
3792
0
      if (proto) {
3793
0
        error(startRange, "invalid 'proto' modifier");
3794
0
      }
3795
0
      if (isStatic && allowStaticProperty == AllowStaticProperty::No) {
3796
0
        error(startRange, "invalid 'static' modifier");
3797
0
      }
3798
0
      auto optKey = parsePropertyName();
3799
0
      if (!optKey)
3800
0
        return false;
3801
0
      key = *optKey;
3802
0
      auto optGetSet = parseGetOrSetTypePropertyFlow(
3803
0
          start, isStatic, ident->_name == getIdent_, key);
3804
0
      if (!optGetSet)
3805
0
        return false;
3806
0
      properties.push_back(**optGetSet);
3807
0
      return true;
3808
0
    }
3809
0
  }
3810
3811
0
  errorExpected(
3812
0
      {TokenKind::colon, TokenKind::question},
3813
0
      "in property type annotation",
3814
0
      "start of properties",
3815
0
      start);
3816
0
  return false;
3817
0
}
3818
3819
Optional<ESTree::Node *> JSParserImpl::parseTypePropertyFlow(
3820
    SMLoc start,
3821
    ESTree::Node *variance,
3822
    bool isStatic,
3823
    bool proto,
3824
0
    ESTree::Node *key) {
3825
0
  assert(check(TokenKind::colon, TokenKind::question));
3826
3827
0
  bool optional =
3828
0
      checkAndEat(TokenKind::question, JSLexer::GrammarContext::Type);
3829
0
  if (!eat(
3830
0
          TokenKind::colon,
3831
0
          JSLexer::GrammarContext::Type,
3832
0
          "in type property",
3833
0
          "start of property",
3834
0
          start))
3835
0
    return None;
3836
3837
0
  auto optValue = parseTypeAnnotationFlow();
3838
0
  if (!optValue)
3839
0
    return None;
3840
0
  ESTree::Node *value = *optValue;
3841
3842
0
  bool method = false;
3843
0
  UniqueString *kind = initIdent_;
3844
3845
0
  return setLocation(
3846
0
      start,
3847
0
      getPrevTokenEndLoc(),
3848
0
      new (context_) ESTree::ObjectTypePropertyNode(
3849
0
          key, value, method, optional, isStatic, proto, variance, kind));
3850
0
}
3851
3852
Optional<ESTree::Node *> JSParserImpl::parseMethodTypePropertyFlow(
3853
    SMLoc start,
3854
    bool isStatic,
3855
0
    ESTree::Node *key) {
3856
0
  assert(check(TokenKind::less, TokenKind::l_paren));
3857
3858
0
  ESTree::Node *typeParams = nullptr;
3859
0
  if (check(TokenKind::less)) {
3860
0
    auto optTypeParams = parseTypeParamsFlow();
3861
0
    if (!optTypeParams)
3862
0
      return None;
3863
0
    typeParams = *optTypeParams;
3864
0
  }
3865
3866
0
  auto optValue = parseMethodishTypeAnnotationFlow(start, typeParams);
3867
0
  if (!optValue)
3868
0
    return None;
3869
0
  ESTree::Node *value = *optValue;
3870
3871
0
  bool method = true;
3872
0
  bool optional = false;
3873
0
  bool proto = false;
3874
0
  UniqueString *kind = initIdent_;
3875
3876
0
  return setLocation(
3877
0
      start,
3878
0
      getPrevTokenEndLoc(),
3879
0
      new (context_) ESTree::ObjectTypePropertyNode(
3880
0
          key,
3881
0
          value,
3882
0
          method,
3883
0
          optional,
3884
0
          isStatic,
3885
0
          proto,
3886
0
          /* variance */ nullptr,
3887
0
          kind));
3888
0
}
3889
3890
Optional<ESTree::Node *> JSParserImpl::parseGetOrSetTypePropertyFlow(
3891
    SMLoc start,
3892
    bool isStatic,
3893
    bool isGetter,
3894
0
    ESTree::Node *key) {
3895
0
  auto optValue = parseMethodishTypeAnnotationFlow(start, nullptr);
3896
0
  if (!optValue)
3897
0
    return None;
3898
3899
0
  ESTree::FunctionTypeAnnotationNode *value = *optValue;
3900
0
  bool method = false;
3901
0
  bool optional = false;
3902
0
  bool proto = false;
3903
0
  ESTree::Node *variance = nullptr;
3904
0
  UniqueString *kind = isGetter ? getIdent_ : setIdent_;
3905
3906
  // Check the number of parameters, but we can continue parsing anyway.
3907
0
  if (isGetter) {
3908
0
    if (value->_params.size() != 0) {
3909
0
      error(value->getSourceRange(), "Getter must have 0 parameters");
3910
0
    }
3911
0
  } else {
3912
0
    if (value->_params.size() != 1) {
3913
0
      error(value->getSourceRange(), "Setter must have 1 parameter");
3914
0
    }
3915
0
  }
3916
3917
0
  if (value->_this) {
3918
0
    error(
3919
0
        value->_this->getSourceRange(),
3920
0
        "Accessors must not have 'this' annotations");
3921
0
  }
3922
3923
0
  return setLocation(
3924
0
      start,
3925
0
      getPrevTokenEndLoc(),
3926
0
      new (context_) ESTree::ObjectTypePropertyNode(
3927
0
          key, value, method, optional, isStatic, proto, variance, kind));
3928
0
}
3929
3930
Optional<ESTree::Node *> JSParserImpl::parseTypeMappedTypePropertyFlow(
3931
    SMLoc start,
3932
    ESTree::Node *left,
3933
0
    ESTree::Node *variance) {
3934
0
  auto idOpt = reparseTypeAnnotationAsIdFlow(left);
3935
0
  if (!idOpt)
3936
0
    return None;
3937
0
  UniqueString *id = *idOpt;
3938
0
  ESTree::Node *keyTparam = setLocation(
3939
0
      left,
3940
0
      left,
3941
0
      new (context_) ESTree::TypeParameterNode(
3942
0
          id, false, nullptr, nullptr, nullptr, false));
3943
3944
0
  auto optSourceType = parseTypeAnnotationFlow();
3945
0
  if (!optSourceType)
3946
0
    return None;
3947
3948
0
  if (!eat(
3949
0
          TokenKind::r_square,
3950
0
          JSLexer::GrammarContext::Type,
3951
0
          "in mapped type",
3952
0
          "start of mapped type",
3953
0
          start))
3954
0
    return None;
3955
3956
0
  UniqueString *optional = nullptr;
3957
0
  if (checkAndEat(TokenKind::plus, JSLexer::GrammarContext::Type)) {
3958
0
    if (!eat(
3959
0
            TokenKind::question,
3960
0
            JSLexer::GrammarContext::Type,
3961
0
            "in mapped type",
3962
0
            "start of mapped type",
3963
0
            start))
3964
0
      return None;
3965
3966
0
    optional = mappedTypePlusOptionalIdent_;
3967
0
  } else if (checkAndEat(TokenKind::minus, JSLexer::GrammarContext::Type)) {
3968
0
    if (!eat(
3969
0
            TokenKind::question,
3970
0
            JSLexer::GrammarContext::Type,
3971
0
            "in mapped type",
3972
0
            "start of mapped type",
3973
0
            start))
3974
0
      return None;
3975
3976
0
    optional = mappedTypeMinusOptionalIdent_;
3977
0
  } else if (checkAndEat(TokenKind::question, JSLexer::GrammarContext::Type)) {
3978
0
    optional = mappedTypeOptionalIdent_;
3979
0
  }
3980
3981
0
  if (!eat(
3982
0
          TokenKind::colon,
3983
0
          JSLexer::GrammarContext::Type,
3984
0
          "in mapped type",
3985
0
          "start of mapped type",
3986
0
          start))
3987
0
    return None;
3988
3989
0
  auto optPropType = parseTypeAnnotationFlow();
3990
0
  if (!optPropType)
3991
0
    return None;
3992
3993
0
  return setLocation(
3994
0
      start,
3995
0
      getPrevTokenEndLoc(),
3996
0
      new (context_) ESTree::ObjectTypeMappedTypePropertyNode(
3997
0
          keyTparam, *optPropType, *optSourceType, variance, optional));
3998
0
}
3999
4000
Optional<ESTree::Node *> JSParserImpl::parseTypeIndexerPropertyFlow(
4001
    SMLoc start,
4002
    ESTree::Node *left,
4003
    ESTree::Node *variance,
4004
0
    bool isStatic) {
4005
0
  ESTree::IdentifierNode *id = nullptr;
4006
0
  ESTree::Node *key = nullptr;
4007
4008
0
  if (checkAndEat(TokenKind::colon, JSLexer::GrammarContext::Type)) {
4009
0
    auto optId = reparseTypeAnnotationAsIdentifierFlow(left);
4010
0
    if (!optId)
4011
0
      return None;
4012
0
    id = *optId;
4013
0
    auto optKey = parseTypeAnnotationFlow();
4014
0
    if (!optKey)
4015
0
      return None;
4016
0
    key = *optKey;
4017
0
  } else {
4018
0
    key = left;
4019
0
  }
4020
4021
0
  if (!eat(
4022
0
          TokenKind::r_square,
4023
0
          JSLexer::GrammarContext::Type,
4024
0
          "in indexer",
4025
0
          "start of indexer",
4026
0
          start))
4027
0
    return None;
4028
4029
0
  if (!eat(
4030
0
          TokenKind::colon,
4031
0
          JSLexer::GrammarContext::Type,
4032
0
          "in indexer",
4033
0
          "start of indexer",
4034
0
          start))
4035
0
    return None;
4036
4037
0
  auto optValue = parseTypeAnnotationFlow();
4038
0
  if (!optValue)
4039
0
    return None;
4040
0
  ESTree::Node *value = *optValue;
4041
4042
0
  return setLocation(
4043
0
      start,
4044
0
      getPrevTokenEndLoc(),
4045
0
      new (context_)
4046
0
          ESTree::ObjectTypeIndexerNode(id, key, value, isStatic, variance));
4047
0
}
4048
4049
Optional<ESTree::Node *> JSParserImpl::parseTypeCallPropertyFlow(
4050
    SMLoc start,
4051
0
    bool isStatic) {
4052
0
  ESTree::Node *typeParams = nullptr;
4053
0
  if (check(TokenKind::less)) {
4054
0
    auto optTypeParams = parseTypeParamsFlow();
4055
0
    if (!optTypeParams)
4056
0
      return None;
4057
0
    typeParams = *optTypeParams;
4058
0
  }
4059
0
  auto optValue = parseMethodishTypeAnnotationFlow(start, typeParams);
4060
0
  if (!optValue)
4061
0
    return None;
4062
0
  return setLocation(
4063
0
      start,
4064
0
      getPrevTokenEndLoc(),
4065
0
      new (context_) ESTree::ObjectTypeCallPropertyNode(*optValue, isStatic));
4066
0
}
4067
4068
0
Optional<ESTree::Node *> JSParserImpl::parseTypeParamsFlow() {
4069
0
  assert(check(TokenKind::less));
4070
0
  SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
4071
4072
0
  ESTree::NodeList params{};
4073
4074
0
  do {
4075
0
    auto optType = parseTypeParamFlow();
4076
0
    if (!optType)
4077
0
      return None;
4078
0
    params.push_back(**optType);
4079
4080
0
    if (!checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type))
4081
0
      break;
4082
0
  } while (!check(TokenKind::greater));
4083
4084
0
  SMLoc end = tok_->getEndLoc();
4085
0
  if (!eat(
4086
0
          TokenKind::greater,
4087
0
          JSLexer::GrammarContext::Type,
4088
0
          "at end of type parameters",
4089
0
          "start of type parameters",
4090
0
          start))
4091
0
    return None;
4092
4093
0
  return setLocation(
4094
0
      start,
4095
0
      end,
4096
0
      new (context_) ESTree::TypeParameterDeclarationNode(std::move(params)));
4097
0
}
4098
4099
0
Optional<ESTree::Node *> JSParserImpl::parseTypeParamFlow() {
4100
0
  SMLoc start = tok_->getStartLoc();
4101
0
  bool isConst = false;
4102
0
  ESTree::Node *variance = nullptr;
4103
0
  if (check(TokenKind::rw_const)) {
4104
0
    isConst = true;
4105
0
    advance(JSLexer::GrammarContext::Type);
4106
0
  }
4107
4108
0
  if (check(TokenKind::plus, TokenKind::minus)) {
4109
0
    variance = setLocation(
4110
0
        tok_,
4111
0
        tok_,
4112
0
        new (context_) ESTree::VarianceNode(
4113
0
            check(TokenKind::plus) ? plusIdent_ : minusIdent_));
4114
0
    advance(JSLexer::GrammarContext::Type);
4115
0
  }
4116
4117
0
  if (!need(TokenKind::identifier, "in type parameter", nullptr, {}))
4118
0
    return None;
4119
0
  UniqueString *name = tok_->getIdentifier();
4120
0
  advance(JSLexer::GrammarContext::Type);
4121
4122
0
  ESTree::Node *bound = nullptr;
4123
0
  bool usesExtendsBound = false;
4124
0
  if (check(TokenKind::colon)) {
4125
0
    SMLoc boundStart = advance(JSLexer::GrammarContext::Type).Start;
4126
0
    auto optType = parseTypeAnnotationFlow();
4127
0
    if (!optType)
4128
0
      return None;
4129
0
    bound = setLocation(
4130
0
        boundStart,
4131
0
        getPrevTokenEndLoc(),
4132
0
        new (context_) ESTree::TypeAnnotationNode(*optType));
4133
0
  } else if (check(TokenKind::rw_extends)) {
4134
0
    usesExtendsBound = true;
4135
0
    SMLoc boundStart = advance(JSLexer::GrammarContext::Type).Start;
4136
0
    auto optType = parseTypeAnnotationFlow();
4137
0
    if (!optType)
4138
0
      return None;
4139
0
    bound = setLocation(
4140
0
        boundStart,
4141
0
        getPrevTokenEndLoc(),
4142
0
        new (context_) ESTree::TypeAnnotationNode(*optType));
4143
0
  }
4144
4145
0
  ESTree::Node *initializer = nullptr;
4146
0
  if (checkAndEat(TokenKind::equal, JSLexer::GrammarContext::Type)) {
4147
0
    auto optInit = parseTypeAnnotationFlow();
4148
0
    if (!optInit)
4149
0
      return None;
4150
0
    initializer = *optInit;
4151
0
  }
4152
4153
0
  return setLocation(
4154
0
      start,
4155
0
      getPrevTokenEndLoc(),
4156
0
      new (context_) ESTree::TypeParameterNode(
4157
0
          name, isConst, bound, variance, initializer, usesExtendsBound));
4158
0
}
4159
4160
0
Optional<ESTree::Node *> JSParserImpl::parseTypeArgsFlow() {
4161
0
  assert(check(TokenKind::less));
4162
0
  SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
4163
4164
0
  ESTree::NodeList params{};
4165
4166
0
  while (!check(TokenKind::greater)) {
4167
0
    auto optType = parseTypeAnnotationFlow();
4168
0
    if (!optType)
4169
0
      return None;
4170
0
    params.push_back(**optType);
4171
4172
0
    if (!checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type))
4173
0
      break;
4174
0
  }
4175
4176
0
  SMLoc end = tok_->getEndLoc();
4177
0
  if (!eat(
4178
0
          TokenKind::greater,
4179
0
          JSLexer::GrammarContext::Type,
4180
0
          "at end of type parameters",
4181
0
          "start of type parameters",
4182
0
          start))
4183
0
    return None;
4184
4185
0
  return setLocation(
4186
0
      start,
4187
0
      end,
4188
0
      new (context_) ESTree::TypeParameterInstantiationNode(std::move(params)));
4189
0
}
4190
4191
Optional<ESTree::FunctionTypeAnnotationNode *>
4192
JSParserImpl::parseMethodishTypeAnnotationFlow(
4193
    SMLoc start,
4194
0
    ESTree::Node *typeParams) {
4195
0
  ESTree::NodeList params{};
4196
0
  ESTree::Node *thisConstraint = nullptr;
4197
4198
0
  if (!need(TokenKind::l_paren, "at start of parameters", nullptr, {}))
4199
0
    return None;
4200
0
  auto optRest =
4201
0
      parseFunctionTypeAnnotationParamsFlow(params, thisConstraint, false);
4202
0
  if (!optRest)
4203
0
    return None;
4204
4205
0
  if (!eat(
4206
0
          TokenKind::colon,
4207
0
          JSLexer::GrammarContext::Type,
4208
0
          "in function type annotation",
4209
0
          "start of annotation",
4210
0
          start))
4211
0
    return None;
4212
4213
0
  auto optReturn = parseReturnTypeAnnotationFlow();
4214
0
  if (!optReturn)
4215
0
    return None;
4216
4217
0
  return setLocation(
4218
0
      start,
4219
0
      getPrevTokenEndLoc(),
4220
0
      new (context_) ESTree::FunctionTypeAnnotationNode(
4221
0
          std::move(params), thisConstraint, *optReturn, *optRest, typeParams));
4222
0
}
4223
4224
Optional<ESTree::FunctionTypeParamNode *>
4225
JSParserImpl::parseFunctionTypeAnnotationParamsFlow(
4226
    ESTree::NodeList &params,
4227
    ESTree::NodePtr &thisConstraint,
4228
0
    bool hook) {
4229
0
  assert(check(TokenKind::l_paren));
4230
0
  SMLoc start = advance(JSLexer::GrammarContext::Type).Start;
4231
4232
0
  ESTree::FunctionTypeParamNode *rest = nullptr;
4233
0
  thisConstraint = nullptr;
4234
4235
0
  if (check(TokenKind::rw_this) && !hook) {
4236
0
    OptValue<TokenKind> optNext = lexer_.lookahead1(None);
4237
0
    if (optNext.hasValue() && *optNext == TokenKind::colon) {
4238
0
      SMLoc thisStart = advance(JSLexer::GrammarContext::Type).Start;
4239
0
      advance(JSLexer::GrammarContext::Type);
4240
0
      auto optType = parseTypeAnnotationFlow();
4241
0
      if (!optType)
4242
0
        return None;
4243
0
      ESTree::Node *typeAnnotation = *optType;
4244
4245
0
      thisConstraint = setLocation(
4246
0
          thisStart,
4247
0
          getPrevTokenEndLoc(),
4248
0
          new (context_) ESTree::FunctionTypeParamNode(
4249
0
              /* name */ nullptr, typeAnnotation, /* optional */ false));
4250
0
      checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type);
4251
0
    } else if (optNext.hasValue() && *optNext == TokenKind::question) {
4252
0
      error(tok_->getSourceRange(), "'this' constraint may not be optional");
4253
0
    }
4254
0
  }
4255
4256
0
  while (!check(TokenKind::r_paren)) {
4257
0
    bool isRest =
4258
0
        checkAndEat(TokenKind::dotdotdot, JSLexer::GrammarContext::Type);
4259
4260
0
    auto optParam = hook ? parseHookTypeAnnotationParamFlow()
4261
0
                         : parseFunctionTypeAnnotationParamFlow();
4262
0
    if (!optParam)
4263
0
      return None;
4264
4265
0
    if (isRest) {
4266
      // Rest param must be the last param.
4267
0
      rest = *optParam;
4268
0
      checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type);
4269
0
      break;
4270
0
    } else {
4271
0
      params.push_back(**optParam);
4272
0
      if (!checkAndEat(TokenKind::comma, JSLexer::GrammarContext::Type)) {
4273
0
        break;
4274
0
      }
4275
0
    }
4276
0
  }
4277
4278
0
  if (!eat(
4279
0
          TokenKind::r_paren,
4280
0
          JSLexer::GrammarContext::Type,
4281
0
          "at end of function annotation parameters",
4282
0
          "start of parameters",
4283
0
          start))
4284
0
    return None;
4285
4286
0
  return rest;
4287
0
}
4288
4289
Optional<ESTree::FunctionTypeParamNode *>
4290
0
JSParserImpl::parseHookTypeAnnotationParamFlow() {
4291
0
  if (check(TokenKind::rw_this)) {
4292
0
    OptValue<TokenKind> optNext = lexer_.lookahead1(None);
4293
0
    if (optNext.hasValue() && *optNext == TokenKind::colon) {
4294
0
      error(tok_->getSourceRange(), "hooks do not support 'this' constraints");
4295
0
    }
4296
0
  }
4297
0
  return parseFunctionTypeAnnotationParamFlow();
4298
0
}
4299
4300
Optional<ESTree::FunctionTypeParamNode *>
4301
0
JSParserImpl::parseFunctionTypeAnnotationParamFlow() {
4302
0
  SMLoc start = tok_->getStartLoc();
4303
4304
0
  if (check(TokenKind::rw_this)) {
4305
0
    OptValue<TokenKind> optNext = lexer_.lookahead1(None);
4306
0
    if (optNext.hasValue() && *optNext == TokenKind::colon) {
4307
0
      error(
4308
0
          tok_->getSourceRange(),
4309
0
          "'this' constraint must be the first parameter");
4310
0
    }
4311
0
  }
4312
4313
0
  auto optLeft = parseTypeAnnotationBeforeColonFlow();
4314
0
  if (!optLeft)
4315
0
    return None;
4316
4317
0
  ESTree::Node *name = nullptr;
4318
0
  ESTree::Node *typeAnnotation = nullptr;
4319
0
  bool optional = false;
4320
4321
0
  if (check(TokenKind::colon, TokenKind::question)) {
4322
    // The node is actually supposed to be an identifier, not a TypeAnnotation.
4323
0
    auto optName = reparseTypeAnnotationAsIdentifierFlow(*optLeft);
4324
0
    if (!optName)
4325
0
      return None;
4326
0
    name = *optName;
4327
0
    optional = checkAndEat(TokenKind::question, JSLexer::GrammarContext::Type);
4328
0
    if (!eat(
4329
0
            TokenKind::colon,
4330
0
            JSLexer::GrammarContext::Type,
4331
0
            "in function parameter type annotation",
4332
0
            "start of parameter",
4333
0
            start))
4334
0
      return None;
4335
0
    auto optType = parseTypeAnnotationFlow();
4336
0
    if (!optType)
4337
0
      return None;
4338
0
    typeAnnotation = *optType;
4339
0
  } else {
4340
0
    typeAnnotation = *optLeft;
4341
0
  }
4342
4343
0
  return setLocation(
4344
0
      start,
4345
0
      getPrevTokenEndLoc(),
4346
0
      new (context_)
4347
0
          ESTree::FunctionTypeParamNode(name, typeAnnotation, optional));
4348
0
}
4349
4350
Optional<ESTree::GenericTypeAnnotationNode *>
4351
0
JSParserImpl::parseGenericTypeFlow() {
4352
0
  assert(check(TokenKind::identifier) || tok_->isResWord());
4353
0
  SMLoc start = tok_->getStartLoc();
4354
4355
0
  ESTree::Node *id = setLocation(
4356
0
      tok_,
4357
0
      tok_,
4358
0
      new (context_) ESTree::IdentifierNode(
4359
0
          tok_->getResWordOrIdentifier(), nullptr, false));
4360
0
  advance(JSLexer::GrammarContext::Type);
4361
4362
0
  while (checkAndEat(TokenKind::period, JSLexer::GrammarContext::Type)) {
4363
0
    if (!check(TokenKind::identifier) && !tok_->isResWord()) {
4364
0
      errorExpected(
4365
0
          TokenKind::identifier,
4366
0
          "in qualified generic type name",
4367
0
          "start of type name",
4368
0
          start);
4369
0
      return None;
4370
0
    }
4371
0
    ESTree::Node *next = setLocation(
4372
0
        tok_,
4373
0
        tok_,
4374
0
        new (context_) ESTree::IdentifierNode(
4375
0
            tok_->getResWordOrIdentifier(), nullptr, false));
4376
0
    advance(JSLexer::GrammarContext::Type);
4377
0
    id = setLocation(
4378
0
        id, next, new (context_) ESTree::QualifiedTypeIdentifierNode(id, next));
4379
0
  }
4380
4381
0
  ESTree::Node *typeParams = nullptr;
4382
0
  if (check(TokenKind::less)) {
4383
0
    auto optTypeParams = parseTypeArgsFlow();
4384
0
    if (!optTypeParams)
4385
0
      return None;
4386
0
    typeParams = *optTypeParams;
4387
0
  }
4388
4389
0
  return setLocation(
4390
0
      start,
4391
0
      getPrevTokenEndLoc(),
4392
0
      new (context_) ESTree::GenericTypeAnnotationNode(id, typeParams));
4393
0
}
4394
4395
Optional<ESTree::ClassImplementsNode *>
4396
0
JSParserImpl::parseClassImplementsFlow() {
4397
0
  assert(check(TokenKind::identifier));
4398
0
  SMLoc start = tok_->getStartLoc();
4399
4400
0
  ESTree::Node *id = setLocation(
4401
0
      tok_,
4402
0
      tok_,
4403
0
      new (context_)
4404
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
4405
0
  advance(JSLexer::GrammarContext::Type);
4406
4407
0
  ESTree::Node *typeParams = nullptr;
4408
0
  if (check(TokenKind::less)) {
4409
0
    auto optTypeParams = parseTypeArgsFlow();
4410
0
    if (!optTypeParams)
4411
0
      return None;
4412
0
    typeParams = *optTypeParams;
4413
0
  }
4414
4415
0
  return setLocation(
4416
0
      start,
4417
0
      getPrevTokenEndLoc(),
4418
0
      new (context_) ESTree::ClassImplementsNode(id, typeParams));
4419
0
}
4420
4421
0
Optional<ESTree::Node *> JSParserImpl::parsePredicateFlow() {
4422
0
  assert(check(checksIdent_));
4423
0
  SMRange checksRng = advance(JSLexer::GrammarContext::Type);
4424
0
  if (checkAndEat(TokenKind::l_paren, JSLexer::GrammarContext::AllowRegExp)) {
4425
0
    auto optCond = parseConditionalExpression();
4426
0
    if (!optCond)
4427
0
      return None;
4428
0
    SMLoc end = tok_->getEndLoc();
4429
0
    if (!eat(
4430
0
            TokenKind::r_paren,
4431
0
            JSLexer::GrammarContext::Type,
4432
0
            "in declared predicate",
4433
0
            "start of predicate",
4434
0
            checksRng.Start))
4435
0
      return None;
4436
0
    return setLocation(
4437
0
        checksRng, end, new (context_) ESTree::DeclaredPredicateNode(*optCond));
4438
0
  }
4439
0
  return setLocation(
4440
0
      checksRng, checksRng, new (context_) ESTree::InferredPredicateNode());
4441
0
}
4442
4443
Optional<UniqueString *> JSParserImpl::reparseTypeAnnotationAsIdFlow(
4444
0
    ESTree::Node *typeAnnotation) {
4445
0
  UniqueString *id = nullptr;
4446
0
  if (isa<ESTree::AnyTypeAnnotationNode>(typeAnnotation)) {
4447
0
    id = anyIdent_;
4448
0
  } else if (isa<ESTree::EmptyTypeAnnotationNode>(typeAnnotation)) {
4449
0
    id = emptyIdent_;
4450
0
  } else if (isa<ESTree::BooleanTypeAnnotationNode>(typeAnnotation)) {
4451
0
    id = booleanIdent_;
4452
0
  } else if (isa<ESTree::NumberTypeAnnotationNode>(typeAnnotation)) {
4453
0
    id = numberIdent_;
4454
0
  } else if (isa<ESTree::StringTypeAnnotationNode>(typeAnnotation)) {
4455
0
    id = stringIdent_;
4456
0
  } else if (isa<ESTree::SymbolTypeAnnotationNode>(typeAnnotation)) {
4457
0
    id = symbolIdent_;
4458
0
  } else if (isa<ESTree::NullLiteralTypeAnnotationNode>(typeAnnotation)) {
4459
0
    id = nullIdent_;
4460
0
  } else if (
4461
0
      auto *generic =
4462
0
          dyn_cast<ESTree::GenericTypeAnnotationNode>(typeAnnotation)) {
4463
0
    if (!generic->_typeParameters) {
4464
0
      if (auto *genericId = dyn_cast<ESTree::IdentifierNode>(generic->_id)) {
4465
0
        id = genericId->_name;
4466
0
      }
4467
0
    }
4468
0
  }
4469
4470
0
  if (!id) {
4471
0
    error(typeAnnotation->getSourceRange(), "identifier expected");
4472
0
    return None;
4473
0
  }
4474
4475
0
  return id;
4476
0
}
4477
4478
Optional<ESTree::IdentifierNode *>
4479
JSParserImpl::reparseTypeAnnotationAsIdentifierFlow(
4480
0
    ESTree::Node *typeAnnotation) {
4481
0
  auto idOpt = reparseTypeAnnotationAsIdFlow(typeAnnotation);
4482
0
  if (!idOpt)
4483
0
    return None;
4484
0
  UniqueString *id = *idOpt;
4485
0
  return setLocation(
4486
0
      typeAnnotation,
4487
0
      typeAnnotation,
4488
0
      new (context_) ESTree::IdentifierNode(id, nullptr, false));
4489
0
}
4490
4491
Optional<ESTree::Node *> JSParserImpl::parseEnumDeclarationFlow(
4492
    SMLoc start,
4493
0
    bool declare) {
4494
0
  assert(check(TokenKind::rw_enum));
4495
0
  advance();
4496
4497
0
  if (!check(TokenKind::identifier)) {
4498
0
    errorExpected(
4499
0
        TokenKind::identifier,
4500
0
        "in enum declaration",
4501
0
        "start of declaration",
4502
0
        start);
4503
0
    return None;
4504
0
  }
4505
0
  ESTree::Node *id = setLocation(
4506
0
      tok_,
4507
0
      tok_,
4508
0
      new (context_)
4509
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
4510
0
  advance(JSLexer::GrammarContext::Type);
4511
4512
0
  OptValue<EnumKind> optKind = llvh::None;
4513
0
  Optional<SMLoc> explicitTypeStart = None;
4514
0
  if (check(ofIdent_)) {
4515
0
    explicitTypeStart = advance().Start;
4516
4517
0
    if (checkAndEat(stringIdent_)) {
4518
0
      optKind = EnumKind::String;
4519
0
    } else if (checkAndEat(numberIdent_)) {
4520
0
      optKind = EnumKind::Number;
4521
0
    } else if (checkAndEat(bigintIdent_)) {
4522
0
      optKind = EnumKind::BigInt;
4523
0
    } else if (checkAndEat(booleanIdent_)) {
4524
0
      optKind = EnumKind::Boolean;
4525
0
    } else if (checkAndEat(symbolIdent_)) {
4526
0
      optKind = EnumKind::Symbol;
4527
0
    }
4528
0
  }
4529
4530
0
  if (!need(
4531
0
          TokenKind::l_brace,
4532
0
          "in enum declaration",
4533
0
          "start of declaration",
4534
0
          start))
4535
0
    return None;
4536
4537
0
  auto optBody = parseEnumBodyFlow(optKind, explicitTypeStart);
4538
0
  if (!optBody)
4539
0
    return None;
4540
4541
0
  if (declare)
4542
0
    return setLocation(
4543
0
        start, *optBody, new (context_) ESTree::DeclareEnumNode(id, *optBody));
4544
0
  return setLocation(
4545
0
      start,
4546
0
      *optBody,
4547
0
      new (context_) ESTree::EnumDeclarationNode(id, *optBody));
4548
0
}
4549
4550
Optional<ESTree::Node *> JSParserImpl::parseEnumBodyFlow(
4551
    OptValue<EnumKind> optKind,
4552
0
    Optional<SMLoc> explicitTypeStart) {
4553
0
  assert(check(TokenKind::l_brace));
4554
0
  SMLoc start = advance().Start;
4555
4556
0
  ESTree::NodeList members{};
4557
0
  bool hasUnknownMembers = false;
4558
0
  while (!check(TokenKind::r_brace)) {
4559
0
    if (check(TokenKind::dotdotdot)) {
4560
0
      SMLoc dotdotdotLoc = advance(JSLexer::GrammarContext::Type).Start;
4561
0
      if (!check(TokenKind::r_brace)) {
4562
0
        error(
4563
0
            dotdotdotLoc,
4564
0
            "The `...` must come after all enum members. "
4565
0
            "Move it to the end of the enum body.");
4566
0
        return None;
4567
0
      }
4568
0
      hasUnknownMembers = true;
4569
0
      break;
4570
0
    }
4571
0
    if (!need(
4572
0
            TokenKind::identifier,
4573
0
            "in enum declaration",
4574
0
            "start of declaration",
4575
0
            start))
4576
0
      return None;
4577
4578
0
    auto optMember = parseEnumMemberFlow();
4579
0
    if (!optMember)
4580
0
      return None;
4581
0
    ESTree::Node *member = *optMember;
4582
0
    OptValue<EnumKind> optMemberKind = getMemberEnumKindFlow(member);
4583
4584
0
    if (optKind.hasValue()) {
4585
      // We've already figured out the type of the enum, so ensure that the
4586
      // new member is compatible with this.
4587
0
      if (optMemberKind.hasValue()) {
4588
0
        if (*optKind != *optMemberKind) {
4589
0
          error(
4590
0
              member->getSourceRange(),
4591
0
              llvh::Twine("cannot use ") + enumKindStrFlow(*optMemberKind) +
4592
0
                  " initializer in " + enumKindStrFlow(*optKind) + " enum");
4593
0
          sm_.note(start, "start of enum body", Subsystem::Parser);
4594
0
          return None;
4595
0
        }
4596
0
      }
4597
0
    } else {
4598
0
      optKind = optMemberKind;
4599
0
    }
4600
4601
0
    members.push_back(*member);
4602
0
    if (!checkAndEat(TokenKind::comma))
4603
0
      break;
4604
0
  }
4605
4606
0
  if (!members.empty()) {
4607
    // Ensure that enum members use initializers consistently.
4608
    // This is vacuously true when `members` is empty, so just make sure
4609
    // all members use initializers iff the first member does.
4610
0
    bool usesInitializers =
4611
0
        !isa<ESTree::EnumDefaultedMemberNode>(members.front());
4612
0
    for (const ESTree::Node &member : members) {
4613
0
      if (usesInitializers != !isa<ESTree::EnumDefaultedMemberNode>(member)) {
4614
0
        error(
4615
0
            member.getSourceRange(),
4616
0
            "enum members need to consistently either all use initializers, "
4617
0
            "or use no initializers");
4618
0
        sm_.note(
4619
0
            members.front().getSourceRange(),
4620
0
            "first enum member",
4621
0
            Subsystem::Parser);
4622
0
        return None;
4623
0
      }
4624
0
    }
4625
4626
0
    if (!usesInitializers) {
4627
      // It's only legal to use defaulted members for string and symbol enums,
4628
      // because other kinds of enums can't infer values from names.
4629
0
      if (optKind.hasValue() && *optKind != EnumKind::String &&
4630
0
          *optKind != EnumKind::Symbol) {
4631
0
        error(start, "number and boolean enums must use initializers");
4632
0
        return None;
4633
0
      }
4634
0
    }
4635
0
  }
4636
4637
0
  SMLoc end = tok_->getEndLoc();
4638
0
  if (!eat(
4639
0
          TokenKind::r_brace,
4640
0
          JSLexer::GrammarContext::AllowRegExp,
4641
0
          "in enum body",
4642
0
          "start of body",
4643
0
          start))
4644
0
    return None;
4645
4646
0
  bool hasExplicitType = explicitTypeStart.hasValue();
4647
0
  if (hasExplicitType) {
4648
0
    start = *explicitTypeStart;
4649
0
  }
4650
4651
0
  if (!optKind.hasValue()) {
4652
0
    return setLocation(
4653
0
        start,
4654
0
        end,
4655
0
        new (context_) ESTree::EnumStringBodyNode(
4656
0
            std::move(members), hasExplicitType, hasUnknownMembers));
4657
0
  }
4658
4659
  // There are different node kinds per enum kind.
4660
0
  switch (*optKind) {
4661
0
    case EnumKind::String:
4662
0
      return setLocation(
4663
0
          start,
4664
0
          end,
4665
0
          new (context_) ESTree::EnumStringBodyNode(
4666
0
              std::move(members), hasExplicitType, hasUnknownMembers));
4667
0
    case EnumKind::Number:
4668
0
      return setLocation(
4669
0
          start,
4670
0
          end,
4671
0
          new (context_) ESTree::EnumNumberBodyNode(
4672
0
              std::move(members), hasExplicitType, hasUnknownMembers));
4673
0
    case EnumKind::BigInt:
4674
0
      return setLocation(
4675
0
          start,
4676
0
          end,
4677
0
          new (context_) ESTree::EnumBigIntBodyNode(
4678
0
              std::move(members), hasExplicitType, hasUnknownMembers));
4679
0
    case EnumKind::Boolean:
4680
0
      return setLocation(
4681
0
          start,
4682
0
          end,
4683
0
          new (context_) ESTree::EnumBooleanBodyNode(
4684
0
              std::move(members), hasExplicitType, hasUnknownMembers));
4685
0
    case EnumKind::Symbol:
4686
0
      assert(
4687
0
          hasExplicitType && "symbol enums can only be made via explicit type");
4688
0
      return setLocation(
4689
0
          start,
4690
0
          end,
4691
0
          new (context_) ESTree::EnumSymbolBodyNode(
4692
0
              std::move(members), hasUnknownMembers));
4693
0
  }
4694
0
  llvm_unreachable("No other kind of enum");
4695
0
}
4696
4697
0
Optional<ESTree::Node *> JSParserImpl::parseEnumMemberFlow() {
4698
0
  assert(check(TokenKind::identifier));
4699
0
  ESTree::Node *id = setLocation(
4700
0
      tok_,
4701
0
      tok_,
4702
0
      new (context_)
4703
0
          ESTree::IdentifierNode(tok_->getIdentifier(), nullptr, false));
4704
0
  advance();
4705
4706
0
  ESTree::Node *member = nullptr;
4707
0
  if (checkAndEat(TokenKind::equal)) {
4708
    // Parse initializer.
4709
0
    if (check(TokenKind::rw_true, TokenKind::rw_false)) {
4710
0
      ESTree::Node *init = setLocation(
4711
0
          tok_,
4712
0
          tok_,
4713
0
          new (context_) ESTree::BooleanLiteralNode(check(TokenKind::rw_true)));
4714
0
      member = setLocation(
4715
0
          id, tok_, new (context_) ESTree::EnumBooleanMemberNode(id, init));
4716
0
    } else if (check(TokenKind::string_literal)) {
4717
0
      ESTree::Node *init = setLocation(
4718
0
          tok_,
4719
0
          tok_,
4720
0
          new (context_) ESTree::StringLiteralNode(tok_->getStringLiteral()));
4721
0
      member = setLocation(
4722
0
          id, tok_, new (context_) ESTree::EnumStringMemberNode(id, init));
4723
0
    } else if (check(TokenKind::minus)) {
4724
0
      SMLoc start = tok_->getStartLoc();
4725
0
      advance();
4726
0
      if (check(TokenKind::numeric_literal)) {
4727
        // Negate the literal.
4728
0
        double value = -tok_->getNumericLiteral();
4729
0
        ESTree::Node *init = setLocation(
4730
0
            start, tok_, new (context_) ESTree::NumericLiteralNode(value));
4731
0
        member = setLocation(
4732
0
            id, tok_, new (context_) ESTree::EnumNumberMemberNode(id, init));
4733
0
      } else {
4734
0
        errorExpected(
4735
0
            TokenKind::numeric_literal,
4736
0
            "in negated enum member initializer",
4737
0
            "start of negated enum member",
4738
0
            id->getStartLoc());
4739
0
        return None;
4740
0
      }
4741
0
    } else if (check(TokenKind::numeric_literal)) {
4742
0
      ESTree::Node *init = setLocation(
4743
0
          tok_,
4744
0
          tok_,
4745
0
          new (context_) ESTree::NumericLiteralNode(tok_->getNumericLiteral()));
4746
0
      member = setLocation(
4747
0
          id, tok_, new (context_) ESTree::EnumNumberMemberNode(id, init));
4748
0
    } else if (check(TokenKind::bigint_literal)) {
4749
0
      ESTree::Node *init = setLocation(
4750
0
          tok_,
4751
0
          tok_,
4752
0
          new (context_) ESTree::BigIntLiteralNode(tok_->getBigIntLiteral()));
4753
0
      member = setLocation(
4754
0
          id, tok_, new (context_) ESTree::EnumBigIntMemberNode(id, init));
4755
0
    } else {
4756
0
      errorExpected(
4757
0
          {TokenKind::rw_true,
4758
0
           TokenKind::rw_false,
4759
0
           TokenKind::string_literal,
4760
0
           TokenKind::numeric_literal,
4761
0
           TokenKind::bigint_literal},
4762
0
          "in enum member initializer",
4763
0
          "start of enum member",
4764
0
          id->getStartLoc());
4765
0
      return None;
4766
0
    }
4767
0
    advance();
4768
0
  } else {
4769
0
    member =
4770
0
        setLocation(id, id, new (context_) ESTree::EnumDefaultedMemberNode(id));
4771
0
  }
4772
4773
0
  assert(member != nullptr && "member must have been parsed");
4774
0
  return member;
4775
0
}
4776
4777
#endif
4778
4779
} // namespace detail
4780
} // namespace parser
4781
} // namespace hermes