UNPKG

5.83 kBJavaScriptView Raw
1"use strict"; function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }Object.defineProperty(exports, "__esModule", {value: true});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.processPossibleTypeRange()
20 ) {
21 return true;
22 }
23 if (
24 this.tokens.matches1(_types.TokenType._public) ||
25 this.tokens.matches1(_types.TokenType._protected) ||
26 this.tokens.matches1(_types.TokenType._private) ||
27 this.tokens.matches1(_types.TokenType._abstract) ||
28 this.tokens.matches1(_types.TokenType._readonly) ||
29 this.tokens.matches1(_types.TokenType.nonNullAssertion)
30 ) {
31 this.tokens.removeInitialToken();
32 return true;
33 }
34 if (this.tokens.matches1(_types.TokenType._enum) || this.tokens.matches2(_types.TokenType._const, _types.TokenType._enum)) {
35 this.processEnum();
36 return true;
37 }
38 if (
39 this.tokens.matches2(_types.TokenType._export, _types.TokenType._enum) ||
40 this.tokens.matches3(_types.TokenType._export, _types.TokenType._const, _types.TokenType._enum)
41 ) {
42 this.processEnum(true);
43 return true;
44 }
45 return false;
46 }
47
48 processEnum(isExport = false) {
49 // We might have "export const enum", so just remove all relevant tokens.
50 this.tokens.removeInitialToken();
51 while (this.tokens.matches1(_types.TokenType._const) || this.tokens.matches1(_types.TokenType._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(_types.TokenType.braceL);
61 this.processEnumBody(enumName);
62 this.tokens.copyExpectedToken(_types.TokenType.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 * Rather than try to compute the actual enum values at compile time, we just create variables for
72 * each one and let everything evaluate at runtime. There's some additional complexity due to
73 * handling string literal names, including ones that happen to be valid identifiers.
74 */
75 processEnumBody(enumName) {
76 let isPreviousValidIdentifier = false;
77 let lastValueReference = null;
78 while (true) {
79 if (this.tokens.matches1(_types.TokenType.braceR)) {
80 break;
81 }
82 const nameToken = this.tokens.currentToken();
83 let name;
84 let nameStringCode;
85 if (nameToken.type === _types.TokenType.name) {
86 name = this.tokens.identifierNameForToken(nameToken);
87 nameStringCode = `"${name}"`;
88 } else if (nameToken.type === _types.TokenType.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 = _isIdentifier2.default.call(void 0, name);
95 this.tokens.removeInitialToken();
96
97 let valueIsString;
98 let valueCode;
99
100 if (this.tokens.matches1(_types.TokenType.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(_types.TokenType.string, _types.TokenType.comma) ||
108 this.tokens.matches2(_types.TokenType.string, _types.TokenType.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(_types.TokenType.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} exports.default = TypeScriptTransformer;