UNPKG

25.5 kBJavaScriptView Raw
1/* eslint max-len: 0 */
2
3import {
4 eat,
5 lookaheadType,
6 lookaheadTypeAndKeyword,
7 match,
8 next,
9 popTypeContext,
10 pushTypeContext,
11
12} from "../tokenizer/index";
13import {ContextualKeyword} from "../tokenizer/keywords";
14import {TokenType, TokenType as tt} from "../tokenizer/types";
15import {input, state} from "../traverser/base";
16import {
17 baseParseMaybeAssign,
18 baseParseSubscript,
19 baseParseSubscripts,
20 parseArrow,
21 parseArrowExpression,
22 parseCallExpressionArguments,
23 parseExprAtom,
24 parseExpression,
25 parseFunctionBody,
26 parseIdentifier,
27 parseLiteral,
28
29} from "../traverser/expression";
30import {
31 baseParseExportStar,
32 parseExport,
33 parseExportFrom,
34 parseExportSpecifiers,
35 parseFunctionParams,
36 parseImport,
37 parseStatement,
38} from "../traverser/statement";
39import {
40 canInsertSemicolon,
41 eatContextual,
42 expect,
43 expectContextual,
44 isContextual,
45 isLookaheadContextual,
46 semicolon,
47 unexpected,
48} from "../traverser/util";
49
50function isMaybeDefaultImport(lookahead) {
51 return (
52 (lookahead.type === tt.name || !!(lookahead.type & TokenType.IS_KEYWORD)) &&
53 lookahead.contextualKeyword !== ContextualKeyword._from
54 );
55}
56
57function flowParseTypeInitialiser(tok) {
58 const oldIsType = pushTypeContext(0);
59 expect(tok || tt.colon);
60 flowParseType();
61 popTypeContext(oldIsType);
62}
63
64function flowParsePredicate() {
65 expect(tt.modulo);
66 expectContextual(ContextualKeyword._checks);
67 if (eat(tt.parenL)) {
68 parseExpression();
69 expect(tt.parenR);
70 }
71}
72
73function flowParseTypeAndPredicateInitialiser() {
74 const oldIsType = pushTypeContext(0);
75 expect(tt.colon);
76 if (match(tt.modulo)) {
77 flowParsePredicate();
78 } else {
79 flowParseType();
80 if (match(tt.modulo)) {
81 flowParsePredicate();
82 }
83 }
84 popTypeContext(oldIsType);
85}
86
87function flowParseDeclareClass() {
88 next();
89 flowParseInterfaceish(/* isClass */ true);
90}
91
92function flowParseDeclareFunction() {
93 next();
94 parseIdentifier();
95
96 if (match(tt.lessThan)) {
97 flowParseTypeParameterDeclaration();
98 }
99
100 expect(tt.parenL);
101 flowParseFunctionTypeParams();
102 expect(tt.parenR);
103
104 flowParseTypeAndPredicateInitialiser();
105
106 semicolon();
107}
108
109function flowParseDeclare() {
110 if (match(tt._class)) {
111 flowParseDeclareClass();
112 } else if (match(tt._function)) {
113 flowParseDeclareFunction();
114 } else if (match(tt._var)) {
115 flowParseDeclareVariable();
116 } else if (eatContextual(ContextualKeyword._module)) {
117 if (eat(tt.dot)) {
118 flowParseDeclareModuleExports();
119 } else {
120 flowParseDeclareModule();
121 }
122 } else if (isContextual(ContextualKeyword._type)) {
123 flowParseDeclareTypeAlias();
124 } else if (isContextual(ContextualKeyword._opaque)) {
125 flowParseDeclareOpaqueType();
126 } else if (isContextual(ContextualKeyword._interface)) {
127 flowParseDeclareInterface();
128 } else if (match(tt._export)) {
129 flowParseDeclareExportDeclaration();
130 } else {
131 unexpected();
132 }
133}
134
135function flowParseDeclareVariable() {
136 next();
137 flowParseTypeAnnotatableIdentifier();
138 semicolon();
139}
140
141function flowParseDeclareModule() {
142 if (match(tt.string)) {
143 parseExprAtom();
144 } else {
145 parseIdentifier();
146 }
147
148 expect(tt.braceL);
149 while (!match(tt.braceR) && !state.error) {
150 if (match(tt._import)) {
151 next();
152 parseImport();
153 } else {
154 unexpected();
155 }
156 }
157 expect(tt.braceR);
158}
159
160function flowParseDeclareExportDeclaration() {
161 expect(tt._export);
162
163 if (eat(tt._default)) {
164 if (match(tt._function) || match(tt._class)) {
165 // declare export default class ...
166 // declare export default function ...
167 flowParseDeclare();
168 } else {
169 // declare export default [type];
170 flowParseType();
171 semicolon();
172 }
173 } else if (
174 match(tt._var) || // declare export var ...
175 match(tt._function) || // declare export function ...
176 match(tt._class) || // declare export class ...
177 isContextual(ContextualKeyword._opaque) // declare export opaque ..
178 ) {
179 flowParseDeclare();
180 } else if (
181 match(tt.star) || // declare export * from ''
182 match(tt.braceL) || // declare export {} ...
183 isContextual(ContextualKeyword._interface) || // declare export interface ...
184 isContextual(ContextualKeyword._type) || // declare export type ...
185 isContextual(ContextualKeyword._opaque) // declare export opaque type ...
186 ) {
187 parseExport();
188 } else {
189 unexpected();
190 }
191}
192
193function flowParseDeclareModuleExports() {
194 expectContextual(ContextualKeyword._exports);
195 flowParseTypeAnnotation();
196 semicolon();
197}
198
199function flowParseDeclareTypeAlias() {
200 next();
201 flowParseTypeAlias();
202}
203
204function flowParseDeclareOpaqueType() {
205 next();
206 flowParseOpaqueType(true);
207}
208
209function flowParseDeclareInterface() {
210 next();
211 flowParseInterfaceish();
212}
213
214// Interfaces
215
216function flowParseInterfaceish(isClass = false) {
217 flowParseRestrictedIdentifier();
218
219 if (match(tt.lessThan)) {
220 flowParseTypeParameterDeclaration();
221 }
222
223 if (eat(tt._extends)) {
224 do {
225 flowParseInterfaceExtends();
226 } while (!isClass && eat(tt.comma));
227 }
228
229 if (isContextual(ContextualKeyword._mixins)) {
230 next();
231 do {
232 flowParseInterfaceExtends();
233 } while (eat(tt.comma));
234 }
235
236 if (isContextual(ContextualKeyword._implements)) {
237 next();
238 do {
239 flowParseInterfaceExtends();
240 } while (eat(tt.comma));
241 }
242
243 flowParseObjectType(isClass, false, isClass);
244}
245
246function flowParseInterfaceExtends() {
247 flowParseQualifiedTypeIdentifier(false);
248 if (match(tt.lessThan)) {
249 flowParseTypeParameterInstantiation();
250 }
251}
252
253function flowParseInterface() {
254 flowParseInterfaceish();
255}
256
257function flowParseRestrictedIdentifier() {
258 parseIdentifier();
259}
260
261function flowParseTypeAlias() {
262 flowParseRestrictedIdentifier();
263
264 if (match(tt.lessThan)) {
265 flowParseTypeParameterDeclaration();
266 }
267
268 flowParseTypeInitialiser(tt.eq);
269 semicolon();
270}
271
272function flowParseOpaqueType(declare) {
273 expectContextual(ContextualKeyword._type);
274 flowParseRestrictedIdentifier();
275
276 if (match(tt.lessThan)) {
277 flowParseTypeParameterDeclaration();
278 }
279
280 // Parse the supertype
281 if (match(tt.colon)) {
282 flowParseTypeInitialiser(tt.colon);
283 }
284
285 if (!declare) {
286 flowParseTypeInitialiser(tt.eq);
287 }
288 semicolon();
289}
290
291function flowParseTypeParameter() {
292 flowParseVariance();
293 flowParseTypeAnnotatableIdentifier();
294
295 if (eat(tt.eq)) {
296 flowParseType();
297 }
298}
299
300export function flowParseTypeParameterDeclaration() {
301 const oldIsType = pushTypeContext(0);
302 // istanbul ignore else: this condition is already checked at all call sites
303 if (match(tt.lessThan) || match(tt.typeParameterStart)) {
304 next();
305 } else {
306 unexpected();
307 }
308
309 do {
310 flowParseTypeParameter();
311 if (!match(tt.greaterThan)) {
312 expect(tt.comma);
313 }
314 } while (!match(tt.greaterThan) && !state.error);
315 expect(tt.greaterThan);
316 popTypeContext(oldIsType);
317}
318
319function flowParseTypeParameterInstantiation() {
320 const oldIsType = pushTypeContext(0);
321 expect(tt.lessThan);
322 while (!match(tt.greaterThan) && !state.error) {
323 flowParseType();
324 if (!match(tt.greaterThan)) {
325 expect(tt.comma);
326 }
327 }
328 expect(tt.greaterThan);
329 popTypeContext(oldIsType);
330}
331
332function flowParseInterfaceType() {
333 expectContextual(ContextualKeyword._interface);
334 if (eat(tt._extends)) {
335 do {
336 flowParseInterfaceExtends();
337 } while (eat(tt.comma));
338 }
339 flowParseObjectType(false, false, false);
340}
341
342function flowParseObjectPropertyKey() {
343 if (match(tt.num) || match(tt.string)) {
344 parseExprAtom();
345 } else {
346 parseIdentifier();
347 }
348}
349
350function flowParseObjectTypeIndexer() {
351 // Note: bracketL has already been consumed
352 if (lookaheadType() === tt.colon) {
353 flowParseObjectPropertyKey();
354 flowParseTypeInitialiser();
355 } else {
356 flowParseType();
357 }
358 expect(tt.bracketR);
359 flowParseTypeInitialiser();
360}
361
362function flowParseObjectTypeInternalSlot() {
363 // Note: both bracketL have already been consumed
364 flowParseObjectPropertyKey();
365 expect(tt.bracketR);
366 expect(tt.bracketR);
367 if (match(tt.lessThan) || match(tt.parenL)) {
368 flowParseObjectTypeMethodish();
369 } else {
370 eat(tt.question);
371 flowParseTypeInitialiser();
372 }
373}
374
375function flowParseObjectTypeMethodish() {
376 if (match(tt.lessThan)) {
377 flowParseTypeParameterDeclaration();
378 }
379
380 expect(tt.parenL);
381 while (!match(tt.parenR) && !match(tt.ellipsis) && !state.error) {
382 flowParseFunctionTypeParam();
383 if (!match(tt.parenR)) {
384 expect(tt.comma);
385 }
386 }
387
388 if (eat(tt.ellipsis)) {
389 flowParseFunctionTypeParam();
390 }
391 expect(tt.parenR);
392 flowParseTypeInitialiser();
393}
394
395function flowParseObjectTypeCallProperty() {
396 flowParseObjectTypeMethodish();
397}
398
399function flowParseObjectType(allowStatic, allowExact, allowProto) {
400 let endDelim;
401 if (allowExact && match(tt.braceBarL)) {
402 expect(tt.braceBarL);
403 endDelim = tt.braceBarR;
404 } else {
405 expect(tt.braceL);
406 endDelim = tt.braceR;
407 }
408
409 while (!match(endDelim) && !state.error) {
410 if (allowProto && isContextual(ContextualKeyword._proto)) {
411 const lookahead = lookaheadType();
412 if (lookahead !== tt.colon && lookahead !== tt.question) {
413 next();
414 allowStatic = false;
415 }
416 }
417 if (allowStatic && isContextual(ContextualKeyword._static)) {
418 const lookahead = lookaheadType();
419 if (lookahead !== tt.colon && lookahead !== tt.question) {
420 next();
421 }
422 }
423
424 flowParseVariance();
425
426 if (eat(tt.bracketL)) {
427 if (eat(tt.bracketL)) {
428 flowParseObjectTypeInternalSlot();
429 } else {
430 flowParseObjectTypeIndexer();
431 }
432 } else if (match(tt.parenL) || match(tt.lessThan)) {
433 flowParseObjectTypeCallProperty();
434 } else {
435 if (isContextual(ContextualKeyword._get) || isContextual(ContextualKeyword._set)) {
436 const lookahead = lookaheadType();
437 if (lookahead === tt.name || lookahead === tt.string || lookahead === tt.num) {
438 next();
439 }
440 }
441
442 flowParseObjectTypeProperty();
443 }
444
445 flowObjectTypeSemicolon();
446 }
447
448 expect(endDelim);
449}
450
451function flowParseObjectTypeProperty() {
452 if (match(tt.ellipsis)) {
453 expect(tt.ellipsis);
454 if (!eat(tt.comma)) {
455 eat(tt.semi);
456 }
457 // Explicit inexact object syntax.
458 if (match(tt.braceR)) {
459 return;
460 }
461 flowParseType();
462 } else {
463 flowParseObjectPropertyKey();
464 if (match(tt.lessThan) || match(tt.parenL)) {
465 // This is a method property
466 flowParseObjectTypeMethodish();
467 } else {
468 eat(tt.question);
469 flowParseTypeInitialiser();
470 }
471 }
472}
473
474function flowObjectTypeSemicolon() {
475 if (!eat(tt.semi) && !eat(tt.comma) && !match(tt.braceR) && !match(tt.braceBarR)) {
476 unexpected();
477 }
478}
479
480function flowParseQualifiedTypeIdentifier(initialIdAlreadyParsed) {
481 if (!initialIdAlreadyParsed) {
482 parseIdentifier();
483 }
484 while (eat(tt.dot)) {
485 parseIdentifier();
486 }
487}
488
489function flowParseGenericType() {
490 flowParseQualifiedTypeIdentifier(true);
491 if (match(tt.lessThan)) {
492 flowParseTypeParameterInstantiation();
493 }
494}
495
496function flowParseTypeofType() {
497 expect(tt._typeof);
498 flowParsePrimaryType();
499}
500
501function flowParseTupleType() {
502 expect(tt.bracketL);
503 // We allow trailing commas
504 while (state.pos < input.length && !match(tt.bracketR)) {
505 flowParseType();
506 if (match(tt.bracketR)) {
507 break;
508 }
509 expect(tt.comma);
510 }
511 expect(tt.bracketR);
512}
513
514function flowParseFunctionTypeParam() {
515 const lookahead = lookaheadType();
516 if (lookahead === tt.colon || lookahead === tt.question) {
517 parseIdentifier();
518 eat(tt.question);
519 flowParseTypeInitialiser();
520 } else {
521 flowParseType();
522 }
523}
524
525function flowParseFunctionTypeParams() {
526 while (!match(tt.parenR) && !match(tt.ellipsis) && !state.error) {
527 flowParseFunctionTypeParam();
528 if (!match(tt.parenR)) {
529 expect(tt.comma);
530 }
531 }
532 if (eat(tt.ellipsis)) {
533 flowParseFunctionTypeParam();
534 }
535}
536
537// The parsing of types roughly parallels the parsing of expressions, and
538// primary types are kind of like primary expressions...they're the
539// primitives with which other types are constructed.
540function flowParsePrimaryType() {
541 let isGroupedType = false;
542 const oldNoAnonFunctionType = state.noAnonFunctionType;
543
544 switch (state.type) {
545 case tt.name: {
546 if (isContextual(ContextualKeyword._interface)) {
547 flowParseInterfaceType();
548 return;
549 }
550 parseIdentifier();
551 flowParseGenericType();
552 return;
553 }
554
555 case tt.braceL:
556 flowParseObjectType(false, false, false);
557 return;
558
559 case tt.braceBarL:
560 flowParseObjectType(false, true, false);
561 return;
562
563 case tt.bracketL:
564 flowParseTupleType();
565 return;
566
567 case tt.lessThan:
568 flowParseTypeParameterDeclaration();
569 expect(tt.parenL);
570 flowParseFunctionTypeParams();
571 expect(tt.parenR);
572 expect(tt.arrow);
573 flowParseType();
574 return;
575
576 case tt.parenL:
577 next();
578
579 // Check to see if this is actually a grouped type
580 if (!match(tt.parenR) && !match(tt.ellipsis)) {
581 if (match(tt.name)) {
582 const token = lookaheadType();
583 isGroupedType = token !== tt.question && token !== tt.colon;
584 } else {
585 isGroupedType = true;
586 }
587 }
588
589 if (isGroupedType) {
590 state.noAnonFunctionType = false;
591 flowParseType();
592 state.noAnonFunctionType = oldNoAnonFunctionType;
593
594 // A `,` or a `) =>` means this is an anonymous function type
595 if (
596 state.noAnonFunctionType ||
597 !(match(tt.comma) || (match(tt.parenR) && lookaheadType() === tt.arrow))
598 ) {
599 expect(tt.parenR);
600 return;
601 } else {
602 // Eat a comma if there is one
603 eat(tt.comma);
604 }
605 }
606
607 flowParseFunctionTypeParams();
608
609 expect(tt.parenR);
610 expect(tt.arrow);
611 flowParseType();
612 return;
613
614 case tt.minus:
615 next();
616 parseLiteral();
617 return;
618
619 case tt.string:
620 case tt.num:
621 case tt._true:
622 case tt._false:
623 case tt._null:
624 case tt._this:
625 case tt._void:
626 case tt.star:
627 next();
628 return;
629
630 default:
631 if (state.type === tt._typeof) {
632 flowParseTypeofType();
633 return;
634 } else if (state.type & TokenType.IS_KEYWORD) {
635 next();
636 state.tokens[state.tokens.length - 1].type = tt.name;
637 return;
638 }
639 }
640
641 unexpected();
642}
643
644function flowParsePostfixType() {
645 flowParsePrimaryType();
646 while (!canInsertSemicolon() && match(tt.bracketL)) {
647 expect(tt.bracketL);
648 expect(tt.bracketR);
649 }
650}
651
652function flowParsePrefixType() {
653 if (eat(tt.question)) {
654 flowParsePrefixType();
655 } else {
656 flowParsePostfixType();
657 }
658}
659
660function flowParseAnonFunctionWithoutParens() {
661 flowParsePrefixType();
662 if (!state.noAnonFunctionType && eat(tt.arrow)) {
663 flowParseType();
664 }
665}
666
667function flowParseIntersectionType() {
668 eat(tt.bitwiseAND);
669 flowParseAnonFunctionWithoutParens();
670 while (eat(tt.bitwiseAND)) {
671 flowParseAnonFunctionWithoutParens();
672 }
673}
674
675function flowParseUnionType() {
676 eat(tt.bitwiseOR);
677 flowParseIntersectionType();
678 while (eat(tt.bitwiseOR)) {
679 flowParseIntersectionType();
680 }
681}
682
683function flowParseType() {
684 flowParseUnionType();
685}
686
687export function flowParseTypeAnnotation() {
688 flowParseTypeInitialiser();
689}
690
691function flowParseTypeAnnotatableIdentifier() {
692 parseIdentifier();
693 if (match(tt.colon)) {
694 flowParseTypeAnnotation();
695 }
696}
697
698export function flowParseVariance() {
699 if (match(tt.plus) || match(tt.minus)) {
700 next();
701 }
702}
703
704// ==================================
705// Overrides
706// ==================================
707
708export function flowParseFunctionBodyAndFinish(funcContextId) {
709 // For arrow functions, `parseArrow` handles the return type itself.
710 if (match(tt.colon)) {
711 flowParseTypeAndPredicateInitialiser();
712 }
713
714 parseFunctionBody(false, funcContextId);
715}
716
717export function flowParseSubscript(
718 startTokenIndex,
719 noCalls,
720 stopState,
721) {
722 if (match(tt.questionDot) && lookaheadType() === tt.lessThan) {
723 if (noCalls) {
724 stopState.stop = true;
725 return;
726 }
727 next();
728 flowParseTypeParameterInstantiation();
729 expect(tt.parenL);
730 parseCallExpressionArguments();
731 return;
732 } else if (!noCalls && match(tt.lessThan)) {
733 const snapshot = state.snapshot();
734 flowParseTypeParameterInstantiation();
735 expect(tt.parenL);
736 parseCallExpressionArguments();
737 if (state.error) {
738 state.restoreFromSnapshot(snapshot);
739 } else {
740 return;
741 }
742 }
743 baseParseSubscript(startTokenIndex, noCalls, stopState);
744}
745
746export function flowStartParseNewArguments() {
747 if (match(tt.lessThan)) {
748 const snapshot = state.snapshot();
749 flowParseTypeParameterInstantiation();
750 if (state.error) {
751 state.restoreFromSnapshot(snapshot);
752 }
753 }
754}
755
756// interfaces
757export function flowTryParseStatement() {
758 if (match(tt.name) && state.contextualKeyword === ContextualKeyword._interface) {
759 const oldIsType = pushTypeContext(0);
760 next();
761 flowParseInterface();
762 popTypeContext(oldIsType);
763 return true;
764 } else {
765 return false;
766 }
767}
768
769// declares, interfaces and type aliases
770export function flowParseIdentifierStatement(contextualKeyword) {
771 if (contextualKeyword === ContextualKeyword._declare) {
772 if (
773 match(tt._class) ||
774 match(tt.name) ||
775 match(tt._function) ||
776 match(tt._var) ||
777 match(tt._export)
778 ) {
779 const oldIsType = pushTypeContext(1);
780 flowParseDeclare();
781 popTypeContext(oldIsType);
782 }
783 } else if (match(tt.name)) {
784 if (contextualKeyword === ContextualKeyword._interface) {
785 const oldIsType = pushTypeContext(1);
786 flowParseInterface();
787 popTypeContext(oldIsType);
788 } else if (contextualKeyword === ContextualKeyword._type) {
789 const oldIsType = pushTypeContext(1);
790 flowParseTypeAlias();
791 popTypeContext(oldIsType);
792 } else if (contextualKeyword === ContextualKeyword._opaque) {
793 const oldIsType = pushTypeContext(1);
794 flowParseOpaqueType(false);
795 popTypeContext(oldIsType);
796 }
797 }
798 semicolon();
799}
800
801// export type
802export function flowShouldParseExportDeclaration() {
803 return (
804 isContextual(ContextualKeyword._type) ||
805 isContextual(ContextualKeyword._interface) ||
806 isContextual(ContextualKeyword._opaque)
807 );
808}
809
810export function flowShouldDisallowExportDefaultSpecifier() {
811 return (
812 match(tt.name) &&
813 (state.contextualKeyword === ContextualKeyword._type ||
814 state.contextualKeyword === ContextualKeyword._interface ||
815 state.contextualKeyword === ContextualKeyword._opaque)
816 );
817}
818
819export function flowParseExportDeclaration() {
820 if (isContextual(ContextualKeyword._type)) {
821 const oldIsType = pushTypeContext(1);
822 next();
823
824 if (match(tt.braceL)) {
825 // export type { foo, bar };
826 parseExportSpecifiers();
827 parseExportFrom();
828 } else {
829 // export type Foo = Bar;
830 flowParseTypeAlias();
831 }
832 popTypeContext(oldIsType);
833 } else if (isContextual(ContextualKeyword._opaque)) {
834 const oldIsType = pushTypeContext(1);
835 next();
836 // export opaque type Foo = Bar;
837 flowParseOpaqueType(false);
838 popTypeContext(oldIsType);
839 } else if (isContextual(ContextualKeyword._interface)) {
840 const oldIsType = pushTypeContext(1);
841 next();
842 flowParseInterface();
843 popTypeContext(oldIsType);
844 } else {
845 parseStatement(true);
846 }
847}
848
849export function flowShouldParseExportStar() {
850 return match(tt.star) || (isContextual(ContextualKeyword._type) && lookaheadType() === tt.star);
851}
852
853export function flowParseExportStar() {
854 if (eatContextual(ContextualKeyword._type)) {
855 const oldIsType = pushTypeContext(2);
856 baseParseExportStar();
857 popTypeContext(oldIsType);
858 } else {
859 baseParseExportStar();
860 }
861}
862
863// parse a the super class type parameters and implements
864export function flowAfterParseClassSuper(hasSuper) {
865 if (hasSuper && match(tt.lessThan)) {
866 flowParseTypeParameterInstantiation();
867 }
868 if (isContextual(ContextualKeyword._implements)) {
869 const oldIsType = pushTypeContext(0);
870 next();
871 state.tokens[state.tokens.length - 1].type = tt._implements;
872 do {
873 flowParseRestrictedIdentifier();
874 if (match(tt.lessThan)) {
875 flowParseTypeParameterInstantiation();
876 }
877 } while (eat(tt.comma));
878 popTypeContext(oldIsType);
879 }
880}
881
882// parse type parameters for object method shorthand
883export function flowStartParseObjPropValue() {
884 // method shorthand
885 if (match(tt.lessThan)) {
886 flowParseTypeParameterDeclaration();
887 if (!match(tt.parenL)) unexpected();
888 }
889}
890
891export function flowParseAssignableListItemTypes() {
892 const oldIsType = pushTypeContext(0);
893 eat(tt.question);
894 if (match(tt.colon)) {
895 flowParseTypeAnnotation();
896 }
897 popTypeContext(oldIsType);
898}
899
900// parse typeof and type imports
901export function flowStartParseImportSpecifiers() {
902 if (match(tt._typeof) || isContextual(ContextualKeyword._type)) {
903 const lh = lookaheadTypeAndKeyword();
904 if (isMaybeDefaultImport(lh) || lh.type === tt.braceL || lh.type === tt.star) {
905 next();
906 }
907 }
908}
909
910// parse import-type/typeof shorthand
911export function flowParseImportSpecifier() {
912 const isTypeKeyword =
913 state.contextualKeyword === ContextualKeyword._type || state.type === tt._typeof;
914 if (isTypeKeyword) {
915 next();
916 } else {
917 parseIdentifier();
918 }
919
920 if (isContextual(ContextualKeyword._as) && !isLookaheadContextual(ContextualKeyword._as)) {
921 parseIdentifier();
922 if (isTypeKeyword && !match(tt.name) && !(state.type & TokenType.IS_KEYWORD)) {
923 // `import {type as ,` or `import {type as }`
924 } else {
925 // `import {type as foo`
926 parseIdentifier();
927 }
928 } else if (isTypeKeyword && (match(tt.name) || !!(state.type & TokenType.IS_KEYWORD))) {
929 // `import {type foo`
930 parseIdentifier();
931 if (eatContextual(ContextualKeyword._as)) {
932 parseIdentifier();
933 }
934 }
935}
936
937// parse function type parameters - function foo<T>() {}
938export function flowStartParseFunctionParams() {
939 // Originally this checked if the method is a getter/setter, but if it was, we'd crash soon
940 // anyway, so don't try to propagate that information.
941 if (match(tt.lessThan)) {
942 const oldIsType = pushTypeContext(0);
943 flowParseTypeParameterDeclaration();
944 popTypeContext(oldIsType);
945 }
946}
947
948// parse flow type annotations on variable declarator heads - let foo: string = bar
949export function flowAfterParseVarHead() {
950 if (match(tt.colon)) {
951 flowParseTypeAnnotation();
952 }
953}
954
955// parse the return type of an async arrow function - let foo = (async (): number => {});
956export function flowStartParseAsyncArrowFromCallExpression() {
957 if (match(tt.colon)) {
958 const oldNoAnonFunctionType = state.noAnonFunctionType;
959 state.noAnonFunctionType = true;
960 flowParseTypeAnnotation();
961 state.noAnonFunctionType = oldNoAnonFunctionType;
962 }
963}
964
965// We need to support type parameter declarations for arrow functions. This
966// is tricky. There are three situations we need to handle
967//
968// 1. This is either JSX or an arrow function. We'll try JSX first. If that
969// fails, we'll try an arrow function. If that fails, we'll throw the JSX
970// error.
971// 2. This is an arrow function. We'll parse the type parameter declaration,
972// parse the rest, make sure the rest is an arrow function, and go from
973// there
974// 3. This is neither. Just call the super method
975export function flowParseMaybeAssign(noIn, isWithinParens) {
976 if (match(tt.lessThan)) {
977 const snapshot = state.snapshot();
978 let wasArrow = baseParseMaybeAssign(noIn, isWithinParens);
979 if (state.error) {
980 state.restoreFromSnapshot(snapshot);
981 state.type = tt.typeParameterStart;
982 } else {
983 return wasArrow;
984 }
985
986 const oldIsType = pushTypeContext(0);
987 flowParseTypeParameterDeclaration();
988 popTypeContext(oldIsType);
989 wasArrow = baseParseMaybeAssign(noIn, isWithinParens);
990 if (wasArrow) {
991 return true;
992 }
993 unexpected();
994 }
995
996 return baseParseMaybeAssign(noIn, isWithinParens);
997}
998
999// handle return types for arrow functions
1000export function flowParseArrow() {
1001 if (match(tt.colon)) {
1002 const oldIsType = pushTypeContext(0);
1003 const snapshot = state.snapshot();
1004
1005 const oldNoAnonFunctionType = state.noAnonFunctionType;
1006 state.noAnonFunctionType = true;
1007 flowParseTypeAndPredicateInitialiser();
1008 state.noAnonFunctionType = oldNoAnonFunctionType;
1009
1010 if (canInsertSemicolon()) unexpected();
1011 if (!match(tt.arrow)) unexpected();
1012
1013 if (state.error) {
1014 state.restoreFromSnapshot(snapshot);
1015 }
1016 popTypeContext(oldIsType);
1017 }
1018 return eat(tt.arrow);
1019}
1020
1021export function flowParseSubscripts(startTokenIndex, noCalls = false) {
1022 if (
1023 state.tokens[state.tokens.length - 1].contextualKeyword === ContextualKeyword._async &&
1024 match(tt.lessThan)
1025 ) {
1026 const snapshot = state.snapshot();
1027 const wasArrow = parseAsyncArrowWithTypeParameters();
1028 if (wasArrow && !state.error) {
1029 return;
1030 }
1031 state.restoreFromSnapshot(snapshot);
1032 }
1033
1034 baseParseSubscripts(startTokenIndex, noCalls);
1035}
1036
1037// Returns true if there was an arrow function here.
1038function parseAsyncArrowWithTypeParameters() {
1039 state.scopeDepth++;
1040 const startTokenIndex = state.tokens.length;
1041 parseFunctionParams();
1042 if (!parseArrow()) {
1043 return false;
1044 }
1045 parseArrowExpression(startTokenIndex);
1046 return true;
1047}