@macroforge/typescript-plugin 0.1.66 → 0.1.67

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/dist/index.js CHANGED
@@ -13,7 +13,7 @@
13
13
  * this plugin intercepts the call and returns the macro-expanded version instead.
14
14
  *
15
15
  * 2. **Position Mapping**: Since expanded code has different positions than the original,
16
- * the plugin maintains a {@link PositionMapper} for each file to translate positions
16
+ * the plugin maintains a PositionMapper for each file to translate positions
17
17
  * between original and expanded coordinates.
18
18
  *
19
19
  * 3. **Virtual .d.ts Files**: For each macro-containing file, the plugin generates a
@@ -44,13 +44,13 @@
44
44
  * ```
45
45
  *
46
46
  * @see {@link init} - The main plugin factory function
47
- * @see {@link PositionMapper} - Position mapping between original and expanded code
47
+ * @see PositionMapper from macroforge - Position mapping between original and expanded code
48
48
  * @module @macroforge/typescript-plugin
49
49
  */
50
- import { NativePlugin, __macroforgeGetManifest, loadConfig as nativeLoadConfig } from "macroforge";
51
- import { createRequire } from "module";
52
- import path from "path";
53
- import { parseMacroImportComments, getExternalMacroInfo, getExternalDecoratorInfo, loadMacroConfig, } from "@macroforge/shared";
50
+ import { __macroforgeGetManifest, loadConfig as nativeLoadConfig, NativePlugin } from 'macroforge';
51
+ import { createRequire } from 'node:module';
52
+ import path from 'node:path';
53
+ import { getExternalDecoratorInfo, getExternalMacroInfo, loadMacroConfig, parseMacroImportComments } from '@macroforge/shared';
54
54
  // Create require for external package loading
55
55
  const moduleRequire = createRequire(import.meta.url);
56
56
  /**
@@ -92,8 +92,8 @@ function getMacroManifest() {
92
92
  try {
93
93
  const manifest = __macroforgeGetManifest();
94
94
  macroManifestCache = {
95
- macros: new Map(manifest.macros.map(m => [m.name.toLowerCase(), m])),
96
- decorators: new Map(manifest.decorators.map(d => [d.export.toLowerCase(), d])),
95
+ macros: new Map(manifest.macros.map((m) => [m.name.toLowerCase(), m])),
96
+ decorators: new Map(manifest.decorators.map((d) => [d.export.toLowerCase(), d]))
97
97
  };
98
98
  return macroManifestCache;
99
99
  }
@@ -144,11 +144,11 @@ function findDeriveAtPosition(text, position) {
144
144
  const deriveStart = match.index;
145
145
  const deriveEnd = deriveStart + match[0].length;
146
146
  if (position >= deriveStart && position <= deriveEnd) {
147
- const argsStart = text.indexOf("(", deriveStart) + 1;
148
- const argsEnd = text.indexOf(")", argsStart);
147
+ const argsStart = text.indexOf('(', deriveStart) + 1;
148
+ const argsEnd = text.indexOf(')', argsStart);
149
149
  const argsContent = text.substring(argsStart, argsEnd);
150
150
  let currentPos = argsStart;
151
- const macroNames = argsContent.split(",");
151
+ const macroNames = argsContent.split(',');
152
152
  for (const rawName of macroNames) {
153
153
  const trimmedName = rawName.trim();
154
154
  const nameStartInArgs = rawName.indexOf(trimmedName);
@@ -191,7 +191,7 @@ function findDeriveKeywordAtPosition(text, position) {
191
191
  let match;
192
192
  while ((match = deriveKeywordPattern.exec(text)) !== null) {
193
193
  const start = match.index; // Position of @
194
- const end = start + "@derive".length;
194
+ const end = start + '@derive'.length;
195
195
  if (position >= start && position < end) {
196
196
  return { start, end };
197
197
  }
@@ -242,10 +242,10 @@ function findDecoratorAtPosition(text, position) {
242
242
  const nameEnd = nameStart + match[1].length;
243
243
  if (position >= atSign && position <= nameEnd) {
244
244
  // Skip @derive in JSDoc comments - let findDeriveAtPosition handle those
245
- if (match[1].toLowerCase() === "derive") {
245
+ if (match[1].toLowerCase() === 'derive') {
246
246
  const beforeMatch = text.substring(0, atSign);
247
- const lastCommentStart = beforeMatch.lastIndexOf("/**");
248
- const lastCommentEnd = beforeMatch.lastIndexOf("*/");
247
+ const lastCommentStart = beforeMatch.lastIndexOf('/**');
248
+ const lastCommentEnd = beforeMatch.lastIndexOf('*/');
249
249
  if (lastCommentStart > lastCommentEnd) {
250
250
  continue;
251
251
  }
@@ -289,7 +289,7 @@ function findEnclosingDeriveContext(text, position) {
289
289
  }
290
290
  if (lastMatch) {
291
291
  const macros = lastMatch[1]
292
- .split(",")
292
+ .split(',')
293
293
  .map((m) => m.trim())
294
294
  .filter(Boolean);
295
295
  return macros;
@@ -374,22 +374,22 @@ function getMacroHoverInfo(text, position, tsModule) {
374
374
  if (deriveKeyword) {
375
375
  return {
376
376
  kind: tsModule.ScriptElementKind.keyword,
377
- kindModifiers: "",
377
+ kindModifiers: '',
378
378
  textSpan: {
379
379
  start: deriveKeyword.start,
380
- length: deriveKeyword.end - deriveKeyword.start,
380
+ length: deriveKeyword.end - deriveKeyword.start
381
381
  },
382
- displayParts: [{ text: "@derive", kind: "keyword" }],
382
+ displayParts: [{ text: '@derive', kind: 'keyword' }],
383
383
  documentation: [
384
384
  {
385
- text: "Derive directive - applies compile-time macros to generate methods and implementations.\n\n" +
386
- "**Usage:** `/** @derive(MacroName, AnotherMacro) */`\n\n" +
387
- "**Built-in macros:** Debug, Clone, Default, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize\n\n" +
388
- "External macros can be imported using:\n" +
385
+ text: 'Derive directive - applies compile-time macros to generate methods and implementations.\n\n' +
386
+ '**Usage:** `/** @derive(MacroName, AnotherMacro) */`\n\n' +
387
+ '**Built-in macros:** Debug, Clone, Default, Hash, PartialEq, PartialOrd, Ord, Serialize, Deserialize\n\n' +
388
+ 'External macros can be imported using:\n' +
389
389
  '`/** import macro {Name} from "package"; */`',
390
- kind: "text",
391
- },
392
- ],
390
+ kind: 'text'
391
+ }
392
+ ]
393
393
  };
394
394
  }
395
395
  // Parse external macro imports for later use
@@ -402,19 +402,19 @@ function getMacroHoverInfo(text, position, tsModule) {
402
402
  if (macroInfo) {
403
403
  return {
404
404
  kind: tsModule.ScriptElementKind.functionElement,
405
- kindModifiers: "",
405
+ kindModifiers: '',
406
406
  textSpan: {
407
407
  start: deriveMatch.start,
408
- length: deriveMatch.end - deriveMatch.start,
408
+ length: deriveMatch.end - deriveMatch.start
409
409
  },
410
410
  displayParts: [
411
- { text: "@derive(", kind: "punctuation" },
412
- { text: macroInfo.name, kind: "functionName" },
413
- { text: ")", kind: "punctuation" },
411
+ { text: '@derive(', kind: 'punctuation' },
412
+ { text: macroInfo.name, kind: 'functionName' },
413
+ { text: ')', kind: 'punctuation' }
414
414
  ],
415
415
  documentation: macroInfo.description
416
- ? [{ text: macroInfo.description, kind: "text" }]
417
- : [],
416
+ ? [{ text: macroInfo.description, kind: 'text' }]
417
+ : []
418
418
  };
419
419
  }
420
420
  // 2b. Check external macro imports
@@ -424,39 +424,42 @@ function getMacroHoverInfo(text, position, tsModule) {
424
424
  const externalMacroInfo = getExternalMacroInfo(deriveMatch.macroName, modulePath, moduleRequire);
425
425
  const description = externalMacroInfo?.description
426
426
  ? externalMacroInfo.description
427
- : "This macro is loaded from an external package at compile time.";
427
+ : 'This macro is loaded from an external package at compile time.';
428
428
  return {
429
429
  kind: tsModule.ScriptElementKind.functionElement,
430
- kindModifiers: "external",
430
+ kindModifiers: 'external',
431
431
  textSpan: {
432
432
  start: deriveMatch.start,
433
- length: deriveMatch.end - deriveMatch.start,
433
+ length: deriveMatch.end - deriveMatch.start
434
434
  },
435
435
  displayParts: [
436
- { text: "@derive(", kind: "punctuation" },
437
- { text: externalMacroInfo?.name ?? deriveMatch.macroName, kind: "functionName" },
438
- { text: ")", kind: "punctuation" },
436
+ { text: '@derive(', kind: 'punctuation' },
437
+ {
438
+ text: externalMacroInfo?.name ?? deriveMatch.macroName,
439
+ kind: 'functionName'
440
+ },
441
+ { text: ')', kind: 'punctuation' }
439
442
  ],
440
443
  documentation: [
441
444
  {
442
445
  text: `**External macro** from \`${modulePath}\`\n\n${description}`,
