UNPKG

5.17 kBTypeScriptView Raw
1import type { Token } from "../parser/tokenizer";
2import type TokenProcessor from "../TokenProcessor";
3import type RootTransformer from "./RootTransformer";
4import Transformer from "./Transformer";
5export default class TypeScriptTransformer extends Transformer {
6 readonly rootTransformer: RootTransformer;
7 readonly tokens: TokenProcessor;
8 readonly isImportsTransformEnabled: boolean;
9 constructor(rootTransformer: RootTransformer, tokens: TokenProcessor, isImportsTransformEnabled: boolean);
10 process(): boolean;
11 processEnum(isExport?: boolean): void;
12 /**
13 * Transform an enum into equivalent JS. This has complexity in a few places:
14 * - TS allows string enums, numeric enums, and a mix of the two styles within an enum.
15 * - Enum keys are allowed to be referenced in later enum values.
16 * - Enum keys are allowed to be strings.
17 * - When enum values are omitted, they should follow an auto-increment behavior.
18 */
19 processEnumBody(enumName: string): void;
20 /**
21 * Detect name information about this enum key, which will be used to determine which code to emit
22 * and whether we should declare a variable as part of this declaration.
23 *
24 * Some cases to keep in mind:
25 * - Enum keys can be implicitly referenced later, e.g. `X = 1, Y = X`. In Sucrase, we implement
26 * this by declaring a variable `X` so that later expressions can use it.
27 * - In addition to the usual identifier key syntax, enum keys are allowed to be string literals,
28 * e.g. `"hello world" = 3,`. Template literal syntax is NOT allowed.
29 * - Even if the enum key is defined as a string literal, it may still be referenced by identifier
30 * later, e.g. `"X" = 1, Y = X`. That means that we need to detect whether or not a string
31 * literal is identifier-like and emit a variable if so, even if the declaration did not use an
32 * identifier.
33 * - Reserved keywords like `break` are valid enum keys, but are not valid to be referenced later
34 * and would be a syntax error if we emitted a variable, so we need to skip the variable
35 * declaration in those cases.
36 *
37 * The variableName return value captures these nuances: if non-null, we can and must emit a
38 * variable declaration, and if null, we can't and shouldn't.
39 */
40 extractEnumKeyInfo(nameToken: Token): {
41 nameStringCode: string;
42 variableName: string | null;
43 };
44 /**
45 * Handle an enum member where the RHS is just a string literal (not omitted, not a number, and
46 * not a complex expression). This is the typical form for TS string enums, and in this case, we
47 * do *not* create a reverse mapping.
48 *
49 * This is called after deleting the key token, when the token processor is at the equals sign.
50 *
51 * Example 1:
52 * someKey = "some value"
53 * ->
54 * const someKey = "some value"; MyEnum["someKey"] = someKey;
55 *
56 * Example 2:
57 * "some key" = "some value"
58 * ->
59 * MyEnum["some key"] = "some value";
60 */
61 processStringLiteralEnumMember(enumName: string, nameStringCode: string, variableName: string | null): void;
62 /**
63 * Handle an enum member initialized with an expression on the right-hand side (other than a
64 * string literal). In these cases, we should transform the expression and emit code that sets up
65 * a reverse mapping.
66 *
67 * The TypeScript implementation of this operation distinguishes between expressions that can be
68 * "constant folded" at compile time (i.e. consist of number literals and simple math operations
69 * on those numbers) and ones that are dynamic. For constant expressions, it emits the resolved
70 * numeric value, and auto-incrementing is only allowed in that case. Evaluating expressions at
71 * compile time would add significant complexity to Sucrase, so Sucrase instead leaves the
72 * expression as-is, and will later emit something like `MyEnum["previousKey"] + 1` to implement
73 * auto-incrementing.
74 *
75 * This is called after deleting the key token, when the token processor is at the equals sign.
76 *
77 * Example 1:
78 * someKey = 1 + 1
79 * ->
80 * const someKey = 1 + 1; MyEnum[MyEnum["someKey"] = someKey] = "someKey";
81 *
82 * Example 2:
83 * "some key" = 1 + 1
84 * ->
85 * MyEnum[MyEnum["some key"] = 1 + 1] = "some key";
86 */
87 processExplicitValueEnumMember(enumName: string, nameStringCode: string, variableName: string | null): void;
88 /**
89 * Handle an enum member with no right-hand side expression. In this case, the value is the
90 * previous value plus 1, or 0 if there was no previous value. We should also always emit a
91 * reverse mapping.
92 *
93 * Example 1:
94 * someKey2
95 * ->
96 * const someKey2 = someKey1 + 1; MyEnum[MyEnum["someKey2"] = someKey2] = "someKey2";
97 *
98 * Example 2:
99 * "some key 2"
100 * ->
101 * MyEnum[MyEnum["some key 2"] = someKey1 + 1] = "some key 2";
102 */
103 processImplicitValueEnumMember(enumName: string, nameStringCode: string, variableName: string | null, previousValueCode: string | null): void;
104}