1 | import {TokenType as tt} from "../parser/tokenizer/types";
|
2 |
|
3 | import isIdentifier from "../util/isIdentifier";
|
4 |
|
5 | import Transformer from "./Transformer";
|
6 |
|
7 | export default class TypeScriptTransformer extends Transformer {
|
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.processPossibleTypeRange()
|
20 | ) {
|
21 | return true;
|
22 | }
|
23 | if (
|
24 | this.tokens.matches1(tt._public) ||
|
25 | this.tokens.matches1(tt._protected) ||
|
26 | this.tokens.matches1(tt._private) ||
|
27 | this.tokens.matches1(tt._abstract) ||
|
28 | this.tokens.matches1(tt._readonly) ||
|
29 | this.tokens.matches1(tt.nonNullAssertion)
|
30 | ) {
|
31 | this.tokens.removeInitialToken();
|
32 | return true;
|
33 | }
|
34 | if (this.tokens.matches1(tt._enum) || this.tokens.matches2(tt._const, tt._enum)) {
|
35 | this.processEnum();
|
36 | return true;
|
37 | }
|
38 | if (
|
39 | this.tokens.matches2(tt._export, tt._enum) ||
|
40 | this.tokens.matches3(tt._export, tt._const, tt._enum)
|
41 | ) {
|
42 | this.processEnum(true);
|
43 | return true;
|
44 | }
|
45 | return false;
|
46 | }
|
47 |
|
48 | processEnum(isExport = false) {
|
49 |
|
50 | this.tokens.removeInitialToken();
|
51 | while (this.tokens.matches1(tt._const) || this.tokens.matches1(tt._enum)) {
|
52 | this.tokens.removeToken();
|
53 | }
|
54 | const enumName = this.tokens.identifierName();
|
55 | this.tokens.removeToken();
|
56 | if (isExport && !this.isImportsTransformEnabled) {
|
57 | this.tokens.appendCode("export ");
|
58 | }
|
59 | this.tokens.appendCode(`var ${enumName}; (function (${enumName})`);
|
60 | this.tokens.copyExpectedToken(tt.braceL);
|
61 | this.processEnumBody(enumName);
|
62 | this.tokens.copyExpectedToken(tt.braceR);
|
63 | if (isExport && this.isImportsTransformEnabled) {
|
64 | this.tokens.appendCode(`)(${enumName} || (exports.${enumName} = ${enumName} = {}));`);
|
65 | } else {
|
66 | this.tokens.appendCode(`)(${enumName} || (${enumName} = {}));`);
|
67 | }
|
68 | }
|
69 |
|
70 | |
71 |
|
72 |
|
73 |
|
74 |
|
75 | processEnumBody(enumName) {
|
76 | let isPreviousValidIdentifier = false;
|
77 | let lastValueReference = null;
|
78 | while (true) {
|
79 | if (this.tokens.matches1(tt.braceR)) {
|
80 | break;
|
81 | }
|
82 | const nameToken = this.tokens.currentToken();
|
83 | let name;
|
84 | let nameStringCode;
|
85 | if (nameToken.type === tt.name) {
|
86 | name = this.tokens.identifierNameForToken(nameToken);
|
87 | nameStringCode = `"${name}"`;
|
88 | } else if (nameToken.type === tt.string) {
|
89 | name = this.tokens.stringValueForToken(nameToken);
|
90 | nameStringCode = this.tokens.code.slice(nameToken.start, nameToken.end);
|
91 | } else {
|
92 | throw new Error("Expected name or string at beginning of enum element.");
|
93 | }
|
94 | const isValidIdentifier = isIdentifier(name);
|
95 | this.tokens.removeInitialToken();
|
96 |
|
97 | let valueIsString;
|
98 | let valueCode;
|
99 |
|
100 | if (this.tokens.matches1(tt.eq)) {
|
101 | const rhsEndIndex = this.tokens.currentToken().rhsEndIndex;
|
102 | if (rhsEndIndex == null) {
|
103 | throw new Error("Expected rhsEndIndex on enum assign.");
|
104 | }
|
105 | this.tokens.removeToken();
|
106 | if (
|
107 | this.tokens.matches2(tt.string, tt.comma) ||
|
108 | this.tokens.matches2(tt.string, tt.braceR)
|
109 | ) {
|
110 | valueIsString = true;
|
111 | }
|
112 | const startToken = this.tokens.currentToken();
|
113 | while (this.tokens.currentIndex() < rhsEndIndex) {
|
114 | this.tokens.removeToken();
|
115 | }
|
116 | valueCode = this.tokens.code.slice(
|
117 | startToken.start,
|
118 | this.tokens.tokenAtRelativeIndex(-1).end,
|
119 | );
|
120 | } else {
|
121 | valueIsString = false;
|
122 | if (lastValueReference != null) {
|
123 | if (isPreviousValidIdentifier) {
|
124 | valueCode = `${lastValueReference} + 1`;
|
125 | } else {
|
126 | valueCode = `(${lastValueReference}) + 1`;
|
127 | }
|
128 | } else {
|
129 | valueCode = "0";
|
130 | }
|
131 | }
|
132 | if (this.tokens.matches1(tt.comma)) {
|
133 | this.tokens.removeToken();
|
134 | }
|
135 |
|
136 | let valueReference;
|
137 | if (isValidIdentifier) {
|
138 | this.tokens.appendCode(`const ${name} = ${valueCode}; `);
|
139 | valueReference = name;
|
140 | } else {
|
141 | valueReference = valueCode;
|
142 | }
|
143 |
|
144 | if (valueIsString) {
|
145 | this.tokens.appendCode(`${enumName}[${nameStringCode}] = ${valueReference};`);
|
146 | } else {
|
147 | this.tokens.appendCode(
|
148 | `${enumName}[${enumName}[${nameStringCode}] = ${valueReference}] = ${nameStringCode};`,
|
149 | );
|
150 | }
|
151 | lastValueReference = valueReference;
|
152 | isPreviousValidIdentifier = isValidIdentifier;
|
153 | }
|
154 | }
|
155 | }
|