source: frontend/node_modules/sucrase/dist/transformers/FlowTransformer.js

Last change on this file was 9af201e, checked in by MBK <marija.karapandzova@…>, 12 days ago

Fix frontend appearance

  • Property mode set to 100644
File size: 6.4 KB
Line 
1"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _keywords = require('../parser/tokenizer/keywords');
2var _types = require('../parser/tokenizer/types');
3
4
5var _Transformer = require('./Transformer'); var _Transformer2 = _interopRequireDefault(_Transformer);
6
7 class FlowTransformer extends _Transformer2.default {
8 constructor(
9 rootTransformer,
10 tokens,
11 isImportsTransformEnabled,
12 ) {
13 super();this.rootTransformer = rootTransformer;this.tokens = tokens;this.isImportsTransformEnabled = isImportsTransformEnabled;;
14 }
15
16 process() {
17 if (
18 this.rootTransformer.processPossibleArrowParamEnd() ||
19 this.rootTransformer.processPossibleAsyncArrowWithTypeParams() ||
20 this.rootTransformer.processPossibleTypeRange()
21 ) {
22 return true;
23 }
24 if (this.tokens.matches1(_types.TokenType._enum)) {
25 this.processEnum();
26 return true;
27 }
28 if (this.tokens.matches2(_types.TokenType._export, _types.TokenType._enum)) {
29 this.processNamedExportEnum();
30 return true;
31 }
32 if (this.tokens.matches3(_types.TokenType._export, _types.TokenType._default, _types.TokenType._enum)) {
33 this.processDefaultExportEnum();
34 return true;
35 }
36 return false;
37 }
38
39 /**
40 * Handle a declaration like:
41 * export enum E ...
42 *
43 * With this imports transform, this becomes:
44 * const E = [[enum]]; exports.E = E;
45 *
46 * otherwise, it becomes:
47 * export const E = [[enum]];
48 */
49 processNamedExportEnum() {
50 if (this.isImportsTransformEnabled) {
51 // export
52 this.tokens.removeInitialToken();
53 const enumName = this.tokens.identifierNameAtRelativeIndex(1);
54 this.processEnum();
55 this.tokens.appendCode(` exports.${enumName} = ${enumName};`);
56 } else {
57 this.tokens.copyToken();
58 this.processEnum();
59 }
60 }
61
62 /**
63 * Handle a declaration like:
64 * export default enum E
65 *
66 * With the imports transform, this becomes:
67 * const E = [[enum]]; exports.default = E;
68 *
69 * otherwise, it becomes:
70 * const E = [[enum]]; export default E;
71 */
72 processDefaultExportEnum() {
73 // export
74 this.tokens.removeInitialToken();
75 // default
76 this.tokens.removeToken();
77 const enumName = this.tokens.identifierNameAtRelativeIndex(1);
78 this.processEnum();
79 if (this.isImportsTransformEnabled) {
80 this.tokens.appendCode(` exports.default = ${enumName};`);
81 } else {
82 this.tokens.appendCode(` export default ${enumName};`);
83 }
84 }
85
86 /**
87 * Transpile flow enums to invoke the "flow-enums-runtime" library.
88 *
89 * Currently, the transpiled code always uses `require("flow-enums-runtime")`,
90 * but if future flexibility is needed, we could expose a config option for
91 * this string (similar to configurable JSX). Even when targeting ESM, the
92 * default behavior of babel-plugin-transform-flow-enums is to use require
93 * rather than injecting an import.
94 *
95 * Flow enums are quite a bit simpler than TS enums and have some convenient
96 * constraints:
97 * - Element initializers must be either always present or always absent. That
98 * means that we can use fixed lookahead on the first element (if any) and
99 * assume that all elements are like that.
100 * - The right-hand side of an element initializer must be a literal value,
101 * not a complex expression and not referencing other elements. That means
102 * we can simply copy a single token.
103 *
104 * Enums can be broken up into three basic cases:
105 *
106 * Mirrored enums:
107 * enum E {A, B}
108 * ->
109 * const E = require("flow-enums-runtime").Mirrored(["A", "B"]);
110 *
111 * Initializer enums:
112 * enum E {A = 1, B = 2}
113 * ->
114 * const E = require("flow-enums-runtime")({A: 1, B: 2});
115 *
116 * Symbol enums:
117 * enum E of symbol {A, B}
118 * ->
119 * const E = require("flow-enums-runtime")({A: Symbol("A"), B: Symbol("B")});
120 *
121 * We can statically detect which of the three cases this is by looking at the
122 * "of" declaration (if any) and seeing if the first element has an initializer.
123 * Since the other transform details are so similar between the three cases, we
124 * use a single implementation and vary the transform within processEnumElement
125 * based on case.
126 */
127 processEnum() {
128 // enum E -> const E
129 this.tokens.replaceToken("const");
130 this.tokens.copyExpectedToken(_types.TokenType.name);
131
132 let isSymbolEnum = false;
133 if (this.tokens.matchesContextual(_keywords.ContextualKeyword._of)) {
134 this.tokens.removeToken();
135 isSymbolEnum = this.tokens.matchesContextual(_keywords.ContextualKeyword._symbol);
136 this.tokens.removeToken();
137 }
138 const hasInitializers = this.tokens.matches3(_types.TokenType.braceL, _types.TokenType.name, _types.TokenType.eq);
139 this.tokens.appendCode(' = require("flow-enums-runtime")');
140
141 const isMirrored = !isSymbolEnum && !hasInitializers;
142 this.tokens.replaceTokenTrimmingLeftWhitespace(isMirrored ? ".Mirrored([" : "({");
143
144 while (!this.tokens.matches1(_types.TokenType.braceR)) {
145 // ... is allowed at the end and has no runtime behavior.
146 if (this.tokens.matches1(_types.TokenType.ellipsis)) {
147 this.tokens.removeToken();
148 break;
149 }
150 this.processEnumElement(isSymbolEnum, hasInitializers);
151 if (this.tokens.matches1(_types.TokenType.comma)) {
152 this.tokens.copyToken();
153 }
154 }
155
156 this.tokens.replaceToken(isMirrored ? "]);" : "});");
157 }
158
159 /**
160 * Process an individual enum element, producing either an array element or an
161 * object element based on what type of enum this is.
162 */
163 processEnumElement(isSymbolEnum, hasInitializers) {
164 if (isSymbolEnum) {
165 // Symbol enums never have initializers and are expanded to object elements.
166 // A, -> A: Symbol("A"),
167 const elementName = this.tokens.identifierName();
168 this.tokens.copyToken();
169 this.tokens.appendCode(`: Symbol("${elementName}")`);
170 } else if (hasInitializers) {
171 // Initializers are expanded to object elements.
172 // A = 1, -> A: 1,
173 this.tokens.copyToken();
174 this.tokens.replaceTokenTrimmingLeftWhitespace(":");
175 this.tokens.copyToken();
176 } else {
177 // Enum elements without initializers become string literal array elements.
178 // A, -> "A",
179 this.tokens.replaceToken(`"${this.tokens.identifierName()}"`);
180 }
181 }
182} exports.default = FlowTransformer;
Note: See TracBrowser for help on using the repository browser.