@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,222 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
36
|
+
exports.default = arrayGeneralTransformer;
|
|
37
|
+
const ts = __importStar(require("typescript"));
|
|
38
|
+
const utils_1 = require("./utils");
|
|
39
|
+
function makeArrayPolyfillExpression(functionName) {
|
|
40
|
+
return (0, utils_1.markUntouchable)(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier('bt'), ts.factory.createIdentifier('polyfill')), ts.factory.createIdentifier('Array')), ts.factory.createIdentifier(functionName)));
|
|
41
|
+
}
|
|
42
|
+
function collectArgs(expression, node, count, restAsArray = false, visitor = undefined) {
|
|
43
|
+
const args = [expression];
|
|
44
|
+
if (count !== undefined) {
|
|
45
|
+
const positionalEnd = restAsArray ? count - 2 : count - 1;
|
|
46
|
+
for (let i = 0; i < positionalEnd; i++) {
|
|
47
|
+
args.push(node.arguments[i] || ts.factory.createIdentifier('undefined'));
|
|
48
|
+
}
|
|
49
|
+
if (restAsArray) {
|
|
50
|
+
const restArgs = node.arguments.slice(positionalEnd);
|
|
51
|
+
args.push(ts.factory.createArrayLiteralExpression(restArgs));
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
else {
|
|
55
|
+
args.push(...node.arguments);
|
|
56
|
+
}
|
|
57
|
+
if (visitor !== undefined) {
|
|
58
|
+
for (let i = 0; i < args.length; i++) {
|
|
59
|
+
args[i] = ts.visitNode(args[i], visitor);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
return args;
|
|
63
|
+
}
|
|
64
|
+
function arrayGeneralTransformer(program) {
|
|
65
|
+
return (context) => (file) => {
|
|
66
|
+
const typeChecker = program.getTypeChecker();
|
|
67
|
+
function visit(node) {
|
|
68
|
+
// Check for method calls on arrays
|
|
69
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {
|
|
70
|
+
const expression = node.expression.expression;
|
|
71
|
+
const type = typeChecker.getTypeAtLocation(expression);
|
|
72
|
+
// Check if the type is an array or array-like
|
|
73
|
+
const isArrayType = typeChecker.typeToString(type).includes('[]') ||
|
|
74
|
+
((type.flags & ts.TypeFlags.Object) !== 0 && typeChecker.getIndexTypeOfType(type, ts.IndexKind.Number) !== undefined);
|
|
75
|
+
if (isArrayType) {
|
|
76
|
+
if (node.expression.name.text === 'at') {
|
|
77
|
+
const args = collectArgs(expression, node, 2, false, visit);
|
|
78
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('at'), undefined, args);
|
|
79
|
+
}
|
|
80
|
+
if (node.expression.name.text === 'concat') {
|
|
81
|
+
const args = collectArgs(expression, node, undefined, false, visit);
|
|
82
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('ArrayUnion'), undefined, args);
|
|
83
|
+
}
|
|
84
|
+
if (node.expression.name.text === 'copyWithin') {
|
|
85
|
+
const args = collectArgs(expression, node, 4, false, visit);
|
|
86
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('copyWithin'), undefined, args);
|
|
87
|
+
}
|
|
88
|
+
if (node.expression.name.text === 'entries') {
|
|
89
|
+
const args = collectArgs(expression, node, 1, false, visit);
|
|
90
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('entries'), undefined, args);
|
|
91
|
+
}
|
|
92
|
+
if (node.expression.name.text === 'fill') {
|
|
93
|
+
const args = collectArgs(expression, node, 4, false, visit);
|
|
94
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('fill'), undefined, args);
|
|
95
|
+
}
|
|
96
|
+
if (node.expression.name.text === 'flat') {
|
|
97
|
+
const args = collectArgs(expression, node, 2, false, visit);
|
|
98
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('flat'), undefined, args);
|
|
99
|
+
}
|
|
100
|
+
if (node.expression.name.text === 'includes') {
|
|
101
|
+
const args = collectArgs(expression, node, 3, false, visit);
|
|
102
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('includes'), undefined, args);
|
|
103
|
+
}
|
|
104
|
+
if (node.expression.name.text === 'indexOf') {
|
|
105
|
+
const args = collectArgs(expression, node, 3, false, visit);
|
|
106
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('indexOf'), undefined, args);
|
|
107
|
+
}
|
|
108
|
+
if (node.expression.name.text === 'join') {
|
|
109
|
+
const args = collectArgs(expression, node, 2, false, visit);
|
|
110
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('join'), undefined, args);
|
|
111
|
+
}
|
|
112
|
+
if (node.expression.name.text === 'keys') {
|
|
113
|
+
const args = collectArgs(expression, node, 1, false, visit);
|
|
114
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('keys'), undefined, args);
|
|
115
|
+
}
|
|
116
|
+
if (node.expression.name.text === 'lastIndexOf') {
|
|
117
|
+
const args = collectArgs(expression, node, 3, false, visit);
|
|
118
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('lastIndexOf'), undefined, args);
|
|
119
|
+
}
|
|
120
|
+
if (node.expression.name.text === 'pop') {
|
|
121
|
+
const args = collectArgs(expression, node, 1, false, visit);
|
|
122
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('pop'), undefined, args);
|
|
123
|
+
}
|
|
124
|
+
// if (node.expression.name.text === 'push') {
|
|
125
|
+
// const args = collectArgs(expression, node, 1);
|
|
126
|
+
// return ts.factory.createCallExpression(
|
|
127
|
+
// makeArrayPolyfillExpression('push'),
|
|
128
|
+
// undefined,
|
|
129
|
+
// args
|
|
130
|
+
// );
|
|
131
|
+
// }
|
|
132
|
+
if (node.expression.name.text === 'reverse') {
|
|
133
|
+
const args = collectArgs(expression, node, 1, false, visit);
|
|
134
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('reverse'), undefined, args);
|
|
135
|
+
}
|
|
136
|
+
if (node.expression.name.text === 'shift') {
|
|
137
|
+
const args = collectArgs(expression, node, 1, false, visit);
|
|
138
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('shift'), undefined, args);
|
|
139
|
+
}
|
|
140
|
+
if (node.expression.name.text === 'slice') {
|
|
141
|
+
const args = collectArgs(expression, node, 3, false, visit);
|
|
142
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('slice'), undefined, args);
|
|
143
|
+
}
|
|
144
|
+
if (node.expression.name.text === 'splice') {
|
|
145
|
+
const args = collectArgs(expression, node, 4, true, visit);
|
|
146
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('splice'), undefined, args);
|
|
147
|
+
}
|
|
148
|
+
// if (node.expression.name.text === 'sort') {
|
|
149
|
+
// const args = collectArgs(expression, node, 3);
|
|
150
|
+
// return ts.factory.createCallExpression(
|
|
151
|
+
// makeArrayPolyfillExpression('sort'),
|
|
152
|
+
// undefined,
|
|
153
|
+
// args
|
|
154
|
+
// );
|
|
155
|
+
// }
|
|
156
|
+
if (node.expression.name.text === 'toReversed') {
|
|
157
|
+
const args = collectArgs(expression, node, 1, false, visit);
|
|
158
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('toReversed'), undefined, args);
|
|
159
|
+
}
|
|
160
|
+
// if (node.expression.name.text === 'toSorted') {
|
|
161
|
+
// const args = collectArgs(expression, node, 3);
|
|
162
|
+
// return ts.factory.createCallExpression(
|
|
163
|
+
// makeArrayPolyfillExpression('toSorted'),
|
|
164
|
+
// undefined,
|
|
165
|
+
// args
|
|
166
|
+
// );
|
|
167
|
+
// }
|
|
168
|
+
if (node.expression.name.text === 'toSpliced') {
|
|
169
|
+
const args = collectArgs(expression, node, 4, true, visit);
|
|
170
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('toSpliced'), undefined, args);
|
|
171
|
+
}
|
|
172
|
+
if (node.expression.name.text === 'unshift') {
|
|
173
|
+
const args = collectArgs(expression, node, 2, true, visit);
|
|
174
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('unshift'), undefined, args);
|
|
175
|
+
}
|
|
176
|
+
if (node.expression.name.text === 'values') {
|
|
177
|
+
const args = collectArgs(expression, node, 1, false, visit);
|
|
178
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('values'), undefined, args);
|
|
179
|
+
}
|
|
180
|
+
if (node.expression.name.text === 'with') {
|
|
181
|
+
const args = collectArgs(expression, node, 3, false, visit);
|
|
182
|
+
return ts.factory.createCallExpression(makeArrayPolyfillExpression('_with'), undefined, args);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
// Check for .length property access
|
|
187
|
+
if (ts.isPropertyAccessExpression(node) && node.name.text === 'length') {
|
|
188
|
+
const expression = node.expression;
|
|
189
|
+
const type = typeChecker.getTypeAtLocation(expression);
|
|
190
|
+
// Check if the type is an array or array-like
|
|
191
|
+
const isArrayType = typeChecker.typeToString(type).includes('[]') ||
|
|
192
|
+
((type.flags & ts.TypeFlags.Object) !== 0 && typeChecker.getIndexTypeOfType(type, ts.IndexKind.Number) !== undefined);
|
|
193
|
+
if (isArrayType) {
|
|
194
|
+
// Replace arr.length with ArrayCount(arr)
|
|
195
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('ArrayCount'), undefined, [expression]);
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
// Check for Array.isArray and Array.from calls
|
|
199
|
+
if (ts.isCallExpression(node)) {
|
|
200
|
+
const expression = node.expression;
|
|
201
|
+
if (ts.isPropertyAccessExpression(expression) &&
|
|
202
|
+
expression.name.text === 'isArray' &&
|
|
203
|
+
ts.isIdentifier(expression.expression) &&
|
|
204
|
+
expression.expression.text === 'Array') {
|
|
205
|
+
// Replace Array.isArray(value) with IsArray(value)
|
|
206
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('IsArray'), undefined, node.arguments);
|
|
207
|
+
}
|
|
208
|
+
if (ts.isPropertyAccessExpression(expression) &&
|
|
209
|
+
expression.name.text === 'from' &&
|
|
210
|
+
ts.isIdentifier(expression.expression) &&
|
|
211
|
+
expression.expression.text === 'Array') {
|
|
212
|
+
// Replace Array.from(value) with ArraySelectAll(value)
|
|
213
|
+
return ts.factory.createCallExpression(ts.factory.createIdentifier('ArraySelectAll'), undefined, node.arguments);
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
// Recursively visit child nodes
|
|
217
|
+
return ts.visitEachChild(node, visit, context);
|
|
218
|
+
}
|
|
219
|
+
const transformedFile = ts.visitNode(file, visit);
|
|
220
|
+
return ts.factory.updateSourceFile(transformedFile, transformedFile.statements);
|
|
221
|
+
};
|
|
222
|
+
}
|
|
@@ -0,0 +1,212 @@
|
|
|
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.blockScopingTransformer = blockScopingTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
/**
|
|
9
|
+
* Трансформер для преобразования let/const в var.
|
|
10
|
+
*
|
|
11
|
+
* Обрабатывает:
|
|
12
|
+
* 1. Простая замена let/const → var
|
|
13
|
+
* 2. Shadowing detection — переименование при конфликтах имён
|
|
14
|
+
*
|
|
15
|
+
* НЕ обрабатывает (MVP):
|
|
16
|
+
* - Замыкания в циклах (IIFE wrapper)
|
|
17
|
+
* - TDZ (Temporal Dead Zone) — TypeScript проверяет
|
|
18
|
+
* - Const violations — TypeScript проверяет
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Вход:
|
|
22
|
+
* let x = 1;
|
|
23
|
+
* const y = 2;
|
|
24
|
+
* {
|
|
25
|
+
* let x = 3; // shadowing
|
|
26
|
+
* }
|
|
27
|
+
*
|
|
28
|
+
* // Выход:
|
|
29
|
+
* var x = 1;
|
|
30
|
+
* var y = 2;
|
|
31
|
+
* {
|
|
32
|
+
* var x_1 = 3; // переименовано
|
|
33
|
+
* }
|
|
34
|
+
*
|
|
35
|
+
* @returns TypeScript transformer factory
|
|
36
|
+
*/
|
|
37
|
+
function blockScopingTransformer() {
|
|
38
|
+
return (context) => {
|
|
39
|
+
return (sourceFile) => {
|
|
40
|
+
// Счётчик для генерации уникальных имён
|
|
41
|
+
let uidCounter = 0;
|
|
42
|
+
const generateUid = (name) => `${name}_${++uidCounter}`;
|
|
43
|
+
const scopeStack = [];
|
|
44
|
+
// Текущие переименования для данного scope
|
|
45
|
+
const pushScope = () => scopeStack.push(new Map());
|
|
46
|
+
const popScope = () => scopeStack.pop();
|
|
47
|
+
/**
|
|
48
|
+
* Получить текущее имя переменной с учётом переименований
|
|
49
|
+
*/
|
|
50
|
+
const resolveName = (name) => {
|
|
51
|
+
// Ищем снизу вверх (от внутреннего scope к внешнему)
|
|
52
|
+
for (let i = scopeStack.length - 1; i >= 0; i--) {
|
|
53
|
+
const renamed = scopeStack[i].get(name);
|
|
54
|
+
if (renamed !== undefined) {
|
|
55
|
+
return renamed;
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
return name;
|
|
59
|
+
};
|
|
60
|
+
/**
|
|
61
|
+
* Проверить, есть ли переменная в родительских scopes (для shadowing detection)
|
|
62
|
+
*/
|
|
63
|
+
const hasInParentScopes = (name) => {
|
|
64
|
+
for (let i = scopeStack.length - 2; i >= 0; i--) {
|
|
65
|
+
if (scopeStack[i].has(name)) {
|
|
66
|
+
return true;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return false;
|
|
70
|
+
};
|
|
71
|
+
/**
|
|
72
|
+
* Зарегистрировать переменную в текущем scope
|
|
73
|
+
* Возвращает новое имя если было переименование, иначе оригинальное
|
|
74
|
+
*/
|
|
75
|
+
const registerVariable = (name) => {
|
|
76
|
+
const currentScope = scopeStack[scopeStack.length - 1];
|
|
77
|
+
if (!currentScope)
|
|
78
|
+
return name;
|
|
79
|
+
// Проверяем shadowing
|
|
80
|
+
if (hasInParentScopes(name)) {
|
|
81
|
+
const newName = generateUid(name);
|
|
82
|
+
currentScope.set(name, newName);
|
|
83
|
+
return newName;
|
|
84
|
+
}
|
|
85
|
+
// Нет shadowing — регистрируем с оригинальным именем
|
|
86
|
+
currentScope.set(name, name);
|
|
87
|
+
return name;
|
|
88
|
+
};
|
|
89
|
+
/**
|
|
90
|
+
* Проверяем, является ли узел началом нового block scope
|
|
91
|
+
*/
|
|
92
|
+
const isBlockScopeNode = (node) => {
|
|
93
|
+
return typescript_1.default.isBlock(node) ||
|
|
94
|
+
typescript_1.default.isForStatement(node) ||
|
|
95
|
+
typescript_1.default.isForInStatement(node) ||
|
|
96
|
+
typescript_1.default.isForOfStatement(node) ||
|
|
97
|
+
typescript_1.default.isCaseClause(node) ||
|
|
98
|
+
typescript_1.default.isDefaultClause(node);
|
|
99
|
+
};
|
|
100
|
+
/**
|
|
101
|
+
* Проверяем, является ли узел function scope (var hoisting boundary)
|
|
102
|
+
*/
|
|
103
|
+
const isFunctionScopeNode = (node) => {
|
|
104
|
+
return typescript_1.default.isFunctionDeclaration(node) ||
|
|
105
|
+
typescript_1.default.isFunctionExpression(node) ||
|
|
106
|
+
typescript_1.default.isArrowFunction(node) ||
|
|
107
|
+
typescript_1.default.isMethodDeclaration(node) ||
|
|
108
|
+
typescript_1.default.isSourceFile(node);
|
|
109
|
+
};
|
|
110
|
+
/**
|
|
111
|
+
* Обрабатываем VariableDeclarationList
|
|
112
|
+
*/
|
|
113
|
+
const transformVariableDeclarationList = (node) => {
|
|
114
|
+
const isLet = (node.flags & typescript_1.default.NodeFlags.Let) !== 0;
|
|
115
|
+
const isConst = (node.flags & typescript_1.default.NodeFlags.Const) !== 0;
|
|
116
|
+
if (!isLet && !isConst) {
|
|
117
|
+
// Уже var — просто обходим дочерние узлы
|
|
118
|
+
return typescript_1.default.factory.updateVariableDeclarationList(node, node.declarations.map(decl => typescript_1.default.visitNode(decl, visitor)));
|
|
119
|
+
}
|
|
120
|
+
// Преобразуем let/const → var
|
|
121
|
+
const newDeclarations = node.declarations.map(decl => {
|
|
122
|
+
if (typescript_1.default.isIdentifier(decl.name)) {
|
|
123
|
+
const originalName = decl.name.text;
|
|
124
|
+
const newName = registerVariable(originalName);
|
|
125
|
+
// Рекурсивно обрабатываем initializer
|
|
126
|
+
const newInitializer = decl.initializer
|
|
127
|
+
? typescript_1.default.visitNode(decl.initializer, visitor)
|
|
128
|
+
: undefined;
|
|
129
|
+
if (newName !== originalName) {
|
|
130
|
+
// Переименовываем
|
|
131
|
+
return typescript_1.default.factory.createVariableDeclaration(typescript_1.default.factory.createIdentifier(newName), undefined, undefined, newInitializer);
|
|
132
|
+
}
|
|
133
|
+
else {
|
|
134
|
+
return typescript_1.default.factory.createVariableDeclaration(decl.name, undefined, undefined, newInitializer);
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
// TODO: BindingPattern (деструктуризация) — пока просто обходим
|
|
138
|
+
return typescript_1.default.visitNode(decl, visitor);
|
|
139
|
+
});
|
|
140
|
+
// Создаём var declaration
|
|
141
|
+
return typescript_1.default.factory.createVariableDeclarationList(newDeclarations, typescript_1.default.NodeFlags.None // var
|
|
142
|
+
);
|
|
143
|
+
};
|
|
144
|
+
/**
|
|
145
|
+
* Основной visitor
|
|
146
|
+
*/
|
|
147
|
+
const visitor = (node) => {
|
|
148
|
+
// Начало function scope — полностью новый контекст для var
|
|
149
|
+
if (isFunctionScopeNode(node) && !typescript_1.default.isSourceFile(node)) {
|
|
150
|
+
pushScope();
|
|
151
|
+
const result = typescript_1.default.visitEachChild(node, visitor, context);
|
|
152
|
+
popScope();
|
|
153
|
+
return result;
|
|
154
|
+
}
|
|
155
|
+
// Начало block scope
|
|
156
|
+
if (isBlockScopeNode(node)) {
|
|
157
|
+
pushScope();
|
|
158
|
+
const result = typescript_1.default.visitEachChild(node, visitor, context);
|
|
159
|
+
popScope();
|
|
160
|
+
return result;
|
|
161
|
+
}
|
|
162
|
+
// Обрабатываем VariableDeclarationList
|
|
163
|
+
if (typescript_1.default.isVariableDeclarationList(node)) {
|
|
164
|
+
return transformVariableDeclarationList(node);
|
|
165
|
+
}
|
|
166
|
+
// Переименовываем использования переменных
|
|
167
|
+
if (typescript_1.default.isIdentifier(node)) {
|
|
168
|
+
const parent = node.parent;
|
|
169
|
+
// Пропускаем случаи где identifier — не ссылка на переменную:
|
|
170
|
+
// - объявления (обрабатываются в transformVariableDeclarationList)
|
|
171
|
+
// - property access: obj.prop
|
|
172
|
+
// - property name в объектном литерале: { prop: value }
|
|
173
|
+
// - parameter names (обрабатываются отдельно)
|
|
174
|
+
if (parent) {
|
|
175
|
+
// obj.prop — prop не переменная
|
|
176
|
+
if (typescript_1.default.isPropertyAccessExpression(parent) && parent.name === node) {
|
|
177
|
+
return node;
|
|
178
|
+
}
|
|
179
|
+
// { prop: value } — prop не переменная
|
|
180
|
+
if (typescript_1.default.isPropertyAssignment(parent) && parent.name === node) {
|
|
181
|
+
return node;
|
|
182
|
+
}
|
|
183
|
+
// function foo() — foo обрабатывается отдельно
|
|
184
|
+
if (typescript_1.default.isFunctionDeclaration(parent) && parent.name === node) {
|
|
185
|
+
return node;
|
|
186
|
+
}
|
|
187
|
+
// let x = ... — x обрабатывается в transformVariableDeclarationList
|
|
188
|
+
if (typescript_1.default.isVariableDeclaration(parent) && parent.name === node) {
|
|
189
|
+
return node;
|
|
190
|
+
}
|
|
191
|
+
// (param) => ... — param не let/const
|
|
192
|
+
if (typescript_1.default.isParameter(parent) && parent.name === node) {
|
|
193
|
+
return node;
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
// Проверяем, нужно ли переименовать
|
|
197
|
+
const originalName = node.text;
|
|
198
|
+
const resolvedName = resolveName(originalName);
|
|
199
|
+
if (resolvedName !== originalName) {
|
|
200
|
+
return typescript_1.default.factory.createIdentifier(resolvedName);
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
204
|
+
};
|
|
205
|
+
// Инициализируем глобальный scope
|
|
206
|
+
pushScope();
|
|
207
|
+
const result = typescript_1.default.visitNode(sourceFile, visitor);
|
|
208
|
+
popScope();
|
|
209
|
+
return result;
|
|
210
|
+
};
|
|
211
|
+
};
|
|
212
|
+
}
|
|
@@ -0,0 +1,133 @@
|
|
|
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.destructuringTransformer = destructuringTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
/**
|
|
9
|
+
* Трансформер для преобразования деструктуризации объектов и массивов.
|
|
10
|
+
*
|
|
11
|
+
* @example
|
|
12
|
+
* // Вход (объект):
|
|
13
|
+
* const { a, b, ...rest } = obj;
|
|
14
|
+
*
|
|
15
|
+
* // Выход:
|
|
16
|
+
* const a = obj.a;
|
|
17
|
+
* const b = obj.b;
|
|
18
|
+
* const rest = bt.object_rest(obj, ["a", "b"]);
|
|
19
|
+
*
|
|
20
|
+
* @example
|
|
21
|
+
* // Вход (массив):
|
|
22
|
+
* const [x, y, ...rest] = arr;
|
|
23
|
+
*
|
|
24
|
+
* // Выход:
|
|
25
|
+
* const _arr = ArrayDirect(arr);
|
|
26
|
+
* const x = _arr[0];
|
|
27
|
+
* const y = _arr[1];
|
|
28
|
+
* const rest = bt.array_rest(_arr, 2);
|
|
29
|
+
*
|
|
30
|
+
* @returns TypeScript transformer factory
|
|
31
|
+
*/
|
|
32
|
+
function destructuringTransformer() {
|
|
33
|
+
return (context) => {
|
|
34
|
+
let uidCounter = 0;
|
|
35
|
+
/**
|
|
36
|
+
* Генерирует уникальный идентификатор
|
|
37
|
+
*/
|
|
38
|
+
const generateUid = (prefix) => {
|
|
39
|
+
return typescript_1.default.factory.createIdentifier(`_${prefix}${uidCounter++}`);
|
|
40
|
+
};
|
|
41
|
+
return (sourceFile) => {
|
|
42
|
+
const visitor = (node) => {
|
|
43
|
+
// Обрабатываем объявления переменных
|
|
44
|
+
if (typescript_1.default.isVariableStatement(node)) {
|
|
45
|
+
const declarations = node.declarationList.declarations;
|
|
46
|
+
const newStatements = [];
|
|
47
|
+
let hasDestructuring = false;
|
|
48
|
+
for (const declarator of declarations) {
|
|
49
|
+
// Обрабатываем деструктуризацию объекта
|
|
50
|
+
if (typescript_1.default.isObjectBindingPattern(declarator.name) && declarator.initializer) {
|
|
51
|
+
hasDestructuring = true;
|
|
52
|
+
const init = typescript_1.default.visitNode(declarator.initializer, visitor);
|
|
53
|
+
const excludedKeys = [];
|
|
54
|
+
for (const element of declarator.name.elements) {
|
|
55
|
+
if (typescript_1.default.isBindingElement(element)) {
|
|
56
|
+
if (element.dotDotDotToken) {
|
|
57
|
+
// Rest element: ...rest
|
|
58
|
+
const restName = element.name;
|
|
59
|
+
const restCall = typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createPropertyAccessExpression(typescript_1.default.factory.createIdentifier('bt'), 'object_rest'), undefined, [
|
|
60
|
+
init,
|
|
61
|
+
typescript_1.default.factory.createArrayLiteralExpression(excludedKeys.map(k => typescript_1.default.factory.createStringLiteral(k)))
|
|
62
|
+
]);
|
|
63
|
+
newStatements.push(createVarStatement(restName.text, restCall));
|
|
64
|
+
}
|
|
65
|
+
else {
|
|
66
|
+
// Regular property: { a } or { a: b }
|
|
67
|
+
const propertyName = element.propertyName
|
|
68
|
+
? element.propertyName.text
|
|
69
|
+
: element.name.text;
|
|
70
|
+
const variableName = element.name.text;
|
|
71
|
+
excludedKeys.push(propertyName);
|
|
72
|
+
const memberAccess = typescript_1.default.factory.createPropertyAccessExpression(init, propertyName);
|
|
73
|
+
newStatements.push(createVarStatement(variableName, memberAccess));
|
|
74
|
+
}
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
// Обрабатываем деструктуризацию массива
|
|
79
|
+
else if (typescript_1.default.isArrayBindingPattern(declarator.name) && declarator.initializer) {
|
|
80
|
+
hasDestructuring = true;
|
|
81
|
+
const init = typescript_1.default.visitNode(declarator.initializer, visitor);
|
|
82
|
+
// Создаём вспомогательную переменную: var _arr = ArrayDirect(init)
|
|
83
|
+
const auxVar = generateUid('arr');
|
|
84
|
+
const auxCall = typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createIdentifier('ArrayDirect'), undefined, [init]);
|
|
85
|
+
newStatements.push(createVarStatement(auxVar.text, auxCall));
|
|
86
|
+
// Обрабатываем элементы массива
|
|
87
|
+
let index = 0;
|
|
88
|
+
for (const element of declarator.name.elements) {
|
|
89
|
+
if (typescript_1.default.isOmittedExpression(element)) {
|
|
90
|
+
// Пропущенный элемент [, , x]
|
|
91
|
+
index++;
|
|
92
|
+
continue;
|
|
93
|
+
}
|
|
94
|
+
if (typescript_1.default.isBindingElement(element)) {
|
|
95
|
+
if (element.dotDotDotToken) {
|
|
96
|
+
// Rest element: ...rest
|
|
97
|
+
const restName = element.name;
|
|
98
|
+
const restCall = typescript_1.default.factory.createCallExpression(typescript_1.default.factory.createPropertyAccessExpression(typescript_1.default.factory.createIdentifier('bt'), 'array_rest'), undefined, [auxVar, typescript_1.default.factory.createNumericLiteral(index)]);
|
|
99
|
+
newStatements.push(createVarStatement(restName.text, restCall));
|
|
100
|
+
}
|
|
101
|
+
else {
|
|
102
|
+
// Regular element: [a, b]
|
|
103
|
+
const variableName = element.name.text;
|
|
104
|
+
const elementAccess = typescript_1.default.factory.createElementAccessExpression(auxVar, typescript_1.default.factory.createNumericLiteral(index));
|
|
105
|
+
newStatements.push(createVarStatement(variableName, elementAccess));
|
|
106
|
+
index++;
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
// Обычные объявления - оставляем как есть
|
|
112
|
+
else {
|
|
113
|
+
const visitedDeclarator = typescript_1.default.visitNode(declarator, visitor);
|
|
114
|
+
newStatements.push(typescript_1.default.factory.createVariableStatement(undefined, typescript_1.default.factory.createVariableDeclarationList([visitedDeclarator], typescript_1.default.NodeFlags.None)));
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
if (hasDestructuring) {
|
|
118
|
+
return newStatements;
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
122
|
+
};
|
|
123
|
+
return typescript_1.default.visitNode(sourceFile, visitor);
|
|
124
|
+
};
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Создаёт var statement: var name = initializer;
|
|
129
|
+
*/
|
|
130
|
+
function createVarStatement(name, initializer) {
|
|
131
|
+
return typescript_1.default.factory.createVariableStatement(undefined, typescript_1.default.factory.createVariableDeclarationList([typescript_1.default.factory.createVariableDeclaration(name, undefined, undefined, initializer)], typescript_1.default.NodeFlags.None // var
|
|
132
|
+
));
|
|
133
|
+
}
|
|
@@ -0,0 +1,79 @@
|
|
|
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.dirnameTransformer = dirnameTransformer;
|
|
7
|
+
const typescript_1 = __importDefault(require("typescript"));
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
function dirnameTransformer() {
|
|
10
|
+
return (context) => (sourceFile) => {
|
|
11
|
+
const factory = context.factory;
|
|
12
|
+
const isExecObj = (0, utils_1.isExecutableObject)(sourceFile);
|
|
13
|
+
const execObjKey = isExecObj ? (0, utils_1.getExecutableObjectKey)(sourceFile) : undefined;
|
|
14
|
+
// console.log(`dirnameTransformer: isExecObj=${isExecObj}, execObjKey=${execObjKey}`);
|
|
15
|
+
let hasAbsoluteUrlCalls = true;
|
|
16
|
+
// Рекурсивная функция для обхода и трансформации дерева
|
|
17
|
+
const visitor = (node) => {
|
|
18
|
+
// Проверяем, является ли узел вызовом функции AbsoluteUrl
|
|
19
|
+
if (typescript_1.default.isCallExpression(node) &&
|
|
20
|
+
typescript_1.default.isIdentifier(node.expression) &&
|
|
21
|
+
node.expression.text === 'AbsoluteUrl') {
|
|
22
|
+
hasAbsoluteUrlCalls = true;
|
|
23
|
+
// Заменяем на __AbsoluteUrl
|
|
24
|
+
const args = node.arguments;
|
|
25
|
+
const newArgs = [];
|
|
26
|
+
if (args.length >= 1) {
|
|
27
|
+
newArgs.push(args[0]); // url
|
|
28
|
+
}
|
|
29
|
+
if (args.length >= 2) {
|
|
30
|
+
newArgs.push(args[1]); // baseUrl
|
|
31
|
+
}
|
|
32
|
+
else {
|
|
33
|
+
// Если baseUrl не указан, добавляем undefined
|
|
34
|
+
newArgs.push(factory.createIdentifier('undefined'));
|
|
35
|
+
}
|
|
36
|
+
return factory.updateCallExpression(node, factory.createIdentifier('__AbsoluteUrl'), node.typeArguments, newArgs);
|
|
37
|
+
}
|
|
38
|
+
return typescript_1.default.visitEachChild(node, visitor, context);
|
|
39
|
+
};
|
|
40
|
+
// Обходим файл
|
|
41
|
+
const transformedSourceFile = typescript_1.default.visitNode(sourceFile, visitor);
|
|
42
|
+
// Если были вызовы AbsoluteUrl, добавляем функцию __AbsoluteUrl
|
|
43
|
+
if (hasAbsoluteUrlCalls) {
|
|
44
|
+
let functionBody;
|
|
45
|
+
if (isExecObj && execObjKey !== undefined) {
|
|
46
|
+
// Для executable object: если baseUrl === undefined, используем UrlAppendPath(UrlParent(bt.getFileUrl(KEY)), url)
|
|
47
|
+
functionBody = factory.createReturnStatement(factory.createConditionalExpression(factory.createBinaryExpression(factory.createIdentifier('baseUrl'), factory.createToken(typescript_1.default.SyntaxKind.EqualsEqualsEqualsToken), factory.createIdentifier('undefined')), factory.createToken(typescript_1.default.SyntaxKind.QuestionToken), factory.createCallExpression(factory.createIdentifier('UrlAppendPath'), undefined, [
|
|
48
|
+
factory.createCallExpression(factory.createIdentifier('UrlParent'), undefined, [
|
|
49
|
+
(0, utils_1.markUntouchable)(factory.createCallExpression(factory.createPropertyAccessExpression(factory.createIdentifier('bt'), 'getFileUrl'), undefined, [factory.createStringLiteral(execObjKey)]))
|
|
50
|
+
]),
|
|
51
|
+
factory.createIdentifier('url')
|
|
52
|
+
]), factory.createToken(typescript_1.default.SyntaxKind.ColonToken), factory.createCallExpression(factory.createIdentifier('AbsoluteUrl'), undefined, [
|
|
53
|
+
factory.createIdentifier('url'),
|
|
54
|
+
factory.createIdentifier('baseUrl')
|
|
55
|
+
])));
|
|
56
|
+
}
|
|
57
|
+
else {
|
|
58
|
+
// Для обычных файлов
|
|
59
|
+
functionBody = factory.createReturnStatement(factory.createConditionalExpression(factory.createBinaryExpression(factory.createIdentifier('baseUrl'), factory.createToken(typescript_1.default.SyntaxKind.EqualsEqualsEqualsToken), factory.createIdentifier('undefined')), factory.createToken(typescript_1.default.SyntaxKind.QuestionToken), factory.createCallExpression(factory.createIdentifier('AbsoluteUrl'), undefined, [factory.createIdentifier('url')]), factory.createToken(typescript_1.default.SyntaxKind.ColonToken), factory.createCallExpression(factory.createIdentifier('AbsoluteUrl'), undefined, [
|
|
60
|
+
factory.createIdentifier('url'),
|
|
61
|
+
factory.createIdentifier('baseUrl')
|
|
62
|
+
])));
|
|
63
|
+
}
|
|
64
|
+
// Создаем функцию __AbsoluteUrl
|
|
65
|
+
const absoluteUrlFunction = factory.createFunctionDeclaration(undefined, // modifiers
|
|
66
|
+
undefined, // asteriskToken
|
|
67
|
+
'__AbsoluteUrl', undefined, // typeParameters
|
|
68
|
+
[
|
|
69
|
+
factory.createParameterDeclaration(undefined, undefined, 'url', undefined, undefined, undefined),
|
|
70
|
+
factory.createParameterDeclaration(undefined, undefined, 'baseUrl', factory.createToken(typescript_1.default.SyntaxKind.QuestionToken), undefined, undefined)
|
|
71
|
+
], undefined, // type
|
|
72
|
+
factory.createBlock([functionBody], true));
|
|
73
|
+
// Добавляем функцию в начало файла
|
|
74
|
+
const statements = [absoluteUrlFunction, ...transformedSourceFile.statements];
|
|
75
|
+
return (0, utils_1.preserveSymbolsFrom)(factory.updateSourceFile(transformedSourceFile, statements), sourceFile);
|
|
76
|
+
}
|
|
77
|
+
return (0, utils_1.preserveSymbolsFrom)(transformedSourceFile, sourceFile);
|
|
78
|
+
};
|
|
79
|
+
}
|