ts-const-value-transformer 0.9.0 → 0.10.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/CHANGELOG.md +10 -0
- package/README.md +33 -0
- package/dist/TsProxy.d.mts +105 -0
- package/dist/TsProxy.mjs +1 -0
- package/dist/createPortalTransformer.mjs +2 -1
- package/dist/createPortalTransformerWithTsLs.d.mts +59 -0
- package/dist/createPortalTransformerWithTsLs.mjs +159 -0
- package/dist/createTransformer.mjs +2 -1
- package/dist/getCustomTransformers.d.mts +1 -5
- package/dist/index.d.mts +4 -2
- package/dist/index.mjs +4 -2
- package/dist/lsp/SyncLspClient.d.mts +25 -0
- package/dist/lsp/SyncLspClient.mjs +234 -0
- package/dist/lsp/TsLspClient.d.mts +29 -0
- package/dist/lsp/TsLspClient.mjs +271 -0
- package/dist/lsp/lspTransformerUtil.d.mts +1 -0
- package/dist/lsp/lspTransformerUtil.mjs +536 -0
- package/dist/lspTransformer.d.mts +9 -0
- package/dist/lspTransformer.mjs +226 -0
- package/dist/transform.d.mts +8 -5
- package/dist/transform.mjs +105 -298
- package/dist/tscTransformer.d.mts +8 -0
- package/dist/tscTransformer.mjs +377 -0
- package/dist/version.d.mts +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +16 -3
package/dist/transform.mjs
CHANGED
|
@@ -1,10 +1,8 @@
|
|
|
1
1
|
import * as sourceMap from 'source-map';
|
|
2
|
-
import * as tsNamespace from 'typescript';
|
|
3
2
|
const SYMBOL_ORIGINAL_NODE_DATA = Symbol('originalNodeData');
|
|
4
3
|
function assignDefaultValues(options = {}) {
|
|
5
4
|
return {
|
|
6
5
|
// avoid using spread syntax to override `undefined` (not missing) values
|
|
7
|
-
ts: options.ts ?? tsNamespace,
|
|
8
6
|
hoistProperty: options.hoistProperty ?? true,
|
|
9
7
|
hoistEnumValues: options.hoistEnumValues ?? true,
|
|
10
8
|
hoistExternalValues: options.hoistExternalValues ?? true,
|
|
@@ -14,6 +12,7 @@ function assignDefaultValues(options = {}) {
|
|
|
14
12
|
unsafeHoistWritableValues: options.unsafeHoistWritableValues ?? false,
|
|
15
13
|
useUndefinedSymbolForUndefinedValue: options.useUndefinedSymbolForUndefinedValue ?? false,
|
|
16
14
|
hoistUndefinedSymbol: options.hoistUndefinedSymbol ?? true,
|
|
15
|
+
hoistConstTemplateLiteral: options.hoistConstTemplateLiteral ?? false,
|
|
17
16
|
externalNames: options.externalNames ?? [],
|
|
18
17
|
ignoreFiles: options.ignoreFiles ?? [],
|
|
19
18
|
};
|
|
@@ -39,27 +38,29 @@ export function getIgnoreFilesFunction(ignoreFiles) {
|
|
|
39
38
|
};
|
|
40
39
|
}
|
|
41
40
|
////////////////////////////////////////////////////////////////////////////////
|
|
42
|
-
export function
|
|
41
|
+
export function transformSourceWithProxy(sourceFile, proxy, context, options) {
|
|
43
42
|
const requiredOptions = assignDefaultValues(options);
|
|
44
|
-
|
|
45
|
-
|
|
43
|
+
return transformSourceWithProxyImpl(sourceFile, proxy, context, requiredOptions);
|
|
44
|
+
}
|
|
45
|
+
// @internal
|
|
46
|
+
export function transformSourceWithProxyImpl(sourceFile, proxy, context, requiredOptions) {
|
|
47
|
+
return proxy.visitEachChild(sourceFile, (node) => visitNodeChildren(node, sourceFile, sourceFile, proxy, requiredOptions, context, (node) => {
|
|
46
48
|
// skip statements which would not have 'value' expressions
|
|
47
|
-
if (
|
|
48
|
-
|
|
49
|
+
if (proxy.isInterfaceDeclaration(node) ||
|
|
50
|
+
proxy.isTypeAliasDeclaration(node) ||
|
|
49
51
|
// Identifies in import clause should not be parsed
|
|
50
|
-
|
|
51
|
-
|
|
52
|
+
proxy.isImportDeclaration(node) ||
|
|
53
|
+
proxy.isTypeOnlyExportDeclaration(node)) {
|
|
52
54
|
return false;
|
|
53
55
|
}
|
|
54
56
|
return true;
|
|
55
57
|
}), context);
|
|
56
58
|
}
|
|
57
|
-
function visitNodeChildren(node, parent, sourceFile,
|
|
58
|
-
const ts = options.ts;
|
|
59
|
+
function visitNodeChildren(node, parent, sourceFile, proxy, options, context, fnVisit, visitContext, fnVisitBeforeReplace, fnVisitBeforeChild, fnVisitAfterChild, fnReplace) {
|
|
59
60
|
if (fnVisitBeforeReplace) {
|
|
60
61
|
fnVisitBeforeReplace(node, parent, visitContext);
|
|
61
62
|
}
|
|
62
|
-
const newNode = visitNodeAndReplaceIfNeeded(node, parent, sourceFile,
|
|
63
|
+
const newNode = visitNodeAndReplaceIfNeeded(node, parent, sourceFile, proxy, options, context, visitContext, fnReplace ?? 'create');
|
|
63
64
|
if (newNode == null) {
|
|
64
65
|
return node;
|
|
65
66
|
}
|
|
@@ -72,136 +73,136 @@ function visitNodeChildren(node, parent, sourceFile, program, options, context,
|
|
|
72
73
|
const childVisitContext = fnVisitBeforeChild
|
|
73
74
|
? fnVisitBeforeChild(node, parent, visitContext)
|
|
74
75
|
: visitContext;
|
|
75
|
-
const r =
|
|
76
|
+
const r = proxy.visitEachChild(node, (nodeChild) => visitNodeChildren(nodeChild, node, sourceFile, proxy, options, context, fnVisit, childVisitContext, fnVisitBeforeReplace, fnVisitBeforeChild, fnVisitAfterChild, fnReplace), context);
|
|
76
77
|
if (fnVisitAfterChild) {
|
|
77
78
|
fnVisitAfterChild(node, parent, childVisitContext);
|
|
78
79
|
}
|
|
79
80
|
return r;
|
|
80
81
|
}
|
|
81
|
-
function visitNodeAndReplaceIfNeeded(node, parent, sourceFile,
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
if (!ts.isExpression(node) ||
|
|
82
|
+
function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, proxy, options, context, visitContext, replaceOption) {
|
|
83
|
+
if (proxy.isCallLikeExpression(node)) {
|
|
84
|
+
if (!proxy.isExpression(node) ||
|
|
85
85
|
(!options.unsafeHoistFunctionCall &&
|
|
86
86
|
(!options.hoistPureFunctionCall ||
|
|
87
|
-
!hasPureAnnotation(node, sourceFile
|
|
87
|
+
!proxy.hasPureAnnotation(node, sourceFile)))) {
|
|
88
88
|
return node;
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
|
-
else if (
|
|
92
|
-
if (!
|
|
93
|
-
((!
|
|
91
|
+
else if (proxy.isIdentifier(node)) {
|
|
92
|
+
if (!proxy.isComputedPropertyName(parent) &&
|
|
93
|
+
((!proxy.isExpression(parent) &&
|
|
94
94
|
(!('initializer' in parent) || node !== parent.initializer)) ||
|
|
95
|
-
(
|
|
95
|
+
(proxy.isPropertyAccessExpression(parent) && node === parent.name))) {
|
|
96
96
|
return node;
|
|
97
97
|
}
|
|
98
|
-
if (!options.hoistEnumValues && isEnumIdentifier(node,
|
|
98
|
+
if (!options.hoistEnumValues && proxy.isEnumIdentifier(node, sourceFile)) {
|
|
99
99
|
return node;
|
|
100
100
|
}
|
|
101
101
|
if (!options.hoistUndefinedSymbol &&
|
|
102
|
-
isUndefinedIdentifier(node, parent,
|
|
102
|
+
proxy.isUndefinedIdentifier(node, parent, sourceFile)) {
|
|
103
103
|
return node;
|
|
104
104
|
}
|
|
105
105
|
}
|
|
106
|
-
else if (
|
|
107
|
-
|
|
108
|
-
if (!isHoistablePropertyAccess(node,
|
|
106
|
+
else if (proxy.isPropertyAccessExpression(node) ||
|
|
107
|
+
proxy.isElementAccessExpression(node)) {
|
|
108
|
+
if (!proxy.isHoistablePropertyAccess(node, sourceFile)) {
|
|
109
109
|
return node;
|
|
110
110
|
}
|
|
111
|
-
if ((!options.hoistProperty && !isEnumAccess(node,
|
|
111
|
+
if ((!options.hoistProperty && !proxy.isEnumAccess(node, sourceFile)) ||
|
|
112
112
|
(!options.hoistEnumValues &&
|
|
113
|
-
(isEnumAccess(node,
|
|
114
|
-
(
|
|
113
|
+
(proxy.isEnumAccess(node, sourceFile) ||
|
|
114
|
+
(proxy.isIdentifier(node) &&
|
|
115
|
+
proxy.isEnumIdentifier(node, sourceFile))))) {
|
|
115
116
|
return node;
|
|
116
117
|
}
|
|
117
118
|
}
|
|
118
|
-
else if (
|
|
119
|
+
else if (proxy.isAsExpression(node)) {
|
|
119
120
|
if (!options.unsafeHoistAsExpresion) {
|
|
120
121
|
return node;
|
|
121
122
|
}
|
|
122
123
|
}
|
|
124
|
+
else if (proxy.isTemplateExpression(node)) {
|
|
125
|
+
if (!options.hoistConstTemplateLiteral) {
|
|
126
|
+
return node;
|
|
127
|
+
}
|
|
128
|
+
}
|
|
123
129
|
else {
|
|
124
130
|
return node;
|
|
125
131
|
}
|
|
126
132
|
if (!options.hoistExternalValues &&
|
|
127
|
-
isExternalReference(node,
|
|
133
|
+
proxy.isExternalReference(node, options.externalNames, sourceFile)) {
|
|
128
134
|
return node;
|
|
129
135
|
}
|
|
130
|
-
if (!options.unsafeHoistAsExpresion &&
|
|
136
|
+
if (!options.unsafeHoistAsExpresion &&
|
|
137
|
+
hasAsExpression(node, proxy, context)) {
|
|
131
138
|
return node;
|
|
132
139
|
}
|
|
133
140
|
if (!options.unsafeHoistWritableValues) {
|
|
134
|
-
const r = isReadonlyExpression(node,
|
|
141
|
+
const r = proxy.isReadonlyExpression(node, sourceFile);
|
|
135
142
|
if (r === false) {
|
|
136
143
|
return node;
|
|
137
144
|
}
|
|
138
145
|
}
|
|
139
146
|
try {
|
|
140
|
-
const
|
|
141
|
-
const type = typeChecker.getTypeAtLocation(node);
|
|
142
|
-
const flags = type.getFlags();
|
|
147
|
+
const type = proxy.getTypeAtLocation(node, sourceFile);
|
|
143
148
|
let newNode;
|
|
144
|
-
if (type
|
|
149
|
+
if (!type) {
|
|
145
150
|
return node;
|
|
146
151
|
}
|
|
147
152
|
let newSource;
|
|
148
|
-
if (
|
|
149
|
-
if (replaceOption === 'create') {
|
|
150
|
-
newNode =
|
|
153
|
+
if (proxy.isStringLiteral(type)) {
|
|
154
|
+
if (replaceOption === 'create' && proxy.factory) {
|
|
155
|
+
newNode = proxy.factory.createStringLiteral(type.value);
|
|
151
156
|
}
|
|
152
|
-
newSource =
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
? `"${ts.escapeNonAsciiString(type.value, 'CharacterCodes' in ts
|
|
156
|
-
? ts.CharacterCodes.doubleQuote
|
|
157
|
-
: 34 /* doubleQuote */)}"`
|
|
158
|
-
: JSON.stringify(type.value);
|
|
159
|
-
}
|
|
160
|
-
else if (type.isNumberLiteral()) {
|
|
157
|
+
newSource = proxy.makeStringLiteralSource(type.value);
|
|
158
|
+
}
|
|
159
|
+
else if (proxy.isNumberLiteral(type)) {
|
|
161
160
|
if (type.value < 0) {
|
|
162
|
-
if (replaceOption === 'create') {
|
|
163
|
-
newNode =
|
|
161
|
+
if (replaceOption === 'create' && proxy.factory) {
|
|
162
|
+
newNode = proxy.factory.createParenthesizedExpression(proxy.factory.createExpressionWithMinusToken(proxy.factory.createNumericLiteral(-type.value)));
|
|
164
163
|
}
|
|
165
164
|
newSource = `(-${-type.value})`;
|
|
166
165
|
}
|
|
167
166
|
else {
|
|
168
|
-
if (replaceOption === 'create') {
|
|
169
|
-
newNode =
|
|
167
|
+
if (replaceOption === 'create' && proxy.factory) {
|
|
168
|
+
newNode = proxy.factory.createNumericLiteral(type.value);
|
|
170
169
|
}
|
|
171
170
|
newSource = `${type.value}`;
|
|
172
171
|
}
|
|
173
172
|
}
|
|
174
|
-
else if (
|
|
175
|
-
const text =
|
|
176
|
-
if (replaceOption === 'create') {
|
|
177
|
-
newNode =
|
|
173
|
+
else if (proxy.isBigIntLiteral(type)) {
|
|
174
|
+
const text = proxy.typeToString(type);
|
|
175
|
+
if (replaceOption === 'create' && proxy.factory) {
|
|
176
|
+
newNode = proxy.factory.createBigIntLiteral(text);
|
|
178
177
|
}
|
|
179
178
|
newSource = text;
|
|
180
179
|
}
|
|
181
|
-
else if (
|
|
182
|
-
const text =
|
|
183
|
-
if (replaceOption === 'create') {
|
|
180
|
+
else if (proxy.isBooleanLiteral(type)) {
|
|
181
|
+
const text = proxy.typeToString(type);
|
|
182
|
+
if (replaceOption === 'create' && proxy.factory) {
|
|
184
183
|
newNode =
|
|
185
|
-
text === 'true'
|
|
184
|
+
text === 'true'
|
|
185
|
+
? proxy.factory.createTrue()
|
|
186
|
+
: proxy.factory.createFalse();
|
|
186
187
|
}
|
|
187
188
|
newSource = text;
|
|
188
189
|
}
|
|
189
|
-
else if (
|
|
190
|
-
if (replaceOption === 'create') {
|
|
191
|
-
newNode =
|
|
190
|
+
else if (proxy.isNullType(type)) {
|
|
191
|
+
if (replaceOption === 'create' && proxy.factory) {
|
|
192
|
+
newNode = proxy.factory.createNull();
|
|
192
193
|
}
|
|
193
194
|
newSource = 'null';
|
|
194
195
|
}
|
|
195
|
-
else if (
|
|
196
|
+
else if (proxy.isUndefinedType(type)) {
|
|
196
197
|
if (options.useUndefinedSymbolForUndefinedValue) {
|
|
197
|
-
if (replaceOption === 'create') {
|
|
198
|
-
newNode =
|
|
198
|
+
if (replaceOption === 'create' && proxy.factory) {
|
|
199
|
+
newNode = proxy.factory.createIdentifier('undefined');
|
|
199
200
|
}
|
|
200
201
|
newSource = 'undefined';
|
|
201
202
|
}
|
|
202
203
|
else {
|
|
203
|
-
if (replaceOption === 'create') {
|
|
204
|
-
newNode =
|
|
204
|
+
if (replaceOption === 'create' && proxy.factory) {
|
|
205
|
+
newNode = proxy.factory.createParenthesizedExpression(proxy.factory.createVoidZero());
|
|
205
206
|
}
|
|
206
207
|
newSource = '(void 0)';
|
|
207
208
|
}
|
|
@@ -209,20 +210,20 @@ function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options,
|
|
|
209
210
|
else {
|
|
210
211
|
return node;
|
|
211
212
|
}
|
|
212
|
-
const originalSource =
|
|
213
|
+
const originalSource = proxy.getNodeText(node, sourceFile);
|
|
213
214
|
const comment = ` ${originalSource.replace(/\/\*/g, ' *').replace(/\*\//g, '* ')} `;
|
|
214
215
|
let result = newNode
|
|
215
|
-
?
|
|
216
|
+
? proxy.appendMultiLineComment(newNode, comment)
|
|
216
217
|
: undefined;
|
|
217
218
|
newSource = `${newSource} /*${comment}*/`;
|
|
218
219
|
if (/[\r\n]/m.test(originalSource)) {
|
|
219
|
-
if (result) {
|
|
220
|
-
result =
|
|
220
|
+
if (result && proxy.factory) {
|
|
221
|
+
result = proxy.factory.createParenthesizedExpression(result);
|
|
221
222
|
}
|
|
222
223
|
newSource = `(${newSource})`;
|
|
223
224
|
}
|
|
224
225
|
if (result) {
|
|
225
|
-
|
|
226
|
+
proxy.setTextRange(result, node);
|
|
226
227
|
result[SYMBOL_ORIGINAL_NODE_DATA] = [
|
|
227
228
|
originalSource,
|
|
228
229
|
newSource,
|
|
@@ -239,226 +240,33 @@ function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options,
|
|
|
239
240
|
return node;
|
|
240
241
|
}
|
|
241
242
|
}
|
|
242
|
-
function
|
|
243
|
-
const ts = tsInstance;
|
|
244
|
-
const typeChecker = program.getTypeChecker();
|
|
245
|
-
const type = typeChecker.getTypeAtLocation(node);
|
|
246
|
-
return (type.getFlags() & ts.TypeFlags.EnumLiteral) !== 0;
|
|
247
|
-
}
|
|
248
|
-
function isEnumIdentifier(node, program, tsInstance) {
|
|
249
|
-
const ts = tsInstance;
|
|
250
|
-
const typeChecker = program.getTypeChecker();
|
|
251
|
-
const type = typeChecker.getTypeAtLocation(node);
|
|
252
|
-
return (type.getFlags() & ts.TypeFlags.EnumLiteral) !== 0;
|
|
253
|
-
}
|
|
254
|
-
function isExternalReference(node, program, externalNames, tsInstance) {
|
|
255
|
-
const ts = tsInstance;
|
|
256
|
-
const typeChecker = program.getTypeChecker();
|
|
257
|
-
const nodeSym = typeChecker.getSymbolAtLocation(node);
|
|
258
|
-
let nodeFrom = nodeSym?.getDeclarations()?.[0];
|
|
259
|
-
while (nodeFrom) {
|
|
260
|
-
const sourceFileName = nodeFrom.getSourceFile();
|
|
261
|
-
if (externalNames.length === 0) {
|
|
262
|
-
if (/[\\/]node_modules[\\/]/.test(sourceFileName.fileName)) {
|
|
263
|
-
return true;
|
|
264
|
-
}
|
|
265
|
-
}
|
|
266
|
-
else {
|
|
267
|
-
if (externalNames.some((part) => {
|
|
268
|
-
if (typeof part === 'string') {
|
|
269
|
-
return sourceFileName.fileName.replace(/\\/g, '/').includes(part);
|
|
270
|
-
}
|
|
271
|
-
else {
|
|
272
|
-
return part.test(sourceFileName.fileName);
|
|
273
|
-
}
|
|
274
|
-
})) {
|
|
275
|
-
return true;
|
|
276
|
-
}
|
|
277
|
-
}
|
|
278
|
-
// Walk into the 'import' variables
|
|
279
|
-
if (!ts.isImportSpecifier(nodeFrom)) {
|
|
280
|
-
break;
|
|
281
|
-
}
|
|
282
|
-
const baseName = nodeFrom.propertyName ?? nodeFrom.name;
|
|
283
|
-
const baseSym = typeChecker.getSymbolAtLocation(baseName);
|
|
284
|
-
// We must follow 'aliased' symbol for parsing the symbol which name is not changed from the exported symbol name
|
|
285
|
-
const exportedSym = baseSym && baseSym.getFlags() & ts.SymbolFlags.Alias
|
|
286
|
-
? typeChecker.getAliasedSymbol(baseSym)
|
|
287
|
-
: baseSym;
|
|
288
|
-
nodeFrom = exportedSym?.getDeclarations()?.[0];
|
|
289
|
-
}
|
|
290
|
-
const type = typeChecker.getTypeAtLocation(node);
|
|
291
|
-
const sym = type.getSymbol();
|
|
292
|
-
if (!sym) {
|
|
293
|
-
return false;
|
|
294
|
-
}
|
|
295
|
-
const def = sym.getDeclarations()?.[0];
|
|
296
|
-
if (!def) {
|
|
297
|
-
return false;
|
|
298
|
-
}
|
|
299
|
-
const typeDefinitionSource = def.getSourceFile();
|
|
300
|
-
if (program.isSourceFileFromExternalLibrary(typeDefinitionSource)) {
|
|
301
|
-
return true;
|
|
302
|
-
}
|
|
303
|
-
return false;
|
|
304
|
-
}
|
|
305
|
-
function hasAsExpression(node, tsInstance, context) {
|
|
306
|
-
const ts = tsInstance;
|
|
243
|
+
function hasAsExpression(node, proxy, context) {
|
|
307
244
|
// including 'as const'
|
|
308
|
-
if (
|
|
245
|
+
if (proxy.isAsExpression(node)) {
|
|
309
246
|
return true;
|
|
310
247
|
}
|
|
311
248
|
let found = false;
|
|
312
|
-
|
|
249
|
+
proxy.visitEachChild(node, (node) => {
|
|
313
250
|
if (!found) {
|
|
314
|
-
found = hasAsExpression(node,
|
|
251
|
+
found = hasAsExpression(node, proxy, context);
|
|
315
252
|
}
|
|
316
253
|
return node;
|
|
317
254
|
}, context);
|
|
318
255
|
return found;
|
|
319
256
|
}
|
|
320
|
-
function hasPureAnnotation(node, sourceFile, tsInstance) {
|
|
321
|
-
const ts = tsInstance;
|
|
322
|
-
const fullText = node.getFullText(sourceFile);
|
|
323
|
-
const ranges = ts.getLeadingCommentRanges(fullText, 0) ?? [];
|
|
324
|
-
for (const range of ranges) {
|
|
325
|
-
if (range.kind !== ts.SyntaxKind.MultiLineCommentTrivia) {
|
|
326
|
-
continue;
|
|
327
|
-
}
|
|
328
|
-
const text = fullText.slice(range.pos + 2, range.end - 2).trim();
|
|
329
|
-
if ((text[0] === '@' || text[0] === '#') && text.slice(1) === '__PURE__') {
|
|
330
|
-
return true;
|
|
331
|
-
}
|
|
332
|
-
}
|
|
333
|
-
return false;
|
|
334
|
-
}
|
|
335
|
-
function getNameFromElementAccessExpression(node, typeChecker) {
|
|
336
|
-
const type = typeChecker.getTypeAtLocation(node.argumentExpression);
|
|
337
|
-
if (type.isStringLiteral() || type.isNumberLiteral()) {
|
|
338
|
-
return `${type.value}`;
|
|
339
|
-
}
|
|
340
|
-
return null;
|
|
341
|
-
}
|
|
342
|
-
function isReadonlyPropertyAccess(a, typeChecker, tsInstance) {
|
|
343
|
-
const ts = tsInstance;
|
|
344
|
-
const type = typeChecker.getTypeAtLocation(a.expression);
|
|
345
|
-
const memberName = ts.isPropertyAccessExpression(a)
|
|
346
|
-
? a.name.getText()
|
|
347
|
-
: getNameFromElementAccessExpression(a, typeChecker);
|
|
348
|
-
if (memberName == null) {
|
|
349
|
-
return false;
|
|
350
|
-
}
|
|
351
|
-
if (type.getFlags() & ts.TypeFlags.Object) {
|
|
352
|
-
const prop = type.getProperty(memberName);
|
|
353
|
-
if (prop) {
|
|
354
|
-
// Use internal but exported function to improve memory performance
|
|
355
|
-
if ('getCheckFlags' in ts &&
|
|
356
|
-
'CheckFlags' in ts &&
|
|
357
|
-
ts.CheckFlags.Readonly != null) {
|
|
358
|
-
const checkFlags = ts.getCheckFlags(prop);
|
|
359
|
-
if (checkFlags & ts.CheckFlags.Readonly) {
|
|
360
|
-
return true;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
if ('getDeclarationModifierFlagsFromSymbol' in ts) {
|
|
364
|
-
const modifierFlags = ts.getDeclarationModifierFlagsFromSymbol(prop);
|
|
365
|
-
if (modifierFlags & ts.ModifierFlags.Readonly) {
|
|
366
|
-
return true;
|
|
367
|
-
}
|
|
368
|
-
}
|
|
369
|
-
if (prop.declarations && prop.declarations.length > 0) {
|
|
370
|
-
const decl = prop.declarations[0];
|
|
371
|
-
if (ts.isPropertySignature(decl) &&
|
|
372
|
-
decl.modifiers?.some((m) => m.kind === ts.SyntaxKind.ReadonlyKeyword)) {
|
|
373
|
-
return true;
|
|
374
|
-
}
|
|
375
|
-
if (ts.isVariableDeclaration(decl) &&
|
|
376
|
-
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
377
|
-
decl.parent &&
|
|
378
|
-
ts.isVariableDeclarationList(decl.parent) &&
|
|
379
|
-
decl.parent.flags & ts.NodeFlags.Const) {
|
|
380
|
-
return true;
|
|
381
|
-
}
|
|
382
|
-
}
|
|
383
|
-
}
|
|
384
|
-
}
|
|
385
|
-
return false;
|
|
386
|
-
}
|
|
387
|
-
function isReadonlyExpression(node, program, tsInstance) {
|
|
388
|
-
const ts = tsInstance;
|
|
389
|
-
const typeChecker = program.getTypeChecker();
|
|
390
|
-
if (ts.isIdentifier(node) &&
|
|
391
|
-
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
392
|
-
node.parent &&
|
|
393
|
-
!ts.isPropertyAccessExpression(node.parent)) {
|
|
394
|
-
const nodeSym = typeChecker.getSymbolAtLocation(node);
|
|
395
|
-
if (nodeSym?.valueDeclaration) {
|
|
396
|
-
if (ts.isVariableDeclarationList(nodeSym.valueDeclaration.parent)) {
|
|
397
|
-
if (nodeSym.valueDeclaration.parent.flags & ts.NodeFlags.Const) {
|
|
398
|
-
return true;
|
|
399
|
-
}
|
|
400
|
-
return false;
|
|
401
|
-
}
|
|
402
|
-
}
|
|
403
|
-
}
|
|
404
|
-
if (ts.isPropertyAccessExpression(node) ||
|
|
405
|
-
ts.isElementAccessExpression(node)) {
|
|
406
|
-
if (isEnumAccess(node, program, ts)) {
|
|
407
|
-
return true;
|
|
408
|
-
}
|
|
409
|
-
return isReadonlyPropertyAccess(node, typeChecker, ts);
|
|
410
|
-
}
|
|
411
|
-
return null;
|
|
412
|
-
}
|
|
413
|
-
function isHoistablePropertyAccess(a, program, tsInstance) {
|
|
414
|
-
const ts = tsInstance;
|
|
415
|
-
const typeChecker = program.getTypeChecker();
|
|
416
|
-
const type = typeChecker.getTypeAtLocation(a.expression);
|
|
417
|
-
const memberName = ts.isPropertyAccessExpression(a)
|
|
418
|
-
? a.name.getText()
|
|
419
|
-
: getNameFromElementAccessExpression(a, typeChecker);
|
|
420
|
-
if (memberName == null) {
|
|
421
|
-
return false;
|
|
422
|
-
}
|
|
423
|
-
if (type.getFlags() & ts.TypeFlags.Object) {
|
|
424
|
-
const prop = type.getProperty(memberName);
|
|
425
|
-
// If the property access uses indexed access, `prop` will be undefined
|
|
426
|
-
if (prop) {
|
|
427
|
-
return true;
|
|
428
|
-
}
|
|
429
|
-
}
|
|
430
|
-
return false;
|
|
431
|
-
}
|
|
432
|
-
function isUndefinedIdentifier(node, parent, program, tsInstance) {
|
|
433
|
-
if (tsInstance.isPropertyAccessExpression(parent) ||
|
|
434
|
-
tsInstance.isElementAccessExpression(parent)) {
|
|
435
|
-
return false;
|
|
436
|
-
}
|
|
437
|
-
const typeChecker = program.getTypeChecker();
|
|
438
|
-
const type = typeChecker.getTypeAtLocation(node);
|
|
439
|
-
const sym = typeChecker.getSymbolAtLocation(node);
|
|
440
|
-
if (!sym || sym.getEscapedName().toString() !== 'undefined') {
|
|
441
|
-
return false;
|
|
442
|
-
}
|
|
443
|
-
if (type.isUnionOrIntersection() ||
|
|
444
|
-
!(type.getFlags() & tsInstance.TypeFlags.Undefined)) {
|
|
445
|
-
return false;
|
|
446
|
-
}
|
|
447
|
-
return true;
|
|
448
|
-
}
|
|
449
257
|
////////////////////////////////////////////////////////////////////////////////
|
|
450
|
-
export function
|
|
451
|
-
return printSourceImpl(
|
|
258
|
+
export function printSourceWithProxy(sourceFile, proxy) {
|
|
259
|
+
return printSourceImpl(proxy, sourceFile)[0];
|
|
452
260
|
}
|
|
453
|
-
export function
|
|
261
|
+
export function printSourceWithMapWithProxy(sourceFile, originalSourceName, proxy, startOfSourceMap) {
|
|
454
262
|
const generator = new sourceMap.SourceMapGenerator(startOfSourceMap);
|
|
455
|
-
generator.setSourceContent(originalSourceName, sourceFile.
|
|
456
|
-
return printSourceImpl(
|
|
263
|
+
generator.setSourceContent(originalSourceName, sourceFile.text);
|
|
264
|
+
return printSourceImpl(proxy, sourceFile, originalSourceName, generator);
|
|
457
265
|
}
|
|
458
|
-
function positionToLineAndColumn(sourceFile, pos, generatedDiff) {
|
|
266
|
+
function positionToLineAndColumn(proxy, sourceFile, pos, generatedDiff) {
|
|
459
267
|
let line = 0;
|
|
460
268
|
let lastLinePos = 0;
|
|
461
|
-
for (const linePos of
|
|
269
|
+
for (const linePos of proxy.getLineStarts(sourceFile)) {
|
|
462
270
|
if (pos < linePos) {
|
|
463
271
|
break;
|
|
464
272
|
}
|
|
@@ -467,12 +275,11 @@ function positionToLineAndColumn(sourceFile, pos, generatedDiff) {
|
|
|
467
275
|
}
|
|
468
276
|
return { line, column: pos - lastLinePos + generatedDiff };
|
|
469
277
|
}
|
|
470
|
-
function printSourceImpl(
|
|
471
|
-
const
|
|
472
|
-
const r = printNode(ts, sourceFile.getFullText(), sourceFile, sourceFile, { pos: 0, diff: 0, lastLine: 0 }, originalSourceName, mapGenerator);
|
|
278
|
+
function printSourceImpl(proxy, sourceFile, originalSourceName, mapGenerator) {
|
|
279
|
+
const r = printNode(proxy, sourceFile.text, sourceFile, sourceFile, { pos: 0, diff: 0, lastLine: 0 }, originalSourceName, mapGenerator);
|
|
473
280
|
return [r, mapGenerator?.toJSON()];
|
|
474
281
|
}
|
|
475
|
-
function printNode(
|
|
282
|
+
function printNode(proxy, baseSource, sourceFile, node, posContext, originalSourceName, mapGenerator) {
|
|
476
283
|
const originalNodeData = node[SYMBOL_ORIGINAL_NODE_DATA];
|
|
477
284
|
if (originalNodeData) {
|
|
478
285
|
const result = originalNodeData[1];
|
|
@@ -494,7 +301,7 @@ function printNode(tsInstance, baseSource, sourceFile, node, posContext, origina
|
|
|
494
301
|
let output = '';
|
|
495
302
|
let headPrinted = false;
|
|
496
303
|
let lastChildPos = 0;
|
|
497
|
-
|
|
304
|
+
proxy.visitEachChild(node, (child) => {
|
|
498
305
|
if (!headPrinted) {
|
|
499
306
|
headPrinted = true;
|
|
500
307
|
if (child.pos > node.pos) {
|
|
@@ -508,7 +315,7 @@ function printNode(tsInstance, baseSource, sourceFile, node, posContext, origina
|
|
|
508
315
|
output += text;
|
|
509
316
|
posContext.pos = child.pos;
|
|
510
317
|
}
|
|
511
|
-
output += printNode(
|
|
318
|
+
output += printNode(proxy, baseSource, sourceFile, child, posContext, originalSourceName, mapGenerator);
|
|
512
319
|
lastChildPos = child.end;
|
|
513
320
|
return child;
|
|
514
321
|
}, void 0);
|
|
@@ -523,7 +330,7 @@ function printNode(tsInstance, baseSource, sourceFile, node, posContext, origina
|
|
|
523
330
|
}
|
|
524
331
|
return output;
|
|
525
332
|
function addMappingForCurrent(name) {
|
|
526
|
-
const original = positionToLineAndColumn(sourceFile, posContext.pos, 0);
|
|
333
|
+
const original = positionToLineAndColumn(proxy, sourceFile, posContext.pos, 0);
|
|
527
334
|
if (original.line !== posContext.lastLine) {
|
|
528
335
|
posContext.diff = 0;
|
|
529
336
|
posContext.lastLine = original.line;
|
|
@@ -531,7 +338,7 @@ function printNode(tsInstance, baseSource, sourceFile, node, posContext, origina
|
|
|
531
338
|
if (mapGenerator) {
|
|
532
339
|
mapGenerator.addMapping({
|
|
533
340
|
original,
|
|
534
|
-
generated: positionToLineAndColumn(sourceFile, posContext.pos, posContext.diff),
|
|
341
|
+
generated: positionToLineAndColumn(proxy, sourceFile, posContext.pos, posContext.diff),
|
|
535
342
|
source: originalSourceName,
|
|
536
343
|
name,
|
|
537
344
|
});
|
|
@@ -539,24 +346,24 @@ function printNode(tsInstance, baseSource, sourceFile, node, posContext, origina
|
|
|
539
346
|
}
|
|
540
347
|
}
|
|
541
348
|
////////////////////////////////////////////////////////////////////////////////
|
|
542
|
-
export function
|
|
543
|
-
return transformAndPrintSourceImpl(sourceFile,
|
|
349
|
+
export function transformAndPrintSourceWithProxy(sourceFile, proxy, context, options) {
|
|
350
|
+
return transformAndPrintSourceImpl(sourceFile, proxy, context, options)[0];
|
|
544
351
|
}
|
|
545
|
-
export function
|
|
352
|
+
export function transformAndPrintSourceWithMapWithProxy(sourceFile, proxy, context, originalSourceName, options, startOfSourceMap) {
|
|
546
353
|
const generator = new sourceMap.SourceMapGenerator(startOfSourceMap);
|
|
547
|
-
return transformAndPrintSourceImpl(sourceFile,
|
|
354
|
+
return transformAndPrintSourceImpl(sourceFile, proxy, context, options, originalSourceName, generator);
|
|
548
355
|
}
|
|
549
|
-
function transformAndPrintSourceImpl(sourceFile,
|
|
356
|
+
function transformAndPrintSourceImpl(sourceFile, proxy, context, options, originalSourceName, mapGenerator) {
|
|
550
357
|
const requiredOptions = assignDefaultValues(options);
|
|
551
358
|
if (mapGenerator) {
|
|
552
|
-
mapGenerator.setSourceContent(originalSourceName, sourceFile.
|
|
359
|
+
mapGenerator.setSourceContent(originalSourceName, sourceFile.text);
|
|
553
360
|
}
|
|
554
|
-
const r = transformAndPrintNode({ pos: 0, diff: 0, lastLine: 0 }, sourceFile.
|
|
361
|
+
const r = transformAndPrintNode({ pos: 0, diff: 0, lastLine: 0 }, sourceFile.text, sourceFile, proxy, context, requiredOptions, originalSourceName, mapGenerator);
|
|
555
362
|
return [r, mapGenerator?.toJSON()];
|
|
556
363
|
}
|
|
557
|
-
function transformAndPrintNode(posContext, baseSource, sourceFile,
|
|
364
|
+
function transformAndPrintNode(posContext, baseSource, sourceFile, proxy, context, options, originalSourceName, mapGenerator) {
|
|
558
365
|
let output = '';
|
|
559
|
-
visitNodeChildren(sourceFile, sourceFile, sourceFile,
|
|
366
|
+
visitNodeChildren(sourceFile, sourceFile, sourceFile, proxy, options, context,
|
|
560
367
|
// fnVisit
|
|
561
368
|
(child, _parent, visitContext) => {
|
|
562
369
|
visitContext.lastChildPos = child.end;
|
|
@@ -623,7 +430,7 @@ function transformAndPrintNode(posContext, baseSource, sourceFile, program, cont
|
|
|
623
430
|
});
|
|
624
431
|
return output;
|
|
625
432
|
function addMappingForCurrent(name) {
|
|
626
|
-
const original = positionToLineAndColumn(sourceFile, posContext.pos, 0);
|
|
433
|
+
const original = positionToLineAndColumn(proxy, sourceFile, posContext.pos, 0);
|
|
627
434
|
if (original.line !== posContext.lastLine) {
|
|
628
435
|
posContext.diff = 0;
|
|
629
436
|
posContext.lastLine = original.line;
|
|
@@ -631,7 +438,7 @@ function transformAndPrintNode(posContext, baseSource, sourceFile, program, cont
|
|
|
631
438
|
if (mapGenerator) {
|
|
632
439
|
mapGenerator.addMapping({
|
|
633
440
|
original,
|
|
634
|
-
generated: positionToLineAndColumn(sourceFile, posContext.pos, posContext.diff),
|
|
441
|
+
generated: positionToLineAndColumn(proxy, sourceFile, posContext.pos, posContext.diff),
|
|
635
442
|
source: originalSourceName,
|
|
636
443
|
name,
|
|
637
444
|
});
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import type * as sourceMap from 'source-map';
|
|
2
|
+
import type * as ts from 'typescript';
|
|
3
|
+
import { type TransformOptions } from './transform.mjs';
|
|
4
|
+
export declare function printSource(sourceFile: ts.SourceFile, tsInstance?: typeof ts): string;
|
|
5
|
+
export declare function printSourceWithMap(sourceFile: ts.SourceFile, originalSourceName: string, startOfSourceMap?: sourceMap.RawSourceMap, tsInstance?: typeof ts): [string, sourceMap.RawSourceMap];
|
|
6
|
+
export declare function transformSource(sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, options?: TransformOptions): ts.SourceFile;
|
|
7
|
+
export declare function transformAndPrintSource(sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, options?: TransformOptions): string;
|
|
8
|
+
export declare function transformAndPrintSourceWithMap(sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, originalSourceName: string, options?: TransformOptions, startOfSourceMap?: sourceMap.RawSourceMap): [string, sourceMap.RawSourceMap];
|