@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,620 @@
|
|
|
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.remoduleTransformer = remoduleTransformer;
|
|
7
|
+
// src/transformers/remodule.ts
|
|
8
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
9
|
+
const utils_1 = require("./utils");
|
|
10
|
+
function remoduleTransformer(program) {
|
|
11
|
+
const typeChecker = program.getTypeChecker();
|
|
12
|
+
return (context) => {
|
|
13
|
+
return (sourceFile) => {
|
|
14
|
+
const factory = context.factory;
|
|
15
|
+
let currentScope = null;
|
|
16
|
+
let scopeIdCounter = 0;
|
|
17
|
+
const scopeToId = new WeakMap();
|
|
18
|
+
const variableUsages = new Map(); // "scopeId:varName" -> usage info
|
|
19
|
+
function getUsageKey(scopeId, varName) {
|
|
20
|
+
return `${scopeId}:${varName}`;
|
|
21
|
+
}
|
|
22
|
+
// Проверяет, является ли импорт только типом (type, interface, etc.)
|
|
23
|
+
function isTypeOnlyImport(node) {
|
|
24
|
+
let symbol = typeChecker.getSymbolAtLocation(node);
|
|
25
|
+
if (!symbol) {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
// Получаем алиасированный символ (если это импорт)
|
|
29
|
+
if (symbol.flags & typescript_1.default.SymbolFlags.Alias) {
|
|
30
|
+
symbol = typeChecker.getAliasedSymbol(symbol);
|
|
31
|
+
}
|
|
32
|
+
// Если у символа нет деклараций, считаем что это не тип
|
|
33
|
+
if (!symbol.declarations || symbol.declarations.length === 0) {
|
|
34
|
+
return false;
|
|
35
|
+
}
|
|
36
|
+
// Проверяем все декларации символа
|
|
37
|
+
return symbol.declarations.every(decl => {
|
|
38
|
+
return typescript_1.default.isTypeAliasDeclaration(decl) ||
|
|
39
|
+
typescript_1.default.isInterfaceDeclaration(decl) ||
|
|
40
|
+
typescript_1.default.isTypeParameterDeclaration(decl);
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
// Добавляем var __module_env = {}; в начало файла
|
|
44
|
+
const moduleEnvDecl = factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration('__module_env', undefined, undefined, factory.createObjectLiteralExpression([], false))], typescript_1.default.NodeFlags.None));
|
|
45
|
+
function createScope(envName) {
|
|
46
|
+
const scope = {
|
|
47
|
+
parent: currentScope,
|
|
48
|
+
declarations: new Set(),
|
|
49
|
+
envName
|
|
50
|
+
};
|
|
51
|
+
scopeToId.set(scope, `scope_${scopeIdCounter++}`);
|
|
52
|
+
return scope;
|
|
53
|
+
}
|
|
54
|
+
function getScopeId(scope) {
|
|
55
|
+
return scopeToId.get(scope) || 'unknown';
|
|
56
|
+
}
|
|
57
|
+
function addDeclaration(name, isFunction = false) {
|
|
58
|
+
if (currentScope) {
|
|
59
|
+
currentScope.declarations.add(name);
|
|
60
|
+
const scopeId = getScopeId(currentScope);
|
|
61
|
+
const key = getUsageKey(scopeId, name);
|
|
62
|
+
// Инициализируем информацию об использовании только если еще не было
|
|
63
|
+
if (!variableUsages.has(key)) {
|
|
64
|
+
variableUsages.set(key, {
|
|
65
|
+
declaredInScope: scopeId,
|
|
66
|
+
usedInScopes: new Set(),
|
|
67
|
+
isFunction
|
|
68
|
+
});
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
function recordUsage(name) {
|
|
73
|
+
if (currentScope) {
|
|
74
|
+
// Находим, где объявлена эта переменная
|
|
75
|
+
let scope = currentScope;
|
|
76
|
+
while (scope) {
|
|
77
|
+
if (scope.declarations.has(name)) {
|
|
78
|
+
const declScopeId = getScopeId(scope);
|
|
79
|
+
const key = getUsageKey(declScopeId, name);
|
|
80
|
+
const usage = variableUsages.get(key);
|
|
81
|
+
if (usage) {
|
|
82
|
+
const currentScopeId = getScopeId(currentScope);
|
|
83
|
+
usage.usedInScopes.add(currentScopeId);
|
|
84
|
+
}
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
scope = scope.parent;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
function isUsedInDifferentScope(varName) {
|
|
92
|
+
// Находим, где объявлена эта переменная
|
|
93
|
+
let scope = currentScope;
|
|
94
|
+
while (scope) {
|
|
95
|
+
if (scope.declarations.has(varName)) {
|
|
96
|
+
const declScopeId = getScopeId(scope);
|
|
97
|
+
const key = getUsageKey(declScopeId, varName);
|
|
98
|
+
const usage = variableUsages.get(key);
|
|
99
|
+
if (!usage)
|
|
100
|
+
return false;
|
|
101
|
+
// Проверяем, используется ли переменная в scope'е, отличном от того где объявлена
|
|
102
|
+
for (const scopeId of usage.usedInScopes) {
|
|
103
|
+
if (scopeId !== usage.declaredInScope) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
return false;
|
|
108
|
+
}
|
|
109
|
+
scope = scope.parent;
|
|
110
|
+
}
|
|
111
|
+
return false;
|
|
112
|
+
}
|
|
113
|
+
function findDeclaration(name) {
|
|
114
|
+
let scope = currentScope;
|
|
115
|
+
let depth = 0;
|
|
116
|
+
while (scope) {
|
|
117
|
+
if (scope.declarations.has(name)) {
|
|
118
|
+
// Строим путь к переменной
|
|
119
|
+
if (depth === 0) {
|
|
120
|
+
return { envPath: `__env.${name}`, found: true };
|
|
121
|
+
}
|
|
122
|
+
let path = '__env';
|
|
123
|
+
for (let i = 0; i < depth; i++) {
|
|
124
|
+
path += '.__parent';
|
|
125
|
+
}
|
|
126
|
+
path += '.' + name;
|
|
127
|
+
return { envPath: path, found: true };
|
|
128
|
+
}
|
|
129
|
+
scope = scope.parent;
|
|
130
|
+
depth++;
|
|
131
|
+
}
|
|
132
|
+
return { envPath: name, found: false };
|
|
133
|
+
}
|
|
134
|
+
function parseEnvPath(envPath) {
|
|
135
|
+
const parts = envPath.split('.');
|
|
136
|
+
let expr = factory.createIdentifier(parts[0]);
|
|
137
|
+
for (let i = 1; i < parts.length; i++) {
|
|
138
|
+
expr = factory.createPropertyAccessExpression(expr, parts[i]);
|
|
139
|
+
}
|
|
140
|
+
return expr;
|
|
141
|
+
}
|
|
142
|
+
function createFunctionDescriptor(funcName, parentEnvName, isExported = false) {
|
|
143
|
+
const envName = `${funcName}__env`;
|
|
144
|
+
const descName = `${funcName}__desc`;
|
|
145
|
+
const statements = [];
|
|
146
|
+
// var funcName__env = { __parent: parentEnv };
|
|
147
|
+
statements.push(factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(envName, undefined, undefined, factory.createObjectLiteralExpression([
|
|
148
|
+
factory.createPropertyAssignment('__parent', factory.createIdentifier(parentEnvName))
|
|
149
|
+
], false))], typescript_1.default.NodeFlags.None)));
|
|
150
|
+
// var funcName__desc = { "@descriptor": "function", "obj": undefined, "env": funcName__env, "callable": funcName };
|
|
151
|
+
statements.push(factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(descName, undefined, undefined, factory.createObjectLiteralExpression([
|
|
152
|
+
factory.createPropertyAssignment(factory.createStringLiteral('@descriptor'), factory.createStringLiteral('function')),
|
|
153
|
+
factory.createPropertyAssignment(factory.createStringLiteral('obj'), factory.createIdentifier('undefined')),
|
|
154
|
+
factory.createPropertyAssignment(factory.createStringLiteral('env'), factory.createIdentifier(envName)),
|
|
155
|
+
factory.createPropertyAssignment(factory.createStringLiteral('callable'), factory.createIdentifier(funcName))
|
|
156
|
+
], true))], typescript_1.default.NodeFlags.None)));
|
|
157
|
+
// parentEnv.funcName = funcName__desc
|
|
158
|
+
statements.push(factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(factory.createIdentifier(parentEnvName)), funcName), factory.createIdentifier(descName))));
|
|
159
|
+
// Если экспортируется, добавляем __module.exports.funcName = funcName__desc
|
|
160
|
+
if (isExported) {
|
|
161
|
+
const moduleExportPropertyAccessExpression = factory.createPropertyAccessExpression(factory.createIdentifier('__module'), 'exports');
|
|
162
|
+
statements.push(factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(moduleExportPropertyAccessExpression), funcName), factory.createIdentifier(descName))));
|
|
163
|
+
}
|
|
164
|
+
return statements;
|
|
165
|
+
}
|
|
166
|
+
function createVariableEnvAssignment(varName, parentEnvName) {
|
|
167
|
+
// parentEnv.varName = varName
|
|
168
|
+
return factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression(factory.createIdentifier(parentEnvName), varName), factory.createIdentifier(varName)));
|
|
169
|
+
}
|
|
170
|
+
// Сначала собираем все декларации в области видимости
|
|
171
|
+
function collectDeclarations(statements) {
|
|
172
|
+
for (const stmt of statements) {
|
|
173
|
+
if (typescript_1.default.isFunctionDeclaration(stmt) && stmt.name) {
|
|
174
|
+
addDeclaration(stmt.name.text, true); // функция
|
|
175
|
+
}
|
|
176
|
+
else if (typescript_1.default.isVariableStatement(stmt)) {
|
|
177
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
178
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
179
|
+
addDeclaration(decl.name.text, false); // переменная
|
|
180
|
+
}
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
// Первый проход: собираем информацию об использовании переменных
|
|
186
|
+
function analyzeUsages(node) {
|
|
187
|
+
if (typescript_1.default.isFunctionDeclaration(node) && node.name) {
|
|
188
|
+
const savedScope = currentScope;
|
|
189
|
+
currentScope = createScope('__env');
|
|
190
|
+
if (node.body) {
|
|
191
|
+
collectDeclarations(node.body.statements);
|
|
192
|
+
for (const stmt of node.body.statements) {
|
|
193
|
+
analyzeUsages(stmt);
|
|
194
|
+
}
|
|
195
|
+
// Также анализируем тело функции для использования переменных
|
|
196
|
+
analyzeUsagesInExpression(node.body);
|
|
197
|
+
}
|
|
198
|
+
currentScope = savedScope;
|
|
199
|
+
return;
|
|
200
|
+
}
|
|
201
|
+
if (typescript_1.default.isVariableStatement(node)) {
|
|
202
|
+
// Проверяем initializer для использования переменных
|
|
203
|
+
for (const decl of node.declarationList.declarations) {
|
|
204
|
+
if (decl.initializer) {
|
|
205
|
+
analyzeUsagesInExpression(decl.initializer);
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
typescript_1.default.forEachChild(node, analyzeUsages);
|
|
211
|
+
}
|
|
212
|
+
function analyzeUsagesInExpression(node) {
|
|
213
|
+
if (typescript_1.default.isIdentifier(node) && node.parent) {
|
|
214
|
+
// Не считаем декларации и property names
|
|
215
|
+
if (!typescript_1.default.isVariableDeclaration(node.parent) &&
|
|
216
|
+
!typescript_1.default.isFunctionDeclaration(node.parent) &&
|
|
217
|
+
!typescript_1.default.isParameter(node.parent) &&
|
|
218
|
+
!(typescript_1.default.isPropertyAccessExpression(node.parent) && node.parent.name === node) &&
|
|
219
|
+
!(typescript_1.default.isPropertyAssignment(node.parent) && node.parent.name === node) &&
|
|
220
|
+
!(typescript_1.default.isBindingElement(node.parent) && node.parent.name === node)) {
|
|
221
|
+
recordUsage(node.text);
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
typescript_1.default.forEachChild(node, analyzeUsagesInExpression);
|
|
225
|
+
}
|
|
226
|
+
function transformFunctionBody(body, funcName) {
|
|
227
|
+
if (!body)
|
|
228
|
+
return { body, envAssignments: [] };
|
|
229
|
+
const savedScope = currentScope;
|
|
230
|
+
currentScope = createScope('__env');
|
|
231
|
+
// Собираем все декларации в теле функции
|
|
232
|
+
collectDeclarations(body.statements);
|
|
233
|
+
const envAssignments = [];
|
|
234
|
+
const visitor = (node) => {
|
|
235
|
+
// Заменяем this на __this
|
|
236
|
+
if (node.kind === typescript_1.default.SyntaxKind.ThisKeyword) {
|
|
237
|
+
return (0, utils_1.setParentNodes)(factory.createIdentifier('__this'), node.parent);
|
|
238
|
+
}
|
|
239
|
+
// Обрабатываем идентификаторы (доступ к переменным)
|
|
240
|
+
if (typescript_1.default.isIdentifier(node) && node.parent && currentScope) {
|
|
241
|
+
// Не трогаем: объявления переменных, имена функций при декларации, property access справа, параметры
|
|
242
|
+
// Для PropertyAssignment проверяем, что это имя свойства (name), а не значение (initializer)
|
|
243
|
+
if ((typescript_1.default.isVariableDeclaration(node.parent) && node.parent.name === node) ||
|
|
244
|
+
typescript_1.default.isFunctionDeclaration(node.parent) ||
|
|
245
|
+
typescript_1.default.isParameter(node.parent) ||
|
|
246
|
+
(typescript_1.default.isPropertyAccessExpression(node.parent) && node.parent.name === node) ||
|
|
247
|
+
(typescript_1.default.isPropertyAssignment(node.parent) && node.parent.name === node && node !== node.parent.initializer) ||
|
|
248
|
+
(typescript_1.default.isBindingElement(node.parent) && node.parent.name === node)) {
|
|
249
|
+
return node;
|
|
250
|
+
}
|
|
251
|
+
const { envPath, found } = findDeclaration(node.text);
|
|
252
|
+
if (found) {
|
|
253
|
+
// Находим usage для этой переменной
|
|
254
|
+
let scope = currentScope;
|
|
255
|
+
let usage;
|
|
256
|
+
while (scope) {
|
|
257
|
+
if (scope.declarations.has(node.text)) {
|
|
258
|
+
const declScopeId = getScopeId(scope);
|
|
259
|
+
const key = getUsageKey(declScopeId, node.text);
|
|
260
|
+
usage = variableUsages.get(key);
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
scope = scope.parent;
|
|
264
|
+
}
|
|
265
|
+
// Заменяем если:
|
|
266
|
+
// 1. Переменная используется в другом scope
|
|
267
|
+
// 2. Это функция (всегда используем дескриптор)
|
|
268
|
+
if (usage && (isUsedInDifferentScope(node.text) || usage.isFunction)) {
|
|
269
|
+
// console.log(envPath);
|
|
270
|
+
const newEnvPath = (0, utils_1.setParentNodes)(parseEnvPath(envPath), node.parent);
|
|
271
|
+
(0, utils_1.markUntouchable)(newEnvPath.expression);
|
|
272
|
+
// console.log(printAstNode((newEnvPath as ts.PropertyAccessExpression).expression));
|
|
273
|
+
// console.log(newEnvPath.parent);
|
|
274
|
+
return newEnvPath;
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
279
|
+
};
|
|
280
|
+
const transformedStatements = [];
|
|
281
|
+
for (const stmt of body.statements) {
|
|
282
|
+
// Обрабатываем объявления переменных
|
|
283
|
+
if (typescript_1.default.isVariableStatement(stmt)) {
|
|
284
|
+
const declarations = [];
|
|
285
|
+
for (const decl of stmt.declarationList.declarations) {
|
|
286
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
287
|
+
const varName = decl.name.text;
|
|
288
|
+
if (isUsedInDifferentScope(varName)) {
|
|
289
|
+
// Переменная используется в другом scope - создаем присваивание в env
|
|
290
|
+
const initializer = decl.initializer
|
|
291
|
+
? typescript_1.default.visitNode(decl.initializer, visitor)
|
|
292
|
+
: factory.createIdentifier('undefined');
|
|
293
|
+
transformedStatements.push(factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(factory.createIdentifier('__env')), varName), initializer)));
|
|
294
|
+
}
|
|
295
|
+
else {
|
|
296
|
+
// Переменная не используется в других scope - оставляем обычное объявление
|
|
297
|
+
declarations.push(factory.createVariableDeclaration(decl.name, decl.exclamationToken, decl.type, decl.initializer ? typescript_1.default.visitNode(decl.initializer, visitor) : undefined));
|
|
298
|
+
}
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
// Если остались обычные декларации, добавляем их
|
|
302
|
+
if (declarations.length > 0) {
|
|
303
|
+
transformedStatements.push(factory.createVariableStatement(stmt.modifiers, factory.createVariableDeclarationList(declarations, stmt.declarationList.flags)));
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
// Обрабатываем вложенные функции
|
|
307
|
+
else if (typescript_1.default.isFunctionDeclaration(stmt) && stmt.name) {
|
|
308
|
+
const nestedFuncName = stmt.name.text;
|
|
309
|
+
// Трансформируем тело вложенной функции
|
|
310
|
+
const { body: transformedBody, envAssignments: nestedEnvAssignments } = transformFunctionBody(stmt.body, nestedFuncName);
|
|
311
|
+
// Создаем функцию
|
|
312
|
+
const funcDecl = factory.createFunctionDeclaration(undefined, stmt.asteriskToken, nestedFuncName, stmt.typeParameters, stmt.parameters, stmt.type, transformedBody);
|
|
313
|
+
transformedStatements.push(funcDecl);
|
|
314
|
+
// Добавляем env assignments для переменных внутри вложенной функции
|
|
315
|
+
transformedStatements.push(...nestedEnvAssignments);
|
|
316
|
+
// Создаем дескриптор для вложенной функции
|
|
317
|
+
const descriptorStatements = createFunctionDescriptor(nestedFuncName, '__env');
|
|
318
|
+
transformedStatements.push(...descriptorStatements);
|
|
319
|
+
}
|
|
320
|
+
else {
|
|
321
|
+
transformedStatements.push(typescript_1.default.visitEachChild(stmt, visitor, context));
|
|
322
|
+
}
|
|
323
|
+
}
|
|
324
|
+
currentScope = savedScope;
|
|
325
|
+
return {
|
|
326
|
+
body: factory.createBlock(transformedStatements, true),
|
|
327
|
+
envAssignments
|
|
328
|
+
};
|
|
329
|
+
}
|
|
330
|
+
function visitTopLevel(node) {
|
|
331
|
+
// Импорты уже обработаны в НУЛЕВОМ ПРОХОДЕ, пропускаем их здесь
|
|
332
|
+
if (typescript_1.default.isImportDeclaration(node)) {
|
|
333
|
+
return node;
|
|
334
|
+
}
|
|
335
|
+
// Обрабатываем export { ... }
|
|
336
|
+
if (typescript_1.default.isExportDeclaration(node)) {
|
|
337
|
+
if (!node.exportClause || !typescript_1.default.isNamedExports(node.exportClause)) {
|
|
338
|
+
// export * from '...' - пока не обрабатываем
|
|
339
|
+
return node;
|
|
340
|
+
}
|
|
341
|
+
const result = [];
|
|
342
|
+
for (const element of node.exportClause.elements) {
|
|
343
|
+
const localName = element.propertyName ? element.propertyName.text : element.name.text;
|
|
344
|
+
const exportedName = element.name.text;
|
|
345
|
+
// Находим, где объявлена переменная
|
|
346
|
+
const { envPath, found } = findDeclaration(localName);
|
|
347
|
+
let sourceExpr;
|
|
348
|
+
if (found) {
|
|
349
|
+
// Проверяем, нужно ли использовать env path
|
|
350
|
+
let scope = currentScope;
|
|
351
|
+
let usage;
|
|
352
|
+
while (scope) {
|
|
353
|
+
if (scope.declarations.has(localName)) {
|
|
354
|
+
const declScopeId = getScopeId(scope);
|
|
355
|
+
const key = getUsageKey(declScopeId, localName);
|
|
356
|
+
usage = variableUsages.get(key);
|
|
357
|
+
break;
|
|
358
|
+
}
|
|
359
|
+
scope = scope.parent;
|
|
360
|
+
}
|
|
361
|
+
if (usage && (usage.isFunction || isUsedInDifferentScope(localName))) {
|
|
362
|
+
const topLevelPath = envPath.replace('__env', '__module_env');
|
|
363
|
+
sourceExpr = parseEnvPath(topLevelPath);
|
|
364
|
+
}
|
|
365
|
+
else {
|
|
366
|
+
sourceExpr = factory.createIdentifier(localName);
|
|
367
|
+
}
|
|
368
|
+
}
|
|
369
|
+
else {
|
|
370
|
+
sourceExpr = factory.createIdentifier(localName);
|
|
371
|
+
}
|
|
372
|
+
// __module.exports.exportedName = sourceExpr
|
|
373
|
+
const moduleExportPropertyAccessExpression = factory.createPropertyAccessExpression(factory.createIdentifier('__module'), 'exports');
|
|
374
|
+
result.push(factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(moduleExportPropertyAccessExpression), exportedName), sourceExpr)));
|
|
375
|
+
}
|
|
376
|
+
// Добавляем оригинальное export {} в конец для TypeScript declarations
|
|
377
|
+
result.push(node);
|
|
378
|
+
return result;
|
|
379
|
+
}
|
|
380
|
+
// Обрабатываем export default
|
|
381
|
+
if (typescript_1.default.isExportAssignment(node)) {
|
|
382
|
+
// export default expression
|
|
383
|
+
const topLevelVisitor = (n) => {
|
|
384
|
+
if (typescript_1.default.isIdentifier(n) && n.parent && currentScope) {
|
|
385
|
+
if (typescript_1.default.isVariableDeclaration(n.parent) ||
|
|
386
|
+
typescript_1.default.isFunctionDeclaration(n.parent) ||
|
|
387
|
+
typescript_1.default.isParameter(n.parent) ||
|
|
388
|
+
(typescript_1.default.isPropertyAccessExpression(n.parent) && n.parent.name === n) ||
|
|
389
|
+
(typescript_1.default.isPropertyAssignment(n.parent) && n.parent.name === n && n !== n.parent.initializer) ||
|
|
390
|
+
(typescript_1.default.isBindingElement(n.parent) && n.parent.name === n)) {
|
|
391
|
+
return n;
|
|
392
|
+
}
|
|
393
|
+
const { envPath, found } = findDeclaration(n.text);
|
|
394
|
+
if (found) {
|
|
395
|
+
let scope = currentScope;
|
|
396
|
+
let usage;
|
|
397
|
+
while (scope) {
|
|
398
|
+
if (scope.declarations.has(n.text)) {
|
|
399
|
+
const declScopeId = getScopeId(scope);
|
|
400
|
+
const key = getUsageKey(declScopeId, n.text);
|
|
401
|
+
usage = variableUsages.get(key);
|
|
402
|
+
break;
|
|
403
|
+
}
|
|
404
|
+
scope = scope.parent;
|
|
405
|
+
}
|
|
406
|
+
if (usage && (usage.isFunction || isUsedInDifferentScope(n.text))) {
|
|
407
|
+
const topLevelPath = envPath.replace('__env', '__module_env');
|
|
408
|
+
const newEnvPath = (0, utils_1.setParentNodes)(parseEnvPath(topLevelPath), n.parent);
|
|
409
|
+
(0, utils_1.markUntouchable)(newEnvPath.expression);
|
|
410
|
+
return newEnvPath;
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
return typescript_1.default.visitEachChild(n, topLevelVisitor, context);
|
|
415
|
+
};
|
|
416
|
+
const transformedExpression = typescript_1.default.visitNode(node.expression, topLevelVisitor);
|
|
417
|
+
// __module.exports.__default = expression
|
|
418
|
+
const moduleExportPropertyAccessExpression = factory.createPropertyAccessExpression(factory.createIdentifier('__module'), 'exports');
|
|
419
|
+
const exportAssignment = factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(moduleExportPropertyAccessExpression), '__default'), transformedExpression));
|
|
420
|
+
// Возвращаем и присваивание и оригинальный export default для TypeScript
|
|
421
|
+
return [exportAssignment, node];
|
|
422
|
+
}
|
|
423
|
+
// Visitor для замены идентификаторов на top-level
|
|
424
|
+
const topLevelVisitor = (node) => {
|
|
425
|
+
// Обрабатываем идентификаторы (доступ к переменным)
|
|
426
|
+
if (typescript_1.default.isIdentifier(node) && node.parent && currentScope) {
|
|
427
|
+
// Не трогаем: объявления переменных, имена функций при декларации, property access справа, параметры
|
|
428
|
+
// Для PropertyAssignment проверяем, что это имя свойства (name), а не значение (initializer)
|
|
429
|
+
if ((typescript_1.default.isVariableDeclaration(node.parent) && node.parent.name === node) ||
|
|
430
|
+
typescript_1.default.isFunctionDeclaration(node.parent) ||
|
|
431
|
+
typescript_1.default.isParameter(node.parent) ||
|
|
432
|
+
(typescript_1.default.isPropertyAccessExpression(node.parent) && node.parent.name === node) ||
|
|
433
|
+
(typescript_1.default.isPropertyAssignment(node.parent) && node.parent.name === node && node !== node.parent.initializer) ||
|
|
434
|
+
(typescript_1.default.isBindingElement(node.parent) && node.parent.name === node)) {
|
|
435
|
+
return node;
|
|
436
|
+
}
|
|
437
|
+
const { envPath, found } = findDeclaration(node.text);
|
|
438
|
+
if (found) {
|
|
439
|
+
// Находим usage для этой переменной
|
|
440
|
+
let scope = currentScope;
|
|
441
|
+
let usage;
|
|
442
|
+
while (scope) {
|
|
443
|
+
if (scope.declarations.has(node.text)) {
|
|
444
|
+
const declScopeId = getScopeId(scope);
|
|
445
|
+
const key = getUsageKey(declScopeId, node.text);
|
|
446
|
+
usage = variableUsages.get(key);
|
|
447
|
+
break;
|
|
448
|
+
}
|
|
449
|
+
scope = scope.parent;
|
|
450
|
+
}
|
|
451
|
+
// На top-level заменяем если это функция (используем дескриптор)
|
|
452
|
+
// или если переменная используется в другом scope
|
|
453
|
+
if (usage && (usage.isFunction || isUsedInDifferentScope(node.text))) {
|
|
454
|
+
// Для top-level используем __module_env вместо __env
|
|
455
|
+
const topLevelPath = envPath.replace('__env', '__module_env');
|
|
456
|
+
const newEnvPath = (0, utils_1.setParentNodes)(parseEnvPath(topLevelPath), node.parent);
|
|
457
|
+
(0, utils_1.markUntouchable)(newEnvPath.expression);
|
|
458
|
+
// console.log(printAstNode((newEnvPath as ts.PropertyAccessExpression).expression));
|
|
459
|
+
// console.log(newEnvPath.parent);
|
|
460
|
+
return newEnvPath;
|
|
461
|
+
// return setParentNodes(parseEnvPath(topLevelPath), node.parent);
|
|
462
|
+
}
|
|
463
|
+
}
|
|
464
|
+
}
|
|
465
|
+
return typescript_1.default.visitEachChild(node, topLevelVisitor, context);
|
|
466
|
+
};
|
|
467
|
+
// Обрабатываем top-level функции
|
|
468
|
+
if (typescript_1.default.isFunctionDeclaration(node) && node.name) {
|
|
469
|
+
const funcName = node.name.text;
|
|
470
|
+
const isExported = node.modifiers?.some(mod => mod.kind === typescript_1.default.SyntaxKind.ExportKeyword) || false;
|
|
471
|
+
// Добавляем в module scope
|
|
472
|
+
if (!currentScope) {
|
|
473
|
+
currentScope = createScope('__module_env');
|
|
474
|
+
}
|
|
475
|
+
addDeclaration(funcName);
|
|
476
|
+
// Трансформируем тело функции
|
|
477
|
+
const { body: transformedBody, envAssignments } = transformFunctionBody(node.body, funcName);
|
|
478
|
+
// Создаем функцию сохраняя export модификатор
|
|
479
|
+
const funcDecl = factory.createFunctionDeclaration(node.modifiers, // сохраняем модификаторы включая export
|
|
480
|
+
node.asteriskToken, funcName, node.typeParameters, node.parameters, node.type, transformedBody);
|
|
481
|
+
const result = [funcDecl];
|
|
482
|
+
// Добавляем env assignments для переменных внутри функции
|
|
483
|
+
result.push(...envAssignments);
|
|
484
|
+
// Создаем дескриптор (с флагом isExported)
|
|
485
|
+
const descriptorStatements = createFunctionDescriptor(funcName, '__module_env', isExported);
|
|
486
|
+
result.push(...descriptorStatements);
|
|
487
|
+
return result;
|
|
488
|
+
}
|
|
489
|
+
// Обрабатываем top-level переменные
|
|
490
|
+
if (typescript_1.default.isVariableStatement(node)) {
|
|
491
|
+
if (!currentScope) {
|
|
492
|
+
currentScope = createScope('__module_env');
|
|
493
|
+
}
|
|
494
|
+
const isExported = node.modifiers?.some(mod => mod.kind === typescript_1.default.SyntaxKind.ExportKeyword) || false;
|
|
495
|
+
const result = [];
|
|
496
|
+
const declarations = [];
|
|
497
|
+
for (const decl of node.declarationList.declarations) {
|
|
498
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
499
|
+
const varName = decl.name.text;
|
|
500
|
+
addDeclaration(varName);
|
|
501
|
+
if (isUsedInDifferentScope(varName)) {
|
|
502
|
+
// Переменная используется в другом scope - не создаем обычное объявление
|
|
503
|
+
// вместо этого сразу записываем в env
|
|
504
|
+
const initializer = decl.initializer
|
|
505
|
+
? typescript_1.default.visitNode(decl.initializer, topLevelVisitor)
|
|
506
|
+
: factory.createIdentifier('undefined');
|
|
507
|
+
result.push(factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(factory.createIdentifier('__module_env')), varName), initializer)));
|
|
508
|
+
}
|
|
509
|
+
else {
|
|
510
|
+
// Переменная не используется в других scope - оставляем обычное объявление
|
|
511
|
+
const visitedDecl = factory.createVariableDeclaration(decl.name, decl.exclamationToken, decl.type, decl.initializer ? typescript_1.default.visitNode(decl.initializer, topLevelVisitor) : undefined);
|
|
512
|
+
declarations.push(visitedDecl);
|
|
513
|
+
}
|
|
514
|
+
// Если экспортируется, добавляем __module.exports.varName = varName или __module_env.varName
|
|
515
|
+
if (isExported) {
|
|
516
|
+
const moduleExportPropertyAccessExpression = factory.createPropertyAccessExpression(factory.createIdentifier('__module'), 'exports');
|
|
517
|
+
// Если переменная захвачена в __module_env, берем ее оттуда
|
|
518
|
+
const sourceExpr = isUsedInDifferentScope(varName)
|
|
519
|
+
? factory.createPropertyAccessExpression(factory.createIdentifier('__module_env'), varName)
|
|
520
|
+
: factory.createIdentifier(varName);
|
|
521
|
+
result.push(factory.createExpressionStatement(factory.createAssignment(factory.createPropertyAccessExpression((0, utils_1.markUntouchable)(moduleExportPropertyAccessExpression), varName), sourceExpr)));
|
|
522
|
+
}
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
// Если остались обычные декларации, добавляем их первыми (сохраняя export модификатор)
|
|
526
|
+
if (declarations.length > 0) {
|
|
527
|
+
result.unshift(factory.createVariableStatement(node.modifiers, // сохраняем модификаторы включая export
|
|
528
|
+
factory.createVariableDeclarationList(declarations, node.declarationList.flags)));
|
|
529
|
+
}
|
|
530
|
+
return result.length > 0 ? result : node;
|
|
531
|
+
}
|
|
532
|
+
// Для всех остальных top-level statements применяем visitor
|
|
533
|
+
return typescript_1.default.visitEachChild(node, topLevelVisitor, context);
|
|
534
|
+
}
|
|
535
|
+
// НУЛЕВОЙ ПРОХОД: Трансформируем импорты в переменные
|
|
536
|
+
function transformImports(statements) {
|
|
537
|
+
const result = [];
|
|
538
|
+
for (const statement of statements) {
|
|
539
|
+
if (typescript_1.default.isImportDeclaration(statement)) {
|
|
540
|
+
const moduleSpecifier = statement.moduleSpecifier;
|
|
541
|
+
if (!typescript_1.default.isStringLiteral(moduleSpecifier)) {
|
|
542
|
+
result.push(statement);
|
|
543
|
+
continue;
|
|
544
|
+
}
|
|
545
|
+
const modulePath = moduleSpecifier.text;
|
|
546
|
+
// Генерируем имя переменной для модуля
|
|
547
|
+
const moduleVarName = `__module_${modulePath.replace(/[^a-zA-Z0-9]/g, '_')}`;
|
|
548
|
+
// var moduleVarName = bt.require(modulePath, UrlParent(AbsoluteUrl("dummy")))
|
|
549
|
+
const requireCall = (factory.createCallExpression((0, utils_1.markUntouchable)(factory.createPropertyAccessExpression(factory.createIdentifier('bt'), factory.createIdentifier('require'))), undefined, [
|
|
550
|
+
factory.createStringLiteral(modulePath),
|
|
551
|
+
factory.createCallExpression(factory.createIdentifier('UrlParent'), undefined, [
|
|
552
|
+
factory.createCallExpression(factory.createIdentifier('__AbsoluteUrl'), undefined, [factory.createStringLiteral('dummy')])
|
|
553
|
+
])
|
|
554
|
+
]));
|
|
555
|
+
result.push(factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(moduleVarName, undefined, undefined, requireCall)], typescript_1.default.NodeFlags.None)));
|
|
556
|
+
// Обрабатываем import clause
|
|
557
|
+
if (statement.importClause) {
|
|
558
|
+
// import X from "Y" -> var X = moduleY.__default
|
|
559
|
+
if (statement.importClause.name) {
|
|
560
|
+
const importName = statement.importClause.name.text;
|
|
561
|
+
// Пропускаем импорты типов
|
|
562
|
+
if (!isTypeOnlyImport(statement.importClause.name)) {
|
|
563
|
+
result.push(factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(importName, undefined, undefined, factory.createPropertyAccessExpression(factory.createIdentifier(moduleVarName), '__default'))], typescript_1.default.NodeFlags.None)));
|
|
564
|
+
}
|
|
565
|
+
}
|
|
566
|
+
// import { a, b as c } from "Y"
|
|
567
|
+
if (statement.importClause.namedBindings && typescript_1.default.isNamedImports(statement.importClause.namedBindings)) {
|
|
568
|
+
for (const element of statement.importClause.namedBindings.elements) {
|
|
569
|
+
const importedName = element.propertyName ? element.propertyName.text : element.name.text;
|
|
570
|
+
const localName = element.name.text;
|
|
571
|
+
// Пропускаем импорты типов
|
|
572
|
+
if (!isTypeOnlyImport(element.name)) {
|
|
573
|
+
result.push(factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(localName, undefined, undefined, factory.createPropertyAccessExpression(factory.createIdentifier(moduleVarName), importedName))], typescript_1.default.NodeFlags.None)));
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
// import * as ns from "Y"
|
|
578
|
+
if (statement.importClause.namedBindings && typescript_1.default.isNamespaceImport(statement.importClause.namedBindings)) {
|
|
579
|
+
const namespaceName = statement.importClause.namedBindings.name.text;
|
|
580
|
+
result.push(factory.createVariableStatement(undefined, factory.createVariableDeclarationList([factory.createVariableDeclaration(namespaceName, undefined, undefined, factory.createIdentifier(moduleVarName))], typescript_1.default.NodeFlags.None)));
|
|
581
|
+
}
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
else {
|
|
585
|
+
result.push(statement);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
return result.map(stmt => (0, utils_1.setParentNodes)(stmt));
|
|
589
|
+
}
|
|
590
|
+
// Трансформируем импорты перед анализом
|
|
591
|
+
const statementsWithTransformedImports = transformImports(sourceFile.statements);
|
|
592
|
+
// ПЕРВЫЙ ПРОХОД: Собираем все top-level декларации и анализируем использование
|
|
593
|
+
currentScope = createScope('__module_env');
|
|
594
|
+
collectDeclarations(statementsWithTransformedImports);
|
|
595
|
+
for (const statement of statementsWithTransformedImports) {
|
|
596
|
+
analyzeUsages(statement);
|
|
597
|
+
}
|
|
598
|
+
// ВТОРОЙ ПРОХОД: Трансформируем
|
|
599
|
+
// Сбрасываем счетчик scope ID и создаем новый module scope
|
|
600
|
+
scopeIdCounter = 0;
|
|
601
|
+
currentScope = createScope('__module_env');
|
|
602
|
+
collectDeclarations(statementsWithTransformedImports);
|
|
603
|
+
// Трансформируем все statements
|
|
604
|
+
const transformedStatements = [];
|
|
605
|
+
for (const statement of statementsWithTransformedImports) {
|
|
606
|
+
const result = visitTopLevel(statement);
|
|
607
|
+
if (Array.isArray(result)) {
|
|
608
|
+
transformedStatements.push(...result);
|
|
609
|
+
}
|
|
610
|
+
else if (result) {
|
|
611
|
+
transformedStatements.push(result);
|
|
612
|
+
}
|
|
613
|
+
}
|
|
614
|
+
const newStatements = [moduleEnvDecl, ...transformedStatements];
|
|
615
|
+
newStatements.forEach(stmt => (0, utils_1.setParentNodes)(stmt, sourceFile));
|
|
616
|
+
// Возвращаем файл с __module_env в начале и трансформированными statements
|
|
617
|
+
return (0, utils_1.preserveSymbolsFrom)(factory.updateSourceFile(sourceFile, [moduleEnvDecl, ...transformedStatements]), sourceFile);
|
|
618
|
+
};
|
|
619
|
+
};
|
|
620
|
+
}
|