443
- kind: "text",
444
- },
445
- ],
446
+ kind: 'text'
447
+ }
448
+ ]
446
449
  };
447
450
  }
448
451
  // 2c. Fallback for unknown/unrecognized macros
449
452
  return {
450
453
  kind: tsModule.ScriptElementKind.functionElement,
451
- kindModifiers: "",
454
+ kindModifiers: '',
452
455
  textSpan: {
453
456
  start: deriveMatch.start,
454
- length: deriveMatch.end - deriveMatch.start,
457
+ length: deriveMatch.end - deriveMatch.start
455
458
  },
456
459
  displayParts: [
457
- { text: "@derive(", kind: "punctuation" },
458
- { text: deriveMatch.macroName, kind: "functionName" },
459
- { text: ")", kind: "punctuation" },
460
+ { text: '@derive(', kind: 'punctuation' },
461
+ { text: deriveMatch.macroName, kind: 'functionName' },
462
+ { text: ')', kind: 'punctuation' }
460
463
  ],
461
464
  documentation: [
462
465
  {
@@ -464,9 +467,9 @@ function getMacroHoverInfo(text, position, tsModule) {
464
467
  "This macro is not in the built-in manifest. If it's a custom macro, " +
465
468
  "ensure it's imported using:\n\n" +
466
469
  `\`/** import macro {${deriveMatch.macroName}} from "your-package"; */\``,
467
- kind: "text",
468
- },
469
- ],
470
+ kind: 'text'
471
+ }
472
+ ]
470
473
  };
471
474
  }
472
475
  // 3. Check for @decorator patterns
