@effect/language-service 0.57.0 → 0.58.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
@@ -867,7 +867,7 @@ var require_getParsedConfigFile = __commonJS({
867
867
  throw new Error(formatDiagnostics([diag]));
868
868
  },
869
869
  readDirectory: tsserver.sys.readDirectory,
870
- readFile: (file6) => fs.readFileSync(path2.isAbsolute(file6) ? file6 : path2.join(getCurrentDirectory(), file6), "utf-8"),
870
+ readFile: (file5) => fs.readFileSync(path2.isAbsolute(file5) ? file5 : path2.join(getCurrentDirectory(), file5), "utf-8"),
871
871
  useCaseSensitiveFileNames: tsserver.sys.useCaseSensitiveFileNames
872
872
  });
873
873
  if (parsed?.errors.length) {
@@ -7113,18 +7113,18 @@ var fromFlatLoop = (flat, prefix, config2, split2) => {
7113
7113
  }
7114
7114
  };
7115
7115
  var fromFlatLoopFail = (prefix, path2) => (index) => left2(MissingData(prefix, `The element at index ${index} in a sequence at path "${path2}" was missing`));
7116
- var splitPathString = (text8, delim) => {
7117
- const split2 = text8.split(new RegExp(`\\s*${escape(delim)}\\s*`));
7116
+ var splitPathString = (text9, delim) => {
7117
+ const split2 = text9.split(new RegExp(`\\s*${escape(delim)}\\s*`));
7118
7118
  return split2;
7119
7119
  };
7120
- var parsePrimitive = (text8, path2, primitive2, delimiter, split2) => {
7120
+ var parsePrimitive = (text9, path2, primitive2, delimiter, split2) => {
7121
7121
  if (!split2) {
7122
- return pipe(primitive2.parse(text8), mapBoth2({
7122
+ return pipe(primitive2.parse(text9), mapBoth2({
7123
7123
  onFailure: prefixed(path2),
7124
7124
  onSuccess: of
7125
7125
  }));
7126
7126
  }
7127
- return pipe(splitPathString(text8, delimiter), forEachSequential((char4) => primitive2.parse(char4.trim())), mapError(prefixed(path2)));
7127
+ return pipe(splitPathString(text9, delimiter), forEachSequential((char4) => primitive2.parse(char4.trim())), mapError(prefixed(path2)));
7128
7128
  };
7129
7129
  var transpose = (array7) => {
7130
7130
  return Object.keys(array7[0]).map((column3) => array7.map((row) => row[column3]));
@@ -9226,14 +9226,14 @@ var structuredMessage = (u) => {
9226
9226
  }
9227
9227
  }
9228
9228
  };
9229
- var withColor = (text8, ...colors2) => {
9229
+ var withColor = (text9, ...colors2) => {
9230
9230
  let out = "";
9231
9231
  for (let i = 0; i < colors2.length; i++) {
9232
9232
  out += `\x1B[${colors2[i]}m`;
9233
9233
  }
9234
- return out + text8 + "\x1B[0m";
9234
+ return out + text9 + "\x1B[0m";
9235
9235
  };
9236
- var withColorNoop = (text8, ..._colors) => text8;
9236
+ var withColorNoop = (text9, ..._colors) => text9;
9237
9237
  var colors = {
9238
9238
  bold: "1",
9239
9239
  red: "31",
@@ -15196,10 +15196,10 @@ var char = (char4) => {
15196
15196
  op.char = char4;
15197
15197
  return op;
15198
15198
  };
15199
- var text = (text8) => {
15199
+ var text = (text9) => {
15200
15200
  const op = Object.create(proto5);
15201
15201
  op._tag = "Text";
15202
- op.text = text8;
15202
+ op.text = text9;
15203
15203
  return op;
15204
15204
  };
15205
15205
  var flatAlt = /* @__PURE__ */ dual(2, (self, that) => {
@@ -15488,10 +15488,10 @@ var char2 = /* @__PURE__ */ dual(2, (self, char4) => {
15488
15488
  op.stream = self;
15489
15489
  return op;
15490
15490
  });
15491
- var text2 = /* @__PURE__ */ dual(2, (self, text8) => {
15491
+ var text2 = /* @__PURE__ */ dual(2, (self, text9) => {
15492
15492
  const op = Object.create(proto6);
15493
15493
  op._tag = "TextStream";
15494
- op.text = text8;
15494
+ op.text = text9;
15495
15495
  op.stream = self;
15496
15496
  return op;
15497
15497
  });
@@ -16309,8 +16309,8 @@ var make44 = (bytes) => {
16309
16309
  redactedRegistry.set(secret4, bytes.map((byte) => String.fromCharCode(byte)).join(""));
16310
16310
  return secret4;
16311
16311
  };
16312
- var fromString = (text8) => {
16313
- return make44(text8.split("").map((char4) => char4.charCodeAt(0)));
16312
+ var fromString = (text9) => {
16313
+ return make44(text9.split("").map((char4) => char4.charCodeAt(0)));
16314
16314
  };
16315
16315
 
16316
16316
  // node_modules/.pnpm/effect@3.19.0/node_modules/effect/dist/esm/internal/config.js
@@ -18888,7 +18888,7 @@ var defaultConfig = {
18888
18888
  showBuiltIns: true,
18889
18889
  showTypes: true
18890
18890
  };
18891
- var normalizeCase = /* @__PURE__ */ dual(2, (self, text8) => self.isCaseSensitive ? text8 : text8.toLowerCase());
18891
+ var normalizeCase = /* @__PURE__ */ dual(2, (self, text9) => self.isCaseSensitive ? text9 : text9.toLowerCase());
18892
18892
 
18893
18893
  // node_modules/.pnpm/@effect+cli@0.72.0_@effect+platform@0.93.0_@effect+printer-ansi@0.47.0_@effect+printer@0.47.0_effect@3.19.0/node_modules/@effect/cli/dist/esm/internal/autoCorrect.js
18894
18894
  var levensteinDistance = (first3, second, config2) => {
@@ -22834,11 +22834,11 @@ var make53 = (impl) => {
22834
22834
  }),
22835
22835
  stream: (path2, options3) => pipe(impl.open(path2, {
22836
22836
  flag: "r"
22837
- }), options3?.offset ? tap2((file6) => file6.seek(options3.offset, "start")) : identity, map17((file6) => stream(file6, options3)), unwrapScoped6),
22837
+ }), options3?.offset ? tap2((file5) => file5.seek(options3.offset, "start")) : identity, map17((file5) => stream(file5, options3)), unwrapScoped6),
22838
22838
  sink: (path2, options3) => pipe(impl.open(path2, {
22839
22839
  flag: "w",
22840
22840
  ...options3
22841
- }), map17((file6) => forEach10((_) => file6.writeAll(_))), unwrapScoped5),
22841
+ }), map17((file5) => forEach10((_) => file5.writeAll(_))), unwrapScoped5),
22842
22842
  writeFileString: (path2, data, options3) => flatMap9(try_3({
22843
22843
  try: () => new TextEncoder().encode(data),
22844
22844
  catch: (cause2) => new BadArgument({
@@ -22850,7 +22850,7 @@ var make53 = (impl) => {
22850
22850
  }), (_) => impl.writeFile(path2, _, options3))
22851
22851
  });
22852
22852
  };
22853
- var stream = (file6, {
22853
+ var stream = (file5, {
22854
22854
  bufferSize = 16,
22855
22855
  bytesToRead: bytesToRead_,
22856
22856
  chunkSize: chunkSize_ = Size(64 * 1024)
@@ -22862,7 +22862,7 @@ var stream = (file6, {
22862
22862
  return void_6;
22863
22863
  }
22864
22864
  const toRead = bytesToRead !== void 0 && bytesToRead - totalBytesRead < chunkSize ? bytesToRead - totalBytesRead : chunkSize;
22865
- return flatMap15(file6.readAlloc(toRead), match2({
22865
+ return flatMap15(file5.readAlloc(toRead), match2({
22866
22866
  onNone: () => void_6,
22867
22867
  onSome: (buf) => flatMap15(write2(of2(buf)), (_) => loop2(totalBytesRead + BigInt(buf.length)))
22868
22868
  }));
@@ -23161,12 +23161,12 @@ var windowsFigures = {
23161
23161
  pointer: /* @__PURE__ */ text3(">")
23162
23162
  };
23163
23163
  var figures = /* @__PURE__ */ map17(/* @__PURE__ */ sync4(() => process.platform === "win32"), (isWindows) => isWindows ? windowsFigures : defaultFigures);
23164
- function eraseText(text8, columns) {
23164
+ function eraseText(text9, columns) {
23165
23165
  if (columns === 0) {
23166
23166
  return cat2(eraseLine3, cursorTo3(0));
23167
23167
  }
23168
23168
  let rows = 0;
23169
- const lines3 = text8.split(/\r?\n/);
23169
+ const lines3 = text9.split(/\r?\n/);
23170
23170
  for (const line4 of lines3) {
23171
23171
  rows += 1 + Math.floor(Math.max(line4.length - 1, 0) / columns);
23172
23172
  }
@@ -24168,10 +24168,10 @@ function getFileList(directory3, options3) {
24168
24168
  // to be filtered out if the user so desires
24169
24169
  map17((files2) => ["..", ...files2])
24170
24170
  );
24171
- return yield* filter8(files, (file6) => {
24172
- const result = options3.filter(file6);
24171
+ return yield* filter8(files, (file5) => {
24172
+ const result = options3.filter(file5);
24173
24173
  const userDefinedFilter = isEffect2(result) ? result : succeed7(result);
24174
- const directoryFilter = options3.type === "directory" ? map17(orDie2(fs.stat(path2.join(directory3, file6))), (info2) => info2.type === "Directory") : succeed7(true);
24174
+ const directoryFilter = options3.type === "directory" ? map17(orDie2(fs.stat(path2.join(directory3, file5))), (info2) => info2.type === "Directory") : succeed7(true);
24175
24175
  return zipWith4(userDefinedFilter, directoryFilter, (a, b) => a && b);
24176
24176
  }, {
24177
24177
  concurrency: files.length
@@ -24184,12 +24184,12 @@ function handleClear2(options3) {
24184
24184
  const terminal = yield* Terminal;
24185
24185
  const columns = yield* terminal.columns;
24186
24186
  const currentPath = yield* resolveCurrentPath(state.path, options3);
24187
- const text8 = "\n".repeat(Math.min(state.files.length, options3.maxPerPage));
24187
+ const text9 = "\n".repeat(Math.min(state.files.length, options3.maxPerPage));
24188
24188
  const clearPath = eraseText(currentPath, columns);
24189
24189
  const message = showConfirmation(state.confirm) ? CONFIRM_MESSAGE : options3.message;
24190
24190
  const clearPrompt = eraseText(`
24191
24191
  ${message}`, columns);
24192
- const clearOptions = eraseText(text8, columns);
24192
+ const clearOptions = eraseText(text9, columns);
24193
24193
  return clearOptions.pipe(cat2(clearPath), cat2(clearPrompt), optimize3(Deep), render3({
24194
24194
  style: "pretty",
24195
24195
  options: {
@@ -24220,8 +24220,8 @@ function renderPrefix(state, toDisplay, currentIndex, length3, figures2) {
24220
24220
  }
24221
24221
  return state.cursor === currentIndex ? figures2.pointer.pipe(annotate2(cyanBright2), cat2(prefix)) : prefix.pipe(cat2(space2));
24222
24222
  }
24223
- function renderFileName(file6, isSelected) {
24224
- return isSelected ? annotate2(text3(file6), combine10(underlined2, cyanBright2)) : text3(file6);
24223
+ function renderFileName(file5, isSelected) {
24224
+ return isSelected ? annotate2(text3(file5), combine10(underlined2, cyanBright2)) : text3(file5);
24225
24225
  }
24226
24226
  function renderFiles(state, files, figures2, options3) {
24227
24227
  const length3 = files.length;
@@ -24325,7 +24325,7 @@ function processSelection(state, options3) {
24325
24325
  const info2 = yield* orDie2(fs.stat(resolvedPath));
24326
24326
  if (info2.type === "Directory") {
24327
24327
  const files = yield* getFileList(resolvedPath, options3);
24328
- const filesWithoutParent = files.filter((file6) => file6 !== "..");
24328
+ const filesWithoutParent = files.filter((file5) => file5 !== "..");
24329
24329
  if (options3.type === "directory" || options3.type === "either") {
24330
24330
  return filesWithoutParent.length === 0 ? Action.Submit({
24331
24331
  value: resolvedPath
@@ -24899,8 +24899,8 @@ function handleClear4(options3) {
24899
24899
  const terminal = yield* Terminal;
24900
24900
  const columns = yield* terminal.columns;
24901
24901
  const clearPrompt = cat2(eraseLine3, cursorLeft3);
24902
- const text8 = "\n".repeat(Math.min(options3.choices.length, options3.maxPerPage)) + options3.message;
24903
- const clearOutput = eraseText(text8, columns);
24902
+ const text9 = "\n".repeat(Math.min(options3.choices.length, options3.maxPerPage)) + options3.message;
24903
+ const clearOutput = eraseText(text9, columns);
24904
24904
  return clearOutput.pipe(cat2(clearPrompt), optimize3(Deep), render3({
24905
24905
  style: "pretty",
24906
24906
  options: {
@@ -25000,7 +25000,7 @@ ${error4}`, columns))
25000
25000
  });
25001
25001
  }
25002
25002
  function renderInput2(nextState, options3, submitted) {
25003
- const text8 = getValue(nextState, options3);
25003
+ const text9 = getValue(nextState, options3);
25004
25004
  const annotation = match2(nextState.error, {
25005
25005
  onNone: () => {
25006
25006
  if (submitted) {
@@ -25018,10 +25018,10 @@ function renderInput2(nextState, options3, submitted) {
25018
25018
  return empty32;
25019
25019
  }
25020
25020
  case "password": {
25021
- return annotate2(text3("*".repeat(text8.length)), annotation);
25021
+ return annotate2(text3("*".repeat(text9.length)), annotation);
25022
25022
  }
25023
25023
  case "text": {
25024
- return annotate2(text3(text8), annotation);
25024
+ return annotate2(text3(text9), annotation);
25025
25025
  }
25026
25026
  }
25027
25027
  }
@@ -25401,6 +25401,11 @@ var path = (pathType, pathExists) => {
25401
25401
  op.pathExists = pathExists;
25402
25402
  return op;
25403
25403
  };
25404
+ var text6 = /* @__PURE__ */ (() => {
25405
+ const op = /* @__PURE__ */ Object.create(proto19);
25406
+ op._tag = "Text";
25407
+ return op;
25408
+ })();
25404
25409
  var getChoices = (self) => getChoicesInternal(self);
25405
25410
  var getHelp = (self) => getHelpInternal(self);
25406
25411
  var getTypeName = (self) => getTypeNameInternal(self);
@@ -26032,6 +26037,7 @@ var none10 = /* @__PURE__ */ (() => {
26032
26037
  op._tag = "Empty";
26033
26038
  return op;
26034
26039
  })();
26040
+ var text7 = (name) => makeSingle(name, empty2(), text6);
26035
26041
  var getHelp3 = (self) => getHelpInternal2(self);
26036
26042
  var getUsage = (self) => getUsageInternal(self);
26037
26043
  var map29 = /* @__PURE__ */ dual(2, (self, f) => makeMap(self, (a) => right2(f(a))));
@@ -26994,6 +27000,7 @@ var boolean5 = boolean4;
26994
27000
  var choice3 = choice2;
26995
27001
  var directory2 = directory;
26996
27002
  var file3 = file2;
27003
+ var text8 = text7;
26997
27004
  var optional4 = optional3;
26998
27005
  var repeated4 = repeated3;
26999
27006
  var withDefault3 = withDefault2;
@@ -27212,7 +27219,7 @@ var validateInternal2 = (self, args3, config2) => {
27212
27219
  return fail7(missingValue(p(`Missing argument ${getTypeName(self.primitiveType)}`)));
27213
27220
  },
27214
27221
  onNonEmpty: (head5, tail) => validate4(self.primitiveType, some2(head5), config2).pipe(mapBoth4({
27215
- onFailure: (text8) => invalidArgument(p(text8)),
27222
+ onFailure: (text9) => invalidArgument(p(text9)),
27216
27223
  onSuccess: (a) => [tail, a]
27217
27224
  }))
27218
27225
  });
@@ -28080,10 +28087,10 @@ var handleBuiltInOption = (self, executable, args3, builtIn2, execute2, config2)
28080
28087
  const description = descriptionList([[text4("Instructions"), instructions]]);
28081
28088
  const header = h1(spans([code("Wizard Mode for CLI Application:"), space3, code(self.name), space3, code(`(${self.version})`), summary5]));
28082
28089
  const help = sequence(header, description);
28083
- const text8 = toAnsiText(help);
28090
+ const text9 = toAnsiText(help);
28084
28091
  const command = fromIterable(getNames2(self.command))[0];
28085
28092
  const wizardPrefix = getWizardPrefix(builtIn2, command, args3);
28086
- return log3(text8).pipe(zipRight3(wizard4(builtIn2.command, wizardPrefix, config2)), tap2((args4) => log3(toAnsiText(renderWizardArgs(args4)))), flatMap9((args4) => toggle2({
28093
+ return log3(text9).pipe(zipRight3(wizard4(builtIn2.command, wizardPrefix, config2)), tap2((args4) => log3(toAnsiText(renderWizardArgs(args4)))), flatMap9((args4) => toggle2({
28087
28094
  message: "Would you like to run the command?",
28088
28095
  initial: true,
28089
28096
  active: "yes",
@@ -28899,7 +28906,7 @@ var makeTempFile = /* @__PURE__ */ makeTempFileFactory("makeTempFile");
28899
28906
  var makeTempFileScoped = /* @__PURE__ */ (() => {
28900
28907
  const makeFile2 = /* @__PURE__ */ makeTempFileFactory("makeTempFileScoped");
28901
28908
  const removeDirectory = /* @__PURE__ */ removeFactory("makeTempFileScoped");
28902
- return (options3) => acquireRelease2(makeFile2(options3), (file6) => orDie2(removeDirectory(Path3.dirname(file6), {
28909
+ return (options3) => acquireRelease2(makeFile2(options3), (file5) => orDie2(removeDirectory(Path3.dirname(file5), {
28903
28910
  recursive: true
28904
28911
  })));
28905
28912
  })();
@@ -33538,18 +33545,18 @@ var BATCH_SIZE = 50;
33538
33545
  var codegen = make58(
33539
33546
  "codegen",
33540
33547
  { file: file4, project: project2, verbose },
33541
- fn("codegen")(function* ({ file: file6, project: project4, verbose: verbose2 }) {
33548
+ fn("codegen")(function* ({ file: file5, project: project3, verbose: verbose2 }) {
33542
33549
  const path2 = yield* Path2;
33543
33550
  const fs = yield* FileSystem;
33544
33551
  const tsInstance = yield* getTypeScript;
33545
33552
  let filesToCodegen = /* @__PURE__ */ new Set();
33546
33553
  let checkedFilesCount = 0;
33547
33554
  let updatedFilesCount = 0;
33548
- if (isSome2(project4)) {
33549
- filesToCodegen = yield* getFileNamesInTsConfig(project4.value);
33555
+ if (isSome2(project3)) {
33556
+ filesToCodegen = yield* getFileNamesInTsConfig(project3.value);
33550
33557
  }
33551
- if (isSome2(file6)) {
33552
- filesToCodegen.add(path2.resolve(file6.value));
33558
+ if (isSome2(file5)) {
33559
+ filesToCodegen.add(path2.resolve(file5.value));
33553
33560
  }
33554
33561
  if (filesToCodegen.size === 0) {
33555
33562
  return yield* new NoFilesToCodegenError();
@@ -33580,8 +33587,8 @@ var codegen = make58(
33580
33587
  try {
33581
33588
  const scriptInfo = service3.getScriptInfo(filePath);
33582
33589
  if (!scriptInfo) continue;
33583
- const project5 = scriptInfo.getDefaultProject();
33584
- const languageService = project5.getLanguageService(true);
33590
+ const project4 = scriptInfo.getDefaultProject();
33591
+ const languageService = project4.getLanguageService(true);
33585
33592
  disposeIfLanguageServiceChanged(languageService);
33586
33593
  const program = languageService.getProgram();
33587
33594
  if (!program) continue;
@@ -33590,8 +33597,8 @@ var codegen = make58(
33590
33597
  const pluginConfig = extractEffectLspOptions(program.getCompilerOptions());
33591
33598
  if (!pluginConfig) continue;
33592
33599
  const formatContext = tsInstance.formatting.getFormatContext(
33593
- tsInstance.getDefaultFormatCodeSettings(project5.getNewLine()),
33594
- project5
33600
+ tsInstance.getDefaultFormatCodeSettings(project4.getNewLine()),
33601
+ project4
33595
33602
  );
33596
33603
  const allFileChanges = pipe(
33597
33604
  gen3(function* () {
@@ -33606,7 +33613,7 @@ var codegen = make58(
33606
33613
  const changes2 = tsInstance.textChanges.ChangeTracker.with(
33607
33614
  {
33608
33615
  formatContext,
33609
- host: project5,
33616
+ host: project4,
33610
33617
  preferences: {}
33611
33618
  },
33612
33619
  (changeTracker) => pipe(
@@ -35528,6 +35535,11 @@ var runEffectInsideEffect = createDiagnostic({
35528
35535
  apply: fn2("runEffectInsideEffect.apply")(function* (sourceFile, report) {
35529
35536
  const ts = yield* service2(TypeScriptApi);
35530
35537
  const typeParser = yield* service2(TypeParser);
35538
+ const tsUtils = yield* service2(TypeScriptUtils);
35539
+ const parseEffectMethod = (node, methodName) => pipe(
35540
+ typeParser.isNodeReferenceToEffectModuleApi(methodName)(node),
35541
+ map34(() => ({ node, methodName }))
35542
+ );
35531
35543
  const nodeToVisit = [];
35532
35544
  const appendNodeToVisit = (node) => {
35533
35545
  nodeToVisit.push(node);
@@ -35538,11 +35550,12 @@ var runEffectInsideEffect = createDiagnostic({
35538
35550
  const node = nodeToVisit.shift();
35539
35551
  ts.forEachChild(node, appendNodeToVisit);
35540
35552
  if (!ts.isCallExpression(node)) continue;
35553
+ if (node.arguments.length === 0) continue;
35541
35554
  const isEffectRunCall = yield* pipe(
35542
- typeParser.isNodeReferenceToEffectModuleApi("runPromise")(node.expression),
35543
- orElse14(() => typeParser.isNodeReferenceToEffectModuleApi("runSync")(node.expression)),
35544
- orElse14(() => typeParser.isNodeReferenceToEffectModuleApi("runFork")(node.expression)),
35545
- orElse14(() => typeParser.isNodeReferenceToEffectModuleApi("runCallback")(node.expression)),
35555
+ parseEffectMethod(node.expression, "runPromise"),
35556
+ orElse14(() => parseEffectMethod(node.expression, "runSync")),
35557
+ orElse14(() => parseEffectMethod(node.expression, "runFork")),
35558
+ orElse14(() => parseEffectMethod(node.expression, "runCallback")),
35546
35559
  option4
35547
35560
  );
35548
35561
  if (isNone2(isEffectRunCall)) continue;
@@ -35562,18 +35575,90 @@ var runEffectInsideEffect = createDiagnostic({
35562
35575
  orElse14(() => typeParser.effectFnGen(possiblyEffectGen)),
35563
35576
  option4
35564
35577
  );
35565
- if (isSome2(isInEffectGen)) {
35578
+ if (isSome2(isInEffectGen) && isInEffectGen.value.body.statements.length > 0) {
35566
35579
  const nodeText = sourceFile.text.substring(
35567
35580
  ts.getTokenPosOfNode(node.expression, sourceFile),
35568
35581
  node.expression.end
35569
35582
  );
35570
- const messageText = nodeIntroduceScope && nodeIntroduceScope !== isInEffectGen.value.generatorFunction ? `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
35571
- Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.run* with the extracted runtime instead.` : `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`;
35572
- report({
35573
- location: node.expression,
35574
- messageText,
35575
- fixes: []
35576
- });
35583
+ if (nodeIntroduceScope && nodeIntroduceScope !== isInEffectGen.value.generatorFunction) {
35584
+ const fixAddRuntime = gen3(function* () {
35585
+ const changeTracker = yield* service2(ChangeTracker);
35586
+ const runtimeModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Runtime") || "Runtime";
35587
+ const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Effect") || "Effect";
35588
+ let runtimeIdentifier = void 0;
35589
+ for (const statement of isInEffectGen.value.generatorFunction.body.statements) {
35590
+ if (ts.isVariableStatement(statement) && statement.declarationList.declarations.length === 1) {
35591
+ const declaration = statement.declarationList.declarations[0];
35592
+ if (declaration.initializer && ts.isYieldExpression(declaration.initializer) && declaration.initializer.asteriskToken && declaration.initializer.expression) {
35593
+ const yieldedExpression = declaration.initializer.expression;
35594
+ if (ts.isCallExpression(yieldedExpression)) {
35595
+ const maybeEffectRuntime = yield* pipe(
35596
+ typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
35597
+ option4
35598
+ );
35599
+ if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
35600
+ runtimeIdentifier = ts.idText(declaration.name);
35601
+ }
35602
+ }
35603
+ }
35604
+ }
35605
+ }
35606
+ if (!runtimeIdentifier) {
35607
+ changeTracker.insertNodeAt(
35608
+ sourceFile,
35609
+ isInEffectGen.value.body.statements[0].pos,
35610
+ ts.factory.createVariableStatement(
35611
+ void 0,
35612
+ ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(
35613
+ "effectRuntime",
35614
+ void 0,
35615
+ void 0,
35616
+ ts.factory.createYieldExpression(
35617
+ ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
35618
+ ts.factory.createCallExpression(
35619
+ ts.factory.createPropertyAccessExpression(
35620
+ ts.factory.createIdentifier(effectModuleIdentifier),
35621
+ "runtime"
35622
+ ),
35623
+ [ts.factory.createTypeReferenceNode("never")],
35624
+ []
35625
+ )
35626
+ )
35627
+ )], ts.NodeFlags.Const)
35628
+ ),
35629
+ {
35630
+ prefix: "\n",
35631
+ suffix: "\n"
35632
+ }
35633
+ );
35634
+ }
35635
+ changeTracker.deleteRange(sourceFile, {
35636
+ pos: ts.getTokenPosOfNode(node.expression, sourceFile),
35637
+ end: node.arguments[0].pos
35638
+ });
35639
+ changeTracker.insertText(
35640
+ sourceFile,
35641
+ node.arguments[0].pos,
35642
+ `${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
35643
+ );
35644
+ });
35645
+ report({
35646
+ location: node.expression,
35647
+ messageText: `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
35648
+ Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`,
35649
+ fixes: [{
35650
+ fixName: "runEffectInsideEffect_fix",
35651
+ description: "Use a runtime to run the Effect",
35652
+ apply: fixAddRuntime
35653
+ }]
35654
+ });
35655
+ } else {
35656
+ report({
35657
+ location: node.expression,
35658
+ messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
35659
+ fixes: []
35660
+ });
35661
+ }
35577
35662
  }
35578
35663
  currentParent = currentParent.parent;
35579
35664
  }
@@ -36281,53 +36366,267 @@ var NoFilesToCheckError = class extends TaggedError("NoFilesToCheckError") {
36281
36366
  return "No files to check. Please provide an existing .ts file or a project tsconfig.json";
36282
36367
  }
36283
36368
  };
36284
- var file5 = file3("file").pipe(
36285
- optional4,
36286
- withDescription3("The full path of the file to check for diagnostics.")
36287
- );
36288
- var project3 = file3("project").pipe(
36289
- optional4,
36290
- withDescription3("The full path of the project tsconfig.json file to check for diagnostics.")
36291
- );
36369
+ var DiagnosticsFoundError = class extends TaggedError("DiagnosticsFoundError") {
36370
+ get message() {
36371
+ return `Found ${this.errorsCount} errors, ${this.warningsCount} warnings and ${this.messagesCount} messages.`;
36372
+ }
36373
+ };
36374
+ var categoryToSeverity = (category, tsInstance) => {
36375
+ switch (category) {
36376
+ case tsInstance.DiagnosticCategory.Error:
36377
+ return "error";
36378
+ case tsInstance.DiagnosticCategory.Warning:
36379
+ return "warning";
36380
+ default:
36381
+ return "message";
36382
+ }
36383
+ };
36384
+ var formatDiagnosticForJson = (diagnostic, tsInstance) => {
36385
+ if (!diagnostic.file || diagnostic.start === void 0) return void 0;
36386
+ const { character, line: line4 } = tsInstance.getLineAndCharacterOfPosition(diagnostic.file, diagnostic.start);
36387
+ const endPos = diagnostic.start + (diagnostic.length ?? 0);
36388
+ const { character: endCharacter, line: endLine } = tsInstance.getLineAndCharacterOfPosition(diagnostic.file, endPos);
36389
+ const diagnosticName = Object.values(diagnostics).find((_) => _.code === diagnostic.code)?.name ?? `effect(${diagnostic.code})`;
36390
+ return {
36391
+ file: diagnostic.file.fileName,
36392
+ line: line4 + 1,
36393
+ column: character + 1,
36394
+ endLine: endLine + 1,
36395
+ endColumn: endCharacter + 1,
36396
+ severity: categoryToSeverity(diagnostic.category, tsInstance),
36397
+ code: diagnostic.code,
36398
+ name: diagnosticName,
36399
+ message: tsInstance.flattenDiagnosticMessageText(diagnostic.messageText, "\n")
36400
+ };
36401
+ };
36402
+ var severityToGitHubCommand = (severity) => {
36403
+ switch (severity) {
36404
+ case "error":
36405
+ return "error";
36406
+ case "warning":
36407
+ return "warning";
36408
+ default:
36409
+ return "notice";
36410
+ }
36411
+ };
36412
+ var formatDiagnosticForGitHubActions = (diagnostic, tsInstance) => {
36413
+ const output = formatDiagnosticForJson(diagnostic, tsInstance);
36414
+ if (!output) return void 0;
36415
+ const command = severityToGitHubCommand(output.severity);
36416
+ const message = output.message.replace(/%/g, "%25").replace(/\r/g, "%0D").replace(/\n/g, "%0A");
36417
+ return `::${command} file=${output.file},line=${output.line},col=${output.column},endLine=${output.endLine},endColumn=${output.endColumn},title=${output.name}::${message}`;
36418
+ };
36419
+ var parseSeverityFilter = (severityOption) => {
36420
+ if (isNone2(severityOption)) return void 0;
36421
+ const levels = severityOption.value.split(",").map((s) => s.trim().toLowerCase());
36422
+ const validLevels = /* @__PURE__ */ new Set();
36423
+ for (const level of levels) {
36424
+ if (level === "error" || level === "warning" || level === "message") {
36425
+ validLevels.add(level);
36426
+ }
36427
+ }
36428
+ return validLevels.size > 0 ? validLevels : void 0;
36429
+ };
36430
+ var diagnosticPrettyFormatter = gen2(function* () {
36431
+ const path2 = yield* Path2;
36432
+ return identity({
36433
+ onBegin: () => _void,
36434
+ onFile: () => _void,
36435
+ onDiagnostics: (state, _filePath, diagnostics3) => sync4(() => {
36436
+ const rawFormatted = state.tsInstance.formatDiagnosticsWithColorAndContext(diagnostics3, {
36437
+ getCanonicalFileName: (fileName) => path2.resolve(fileName),
36438
+ getCurrentDirectory: () => path2.resolve("."),
36439
+ getNewLine: () => "\n"
36440
+ });
36441
+ return Object.values(diagnostics).reduce(
36442
+ (text9, def) => text9.replace(new RegExp(`TS${def.code}:`, "g"), `effect(${def.name}):`),
36443
+ rawFormatted
36444
+ );
36445
+ }).pipe(flatMap9(log3), when2(() => diagnostics3.length > 0)),
36446
+ onEnd: (state) => log3(
36447
+ `Checked ${state.checkedCount} files out of ${state.totalFilesCount} files.
36448
+ ${state.errorsCount} errors, ${state.warningsCount} warnings and ${state.messagesCount} messages.`
36449
+ )
36450
+ });
36451
+ });
36452
+ var diagnosticTextFormatter = gen2(function* () {
36453
+ const path2 = yield* Path2;
36454
+ return identity({
36455
+ onBegin: () => _void,
36456
+ onFile: () => _void,
36457
+ onDiagnostics: (state, _filePath, diagnostics3) => sync4(() => {
36458
+ const rawFormatted = state.tsInstance.formatDiagnostics(diagnostics3, {
36459
+ getCanonicalFileName: (fileName) => path2.resolve(fileName),
36460
+ getCurrentDirectory: () => path2.resolve("."),
36461
+ getNewLine: () => "\n"
36462
+ });
36463
+ return Object.values(diagnostics).reduce(
36464
+ (text9, def) => text9.replace(new RegExp(`TS${def.code}:`, "g"), `effect(${def.name}):`),
36465
+ rawFormatted
36466
+ );
36467
+ }).pipe(flatMap9(log3), when2(() => diagnostics3.length > 0)),
36468
+ onEnd: (state) => log3(
36469
+ `Checked ${state.checkedCount} files out of ${state.totalFilesCount} files.
36470
+ ${state.errorsCount} errors, ${state.warningsCount} warnings and ${state.messagesCount} messages.`
36471
+ )
36472
+ });
36473
+ });
36474
+ var diagnosticJsonFormatter = gen2(function* () {
36475
+ let hasEmittedDiagnostics = false;
36476
+ return identity({
36477
+ onBegin: () => log3(`{ "diagnostics": [`),
36478
+ onFile: () => _void,
36479
+ onDiagnostics: (state, _filePath, diagnostics3) => gen2(function* () {
36480
+ for (const diagnostic of diagnostics3) {
36481
+ const jsonDiagnostic = formatDiagnosticForJson(diagnostic, state.tsInstance);
36482
+ if (jsonDiagnostic) {
36483
+ if (hasEmittedDiagnostics) yield* log3(", ");
36484
+ yield* log3(JSON.stringify(jsonDiagnostic, null, 2));
36485
+ hasEmittedDiagnostics = true;
36486
+ }
36487
+ }
36488
+ }),
36489
+ onEnd: (state) => log3(`], "summary": ${JSON.stringify(
36490
+ {
36491
+ filesChecked: state.checkedCount,
36492
+ totalFiles: state.totalFilesCount,
36493
+ errors: state.errorsCount,
36494
+ warnings: state.warningsCount,
36495
+ messages: state.messagesCount
36496
+ },
36497
+ null,
36498
+ 2
36499
+ )} }`)
36500
+ });
36501
+ });
36502
+ var diagnosticGitHubActionsFormatter = gen2(function* () {
36503
+ return identity({
36504
+ onBegin: () => _void,
36505
+ onFile: () => _void,
36506
+ onDiagnostics: (state, _filePath, diagnostics3) => gen2(function* () {
36507
+ if (diagnostics3.length === 0) return;
36508
+ for (const diagnostic of diagnostics3) {
36509
+ const formatted = formatDiagnosticForGitHubActions(diagnostic, state.tsInstance);
36510
+ if (formatted) {
36511
+ yield* log3(formatted);
36512
+ }
36513
+ }
36514
+ }),
36515
+ onEnd: (state) => log3(
36516
+ `Checked ${state.checkedCount} files out of ${state.totalFilesCount} files.
36517
+ ${state.errorsCount} errors, ${state.warningsCount} warnings and ${state.messagesCount} messages.`
36518
+ )
36519
+ });
36520
+ });
36521
+ var withDiagnosticsProgressFormatter = (formatter) => gen2(function* () {
36522
+ return identity({
36523
+ onBegin: (state) => sync4(() => process.stderr.write(`Starting diagnostics for ${state.totalFilesCount} files...
36524
+ `)).pipe(
36525
+ flatMap9(() => formatter.onBegin(state))
36526
+ ),
36527
+ onFile: (state, filePath) => sync4(
36528
+ () => process.stderr.write(
36529
+ `[${state.currentFileIndex}/${state.totalFilesCount}] ${filePath.slice(-60).padStart(60)}\r`
36530
+ )
36531
+ ).pipe(
36532
+ flatMap9(() => formatter.onFile(state, filePath))
36533
+ ),
36534
+ onDiagnostics: (state, filePath, diagnostics3) => formatter.onDiagnostics(state, filePath, diagnostics3),
36535
+ onEnd: (state) => sync4(() => process.stderr.write("\n")).pipe(
36536
+ flatMap9(() => formatter.onEnd(state))
36537
+ )
36538
+ });
36539
+ });
36292
36540
  var BATCH_SIZE2 = 50;
36293
36541
  var diagnostics2 = make58(
36294
36542
  "diagnostics",
36295
- { file: file5, project: project3 },
36296
- fn("diagnostics")(function* ({ file: file6, project: project4 }) {
36543
+ {
36544
+ file: file3("file").pipe(
36545
+ optional4,
36546
+ withDescription3("The full path of the file to check for diagnostics.")
36547
+ ),
36548
+ project: file3("project").pipe(
36549
+ optional4,
36550
+ withDescription3("The full path of the project tsconfig.json file to check for diagnostics.")
36551
+ ),
36552
+ format: choice3("format", ["json", "pretty", "text", "github-actions"]).pipe(
36553
+ withDefault3("pretty"),
36554
+ withDescription3(
36555
+ "Output format: json (machine-readable), pretty (colored with context), text (plain text), github-actions (workflow commands)"
36556
+ )
36557
+ ),
36558
+ strict: boolean5("strict").pipe(
36559
+ withDefault3(false),
36560
+ withDescription3("Treat warnings as errors (affects exit code)")
36561
+ ),
36562
+ severity: text8("severity").pipe(
36563
+ optional4,
36564
+ withDescription3("Filter by severity levels (comma-separated: error,warning,message)")
36565
+ ),
36566
+ progress: boolean5("progress").pipe(
36567
+ withDefault3(false),
36568
+ withDescription3("Show progress as files are checked (outputs to stderr)")
36569
+ )
36570
+ },
36571
+ fn("diagnostics")(function* ({ file: file5, format: format6, progress, project: project3, severity, strict: strict2 }) {
36297
36572
  const path2 = yield* Path2;
36298
- const tsInstance = yield* getTypeScript;
36299
- let filesToCheck = /* @__PURE__ */ new Set();
36300
- let checkedFilesCount = 0;
36301
- let errorsCount = 0;
36302
- let warningsCount = 0;
36303
- let messagesCount = 0;
36304
- if (isSome2(project4)) {
36305
- filesToCheck = yield* getFileNamesInTsConfig(project4.value);
36306
- }
36307
- if (isSome2(file6)) {
36308
- filesToCheck.add(path2.resolve(file6.value));
36573
+ const severityFilter = parseSeverityFilter(severity);
36574
+ const state = {
36575
+ tsInstance: yield* getTypeScript,
36576
+ checkedCount: 0,
36577
+ errorsCount: 0,
36578
+ warningsCount: 0,
36579
+ messagesCount: 0,
36580
+ languageService: void 0,
36581
+ totalFilesCount: 0,
36582
+ currentFileIndex: 0
36583
+ };
36584
+ const filesToCheck = isSome2(project3) ? yield* getFileNamesInTsConfig(project3.value) : /* @__PURE__ */ new Set();
36585
+ if (isSome2(file5)) {
36586
+ filesToCheck.add(path2.resolve(file5.value));
36309
36587
  }
36310
36588
  if (filesToCheck.size === 0) {
36311
36589
  return yield* new NoFilesToCheckError();
36312
36590
  }
36313
- const filesToCheckArray = fromIterable(filesToCheck);
36314
- const batches = chunksOf(filesToCheckArray, BATCH_SIZE2);
36315
- let lastLanguageService;
36591
+ state.totalFilesCount = filesToCheck.size;
36592
+ let reporter;
36593
+ switch (format6) {
36594
+ case "pretty":
36595
+ reporter = yield* diagnosticPrettyFormatter;
36596
+ break;
36597
+ case "text":
36598
+ reporter = yield* diagnosticTextFormatter;
36599
+ break;
36600
+ case "json":
36601
+ reporter = yield* diagnosticJsonFormatter;
36602
+ break;
36603
+ case "github-actions":
36604
+ reporter = yield* diagnosticGitHubActionsFormatter;
36605
+ break;
36606
+ default:
36607
+ reporter = yield* diagnosticPrettyFormatter;
36608
+ }
36609
+ if (progress) {
36610
+ reporter = yield* withDiagnosticsProgressFormatter(reporter);
36611
+ }
36612
+ yield* reporter.onBegin(state);
36316
36613
  const disposeIfLanguageServiceChanged = (languageService) => {
36317
- if (lastLanguageService !== languageService) {
36318
- lastLanguageService?.dispose();
36319
- lastLanguageService = languageService;
36614
+ if (state.languageService !== languageService) {
36615
+ state.languageService?.dispose();
36616
+ state.languageService = languageService;
36320
36617
  }
36321
36618
  };
36322
- for (const batch of batches) {
36619
+ for (const batch of chunksOf(filesToCheck, BATCH_SIZE2)) {
36323
36620
  const { service: service3 } = (0, import_project_service2.createProjectService)({ options: { loadTypeScriptPlugins: false } });
36324
36621
  for (const filePath of batch) {
36622
+ state.currentFileIndex++;
36623
+ yield* reporter.onFile(state, filePath);
36325
36624
  service3.openClientFile(filePath);
36326
36625
  try {
36327
36626
  const scriptInfo = service3.getScriptInfo(filePath);
36328
36627
  if (!scriptInfo) continue;
36329
- const project5 = scriptInfo.getDefaultProject();
36330
- const languageService = project5.getLanguageService(true);
36628
+ const projectInfo = scriptInfo.getDefaultProject();
36629
+ const languageService = projectInfo.getLanguageService(true);
36331
36630
  disposeIfLanguageServiceChanged(languageService);
36332
36631
  const program = languageService.getProgram();
36333
36632
  if (!program) continue;
@@ -36335,14 +36634,14 @@ var diagnostics2 = make58(
36335
36634
  if (!sourceFile) continue;
36336
36635
  const pluginConfig = extractEffectLspOptions(program.getCompilerOptions());
36337
36636
  if (!pluginConfig) continue;
36338
- const results = pipe(
36637
+ const rawResults = pipe(
36339
36638
  getSemanticDiagnosticsWithCodeFixes(diagnostics, sourceFile),
36340
36639
  nanoLayer3,
36341
36640
  nanoLayer2,
36342
36641
  nanoLayer,
36343
36642
  provideService7(TypeCheckerApi, program.getTypeChecker()),
36344
36643
  provideService7(TypeScriptProgram, program),
36345
- provideService7(TypeScriptApi, tsInstance),
36644
+ provideService7(TypeScriptApi, state.tsInstance),
36346
36645
  provideService7(
36347
36646
  LanguageServicePluginOptions,
36348
36647
  { ...parse4(pluginConfig), diagnosticsName: false }
@@ -36351,26 +36650,21 @@ var diagnostics2 = make58(
36351
36650
  map((_) => _.diagnostics),
36352
36651
  map(
36353
36652
  map4(
36354
- (_) => _.category === tsInstance.DiagnosticCategory.Suggestion ? { ..._, category: tsInstance.DiagnosticCategory.Message } : _
36653
+ (_) => _.category === state.tsInstance.DiagnosticCategory.Suggestion ? { ..._, category: state.tsInstance.DiagnosticCategory.Message } : _
36355
36654
  )
36356
36655
  ),
36357
36656
  getOrElse(() => [])
36358
36657
  );
36359
- checkedFilesCount++;
36360
- errorsCount += results.filter((_) => _.category === tsInstance.DiagnosticCategory.Error).length;
36361
- warningsCount += results.filter((_) => _.category === tsInstance.DiagnosticCategory.Warning).length;
36362
- messagesCount += results.filter((_) => _.category === tsInstance.DiagnosticCategory.Message).length;
36363
- if (results.length > 0) {
36364
- let formattedResults = tsInstance.formatDiagnosticsWithColorAndContext(results, {
36365
- getCanonicalFileName: (fileName) => path2.resolve(fileName),
36366
- getCurrentDirectory: () => path2.resolve("."),
36367
- getNewLine: () => "\n"
36368
- });
36369
- Object.values(diagnostics).forEach(
36370
- (_) => formattedResults = formattedResults.replace(new RegExp(`TS${_.code}:`, "g"), `effect(${_.name}):`)
36371
- );
36372
- console.log(formattedResults);
36373
- }
36658
+ const results = severityFilter ? rawResults.filter((d) => severityFilter.has(categoryToSeverity(d.category, state.tsInstance))) : rawResults;
36659
+ state.checkedCount++;
36660
+ state.errorsCount += results.filter((_) => _.category === state.tsInstance.DiagnosticCategory.Error).length;
36661
+ state.warningsCount += results.filter(
36662
+ (_) => _.category === state.tsInstance.DiagnosticCategory.Warning
36663
+ ).length;
36664
+ state.messagesCount += results.filter(
36665
+ (_) => _.category === state.tsInstance.DiagnosticCategory.Message
36666
+ ).length;
36667
+ yield* reporter.onDiagnostics(state, filePath, results);
36374
36668
  } finally {
36375
36669
  service3.closeClientFile(filePath);
36376
36670
  }
@@ -36378,10 +36672,9 @@ var diagnostics2 = make58(
36378
36672
  yield* yieldNow4();
36379
36673
  }
36380
36674
  disposeIfLanguageServiceChanged(void 0);
36381
- console.log(
36382
- `Checked ${checkedFilesCount} files out of ${filesToCheck.size} files.
36383
- ${errorsCount} errors, ${warningsCount} warnings and ${messagesCount} messages.`
36384
- );
36675
+ yield* reporter.onEnd(state);
36676
+ const hasFailures = state.errorsCount > 0 || strict2 && state.warningsCount > 0;
36677
+ if (hasFailures) return yield* sync4(() => process.exit(1));
36385
36678
  })
36386
36679
  );
36387
36680
 
@@ -36428,8 +36721,8 @@ var getPatchesForModule = fn("getPatchesForModule")(
36428
36721
  }
36429
36722
  return find3(sourceFile2);
36430
36723
  }
36431
- function pushFunctionDeclarationNode(text8) {
36432
- const regex = new RegExp(text8, "ig");
36724
+ function pushFunctionDeclarationNode(text9) {
36725
+ const regex = new RegExp(text9, "ig");
36433
36726
  let pushed = false;
36434
36727
  let match18;
36435
36728
  while ((match18 = regex.exec(sourceFile.text)) !== null) {