@effect/language-service 0.66.1 → 0.68.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
@@ -26161,6 +26161,7 @@ var text7 = (name) => makeSingle(name, empty2(), text6);
26161
26161
  var getHelp3 = (self) => getHelpInternal2(self);
26162
26162
  var getUsage = (self) => getUsageInternal(self);
26163
26163
  var map29 = /* @__PURE__ */ dual(2, (self, f) => makeMap(self, (a) => right2(f(a))));
26164
+ var mapEffect5 = /* @__PURE__ */ dual(2, (self, f) => makeMap(self, f));
26164
26165
  var optional3 = (self) => withDefault2(map29(self, some2), none2());
26165
26166
  var orElse14 = /* @__PURE__ */ dual(2, (self, that) => orElseEither4(self, that).pipe(map29(merge)));
26166
26167
  var orElseEither4 = /* @__PURE__ */ dual(2, (self, that) => makeOrElse(self, that));
@@ -27122,6 +27123,7 @@ var directory2 = directory;
27122
27123
  var file3 = file2;
27123
27124
  var integer5 = integer4;
27124
27125
  var text8 = text7;
27126
+ var mapEffect6 = mapEffect5;
27125
27127
  var optional4 = optional3;
27126
27128
  var repeated4 = repeated3;
27127
27129
  var withDefault3 = withDefault2;
@@ -27173,8 +27175,8 @@ var none11 = /* @__PURE__ */ (() => {
27173
27175
  })();
27174
27176
  var getHelp4 = (self) => getHelpInternal3(self);
27175
27177
  var getUsage2 = (self) => getUsageInternal2(self);
27176
- var map30 = /* @__PURE__ */ dual(2, (self, f) => mapEffect6(self, (a) => succeed7(f(a))));
27177
- var mapEffect6 = /* @__PURE__ */ dual(2, (self, f) => makeMap2(self, f));
27178
+ var map30 = /* @__PURE__ */ dual(2, (self, f) => mapEffect7(self, (a) => succeed7(f(a))));
27179
+ var mapEffect7 = /* @__PURE__ */ dual(2, (self, f) => makeMap2(self, f));
27178
27180
  var validate5 = /* @__PURE__ */ dual(3, (self, args3, config2) => validateInternal2(self, args3, config2));
27179
27181
  var wizard3 = /* @__PURE__ */ dual(2, (self, config2) => wizardInternal3(self, config2));
