UNPKG

5.91 kBJavaScriptView Raw
1"use strict";Object.defineProperty(exports, "__esModule", {value: true}); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }var _types = require('../parser/tokenizer/types');
2
3var _isIdentifier = require('../util/isIdentifier'); var _isIdentifier2 = _interopRequireDefault(_isIdentifier);
4
5var _Transformer = require('./Transformer'); var _Transformer2 = _interopRequireDefault(_Transformer);
6
7 class TypeScriptTransformer 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 (
25 this.tokens.matches1(_types.TokenType._public) ||
26 this.tokens.matches1(_types.TokenType._protected) ||
27 this.tokens.matches1(_types.TokenType._private) ||
28 this.tokens.matches1(_types.TokenType._abstract) ||
29 this.tokens.matches1(_types.TokenType._readonly) ||
30 this.tokens.matches1(_types.TokenType.nonNullAssertion)
31 ) {
32 this.tokens.removeInitialToken();
33 return true;
34 }
35 if (this.tokens.matches1(_types.TokenType._enum) || this.tokens.matches2(_types.TokenType._const, _types.TokenType._enum)) {
36 this.processEnum();
37 return true;
38 }
39 if (
40 this.tokens.matches2(_types.TokenType._export, _types.TokenType._enum) ||
41 this.tokens.matches3(_types.TokenType._export, _types.TokenType._const, _types.TokenType._enum)
42 ) {
43 this.processEnum(true);
44 return true;
45 }
46 return false;
47 }
48
49 processEnum(isExport = false) {
50 // We might have "export const enum", so just remove all relevant tokens.
51 this.tokens.removeInitialToken();
52 while (this.tokens.matches1(_types.TokenType._const) || this.tokens.matches1(_types.TokenType._enum)) {
53 this.tokens.removeToken();
54 }
55 const enumName = this.tokens.identifierName();
56 this.tokens.removeToken();
57 if (isExport && !this.isImportsTransformEnabled) {
58 this.tokens.appendCode("export ");
59 }
60 this.tokens.appendCode(`var ${enumName}; (function (${enumName})`);
61 this.tokens.copyExpectedToken(_types.TokenType.braceL);
62 this.processEnumBody(enumName);
63 this.tokens.copyExpectedToken(_types.TokenType.braceR);
64 if (isExport && this.isImportsTransformEnabled) {
65 this.tokens.appendCode(`)(${enumName} || (exports.${enumName} = ${enumName} = {}));`);
66 } else {
67 this.tokens.appendCode(`)(${enumName} || (${enumName} = {}));`);
68 }
69 }
70
71 /**
72 * Rather than try to compute the actual enum values at compile time, we just create variables for
73 * each one and let everything evaluate at runtime. There's some additional complexity due to
74 * handling string literal names, including ones that happen to be valid identifiers.
75 */
76 processEnumBody(enumName) {
77 let isPreviousValidIdentifier = false;
78 let lastValueReference = null;
79 while (true) {
80 if (this.tokens.matches1(_types.TokenType.braceR)) {
81 break;
82 }
83 const nameToken = this.tokens.currentToken();
84 let name;
85 let nameStringCode;
86 if (nameToken.type === _types.TokenType.name) {
87 name = this.tokens.identifierNameForToken(nameToken);
88 nameStringCode = `"${name}"`;
89 } else if (nameToken.type === _types.TokenType.string) {
90 name = this.tokens.stringValueForToken(nameToken);
91 nameStringCode = this.tokens.code.slice(nameToken.start, nameToken.end);
92 } else {
93 throw new Error("Expected name or string at beginning of enum element.");
94 }
95 const isValidIdentifier = _isIdentifier2.default.call(void 0, name);
96 this.tokens.removeInitialToken();
97
98 let valueIsString;
99 let valueCode;
100
101 if (this.tokens.matches1(_types.TokenType.eq)) {
102 const rhsEndIndex = this.tokens.currentToken().rhsEndIndex;
103 if (rhsEndIndex == null) {
104 throw new Error("Expected rhsEndIndex on enum assign.");
105 }
106 this.tokens.removeToken();
107 if (
108 this.tokens.matches2(_types.TokenType.string, _types.TokenType.comma) ||
109 this.tokens.matches2(_types.TokenType.string, _types.TokenType.braceR)
110 ) {
111 valueIsString = true;
112 }
113 const startToken = this.tokens.currentToken();
114 while (this.tokens.currentIndex() < rhsEndIndex) {
115 this.tokens.removeToken();
116 }
117 valueCode = this.tokens.code.slice(
118 startToken.start,
119 this.tokens.tokenAtRelativeIndex(-1).end,
120 );
121 } else {
122 valueIsString = false;
123 if (lastValueReference != null) {
124 if (isPreviousValidIdentifier) {
125 valueCode = `${lastValueReference} + 1`;
126 } else {
127 valueCode = `(${lastValueReference}) + 1`;
128 }
129 } else {
130 valueCode = "0";
131 }
132 }
133 if (this.tokens.matches1(_types.TokenType.comma)) {
134 this.tokens.removeToken();
135 }
136
137 let valueReference;
138 if (isValidIdentifier) {
139 this.tokens.appendCode(`const ${name} = ${valueCode}; `);
140 valueReference = name;
141 } else {
142 valueReference = valueCode;
143 }
144
145 if (valueIsString) {
146 this.tokens.appendCode(`${enumName}[${nameStringCode}] = ${valueReference};`);
147 } else {
148 this.tokens.appendCode(
149 `${enumName}[${enumName}[${nameStringCode}] = ${valueReference}] = ${nameStringCode};`,
150 );
151 }
152 lastValueReference = valueReference;
153 isPreviousValidIdentifier = isValidIdentifier;
154 }
155 }
156} exports.default = TypeScriptTransformer;