@@ -477,18 +480,18 @@ function getMacroHoverInfo(text, position, tsModule) {
477
480
  if (macroInfo) {
478
481
  return {
479
482
  kind: tsModule.ScriptElementKind.functionElement,
480
- kindModifiers: "",
483
+ kindModifiers: '',
481
484
  textSpan: {
482
485
  start: decoratorMatch.start,
483
- length: decoratorMatch.end - decoratorMatch.start,
486
+ length: decoratorMatch.end - decoratorMatch.start
484
487
  },
485
488
  displayParts: [
486
- { text: "@", kind: "punctuation" },
487
- { text: macroInfo.name, kind: "functionName" },
489
+ { text: '@', kind: 'punctuation' },
490
+ { text: macroInfo.name, kind: 'functionName' }
488
491
  ],
489
492
  documentation: macroInfo.description
490
- ? [{ text: macroInfo.description, kind: "text" }]
491
- : [],
493
+ ? [{ text: macroInfo.description, kind: 'text' }]
494
+ : []
492
495
  };
493
496
  }
494
497
  // 3b. Check if it's a built-in decorator
@@ -496,16 +499,16 @@ function getMacroHoverInfo(text, position, tsModule) {
496
499
  if (decoratorInfo && decoratorInfo.docs) {
497
500
  return {
498
501
  kind: tsModule.ScriptElementKind.functionElement,
499
- kindModifiers: "",
502
+ kindModifiers: '',
500
503
  textSpan: {
501
504
  start: decoratorMatch.start,
502
- length: decoratorMatch.end - decoratorMatch.start,
505
+ length: decoratorMatch.end - decoratorMatch.start
503
506
  },
504
507
  displayParts: [
505
- { text: "@", kind: "punctuation" },
506
- { text: decoratorInfo.export, kind: "functionName" },
508
+ { text: '@', kind: 'punctuation' },
509
+ { text: decoratorInfo.export, kind: 'functionName' }
507
510
  ],
508
- documentation: [{ text: decoratorInfo.docs, kind: "text" }],
511
+ documentation: [{ text: decoratorInfo.docs, kind: 'text' }]
509
512
  };
510
513
  }
511
514
  // 3c. Check if this decorator is in a macro context (for external/custom decorators)
@@ -521,47 +524,50 @@ function getMacroHoverInfo(text, position, tsModule) {
521
524
  : null;
522
525
  const description = externalDecoratorInfo?.docs
523
526
  ? externalDecoratorInfo.docs
524
- : "This decorator configures field-level behavior for the macro.";
527
+ : 'This decorator configures field-level behavior for the macro.';
525
528
  return {
526
529
  kind: tsModule.ScriptElementKind.functionElement,
527
- kindModifiers: "external",
530
+ kindModifiers: 'external',
528
531
  textSpan: {
529
532
  start: decoratorMatch.start,
530
- length: decoratorMatch.end - decoratorMatch.start,
533
+ length: decoratorMatch.end - decoratorMatch.start
531
534
  },
532
535
  displayParts: [
533
- { text: "@", kind: "punctuation" },
534
- { text: externalDecoratorInfo?.export ?? decoratorMatch.name, kind: "functionName" },
536
+ { text: '@', kind: 'punctuation' },
537
+ {
538
+ text: externalDecoratorInfo?.export ?? decoratorMatch.name,
539
+ kind: 'functionName'
540
+ }
535
541
  ],
536
542
  documentation: [
537
543
  {
538
544
  text: `**Field decorator** from \`${likelySourceMacro}\` macro (\`${modulePath}\`)\n\n` +
539
545
  description,
540
- kind: "text",
541
- },
542
- ],
546
+ kind: 'text'
547
+ }
548
+ ]
543
549
  };
544
550
  }
545
551
  // Fallback: Generic decorator in macro context
546
552
  return {
547
553
  kind: tsModule.ScriptElementKind.functionElement,
548
- kindModifiers: "",
554
+ kindModifiers: '',
549
555
  textSpan: {
550
556
  start: decoratorMatch.start,
551
- length: decoratorMatch.end - decoratorMatch.start,
557
+ length: decoratorMatch.end - decoratorMatch.start
552
558
  },
553
559
  displayParts: [
554
- { text: "@", kind: "punctuation" },
555
- { text: decoratorMatch.name, kind: "functionName" },
560
+ { text: '@', kind: 'punctuation' },
561
+ { text: decoratorMatch.name, kind: 'functionName' }
556
562
  ],
557
563
  documentation: [
558
564
  {
559
565
  text: `**Field decorator:** ${decoratorMatch.name}\n\n` +
560
- `Used with @derive(${enclosingMacros.join(", ")}).\n` +
561
- "This decorator configures field-level behavior for the applied macros.",
562
- kind: "text",
563
- },
564
- ],
566
+ `Used with @derive(${enclosingMacros.join(', ')}).\n` +
567
+ 'This decorator configures field-level behavior for the applied macros.',
568
+ kind: 'text'
569
+ }
570
+ ]
565
571
  };
566
572
  }
567
573
  }
