ts-const-value-transformer 0.10.0 → 0.10.1
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 +4 -0
- package/dist/createPortalTransformerWithTsLs.mjs +6 -1
- package/dist/lsp/TsLspClient.d.mts +3 -2
- package/dist/lsp/TsLspClient.mjs +21 -18
- package/dist/lsp/lspTransformerUtil.mjs +42 -33
- package/dist/version.d.mts +1 -1
- package/dist/version.mjs +1 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -29,7 +29,8 @@ function createPortalTransformerImpl(options, ts) {
|
|
|
29
29
|
const cwd = options.cwd ?? process.cwd();
|
|
30
30
|
const cacheBaseSource = options.cacheBaseSource ?? false;
|
|
31
31
|
const cacheResult = options.cacheResult ?? true;
|
|
32
|
-
const
|
|
32
|
+
const projectFullPath = path.resolve(cwd, project);
|
|
33
|
+
const workspaceFolder = path.dirname(projectFullPath);
|
|
33
34
|
const client = new TsLspClient(commandArray[0], commandArray.slice(1));
|
|
34
35
|
let isInitialized = false;
|
|
35
36
|
const cache = new Map();
|
|
@@ -83,6 +84,10 @@ function createPortalTransformerImpl(options, ts) {
|
|
|
83
84
|
}
|
|
84
85
|
if (!isInitialized) {
|
|
85
86
|
client.waitForFirstDiagnosticsReceived();
|
|
87
|
+
const diag = client.getCachedDiagnostics(projectFullPath);
|
|
88
|
+
if (diag && diag.length > 0) {
|
|
89
|
+
throw new Error('Error for tsconfig:\n' + diag.map((d) => d.message).join('\n'));
|
|
90
|
+
}
|
|
86
91
|
isInitialized = true;
|
|
87
92
|
}
|
|
88
93
|
const result = transformAndPrintSourceWithMap(sourceFile, client, getSourceFile, fileName, { ...options, ...individualOptions, ts }, rawSourceMap);
|
|
@@ -6,6 +6,7 @@ export default class TsLspClient extends SyncLspClient {
|
|
|
6
6
|
constructor(command: string, argv: string[], encoding?: BufferEncoding);
|
|
7
7
|
initialize(rootDir: string): void;
|
|
8
8
|
waitForFirstDiagnosticsReceived(): void;
|
|
9
|
+
getCachedDiagnostics(fileName: string): Diagnostic[] | null;
|
|
9
10
|
openDocument(fileName: string, content: string): void;
|
|
10
11
|
closeDocument(fileName: string): void;
|
|
11
12
|
/** Only returns first string from contents */
|
|
@@ -17,13 +18,13 @@ export default class TsLspClient extends SyncLspClient {
|
|
|
17
18
|
lineEnd: number;
|
|
18
19
|
posEnd: number;
|
|
19
20
|
} | null;
|
|
20
|
-
getTypeDefitition(fileName: string, line: number, pos: number): {
|
|
21
|
+
getTypeDefitition(fileName: string, line: number, pos: number): Array<{
|
|
21
22
|
fileName: string;
|
|
22
23
|
lineStart: number;
|
|
23
24
|
posStart: number;
|
|
24
25
|
lineEnd: number;
|
|
25
26
|
posEnd: number;
|
|
26
|
-
}
|
|
27
|
+
}>;
|
|
27
28
|
sendReplaceText(fileName: string, lineStart: number, posStart: number, lineEnd: number, posEnd: number, text: string): void;
|
|
28
29
|
exit(): void;
|
|
29
30
|
}
|
package/dist/lsp/TsLspClient.mjs
CHANGED
|
@@ -3,7 +3,6 @@ import { fileURLToPath, pathToFileURL } from 'url';
|
|
|
3
3
|
// @internal
|
|
4
4
|
import version from '../version.mjs';
|
|
5
5
|
import SyncLspClient from './SyncLspClient.mjs';
|
|
6
|
-
/* eslint-disable @typescript-eslint/no-unsafe-member-access */
|
|
7
6
|
export default class TsLspClient extends SyncLspClient {
|
|
8
7
|
_supportPullDiagnostics;
|
|
9
8
|
_firstDiagnosticsReceived;
|
|
@@ -93,6 +92,12 @@ export default class TsLspClient extends SyncLspClient {
|
|
|
93
92
|
}
|
|
94
93
|
}
|
|
95
94
|
}
|
|
95
|
+
getCachedDiagnostics(fileName) {
|
|
96
|
+
const uri = pathToFileURL(fileName).href;
|
|
97
|
+
return this._fileForDiagnostics.has(uri)
|
|
98
|
+
? this._fileForDiagnostics.get(uri)
|
|
99
|
+
: null;
|
|
100
|
+
}
|
|
96
101
|
openDocument(fileName, content) {
|
|
97
102
|
const uri = pathToFileURL(fileName).href;
|
|
98
103
|
this._fileForDiagnostics.delete(uri);
|
|
@@ -221,24 +226,22 @@ export default class TsLspClient extends SyncLspClient {
|
|
|
221
226
|
const r = this.receiveMessage(id);
|
|
222
227
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
223
228
|
if (!r) {
|
|
224
|
-
return
|
|
225
|
-
}
|
|
226
|
-
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
227
|
-
const loc = r instanceof Array ? r[0] : r;
|
|
228
|
-
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
229
|
-
if (!loc) {
|
|
230
|
-
return null;
|
|
229
|
+
return [];
|
|
231
230
|
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
231
|
+
const a = r instanceof Array ? r : [r];
|
|
232
|
+
return a.map((loc) => {
|
|
233
|
+
/* eslint-disable @typescript-eslint/no-unsafe-assignment */
|
|
234
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
235
|
+
const defFileName = fileURLToPath(loc.uri);
|
|
236
|
+
return {
|
|
237
|
+
fileName: defFileName,
|
|
238
|
+
lineStart: loc.range.start.line,
|
|
239
|
+
posStart: loc.range.start.character,
|
|
240
|
+
lineEnd: loc.range.end.line,
|
|
241
|
+
posEnd: loc.range.end.character,
|
|
242
|
+
};
|
|
243
|
+
/* eslint-enable @typescript-eslint/no-unsafe-assignment */
|
|
244
|
+
});
|
|
242
245
|
}
|
|
243
246
|
sendReplaceText(fileName, lineStart, posStart, lineEnd, posEnd, text) {
|
|
244
247
|
const uri = pathToFileURL(fileName).href;
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import * as ts from 'typescript';
|
|
2
1
|
const HOVER_CACHE_SYMBOL = Symbol('hover-cache');
|
|
3
2
|
const TYPE_CACHE_SYMBOL = Symbol('type-cache');
|
|
4
3
|
const READONLY_CACHE_SYMBOL = Symbol('read-only-cache');
|
|
@@ -22,7 +21,7 @@ function addToPositionByText(pos, text) {
|
|
|
22
21
|
}
|
|
23
22
|
return r;
|
|
24
23
|
}
|
|
25
|
-
function getNodeFromPosition(sourceFile, line, pos) {
|
|
24
|
+
function getNodeFromPosition(sourceFile, line, pos, tsInstance) {
|
|
26
25
|
const lines = sourceFile.getLineStarts();
|
|
27
26
|
if (line >= lines.length) {
|
|
28
27
|
line = lines.length - 1;
|
|
@@ -36,7 +35,7 @@ function getNodeFromPosition(sourceFile, line, pos) {
|
|
|
36
35
|
if (node.pos <= nodePos && node.end >= nodePos) {
|
|
37
36
|
foundNode = node;
|
|
38
37
|
}
|
|
39
|
-
|
|
38
|
+
tsInstance.visitEachChild(node, (n) => visit(n, node), undefined);
|
|
40
39
|
return node;
|
|
41
40
|
}
|
|
42
41
|
}
|
|
@@ -101,7 +100,10 @@ function hoverToTypeString(node, hover, tsInstance) {
|
|
|
101
100
|
}
|
|
102
101
|
}
|
|
103
102
|
}
|
|
104
|
-
else if (
|
|
103
|
+
else if (
|
|
104
|
+
// For node is null, always check function-like type string (used by retrieveActualTypeString)
|
|
105
|
+
(!node || tsInstance.isIdentifier(node)) &&
|
|
106
|
+
isFunctionLike(hover)) {
|
|
105
107
|
if (hover.startsWith('function')) {
|
|
106
108
|
hover = hover.slice(8);
|
|
107
109
|
}
|
|
@@ -197,10 +199,12 @@ function hoverToFunctionReturnTypeString(node, hover, tsInstance) {
|
|
|
197
199
|
}
|
|
198
200
|
}
|
|
199
201
|
function retrieveActualTypeString(fileName, pos, tsIntance, client) {
|
|
200
|
-
const
|
|
201
|
-
|
|
202
|
+
const defs = client.getTypeDefitition(fileName, pos.line, pos.column);
|
|
203
|
+
// For enum types (not enum-literal types), the returned definitons will be multiple
|
|
204
|
+
if (defs.length !== 1) {
|
|
202
205
|
return ['', ''];
|
|
203
206
|
}
|
|
207
|
+
const def = defs[0];
|
|
204
208
|
const o = client.hoverForPosition(def.fileName, def.lineEnd, def.posEnd);
|
|
205
209
|
const code = hoverResultToCode(o);
|
|
206
210
|
return [code, hoverToTypeString(null, code, tsIntance)];
|
|
@@ -220,7 +224,8 @@ function typeStringToLiteralType(typeString, tsInstance) {
|
|
|
220
224
|
return tsInstance.TypeFlags.BooleanLiteral;
|
|
221
225
|
}
|
|
222
226
|
// string literal
|
|
223
|
-
if (/^(["
|
|
227
|
+
if (/^"(?:[^"\\]|\\.)*"$/.test(typeString) ||
|
|
228
|
+
/^'(?:[^'\\]|\\.)*'$/.test(typeString)) {
|
|
224
229
|
return tsInstance.TypeFlags.StringLiteral;
|
|
225
230
|
}
|
|
226
231
|
// number / bigint
|
|
@@ -373,7 +378,7 @@ function determineIfPropertyIsReadonly(node, sourceFile, tsInstance, client, get
|
|
|
373
378
|
return false;
|
|
374
379
|
}
|
|
375
380
|
let def;
|
|
376
|
-
if (
|
|
381
|
+
if (tsInstance.isElementAccessExpression(node)) {
|
|
377
382
|
def = performActualPropertyForElementAccessExpression(node, sourceFile, tsInstance, client, (pos) => client.getDefinition(sourceFile.fileName, pos.line, pos.column));
|
|
378
383
|
}
|
|
379
384
|
else {
|
|
@@ -384,7 +389,7 @@ function determineIfPropertyIsReadonly(node, sourceFile, tsInstance, client, get
|
|
|
384
389
|
return false;
|
|
385
390
|
}
|
|
386
391
|
const defSource = getSourceFile(def.fileName);
|
|
387
|
-
const expr = getNodeFromPosition(defSource, def.lineEnd, def.posEnd);
|
|
392
|
+
const expr = getNodeFromPosition(defSource, def.lineEnd, def.posEnd, tsInstance);
|
|
388
393
|
if (!expr) {
|
|
389
394
|
return false;
|
|
390
395
|
}
|
|
@@ -392,28 +397,28 @@ function determineIfPropertyIsReadonly(node, sourceFile, tsInstance, client, get
|
|
|
392
397
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
393
398
|
while (parent) {
|
|
394
399
|
// For interface/type literal
|
|
395
|
-
if (
|
|
396
|
-
if (parent.modifiers?.some((mod) => mod.kind ===
|
|
400
|
+
if (tsInstance.isPropertySignature(parent)) {
|
|
401
|
+
if (parent.modifiers?.some((mod) => mod.kind === tsInstance.SyntaxKind.ReadonlyKeyword)) {
|
|
397
402
|
return true;
|
|
398
403
|
}
|
|
399
404
|
break;
|
|
400
405
|
}
|
|
401
|
-
else if (
|
|
406
|
+
else if (tsInstance.isAsExpression(parent)) {
|
|
402
407
|
// For definition, 'as const' should be readonly
|
|
403
|
-
if (parent.type.getText(
|
|
408
|
+
if (parent.type.getText(defSource) === 'const') {
|
|
404
409
|
return true;
|
|
405
410
|
}
|
|
406
411
|
}
|
|
407
|
-
else if (
|
|
412
|
+
else if (tsInstance.isEnumMember(parent)) {
|
|
408
413
|
// Enum member is readonly
|
|
409
414
|
return true;
|
|
410
415
|
}
|
|
411
|
-
else if (
|
|
416
|
+
else if (tsInstance.isVariableDeclaration(parent)) {
|
|
412
417
|
if (isParentNode(parent.name, expr, parent)) {
|
|
413
418
|
const p = parent.parent;
|
|
414
419
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
415
|
-
if (p &&
|
|
416
|
-
return (p.flags &
|
|
420
|
+
if (p && tsInstance.isVariableDeclarationList(p)) {
|
|
421
|
+
return (p.flags & tsInstance.NodeFlags.Const) !== 0;
|
|
417
422
|
}
|
|
418
423
|
}
|
|
419
424
|
// Reached to top level
|
|
@@ -431,32 +436,36 @@ export function isExpressionReadonly(node, sourceFile, tsInstance, client, getSo
|
|
|
431
436
|
if (node[READONLY_CACHE_SYMBOL] != null) {
|
|
432
437
|
return node[READONLY_CACHE_SYMBOL];
|
|
433
438
|
}
|
|
434
|
-
if (!
|
|
435
|
-
!
|
|
436
|
-
!
|
|
439
|
+
if (!tsInstance.isIdentifier(node) &&
|
|
440
|
+
!tsInstance.isPropertyAccessExpression(node) &&
|
|
441
|
+
!tsInstance.isElementAccessExpression(node)) {
|
|
437
442
|
return null;
|
|
438
443
|
}
|
|
439
|
-
|
|
444
|
+
let isReadonly;
|
|
445
|
+
if (tsInstance.isIdentifier(node)) {
|
|
440
446
|
if (
|
|
441
447
|
// eslint-disable-next-line @typescript-eslint/strict-boolean-expressions
|
|
442
448
|
node.parent &&
|
|
443
449
|
isUndefinedIdentifier(node, node.parent, sourceFile, tsInstance, client)) {
|
|
444
|
-
|
|
450
|
+
isReadonly = true;
|
|
445
451
|
}
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
+
else {
|
|
453
|
+
const hover = getHoverFromNode(node, sourceFile, tsInstance, client);
|
|
454
|
+
if (hover.startsWith('(alias)')) {
|
|
455
|
+
// Aliased symbols should be import-ed symbols, which are readonly
|
|
456
|
+
isReadonly = true;
|
|
457
|
+
}
|
|
458
|
+
else {
|
|
459
|
+
isReadonly = /^const\b/.test(hover);
|
|
452
460
|
}
|
|
453
461
|
}
|
|
454
|
-
const isReadonly = /^const\b/.test(hover);
|
|
455
|
-
node[READONLY_CACHE_SYMBOL] =
|
|
456
|
-
isReadonly;
|
|
457
|
-
return isReadonly;
|
|
458
462
|
}
|
|
459
|
-
|
|
463
|
+
else {
|
|
464
|
+
isReadonly = determineIfPropertyIsReadonly(node, sourceFile, tsInstance, client, getSourceFile);
|
|
465
|
+
}
|
|
466
|
+
node[READONLY_CACHE_SYMBOL] =
|
|
467
|
+
isReadonly;
|
|
468
|
+
return isReadonly;
|
|
460
469
|
// const typeString = nodeToTypeString(node, sourceFile, tsInstance, client);
|
|
461
470
|
// if (typeStringToLiteralType(typeString, tsInstance) === 0) {
|
|
462
471
|
// return null;
|
package/dist/version.d.mts
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
declare const _default: "0.10.
|
|
1
|
+
declare const _default: "0.10.1";
|
|
2
2
|
export default _default;
|
package/dist/version.mjs
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export default '0.10.
|
|
1
|
+
export default '0.10.1';
|