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 CHANGED
@@ -1,5 +1,9 @@
1
1
  # Changelog
2
2
 
3
+ ## v0.10.1
4
+
5
+ - Fix for transformation with langage-server
6
+
3
7
  ## v0.10.0
4
8
 
5
9
  - Fix to avoid hosting parameters
@@ -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 workspaceFolder = path.dirname(path.resolve(cwd, project));
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
- } | null;
27
+ }>;
27
28
  sendReplaceText(fileName: string, lineStart: number, posStart: number, lineEnd: number, posEnd: number, text: string): void;
28
29
  exit(): void;
29
30
  }
@@ -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 null;
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
- // eslint-disable-next-line @typescript-eslint/no-unsafe-argument
233
- const defFileName = fileURLToPath(loc.uri);
234
- return {
235
- fileName: defFileName,
236
- lineStart: loc.range.start.line,
237
- posStart: loc.range.start.character,
238
- lineEnd: loc.range.end.line,
239
- posEnd: loc.range.end.character,
240
- };
241
- /* eslint-enable @typescript-eslint/no-unsafe-assignment */
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
- ts.visitEachChild(node, (n) => visit(n, node), undefined);
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 (node && tsInstance.isIdentifier(node) && isFunctionLike(hover)) {
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 def = client.getTypeDefitition(fileName, pos.line, pos.column);
201
- if (!def) {
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 (/^(["']).*\1$/.test(typeString)) {
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 (ts.isElementAccessExpression(node)) {
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 (ts.isPropertySignature(parent)) {
396
- if (parent.modifiers?.some((mod) => mod.kind === ts.SyntaxKind.ReadonlyKeyword)) {
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 (ts.isAsExpression(parent)) {
406
+ else if (tsInstance.isAsExpression(parent)) {
402
407
  // For definition, 'as const' should be readonly
403
- if (parent.type.getText(sourceFile) === 'const') {
408
+ if (parent.type.getText(defSource) === 'const') {
404
409
  return true;
405
410
  }
406
411
  }
407
- else if (ts.isEnumMember(parent)) {
412
+ else if (tsInstance.isEnumMember(parent)) {
408
413
  // Enum member is readonly
409
414
  return true;
410
415
  }
411
- else if (ts.isVariableDeclaration(parent)) {
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 && ts.isVariableDeclarationList(p)) {
416
- return (p.flags & ts.NodeFlags.Const) !== 0;
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 (!ts.isIdentifier(node) &&
435
- !ts.isPropertyAccessExpression(node) &&
436
- !ts.isElementAccessExpression(node)) {
439
+ if (!tsInstance.isIdentifier(node) &&
440
+ !tsInstance.isPropertyAccessExpression(node) &&
441
+ !tsInstance.isElementAccessExpression(node)) {
437
442
  return null;
438
443
  }
439
- if (ts.isIdentifier(node)) {
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
- return true;
450
+ isReadonly = true;
445
451
  }
446
- let hover = getHoverFromNode(node, sourceFile, tsInstance, client);
447
- if (hover.startsWith('(alias)')) {
448
- hover = hover.slice(7).trim();
449
- const lines = hover.split(/\r?\n/g);
450
- if (lines.length >= 2 && /^import\b/.test(lines[1].trim())) {
451
- return true;
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
- return determineIfPropertyIsReadonly(node, sourceFile, tsInstance, client, getSourceFile);
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;
@@ -1,2 +1,2 @@
1
- declare const _default: "0.10.0";
1
+ declare const _default: "0.10.1";
2
2
  export default _default;
package/dist/version.mjs CHANGED
@@ -1 +1 @@
1
- export default '0.10.0';
1
+ export default '0.10.1';
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ts-const-value-transformer",
3
- "version": "0.10.0",
3
+ "version": "0.10.1",
4
4
  "engines": {
5
5
  "node": ">=20.19.3"
6
6
  },