ts-const-value-transformer 0.5.0 → 0.6.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 +14 -0
- package/README.md +20 -1
- package/dist/createPortalTransformer.d.mts +13 -0
- package/dist/createPortalTransformer.mjs +58 -25
- package/dist/createTransformer.d.mts +2 -1
- package/dist/createTransformer.mjs +12 -7
- package/dist/loader.d.mts +2 -6
- package/dist/loader.mjs +7 -5
- package/dist/transform.d.mts +5 -4
- package/dist/transform.mjs +60 -43
- package/dist/version.d.mts +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## v0.6.0
|
|
4
|
+
|
|
5
|
+
- Remove skipping satisfies expression
|
|
6
|
+
- Accept `undefined` for `context` and remove dependencies for `context`
|
|
7
|
+
- Fix referring `ts` instance and add `ts` parameter for printSource
|
|
8
|
+
- Add cache to createPortalTransformer
|
|
9
|
+
- Add `recreateProgramOnTransformCount` option for PortalTransformer
|
|
10
|
+
- Fix to use `createPortalTransformerSync` for webpack loader
|
|
11
|
+
- Search tsconfig before loading
|
|
12
|
+
|
|
13
|
+
## v0.5.1
|
|
14
|
+
|
|
15
|
+
- Fix missing for handling `ignoreFiles` for `createTransformer` (used from ts-loader, etc.)
|
|
16
|
+
|
|
3
17
|
## v0.5.0
|
|
4
18
|
|
|
5
19
|
- Add `useUndefinedSymbolForUndefinedValue` and `hoistUndefinedSymbol` options
|
package/README.md
CHANGED
|
@@ -264,6 +264,8 @@ Prints (generates) source code from `SourceFile`, along with raw source-map data
|
|
|
264
264
|
|
|
265
265
|
Transforms the source file with TypeScript project. You don't need to call this function directly; use `createTransformer` or `createPortalTransformer` instead.
|
|
266
266
|
|
|
267
|
+
Note that `ignoreFiles` of `options` will be ignored for this function.
|
|
268
|
+
|
|
267
269
|
#### version: string
|
|
268
270
|
|
|
269
271
|
The version string of this package.
|
|
@@ -277,7 +279,24 @@ See [Transform options](#transform-options).
|
|
|
277
279
|
Creates 'portal transformer', which can be used the transformer easily from the code which does not use TypeScript Compiler API.
|
|
278
280
|
The return object has `transform` method with signature: `(content: string, fileName: string, sourceMap?: string | RawSourceMap | null, options?: TransformOptions) => [newSource: string, newSourceMap: RawSourceMap | undefined]`. You can call to transform TypeScript source code. (Note that this API does not transpile to JavaScript; the output code is still TypeScript code.)
|
|
279
281
|
|
|
280
|
-
`CreatePortalTransformerOptions` has
|
|
282
|
+
`CreatePortalTransformerOptions` has a following signature. Also, `ignoreFiles` of `TransformOptions` can be used.
|
|
283
|
+
|
|
284
|
+
```ts
|
|
285
|
+
interface CreatePortalTransformerOptions extends TransformOptions {
|
|
286
|
+
/** Path to tsconfig.json. If omitted, `tsconfig.json` will be used. */
|
|
287
|
+
project?: string;
|
|
288
|
+
/** Package path to `typescript` or `typescript` namespace object. */
|
|
289
|
+
typescript?: string | typeof tsNamespace;
|
|
290
|
+
/** The current directory for file search. Also affects to `project` option. */
|
|
291
|
+
cwd?: string;
|
|
292
|
+
/**
|
|
293
|
+
* Speficies the count. When the transformation count reaches this value, `program` instance will be recreated (and count will be reset).
|
|
294
|
+
* This is useful if the project is big and out-of-memory occurs during transformation, but the process may be slower.
|
|
295
|
+
* If 0 or `undefined`, recreation will not be performed.
|
|
296
|
+
*/
|
|
297
|
+
recreateProgramOnTransformCount?: number;
|
|
298
|
+
}
|
|
299
|
+
```
|
|
281
300
|
|
|
282
301
|
If `Promise` cannot be used for some reason, use `createPortalTransformerSync` instead.
|
|
283
302
|
|
|
@@ -2,15 +2,28 @@ import type { RawSourceMap } from 'source-map';
|
|
|
2
2
|
import type * as tsNamespace from 'typescript';
|
|
3
3
|
import { type TransformOptions } from './transform.mjs';
|
|
4
4
|
export interface CreatePortalTransformerOptions extends TransformOptions {
|
|
5
|
+
/** Path to tsconfig.json. If omitted, `tsconfig.json` will be used. */
|
|
5
6
|
project?: string;
|
|
7
|
+
/** Package path to `typescript` or `typescript` namespace object. */
|
|
6
8
|
typescript?: string | typeof tsNamespace;
|
|
9
|
+
/** The current directory for file search. Also affects to `project` option. */
|
|
7
10
|
cwd?: string;
|
|
11
|
+
/**
|
|
12
|
+
* Speficies the count. When the transformation count reaches this value, `program` instance will be recreated (and count will be reset).
|
|
13
|
+
* This is useful if the project is big and out-of-memory occurs during transformation, but the process may be slower.
|
|
14
|
+
* If 0 or `undefined`, recreation will not be performed.
|
|
15
|
+
*/
|
|
16
|
+
recreateProgramOnTransformCount?: number;
|
|
8
17
|
}
|
|
9
18
|
export interface PortalTransformer {
|
|
10
19
|
/** The `typescript` namespace object */
|
|
11
20
|
readonly ts: typeof tsNamespace;
|
|
12
21
|
/** Active `Program` instance for the transformer */
|
|
13
22
|
readonly program: tsNamespace.Program;
|
|
23
|
+
/** Clears transformed cache. */
|
|
24
|
+
clearCache(): void;
|
|
25
|
+
/** Forces `program` recreation. The transformation count for `recreateProgramOnTransformCount` will also be resetted. */
|
|
26
|
+
recreateProgram(): void;
|
|
14
27
|
/**
|
|
15
28
|
* Performs transformation.
|
|
16
29
|
* @param content Base source code. If null, uses loaded source code in the TS project.
|
|
@@ -2,27 +2,31 @@ import * as fs from 'fs';
|
|
|
2
2
|
import { createRequire } from 'module';
|
|
3
3
|
import * as path from 'path';
|
|
4
4
|
import createTransformer from './createTransformer.mjs';
|
|
5
|
-
import { printSourceWithMap } from './transform.mjs';
|
|
5
|
+
import { getIgnoreFilesFunction, printSourceWithMap, } from './transform.mjs';
|
|
6
6
|
const require = createRequire(import.meta.url);
|
|
7
|
+
function optionsToString(options) {
|
|
8
|
+
return JSON.stringify(options, (key, value) => {
|
|
9
|
+
if (typeof value === 'function' || value instanceof RegExp) {
|
|
10
|
+
return value.toString();
|
|
11
|
+
}
|
|
12
|
+
if (key === 'typescript' && typeof value === 'object' && value != null) {
|
|
13
|
+
return '[object typescript]';
|
|
14
|
+
}
|
|
15
|
+
return value;
|
|
16
|
+
});
|
|
17
|
+
}
|
|
7
18
|
function createPortalTransformerImpl(options, ts) {
|
|
8
19
|
const project = options.project ?? 'tsconfig.json';
|
|
9
|
-
|
|
10
|
-
if (typeof ignoreFiles !== 'function') {
|
|
11
|
-
const a = ignoreFiles;
|
|
12
|
-
ignoreFiles = (fileName) => {
|
|
13
|
-
return a.some((t) => {
|
|
14
|
-
if (typeof t === 'string') {
|
|
15
|
-
return fileName.indexOf(t) >= 0;
|
|
16
|
-
}
|
|
17
|
-
else {
|
|
18
|
-
return t.test(fileName);
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
};
|
|
22
|
-
}
|
|
20
|
+
const ignoreFiles = getIgnoreFilesFunction(options.ignoreFiles);
|
|
23
21
|
const cwd = options.cwd ?? process.cwd();
|
|
22
|
+
const recreateProgramOnTransformCount = options.recreateProgramOnTransformCount ?? 0;
|
|
23
|
+
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
24
|
+
const foundConfigPath = ts.findConfigFile(cwd, ts.sys.fileExists, project);
|
|
25
|
+
if (foundConfigPath == null) {
|
|
26
|
+
throw new Error(`[ts-const-value-transformer] Unable to load tsconfig file (effective name = '${project}')`);
|
|
27
|
+
}
|
|
24
28
|
const getCurrentDirectory = () => cwd;
|
|
25
|
-
const config = ts.getParsedCommandLineOfConfigFile(
|
|
29
|
+
const config = ts.getParsedCommandLineOfConfigFile(foundConfigPath, void 0, {
|
|
26
30
|
fileExists: fs.existsSync,
|
|
27
31
|
getCurrentDirectory,
|
|
28
32
|
// eslint-disable-next-line @typescript-eslint/unbound-method
|
|
@@ -38,16 +42,37 @@ function createPortalTransformerImpl(options, ts) {
|
|
|
38
42
|
},
|
|
39
43
|
});
|
|
40
44
|
if (!config) {
|
|
41
|
-
throw new Error(`[ts-const-value-transformer] Unable to load tsconfig file (effective name = '${
|
|
45
|
+
throw new Error(`[ts-const-value-transformer] Unable to load tsconfig file (effective name = '${foundConfigPath}')`);
|
|
42
46
|
}
|
|
43
|
-
|
|
47
|
+
let program = ts.createProgram({
|
|
44
48
|
options: config.options,
|
|
45
49
|
rootNames: config.fileNames,
|
|
46
50
|
});
|
|
47
|
-
|
|
51
|
+
let transformationCount = 0;
|
|
52
|
+
const recreateProgram = () => {
|
|
53
|
+
const oldProgram = program;
|
|
54
|
+
program = ts.createProgram({
|
|
55
|
+
options: config.options,
|
|
56
|
+
rootNames: config.fileNames,
|
|
57
|
+
oldProgram,
|
|
58
|
+
});
|
|
59
|
+
instance.program = program;
|
|
60
|
+
transformationCount = 0;
|
|
61
|
+
};
|
|
62
|
+
const cache = new Map();
|
|
63
|
+
const instance = {
|
|
48
64
|
ts,
|
|
49
65
|
program,
|
|
66
|
+
clearCache: () => cache.clear(),
|
|
67
|
+
recreateProgram,
|
|
50
68
|
transform: (content, fileName, sourceMap, individualOptions) => {
|
|
69
|
+
const individualOptionsJson = optionsToString(individualOptions ?? {});
|
|
70
|
+
const cachedData = cache.get(fileName);
|
|
71
|
+
if (cachedData &&
|
|
72
|
+
cachedData.content === content &&
|
|
73
|
+
cachedData.optJson === individualOptionsJson) {
|
|
74
|
+
return cachedData.result;
|
|
75
|
+
}
|
|
51
76
|
// eslint-disable-next-line @typescript-eslint/no-unsafe-assignment
|
|
52
77
|
const rawSourceMap = typeof sourceMap === 'string'
|
|
53
78
|
? JSON.parse(sourceMap)
|
|
@@ -55,30 +80,38 @@ function createPortalTransformerImpl(options, ts) {
|
|
|
55
80
|
if (ignoreFiles(fileName)) {
|
|
56
81
|
return [content, rawSourceMap];
|
|
57
82
|
}
|
|
83
|
+
transformationCount++;
|
|
84
|
+
if (recreateProgramOnTransformCount > 0 &&
|
|
85
|
+
transformationCount >= recreateProgramOnTransformCount) {
|
|
86
|
+
recreateProgram();
|
|
87
|
+
}
|
|
58
88
|
const sourceFile = program.getSourceFile(fileName);
|
|
59
89
|
if (!sourceFile) {
|
|
60
90
|
return [content, rawSourceMap];
|
|
61
91
|
}
|
|
62
92
|
// If input content is changed, replace it
|
|
63
|
-
if (content != null && sourceFile.
|
|
93
|
+
if (content != null && sourceFile.text !== content) {
|
|
64
94
|
sourceFile.update(content, {
|
|
65
95
|
span: { start: 0, length: sourceFile.end },
|
|
66
96
|
newLength: content.length,
|
|
67
97
|
});
|
|
98
|
+
sourceFile.text = content;
|
|
68
99
|
}
|
|
69
100
|
const transformer = createTransformer(program, {
|
|
70
101
|
options: { ...options, ...individualOptions, ts },
|
|
71
102
|
});
|
|
72
|
-
const
|
|
73
|
-
const transformedSource =
|
|
103
|
+
const transformResult = ts.transform(sourceFile, [transformer], program.getCompilerOptions());
|
|
104
|
+
const transformedSource = transformResult.transformed[0];
|
|
74
105
|
// If unchanged, return base file as-is
|
|
75
106
|
if (transformedSource === sourceFile) {
|
|
76
|
-
return [content ?? sourceFile.
|
|
107
|
+
return [content ?? sourceFile.text, rawSourceMap];
|
|
77
108
|
}
|
|
78
|
-
const
|
|
79
|
-
|
|
109
|
+
const result = printSourceWithMap(transformedSource, fileName, rawSourceMap, ts);
|
|
110
|
+
cache.set(fileName, { content, optJson: individualOptionsJson, result });
|
|
111
|
+
return result;
|
|
80
112
|
},
|
|
81
113
|
};
|
|
114
|
+
return instance;
|
|
82
115
|
}
|
|
83
116
|
/**
|
|
84
117
|
* Creates the new portal transformer instance for the TS project.
|
|
@@ -3,7 +3,8 @@ import { type TransformOptions } from './transform.mjs';
|
|
|
3
3
|
interface Config {
|
|
4
4
|
options?: TransformOptions;
|
|
5
5
|
}
|
|
6
|
+
export type TransformerFactory = (context?: ts.TransformationContext) => (sourceFile: ts.SourceFile) => ts.SourceFile;
|
|
6
7
|
export default function createTransformer(program: ts.Program, config?: Config, extras?: {
|
|
7
8
|
ts?: typeof ts;
|
|
8
|
-
}):
|
|
9
|
+
}): TransformerFactory;
|
|
9
10
|
export {};
|
|
@@ -1,15 +1,20 @@
|
|
|
1
|
-
import { transformSource } from './transform.mjs';
|
|
1
|
+
import { getIgnoreFilesFunction, transformSource, } from './transform.mjs';
|
|
2
2
|
export default function createTransformer(program,
|
|
3
3
|
// for ttypescript and ts-patch
|
|
4
4
|
config,
|
|
5
5
|
// for ts-patch
|
|
6
6
|
extras) {
|
|
7
|
-
|
|
7
|
+
const options = {
|
|
8
|
+
...config?.options,
|
|
9
|
+
...(extras?.ts && { ts: extras?.ts }),
|
|
10
|
+
};
|
|
11
|
+
const ignoreFiles = getIgnoreFilesFunction(options.ignoreFiles);
|
|
12
|
+
return ((context) => {
|
|
8
13
|
return (sourceFile) => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
14
|
+
if (ignoreFiles(sourceFile.fileName)) {
|
|
15
|
+
return sourceFile;
|
|
16
|
+
}
|
|
17
|
+
return transformSource(sourceFile, program, context, options);
|
|
13
18
|
};
|
|
14
|
-
};
|
|
19
|
+
});
|
|
15
20
|
}
|
package/dist/loader.d.mts
CHANGED
|
@@ -1,9 +1,5 @@
|
|
|
1
|
-
import type * as tsNamespace from 'typescript';
|
|
2
1
|
import type * as webpack from 'webpack';
|
|
3
|
-
import type
|
|
4
|
-
export
|
|
5
|
-
project?: string;
|
|
6
|
-
typescript?: string | typeof tsNamespace;
|
|
7
|
-
}
|
|
2
|
+
import { type CreatePortalTransformerOptions } from './createPortalTransformer.mjs';
|
|
3
|
+
export type TsConstValueTransformerLoaderOptions = CreatePortalTransformerOptions;
|
|
8
4
|
declare const loader: webpack.LoaderDefinitionFunction<TsConstValueTransformerLoaderOptions | undefined>;
|
|
9
5
|
export default loader;
|
package/dist/loader.mjs
CHANGED
|
@@ -1,17 +1,19 @@
|
|
|
1
1
|
import * as path from 'path';
|
|
2
|
-
import
|
|
2
|
+
import { createPortalTransformerSync, } from './createPortalTransformer.mjs';
|
|
3
3
|
const transformerMap = new Map();
|
|
4
4
|
const loader = function (content, sourceMap) {
|
|
5
|
+
// eslint-disable-next-line @typescript-eslint/no-unused-expressions, @typescript-eslint/strict-boolean-expressions
|
|
6
|
+
this.cacheable && this.cacheable();
|
|
5
7
|
this.async();
|
|
6
|
-
void (
|
|
8
|
+
void Promise.resolve().then(() => {
|
|
7
9
|
try {
|
|
8
10
|
const options = this.getOptions() || {};
|
|
9
11
|
const project = options.project ?? 'tsconfig.json';
|
|
10
12
|
let transformer = transformerMap.get(project);
|
|
11
13
|
if (!transformer) {
|
|
12
|
-
transformer =
|
|
13
|
-
...options,
|
|
14
|
+
transformer = createPortalTransformerSync({
|
|
14
15
|
cwd: path.dirname(this.resourcePath),
|
|
16
|
+
...options,
|
|
15
17
|
});
|
|
16
18
|
transformerMap.set(project, transformer);
|
|
17
19
|
}
|
|
@@ -21,6 +23,6 @@ const loader = function (content, sourceMap) {
|
|
|
21
23
|
catch (e) {
|
|
22
24
|
this.callback(e);
|
|
23
25
|
}
|
|
24
|
-
})
|
|
26
|
+
});
|
|
25
27
|
};
|
|
26
28
|
export default loader;
|
package/dist/transform.d.mts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import * as sourceMap from 'source-map';
|
|
2
|
-
import * as ts from 'typescript';
|
|
2
|
+
import type * as ts from 'typescript';
|
|
3
3
|
export interface TransformOptions {
|
|
4
4
|
/** `typescript` namespace object */
|
|
5
5
|
ts?: typeof ts;
|
|
@@ -35,6 +35,7 @@ export interface TransformOptions {
|
|
|
35
35
|
*/
|
|
36
36
|
ignoreFiles?: ReadonlyArray<string | RegExp> | ((fileName: string) => boolean);
|
|
37
37
|
}
|
|
38
|
-
export declare function
|
|
39
|
-
export declare function
|
|
40
|
-
export declare function
|
|
38
|
+
export declare function getIgnoreFilesFunction(ignoreFiles: TransformOptions['ignoreFiles']): (fileName: string) => boolean;
|
|
39
|
+
export declare function transformSource(sourceFile: ts.SourceFile, program: ts.Program, context: ts.TransformationContext | undefined, options?: TransformOptions): ts.SourceFile;
|
|
40
|
+
export declare function printSource(sourceFile: ts.SourceFile, tsInstance?: typeof ts): string;
|
|
41
|
+
export declare function printSourceWithMap(sourceFile: ts.SourceFile, originalSourceName: string, startOfSourceMap?: sourceMap.RawSourceMap, tsInstance?: typeof ts): [string, sourceMap.RawSourceMap];
|
package/dist/transform.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import * as sourceMap from 'source-map';
|
|
2
|
-
import * as
|
|
2
|
+
import * as tsNamespace from 'typescript';
|
|
3
3
|
const SYMBOL_ORIGINAL_NODE = Symbol('originalNode');
|
|
4
4
|
function assignDefaultValues(options = {}) {
|
|
5
5
|
return {
|
|
6
6
|
// avoid using spread syntax to override `undefined` (not missing) values
|
|
7
|
-
ts: options.ts ??
|
|
7
|
+
ts: options.ts ?? tsNamespace,
|
|
8
8
|
hoistProperty: options.hoistProperty ?? true,
|
|
9
9
|
hoistEnumValues: options.hoistEnumValues ?? true,
|
|
10
10
|
hoistExternalValues: options.hoistExternalValues ?? true,
|
|
@@ -19,18 +19,36 @@ function assignDefaultValues(options = {}) {
|
|
|
19
19
|
};
|
|
20
20
|
}
|
|
21
21
|
////////////////////////////////////////////////////////////////////////////////
|
|
22
|
+
export function getIgnoreFilesFunction(ignoreFiles) {
|
|
23
|
+
if (!ignoreFiles) {
|
|
24
|
+
return () => false;
|
|
25
|
+
}
|
|
26
|
+
if (typeof ignoreFiles === 'function') {
|
|
27
|
+
return ignoreFiles;
|
|
28
|
+
}
|
|
29
|
+
const a = ignoreFiles;
|
|
30
|
+
return (fileName) => {
|
|
31
|
+
return a.some((t) => {
|
|
32
|
+
if (typeof t === 'string') {
|
|
33
|
+
return fileName.indexOf(t) >= 0;
|
|
34
|
+
}
|
|
35
|
+
else {
|
|
36
|
+
return t.test(fileName);
|
|
37
|
+
}
|
|
38
|
+
});
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
////////////////////////////////////////////////////////////////////////////////
|
|
22
42
|
export function transformSource(sourceFile, program, context, options) {
|
|
23
|
-
|
|
43
|
+
const requiredOptions = assignDefaultValues(options);
|
|
44
|
+
return requiredOptions.ts.visitEachChild(sourceFile, (node) => visitNodeChildren(node, sourceFile, sourceFile, program, requiredOptions), context);
|
|
24
45
|
}
|
|
25
|
-
function visitNodeChildren(node, parent, sourceFile, program,
|
|
26
|
-
const
|
|
46
|
+
function visitNodeChildren(node, parent, sourceFile, program, options) {
|
|
47
|
+
const ts = options.ts;
|
|
48
|
+
const newNode = visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options);
|
|
27
49
|
if (newNode[SYMBOL_ORIGINAL_NODE]) {
|
|
28
50
|
return newNode;
|
|
29
51
|
}
|
|
30
|
-
// skip children for satisifes expression
|
|
31
|
-
if (ts.isSatisfiesExpression(newNode)) {
|
|
32
|
-
return newNode;
|
|
33
|
-
}
|
|
34
52
|
// skip statements which would not have 'value' expressions
|
|
35
53
|
if (ts.isInterfaceDeclaration(newNode) ||
|
|
36
54
|
ts.isTypeAliasDeclaration(newNode) ||
|
|
@@ -39,9 +57,9 @@ function visitNodeChildren(node, parent, sourceFile, program, context, options)
|
|
|
39
57
|
ts.isTypeOnlyExportDeclaration(newNode)) {
|
|
40
58
|
return newNode;
|
|
41
59
|
}
|
|
42
|
-
return ts.visitEachChild(newNode, (node) => visitNodeChildren(node, newNode, sourceFile, program,
|
|
60
|
+
return ts.visitEachChild(newNode, (node) => visitNodeChildren(node, newNode, sourceFile, program, options), void 0);
|
|
43
61
|
}
|
|
44
|
-
function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program,
|
|
62
|
+
function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, options) {
|
|
45
63
|
const ts = options.ts;
|
|
46
64
|
if (ts.isCallLikeExpression(node)) {
|
|
47
65
|
if (!ts.isExpression(node) ||
|
|
@@ -87,12 +105,11 @@ function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, context,
|
|
|
87
105
|
return node;
|
|
88
106
|
}
|
|
89
107
|
if (!options.hoistExternalValues &&
|
|
90
|
-
isExternalReference(node, program, options.externalNames)) {
|
|
108
|
+
isExternalReference(node, program, options.externalNames, ts)) {
|
|
91
109
|
return node;
|
|
92
110
|
}
|
|
93
111
|
if (!options.unsafeHoistAsExpresion &&
|
|
94
|
-
(hasAsExpression(node,
|
|
95
|
-
hasParentAsExpression(parent, context, ts))) {
|
|
112
|
+
(hasAsExpression(node, ts) || hasParentAsExpression(parent, ts))) {
|
|
96
113
|
return node;
|
|
97
114
|
}
|
|
98
115
|
if (!options.unsafeHoistWritableValues) {
|
|
@@ -110,35 +127,33 @@ function visitNodeAndReplaceIfNeeded(node, parent, sourceFile, program, context,
|
|
|
110
127
|
return node;
|
|
111
128
|
}
|
|
112
129
|
if (type.isStringLiteral()) {
|
|
113
|
-
newNode =
|
|
130
|
+
newNode = ts.factory.createStringLiteral(type.value);
|
|
114
131
|
}
|
|
115
132
|
else if (type.isNumberLiteral()) {
|
|
116
133
|
if (type.value < 0) {
|
|
117
|
-
newNode =
|
|
134
|
+
newNode = ts.factory.createPrefixUnaryExpression(ts.SyntaxKind.MinusToken, ts.factory.createNumericLiteral(-type.value));
|
|
118
135
|
}
|
|
119
136
|
else {
|
|
120
|
-
newNode =
|
|
137
|
+
newNode = ts.factory.createNumericLiteral(type.value);
|
|
121
138
|
}
|
|
122
139
|
}
|
|
123
140
|
else if (flags & ts.TypeFlags.BigIntLiteral) {
|
|
124
|
-
newNode =
|
|
141
|
+
newNode = ts.factory.createBigIntLiteral(typeChecker.typeToString(type));
|
|
125
142
|
}
|
|
126
143
|
else if (flags & ts.TypeFlags.BooleanLiteral) {
|
|
127
144
|
const text = typeChecker.typeToString(type);
|
|
128
145
|
newNode =
|
|
129
|
-
text === 'true'
|
|
130
|
-
? context.factory.createTrue()
|
|
131
|
-
: context.factory.createFalse();
|
|
146
|
+
text === 'true' ? ts.factory.createTrue() : ts.factory.createFalse();
|
|
132
147
|
}
|
|
133
148
|
else if (flags & ts.TypeFlags.Null) {
|
|
134
|
-
newNode =
|
|
149
|
+
newNode = ts.factory.createNull();
|
|
135
150
|
}
|
|
136
151
|
else if (flags & ts.TypeFlags.Undefined) {
|
|
137
152
|
if (options.useUndefinedSymbolForUndefinedValue) {
|
|
138
|
-
newNode =
|
|
153
|
+
newNode = ts.factory.createIdentifier('undefined');
|
|
139
154
|
}
|
|
140
155
|
else {
|
|
141
|
-
newNode =
|
|
156
|
+
newNode = ts.factory.createVoidZero();
|
|
142
157
|
}
|
|
143
158
|
}
|
|
144
159
|
else {
|
|
@@ -165,7 +180,8 @@ function isEnumIdentifier(node, program, tsInstance) {
|
|
|
165
180
|
const type = typeChecker.getTypeAtLocation(node);
|
|
166
181
|
return (type.getFlags() & ts.TypeFlags.EnumLiteral) !== 0;
|
|
167
182
|
}
|
|
168
|
-
function isExternalReference(node, program, externalNames) {
|
|
183
|
+
function isExternalReference(node, program, externalNames, tsInstance) {
|
|
184
|
+
const ts = tsInstance;
|
|
169
185
|
const typeChecker = program.getTypeChecker();
|
|
170
186
|
const nodeSym = typeChecker.getSymbolAtLocation(node);
|
|
171
187
|
let nodeFrom = nodeSym?.getDeclarations()?.[0];
|
|
@@ -218,7 +234,7 @@ function isExternalReference(node, program, externalNames) {
|
|
|
218
234
|
function isAsConstExpression(node) {
|
|
219
235
|
return node.type.getText() === 'const';
|
|
220
236
|
}
|
|
221
|
-
function hasAsExpression(node,
|
|
237
|
+
function hasAsExpression(node, tsInstance) {
|
|
222
238
|
const ts = tsInstance;
|
|
223
239
|
// including 'as const'
|
|
224
240
|
if (ts.isAsExpression(node)) {
|
|
@@ -227,13 +243,13 @@ function hasAsExpression(node, context, tsInstance) {
|
|
|
227
243
|
let found = false;
|
|
228
244
|
ts.visitEachChild(node, (node) => {
|
|
229
245
|
if (!found) {
|
|
230
|
-
found = hasAsExpression(node,
|
|
246
|
+
found = hasAsExpression(node, ts);
|
|
231
247
|
}
|
|
232
248
|
return node;
|
|
233
|
-
},
|
|
249
|
+
}, void 0);
|
|
234
250
|
return found;
|
|
235
251
|
}
|
|
236
|
-
function hasParentAsExpression(node,
|
|
252
|
+
function hasParentAsExpression(node, tsInstance) {
|
|
237
253
|
const ts = tsInstance;
|
|
238
254
|
if (node == null) {
|
|
239
255
|
return false;
|
|
@@ -244,11 +260,11 @@ function hasParentAsExpression(node, context, tsInstance) {
|
|
|
244
260
|
}
|
|
245
261
|
if (ts.isPropertyAccessExpression(node) ||
|
|
246
262
|
ts.isElementAccessExpression(node)) {
|
|
247
|
-
if (hasAsExpression(node.expression,
|
|
263
|
+
if (hasAsExpression(node.expression, ts)) {
|
|
248
264
|
return true;
|
|
249
265
|
}
|
|
250
266
|
}
|
|
251
|
-
return hasParentAsExpression(node.parent,
|
|
267
|
+
return hasParentAsExpression(node.parent, ts);
|
|
252
268
|
}
|
|
253
269
|
function hasPureAnnotation(node, sourceFile, tsInstance) {
|
|
254
270
|
const ts = tsInstance;
|
|
@@ -388,19 +404,19 @@ function isUndefinedIdentifier(node, parent, program, tsInstance) {
|
|
|
388
404
|
return false;
|
|
389
405
|
}
|
|
390
406
|
if (type.isUnionOrIntersection() ||
|
|
391
|
-
!(type.getFlags() &
|
|
407
|
+
!(type.getFlags() & tsInstance.TypeFlags.Undefined)) {
|
|
392
408
|
return false;
|
|
393
409
|
}
|
|
394
410
|
return true;
|
|
395
411
|
}
|
|
396
412
|
////////////////////////////////////////////////////////////////////////////////
|
|
397
|
-
export function printSource(sourceFile) {
|
|
398
|
-
return printSourceImpl(sourceFile)[0];
|
|
413
|
+
export function printSource(sourceFile, tsInstance) {
|
|
414
|
+
return printSourceImpl(tsInstance, sourceFile)[0];
|
|
399
415
|
}
|
|
400
|
-
export function printSourceWithMap(sourceFile, originalSourceName, startOfSourceMap) {
|
|
416
|
+
export function printSourceWithMap(sourceFile, originalSourceName, startOfSourceMap, tsInstance) {
|
|
401
417
|
const generator = new sourceMap.SourceMapGenerator(startOfSourceMap);
|
|
402
418
|
generator.setSourceContent(originalSourceName, sourceFile.getFullText());
|
|
403
|
-
return printSourceImpl(sourceFile, originalSourceName, generator);
|
|
419
|
+
return printSourceImpl(tsInstance, sourceFile, originalSourceName, generator);
|
|
404
420
|
}
|
|
405
421
|
function positionToLineAndColumn(sourceFile, pos, generatedDiff) {
|
|
406
422
|
let line = 0;
|
|
@@ -414,16 +430,17 @@ function positionToLineAndColumn(sourceFile, pos, generatedDiff) {
|
|
|
414
430
|
}
|
|
415
431
|
return { line, column: pos - lastLinePos + generatedDiff };
|
|
416
432
|
}
|
|
417
|
-
function printSourceImpl(sourceFile, originalSourceName, mapGenerator) {
|
|
433
|
+
function printSourceImpl(tsInstance, sourceFile, originalSourceName, mapGenerator) {
|
|
434
|
+
const ts = tsInstance ?? tsNamespace;
|
|
418
435
|
const printer = ts.createPrinter({ removeComments: true });
|
|
419
|
-
const r = printNode(printer, sourceFile.getFullText(), sourceFile, sourceFile, { pos: 0, diff: 0, lastLine: 0 }, originalSourceName, mapGenerator);
|
|
436
|
+
const r = printNode(ts, printer, sourceFile.getFullText(), sourceFile, sourceFile, { pos: 0, diff: 0, lastLine: 0 }, originalSourceName, mapGenerator);
|
|
420
437
|
return [r, mapGenerator?.toJSON()];
|
|
421
438
|
}
|
|
422
|
-
function printNode(printer, baseSource, sourceFile, node, posContext, originalSourceName, mapGenerator) {
|
|
439
|
+
function printNode(tsInstance, printer, baseSource, sourceFile, node, posContext, originalSourceName, mapGenerator) {
|
|
423
440
|
const originalNode = node[SYMBOL_ORIGINAL_NODE];
|
|
424
441
|
if (originalNode) {
|
|
425
|
-
let result = printer.printNode(
|
|
426
|
-
const comments =
|
|
442
|
+
let result = printer.printNode(tsInstance.EmitHint.Unspecified, node, sourceFile);
|
|
443
|
+
const comments = tsInstance.getSyntheticTrailingComments(node);
|
|
427
444
|
if (comments) {
|
|
428
445
|
for (const comment of comments) {
|
|
429
446
|
result += ` /*${comment.text}*/`;
|
|
@@ -457,7 +474,7 @@ function printNode(printer, baseSource, sourceFile, node, posContext, originalSo
|
|
|
457
474
|
let output = '';
|
|
458
475
|
let headPrinted = false;
|
|
459
476
|
let lastChildPos = 0;
|
|
460
|
-
|
|
477
|
+
tsInstance.visitEachChild(node, (child) => {
|
|
461
478
|
if (!headPrinted) {
|
|
462
479
|
headPrinted = true;
|
|
463
480
|
if (child.pos > node.pos) {
|
|
@@ -473,7 +490,7 @@ function printNode(printer, baseSource, sourceFile, node, posContext, originalSo
|
|
|
473
490
|
addMappingForCurrent();
|
|
474
491
|
posContext.pos = child.pos;
|
|
475
492
|
}
|
|
476
|
-
output += printNode(printer, baseSource, sourceFile, child, posContext, originalSourceName, mapGenerator);
|
|
493
|
+
output += printNode(tsInstance, printer, baseSource, sourceFile, child, posContext, originalSourceName, mapGenerator);
|
|
477
494
|
lastChildPos = child.end;
|
|
478
495
|
return child;
|
|
479
496
|
}, void 0);
|
package/dist/version.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "0.
|
|
1
|
+
declare const _default: "0.6.0";
|
|
2
2
|
export default _default;
|
package/dist/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '0.
|
|
1
|
+
export default '0.6.0';
|