@effect/language-service 0.66.1 → 0.67.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/cli.js CHANGED
@@ -945,7 +945,7 @@ var require_createProjectService = __commonJS({
945
945
  return mod && mod.__esModule ? mod : { "default": mod };
946
946
  };
947
947
  Object.defineProperty(exports2, "__esModule", { value: true });
948
- exports2.createProjectService = createProjectService5;
948
+ exports2.createProjectService = createProjectService6;
949
949
  var debug_1 = __importDefault(require_src());
950
950
  var getParsedConfigFileFromTSServer_js_1 = require_getParsedConfigFileFromTSServer();
951
951
  var DEFAULT_PROJECT_MATCHED_FILES_THRESHOLD = 8;
@@ -959,7 +959,7 @@ var require_createProjectService = __commonJS({
959
959
  var createStubFileWatcher = () => ({
960
960
  close: doNothing
961
961
  });
962
- function createProjectService5({ jsDocParsingMode, options: optionsRaw = {}, tsconfigRootDir } = {}) {
962
+ function createProjectService6({ jsDocParsingMode, options: optionsRaw = {}, tsconfigRootDir } = {}) {
963
963
  const options3 = {
964
964
  defaultProject: "tsconfig.json",
965
965
  ...optionsRaw
@@ -30211,7 +30211,7 @@ var runMain3 = runMain2;
30211
30211
  // package.json
30212
30212
  var package_default = {
30213
30213
  name: "@effect/language-service",
30214
- version: "0.66.1",
30214
+ version: "0.67.0",
30215
30215
  packageManager: "pnpm@8.11.0",
30216
30216
  publishConfig: {
30217
30217
  access: "public",
@@ -36405,9 +36405,20 @@ var effectFnOpportunity = createDiagnostic({
36405
36405
  if (!traceName) return yield* TypeParserIssue.issue;
36406
36406
  const opportunity = yield* pipe(
36407
36407
  tryParseGenOpportunity(node),
36408
- orElse15(
36409
- () => succeed17({ effectModuleName: sourceEffectModuleName, pipeArguments: [], generatorFunction: void 0 })
36410
- )
36408
+ orElse15(() => {
36409
+ if (ts.isArrowFunction(node) && !ts.isBlock(node.body)) {
36410
+ return TypeParserIssue.issue;
36411
+ }
36412
+ const body = ts.isArrowFunction(node) ? node.body : node.body;
36413
+ if (!body || !ts.isBlock(body) || body.statements.length <= 5) {
36414
+ return TypeParserIssue.issue;
36415
+ }
36416
+ return succeed17({
36417
+ effectModuleName: sourceEffectModuleName,
36418
+ pipeArguments: [],
36419
+ generatorFunction: void 0
36420
+ });
36421
+ })
36411
36422
  );
36412
36423
  return {
36413
36424
  node,
@@ -41358,6 +41369,523 @@ var patch9 = make58(
41358
41369
  )
41359
41370
  );
41360
41371
 
41372
+ // src/cli/quickfixes.ts
41373
+ var import_project_service5 = __toESM(require_dist2());
41374
+
41375
+ // src/cli/setup/text-diff-renderer.ts
41376
+ function getLines(text10) {
41377
+ return text10.split("\n");
41378
+ }
41379
+ function getLineAndCharacterOfPosition(text10, position) {
41380
+ const lines3 = text10.split("\n");
41381
+ let currentPos = 0;
41382
+ for (let lineIndex = 0; lineIndex < lines3.length; lineIndex++) {
41383
+ const lineLength = lines3[lineIndex].length;
41384
+ const lineEndPos = currentPos + lineLength;
41385
+ if (position <= lineEndPos) {
41386
+ return { line: lineIndex, character: position - currentPos };
41387
+ }
41388
+ currentPos = lineEndPos + 1;
41389
+ }
41390
+ const lastLineIndex = lines3.length - 1;
41391
+ return { line: lastLineIndex, character: lines3[lastLineIndex]?.length ?? 0 };
41392
+ }
41393
+ function renderLine(lineNum, symbol3, text10, color3) {
41394
+ const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
41395
+ return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
41396
+ }
41397
+ function renderPlainTextChange(text10, textChange) {
41398
+ const startPos = textChange.span.start;
41399
+ const endPos = textChange.span.start + textChange.span.length;
41400
+ const startLineAndChar = getLineAndCharacterOfPosition(text10, startPos);
41401
+ const endLineAndChar = getLineAndCharacterOfPosition(text10, endPos);
41402
+ const startLine = startLineAndChar.line;
41403
+ const endLine = endLineAndChar.line;
41404
+ const startCol = startLineAndChar.character;
41405
+ const endCol = endLineAndChar.character;
41406
+ const lines3 = [];
41407
+ const allLines = getLines(text10);
41408
+ if (startLine > 0) {
41409
+ const contextBefore = allLines[startLine - 1];
41410
+ lines3.push(renderLine(startLine, "|", contextBefore, blackBright2));
41411
+ }
41412
+ if (startLine <= endLine) {
41413
+ const firstLineText = allLines[startLine];
41414
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41415
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41416
+ if (hasNonWhitespaceKept) {
41417
+ lines3.push(renderLine(startLine + 1, "|", keptBeforeDeletion, blackBright2));
41418
+ }
41419
+ const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
41420
+ if (deletedOnFirstLine.length > 0) {
41421
+ const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
41422
+ lines3.push(renderLine(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
41423
+ }
41424
+ }
41425
+ for (let i = startLine + 1; i < endLine; i++) {
41426
+ const lineText = allLines[i];
41427
+ if (lineText !== void 0) {
41428
+ lines3.push(renderLine(void 0, "-", lineText, red4));
41429
+ }
41430
+ }
41431
+ if (endLine > startLine) {
41432
+ const lastLineText = allLines[endLine];
41433
+ const deletedOnLastLine = lastLineText.slice(0, endCol);
41434
+ if (deletedOnLastLine.length > 0) {
41435
+ lines3.push(renderLine(void 0, "-", deletedOnLastLine, red4));
41436
+ }
41437
+ }
41438
+ if (textChange.newText.length > 0) {
41439
+ const newTextLines = textChange.newText.split("\n");
41440
+ const firstLineText = allLines[startLine];
41441
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41442
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41443
+ const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
41444
+ for (let i = 0; i < newTextLines.length; i++) {
41445
+ const newLine = newTextLines[i];
41446
+ if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
41447
+ continue;
41448
+ }
41449
+ const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
41450
+ lines3.push(renderLine(void 0, "+", `${padding}${newLine}`, green3));
41451
+ }
41452
+ }
41453
+ let alignmentForKeptPart = 0;
41454
+ if (textChange.newText.length > 0) {
41455
+ const newTextLines = textChange.newText.split("\n");
41456
+ const lastNewLine = newTextLines[newTextLines.length - 1];
41457
+ if (lastNewLine.length === 0 && newTextLines.length > 1) {
41458
+ alignmentForKeptPart = 0;
41459
+ } else {
41460
+ const firstLineText = allLines[startLine];
41461
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41462
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41463
+ if (hasNonWhitespaceKept) {
41464
+ if (newTextLines.length === 1) {
41465
+ alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
41466
+ } else {
41467
+ alignmentForKeptPart = lastNewLine.length;
41468
+ }
41469
+ } else {
41470
+ alignmentForKeptPart = lastNewLine.length;
41471
+ }
41472
+ }
41473
+ } else {
41474
+ alignmentForKeptPart = endCol;
41475
+ }
41476
+ if (endLine > startLine) {
41477
+ const lastLineText = allLines[endLine];
41478
+ const keptAfterDeletion = lastLineText.slice(endCol);
41479
+ if (keptAfterDeletion.trim().length > 0) {
41480
+ const alignment = " ".repeat(alignmentForKeptPart);
41481
+ lines3.push(renderLine(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
41482
+ }
41483
+ } else if (startLine === endLine) {
41484
+ const firstLineText = allLines[startLine];
41485
+ const keptAfterDeletion = firstLineText.slice(endCol);
41486
+ if (keptAfterDeletion.trim().length > 0) {
41487
+ const alignment = " ".repeat(alignmentForKeptPart);
41488
+ lines3.push(renderLine(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
41489
+ }
41490
+ }
41491
+ if (endLine + 1 < allLines.length) {
41492
+ const contextAfter = allLines[endLine + 1];
41493
+ lines3.push(renderLine(endLine + 2, "|", contextAfter, blackBright2));
41494
+ }
41495
+ return lines3;
41496
+ }
41497
+ function renderPlainTextFileChanges(text10, textChanges) {
41498
+ const lines3 = [];
41499
+ const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
41500
+ for (let i = 0; i < sortedChanges.length; i++) {
41501
+ const change = sortedChanges[i];
41502
+ const changeLines = renderPlainTextChange(text10, change);
41503
+ for (const line4 of changeLines) {
41504
+ lines3.push(line4);
41505
+ }
41506
+ if (i < sortedChanges.length - 1) {
41507
+ lines3.push(text3(""));
41508
+ }
41509
+ }
41510
+ return lines3;
41511
+ }
41512
+
41513
+ // src/cli/setup/diff-renderer.ts
41514
+ function getLines2(text10) {
41515
+ return text10.split("\n");
41516
+ }
41517
+ function renderLine2(lineNum, symbol3, text10, color3) {
41518
+ const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
41519
+ return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
41520
+ }
41521
+ function renderTextChange(sourceFile, textChange) {
41522
+ const startPos = textChange.span.start;
41523
+ const endPos = textChange.span.start + textChange.span.length;
41524
+ const startLineAndChar = sourceFile.getLineAndCharacterOfPosition(startPos);
41525
+ const endLineAndChar = sourceFile.getLineAndCharacterOfPosition(endPos);
41526
+ const startLine = startLineAndChar.line;
41527
+ const endLine = endLineAndChar.line;
41528
+ const startCol = startLineAndChar.character;
41529
+ const endCol = endLineAndChar.character;
41530
+ const lines3 = [];
41531
+ const allLines = getLines2(sourceFile.text);
41532
+ if (startLine > 0) {
41533
+ const contextBefore = allLines[startLine - 1];
41534
+ lines3.push(renderLine2(startLine, "|", contextBefore, blackBright2));
41535
+ }
41536
+ if (startLine <= endLine) {
41537
+ const firstLineText = allLines[startLine];
41538
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41539
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41540
+ if (hasNonWhitespaceKept) {
41541
+ lines3.push(renderLine2(startLine + 1, "|", keptBeforeDeletion, blackBright2));
41542
+ }
41543
+ const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
41544
+ if (deletedOnFirstLine.length > 0) {
41545
+ const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
41546
+ lines3.push(renderLine2(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
41547
+ }
41548
+ }
41549
+ for (let i = startLine + 1; i < endLine; i++) {
41550
+ const lineText = allLines[i];
41551
+ if (lineText !== void 0) {
41552
+ lines3.push(renderLine2(void 0, "-", lineText, red4));
41553
+ }
41554
+ }
41555
+ if (endLine > startLine) {
41556
+ const lastLineText = allLines[endLine];
41557
+ const deletedOnLastLine = lastLineText.slice(0, endCol);
41558
+ if (deletedOnLastLine.length > 0) {
41559
+ lines3.push(renderLine2(void 0, "-", deletedOnLastLine, red4));
41560
+ }
41561
+ }
41562
+ if (textChange.newText.length > 0) {
41563
+ const newTextLines = textChange.newText.split("\n");
41564
+ const firstLineText = allLines[startLine];
41565
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41566
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41567
+ const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
41568
+ for (let i = 0; i < newTextLines.length; i++) {
41569
+ const newLine = newTextLines[i];
41570
+ if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
41571
+ continue;
41572
+ }
41573
+ const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
41574
+ lines3.push(renderLine2(void 0, "+", `${padding}${newLine}`, green3));
41575
+ }
41576
+ }
41577
+ let alignmentForKeptPart = 0;
41578
+ if (textChange.newText.length > 0) {
41579
+ const newTextLines = textChange.newText.split("\n");
41580
+ const lastNewLine = newTextLines[newTextLines.length - 1];
41581
+ if (lastNewLine.length === 0 && newTextLines.length > 1) {
41582
+ alignmentForKeptPart = 0;
41583
+ } else {
41584
+ const firstLineText = allLines[startLine];
41585
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41586
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41587
+ if (hasNonWhitespaceKept) {
41588
+ if (newTextLines.length === 1) {
41589
+ alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
41590
+ } else {
41591
+ alignmentForKeptPart = lastNewLine.length;
41592
+ }
41593
+ } else {
41594
+ alignmentForKeptPart = lastNewLine.length;
41595
+ }
41596
+ }
41597
+ } else {
41598
+ alignmentForKeptPart = endCol;
41599
+ }
41600
+ if (endLine > startLine) {
41601
+ const lastLineText = allLines[endLine];
41602
+ const keptAfterDeletion = lastLineText.slice(endCol);
41603
+ if (keptAfterDeletion.trim().length > 0) {
41604
+ const alignment = " ".repeat(alignmentForKeptPart);
41605
+ lines3.push(renderLine2(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
41606
+ }
41607
+ } else if (startLine === endLine) {
41608
+ const firstLineText = allLines[startLine];
41609
+ const keptAfterDeletion = firstLineText.slice(endCol);
41610
+ if (keptAfterDeletion.trim().length > 0) {
41611
+ const alignment = " ".repeat(alignmentForKeptPart);
41612
+ lines3.push(renderLine2(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
41613
+ }
41614
+ }
41615
+ if (endLine + 1 < allLines.length) {
41616
+ const contextAfter = allLines[endLine + 1];
41617
+ lines3.push(renderLine2(endLine + 2, "|", contextAfter, blackBright2));
41618
+ }
41619
+ return lines3;
41620
+ }
41621
+ function renderFileChanges(sourceFile, textChanges) {
41622
+ const lines3 = [];
41623
+ const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
41624
+ for (let i = 0; i < sortedChanges.length; i++) {
41625
+ const change = sortedChanges[i];
41626
+ const changeLines = renderTextChange(sourceFile, change);
41627
+ for (const line4 of changeLines) {
41628
+ lines3.push(line4);
41629
+ }
41630
+ if (i < sortedChanges.length - 1) {
41631
+ lines3.push(text3(""));
41632
+ }
41633
+ }
41634
+ return lines3;
41635
+ }
41636
+ var renderCodeActions = (result, assessmentState) => gen2(function* () {
41637
+ if (result.codeActions.length === 0) {
41638
+ const noChanges = annotate2(
41639
+ text3("No changes needed - your configuration is already up to date!"),
41640
+ green3
41641
+ );
41642
+ const noChangesStr = noChanges.pipe(render3({ style: "pretty" }));
41643
+ yield* log3(noChangesStr);
41644
+ return;
41645
+ }
41646
+ const sourceFiles = [
41647
+ assessmentState.packageJson.sourceFile,
41648
+ assessmentState.tsconfig.sourceFile
41649
+ ];
41650
+ if (isSome2(assessmentState.vscodeSettings)) {
41651
+ sourceFiles.push(assessmentState.vscodeSettings.value.sourceFile);
41652
+ }
41653
+ const plainTextFiles = [];
41654
+ if (isSome2(assessmentState.agentsMd)) {
41655
+ plainTextFiles.push({
41656
+ path: assessmentState.agentsMd.value.path,
41657
+ text: assessmentState.agentsMd.value.text
41658
+ });
41659
+ }
41660
+ if (isSome2(assessmentState.claudeMd)) {
41661
+ plainTextFiles.push({
41662
+ path: assessmentState.claudeMd.value.path,
41663
+ text: assessmentState.claudeMd.value.text
41664
+ });
41665
+ }
41666
+ for (const codeAction of result.codeActions) {
41667
+ for (const fileChange of codeAction.changes) {
41668
+ const sourceFile = sourceFiles.find((sf) => sf.fileName === fileChange.fileName);
41669
+ const plainTextFile = plainTextFiles.find((pf) => pf.path === fileChange.fileName);
41670
+ const header = vsep2([
41671
+ empty32,
41672
+ annotate2(text3(codeAction.description), bold2),
41673
+ annotate2(text3(fileChange.fileName), cyan4),
41674
+ empty32
41675
+ ]);
41676
+ const headerStr = header.pipe(render3({ style: "pretty" }));
41677
+ yield* log3(headerStr);
41678
+ if (sourceFile) {
41679
+ const diffLines = renderFileChanges(sourceFile, fileChange.textChanges);
41680
+ const diff8 = vsep2(diffLines);
41681
+ const diffStr = diff8.pipe(render3({ style: "pretty" }));
41682
+ yield* log3(diffStr);
41683
+ } else if (plainTextFile) {
41684
+ const diffLines = renderPlainTextFileChanges(plainTextFile.text, fileChange.textChanges);
41685
+ const diff8 = vsep2(diffLines);
41686
+ const diffStr = diff8.pipe(render3({ style: "pretty" }));
41687
+ yield* log3(diffStr);
41688
+ } else {
41689
+ const noticeStr = text3(" (file will be modified)").pipe(render3({ style: "pretty" }));
41690
+ yield* log3(noticeStr);
41691
+ }
41692
+ }
41693
+ }
41694
+ if (result.messages.length > 0) {
41695
+ yield* log3("");
41696
+ for (const message of result.messages) {
41697
+ const messageDoc = message.includes("WARNING") ? annotate2(text3(message), yellow3) : text3(message);
41698
+ const messageStr = messageDoc.pipe(render3({ style: "pretty" }));
41699
+ yield* log3(messageStr);
41700
+ }
41701
+ }
41702
+ });
41703
+
41704
+ // src/cli/quickfixes.ts
41705
+ var isSkipFix = (fixName) => fixName.endsWith("_skipNextLine") || fixName.endsWith("_skipFile");
41706
+ var renderQuickFix = (sourceFile, fix) => {
41707
+ const lines3 = [];
41708
+ lines3.push(empty32);
41709
+ lines3.push(
41710
+ cat2(
41711
+ cat2(
41712
+ cat2(
41713
+ annotate2(text3(" Fix: "), bold2),
41714
+ annotate2(text3(fix.fixName), cyan4)
41715
+ ),
41716
+ text3(" - ")
41717
+ ),
41718
+ text3(fix.description)
41719
+ )
41720
+ );
41721
+ lines3.push(annotate2(text3(" " + "\u2500".repeat(60)), blackBright2));
41722
+ for (const fileChange of fix.changes) {
41723
+ if (fileChange.fileName === sourceFile.fileName) {
41724
+ for (const textChange of fileChange.textChanges) {
41725
+ const diffLines = renderTextChange(sourceFile, textChange);
41726
+ for (const diffLine of diffLines) {
41727
+ lines3.push(cat2(text3(" "), diffLine));
41728
+ }
41729
+ }
41730
+ }
41731
+ }
41732
+ return vsep2(lines3);
41733
+ };
41734
+ var renderDiagnosticWithFixes = (sourceFile, info2, tsInstance) => {
41735
+ const lines3 = [];
41736
+ const { character, line: line4 } = tsInstance.getLineAndCharacterOfPosition(sourceFile, info2.diagnostic.start);
41737
+ const locationStr = `${sourceFile.fileName}:${line4 + 1}:${character + 1}`;
41738
+ lines3.push(
41739
+ cat2(
41740
+ cat2(
41741
+ cat2(
41742
+ cat2(
41743
+ annotate2(text3(locationStr), cyan4),
41744
+ text3(" ")
41745
+ ),
41746
+ annotate2(text3(`effect(${info2.diagnostic.ruleName})`), yellow3)
41747
+ ),
41748
+ text3(": ")
41749
+ ),
41750
+ text3(info2.diagnostic.messageText)
41751
+ )
41752
+ );
41753
+ for (const fix of info2.fixes) {
41754
+ lines3.push(renderQuickFix(sourceFile, fix));
41755
+ }
41756
+ lines3.push(empty32);
41757
+ return vsep2(lines3);
41758
+ };
41759
+ var BATCH_SIZE4 = 50;
41760
+ var quickfixes = make58(
41761
+ "quickfixes",
41762
+ {
41763
+ file: file3("file").pipe(
41764
+ optional4,
41765
+ withDescription3("The full path of the file to check for quick fixes.")
41766
+ ),
41767
+ project: file3("project").pipe(
41768
+ optional4,
41769
+ withDescription3("The full path of the project tsconfig.json file to check for quick fixes.")
41770
+ )
41771
+ },
41772
+ fn("quickfixes")(function* ({ file: file5, project: project3 }) {
41773
+ const path2 = yield* Path2;
41774
+ const tsInstance = yield* TypeScriptContext;
41775
+ const filesToCheck = isSome2(project3) ? yield* getFileNamesInTsConfig(project3.value) : /* @__PURE__ */ new Set();
41776
+ if (isSome2(file5)) {
41777
+ filesToCheck.add(path2.resolve(file5.value));
41778
+ }
41779
+ if (filesToCheck.size === 0) {
41780
+ return yield* new NoFilesToCheckError();
41781
+ }
41782
+ let totalDiagnosticsWithFixes = 0;
41783
+ for (const batch of chunksOf(filesToCheck, BATCH_SIZE4)) {
41784
+ const { service: service3 } = (0, import_project_service5.createProjectService)({ options: { loadTypeScriptPlugins: false } });
41785
+ for (const filePath of batch) {
41786
+ service3.openClientFile(filePath);
41787
+ try {
41788
+ const scriptInfo = service3.getScriptInfo(filePath);
41789
+ if (!scriptInfo) continue;
41790
+ const projectInfo = scriptInfo.getDefaultProject();
41791
+ const languageService = projectInfo.getLanguageService(true);
41792
+ const program = languageService.getProgram();
41793
+ if (!program) continue;
41794
+ const sourceFile = program.getSourceFile(filePath);
41795
+ if (!sourceFile) continue;
41796
+ const pluginConfig = extractEffectLspOptions(program.getCompilerOptions());
41797
+ if (!pluginConfig) continue;
41798
+ const result = pipe(
41799
+ getSemanticDiagnosticsWithCodeFixes(diagnostics, sourceFile),
41800
+ nanoLayer3,
41801
+ nanoLayer2,
41802
+ nanoLayer,
41803
+ provideService7(TypeCheckerApi, program.getTypeChecker()),
41804
+ provideService7(TypeScriptProgram, program),
41805
+ provideService7(TypeScriptApi, tsInstance),
41806
+ provideService7(
41807
+ LanguageServicePluginOptions,
41808
+ { ...parse4(pluginConfig), diagnosticsName: false }
41809
+ ),
41810
+ run9,
41811
+ getOrElse(() => ({ diagnostics: [], codeFixes: [] }))
41812
+ );
41813
+ const diagnosticMap = /* @__PURE__ */ new Map();
41814
+ for (const diagnostic of result.diagnostics) {
41815
+ if (diagnostic.start === void 0) continue;
41816
+ const key = `${diagnostic.start}-${diagnostic.start + (diagnostic.length ?? 0)}-${diagnostic.code}`;
41817
+ const ruleName = Object.values(diagnostics).find((_) => _.code === diagnostic.code)?.name ?? `unknown(${diagnostic.code})`;
41818
+ if (!diagnosticMap.has(key)) {
41819
+ diagnosticMap.set(key, {
41820
+ diagnostic: {
41821
+ start: diagnostic.start,
41822
+ end: diagnostic.start + (diagnostic.length ?? 0),
41823
+ messageText: tsInstance.flattenDiagnosticMessageText(diagnostic.messageText, "\n"),
41824
+ code: diagnostic.code,
41825
+ ruleName
41826
+ },
41827
+ fixes: []
41828
+ });
41829
+ }
41830
+ }
41831
+ const formatContext = tsInstance.formatting.getFormatContext(
41832
+ tsInstance.getDefaultFormatCodeSettings(),
41833
+ { getNewLine: () => "\n" }
41834
+ );
41835
+ for (const codeFix of result.codeFixes) {
41836
+ if (isSkipFix(codeFix.fixName)) continue;
41837
+ const key = `${codeFix.start}-${codeFix.end}-${codeFix.code}`;
41838
+ const info2 = diagnosticMap.get(key);
41839
+ if (!info2) continue;
41840
+ const changes2 = tsInstance.textChanges.ChangeTracker.with(
41841
+ {
41842
+ formatContext,
41843
+ host: { getNewLine: () => "\n" },
41844
+ preferences: {}
41845
+ },
41846
+ (changeTracker) => pipe(
41847
+ codeFix.apply,
41848
+ provideService7(ChangeTracker, changeTracker),
41849
+ run9
41850
+ )
41851
+ );
41852
+ info2.fixes.push({
41853
+ fixName: codeFix.fixName,
41854
+ description: codeFix.description,
41855
+ changes: changes2
41856
+ });
41857
+ }
41858
+ const diagnosticsWithFixes = Array.from(diagnosticMap.values()).filter(
41859
+ (info2) => info2.fixes.length > 0
41860
+ );
41861
+ if (diagnosticsWithFixes.length === 0) continue;
41862
+ diagnosticsWithFixes.sort((a, b) => a.diagnostic.start - b.diagnostic.start);
41863
+ totalDiagnosticsWithFixes += diagnosticsWithFixes.length;
41864
+ for (const info2 of diagnosticsWithFixes) {
41865
+ const doc = renderDiagnosticWithFixes(sourceFile, info2, tsInstance);
41866
+ yield* log3(doc.pipe(render3({ style: "pretty" })));
41867
+ }
41868
+ } finally {
41869
+ service3.closeClientFile(filePath);
41870
+ }
41871
+ }
41872
+ yield* yieldNow4();
41873
+ }
41874
+ if (totalDiagnosticsWithFixes === 0) {
41875
+ yield* log3("No quick fixes available.");
41876
+ } else {
41877
+ yield* log3(
41878
+ annotate2(
41879
+ text3(`Found ${totalDiagnosticsWithFixes} diagnostic(s) with quick fixes.`),
41880
+ bold2
41881
+ ).pipe(render3({ style: "pretty" }))
41882
+ );
41883
+ }
41884
+ })
41885
+ ).pipe(
41886
+ withDescription6("Shows diagnostics with available quick fixes and their proposed changes.")
41887
+ );
41888
+
41361
41889
  // node_modules/.pnpm/@effect+cli@0.73.0_@effect+platform@0.94.1_@effect+printer-ansi@0.47.0_@effect+printer@0.47.0_effect@3.19.14/node_modules/@effect/cli/dist/esm/internal/prompt/confirm.js
41362
41890
  var renderBeep7 = /* @__PURE__ */ render3(beep3, {
41363
41891
  style: "pretty"
@@ -42434,335 +42962,6 @@ var computeVSCodeSettingsChanges = (current, target) => {
42434
42962
  });
42435
42963
  };
42436
42964
 
42437
- // src/cli/setup/text-diff-renderer.ts
42438
- function getLines(text10) {
42439
- return text10.split("\n");
42440
- }
42441
- function getLineAndCharacterOfPosition(text10, position) {
42442
- const lines3 = text10.split("\n");
42443
- let currentPos = 0;
42444
- for (let lineIndex = 0; lineIndex < lines3.length; lineIndex++) {
42445
- const lineLength = lines3[lineIndex].length;
42446
- const lineEndPos = currentPos + lineLength;
42447
- if (position <= lineEndPos) {
42448
- return { line: lineIndex, character: position - currentPos };
42449
- }
42450
- currentPos = lineEndPos + 1;
42451
- }
42452
- const lastLineIndex = lines3.length - 1;
42453
- return { line: lastLineIndex, character: lines3[lastLineIndex]?.length ?? 0 };
42454
- }
42455
- function renderLine(lineNum, symbol3, text10, color3) {
42456
- const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
42457
- return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
42458
- }
42459
- function renderPlainTextChange(text10, textChange) {
42460
- const startPos = textChange.span.start;
42461
- const endPos = textChange.span.start + textChange.span.length;
42462
- const startLineAndChar = getLineAndCharacterOfPosition(text10, startPos);
42463
- const endLineAndChar = getLineAndCharacterOfPosition(text10, endPos);
42464
- const startLine = startLineAndChar.line;
42465
- const endLine = endLineAndChar.line;
42466
- const startCol = startLineAndChar.character;
42467
- const endCol = endLineAndChar.character;
42468
- const lines3 = [];
42469
- const allLines = getLines(text10);
42470
- if (startLine > 0) {
42471
- const contextBefore = allLines[startLine - 1];
42472
- lines3.push(renderLine(startLine, "|", contextBefore, blackBright2));
42473
- }
42474
- if (startLine <= endLine) {
42475
- const firstLineText = allLines[startLine];
42476
- const keptBeforeDeletion = firstLineText.slice(0, startCol);
42477
- const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
42478
- if (hasNonWhitespaceKept) {
42479
- lines3.push(renderLine(startLine + 1, "|", keptBeforeDeletion, blackBright2));
42480
- }
42481
- const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
42482
- if (deletedOnFirstLine.length > 0) {
42483
- const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
42484
- lines3.push(renderLine(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
42485
- }
42486
- }
42487
- for (let i = startLine + 1; i < endLine; i++) {
42488
- const lineText = allLines[i];
42489
- if (lineText !== void 0) {
42490
- lines3.push(renderLine(void 0, "-", lineText, red4));
42491
- }
42492
- }
42493
- if (endLine > startLine) {
42494
- const lastLineText = allLines[endLine];
42495
- const deletedOnLastLine = lastLineText.slice(0, endCol);
42496
- if (deletedOnLastLine.length > 0) {
42497
- lines3.push(renderLine(void 0, "-", deletedOnLastLine, red4));
42498
- }
42499
- }
42500
- if (textChange.newText.length > 0) {
42501
- const newTextLines = textChange.newText.split("\n");
42502
- const firstLineText = allLines[startLine];
42503
- const keptBeforeDeletion = firstLineText.slice(0, startCol);
42504
- const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
42505
- const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
42506
- for (let i = 0; i < newTextLines.length; i++) {
42507
- const newLine = newTextLines[i];
42508
- if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
42509
- continue;
42510
- }
42511
- const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
42512
- lines3.push(renderLine(void 0, "+", `${padding}${newLine}`, green3));
42513
- }
42514
- }
42515
- let alignmentForKeptPart = 0;
42516
- if (textChange.newText.length > 0) {
42517
- const newTextLines = textChange.newText.split("\n");
42518
- const lastNewLine = newTextLines[newTextLines.length - 1];
42519
- if (lastNewLine.length === 0 && newTextLines.length > 1) {
42520
- alignmentForKeptPart = 0;
42521
- } else {
42522
- const firstLineText = allLines[startLine];
42523
- const keptBeforeDeletion = firstLineText.slice(0, startCol);
42524
- const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
42525
- if (hasNonWhitespaceKept) {
42526
- if (newTextLines.length === 1) {
42527
- alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
42528
- } else {
42529
- alignmentForKeptPart = lastNewLine.length;
42530
- }
42531
- } else {
42532
- alignmentForKeptPart = lastNewLine.length;
42533
- }
42534
- }
42535
- } else {
42536
- alignmentForKeptPart = endCol;
42537
- }
42538
- if (endLine > startLine) {
42539
- const lastLineText = allLines[endLine];
42540
- const keptAfterDeletion = lastLineText.slice(endCol);
42541
- if (keptAfterDeletion.trim().length > 0) {
42542
- const alignment = " ".repeat(alignmentForKeptPart);
42543
- lines3.push(renderLine(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
42544
- }
42545
- } else if (startLine === endLine) {
42546
- const firstLineText = allLines[startLine];
42547
- const keptAfterDeletion = firstLineText.slice(endCol);
42548
- if (keptAfterDeletion.trim().length > 0) {
42549
- const alignment = " ".repeat(alignmentForKeptPart);
42550
- lines3.push(renderLine(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
42551
- }
42552
- }
42553
- if (endLine + 1 < allLines.length) {
42554
- const contextAfter = allLines[endLine + 1];
42555
- lines3.push(renderLine(endLine + 2, "|", contextAfter, blackBright2));
42556
- }
42557
- return lines3;
42558
- }
42559
- function renderPlainTextFileChanges(text10, textChanges) {
42560
- const lines3 = [];
42561
- const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
42562
- for (let i = 0; i < sortedChanges.length; i++) {
42563
- const change = sortedChanges[i];
42564
- const changeLines = renderPlainTextChange(text10, change);
42565
- for (const line4 of changeLines) {
42566
- lines3.push(line4);
42567
- }
42568
- if (i < sortedChanges.length - 1) {
42569
- lines3.push(text3(""));
42570
- }
42571
- }
42572
- return lines3;
42573
- }
42574
-
42575
- // src/cli/setup/diff-renderer.ts
42576
- function getLines2(text10) {
42577
- return text10.split("\n");
42578
- }
42579
- function renderLine2(lineNum, symbol3, text10, color3) {
42580
- const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
42581
- return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
42582
- }
42583
- function renderTextChange(sourceFile, textChange) {
42584
- const startPos = textChange.span.start;
42585
- const endPos = textChange.span.start + textChange.span.length;
42586
- const startLineAndChar = sourceFile.getLineAndCharacterOfPosition(startPos);
42587
- const endLineAndChar = sourceFile.getLineAndCharacterOfPosition(endPos);
42588
- const startLine = startLineAndChar.line;
42589
- const endLine = endLineAndChar.line;
42590
- const startCol = startLineAndChar.character;
42591
- const endCol = endLineAndChar.character;
42592
- const lines3 = [];
42593
- const allLines = getLines2(sourceFile.text);
42594
- if (startLine > 0) {
42595
- const contextBefore = allLines[startLine - 1];
42596
- lines3.push(renderLine2(startLine, "|", contextBefore, blackBright2));
42597
- }
42598
- if (startLine <= endLine) {
42599
- const firstLineText = allLines[startLine];
42600
- const keptBeforeDeletion = firstLineText.slice(0, startCol);
42601
- const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
42602
- if (hasNonWhitespaceKept) {
42603
- lines3.push(renderLine2(startLine + 1, "|", keptBeforeDeletion, blackBright2));
42604
- }
42605
- const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
42606
- if (deletedOnFirstLine.length > 0) {
42607
- const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
42608
- lines3.push(renderLine2(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
42609
- }
42610
- }
42611
- for (let i = startLine + 1; i < endLine; i++) {
42612
- const lineText = allLines[i];
42613
- if (lineText !== void 0) {
42614
- lines3.push(renderLine2(void 0, "-", lineText, red4));
42615
- }
42616
- }
42617
- if (endLine > startLine) {
42618
- const lastLineText = allLines[endLine];
42619
- const deletedOnLastLine = lastLineText.slice(0, endCol);
42620
- if (deletedOnLastLine.length > 0) {
42621
- lines3.push(renderLine2(void 0, "-", deletedOnLastLine, red4));
42622
- }
42623
- }
42624
- if (textChange.newText.length > 0) {
42625
- const newTextLines = textChange.newText.split("\n");
42626
- const firstLineText = allLines[startLine];
42627
- const keptBeforeDeletion = firstLineText.slice(0, startCol);
42628
- const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
42629
- const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
42630
- for (let i = 0; i < newTextLines.length; i++) {
42631
- const newLine = newTextLines[i];
42632
- if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
42633
- continue;
42634
- }
42635
- const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
42636
- lines3.push(renderLine2(void 0, "+", `${padding}${newLine}`, green3));
42637
- }
42638
- }
42639
- let alignmentForKeptPart = 0;
42640
- if (textChange.newText.length > 0) {
42641
- const newTextLines = textChange.newText.split("\n");
42642
- const lastNewLine = newTextLines[newTextLines.length - 1];
42643
- if (lastNewLine.length === 0 && newTextLines.length > 1) {
42644
- alignmentForKeptPart = 0;
42645
- } else {
42646
- const firstLineText = allLines[startLine];
42647
- const keptBeforeDeletion = firstLineText.slice(0, startCol);
42648
- const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
42649
- if (hasNonWhitespaceKept) {
42650
- if (newTextLines.length === 1) {
42651
- alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
42652
- } else {
42653
- alignmentForKeptPart = lastNewLine.length;
42654
- }
42655
- } else {
42656
- alignmentForKeptPart = lastNewLine.length;
42657
- }
42658
- }
42659
- } else {
42660
- alignmentForKeptPart = endCol;
42661
- }
42662
- if (endLine > startLine) {
42663
- const lastLineText = allLines[endLine];
42664
- const keptAfterDeletion = lastLineText.slice(endCol);
42665
- if (keptAfterDeletion.trim().length > 0) {
42666
- const alignment = " ".repeat(alignmentForKeptPart);
42667
- lines3.push(renderLine2(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
42668
- }
42669
- } else if (startLine === endLine) {
42670
- const firstLineText = allLines[startLine];
42671
- const keptAfterDeletion = firstLineText.slice(endCol);
42672
- if (keptAfterDeletion.trim().length > 0) {
42673
- const alignment = " ".repeat(alignmentForKeptPart);
42674
- lines3.push(renderLine2(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
42675
- }
42676
- }
42677
- if (endLine + 1 < allLines.length) {
42678
- const contextAfter = allLines[endLine + 1];
42679
- lines3.push(renderLine2(endLine + 2, "|", contextAfter, blackBright2));
42680
- }
42681
- return lines3;
42682
- }
42683
- function renderFileChanges(sourceFile, textChanges) {
42684
- const lines3 = [];
42685
- const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
42686
- for (let i = 0; i < sortedChanges.length; i++) {
42687
- const change = sortedChanges[i];
42688
- const changeLines = renderTextChange(sourceFile, change);
42689
- for (const line4 of changeLines) {
42690
- lines3.push(line4);
42691
- }
42692
- if (i < sortedChanges.length - 1) {
42693
- lines3.push(text3(""));
42694
- }
42695
- }
42696
- return lines3;
42697
- }
42698
- var renderCodeActions = (result, assessmentState) => gen2(function* () {
42699
- if (result.codeActions.length === 0) {
42700
- const noChanges = annotate2(
42701
- text3("No changes needed - your configuration is already up to date!"),
42702
- green3
42703
- );
42704
- const noChangesStr = noChanges.pipe(render3({ style: "pretty" }));
42705
- yield* log3(noChangesStr);
42706
- return;
42707
- }
42708
- const sourceFiles = [
42709
- assessmentState.packageJson.sourceFile,
42710
- assessmentState.tsconfig.sourceFile
42711
- ];
42712
- if (isSome2(assessmentState.vscodeSettings)) {
42713
- sourceFiles.push(assessmentState.vscodeSettings.value.sourceFile);
42714
- }
42715
- const plainTextFiles = [];
42716
- if (isSome2(assessmentState.agentsMd)) {
42717
- plainTextFiles.push({
42718
- path: assessmentState.agentsMd.value.path,
42719
- text: assessmentState.agentsMd.value.text
42720
- });
42721
- }
42722
- if (isSome2(assessmentState.claudeMd)) {
42723
- plainTextFiles.push({
42724
- path: assessmentState.claudeMd.value.path,
42725
- text: assessmentState.claudeMd.value.text
42726
- });
42727
- }
42728
- for (const codeAction of result.codeActions) {
42729
- for (const fileChange of codeAction.changes) {
42730
- const sourceFile = sourceFiles.find((sf) => sf.fileName === fileChange.fileName);
42731
- const plainTextFile = plainTextFiles.find((pf) => pf.path === fileChange.fileName);
42732
- const header = vsep2([
42733
- empty32,
42734
- annotate2(text3(codeAction.description), bold2),
42735
- annotate2(text3(fileChange.fileName), cyan4),
42736
- empty32
42737
- ]);
42738
- const headerStr = header.pipe(render3({ style: "pretty" }));
42739
- yield* log3(headerStr);
42740
- if (sourceFile) {
42741
- const diffLines = renderFileChanges(sourceFile, fileChange.textChanges);
42742
- const diff8 = vsep2(diffLines);
42743
- const diffStr = diff8.pipe(render3({ style: "pretty" }));
42744
- yield* log3(diffStr);
42745
- } else if (plainTextFile) {
42746
- const diffLines = renderPlainTextFileChanges(plainTextFile.text, fileChange.textChanges);
42747
- const diff8 = vsep2(diffLines);
42748
- const diffStr = diff8.pipe(render3({ style: "pretty" }));
42749
- yield* log3(diffStr);
42750
- } else {
42751
- const noticeStr = text3(" (file will be modified)").pipe(render3({ style: "pretty" }));
42752
- yield* log3(noticeStr);
42753
- }
42754
- }
42755
- }
42756
- if (result.messages.length > 0) {
42757
- yield* log3("");
42758
- for (const message of result.messages) {
42759
- const messageDoc = message.includes("WARNING") ? annotate2(text3(message), yellow3) : text3(message);
42760
- const messageStr = messageDoc.pipe(render3({ style: "pretty" }));
42761
- yield* log3(messageStr);
42762
- }
42763
- }
42764
- });
42765
-
42766
42965
  // src/cli/setup/errors.ts
42767
42966
  var PackageJsonNotFoundError = class extends TaggedError("PackageJsonNotFoundError") {
42768
42967
  get message() {
@@ -43404,7 +43603,7 @@ var cliCommand = make58(
43404
43603
  "effect-language-service",
43405
43604
  {},
43406
43605
  () => log3("Please select a command or run --help.")
43407
- ).pipe(withSubcommands3([setup, patch9, unpatch, check2, diagnostics2, codegen, overview, layerInfo]));
43606
+ ).pipe(withSubcommands3([setup, patch9, unpatch, check2, diagnostics2, quickfixes, codegen, overview, layerInfo]));
43408
43607
  var main = run8(cliCommand, {
43409
43608
  name: "effect-language-service",
43410
43609
  version: package_default.version