@boristype/bt-cli 0.1.0-alpha.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +66 -0
- package/build/builder/config.js +88 -0
- package/build/cli/commands/artifact.js +14 -0
- package/build/cli/commands/build.js +25 -0
- package/build/cli/commands/dev.js +190 -0
- package/build/cli/commands/index.js +18 -0
- package/build/cli/commands/init.js +15 -0
- package/build/cli/commands/link.js +18 -0
- package/build/cli/commands/push.js +28 -0
- package/build/cli/index.js +14 -0
- package/build/cli/types.js +2 -0
- package/build/core/artifacting/context.js +54 -0
- package/build/core/artifacting/index.js +37 -0
- package/build/core/artifacting/stages/index.js +10 -0
- package/build/core/artifacting/stages/main-archive.js +72 -0
- package/build/core/artifacting/stages/validate.js +70 -0
- package/build/core/artifacting/types.js +6 -0
- package/build/core/artifacting/utils/index.js +10 -0
- package/build/core/artifacting/utils/zip.js +94 -0
- package/build/core/babel.js +96 -0
- package/build/core/btconfig.types.js +6 -0
- package/build/core/build.js +280 -0
- package/build/core/building/compile-mode.js +146 -0
- package/build/core/building/compiler.js +281 -0
- package/build/core/building/coordinator.js +71 -0
- package/build/core/building/files.js +290 -0
- package/build/core/building/index.js +102 -0
- package/build/core/building/output.js +92 -0
- package/build/core/building/transformers.js +110 -0
- package/build/core/building/types.js +19 -0
- package/build/core/config.js +157 -0
- package/build/core/dependencies.js +223 -0
- package/build/core/linking/cache.js +260 -0
- package/build/core/linking/context.js +149 -0
- package/build/core/linking/dependencies.js +240 -0
- package/build/core/linking/executables.js +61 -0
- package/build/core/linking/generators/api-ext.js +57 -0
- package/build/core/linking/generators/component.js +83 -0
- package/build/core/linking/generators/filemap.js +53 -0
- package/build/core/linking/generators/index.js +21 -0
- package/build/core/linking/generators/init-xml.js +37 -0
- package/build/core/linking/generators/package-json.js +50 -0
- package/build/core/linking/index.js +213 -0
- package/build/core/linking/linkers/component.js +175 -0
- package/build/core/linking/linkers/index.js +69 -0
- package/build/core/linking/linkers/standalone.js +144 -0
- package/build/core/linking/linkers/system.js +86 -0
- package/build/core/linking/parsers.js +278 -0
- package/build/core/linking/types.js +6 -0
- package/build/core/linking/utils/copy.js +101 -0
- package/build/core/linking/utils/index.js +26 -0
- package/build/core/linking/utils/node-modules.js +226 -0
- package/build/core/linking/utils/package-type.js +101 -0
- package/build/core/linking/utils/url.js +73 -0
- package/build/core/linking/utils/write.js +91 -0
- package/build/core/logger.js +10 -0
- package/build/core/pushing/config.js +90 -0
- package/build/core/pushing/index.js +96 -0
- package/build/core/pushing/init-scripts.js +173 -0
- package/build/core/pushing/queue.js +95 -0
- package/build/core/pushing/reinit.js +61 -0
- package/build/core/pushing/session.js +167 -0
- package/build/core/pushing/types.js +6 -0
- package/build/core/pushing/upload.js +35 -0
- package/build/core/tsconfig.js +78 -0
- package/build/core/utils/index.js +17 -0
- package/build/core/utils/logger.js +46 -0
- package/build/core/utils/properties.js +81 -0
- package/build/core/utils/xml.js +44 -0
- package/build/core/utils.js +59 -0
- package/build/index.js +76 -0
- package/build/plugins/destructuring.js +83 -0
- package/build/plugins/forOfToForIn.js +14 -0
- package/build/plugins/loopHoistVariables.js +160 -0
- package/build/plugins/precedence.js +172 -0
- package/build/plugins/removeImportExport.js +42 -0
- package/build/plugins/replaceDollar.js +16 -0
- package/build/plugins/spreadArray.js +42 -0
- package/build/plugins/spreadObject.js +91 -0
- package/build/transformers/arrayFunctional.js +467 -0
- package/build/transformers/arrayGeneral.js +222 -0
- package/build/transformers/blockScoping.js +212 -0
- package/build/transformers/destructuring.js +133 -0
- package/build/transformers/dirname.js +79 -0
- package/build/transformers/enumsToObjects.js +25 -0
- package/build/transformers/execObj.js +220 -0
- package/build/transformers/forOfToForIn.js +45 -0
- package/build/transformers/funcSemantic.js +113 -0
- package/build/transformers/functions.js +270 -0
- package/build/transformers/globalCache.js +34 -0
- package/build/transformers/loopHoistVariables.js +352 -0
- package/build/transformers/math.js +39 -0
- package/build/transformers/namespaces.js +22 -0
- package/build/transformers/numericSeparator.js +46 -0
- package/build/transformers/objectProperties.js +54 -0
- package/build/transformers/precedence.js +192 -0
- package/build/transformers/propSemantic.js +467 -0
- package/build/transformers/remodule.js +620 -0
- package/build/transformers/removeImportExport.js +135 -0
- package/build/transformers/replaceDollar.js +46 -0
- package/build/transformers/shorthandProperties.js +34 -0
- package/build/transformers/spreadArray.js +68 -0
- package/build/transformers/spreadObject.js +134 -0
- package/build/transformers/string.js +138 -0
- package/build/transformers/templateLiterals.js +104 -0
- package/build/transformers/tocodelibrary.js +178 -0
- package/build/transformers/utils.js +202 -0
- package/build/wshcm/client.js +193 -0
- package/build/wshcm/evaluator.js +111 -0
- package/build/wshcm/exceptions.js +25 -0
- package/build/wshcm/index.js +20 -0
- package/build/wshcm/soap-utils.js +228 -0
- package/build/wshcm/types.js +2 -0
- package/build/wshcm/uploader.js +320 -0
- package/package.json +51 -0
|
@@ -0,0 +1,352 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.loopHoistVariablesTransformer = loopHoistVariablesTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
/**
|
|
9
|
+
* Трансформер для поднятия переменных из циклов.
|
|
10
|
+
*
|
|
11
|
+
* Переменные, объявленные внутри циклов, поднимаются перед циклом
|
|
12
|
+
* и переименовываются с суффиксом _loopN для избежания конфликтов.
|
|
13
|
+
* Объявления внутри цикла заменяются на присваивания.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Вход:
|
|
17
|
+
* for (var i in arr) {
|
|
18
|
+
* var x = i * 2;
|
|
19
|
+
* console.log(x);
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* // Выход:
|
|
23
|
+
* var i_loop1 = undefined;
|
|
24
|
+
* var x_loop1 = undefined;
|
|
25
|
+
* for (i_loop1 in arr) {
|
|
26
|
+
* x_loop1 = i_loop1 * 2;
|
|
27
|
+
* console.log(x_loop1);
|
|
28
|
+
* }
|
|
29
|
+
*
|
|
30
|
+
* @returns TypeScript transformer factory
|
|
31
|
+
*/
|
|
32
|
+
function loopHoistVariablesTransformer() {
|
|
33
|
+
return (context) => {
|
|
34
|
+
return (sourceFile) => {
|
|
35
|
+
let loopCounter = 0;
|
|
36
|
+
/**
|
|
37
|
+
* Проверяет, является ли узел циклом
|
|
38
|
+
*/
|
|
39
|
+
const isLoop = (node) => {
|
|
40
|
+
return typescript_1.default.isForStatement(node) ||
|
|
41
|
+
typescript_1.default.isForInStatement(node) ||
|
|
42
|
+
typescript_1.default.isForOfStatement(node) ||
|
|
43
|
+
typescript_1.default.isWhileStatement(node) ||
|
|
44
|
+
typescript_1.default.isDoStatement(node);
|
|
45
|
+
};
|
|
46
|
+
/**
|
|
47
|
+
* Собирает все переменные из тела цикла, включая заголовки вложенных циклов
|
|
48
|
+
*/
|
|
49
|
+
const collectLoopVariables = (loopBody, loopNum, variables) => {
|
|
50
|
+
const visit = (node) => {
|
|
51
|
+
// Не заходим во вложенные функции
|
|
52
|
+
if (typescript_1.default.isFunctionDeclaration(node) || typescript_1.default.isFunctionExpression(node) || typescript_1.default.isArrowFunction(node)) {
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
// Собираем переменные из VariableStatement
|
|
56
|
+
if (typescript_1.default.isVariableStatement(node)) {
|
|
57
|
+
for (const decl of node.declarationList.declarations) {
|
|
58
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
59
|
+
const originalName = decl.name.text;
|
|
60
|
+
const newName = `${originalName}_loop${loopNum}`;
|
|
61
|
+
variables.push({ originalName, newName });
|
|
62
|
+
}
|
|
63
|
+
// TODO: BindingPattern (деструктуризация) — пока пропускаем
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
// Собираем переменные из заголовков вложенных циклов for-in/for-of
|
|
67
|
+
if (typescript_1.default.isForInStatement(node) || typescript_1.default.isForOfStatement(node)) {
|
|
68
|
+
if (typescript_1.default.isVariableDeclarationList(node.initializer)) {
|
|
69
|
+
const decl = node.initializer.declarations[0];
|
|
70
|
+
if (decl && typescript_1.default.isIdentifier(decl.name)) {
|
|
71
|
+
const originalName = decl.name.text;
|
|
72
|
+
const newName = `${originalName}_loop${loopNum}`;
|
|
73
|
+
variables.push({ originalName, newName });
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
// Собираем переменные из заголовков вложенных циклов for
|
|
78
|
+
if (typescript_1.default.isForStatement(node) && node.initializer && typescript_1.default.isVariableDeclarationList(node.initializer)) {
|
|
79
|
+
for (const decl of node.initializer.declarations) {
|
|
80
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
81
|
+
const originalName = decl.name.text;
|
|
82
|
+
const newName = `${originalName}_loop${loopNum}`;
|
|
83
|
+
variables.push({ originalName, newName });
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
typescript_1.default.forEachChild(node, visit);
|
|
88
|
+
};
|
|
89
|
+
visit(loopBody);
|
|
90
|
+
};
|
|
91
|
+
/**
|
|
92
|
+
* Трансформирует тело цикла: заменяет объявления на присваивания
|
|
93
|
+
* и переименовывает использования переменных
|
|
94
|
+
*/
|
|
95
|
+
const transformLoopBody = (body, variables) => {
|
|
96
|
+
const renameMap = new Map(variables.map(v => [v.originalName, v.newName]));
|
|
97
|
+
const visitor = (node) => {
|
|
98
|
+
// Заменяем VariableStatement на присваивания
|
|
99
|
+
if (typescript_1.default.isVariableStatement(node)) {
|
|
100
|
+
const assignments = [];
|
|
101
|
+
for (const decl of node.declarationList.declarations) {
|
|
102
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
103
|
+
const originalName = decl.name.text;
|
|
104
|
+
const newName = renameMap.get(originalName);
|
|
105
|
+
if (newName) {
|
|
106
|
+
// Создаём присваивание: newName = init || undefined
|
|
107
|
+
const init = decl.initializer
|
|
108
|
+
? typescript_1.default.visitNode(decl.initializer, visitor)
|
|
109
|
+
: typescript_1.default.factory.createIdentifier('undefined');
|
|
110
|
+
assignments.push(typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createAssignment(typescript_1.default.factory.createIdentifier(newName), init)));
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
if (assignments.length === 1) {
|
|
115
|
+
return assignments[0];
|
|
116
|
+
}
|
|
117
|
+
else if (assignments.length > 1) {
|
|
118
|
+
// Возвращаем блок с несколькими присваиваниями
|
|
119
|
+
// Но это проблема — нужно вернуть несколько statements
|
|
120
|
+
// Пока возвращаем первое (TODO: обработать множественные)
|
|
121
|
+
return assignments[0];
|
|
122
|
+
}
|
|
123
|
+
}
|
|
124
|
+
// Трансформируем заголовки вложенных циклов for-in/for-of
|
|
125
|
+
if (typescript_1.default.isForInStatement(node) || typescript_1.default.isForOfStatement(node)) {
|
|
126
|
+
let newInitializer = node.initializer;
|
|
127
|
+
if (typescript_1.default.isVariableDeclarationList(node.initializer)) {
|
|
128
|
+
const decl = node.initializer.declarations[0];
|
|
129
|
+
if (decl && typescript_1.default.isIdentifier(decl.name)) {
|
|
130
|
+
const newName = renameMap.get(decl.name.text);
|
|
131
|
+
if (newName) {
|
|
132
|
+
// Заменяем var x на просто x_loopN
|
|
133
|
+
newInitializer = typescript_1.default.factory.createIdentifier(newName);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
const transformedBody = typescript_1.default.visitNode(node.statement, visitor);
|
|
138
|
+
const transformedExpression = typescript_1.default.visitNode(node.expression, visitor);
|
|
139
|
+
if (typescript_1.default.isForInStatement(node)) {
|
|
140
|
+
return typescript_1.default.factory.createForInStatement(newInitializer, transformedExpression, transformedBody);
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
return typescript_1.default.factory.createForOfStatement(node.awaitModifier, newInitializer, transformedExpression, transformedBody);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
// Трансформируем заголовки вложенных циклов for
|
|
147
|
+
if (typescript_1.default.isForStatement(node)) {
|
|
148
|
+
let newInitializer = node.initializer;
|
|
149
|
+
if (node.initializer && typescript_1.default.isVariableDeclarationList(node.initializer)) {
|
|
150
|
+
const assignments = [];
|
|
151
|
+
for (const decl of node.initializer.declarations) {
|
|
152
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
153
|
+
const newName = renameMap.get(decl.name.text);
|
|
154
|
+
if (newName && decl.initializer) {
|
|
155
|
+
assignments.push(typescript_1.default.factory.createAssignment(typescript_1.default.factory.createIdentifier(newName), typescript_1.default.visitNode(decl.initializer, visitor)));
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
if (assignments.length === 1) {
|
|
160
|
+
newInitializer = assignments[0];
|
|
161
|
+
}
|
|
162
|
+
else if (assignments.length > 1) {
|
|
163
|
+
newInitializer = typescript_1.default.factory.createCommaListExpression(assignments);
|
|
164
|
+
}
|
|
165
|
+
else {
|
|
166
|
+
newInitializer = undefined;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
return typescript_1.default.factory.createForStatement(newInitializer, node.condition ? typescript_1.default.visitNode(node.condition, visitor) : undefined, node.incrementor ? typescript_1.default.visitNode(node.incrementor, visitor) : undefined, typescript_1.default.visitNode(node.statement, visitor));
|
|
170
|
+
}
|
|
171
|
+
// Переименовываем идентификаторы
|
|
172
|
+
if (typescript_1.default.isIdentifier(node)) {
|
|
173
|
+
const parent = node.parent;
|
|
174
|
+
// Пропускаем property access и property assignment
|
|
175
|
+
if (parent && typescript_1.default.isPropertyAccessExpression(parent) && parent.name === node) {
|
|
176
|
+
return node;
|
|
177
|
+
}
|
|
178
|
+
if (parent && typescript_1.default.isPropertyAssignment(parent) && parent.name === node) {
|
|
179
|
+
return node;
|
|
180
|
+
}
|
|
181
|
+
const newName = renameMap.get(node.text);
|
|
182
|
+
if (newName) {
|
|
183
|
+
return typescript_1.default.factory.createIdentifier(newName);
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
187
|
+
};
|
|
188
|
+
return typescript_1.default.visitNode(body, visitor);
|
|
189
|
+
};
|
|
190
|
+
/**
|
|
191
|
+
* Создаёт объявления переменных для вставки перед циклом
|
|
192
|
+
*/
|
|
193
|
+
const createHoistedDeclarations = (variables) => {
|
|
194
|
+
return variables.map(v => typescript_1.default.factory.createVariableStatement(undefined, typescript_1.default.factory.createVariableDeclarationList([typescript_1.default.factory.createVariableDeclaration(v.newName, undefined, undefined, typescript_1.default.factory.createIdentifier('undefined'))], typescript_1.default.NodeFlags.None // var
|
|
195
|
+
)));
|
|
196
|
+
};
|
|
197
|
+
/**
|
|
198
|
+
* Обрабатывает for-in цикл
|
|
199
|
+
*/
|
|
200
|
+
const transformForInStatement = (node) => {
|
|
201
|
+
loopCounter++;
|
|
202
|
+
const loopNum = loopCounter;
|
|
203
|
+
const variables = [];
|
|
204
|
+
// Собираем переменную из заголовка цикла (for var x in ...)
|
|
205
|
+
let newInitializer = node.initializer;
|
|
206
|
+
if (typescript_1.default.isVariableDeclarationList(node.initializer)) {
|
|
207
|
+
const decl = node.initializer.declarations[0];
|
|
208
|
+
if (decl && typescript_1.default.isIdentifier(decl.name)) {
|
|
209
|
+
const originalName = decl.name.text;
|
|
210
|
+
const newName = `${originalName}_loop${loopNum}`;
|
|
211
|
+
variables.push({ originalName, newName });
|
|
212
|
+
// Заменяем объявление на просто идентификатор
|
|
213
|
+
newInitializer = typescript_1.default.factory.createIdentifier(newName);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Собираем переменные из тела цикла
|
|
217
|
+
collectLoopVariables(node.statement, loopNum, variables);
|
|
218
|
+
// Трансформируем тело
|
|
219
|
+
const transformedBody = transformLoopBody(node.statement, variables);
|
|
220
|
+
// Создаём новый for-in
|
|
221
|
+
const newForIn = typescript_1.default.factory.createForInStatement(newInitializer, typescript_1.default.visitNode(node.expression, mainVisitor), transformedBody);
|
|
222
|
+
// Возвращаем объявления + цикл
|
|
223
|
+
const hoisted = createHoistedDeclarations(variables);
|
|
224
|
+
return [...hoisted, newForIn];
|
|
225
|
+
};
|
|
226
|
+
/**
|
|
227
|
+
* Обрабатывает for-of цикл (хотя он должен быть уже преобразован в for-in)
|
|
228
|
+
*/
|
|
229
|
+
const transformForOfStatement = (node) => {
|
|
230
|
+
loopCounter++;
|
|
231
|
+
const loopNum = loopCounter;
|
|
232
|
+
const variables = [];
|
|
233
|
+
let newInitializer = node.initializer;
|
|
234
|
+
if (typescript_1.default.isVariableDeclarationList(node.initializer)) {
|
|
235
|
+
const decl = node.initializer.declarations[0];
|
|
236
|
+
if (decl && typescript_1.default.isIdentifier(decl.name)) {
|
|
237
|
+
const originalName = decl.name.text;
|
|
238
|
+
const newName = `${originalName}_loop${loopNum}`;
|
|
239
|
+
variables.push({ originalName, newName });
|
|
240
|
+
newInitializer = typescript_1.default.factory.createIdentifier(newName);
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
collectLoopVariables(node.statement, loopNum, variables);
|
|
244
|
+
const transformedBody = transformLoopBody(node.statement, variables);
|
|
245
|
+
const newForOf = typescript_1.default.factory.createForOfStatement(node.awaitModifier, newInitializer, typescript_1.default.visitNode(node.expression, mainVisitor), transformedBody);
|
|
246
|
+
const hoisted = createHoistedDeclarations(variables);
|
|
247
|
+
return [...hoisted, newForOf];
|
|
248
|
+
};
|
|
249
|
+
/**
|
|
250
|
+
* Обрабатывает for цикл
|
|
251
|
+
*/
|
|
252
|
+
const transformForStatement = (node) => {
|
|
253
|
+
loopCounter++;
|
|
254
|
+
const loopNum = loopCounter;
|
|
255
|
+
const variables = [];
|
|
256
|
+
// Собираем переменные из инициализатора (for (var i = 0; ...))
|
|
257
|
+
let newInitializer = node.initializer;
|
|
258
|
+
if (node.initializer && typescript_1.default.isVariableDeclarationList(node.initializer)) {
|
|
259
|
+
const assignments = [];
|
|
260
|
+
for (const decl of node.initializer.declarations) {
|
|
261
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
262
|
+
const originalName = decl.name.text;
|
|
263
|
+
const newName = `${originalName}_loop${loopNum}`;
|
|
264
|
+
variables.push({ originalName, newName });
|
|
265
|
+
if (decl.initializer) {
|
|
266
|
+
assignments.push(typescript_1.default.factory.createAssignment(typescript_1.default.factory.createIdentifier(newName), decl.initializer));
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
}
|
|
270
|
+
if (assignments.length === 1) {
|
|
271
|
+
newInitializer = assignments[0];
|
|
272
|
+
}
|
|
273
|
+
else if (assignments.length > 1) {
|
|
274
|
+
newInitializer = typescript_1.default.factory.createCommaListExpression(assignments);
|
|
275
|
+
}
|
|
276
|
+
else {
|
|
277
|
+
newInitializer = undefined;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
// Собираем переменные из тела
|
|
281
|
+
collectLoopVariables(node.statement, loopNum, variables);
|
|
282
|
+
// Трансформируем тело и условия
|
|
283
|
+
const renameMap = new Map(variables.map(v => [v.originalName, v.newName]));
|
|
284
|
+
const renameVisitor = (n) => {
|
|
285
|
+
if (typescript_1.default.isIdentifier(n)) {
|
|
286
|
+
const parent = n.parent;
|
|
287
|
+
if (parent && typescript_1.default.isPropertyAccessExpression(parent) && parent.name === n)
|
|
288
|
+
return n;
|
|
289
|
+
if (parent && typescript_1.default.isPropertyAssignment(parent) && parent.name === n)
|
|
290
|
+
return n;
|
|
291
|
+
const newName = renameMap.get(n.text);
|
|
292
|
+
if (newName)
|
|
293
|
+
return typescript_1.default.factory.createIdentifier(newName);
|
|
294
|
+
}
|
|
295
|
+
return typescript_1.default.visitEachChild(n, renameVisitor, context);
|
|
296
|
+
};
|
|
297
|
+
const transformedBody = transformLoopBody(node.statement, variables);
|
|
298
|
+
const transformedCondition = node.condition
|
|
299
|
+
? typescript_1.default.visitNode(node.condition, renameVisitor)
|
|
300
|
+
: undefined;
|
|
301
|
+
const transformedIncrementor = node.incrementor
|
|
302
|
+
? typescript_1.default.visitNode(node.incrementor, renameVisitor)
|
|
303
|
+
: undefined;
|
|
304
|
+
const newFor = typescript_1.default.factory.createForStatement(newInitializer, transformedCondition, transformedIncrementor, transformedBody);
|
|
305
|
+
const hoisted = createHoistedDeclarations(variables);
|
|
306
|
+
return [...hoisted, newFor];
|
|
307
|
+
};
|
|
308
|
+
/**
|
|
309
|
+
* Обрабатывает while/do-while циклы
|
|
310
|
+
*/
|
|
311
|
+
const transformWhileStatement = (node) => {
|
|
312
|
+
loopCounter++;
|
|
313
|
+
const loopNum = loopCounter;
|
|
314
|
+
const variables = [];
|
|
315
|
+
collectLoopVariables(node.statement, loopNum, variables);
|
|
316
|
+
if (variables.length === 0) {
|
|
317
|
+
// Нет переменных — просто обходим детей
|
|
318
|
+
return [typescript_1.default.visitEachChild(node, mainVisitor, context)];
|
|
319
|
+
}
|
|
320
|
+
const transformedBody = transformLoopBody(node.statement, variables);
|
|
321
|
+
let newLoop;
|
|
322
|
+
if (typescript_1.default.isWhileStatement(node)) {
|
|
323
|
+
newLoop = typescript_1.default.factory.createWhileStatement(typescript_1.default.visitNode(node.expression, mainVisitor), transformedBody);
|
|
324
|
+
}
|
|
325
|
+
else {
|
|
326
|
+
newLoop = typescript_1.default.factory.createDoStatement(transformedBody, typescript_1.default.visitNode(node.expression, mainVisitor));
|
|
327
|
+
}
|
|
328
|
+
const hoisted = createHoistedDeclarations(variables);
|
|
329
|
+
return [...hoisted, newLoop];
|
|
330
|
+
};
|
|
331
|
+
/**
|
|
332
|
+
* Основной visitor
|
|
333
|
+
*/
|
|
334
|
+
const mainVisitor = (node) => {
|
|
335
|
+
if (typescript_1.default.isForInStatement(node)) {
|
|
336
|
+
return transformForInStatement(node);
|
|
337
|
+
}
|
|
338
|
+
if (typescript_1.default.isForOfStatement(node)) {
|
|
339
|
+
return transformForOfStatement(node);
|
|
340
|
+
}
|
|
341
|
+
if (typescript_1.default.isForStatement(node)) {
|
|
342
|
+
return transformForStatement(node);
|
|
343
|
+
}
|
|
344
|
+
if (typescript_1.default.isWhileStatement(node) || typescript_1.default.isDoStatement(node)) {
|
|
345
|
+
return transformWhileStatement(node);
|
|
346
|
+
}
|
|
347
|
+
return typescript_1.default.visitEachChild(node, mainVisitor, context);
|
|
348
|
+
};
|
|
349
|
+
return typescript_1.default.visitNode(sourceFile, mainVisitor);
|
|
350
|
+
};
|
|
351
|
+
};
|
|
352
|
+
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.mathTransformer = mathTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
function makeMathPolyfillExpression(functionName) {
|
|
9
|
+
return typescript_1.default.factory.createPropertyAccessExpression(typescript_1.default.factory.createPropertyAccessExpression(typescript_1.default.factory.createPropertyAccessExpression(typescript_1.default.factory.createIdentifier('bt'), typescript_1.default.factory.createIdentifier('polyfill')), typescript_1.default.factory.createIdentifier('Math')), typescript_1.default.factory.createIdentifier(functionName));
|
|
10
|
+
}
|
|
11
|
+
function mathTransformer() {
|
|
12
|
+
return (context) => (sourceFile) => {
|
|
13
|
+
const REPLACE_METHODS = ['ceil', 'floor', 'trunc', 'random'];
|
|
14
|
+
const MAX_METHOD = 'max';
|
|
15
|
+
const MIN_METHOD = 'min';
|
|
16
|
+
function visit(node) {
|
|
17
|
+
node = typescript_1.default.visitEachChild(node, visit, context);
|
|
18
|
+
if (typescript_1.default.isCallExpression(node)) {
|
|
19
|
+
if (typescript_1.default.isPropertyAccessExpression(node.expression)) {
|
|
20
|
+
const prop = node.expression;
|
|
21
|
+
if (typescript_1.default.isIdentifier(prop.expression) && prop.expression.text === 'Math') {
|
|
22
|
+
const methodName = prop.name.text;
|
|
23
|
+
if (REPLACE_METHODS.includes(methodName)) {
|
|
24
|
+
return typescript_1.default.factory.createCallExpression(makeMathPolyfillExpression(methodName), undefined, node.arguments);
|
|
25
|
+
}
|
|
26
|
+
else if (methodName === MAX_METHOD) {
|
|
27
|
+
return typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(`Max`), undefined, node.arguments);
|
|
28
|
+
}
|
|
29
|
+
else if (methodName === MIN_METHOD) {
|
|
30
|
+
return typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier(`Min`), undefined, node.arguments);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
return node;
|
|
36
|
+
}
|
|
37
|
+
return typescript_1.default.visitNode(sourceFile, visit);
|
|
38
|
+
};
|
|
39
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.namespacesTransformer = namespacesTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
function namespacesTransformer() {
|
|
9
|
+
return (context) => (sourceFile) => {
|
|
10
|
+
function visit(node) {
|
|
11
|
+
if (typescript_1.default.isModuleDeclaration(node) && (node.flags & typescript_1.default.NodeFlags.Namespace)) {
|
|
12
|
+
if (node.body && typescript_1.default.isModuleBlock(node.body)) {
|
|
13
|
+
const statements = node.body.statements.map((statement) => typescript_1.default.visitNode(statement, visit));
|
|
14
|
+
const customString = typescript_1.default.factory.createExpressionStatement(typescript_1.default.factory.createStringLiteral(`META:NAMESPACE:${node.name.text}`));
|
|
15
|
+
node = [customString, ...statements];
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
return typescript_1.default.visitEachChild(node, visit, context);
|
|
19
|
+
}
|
|
20
|
+
return typescript_1.default.visitNode(sourceFile, visit);
|
|
21
|
+
};
|
|
22
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.numericSeparatorTransformer = numericSeparatorTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
/**
|
|
9
|
+
* Трансформер для удаления числовых разделителей из литералов.
|
|
10
|
+
* Преобразует числа вида 1_000_000 в 1000000.
|
|
11
|
+
*
|
|
12
|
+
* ВАЖНО: Этот трансформер должен работать в секции `before`,
|
|
13
|
+
* т.к. TypeScript printer сохраняет исходный текст литералов.
|
|
14
|
+
*
|
|
15
|
+
* @example
|
|
16
|
+
* // Вход:
|
|
17
|
+
* const x = 1_000_000;
|
|
18
|
+
* const y = 0xFF_FF;
|
|
19
|
+
*
|
|
20
|
+
* // Выход:
|
|
21
|
+
* const x = 1000000;
|
|
22
|
+
* const y = 0xFFFF;
|
|
23
|
+
*
|
|
24
|
+
* @returns TypeScript transformer factory
|
|
25
|
+
*/
|
|
26
|
+
function numericSeparatorTransformer() {
|
|
27
|
+
return (context) => {
|
|
28
|
+
return (sourceFile) => {
|
|
29
|
+
const visitor = (node) => {
|
|
30
|
+
// Обрабатываем числовые литералы
|
|
31
|
+
if (typescript_1.default.isNumericLiteral(node)) {
|
|
32
|
+
// Получаем исходный текст из source file
|
|
33
|
+
const text = node.getText(sourceFile);
|
|
34
|
+
// Проверяем, содержит ли литерал разделители
|
|
35
|
+
if (text.includes('_')) {
|
|
36
|
+
// Удаляем все подчёркивания и создаём новый литерал
|
|
37
|
+
const cleanedText = text.replace(/_/g, '');
|
|
38
|
+
return typescript_1.default.factory.createNumericLiteral(cleanedText);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
42
|
+
};
|
|
43
|
+
return typescript_1.default.visitNode(sourceFile, visitor);
|
|
44
|
+
};
|
|
45
|
+
};
|
|
46
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.objectPropertiesTransformer = objectPropertiesTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
function objectPropertiesTransformer() {
|
|
10
|
+
return (context) => (sourceFile) => {
|
|
11
|
+
function visit(node) {
|
|
12
|
+
// Обрабатываем объектные литералы
|
|
13
|
+
if (typescript_1.default.isObjectLiteralExpression(node)) {
|
|
14
|
+
const newProperties = node.properties.map(prop => {
|
|
15
|
+
// Обрабатываем shorthand properties (например, {x} -> {x: x})
|
|
16
|
+
if (typescript_1.default.isShorthandPropertyAssignment(prop)) {
|
|
17
|
+
// Создаем полное свойство с ключом в кавычках
|
|
18
|
+
const keyName = prop.name.text;
|
|
19
|
+
return typescript_1.default.factory.createPropertyAssignment(typescript_1.default.factory.createStringLiteral(keyName), prop.name);
|
|
20
|
+
}
|
|
21
|
+
// Обрабатываем обычные свойства
|
|
22
|
+
if (typescript_1.default.isPropertyAssignment(prop)) {
|
|
23
|
+
let keyNode;
|
|
24
|
+
// Если ключ - идентификатор или число, оборачиваем в строковый литерал
|
|
25
|
+
if (typescript_1.default.isIdentifier(prop.name)) {
|
|
26
|
+
keyNode = typescript_1.default.factory.createStringLiteral(prop.name.text);
|
|
27
|
+
}
|
|
28
|
+
else if (typescript_1.default.isNumericLiteral(prop.name)) {
|
|
29
|
+
keyNode = typescript_1.default.factory.createStringLiteral(prop.name.text);
|
|
30
|
+
}
|
|
31
|
+
else if (typescript_1.default.isComputedPropertyName(prop.name)) {
|
|
32
|
+
// Computed properties оставляем как есть
|
|
33
|
+
keyNode = prop.name;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
// Уже строковый литерал - оставляем как есть
|
|
37
|
+
keyNode = prop.name;
|
|
38
|
+
}
|
|
39
|
+
// Рекурсивно обрабатываем значение
|
|
40
|
+
const visitedValue = typescript_1.default.visitNode(prop.initializer, visit);
|
|
41
|
+
return typescript_1.default.factory.createPropertyAssignment(keyNode, visitedValue);
|
|
42
|
+
}
|
|
43
|
+
// Методы и другие типы свойств оставляем как есть, но обрабатываем рекурсивно
|
|
44
|
+
return typescript_1.default.visitEachChild(prop, visit, context);
|
|
45
|
+
});
|
|
46
|
+
return typescript_1.default.factory.createObjectLiteralExpression(newProperties, true);
|
|
47
|
+
}
|
|
48
|
+
return typescript_1.default.visitEachChild(node, visit, context);
|
|
49
|
+
}
|
|
50
|
+
const transformedSourceFile = typescript_1.default.visitNode(sourceFile, visit);
|
|
51
|
+
(0, utils_1.setParentNodes)(transformedSourceFile, sourceFile);
|
|
52
|
+
return transformedSourceFile;
|
|
53
|
+
};
|
|
54
|
+
}
|