27180
27182
  var allTupled2 = (arg) => {
@@ -27615,8 +27617,8 @@ var getFishCompletions4 = (self, executable) => getFishCompletionsInternal(self,
27615
27617
  var getZshCompletions4 = (self, executable) => getZshCompletionsInternal(self, executable);
27616
27618
  var getSubcommands = (self) => fromIterable6(getSubcommandsInternal(self));
27617
27619
  var getUsage3 = (self) => getUsageInternal3(self);
27618
- var map32 = /* @__PURE__ */ dual(2, (self, f) => mapEffect7(self, (a) => right2(f(a))));
27619
- var mapEffect7 = /* @__PURE__ */ dual(2, (self, f) => {
27620
+ var map32 = /* @__PURE__ */ dual(2, (self, f) => mapEffect8(self, (a) => right2(f(a))));
27621
+ var mapEffect8 = /* @__PURE__ */ dual(2, (self, f) => {
27620
27622
  const op = Object.create(proto23);
27621
27623
  op._tag = "Map";
27622
27624
  op.command = self;
@@ -27921,7 +27923,7 @@ var withDescriptionInternal = (self, description) => {
27921
27923
  return op;
27922
27924
  }
27923
27925
  case "Map": {
27924
- return mapEffect7(withDescriptionInternal(self.command, description), self.f);
27926
+ return mapEffect8(withDescriptionInternal(self.command, description), self.f);
27925
27927
  }
27926
27928
  case "Subcommands": {
27927
27929
  const op = Object.create(proto23);
@@ -28147,6 +28149,7 @@ var helpRequestedError = (command) => {
28147
28149
 
28148
28150
  // 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/ValidationError.js
28149
28151
  var helpRequested = helpRequestedError;
28152
+ var invalidValue2 = invalidValue;
28150
28153
 
28151
28154
  // node_modules/.pnpm/effect@3.19.14/node_modules/effect/dist/esm/Logger.js
28152
28155
  var withMinimumLogLevel2 = withMinimumLogLevel;
@@ -30211,7 +30214,7 @@ var runMain3 = runMain2;
30211
30214
  // package.json
30212
30215
  var package_default = {
30213
30216
  name: "@effect/language-service",
30214
- version: "0.66.1",
30217
+ version: "0.68.0",
30215
30218
  packageManager: "pnpm@8.11.0",
30216
30219
  publishConfig: {
30217
30220
  access: "public",
@@ -36405,9 +36408,20 @@ var effectFnOpportunity = createDiagnostic({
36405
36408
  if (!traceName) return yield* TypeParserIssue.issue;
36406
36409
  const opportunity = yield* pipe(
36407
36410
  tryParseGenOpportunity(node),
36408
- orElse15(
36409
- () => succeed17({ effectModuleName: sourceEffectModuleName, pipeArguments: [], generatorFunction: void 0 })
36410
- )
36411
+ orElse15(() => {
36412
+ if (ts.isArrowFunction(node) && !ts.isBlock(node.body)) {
36413
+ return TypeParserIssue.issue;
36414
+ }
36415
+ const body = ts.isArrowFunction(node) ? node.body : node.body;
36416
+ if (!body || !ts.isBlock(body) || body.statements.length <= 5) {
36417
+ return TypeParserIssue.issue;
36418
+ }
36419
+ return succeed17({
36420
+ effectModuleName: sourceEffectModuleName,
36421
+ pipeArguments: [],
36422
+ generatorFunction: void 0
36423
+ });
36424
+ })
36411
36425
  );
36412
36426
  return {
36413
36427
  node,
@@ -37019,6 +37033,69 @@ var importFromBarrel = createDiagnostic({
37019
37033
  })
37020
37034
  });
37021
37035
 
37036
+ // src/diagnostics/instanceOfSchema.ts
37037
+ var instanceOfSchema = createDiagnostic({
37038
+ name: "instanceOfSchema",
37039
+ code: 45,
37040
+ description: "Suggests using Schema.is instead of instanceof for Effect Schema types",
37041
+ severity: "off",
37042
+ apply: fn2("instanceOfSchema.apply")(function* (sourceFile, report) {
37043
+ const ts = yield* service2(TypeScriptApi);
37044
+ const typeParser = yield* service2(TypeParser);
37045
+ const typeCheckerUtils = yield* service2(TypeCheckerUtils);
37046
+ const nodeToVisit = [];
37047
+ const appendNodeToVisit = (node) => {
37048
+ nodeToVisit.push(node);
37049
+ return void 0;
37050
+ };
37051
+ ts.forEachChild(sourceFile, appendNodeToVisit);
37052
+ while (nodeToVisit.length > 0) {
37053
+ const node = nodeToVisit.shift();
37054
+ if (ts.isBinaryExpression(node) && node.operatorToken.kind === ts.SyntaxKind.InstanceOfKeyword) {
37055
+ const leftExpr = node.left;
37056
+ const rightExpr = node.right;
37057
+ const rightType = typeCheckerUtils.getTypeAtLocation(rightExpr);
37058
+ if (!rightType) {
37059
+ ts.forEachChild(node, appendNodeToVisit);
37060
+ continue;
37061
+ }
37062
+ const isSchemaType = yield* pipe(
37063
+ typeParser.effectSchemaType(rightType, rightExpr),
37064
+ option5
37065
+ );
37066
+ if (isSchemaType._tag === "Some") {
37067
+ report({
37068
+ location: node,
37069
+ messageText: "Consider using Schema.is instead of instanceof for Effect Schema types.",
37070
+ fixes: [{
37071
+ fixName: "instanceOfSchema_fix",
37072
+ description: "Replace with Schema.is",
37073
+ apply: gen3(function* () {
37074
+ const changeTracker = yield* service2(ChangeTracker);
37075
+ const schemaIsCall = ts.factory.createCallExpression(
37076
+ ts.factory.createPropertyAccessExpression(
37077
+ ts.factory.createIdentifier("Schema"),
37078
+ "is"
37079
+ ),
37080
+ void 0,
37081
+ [rightExpr]
37082
+ );
37083
+ const fullCall = ts.factory.createCallExpression(
37084
+ schemaIsCall,
37085
+ void 0,
37086
+ [leftExpr]
37087
+ );
37088
+ changeTracker.replaceNode(sourceFile, node, fullCall);
37089
+ })
37090
+ }]
37091
+ });
37092
+ }
37093
+ }
37094
+ ts.forEachChild(node, appendNodeToVisit);
37095
+ }
37096
+ })
37097
+ });
37098
+
37022
37099
  // src/diagnostics/layerMergeAllWithDependencies.ts
37023
37100
  var layerMergeAllWithDependencies = createDiagnostic({
37024
37101
  name: "layerMergeAllWithDependencies",
@@ -37226,12 +37303,18 @@ var leakingRequirements = createDiagnostic({
37226
37303
  );
37227
37304
  function reportLeakingRequirements(node, requirements) {
37228
37305
  if (requirements.length === 0) return;
37306
+ const requirementsStr = requirements.map((_) => typeChecker.typeToString(_)).join(" | ");
37229
37307
  report({
37230
37308
  location: node,
37231
- messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement.
37232
- If these requirements cannot be cached and are expected to be provided per method invocation (e.g. HttpServerRequest), you can either safely disable this diagnostic for this line through quickfixes or mark the service declaration with a JSDoc @effect-leakable-service.
37233
- Services should usually be collected in the layer creation body, and then provided at each method that requires them.
37234
- More info at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
37309
+ messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
37310
+
37311
+ This leaks implementation details into the service's public type \u2014 callers shouldn't need to know *how* the service works internally, only *what* it provides.
37312
+
37313
+ Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
37314
+
37315
+ To suppress this diagnostic for specific dependency types that are intentionally passed through (e.g., HttpServerRequest), add \`@effect-leakable-service\` JSDoc to their interface declarations (e.g., the \`${typeChecker.typeToString(requirements[0])}\` interface), not to this service.
37316
+
37317
+ More info and examples at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
37235
37318
  fixes: []
37236
37319
  });
37237
37320
  }
@@ -39409,6 +39492,7 @@ var unsupportedServiceAccessors = createDiagnostic({
39409
39492
  // src/diagnostics.ts
39410
39493
  var diagnostics = [
39411
39494
  anyUnknownInErrorContext,
39495
+ instanceOfSchema,
39412
39496
  catchAllToMapError,
39413
39497
  catchUnfailableEffect,
39414
39498
  classSelfMismatch,
@@ -41358,6 +41442,571 @@ var patch9 = make58(
41358
41442
  )
41359
41443
  );
41360
41444
 
41445
+ // src/cli/quickfixes.ts
41446
+ var import_project_service5 = __toESM(require_dist2());
41447
+
41448
+ // src/cli/setup/text-diff-renderer.ts
41449
+ function getLines(text10) {
41450
+ return text10.split("\n");
41451
+ }
41452
+ function getLineAndCharacterOfPosition(text10, position) {
41453
+ const lines3 = text10.split("\n");
41454
+ let currentPos = 0;
41455
+ for (let lineIndex = 0; lineIndex < lines3.length; lineIndex++) {
41456
+ const lineLength = lines3[lineIndex].length;
41457
+ const lineEndPos = currentPos + lineLength;
41458
+ if (position <= lineEndPos) {
41459
+ return { line: lineIndex, character: position - currentPos };
41460
+ }
41461
+ currentPos = lineEndPos + 1;
41462
+ }
41463
+ const lastLineIndex = lines3.length - 1;
41464
+ return { line: lastLineIndex, character: lines3[lastLineIndex]?.length ?? 0 };
41465
+ }
41466
+ function renderLine(lineNum, symbol3, text10, color3) {
41467
+ const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
41468
+ return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
41469
+ }
41470
+ function renderPlainTextChange(text10, textChange) {
41471
+ const startPos = textChange.span.start;
41472
+ const endPos = textChange.span.start + textChange.span.length;
41473
+ const startLineAndChar = getLineAndCharacterOfPosition(text10, startPos);
41474
+ const endLineAndChar = getLineAndCharacterOfPosition(text10, endPos);
41475
+ const startLine = startLineAndChar.line;
41476
+ const endLine = endLineAndChar.line;
41477
+ const startCol = startLineAndChar.character;
41478
+ const endCol = endLineAndChar.character;
41479
+ const lines3 = [];
41480
+ const allLines = getLines(text10);
41481
+ if (startLine > 0) {
41482
+ const contextBefore = allLines[startLine - 1];
41483
+ lines3.push(renderLine(startLine, "|", contextBefore, blackBright2));
41484
+ }
41485
+ if (startLine <= endLine) {
41486
+ const firstLineText = allLines[startLine];
41487
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41488
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41489
+ if (hasNonWhitespaceKept) {
41490
+ lines3.push(renderLine(startLine + 1, "|", keptBeforeDeletion, blackBright2));
41491
+ }
41492
+ const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
41493
+ if (deletedOnFirstLine.length > 0) {
41494
+ const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
41495
+ lines3.push(renderLine(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
41496
+ }
41497
+ }
41498
+ for (let i = startLine + 1; i < endLine; i++) {
41499
+ const lineText = allLines[i];
41500
+ if (lineText !== void 0) {
41501
+ lines3.push(renderLine(void 0, "-", lineText, red4));
41502
+ }
41503
+ }
41504
+ if (endLine > startLine) {
41505
+ const lastLineText = allLines[endLine];
41506
+ const deletedOnLastLine = lastLineText.slice(0, endCol);
41507
+ if (deletedOnLastLine.length > 0) {
41508
+ lines3.push(renderLine(void 0, "-", deletedOnLastLine, red4));
41509
+ }
41510
+ }
41511
+ if (textChange.newText.length > 0) {
41512
+ const newTextLines = textChange.newText.split("\n");
41513
+ const firstLineText = allLines[startLine];
41514
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41515
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41516
+ const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
41517
+ for (let i = 0; i < newTextLines.length; i++) {
41518
+ const newLine = newTextLines[i];
41519
+ if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
41520
+ continue;
41521
+ }
41522
+ const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
41523
+ lines3.push(renderLine(void 0, "+", `${padding}${newLine}`, green3));
41524
+ }
41525
+ }
41526
+ let alignmentForKeptPart = 0;
41527
+ if (textChange.newText.length > 0) {
41528
+ const newTextLines = textChange.newText.split("\n");
41529
+ const lastNewLine = newTextLines[newTextLines.length - 1];
41530
+ if (lastNewLine.length === 0 && newTextLines.length > 1) {
41531
+ alignmentForKeptPart = 0;
41532
+ } else {
41533
+ const firstLineText = allLines[startLine];
41534
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41535
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41536
+ if (hasNonWhitespaceKept) {
41537
+ if (newTextLines.length === 1) {
41538
+ alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
41539
+ } else {
41540
+ alignmentForKeptPart = lastNewLine.length;
41541
+ }
41542
+ } else {
41543
+ alignmentForKeptPart = lastNewLine.length;
41544
+ }
41545
+ }
41546
+ } else {
41547
+ alignmentForKeptPart = endCol;
41548
+ }
41549
+ if (endLine > startLine) {
41550
+ const lastLineText = allLines[endLine];
41551
+ const keptAfterDeletion = lastLineText.slice(endCol);
41552
+ if (keptAfterDeletion.trim().length > 0) {
41553
+ const alignment = " ".repeat(alignmentForKeptPart);
41554
+ lines3.push(renderLine(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
41555
+ }
41556
+ } else if (startLine === endLine) {
41557
+ const firstLineText = allLines[startLine];
41558
+ const keptAfterDeletion = firstLineText.slice(endCol);
41559
+ if (keptAfterDeletion.trim().length > 0) {
41560
+ const alignment = " ".repeat(alignmentForKeptPart);
41561
+ lines3.push(renderLine(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
41562
+ }
41563
+ }
41564
+ if (endLine + 1 < allLines.length) {
41565
+ const contextAfter = allLines[endLine + 1];
41566
+ lines3.push(renderLine(endLine + 2, "|", contextAfter, blackBright2));
41567
+ }
41568
+ return lines3;
41569
+ }
41570
+ function renderPlainTextFileChanges(text10, textChanges) {
41571
+ const lines3 = [];
41572
+ const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
41573
+ for (let i = 0; i < sortedChanges.length; i++) {
41574
+ const change = sortedChanges[i];
41575
+ const changeLines = renderPlainTextChange(text10, change);
41576
+ for (const line4 of changeLines) {
41577
+ lines3.push(line4);
41578
+ }
41579
+ if (i < sortedChanges.length - 1) {
41580
+ lines3.push(text3(""));
41581
+ }
41582
+ }
41583
+ return lines3;
41584
+ }
41585
+
41586
+ // src/cli/setup/diff-renderer.ts
41587
+ function getLines2(text10) {
41588
+ return text10.split("\n");
41589
+ }
41590
+ function renderLine2(lineNum, symbol3, text10, color3) {
41591
+ const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
41592
+ return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
41593
+ }
41594
+ function renderTextChange(sourceFile, textChange) {
41595
+ const startPos = textChange.span.start;
41596
+ const endPos = textChange.span.start + textChange.span.length;
41597
+ const startLineAndChar = sourceFile.getLineAndCharacterOfPosition(startPos);
41598
+ const endLineAndChar = sourceFile.getLineAndCharacterOfPosition(endPos);
41599
+ const startLine = startLineAndChar.line;
41600
+ const endLine = endLineAndChar.line;
41601
+ const startCol = startLineAndChar.character;
41602
+ const endCol = endLineAndChar.character;
41603
+ const lines3 = [];
41604
+ const allLines = getLines2(sourceFile.text);
41605
+ if (startLine > 0) {
41606
+ const contextBefore = allLines[startLine - 1];
41607
+ lines3.push(renderLine2(startLine, "|", contextBefore, blackBright2));
41608
+ }
41609
+ if (startLine <= endLine) {
41610
+ const firstLineText = allLines[startLine];
41611
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41612
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41613
+ if (hasNonWhitespaceKept) {
41614
+ lines3.push(renderLine2(startLine + 1, "|", keptBeforeDeletion, blackBright2));
41615
+ }
41616
+ const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
41617
+ if (deletedOnFirstLine.length > 0) {
41618
+ const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
41619
+ lines3.push(renderLine2(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
41620
+ }
41621
+ }
41622
+ for (let i = startLine + 1; i < endLine; i++) {
41623
+ const lineText = allLines[i];
41624
+ if (lineText !== void 0) {
41625
+ lines3.push(renderLine2(void 0, "-", lineText, red4));
41626
+ }
41627
+ }
41628
+ if (endLine > startLine) {
41629
+ const lastLineText = allLines[endLine];
41630
+ const deletedOnLastLine = lastLineText.slice(0, endCol);
41631
+ if (deletedOnLastLine.length > 0) {
41632
+ lines3.push(renderLine2(void 0, "-", deletedOnLastLine, red4));
41633
+ }
41634
+ }
41635
+ if (textChange.newText.length > 0) {
41636
+ const newTextLines = textChange.newText.split("\n");
41637
+ const firstLineText = allLines[startLine];
41638
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41639
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41640
+ const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
41641
+ for (let i = 0; i < newTextLines.length; i++) {
41642
+ const newLine = newTextLines[i];
41643
+ if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
41644
+ continue;
41645
+ }
41646
+ const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
41647
+ lines3.push(renderLine2(void 0, "+", `${padding}${newLine}`, green3));
41648
+ }
41649
+ }
41650
+ let alignmentForKeptPart = 0;
41651
+ if (textChange.newText.length > 0) {
41652
+ const newTextLines = textChange.newText.split("\n");
41653
+ const lastNewLine = newTextLines[newTextLines.length - 1];
41654
+ if (lastNewLine.length === 0 && newTextLines.length > 1) {
41655
+ alignmentForKeptPart = 0;
41656
+ } else {
41657
+ const firstLineText = allLines[startLine];
41658
+ const keptBeforeDeletion = firstLineText.slice(0, startCol);
41659
+ const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
41660
+ if (hasNonWhitespaceKept) {
41661
+ if (newTextLines.length === 1) {
41662
+ alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
41663
+ } else {
41664
+ alignmentForKeptPart = lastNewLine.length;
41665
+ }
41666
+ } else {
41667
+ alignmentForKeptPart = lastNewLine.length;
41668
+ }
41669
+ }
41670
+ } else {
41671
+ alignmentForKeptPart = endCol;
41672
+ }
41673
+ if (endLine > startLine) {
41674
+ const lastLineText = allLines[endLine];
41675
+ const keptAfterDeletion = lastLineText.slice(endCol);
41676
+ if (keptAfterDeletion.trim().length > 0) {
41677
+ const alignment = " ".repeat(alignmentForKeptPart);
41678
+ lines3.push(renderLine2(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
41679
+ }
41680
+ } else if (startLine === endLine) {
41681
+ const firstLineText = allLines[startLine];
41682
+ const keptAfterDeletion = firstLineText.slice(endCol);
41683
+ if (keptAfterDeletion.trim().length > 0) {
41684
+ const alignment = " ".repeat(alignmentForKeptPart);
41685
+ lines3.push(renderLine2(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
41686
+ }
41687
+ }
41688
+ if (endLine + 1 < allLines.length) {
41689
+ const contextAfter = allLines[endLine + 1];
41690
+ lines3.push(renderLine2(endLine + 2, "|", contextAfter, blackBright2));
41691
+ }
41692
+ return lines3;
41693
+ }
41694
+ function renderFileChanges(sourceFile, textChanges) {
41695
+ const lines3 = [];
41696
+ const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
41697
+ for (let i = 0; i < sortedChanges.length; i++) {
41698
+ const change = sortedChanges[i];
41699
+ const changeLines = renderTextChange(sourceFile, change);
41700
+ for (const line4 of changeLines) {
41701
+ lines3.push(line4);
41702
+ }
41703
+ if (i < sortedChanges.length - 1) {
41704
+ lines3.push(text3(""));
41705
+ }
41706
+ }
41707
+ return lines3;
41708
+ }
41709
+ var renderCodeActions = (result, assessmentState) => gen2(function* () {
41710
+ if (result.codeActions.length === 0) {
41711
+ const noChanges = annotate2(
41712
+ text3("No changes needed - your configuration is already up to date!"),
41713
+ green3
41714
+ );
41715
+ const noChangesStr = noChanges.pipe(render3({ style: "pretty" }));
41716
+ yield* log3(noChangesStr);
41717
+ return;
41718
+ }
41719
+ const sourceFiles = [
41720
+ assessmentState.packageJson.sourceFile,
41721
+ assessmentState.tsconfig.sourceFile
41722
+ ];
41723
+ if (isSome2(assessmentState.vscodeSettings)) {
41724
+ sourceFiles.push(assessmentState.vscodeSettings.value.sourceFile);
41725
+ }
41726
+ const plainTextFiles = [];
41727
+ if (isSome2(assessmentState.agentsMd)) {
41728
+ plainTextFiles.push({
41729
+ path: assessmentState.agentsMd.value.path,
41730
+ text: assessmentState.agentsMd.value.text
41731
+ });
41732
+ }
41733
+ if (isSome2(assessmentState.claudeMd)) {
41734
+ plainTextFiles.push({
41735
+ path: assessmentState.claudeMd.value.path,
41736
+ text: assessmentState.claudeMd.value.text
41737
+ });
41738
+ }
41739
+ for (const codeAction of result.codeActions) {
41740
+ for (const fileChange of codeAction.changes) {
41741
+ const sourceFile = sourceFiles.find((sf) => sf.fileName === fileChange.fileName);
41742
+ const plainTextFile = plainTextFiles.find((pf) => pf.path === fileChange.fileName);
41743
+ const header = vsep2([
41744
+ empty32,
41745
+ annotate2(text3(codeAction.description), bold2),
41746
+ annotate2(text3(fileChange.fileName), cyan4),
41747
+ empty32
41748
+ ]);
41749
+ const headerStr = header.pipe(render3({ style: "pretty" }));
41750
+ yield* log3(headerStr);
41751
+ if (sourceFile) {
41752
+ const diffLines = renderFileChanges(sourceFile, fileChange.textChanges);
41753
+ const diff8 = vsep2(diffLines);
41754
+ const diffStr = diff8.pipe(render3({ style: "pretty" }));
41755
+ yield* log3(diffStr);
41756
+ } else if (plainTextFile) {
41757
+ const diffLines = renderPlainTextFileChanges(plainTextFile.text, fileChange.textChanges);
41758
+ const diff8 = vsep2(diffLines);
41759
+ const diffStr = diff8.pipe(render3({ style: "pretty" }));
41760
+ yield* log3(diffStr);
41761
+ } else {
41762
+ const noticeStr = text3(" (file will be modified)").pipe(render3({ style: "pretty" }));
41763
+ yield* log3(noticeStr);
41764
+ }
41765
+ }
41766
+ }
41767
+ if (result.messages.length > 0) {
41768
+ yield* log3("");
41769
+ for (const message of result.messages) {
41770
+ const messageDoc = message.includes("WARNING") ? annotate2(text3(message), yellow3) : text3(message);
41771
+ const messageStr = messageDoc.pipe(render3({ style: "pretty" }));
41772
+ yield* log3(messageStr);
41773
+ }
41774
+ }
41775
+ });
41776
+
41777
+ // src/cli/quickfixes.ts
41778
+ var validDiagnosticNames = new Set(diagnostics.map((_) => _.name));
41779
+ var validDiagnosticCodes = new Set(diagnostics.map((_) => String(_.code)));
41780
+ var diagnosticCodeByName = new Map(diagnostics.map((_) => [_.name, _.code]));
41781
+ var ColumnRequiresLineError = class extends TaggedError("ColumnRequiresLineError") {
41782
+ get message() {
41783
+ return "The --column option requires --line to be specified.";
41784
+ }
41785
+ };
41786
+ var isSkipFix = (fixName) => fixName.endsWith("_skipNextLine") || fixName.endsWith("_skipFile");
41787
+ var renderQuickFix = (sourceFile, fix) => {
41788
+ const lines3 = [];
41789
+ lines3.push(empty32);
41790
+ lines3.push(
41791
+ cat2(
41792
+ cat2(
41793
+ cat2(
41794
+ annotate2(text3(" Fix: "), bold2),
41795
+ annotate2(text3(fix.fixName), cyan4)
41796
+ ),
41797
+ text3(" - ")
41798
+ ),
41799
+ text3(fix.description)
41800
+ )
41801
+ );
41802
+ lines3.push(annotate2(text3(" " + "\u2500".repeat(60)), blackBright2));
41803
+ for (const fileChange of fix.changes) {
41804
+ if (fileChange.fileName === sourceFile.fileName) {
41805
+ for (const textChange of fileChange.textChanges) {
41806
+ const diffLines = renderTextChange(sourceFile, textChange);
41807
+ for (const diffLine of diffLines) {
41808
+ lines3.push(cat2(text3(" "), diffLine));
41809
+ }
41810
+ }
41811
+ }
41812
+ }
41813
+ return vsep2(lines3);
41814
+ };
41815
+ var renderDiagnosticWithFixes = (sourceFile, info2, tsInstance) => {
41816
+ const lines3 = [];
41817
+ const { character, line: line4 } = tsInstance.getLineAndCharacterOfPosition(sourceFile, info2.diagnostic.start);
41818
+ const locationStr = `${sourceFile.fileName}:${line4 + 1}:${character + 1}`;
41819
+ lines3.push(
41820
+ cat2(
41821
+ cat2(
41822
+ cat2(
41823
+ cat2(
41824
+ annotate2(text3(locationStr), cyan4),
41825
+ text3(" ")
41826
+ ),
41827
+ annotate2(text3(`effect(${info2.diagnostic.ruleName})`), yellow3)
41828
+ ),
41829
+ text3(": ")
41830
+ ),
41831
+ text3(info2.diagnostic.messageText)
41832
+ )
41833
+ );
41834
+ for (const fix of info2.fixes) {
41835
+ lines3.push(renderQuickFix(sourceFile, fix));
41836
+ }
41837
+ lines3.push(empty32);
41838
+ return vsep2(lines3);
41839
+ };
41840
+ var BATCH_SIZE4 = 50;
41841
+ var quickfixes = make58(
41842
+ "quickfixes",
41843
+ {
41844
+ file: file3("file").pipe(
41845
+ optional4,
41846
+ withDescription3("The full path of the file to check for quick fixes.")
41847
+ ),
41848
+ project: file3("project").pipe(
41849
+ optional4,
41850
+ withDescription3("The full path of the project tsconfig.json file to check for quick fixes.")
41851
+ ),
41852
+ code: text8("code").pipe(
41853
+ withDescription3("Filter by diagnostic name or code (e.g., 'floatingEffect' or '5')."),
41854
+ mapEffect6((value5) => {
41855
+ if (validDiagnosticNames.has(value5)) {
41856
+ return succeed7(diagnosticCodeByName.get(value5));
41857
+ }
41858
+ if (validDiagnosticCodes.has(value5)) {
41859
+ return succeed7(Number(value5));
41860
+ }
41861
+ const validValues = [...validDiagnosticNames].sort().join(", ");
41862
+ return fail7(
41863
+ invalidValue2(
41864
+ p2(`Invalid diagnostic code '${value5}'. Valid values: ${validValues}`)
41865
+ )
41866
+ );
41867
+ }),
41868
+ optional4
41869
+ ),
41870
+ line: integer5("line").pipe(
41871
+ withDescription3("Filter by line number (1-based)."),
41872
+ optional4
41873
+ ),
41874
+ column: integer5("column").pipe(
41875
+ withDescription3("Filter by column number (1-based). Requires --line to be specified."),
41876
+ optional4
41877
+ ),
41878
+ fix: text8("fix").pipe(
41879
+ withDescription3("Filter by fix name (e.g., 'floatingEffect_yieldStar')."),
41880
+ optional4
41881
+ )
41882
+ },
41883
+ fn("quickfixes")(function* ({ code: code2, column: column3, file: file5, fix, line: line4, project: project3 }) {
41884
+ if (isSome2(column3) && isNone2(line4)) {
41885
+ return yield* new ColumnRequiresLineError();
41886
+ }
41887
+ const path2 = yield* Path2;
41888
+ const tsInstance = yield* TypeScriptContext;
41889
+ const filesToCheck = isSome2(project3) ? yield* getFileNamesInTsConfig(project3.value) : /* @__PURE__ */ new Set();
41890
+ if (isSome2(file5)) {
41891
+ filesToCheck.add(path2.resolve(file5.value));
41892
+ }
41893
+ if (filesToCheck.size === 0) {
41894
+ return yield* new NoFilesToCheckError();
41895
+ }
41896
+ let totalDiagnosticsWithFixes = 0;
41897
+ for (const batch of chunksOf(filesToCheck, BATCH_SIZE4)) {
41898
+ const { service: service3 } = (0, import_project_service5.createProjectService)({ options: { loadTypeScriptPlugins: false } });
41899
+ for (const filePath of batch) {
41900
+ service3.openClientFile(filePath);
41901
+ try {
41902
+ const scriptInfo = service3.getScriptInfo(filePath);
41903
+ if (!scriptInfo) continue;
41904
+ const projectInfo = scriptInfo.getDefaultProject();
41905
+ const languageService = projectInfo.getLanguageService(true);
41906
+ const program = languageService.getProgram();
41907
+ if (!program) continue;
41908
+ const sourceFile = program.getSourceFile(filePath);
41909
+ if (!sourceFile) continue;
41910
+ const pluginConfig = extractEffectLspOptions(program.getCompilerOptions());
41911
+ if (!pluginConfig) continue;
41912
+ const result = pipe(
41913
+ getSemanticDiagnosticsWithCodeFixes(diagnostics, sourceFile),
41914
+ nanoLayer3,
41915
+ nanoLayer2,
41916
+ nanoLayer,
41917
+ provideService7(TypeCheckerApi, program.getTypeChecker()),
41918
+ provideService7(TypeScriptProgram, program),
41919
+ provideService7(TypeScriptApi, tsInstance),
41920
+ provideService7(
41921
+ LanguageServicePluginOptions,
41922
+ { ...parse4(pluginConfig), diagnosticsName: false }
41923
+ ),
41924
+ run9,
41925
+ getOrElse(() => ({ diagnostics: [], codeFixes: [] }))
41926
+ );
41927
+ const diagnosticMap = /* @__PURE__ */ new Map();
41928
+ for (const diagnostic of result.diagnostics) {
41929
+ if (diagnostic.start === void 0) continue;
41930
+ if (isSome2(code2) && diagnostic.code !== code2.value) continue;
41931
+ if (isSome2(line4)) {
41932
+ const pos = tsInstance.getLineAndCharacterOfPosition(sourceFile, diagnostic.start);
41933
+ if (pos.line !== line4.value - 1) continue;
41934
+ if (isSome2(column3) && pos.character !== column3.value - 1) continue;
41935
+ }
41936
+ const key = `${diagnostic.start}-${diagnostic.start + (diagnostic.length ?? 0)}-${diagnostic.code}`;
41937
+ const ruleName = Object.values(diagnostics).find((_) => _.code === diagnostic.code)?.name ?? `unknown(${diagnostic.code})`;
41938
+ if (!diagnosticMap.has(key)) {
41939
+ diagnosticMap.set(key, {
41940
+ diagnostic: {
41941
+ start: diagnostic.start,
41942
+ end: diagnostic.start + (diagnostic.length ?? 0),
41943
+ messageText: tsInstance.flattenDiagnosticMessageText(diagnostic.messageText, "\n"),
41944
+ code: diagnostic.code,
41945
+ ruleName
41946
+ },
41947
+ fixes: []
41948
+ });
41949
+ }
41950
+ }
41951
+ const formatContext = tsInstance.formatting.getFormatContext(
41952
+ tsInstance.getDefaultFormatCodeSettings(),
41953
+ { getNewLine: () => "\n" }
41954
+ );
41955
+ for (const codeFix of result.codeFixes) {
41956
+ if (isSkipFix(codeFix.fixName)) continue;
41957
+ if (isSome2(fix) && codeFix.fixName !== fix.value) continue;
41958
+ const key = `${codeFix.start}-${codeFix.end}-${codeFix.code}`;
41959
+ const info2 = diagnosticMap.get(key);
41960
+ if (!info2) continue;
41961
+ const changes2 = tsInstance.textChanges.ChangeTracker.with(
41962
+ {
41963
+ formatContext,
41964
+ host: { getNewLine: () => "\n" },
41965
+ preferences: {}
41966
+ },
41967
+ (changeTracker) => pipe(
41968
+ codeFix.apply,
41969
+ provideService7(ChangeTracker, changeTracker),
41970
+ run9
41971
+ )
41972
+ );
41973
+ info2.fixes.push({
41974
+ fixName: codeFix.fixName,
41975
+ description: codeFix.description,
41976
+ changes: changes2
41977
+ });
41978
+ }
41979
+ const diagnosticsWithFixes = Array.from(diagnosticMap.values()).filter(
41980
+ (info2) => info2.fixes.length > 0
41981
+ );
41982
+ if (diagnosticsWithFixes.length === 0) continue;
41983
+ diagnosticsWithFixes.sort((a, b) => a.diagnostic.start - b.diagnostic.start);
41984
+ totalDiagnosticsWithFixes += diagnosticsWithFixes.length;
41985
+ for (const info2 of diagnosticsWithFixes) {
41986
+ const doc = renderDiagnosticWithFixes(sourceFile, info2, tsInstance);
41987
+ yield* log3(doc.pipe(render3({ style: "pretty" })));
41988
+ }
41989
+ } finally {
41990
+ service3.closeClientFile(filePath);
41991
+ }
41992
+ }
41993
+ yield* yieldNow4();
41994
+ }
41995
+ if (totalDiagnosticsWithFixes === 0) {
41996
+ yield* log3("No quick fixes available.");
41997
+ } else {
41998
+ yield* log3(
41999
+ annotate2(
42000
+ text3(`Found ${totalDiagnosticsWithFixes} diagnostic(s) with quick fixes.`),
42001
+ bold2
42002
+ ).pipe(render3({ style: "pretty" }))
42003
+ );
42004
+ }
42005
+ })
42006
+ ).pipe(
42007
+ withDescription6("Shows diagnostics with available quick fixes and their proposed changes.")
42008
+ );
42009
+
41361
42010
  // 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
42011
  var renderBeep7 = /* @__PURE__ */ render3(beep3, {
41363
42012
  style: "pretty"
@@ -42434,335 +43083,6 @@ var computeVSCodeSettingsChanges = (current, target) => {
42434
43083
  });
42435
43084
  };
42436
43085
 
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
43086
  // src/cli/setup/errors.ts
42767
43087
  var PackageJsonNotFoundError = class extends TaggedError("PackageJsonNotFoundError") {
42768
43088
  get message() {
@@ -43404,7 +43724,7 @@ var cliCommand = make58(
43404
43724
  "effect-language-service",
43405
43725
  {},
43406
43726
  () => log3("Please select a command or run --help.")
43407
- ).pipe(withSubcommands3([setup, patch9, unpatch, check2, diagnostics2, codegen, overview, layerInfo]));
43727
+ ).pipe(withSubcommands3([setup, patch9, unpatch, check2, diagnostics2, quickfixes, codegen, overview, layerInfo]));
43408
43728
  var main = run8(cliCommand, {
43409
43729
  name: "effect-language-service",
43410
43730
  version: package_default.version