@@ -571,7 +577,7 @@ function getMacroHoverInfo(text, position, tsModule) {
571
577
  * File extensions that the plugin will process for macro expansion.
572
578
  * @internal
573
579
  */
574
- const FILE_EXTENSIONS = [".ts", ".tsx", ".svelte"];
580
+ const FILE_EXTENSIONS = ['.ts', '.tsx', '.svelte'];
575
581
  /**
576
582
  * Determines whether a file should be processed for macro expansion.
577
583
  *
@@ -599,12 +605,12 @@ const FILE_EXTENSIONS = [".ts", ".tsx", ".svelte"];
599
605
  */
600
606
  function shouldProcess(fileName) {
601
607
  const lower = fileName.toLowerCase();
602
- if (lower.includes("node_modules"))
608
+ if (lower.includes('node_modules'))
603
609
  return false;
604
610
  if (fileName.includes(`${path.sep}.macroforge${path.sep}`))
605
611
  return false;
606
612
  // Skip generated .d.ts files
607
- if (fileName.endsWith(".macroforge.d.ts"))
613
+ if (fileName.endsWith('.macroforge.d.ts'))
608
614
  return false;
609
615
  return FILE_EXTENSIONS.some((ext) => lower.endsWith(ext));
610
616
  }
@@ -636,7 +642,7 @@ function shouldProcess(fileName) {
636
642
  * ```
637
643
  */
638
644
  function hasMacroDirectives(text) {
639
- return (text.includes("@derive") ||
645
+ return (text.includes('@derive') ||
640
646
  /\/\*\*\s*@derive\s*\(/i.test(text) ||
641
647
  /\/\*\*\s*import\s+macro\b/i.test(text));
642
648
  }
@@ -773,7 +779,7 @@ function init(modules) {
773
779
  const result = nativeLoadConfig(content, filepath);
774
780
  return {
775
781
  ...result,
776
- returnTypes: "vanilla", // TODO: Extract from config if available
782
+ returnTypes: 'vanilla' // TODO: Extract from config if available
777
783
  };
778
784
  }
779
785
  catch {
@@ -782,7 +788,7 @@ function init(modules) {
782
788
  generateConvenienceConst: false,
783
789
  hasForeignTypes: false,
784
790
  foreignTypeCount: 0,
785
- returnTypes: "vanilla",
791
+ returnTypes: 'vanilla'
786
792
  };
787
793
  }
788
794
  };
@@ -804,11 +810,15 @@ function init(modules) {
804
810
  try {
805
811
  info.project.projectService.logger.info(`[macroforge] ${msg}`);
806
812
  }
807
- catch { }
813
+ catch {
814
+ // Ignore logging failures
815
+ }
808
816
  try {
809
817
  console.error(`[macroforge] ${msg}`);
810
818
  }
811
- catch { }
819
+ catch {
820
+ // Ignore logging failures
821
+ }
812
822
  };
813
823
  /**
814
824
  * Registers a virtual `.macroforge.d.ts` file with TypeScript's project service.
@@ -897,7 +907,7 @@ function init(modules) {
897
907
  }
898
908
  };
899
909
  }
900
- log("Plugin initialized");
910
+ log('Plugin initialized');
901
911
  /**
902
912
  * Processes a file through macro expansion via the native Rust plugin.
903
913
  *
@@ -941,9 +951,9 @@ function init(modules) {
941
951
  types: undefined,
942
952
  metadata: undefined,
943
953
  diagnostics: [],
944
- sourceMapping: undefined,
954
+ sourceMapping: undefined
945
955
  },
946
- code: content,
956
+ code: content
947
957
  };
948
958
  }
949
959
  try {
@@ -951,10 +961,10 @@ function init(modules) {
951
961
  const result = nativePlugin.processFile(fileName, content, {
952
962
  keepDecorators,
953
963
  version,
954
- configPath: macroConfig.configPath,
964
+ configPath: macroConfig.configPath
955
965
  });
956
966
  // Update virtual .d.ts files
957
- const virtualDtsFileName = fileName + ".macroforge.d.ts";
967
+ const virtualDtsFileName = fileName + '.macroforge.d.ts';
958
968
  if (result.types) {
959
969
  virtualDtsFiles.set(virtualDtsFileName, tsModule.ScriptSnapshot.fromString(result.types));
960
970
  ensureVirtualDtsRegistered(virtualDtsFileName);
@@ -969,17 +979,17 @@ function init(modules) {
969
979
  catch (e) {
970
980
  const errorMessage = e instanceof Error ? e.stack || e.message : String(e);
971
981
  log(`Plugin expansion failed for ${fileName}: ${errorMessage}`);
972
- virtualDtsFiles.delete(fileName + ".macroforge.d.ts");
973
- cleanupVirtualDts(fileName + ".macroforge.d.ts");
982
+ virtualDtsFiles.delete(fileName + '.macroforge.d.ts');
983
+ cleanupVirtualDts(fileName + '.macroforge.d.ts');
974
984
  return {
975
985
  result: {
976
986
  code: content,
977
987
  types: undefined,
978
988
  metadata: undefined,
979
989
  diagnostics: [],
980
- sourceMapping: undefined,
990
+ sourceMapping: undefined
981
991
  },
982
- code: content,
992
+ code: content
983
993
  };
984
994
  }
985
995
  }
@@ -995,12 +1005,13 @@ function init(modules) {
995
1005
  * them from the source file's version. This ensures TypeScript invalidates
996
1006
  * the virtual file when its source changes.
997
1007
  */
998
- const originalGetScriptVersion = info.languageServiceHost.getScriptVersion.bind(info.languageServiceHost);
1008
+ const originalGetScriptVersion = info.languageServiceHost.getScriptVersion
1009
+ .bind(info.languageServiceHost);
999
1010
  info.languageServiceHost.getScriptVersion = (fileName) => {
1000
1011
  try {
1001
1012
  if (virtualDtsFiles.has(fileName)) {
1002
1013
  // Virtual .d.ts files inherit version from their source file
1003
- const sourceFileName = fileName.replace(".macroforge.d.ts", "");
1014
+ const sourceFileName = fileName.replace('.macroforge.d.ts', '');
1004
1015
  return originalGetScriptVersion(sourceFileName);
1005
1016
  }
1006
1017
  return originalGetScriptVersion(fileName);
@@ -1073,7 +1084,8 @@ function init(modules) {
1073
1084
  * - Uses `processingFiles` Set to prevent infinite loops during expansion
1074
1085
  * - Version-based cache invalidation ensures fresh expansions on file changes
1075
1086
  */
1076
- const originalGetScriptSnapshot = info.languageServiceHost.getScriptSnapshot.bind(info.languageServiceHost);
1087
+ const originalGetScriptSnapshot = info.languageServiceHost.getScriptSnapshot
1088
+ .bind(info.languageServiceHost);
1077
1089
  info.languageServiceHost.getScriptSnapshot = (fileName) => {
1078
1090
  try {
1079
1091
  log(`getScriptSnapshot: ${fileName}`);
@@ -1096,7 +1108,7 @@ function init(modules) {
1096
1108
  if (!snapshot) {
1097
1109
  // Avoid tsserver crashes when a file was reported but no snapshot exists
1098
1110
  log(` -> no snapshot available for ${fileName}, returning empty snapshot`);
1099
- return tsModule.ScriptSnapshot.fromString("");
1111
+ return tsModule.ScriptSnapshot.fromString('');
1100
1112
  }
1101
1113
  const text = snapshot.getText(0, snapshot.getLength());
1102
1114
  // Scenario 4: No macro directives - return original
@@ -1124,7 +1136,7 @@ function init(modules) {
1124
1136
  // Cache for stable identity across TS requests
1125
1137
  snapshotCache.set(fileName, {
1126
1138
  version,
1127
- snapshot: expandedSnapshot,
1139
+ snapshot: expandedSnapshot
1128
1140
  });
1129
1141
  log(` -> returning expanded snapshot`);
1130
1142
  return expandedSnapshot;
@@ -1159,20 +1171,20 @@ function init(modules) {
1159
1171
  * @returns A plain object with diagnostic information
1160
1172
  */
1161
1173
  function toPlainDiagnostic(diag) {
1162
- const message = typeof diag.messageText === "string"
1174
+ const message = typeof diag.messageText === 'string'
1163
1175
  ? diag.messageText
1164
1176
  : diag.messageText.messageText;
1165
1177
  const category = diag.category === tsModule.DiagnosticCategory.Error
1166
- ? "error"
1178
+ ? 'error'
1167
1179
  : diag.category === tsModule.DiagnosticCategory.Warning
1168
- ? "warning"
1169
- : "message";
1180
+ ? 'warning'
1181
+ : 'message';
1170
1182
  return {
1171
1183
  start: diag.start,
1172
1184
  length: diag.length,
1173
1185
  message,
1174
1186
  code: diag.code,
1175
- category,
1187
+ category
1176
1188
  };
1177
1189
  }
1178
1190
  /**
@@ -1197,7 +1209,7 @@ function init(modules) {
1197
1209
  return {
1198
1210
  ...diag,
1199
1211
  start: mappedDiag.start,
1200
- length: mappedDiag.length,
1212
+ length: mappedDiag.length
1201
1213
  };
1202
1214
  });
1203
1215
  }
@@ -1218,7 +1230,8 @@ function init(modules) {
1218
1230
  * meaningful locations in the user's source code, even when the actual error
1219
1231
  * occurred in macro-generated code.
1220
1232
  */
1221
- const originalGetSemanticDiagnostics = info.languageService.getSemanticDiagnostics.bind(info.languageService);
1233
+ const originalGetSemanticDiagnostics = info.languageService
1234
+ .getSemanticDiagnostics.bind(info.languageService);
1222
1235
  info.languageService.getSemanticDiagnostics = (fileName) => {
1223
1236
  try {
1224
1237
  log(`getSemanticDiagnostics: ${fileName}`);
@@ -1262,7 +1275,7 @@ function init(modules) {
1262
1275
  return {
1263
1276
  ...diag,
1264
1277
  start: mapped.start,
1265
- length: mapped.length,
1278
+ length: mapped.length
1266
1279
  };
1267
1280
  })
1268
1281
  .filter((diag) => diag !== null);
@@ -1291,7 +1304,7 @@ function init(modules) {
1291
1304
  while ((match = deriveRegex.exec(text)) !== null) {
1292
1305
  const fullStart = match.index;
1293
1306
  const fullLength = match[0].length;
1294
- const argsStart = match.index + match[0].indexOf("(") + 1;
1307
+ const argsStart = match.index + match[0].indexOf('(') + 1;
1295
1308
  const argsText = match[1];
1296
1309
  // Parse individual macro names from the arguments
1297
1310
  const macros = [];
@@ -1301,7 +1314,7 @@ function init(modules) {
1301
1314
  macros.push({
1302
1315
  name: macroMatch[1],
1303
1316
  start: argsStart + macroMatch.index,
1304
- length: macroMatch[1].length,
1317
+ length: macroMatch[1].length
1305
1318
  });
1306
1319
  }
1307
1320
  deriveDecorators.push({ fullStart, fullLength, macros });
@@ -1319,7 +1332,7 @@ function init(modules) {
1319
1332
  return { start: macro.start, length: macro.length };
1320
1333
  return {
1321
1334
  start: firstDec.fullStart,
1322
- length: firstDec.fullLength,
1335
+ length: firstDec.fullLength
1323
1336
  };
1324
1337
  }
1325
1338
  return { start: 0, length: 7 };
@@ -1350,7 +1363,7 @@ function init(modules) {
1350
1363
  }
1351
1364
  // If macro name is "macro" (generic fallback) and there's exactly one macro,
1352
1365
  // use that macro's position
1353
- if ((macroName === "macro" || macroName === "") &&
1366
+ if ((macroName === 'macro' || macroName === '') &&
1354
1367
  nearestDecorator.macros.length === 1) {
1355
1368
  const onlyMacro = nearestDecorator.macros[0];
1356
1369
  return { start: onlyMacro.start, length: onlyMacro.length };
@@ -1358,7 +1371,7 @@ function init(modules) {
1358
1371
  // Fallback to full decorator if macro not found
1359
1372
  return {
1360
1373
  start: nearestDecorator.fullStart,
1361
- length: nearestDecorator.fullLength,
1374
+ length: nearestDecorator.fullLength
1362
1375
  };
1363
1376
  }
1364
1377
  return { start: 0, length: 7 };
@@ -1370,25 +1383,30 @@ function init(modules) {
1370
1383
  // If mapper didn't return a name, try to get it from the generated region
1371
1384
  if (!macroName) {
1372
1385
  const region = result.sourceMapping.generatedRegions.find((r) => diagStart >= r.start && diagStart < r.end);
1373
- macroName = region?.sourceMacro ?? "macro";
1386
+ macroName = region?.sourceMacro ?? 'macro';
1374
1387
  }
1375
1388
  // Extract just the macro name if it contains a path (e.g., "derive::Debug" -> "Debug")
1376
- const simpleMacroName = macroName.includes("::")
1377
- ? (macroName.split("::").pop() ?? macroName)
1389
+ const simpleMacroName = macroName.includes('::')
1390
+ ? (macroName.split('::').pop() ?? macroName)
1378
1391
  : macroName;
1379
1392
  log(` -> diagnostic at ${diagStart}, macroName="${macroName}", simpleMacroName="${simpleMacroName}"`);
1380
1393
  log(` -> generatedRegions: ${JSON.stringify(result.sourceMapping.generatedRegions)}`);
1381
- log(` -> deriveDecorators: ${JSON.stringify(deriveDecorators.map((d) => ({ fullStart: d.fullStart, macros: d.macros })))}`);
1394
+ log(` -> deriveDecorators: ${JSON.stringify(deriveDecorators.map((d) => ({
1395
+ fullStart: d.fullStart,
1396
+ macros: d.macros
1397
+ })))}`);
1382
1398
  const position = findMacroPosition(diagStart, simpleMacroName);
1383
1399
  log(` -> resolved position: ${JSON.stringify(position)}`);
1384
1400
  generatedDiagsAsMacro.push({
1385
1401
  file: info.languageService.getProgram()?.getSourceFile(fileName),
1386
1402
  start: position.start,
1387
1403
  length: position.length,
1388
- messageText: `[${simpleMacroName}] ${typeof diag.messageText === "string" ? diag.messageText : diag.messageText.messageText}`,
1404
+ messageText: `[${simpleMacroName}] ${typeof diag.messageText === 'string'
1405
+ ? diag.messageText
1406
+ : diag.messageText.messageText}`,
1389
1407
  category: diag.category,
1390
1408
  code: 9998, // Different code for generated code errors
1391
- source: "macroforge-generated",
1409
+ source: 'macroforge-generated'
1392
1410
  });
1393
1411
  }
1394
1412
  log(` -> converted ${generatedDiagsAsMacro.length} generated code diagnostics`);
@@ -1399,15 +1417,18 @@ function init(modules) {
1399
1417
  const decoratorStart = deriveMatch?.index ?? 0;
1400
1418
  const decoratorLength = deriveMatch?.[0].length ?? 7;
1401
1419
  for (const diag of generatedCodeDiagnostics) {
1402
- const macroName = effectiveMapper?.generatedBy(diag.start ?? 0) ?? "macro";
1420
+ const macroName = effectiveMapper?.generatedBy(diag.start ?? 0) ??
1421
+ 'macro';
1403
1422
  generatedDiagsAsMacro.push({
1404
1423
  file: info.languageService.getProgram()?.getSourceFile(fileName),
1405
1424
  start: decoratorStart,
1406
1425
  length: decoratorLength,
1407
- messageText: `[${macroName}] ${typeof diag.messageText === "string" ? diag.messageText : diag.messageText.messageText}`,
1426
+ messageText: `[${macroName}] ${typeof diag.messageText === 'string'
1427
+ ? diag.messageText
1428
+ : diag.messageText.messageText}`,
1408
1429
  category: diag.category,
1409
1430
  code: 9998, // Different code for generated code errors
1410
- source: "macroforge-generated",
1431
+ source: 'macroforge-generated'
1411
1432
  });
1412
1433
  }
1413
1434
  log(` -> converted ${generatedDiagsAsMacro.length} generated code diagnostics (fallback)`);
@@ -1416,9 +1437,9 @@ function init(modules) {
1416
1437
  return [...mappedDiagnostics, ...generatedDiagsAsMacro];
1417
1438
  }
1418
1439
  const macroDiagnostics = result.diagnostics.map((d) => {
1419
- const category = d.level === "error"
1440
+ const category = d.level === 'error'
1420
1441
  ? tsModule.DiagnosticCategory.Error
1421
- : d.level === "warning"
1442
+ : d.level === 'warning'
1422
1443
  ? tsModule.DiagnosticCategory.Warning
1423
1444
  : tsModule.DiagnosticCategory.Message;
1424
1445
  return {
@@ -1428,13 +1449,13 @@ function init(modules) {
1428
1449
  messageText: d.message,
1429
1450
  category,
1430
1451
  code: 9999, // Custom error code
1431
- source: "macroforge",
1452
+ source: 'macroforge'
1432
1453
  };
1433
1454
  });
1434
1455
  return [
1435
1456
  ...mappedDiagnostics,
1436
1457
  ...macroDiagnostics,
1437
- ...generatedDiagsAsMacro,
1458
+ ...generatedDiagsAsMacro
1438
1459
  ];
1439
1460
  }
1440
1461
  catch (e) {
@@ -1449,7 +1470,8 @@ function init(modules) {
1449
1470
  * Simpler than semantic diagnostics as it doesn't need to handle generated
1450
1471
  * code errors (syntax errors are in user code, not generated code).
1451
1472
  */
1452
- const originalGetSyntacticDiagnostics = info.languageService.getSyntacticDiagnostics.bind(info.languageService);
1473
+ const originalGetSyntacticDiagnostics = info.languageService
1474
+ .getSyntacticDiagnostics.bind(info.languageService);
1453
1475
  info.languageService.getSyntacticDiagnostics = (fileName) => {
1454
1476
  try {
1455
1477
  log(`getSyntacticDiagnostics: ${fileName}`);
@@ -1493,7 +1515,8 @@ function init(modules) {
1493
1515
  * If the hover would be in generated code, returns undefined to hide it
1494
1516
  * (prevents confusing users with hover info for code they can't see).
1495
1517
  */
1496
- const originalGetQuickInfoAtPosition = info.languageService.getQuickInfoAtPosition.bind(info.languageService);
1518
+ const originalGetQuickInfoAtPosition = info.languageService
1519
+ .getQuickInfoAtPosition.bind(info.languageService);
1497
1520
  info.languageService.getQuickInfoAtPosition = (fileName, position) => {
1498
1521
  try {
1499
1522
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -1528,8 +1551,8 @@ function init(modules) {
1528
1551
  ...result,
1529
1552
  textSpan: {
1530
1553
  start: mappedTextSpan.start,
1531
- length: mappedTextSpan.length,
1532
- },
1554
+ length: mappedTextSpan.length
1555
+ }
1533
1556
  };
1534
1557
  }
1535
1558
  catch (e) {
@@ -1544,7 +1567,8 @@ function init(modules) {
1544
1567
  * coordinates to get accurate completions that include generated methods,
1545
1568
  * then maps any replacement spans back to original coordinates.
1546
1569
  */
1547
- const originalGetCompletionsAtPosition = info.languageService.getCompletionsAtPosition.bind(info.languageService);
1570
+ const originalGetCompletionsAtPosition = info.languageService
1571
+ .getCompletionsAtPosition.bind(info.languageService);
1548
1572
  info.languageService.getCompletionsAtPosition = (fileName, position, options, formattingSettings) => {
1549
1573
  try {
1550
1574
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -1575,13 +1599,13 @@ function init(modules) {
1575
1599
  return { ...entry, replacementSpan: undefined }; // Remove invalid span
1576
1600
  return {
1577
1601
  ...entry,
1578
- replacementSpan: { start: mapped.start, length: mapped.length },
1602
+ replacementSpan: { start: mapped.start, length: mapped.length }
1579
1603
  };
1580
1604
  });
1581
1605
  return {
1582
1606
  ...result,
1583
1607
  optionalReplacementSpan: mappedOptionalSpan,
1584
- entries: mappedEntries,
1608
+ entries: mappedEntries
1585
1609
  };
1586
1610
  }
1587
1611
  catch (e) {
@@ -1601,7 +1625,8 @@ function init(modules) {
1601
1625
  * passed through unchanged. Only same-file definitions need mapping.
1602
1626
  * Definitions pointing to generated code are filtered out.
1603
1627
  */
1604
- const originalGetDefinitionAtPosition = info.languageService.getDefinitionAtPosition.bind(info.languageService);
1628
+ const originalGetDefinitionAtPosition = info.languageService
1629
+ .getDefinitionAtPosition.bind(info.languageService);
1605
1630
  info.languageService.getDefinitionAtPosition = (fileName, position) => {
1606
1631
  try {
1607
1632
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -1630,7 +1655,7 @@ function init(modules) {
1630
1655
  if (mapped) {
1631
1656
  acc.push({
1632
1657
  ...def,
1633
- textSpan: { start: mapped.start, length: mapped.length },
1658
+ textSpan: { start: mapped.start, length: mapped.length }
1634
1659
  });
1635
1660
  }
1636
1661
  return acc;
@@ -1648,7 +1673,8 @@ function init(modules) {
1648
1673
  * text span that was used to find the definition (useful for highlighting).
1649
1674
  * Maps both the bound span and definition spans.
1650
1675
  */
1651
- const originalGetDefinitionAndBoundSpan = info.languageService.getDefinitionAndBoundSpan.bind(info.languageService);
1676
+ const originalGetDefinitionAndBoundSpan = info.languageService
1677
+ .getDefinitionAndBoundSpan.bind(info.languageService);
1652
1678
  info.languageService.getDefinitionAndBoundSpan = (fileName, position) => {
1653
1679
  try {
1654
1680
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -1681,7 +1707,7 @@ function init(modules) {
1681
1707
  if (mapped) {
1682
1708
  acc.push({
1683
1709
  ...def,
1684
- textSpan: { start: mapped.start, length: mapped.length },
1710
+ textSpan: { start: mapped.start, length: mapped.length }
1685
1711
  });
1686
1712
  }
1687
1713
  return acc;
@@ -1689,9 +1715,9 @@ function init(modules) {
1689
1715
  return {
1690
1716
  textSpan: {
1691
1717
  start: mappedTextSpan.start,
1692
- length: mappedTextSpan.length,
1718
+ length: mappedTextSpan.length
1693
1719
  },
1694
- definitions: mappedDefinitions,
1720
+ definitions: mappedDefinitions
1695
1721
  };
1696
1722
  }
1697
1723
  catch (e) {
@@ -1706,7 +1732,8 @@ function init(modules) {
1706
1732
  * getDefinitionAtPosition but navigates to the type's definition
1707
1733
  * rather than the symbol's definition.
1708
1734
  */
1709
- const originalGetTypeDefinitionAtPosition = info.languageService.getTypeDefinitionAtPosition.bind(info.languageService);
1735
+ const originalGetTypeDefinitionAtPosition = info.languageService
1736
+ .getTypeDefinitionAtPosition.bind(info.languageService);
1710
1737
  info.languageService.getTypeDefinitionAtPosition = (fileName, position) => {
1711
1738
  try {
1712
1739
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -1734,7 +1761,7 @@ function init(modules) {
1734
1761
  if (mapped) {
1735
1762
  acc.push({
1736
1763
  ...def,
1737
- textSpan: { start: mapped.start, length: mapped.length },
1764
+ textSpan: { start: mapped.start, length: mapped.length }
1738
1765
  });
1739
1766
  }
1740
1767
  return acc;
@@ -1752,7 +1779,8 @@ function init(modules) {
1752
1779
  * finds all references in the expanded code, then maps each reference
1753
1780
  * span back to original positions. References in generated code are filtered.
1754
1781
  */
1755
- const originalGetReferencesAtPosition = info.languageService.getReferencesAtPosition.bind(info.languageService);
1782
+ const originalGetReferencesAtPosition = info.languageService
1783
+ .getReferencesAtPosition.bind(info.languageService);
1756
1784
  info.languageService.getReferencesAtPosition = (fileName, position) => {
1757
1785
  try {
1758
1786
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -1780,7 +1808,7 @@ function init(modules) {
1780
1808
  if (mapped) {
1781
1809
  acc.push({
1782
1810
  ...ref,
1783
- textSpan: { start: mapped.start, length: mapped.length },
1811
+ textSpan: { start: mapped.start, length: mapped.length }
1784
1812
  });
1785
1813
  }
1786
1814
  return acc;
@@ -1828,11 +1856,11 @@ function init(modules) {
1828
1856
  if (mapped) {
1829
1857
  acc.push({
1830
1858
  ...ref,
1831
- textSpan: { start: mapped.start, length: mapped.length },
1859
+ textSpan: { start: mapped.start, length: mapped.length }
1832
1860
  });
1833
1861
  }
1834
1862
  return acc;
1835
- }, []),
1863
+ }, [])
1836
1864
  }))
1837
1865
  .filter((s) => s.references.length > 0);
1838
1866
  }
@@ -1847,7 +1875,8 @@ function init(modules) {
1847
1875
  * Provides function signature help (parameter hints shown while typing
1848
1876
  * function arguments). Maps cursor position and the applicable span.
1849
1877
  */
1850
- const originalGetSignatureHelpItems = info.languageService.getSignatureHelpItems.bind(info.languageService);
1878
+ const originalGetSignatureHelpItems = info.languageService
1879
+ .getSignatureHelpItems.bind(info.languageService);
1851
1880
  info.languageService.getSignatureHelpItems = (fileName, position, options) => {
1852
1881
  try {
1853
1882
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -1869,8 +1898,8 @@ function init(modules) {
1869
1898
  ...result,
1870
1899
  applicableSpan: {
1871
1900
  start: mappedSpan.start,
1872
- length: mappedSpan.length,
1873
- },
1901
+ length: mappedSpan.length
1902
+ }
1874
1903
  };
1875
1904
  }
1876
1905
  catch (e) {
@@ -1918,12 +1947,12 @@ function init(modules) {
1918
1947
  if (!mappedSpan) {
1919
1948
  return {
1920
1949
  canRename: false,
1921
- localizedErrorMessage: "Cannot rename in generated code",
1950
+ localizedErrorMessage: 'Cannot rename in generated code'
1922
1951
  };
1923
1952
  }
1924
1953
  return {
1925
1954
  ...result,
1926
- triggerSpan: { start: mappedSpan.start, length: mappedSpan.length },
1955
+ triggerSpan: { start: mappedSpan.start, length: mappedSpan.length }
1927
1956
  };
1928
1957
  }
1929
1958
  catch (e) {
@@ -1942,7 +1971,8 @@ function init(modules) {
1942
1971
  * Uses a compatibility wrapper (callFindRenameLocations) to handle
1943
1972
  * different TypeScript version signatures.
1944
1973
  */
1945
- const originalFindRenameLocations = info.languageService.findRenameLocations.bind(info.languageService);
1974
+ const originalFindRenameLocations = info.languageService.findRenameLocations
1975
+ .bind(info.languageService);
1946
1976
  /**
1947
1977
  * Compatibility wrapper for findRenameLocations that handles both old
1948
1978
  * and new TypeScript API signatures.
@@ -1981,7 +2011,7 @@ function init(modules) {
1981
2011
  if (mapped) {
1982
2012
  acc.push({
1983
2013
  ...loc,
1984
- textSpan: { start: mapped.start, length: mapped.length },
2014
+ textSpan: { start: mapped.start, length: mapped.length }
1985
2015
  });
1986
2016
  }
1987
2017
  return acc;
@@ -1999,7 +2029,8 @@ function init(modules) {
1999
2029
  * click on a variable and see all usages highlighted). Maps highlight
2000
2030
  * spans back to original positions.
2001
2031
  */
2002
- const originalGetDocumentHighlights = info.languageService.getDocumentHighlights.bind(info.languageService);
2032
+ const originalGetDocumentHighlights = info.languageService
2033
+ .getDocumentHighlights.bind(info.languageService);
2003
2034
  info.languageService.getDocumentHighlights = (fileName, position, filesToSearch) => {
2004
2035
  try {
2005
2036
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -2030,11 +2061,11 @@ function init(modules) {
2030
2061
  if (mapped) {
2031
2062
  acc.push({
2032
2063
  ...span,
2033
- textSpan: { start: mapped.start, length: mapped.length },
2064
+ textSpan: { start: mapped.start, length: mapped.length }
2034
2065
  });
2035
2066
  }
2036
2067
  return acc;
2037
- }, []),
2068
+ }, [])
2038
2069
  }))
2039
2070
  .filter((h) => h.highlightSpans.length > 0);
2040
2071
  }
@@ -2049,7 +2080,8 @@ function init(modules) {
2049
2080
  * Provides "Go to Implementation" functionality. Similar to definition
2050
2081
  * but finds concrete implementations of abstract methods/interfaces.
2051
2082
  */
2052
- const originalGetImplementationAtPosition = info.languageService.getImplementationAtPosition.bind(info.languageService);
2083
+ const originalGetImplementationAtPosition = info.languageService
2084
+ .getImplementationAtPosition.bind(info.languageService);
2053
2085
  info.languageService.getImplementationAtPosition = (fileName, position) => {
2054
2086
  try {
2055
2087
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -2077,7 +2109,7 @@ function init(modules) {
2077
2109
  if (mapped) {
2078
2110
  acc.push({
2079
2111
  ...impl,
2080
- textSpan: { start: mapped.start, length: mapped.length },
2112
+ textSpan: { start: mapped.start, length: mapped.length }
2081
2113
  });
2082
2114
  }
2083
2115
  return acc;
@@ -2100,7 +2132,8 @@ function init(modules) {
2100
2132
  * could be problematic. Consider filtering or mapping fix edits in
2101
2133
  * future versions.
2102
2134
  */
2103
- const originalGetCodeFixesAtPosition = info.languageService.getCodeFixesAtPosition.bind(info.languageService);
2135
+ const originalGetCodeFixesAtPosition = info.languageService
2136
+ .getCodeFixesAtPosition.bind(info.languageService);
2104
2137
  info.languageService.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences) => {
2105
2138
  try {
2106
2139
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -2125,7 +2158,8 @@ function init(modules) {
2125
2158
  * Provides the document outline/structure tree (shown in the Outline
2126
2159
  * panel). Recursively maps all spans in the tree back to original positions.
2127
2160
  */
2128
- const originalGetNavigationTree = info.languageService.getNavigationTree.bind(info.languageService);
2161
+ const originalGetNavigationTree = info.languageService.getNavigationTree
2162
+ .bind(info.languageService);
2129
2163
  info.languageService.getNavigationTree = (fileName) => {
2130
2164
  try {
2131
2165
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -2141,9 +2175,7 @@ function init(modules) {
2141
2175
  function mapNavigationItem(item) {
2142
2176
  const mappedSpans = item.spans.map((span) => {
2143
2177
  const mapped = navMapper.mapSpanToOriginal(span.start, span.length);
2144
- return mapped
2145
- ? { start: mapped.start, length: mapped.length }
2146
- : span;
2178
+ return mapped ? { start: mapped.start, length: mapped.length } : span;
2147
2179
  });
2148
2180
  const mappedNameSpan = item.nameSpan
2149
2181
  ? (navMapper.mapSpanToOriginal(item.nameSpan.start, item.nameSpan.length) ?? item.nameSpan)
@@ -2154,7 +2186,7 @@ function init(modules) {
2154
2186
  nameSpan: mappedNameSpan
2155
2187
  ? { start: mappedNameSpan.start, length: mappedNameSpan.length }
2156
2188
  : undefined,
2157
- childItems: item.childItems?.map(mapNavigationItem),
2189
+ childItems: item.childItems?.map(mapNavigationItem)
2158
2190
  };
2159
2191
  }
2160
2192
  return mapNavigationItem(tree);
@@ -2170,7 +2202,8 @@ function init(modules) {
2170
2202
  * Provides code folding regions. Maps both the text span (what gets
2171
2203
  * folded) and hint span (what's shown when collapsed) back to original.
2172
2204
  */
2173
- const originalGetOutliningSpans = info.languageService.getOutliningSpans.bind(info.languageService);
2205
+ const originalGetOutliningSpans = info.languageService.getOutliningSpans
2206
+ .bind(info.languageService);
2174
2207
  info.languageService.getOutliningSpans = (fileName) => {
2175
2208
  try {
2176
2209
  if (virtualDtsFiles.has(fileName) || !shouldProcess(fileName)) {
@@ -2190,12 +2223,12 @@ function init(modules) {
2190
2223
  ...span,
2191
2224
  textSpan: {
2192
2225
  start: mappedTextSpan.start,
2193
- length: mappedTextSpan.length,
2226
+ length: mappedTextSpan.length
2194
2227
  },
2195
2228
  hintSpan: {
2196
2229
  start: mappedHintSpan.start,
2197
- length: mappedHintSpan.length,
2198
- },
2230
+ length: mappedHintSpan.length
2231
+ }
2199
2232
  };
2200
2233
  });
2201
2234
  }
@@ -2215,7 +2248,8 @@ function init(modules) {
2215
2248
  * This hook is conditional - provideInlayHints may not exist in older
2216
2249
  * TypeScript versions.
2217
2250
  */
2218
- const originalProvideInlayHints = info.languageService.provideInlayHints?.bind(info.languageService);
2251
+ const originalProvideInlayHints = info.languageService.provideInlayHints
2252
+ ?.bind(info.languageService);
2219
2253
  if (originalProvideInlayHints) {
2220
2254
  info.languageService.provideInlayHints = (fileName, span, preferences) => {
2221
2255
  try {
@@ -2245,8 +2279,8 @@ function init(modules) {
2245
2279
  return [
2246
2280
  {
2247
2281
  ...hint,
2248
- position: originalPos,
2249
- },
2282
+ position: originalPos
2283
+ }
2250
2284
  ];
2251
2285
  });
2252
2286
  }