@effect/language-service 0.55.5 → 0.56.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.
Files changed (4) hide show
  1. package/README.md +3 -0
  2. package/cli.js +517 -361
  3. package/cli.js.map +1 -1
  4. package/package.json +1 -1
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: (file5) => fs.readFileSync(path2.isAbsolute(file5) ? file5 : path2.join(getCurrentDirectory(), file5), "utf-8"),
870
+ readFile: (file6) => fs.readFileSync(path2.isAbsolute(file6) ? file6 : path2.join(getCurrentDirectory(), file6), "utf-8"),
871
871
  useCaseSensitiveFileNames: tsserver.sys.useCaseSensitiveFileNames
872
872
  });
873
873
  if (parsed?.errors.length) {
@@ -942,7 +942,7 @@ var require_createProjectService = __commonJS({
942
942
  return mod && mod.__esModule ? mod : { "default": mod };
943
943
  };
944
944
  Object.defineProperty(exports2, "__esModule", { value: true });
945
- exports2.createProjectService = createProjectService2;
945
+ exports2.createProjectService = createProjectService3;
946
946
  var debug_1 = __importDefault(require_src());
947
947
  var getParsedConfigFileFromTSServer_js_1 = require_getParsedConfigFileFromTSServer();
948
948
  var DEFAULT_PROJECT_MATCHED_FILES_THRESHOLD = 8;
@@ -956,7 +956,7 @@ var require_createProjectService = __commonJS({
956
956
  var createStubFileWatcher = () => ({
957
957
  close: doNothing
958
958
  });
959
- function createProjectService2({ jsDocParsingMode, options: optionsRaw = {}, tsconfigRootDir } = {}) {
959
+ function createProjectService3({ jsDocParsingMode, options: optionsRaw = {}, tsconfigRootDir } = {}) {
960
960
  const options3 = {
961
961
  defaultProject: "tsconfig.json",
962
962
  ...optionsRaw
@@ -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((file5) => file5.seek(options3.offset, "start")) : identity, map17((file5) => stream(file5, options3)), unwrapScoped6),
22837
+ }), options3?.offset ? tap2((file6) => file6.seek(options3.offset, "start")) : identity, map17((file6) => stream(file6, options3)), unwrapScoped6),
22838
22838
  sink: (path2, options3) => pipe(impl.open(path2, {
22839
22839
  flag: "w",
22840
22840
  ...options3
22841
- }), map17((file5) => forEach10((_) => file5.writeAll(_))), unwrapScoped5),
22841
+ }), map17((file6) => forEach10((_) => file6.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 = (file5, {
22853
+ var stream = (file6, {
22854
22854
  bufferSize = 16,
22855
22855
  bytesToRead: bytesToRead_,
22856
22856
  chunkSize: chunkSize_ = Size(64 * 1024)
@@ -22862,7 +22862,7 @@ var stream = (file5, {
22862
22862
  return void_6;
22863
22863
  }
22864
22864
  const toRead = bytesToRead !== void 0 && bytesToRead - totalBytesRead < chunkSize ? bytesToRead - totalBytesRead : chunkSize;
22865
- return flatMap15(file5.readAlloc(toRead), match2({
22865
+ return flatMap15(file6.readAlloc(toRead), match2({
22866
22866
  onNone: () => void_6,
22867
22867
  onSome: (buf) => flatMap15(write2(of2(buf)), (_) => loop2(totalBytesRead + BigInt(buf.length)))
22868
22868
  }));
@@ -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, (file5) => {
24172
- const result = options3.filter(file5);
24171
+ return yield* filter8(files, (file6) => {
24172
+ const result = options3.filter(file6);
24173
24173
  const userDefinedFilter = isEffect2(result) ? result : succeed7(result);
24174
- const directoryFilter = options3.type === "directory" ? map17(orDie2(fs.stat(path2.join(directory3, file5))), (info2) => info2.type === "Directory") : succeed7(true);
24174
+ const directoryFilter = options3.type === "directory" ? map17(orDie2(fs.stat(path2.join(directory3, file6))), (info2) => info2.type === "Directory") : succeed7(true);
24175
24175
  return zipWith4(userDefinedFilter, directoryFilter, (a, b) => a && b);
24176
24176
  }, {
24177
24177
  concurrency: files.length
@@ -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(file5, isSelected) {
24224
- return isSelected ? annotate2(text3(file5), combine10(underlined2, cyanBright2)) : text3(file5);
24223
+ function renderFileName(file6, isSelected) {
24224
+ return isSelected ? annotate2(text3(file6), combine10(underlined2, cyanBright2)) : text3(file6);
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((file5) => file5 !== "..");
24328
+ const filesWithoutParent = files.filter((file6) => file6 !== "..");
24329
24329
  if (options3.type === "directory" || options3.type === "either") {
24330
24330
  return filesWithoutParent.length === 0 ? Action.Submit({
24331
24331
  value: resolvedPath
@@ -28899,7 +28899,7 @@ var makeTempFile = /* @__PURE__ */ makeTempFileFactory("makeTempFile");
28899
28899
  var makeTempFileScoped = /* @__PURE__ */ (() => {
28900
28900
  const makeFile2 = /* @__PURE__ */ makeTempFileFactory("makeTempFileScoped");
28901
28901
  const removeDirectory = /* @__PURE__ */ removeFactory("makeTempFileScoped");
28902
- return (options3) => acquireRelease2(makeFile2(options3), (file5) => orDie2(removeDirectory(Path3.dirname(file5), {
28902
+ return (options3) => acquireRelease2(makeFile2(options3), (file6) => orDie2(removeDirectory(Path3.dirname(file6), {
28903
28903
  recursive: true
28904
28904
  })));
28905
28905
  })();
@@ -31150,6 +31150,34 @@ var omitBundlerSourceFileComment = fn("omitBundlerSourceFileComment")(
31150
31150
  return yield* applyTextChanges(sourceFile.text, deleteChanges);
31151
31151
  }
31152
31152
  );
31153
+ var extractEffectLspOptions = (compilerOptions) => {
31154
+ return (hasProperty(compilerOptions, "plugins") && Array.isArray(compilerOptions.plugins) ? compilerOptions.plugins : []).find((_) => hasProperty(_, "name") && _.name === "@effect/language-service");
31155
+ };
31156
+ var getFileNamesInTsConfig = fn("getFileNamesInTsConfig")(function* (tsconfigPath) {
31157
+ const path2 = yield* Path2;
31158
+ const tsInstance = yield* getTypeScript;
31159
+ const filesToCheck = /* @__PURE__ */ new Set();
31160
+ let tsconfigToHandle = [tsconfigPath];
31161
+ while (tsconfigToHandle.length > 0) {
31162
+ const tsconfigPath2 = tsconfigToHandle.shift();
31163
+ const tsconfigAbsolutePath = path2.resolve(tsconfigPath2);
31164
+ const configFile = tsInstance.readConfigFile(tsconfigAbsolutePath, tsInstance.sys.readFile);
31165
+ if (configFile.error) {
31166
+ if (!tsconfigAbsolutePath.endsWith("tsconfig.json")) {
31167
+ tsconfigToHandle = [...tsconfigToHandle, path2.resolve(tsconfigPath2, "tsconfig.json")];
31168
+ }
31169
+ continue;
31170
+ }
31171
+ const parsedConfig = tsInstance.parseJsonConfigFileContent(
31172
+ configFile.config,
31173
+ tsInstance.sys,
31174
+ path2.dirname(tsconfigAbsolutePath)
31175
+ );
31176
+ tsconfigToHandle = [...tsconfigToHandle, ...parsedConfig.projectReferences?.map((_) => _.path) ?? []];
31177
+ parsedConfig.fileNames.forEach((_) => filesToCheck.add(_));
31178
+ }
31179
+ return filesToCheck;
31180
+ });
31153
31181
 
31154
31182
  // src/cli/check.ts
31155
31183
  var LOCAL_TYPESCRIPT_DIR = "./node_modules/typescript";
@@ -31186,7 +31214,7 @@ var check2 = make58(
31186
31214
  })
31187
31215
  );
31188
31216
 
31189
- // src/cli/diagnostics.ts
31217
+ // src/cli/codegen.ts
31190
31218
  var import_project_service = __toESM(require_dist2());
31191
31219
 
31192
31220
  // src/core/LanguageServicePluginOptions.ts
@@ -31565,9 +31593,9 @@ var getCodegensForSourceFile = fn2("LSP.getApplicableCodegens")(function* (codeg
31565
31593
  pos: codegenMatch.index + pos + whitespace.length,
31566
31594
  end: codegenMatch.index + pos + codegenMatch[0].length
31567
31595
  };
31568
- const codegen = codegens2.find((codegen2) => codegen2.name === codegenName);
31569
- if (!codegen) continue;
31570
- result.push({ codegen, hash: codegenHash, range: range3 });
31596
+ const codegen2 = codegens2.find((codegen3) => codegen3.name === codegenName);
31597
+ if (!codegen2) continue;
31598
+ result.push({ codegen: codegen2, hash: codegenHash, range: range3 });
31571
31599
  }
31572
31600
  }
31573
31601
  return result;
@@ -31575,18 +31603,18 @@ var getCodegensForSourceFile = fn2("LSP.getApplicableCodegens")(function* (codeg
31575
31603
  var getEditsForCodegen = fn2("LSP.getEditsForCodegen")(function* (codegens2, sourceFile, textRange) {
31576
31604
  const applicableCodegens = yield* getCodegensForSourceFile(codegens2, sourceFile);
31577
31605
  const inRangeCodegens = applicableCodegens.filter(
31578
- (codegen2) => codegen2.range.pos <= textRange.pos && codegen2.range.end >= textRange.end
31606
+ (codegen3) => codegen3.range.pos <= textRange.pos && codegen3.range.end >= textRange.end
31579
31607
  );
31580
31608
  if (inRangeCodegens.length !== 1) {
31581
31609
  return yield* fail18(new CodegenNotApplicableError("zero or multiple codegens in range"));
31582
31610
  }
31583
- const { codegen, range: range3 } = inRangeCodegens[0];
31584
- const edit = yield* codegen.apply(sourceFile, range3);
31611
+ const { codegen: codegen2, range: range3 } = inRangeCodegens[0];
31612
+ const edit = yield* codegen2.apply(sourceFile, range3);
31585
31613
  const updateHashComment = pipe(
31586
31614
  service2(ChangeTracker),
31587
31615
  map34((changeTracker) => {
31588
31616
  changeTracker.deleteRange(sourceFile, range3);
31589
- changeTracker.insertText(sourceFile, range3.pos, `${codegen.name}:${edit.hash}`);
31617
+ changeTracker.insertText(sourceFile, range3.pos, `${codegen2.name}:${edit.hash}`);
31590
31618
  })
31591
31619
  );
31592
31620
  return {
@@ -33063,6 +33091,449 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
33063
33091
  };
33064
33092
  }
33065
33093
 
33094
+ // src/refactors/writeTagClassAccessors.ts
33095
+ var generate = fn2("writeTagClassAccessors.generate")(function* (sourceFile, service3, className, atLocation, involvedMembers) {
33096
+ const ts = yield* service2(TypeScriptApi);
33097
+ const tsUtils = yield* service2(TypeScriptUtils);
33098
+ const typeChecker = yield* service2(TypeCheckerApi);
33099
+ const typeParser = yield* service2(TypeParser);
33100
+ const changeTracker = yield* service2(ChangeTracker);
33101
+ const insertLocation = atLocation.members.length > 0 ? atLocation.members[0].pos : atLocation.end - 1;
33102
+ const effectIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
33103
+ sourceFile,
33104
+ "effect",
33105
+ "Effect"
33106
+ ) || "Effect";
33107
+ const createFunctionProperty = (className2, propertyName, type2, forceAny) => {
33108
+ const arrowBody = ts.factory.createCallExpression(
33109
+ ts.factory.createPropertyAccessExpression(
33110
+ ts.factory.createIdentifier(effectIdentifier),
33111
+ "andThen"
33112
+ ),
33113
+ void 0,
33114
+ [
33115
+ ts.factory.createIdentifier(ts.idText(className2)),
33116
+ ts.factory.createArrowFunction(
33117
+ void 0,
33118
+ void 0,
33119
+ [ts.factory.createParameterDeclaration(
33120
+ void 0,
33121
+ void 0,
33122
+ "_",
33123
+ void 0,
33124
+ forceAny ? ts.factory.createTypeReferenceNode("any") : void 0
33125
+ )],
33126
+ void 0,
33127
+ void 0,
33128
+ ts.factory.createCallExpression(
33129
+ ts.factory.createPropertyAccessExpression(
33130
+ ts.factory.createIdentifier("_"),
33131
+ propertyName
33132
+ ),
33133
+ void 0,
33134
+ [
33135
+ ts.factory.createSpreadElement(ts.factory.createIdentifier("args"))
33136
+ ]
33137
+ )
33138
+ )
33139
+ ]
33140
+ );
33141
+ return ts.factory.createPropertyDeclaration(
33142
+ [
33143
+ ts.factory.createModifier(ts.SyntaxKind.StaticKeyword),
33144
+ ts.factory.createModifier(ts.SyntaxKind.OverrideKeyword)
33145
+ ],
33146
+ propertyName,
33147
+ void 0,
33148
+ type2,
33149
+ ts.factory.createArrowFunction(
33150
+ void 0,
33151
+ void 0,
33152
+ [ts.factory.createParameterDeclaration(
33153
+ void 0,
33154
+ ts.factory.createToken(ts.SyntaxKind.DotDotDotToken),
33155
+ "args",
33156
+ void 0,
33157
+ forceAny ? ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("any")) : void 0
33158
+ )],
33159
+ void 0,
33160
+ void 0,
33161
+ forceAny ? ts.factory.createAsExpression(arrowBody, ts.factory.createTypeReferenceNode("any")) : arrowBody
33162
+ )
33163
+ );
33164
+ };
33165
+ const generateReturnType = (type2, atLocation2, className2) => pipe(
33166
+ typeParser.effectType(type2, atLocation2),
33167
+ flatMap18((returnedEffect) => {
33168
+ const contextType = returnedEffect.R.flags & ts.TypeFlags.Never ? ts.factory.createTypeReferenceNode(ts.idText(className2)) : ts.factory.createUnionTypeNode(
33169
+ [
33170
+ ts.factory.createTypeReferenceNode(ts.idText(className2)),
33171
+ typeChecker.typeToTypeNode(returnedEffect.R, atLocation2, ts.NodeBuilderFlags.NoTruncation)
33172
+ ]
33173
+ );
33174
+ const successType = typeChecker.typeToTypeNode(
33175
+ returnedEffect.A,
33176
+ atLocation2,
33177
+ ts.NodeBuilderFlags.NoTruncation
33178
+ );
33179
+ if (!successType) return fail18("error generating success type");
33180
+ const failureType = typeChecker.typeToTypeNode(
33181
+ returnedEffect.E,
33182
+ atLocation2,
33183
+ ts.NodeBuilderFlags.NoTruncation
33184
+ );
33185
+ if (!failureType) return fail18("error generating failure type");
33186
+ const typeNode = ts.factory.createTypeReferenceNode(
33187
+ ts.factory.createQualifiedName(
33188
+ ts.factory.createIdentifier(effectIdentifier),
33189
+ ts.factory.createIdentifier("Effect")
33190
+ ),
33191
+ [successType, failureType, contextType]
33192
+ );
33193
+ return succeed17(typeNode);
33194
+ }),
33195
+ orElse14(
33196
+ () => pipe(
33197
+ typeParser.promiseLike(type2, atLocation2),
33198
+ flatMap18(({ type: type3 }) => {
33199
+ const successType = typeChecker.typeToTypeNode(
33200
+ type3,
33201
+ atLocation2,
33202
+ ts.NodeBuilderFlags.NoTruncation
33203
+ );
33204
+ if (!successType) return fail18("error generating success type");
33205
+ return succeed17(ts.factory.createTypeReferenceNode(
33206
+ ts.factory.createQualifiedName(
33207
+ ts.factory.createIdentifier(effectIdentifier),
33208
+ ts.factory.createIdentifier("Effect")
33209
+ ),
33210
+ [
33211
+ successType,
33212
+ ts.factory.createTypeReferenceNode(
33213
+ ts.factory.createQualifiedName(
33214
+ ts.factory.createIdentifier("Cause"),
33215
+ ts.factory.createIdentifier("UnknownException")
33216
+ )
33217
+ ),
33218
+ ts.factory.createTypeReferenceNode(ts.idText(className2))
33219
+ ]
33220
+ ));
33221
+ })
33222
+ )
33223
+ ),
33224
+ orElse14(() => {
33225
+ const successType = typeChecker.typeToTypeNode(type2, atLocation2, ts.NodeBuilderFlags.NoTruncation);
33226
+ if (!successType) return fail18("error generating success type");
33227
+ const typeNode = ts.factory.createTypeReferenceNode(
33228
+ ts.factory.createQualifiedName(
33229
+ ts.factory.createIdentifier(effectIdentifier),
33230
+ ts.factory.createIdentifier("Effect")
33231
+ ),
33232
+ [
33233
+ successType,
33234
+ ts.factory.createTypeReferenceNode("never"),
33235
+ ts.factory.createTypeReferenceNode(ts.idText(className2))
33236
+ ]
33237
+ );
33238
+ return succeed17(typeNode);
33239
+ })
33240
+ );
33241
+ const proxySignature = (signature, atLocation2, className2) => gen3(function* () {
33242
+ const signatureDeclaration = typeChecker.signatureToSignatureDeclaration(
33243
+ signature,
33244
+ ts.SyntaxKind.FunctionType,
33245
+ atLocation2,
33246
+ ts.NodeBuilderFlags.NoTruncation
33247
+ );
33248
+ if (!signatureDeclaration) return yield* fail18("error generating signature");
33249
+ const returnType = yield* generateReturnType(
33250
+ typeChecker.getReturnTypeOfSignature(signature),
33251
+ atLocation2,
33252
+ className2
33253
+ );
33254
+ return ts.factory.createFunctionTypeNode(
33255
+ signatureDeclaration.typeParameters,
33256
+ signatureDeclaration.parameters,
33257
+ returnType
33258
+ );
33259
+ });
33260
+ for (const { property, propertyType } of involvedMembers) {
33261
+ const callSignatures = [];
33262
+ let propertyDeclaration = void 0;
33263
+ for (const signature of typeChecker.getSignaturesOfType(propertyType, ts.SignatureKind.Call)) {
33264
+ yield* pipe(
33265
+ proxySignature(signature, atLocation, className),
33266
+ map34((sig) => {
33267
+ callSignatures.push(sig);
33268
+ }),
33269
+ ignore3
33270
+ );
33271
+ }
33272
+ const allSignatures = ts.factory.createIntersectionTypeNode(callSignatures);
33273
+ const type2 = tsUtils.simplifyTypeNode(allSignatures);
33274
+ propertyDeclaration = createFunctionProperty(className, ts.symbolName(property), type2, callSignatures.length > 1);
33275
+ const oldProperty = atLocation.members.filter(ts.isPropertyDeclaration).find((p2) => {
33276
+ const symbol3 = typeChecker.getSymbolAtLocation(p2.name);
33277
+ return symbol3 && ts.symbolName(symbol3) === ts.symbolName(property);
33278
+ });
33279
+ if (oldProperty) {
33280
+ const start4 = ts.getTokenPosOfNode(oldProperty, sourceFile);
33281
+ changeTracker.deleteRange(sourceFile, {
33282
+ pos: start4,
33283
+ end: oldProperty.end
33284
+ });
33285
+ changeTracker.insertNodeAt(sourceFile, start4, propertyDeclaration);
33286
+ } else {
33287
+ changeTracker.insertNodeAt(sourceFile, insertLocation, propertyDeclaration, { suffix: "\n" });
33288
+ }
33289
+ }
33290
+ });
33291
+ var parse5 = fn2("writeTagClassAccessors.parse")(function* (node) {
33292
+ const ts = yield* service2(TypeScriptApi);
33293
+ const typeChecker = yield* service2(TypeCheckerApi);
33294
+ const typeParser = yield* service2(TypeParser);
33295
+ const typeCheckerUtils = yield* service2(TypeCheckerUtils);
33296
+ if (!ts.isClassDeclaration(node)) return yield* fail18("not a class declaration");
33297
+ const { Service, accessors: accessors2, className } = yield* pipe(
33298
+ typeParser.extendsEffectService(node),
33299
+ orElse14(() => map34(typeParser.extendsEffectTag(node), (_) => ({ accessors: true, ..._ }))),
33300
+ orElse14(() => fail18("not a class extending Effect.Service call"))
33301
+ );
33302
+ if (accessors2 !== true) return yield* fail18("accessors are not enabled in the Effect.Service call");
33303
+ const involvedMembers = [];
33304
+ const nonPrimitiveServices = typeCheckerUtils.unrollUnionMembers(Service).filter(
33305
+ (_) => !(_.flags & ts.TypeFlags.Number || _.flags & ts.TypeFlags.String || _.flags & ts.TypeFlags.Boolean || _.flags & ts.TypeFlags.Literal)
33306
+ );
33307
+ if (nonPrimitiveServices.length === 0) return yield* fail18("Service type is a primitive type");
33308
+ for (const serviceShape of nonPrimitiveServices) {
33309
+ for (const property of typeChecker.getPropertiesOfType(serviceShape)) {
33310
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(property, node);
33311
+ const callSignatures = typeChecker.getSignaturesOfType(propertyType, ts.SignatureKind.Call);
33312
+ if (callSignatures.length > 0) {
33313
+ const withTypeParameters = callSignatures.filter((_) => _.typeParameters && _.typeParameters.length > 0);
33314
+ if (callSignatures.length > 1 || withTypeParameters.length > 0) involvedMembers.push({ property, propertyType });
33315
+ }
33316
+ }
33317
+ }
33318
+ const hash2 = involvedMembers.map(({ property, propertyType }) => {
33319
+ return ts.symbolName(property) + ": " + typeChecker.typeToString(propertyType);
33320
+ }).concat([ts.idText(className)]).join("\n");
33321
+ return { Service, className, atLocation: node, hash: cyrb53(hash2), involvedMembers };
33322
+ });
33323
+ var writeTagClassAccessors = createRefactor({
33324
+ name: "writeTagClassAccessors",
33325
+ description: "Implement accessors methods with generics or multiple signatures",
33326
+ apply: fn2("writeTagClassAccessors.apply")(function* (sourceFile, textRange) {
33327
+ const ts = yield* service2(TypeScriptApi);
33328
+ const tsUtils = yield* service2(TypeScriptUtils);
33329
+ const typeChecker = yield* service2(TypeCheckerApi);
33330
+ const typeParser = yield* service2(TypeParser);
33331
+ const parseNode = (node) => pipe(
33332
+ parse5(node),
33333
+ map34(({ Service, atLocation, className, involvedMembers }) => ({
33334
+ kind: "refactor.rewrite.effect.writeTagClassAccessors",
33335
+ description: "Implement Service accessors",
33336
+ apply: pipe(
33337
+ generate(sourceFile, Service, className, atLocation, involvedMembers),
33338
+ provideService7(TypeScriptUtils, tsUtils),
33339
+ provideService7(TypeParser, typeParser),
33340
+ provideService7(TypeCheckerApi, typeChecker),
33341
+ provideService7(TypeScriptApi, ts)
33342
+ )
33343
+ }))
33344
+ );
33345
+ const parentNodes = tsUtils.getAncestorNodesInRange(sourceFile, textRange);
33346
+ return yield* pipe(
33347
+ firstSuccessOf2(parentNodes.map(parseNode)),
33348
+ orElse14(() => fail18(new RefactorNotApplicableError()))
33349
+ );
33350
+ })
33351
+ });
33352
+
33353
+ // src/codegens/accessors.ts
33354
+ var accessors = createCodegen({
33355
+ name: "accessors",
33356
+ apply: fn2("accessors.apply")(function* (sourceFile, textRange) {
33357
+ const ts = yield* service2(TypeScriptApi);
33358
+ const tsUtils = yield* service2(TypeScriptUtils);
33359
+ const typeChecker = yield* service2(TypeCheckerApi);
33360
+ const typeParser = yield* service2(TypeParser);
33361
+ const typeCheckerUtils = yield* service2(TypeCheckerUtils);
33362
+ const nodeAndCommentRange = tsUtils.findNodeWithLeadingCommentAtPosition(sourceFile, textRange.pos);
33363
+ if (!nodeAndCommentRange) return yield* fail18(new CodegenNotApplicableError("no node and comment range"));
33364
+ return yield* pipe(
33365
+ parse5(nodeAndCommentRange.node),
33366
+ map34(
33367
+ (_) => ({
33368
+ hash: _.hash,
33369
+ description: "Generate accessors for the service",
33370
+ apply: pipe(
33371
+ generate(sourceFile, _.Service, _.className, _.atLocation, _.involvedMembers),
33372
+ provideService7(TypeScriptApi, ts),
33373
+ provideService7(TypeScriptUtils, tsUtils),
33374
+ provideService7(TypeCheckerApi, typeChecker),
33375
+ provideService7(TypeParser, typeParser),
33376
+ provideService7(TypeCheckerUtils, typeCheckerUtils)
33377
+ )
33378
+ })
33379
+ ),
33380
+ orElse14((cause2) => fail18(new CodegenNotApplicableError(cause2)))
33381
+ );
33382
+ })
33383
+ });
33384
+
33385
+ // src/codegens.ts
33386
+ var codegens = [accessors];
33387
+
33388
+ // src/cli/codegen.ts
33389
+ var NoFilesToCodegenError = class extends TaggedError("NoFilesToCodegenError") {
33390
+ get message() {
33391
+ return "No files to codegen. Please provide an existing .ts file or a project tsconfig.json";
33392
+ }
33393
+ };
33394
+ var file4 = file3("file").pipe(
33395
+ optional4,
33396
+ withDescription3("The full path of the file to codegen.")
33397
+ );
33398
+ var project2 = file3("project").pipe(
33399
+ optional4,
33400
+ withDescription3("The full path of the project tsconfig.json file to codegen.")
33401
+ );
33402
+ var verbose = boolean5("verbose").pipe(
33403
+ withDefault3(false),
33404
+ withDescription3("Verbose output.")
33405
+ );
33406
+ var BATCH_SIZE = 50;
33407
+ var codegen = make58(
33408
+ "codegen",
33409
+ { file: file4, project: project2, verbose },
33410
+ fn("codegen")(function* ({ file: file6, project: project4, verbose: verbose2 }) {
33411
+ const path2 = yield* Path2;
33412
+ const fs = yield* FileSystem;
33413
+ const tsInstance = yield* getTypeScript;
33414
+ let filesToCodegen = /* @__PURE__ */ new Set();
33415
+ let checkedFilesCount = 0;
33416
+ let updatedFilesCount = 0;
33417
+ if (isSome2(project4)) {
33418
+ filesToCodegen = yield* getFileNamesInTsConfig(project4.value);
33419
+ }
33420
+ if (isSome2(file6)) {
33421
+ filesToCodegen.add(path2.resolve(file6.value));
33422
+ }
33423
+ if (filesToCodegen.size === 0) {
33424
+ return yield* new NoFilesToCodegenError();
33425
+ }
33426
+ const filesWithCodegenDirective = /* @__PURE__ */ new Set();
33427
+ for (const filePath of filesToCodegen) {
33428
+ const sourceText = yield* fs.readFileString(filePath);
33429
+ if (sourceText.toLowerCase().indexOf("@effect-codegens") !== -1) {
33430
+ filesWithCodegenDirective.add(filePath);
33431
+ }
33432
+ }
33433
+ if (filesWithCodegenDirective.size === 0) {
33434
+ return yield* new NoFilesToCodegenError();
33435
+ }
33436
+ const filesToCodegenArray = fromIterable(filesWithCodegenDirective);
33437
+ const batches = chunksOf(filesToCodegenArray, BATCH_SIZE);
33438
+ let lastLanguageService;
33439
+ const disposeIfLanguageServiceChanged = (languageService) => {
33440
+ if (lastLanguageService !== languageService) {
33441
+ lastLanguageService?.dispose();
33442
+ lastLanguageService = languageService;
33443
+ }
33444
+ };
33445
+ for (const batch of batches) {
33446
+ const { service: service3 } = (0, import_project_service.createProjectService)({ options: { loadTypeScriptPlugins: false } });
33447
+ for (const filePath of batch) {
33448
+ service3.openClientFile(filePath);
33449
+ try {
33450
+ const scriptInfo = service3.getScriptInfo(filePath);
33451
+ if (!scriptInfo) continue;
33452
+ const project5 = scriptInfo.getDefaultProject();
33453
+ const languageService = project5.getLanguageService(true);
33454
+ disposeIfLanguageServiceChanged(languageService);
33455
+ const program = languageService.getProgram();
33456
+ if (!program) continue;
33457
+ const sourceFile = program.getSourceFile(filePath);
33458
+ if (!sourceFile) continue;
33459
+ const pluginConfig = extractEffectLspOptions(program.getCompilerOptions());
33460
+ if (!pluginConfig) continue;
33461
+ const formatContext = tsInstance.formatting.getFormatContext(
33462
+ tsInstance.getDefaultFormatCodeSettings(project5.getNewLine()),
33463
+ project5
33464
+ );
33465
+ const allFileChanges = pipe(
33466
+ gen3(function* () {
33467
+ let allChanges = [];
33468
+ const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
33469
+ for (const { codegen: codegen2, hash: hash2, range: range3 } of codegensWithRanges) {
33470
+ const applicable = yield* pipe(
33471
+ getEditsForCodegen([codegen2], sourceFile, range3),
33472
+ orElse14(() => void_8)
33473
+ );
33474
+ if (applicable && applicable.hash !== hash2) {
33475
+ const changes2 = tsInstance.textChanges.ChangeTracker.with(
33476
+ {
33477
+ formatContext,
33478
+ host: project5,
33479
+ preferences: {}
33480
+ },
33481
+ (changeTracker) => pipe(
33482
+ applicable.apply,
33483
+ provideService7(ChangeTracker, changeTracker),
33484
+ run9
33485
+ )
33486
+ );
33487
+ allChanges = [...allChanges, ...changes2];
33488
+ }
33489
+ }
33490
+ return allChanges;
33491
+ }),
33492
+ nanoLayer3,
33493
+ nanoLayer2,
33494
+ nanoLayer,
33495
+ provideService7(TypeCheckerApi, program.getTypeChecker()),
33496
+ provideService7(TypeScriptProgram, program),
33497
+ provideService7(TypeScriptApi, tsInstance),
33498
+ provideService7(
33499
+ LanguageServicePluginOptions,
33500
+ { ...parse4(pluginConfig), diagnosticsName: false }
33501
+ ),
33502
+ run9,
33503
+ getOrElse(() => [])
33504
+ );
33505
+ checkedFilesCount++;
33506
+ const thisFileChanges = allFileChanges.filter((change) => change.fileName === sourceFile.fileName);
33507
+ const flattenedChanges = flatten(thisFileChanges.map((change) => change.textChanges));
33508
+ if (verbose2) {
33509
+ if (flattenedChanges.length > 0) {
33510
+ console.log(`${filePath}: with ${flattenedChanges.length} changes`);
33511
+ } else {
33512
+ console.log(`${filePath}: no changes`);
33513
+ }
33514
+ }
33515
+ if (flattenedChanges.length === 0) continue;
33516
+ const sourceText = yield* fs.readFileString(filePath);
33517
+ const newSourceText = yield* applyTextChanges(sourceText, flattenedChanges);
33518
+ yield* fs.writeFileString(filePath, newSourceText);
33519
+ updatedFilesCount++;
33520
+ } finally {
33521
+ service3.closeClientFile(filePath);
33522
+ }
33523
+ }
33524
+ yield* yieldNow4();
33525
+ }
33526
+ disposeIfLanguageServiceChanged(void 0);
33527
+ console.log(
33528
+ `${filesToCodegen.size} involved files, of which ${filesWithCodegenDirective.size} with codegens.
33529
+ ${checkedFilesCount} checked and ${updatedFilesCount} updated.`
33530
+ );
33531
+ })
33532
+ );
33533
+
33534
+ // src/cli/diagnostics.ts
33535
+ var import_project_service2 = __toESM(require_dist2());
33536
+
33066
33537
  // src/diagnostics/anyUnknownInErrorContext.ts
33067
33538
  var anyUnknownInErrorContext = createDiagnostic({
33068
33539
  name: "anyUnknownInErrorContext",
@@ -34671,300 +35142,6 @@ var nonObjectEffectServiceType = createDiagnostic({
34671
35142
  })
34672
35143
  });
34673
35144
 
34674
- // src/refactors/writeTagClassAccessors.ts
34675
- var generate = fn2("writeTagClassAccessors.generate")(function* (sourceFile, service3, className, atLocation, involvedMembers) {
34676
- const ts = yield* service2(TypeScriptApi);
34677
- const tsUtils = yield* service2(TypeScriptUtils);
34678
- const typeChecker = yield* service2(TypeCheckerApi);
34679
- const typeParser = yield* service2(TypeParser);
34680
- const changeTracker = yield* service2(ChangeTracker);
34681
- const insertLocation = atLocation.members.length > 0 ? atLocation.members[0].pos : atLocation.end - 1;
34682
- const effectIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
34683
- sourceFile,
34684
- "effect",
34685
- "Effect"
34686
- ) || "Effect";
34687
- const createFunctionProperty = (className2, propertyName, type2, forceAny) => {
34688
- const arrowBody = ts.factory.createCallExpression(
34689
- ts.factory.createPropertyAccessExpression(
34690
- ts.factory.createIdentifier(effectIdentifier),
34691
- "andThen"
34692
- ),
34693
- void 0,
34694
- [
34695
- ts.factory.createIdentifier(ts.idText(className2)),
34696
- ts.factory.createArrowFunction(
34697
- void 0,
34698
- void 0,
34699
- [ts.factory.createParameterDeclaration(
34700
- void 0,
34701
- void 0,
34702
- "_",
34703
- void 0,
34704
- forceAny ? ts.factory.createTypeReferenceNode("any") : void 0
34705
- )],
34706
- void 0,
34707
- void 0,
34708
- ts.factory.createCallExpression(
34709
- ts.factory.createPropertyAccessExpression(
34710
- ts.factory.createIdentifier("_"),
34711
- propertyName
34712
- ),
34713
- void 0,
34714
- [
34715
- ts.factory.createSpreadElement(ts.factory.createIdentifier("args"))
34716
- ]
34717
- )
34718
- )
34719
- ]
34720
- );
34721
- return ts.factory.createPropertyDeclaration(
34722
- [
34723
- ts.factory.createModifier(ts.SyntaxKind.StaticKeyword),
34724
- ts.factory.createModifier(ts.SyntaxKind.OverrideKeyword)
34725
- ],
34726
- propertyName,
34727
- void 0,
34728
- type2,
34729
- ts.factory.createArrowFunction(
34730
- void 0,
34731
- void 0,
34732
- [ts.factory.createParameterDeclaration(
34733
- void 0,
34734
- ts.factory.createToken(ts.SyntaxKind.DotDotDotToken),
34735
- "args",
34736
- void 0,
34737
- forceAny ? ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("any")) : void 0
34738
- )],
34739
- void 0,
34740
- void 0,
34741
- forceAny ? ts.factory.createAsExpression(arrowBody, ts.factory.createTypeReferenceNode("any")) : arrowBody
34742
- )
34743
- );
34744
- };
34745
- const generateReturnType = (type2, atLocation2, className2) => pipe(
34746
- typeParser.effectType(type2, atLocation2),
34747
- flatMap18((returnedEffect) => {
34748
- const contextType = returnedEffect.R.flags & ts.TypeFlags.Never ? ts.factory.createTypeReferenceNode(ts.idText(className2)) : ts.factory.createUnionTypeNode(
34749
- [
34750
- ts.factory.createTypeReferenceNode(ts.idText(className2)),
34751
- typeChecker.typeToTypeNode(returnedEffect.R, atLocation2, ts.NodeBuilderFlags.NoTruncation)
34752
- ]
34753
- );
34754
- const successType = typeChecker.typeToTypeNode(
34755
- returnedEffect.A,
34756
- atLocation2,
34757
- ts.NodeBuilderFlags.NoTruncation
34758
- );
34759
- if (!successType) return fail18("error generating success type");
34760
- const failureType = typeChecker.typeToTypeNode(
34761
- returnedEffect.E,
34762
- atLocation2,
34763
- ts.NodeBuilderFlags.NoTruncation
34764
- );
34765
- if (!failureType) return fail18("error generating failure type");
34766
- const typeNode = ts.factory.createTypeReferenceNode(
34767
- ts.factory.createQualifiedName(
34768
- ts.factory.createIdentifier(effectIdentifier),
34769
- ts.factory.createIdentifier("Effect")
34770
- ),
34771
- [successType, failureType, contextType]
34772
- );
34773
- return succeed17(typeNode);
34774
- }),
34775
- orElse14(
34776
- () => pipe(
34777
- typeParser.promiseLike(type2, atLocation2),
34778
- flatMap18(({ type: type3 }) => {
34779
- const successType = typeChecker.typeToTypeNode(
34780
- type3,
34781
- atLocation2,
34782
- ts.NodeBuilderFlags.NoTruncation
34783
- );
34784
- if (!successType) return fail18("error generating success type");
34785
- return succeed17(ts.factory.createTypeReferenceNode(
34786
- ts.factory.createQualifiedName(
34787
- ts.factory.createIdentifier(effectIdentifier),
34788
- ts.factory.createIdentifier("Effect")
34789
- ),
34790
- [
34791
- successType,
34792
- ts.factory.createTypeReferenceNode(
34793
- ts.factory.createQualifiedName(
34794
- ts.factory.createIdentifier("Cause"),
34795
- ts.factory.createIdentifier("UnknownException")
34796
- )
34797
- ),
34798
- ts.factory.createTypeReferenceNode(ts.idText(className2))
34799
- ]
34800
- ));
34801
- })
34802
- )
34803
- ),
34804
- orElse14(() => {
34805
- const successType = typeChecker.typeToTypeNode(type2, atLocation2, ts.NodeBuilderFlags.NoTruncation);
34806
- if (!successType) return fail18("error generating success type");
34807
- const typeNode = ts.factory.createTypeReferenceNode(
34808
- ts.factory.createQualifiedName(
34809
- ts.factory.createIdentifier(effectIdentifier),
34810
- ts.factory.createIdentifier("Effect")
34811
- ),
34812
- [
34813
- successType,
34814
- ts.factory.createTypeReferenceNode("never"),
34815
- ts.factory.createTypeReferenceNode(ts.idText(className2))
34816
- ]
34817
- );
34818
- return succeed17(typeNode);
34819
- })
34820
- );
34821
- const proxySignature = (signature, atLocation2, className2) => gen3(function* () {
34822
- const signatureDeclaration = typeChecker.signatureToSignatureDeclaration(
34823
- signature,
34824
- ts.SyntaxKind.FunctionType,
34825
- atLocation2,
34826
- ts.NodeBuilderFlags.NoTruncation
34827
- );
34828
- if (!signatureDeclaration) return yield* fail18("error generating signature");
34829
- const returnType = yield* generateReturnType(
34830
- typeChecker.getReturnTypeOfSignature(signature),
34831
- atLocation2,
34832
- className2
34833
- );
34834
- return ts.factory.createFunctionTypeNode(
34835
- signatureDeclaration.typeParameters,
34836
- signatureDeclaration.parameters,
34837
- returnType
34838
- );
34839
- });
34840
- for (const { property, propertyType } of involvedMembers) {
34841
- const callSignatures = [];
34842
- let propertyDeclaration = void 0;
34843
- for (const signature of typeChecker.getSignaturesOfType(propertyType, ts.SignatureKind.Call)) {
34844
- yield* pipe(
34845
- proxySignature(signature, atLocation, className),
34846
- map34((sig) => {
34847
- callSignatures.push(sig);
34848
- }),
34849
- ignore3
34850
- );
34851
- }
34852
- const allSignatures = ts.factory.createIntersectionTypeNode(callSignatures);
34853
- const type2 = tsUtils.simplifyTypeNode(allSignatures);
34854
- propertyDeclaration = createFunctionProperty(className, ts.symbolName(property), type2, callSignatures.length > 1);
34855
- const oldProperty = atLocation.members.filter(ts.isPropertyDeclaration).find((p2) => {
34856
- const symbol3 = typeChecker.getSymbolAtLocation(p2.name);
34857
- return symbol3 && ts.symbolName(symbol3) === ts.symbolName(property);
34858
- });
34859
- if (oldProperty) {
34860
- const start4 = ts.getTokenPosOfNode(oldProperty, sourceFile);
34861
- changeTracker.deleteRange(sourceFile, {
34862
- pos: start4,
34863
- end: oldProperty.end
34864
- });
34865
- changeTracker.insertNodeAt(sourceFile, start4, propertyDeclaration);
34866
- } else {
34867
- changeTracker.insertNodeAt(sourceFile, insertLocation, propertyDeclaration, { suffix: "\n" });
34868
- }
34869
- }
34870
- });
34871
- var parse5 = fn2("writeTagClassAccessors.parse")(function* (node) {
34872
- const ts = yield* service2(TypeScriptApi);
34873
- const typeChecker = yield* service2(TypeCheckerApi);
34874
- const typeParser = yield* service2(TypeParser);
34875
- const typeCheckerUtils = yield* service2(TypeCheckerUtils);
34876
- if (!ts.isClassDeclaration(node)) return yield* fail18("not a class declaration");
34877
- const { Service, accessors: accessors2, className } = yield* pipe(
34878
- typeParser.extendsEffectService(node),
34879
- orElse14(() => map34(typeParser.extendsEffectTag(node), (_) => ({ accessors: true, ..._ }))),
34880
- orElse14(() => fail18("not a class extending Effect.Service call"))
34881
- );
34882
- if (accessors2 !== true) return yield* fail18("accessors are not enabled in the Effect.Service call");
34883
- const involvedMembers = [];
34884
- const nonPrimitiveServices = typeCheckerUtils.unrollUnionMembers(Service).filter(
34885
- (_) => !(_.flags & ts.TypeFlags.Number || _.flags & ts.TypeFlags.String || _.flags & ts.TypeFlags.Boolean || _.flags & ts.TypeFlags.Literal)
34886
- );
34887
- if (nonPrimitiveServices.length === 0) return yield* fail18("Service type is a primitive type");
34888
- for (const serviceShape of nonPrimitiveServices) {
34889
- for (const property of typeChecker.getPropertiesOfType(serviceShape)) {
34890
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(property, node);
34891
- const callSignatures = typeChecker.getSignaturesOfType(propertyType, ts.SignatureKind.Call);
34892
- if (callSignatures.length > 0) {
34893
- const withTypeParameters = callSignatures.filter((_) => _.typeParameters && _.typeParameters.length > 0);
34894
- if (callSignatures.length > 1 || withTypeParameters.length > 0) involvedMembers.push({ property, propertyType });
34895
- }
34896
- }
34897
- }
34898
- const hash2 = involvedMembers.map(({ property, propertyType }) => {
34899
- return ts.symbolName(property) + ": " + typeChecker.typeToString(propertyType);
34900
- }).concat([ts.idText(className)]).join("\n");
34901
- return { Service, className, atLocation: node, hash: cyrb53(hash2), involvedMembers };
34902
- });
34903
- var writeTagClassAccessors = createRefactor({
34904
- name: "writeTagClassAccessors",
34905
- description: "Implement accessors methods with generics or multiple signatures",
34906
- apply: fn2("writeTagClassAccessors.apply")(function* (sourceFile, textRange) {
34907
- const ts = yield* service2(TypeScriptApi);
34908
- const tsUtils = yield* service2(TypeScriptUtils);
34909
- const typeChecker = yield* service2(TypeCheckerApi);
34910
- const typeParser = yield* service2(TypeParser);
34911
- const parseNode = (node) => pipe(
34912
- parse5(node),
34913
- map34(({ Service, atLocation, className, involvedMembers }) => ({
34914
- kind: "refactor.rewrite.effect.writeTagClassAccessors",
34915
- description: "Implement Service accessors",
34916
- apply: pipe(
34917
- generate(sourceFile, Service, className, atLocation, involvedMembers),
34918
- provideService7(TypeScriptUtils, tsUtils),
34919
- provideService7(TypeParser, typeParser),
34920
- provideService7(TypeCheckerApi, typeChecker),
34921
- provideService7(TypeScriptApi, ts)
34922
- )
34923
- }))
34924
- );
34925
- const parentNodes = tsUtils.getAncestorNodesInRange(sourceFile, textRange);
34926
- return yield* pipe(
34927
- firstSuccessOf2(parentNodes.map(parseNode)),
34928
- orElse14(() => fail18(new RefactorNotApplicableError()))
34929
- );
34930
- })
34931
- });
34932
-
34933
- // src/codegens/accessors.ts
34934
- var accessors = createCodegen({
34935
- name: "accessors",
34936
- apply: fn2("accessors.apply")(function* (sourceFile, textRange) {
34937
- const ts = yield* service2(TypeScriptApi);
34938
- const tsUtils = yield* service2(TypeScriptUtils);
34939
- const typeChecker = yield* service2(TypeCheckerApi);
34940
- const typeParser = yield* service2(TypeParser);
34941
- const typeCheckerUtils = yield* service2(TypeCheckerUtils);
34942
- const nodeAndCommentRange = tsUtils.findNodeWithLeadingCommentAtPosition(sourceFile, textRange.pos);
34943
- if (!nodeAndCommentRange) return yield* fail18(new CodegenNotApplicableError("no node and comment range"));
34944
- return yield* pipe(
34945
- parse5(nodeAndCommentRange.node),
34946
- map34(
34947
- (_) => ({
34948
- hash: _.hash,
34949
- description: "Generate accessors for the service",
34950
- apply: pipe(
34951
- generate(sourceFile, _.Service, _.className, _.atLocation, _.involvedMembers),
34952
- provideService7(TypeScriptApi, ts),
34953
- provideService7(TypeScriptUtils, tsUtils),
34954
- provideService7(TypeCheckerApi, typeChecker),
34955
- provideService7(TypeParser, typeParser),
34956
- provideService7(TypeCheckerUtils, typeCheckerUtils)
34957
- )
34958
- })
34959
- ),
34960
- orElse14((cause2) => fail18(new CodegenNotApplicableError(cause2)))
34961
- );
34962
- })
34963
- });
34964
-
34965
- // src/codegens.ts
34966
- var codegens = [accessors];
34967
-
34968
35145
  // src/diagnostics/outdatedEffectCodegen.ts
34969
35146
  var outdatedEffectCodegen = createDiagnostic({
34970
35147
  name: "outdatedEffectCodegen",
@@ -34972,23 +35149,23 @@ var outdatedEffectCodegen = createDiagnostic({
34972
35149
  severity: "warning",
34973
35150
  apply: fn2("outdatedEffectCodegen.apply")(function* (sourceFile, _report) {
34974
35151
  const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
34975
- for (const { codegen, hash: hash2, range: range3 } of codegensWithRanges) {
35152
+ for (const { codegen: codegen2, hash: hash2, range: range3 } of codegensWithRanges) {
34976
35153
  yield* pipe(
34977
- getEditsForCodegen([codegen], sourceFile, range3),
35154
+ getEditsForCodegen([codegen2], sourceFile, range3),
34978
35155
  map34((applicable) => {
34979
35156
  if (applicable.hash !== hash2) {
34980
35157
  _report({
34981
35158
  location: range3,
34982
- messageText: `Codegen ${codegen.name} result is outdated`,
35159
+ messageText: `Codegen ${codegen2.name} result is outdated`,
34983
35160
  fixes: [
34984
35161
  {
34985
35162
  fixName: "outdatedEffectCodegen_fix",
34986
- description: `Re-run ${codegen.name}`,
35163
+ description: `Re-run ${codegen2.name}`,
34987
35164
  apply: applicable.apply
34988
35165
  },
34989
35166
  {
34990
35167
  fixName: "outdatedEffectCodegen_ignore",
34991
- description: `Ignore this ${codegen.name} update`,
35168
+ description: `Ignore this ${codegen2.name} update`,
34992
35169
  apply: applicable.ignore
34993
35170
  }
34994
35171
  ]
@@ -34999,7 +35176,7 @@ var outdatedEffectCodegen = createDiagnostic({
34999
35176
  (e) => sync11(() => {
35000
35177
  _report({
35001
35178
  location: range3,
35002
- messageText: `Codegen ${codegen.name} is not applicable here: ${e.cause}`,
35179
+ messageText: `Codegen ${codegen2.name} is not applicable here: ${e.cause}`,
35003
35180
  fixes: []
35004
35181
  });
35005
35182
  })
@@ -35912,58 +36089,37 @@ var NoFilesToCheckError = class extends TaggedError("NoFilesToCheckError") {
35912
36089
  return "No files to check. Please provide an existing .ts file or a project tsconfig.json";
35913
36090
  }
35914
36091
  };
35915
- var file4 = file3("file").pipe(
36092
+ var file5 = file3("file").pipe(
35916
36093
  optional4,
35917
36094
  withDescription3("The full path of the file to check for diagnostics.")
35918
36095
  );
35919
- var project2 = file3("project").pipe(
36096
+ var project3 = file3("project").pipe(
35920
36097
  optional4,
35921
36098
  withDescription3("The full path of the project tsconfig.json file to check for diagnostics.")
35922
36099
  );
35923
- var extractEffectLspOptions = (compilerOptions) => {
35924
- return (hasProperty(compilerOptions, "plugins") && isArray(compilerOptions.plugins) ? compilerOptions.plugins : []).find((_) => hasProperty(_, "name") && _.name === "@effect/language-service");
35925
- };
35926
- var BATCH_SIZE = 50;
36100
+ var BATCH_SIZE2 = 50;
35927
36101
  var diagnostics2 = make58(
35928
36102
  "diagnostics",
35929
- { file: file4, project: project2 },
35930
- fn("diagnostics")(function* ({ file: file5, project: project3 }) {
36103
+ { file: file5, project: project3 },
36104
+ fn("diagnostics")(function* ({ file: file6, project: project4 }) {
35931
36105
  const path2 = yield* Path2;
35932
36106
  const tsInstance = yield* getTypeScript;
35933
- const filesToCheck = /* @__PURE__ */ new Set();
36107
+ let filesToCheck = /* @__PURE__ */ new Set();
35934
36108
  let checkedFilesCount = 0;
35935
36109
  let errorsCount = 0;
35936
36110
  let warningsCount = 0;
35937
36111
  let messagesCount = 0;
35938
- if (isSome2(file5)) {
35939
- filesToCheck.add(path2.resolve(file5.value));
35940
- }
35941
- if (isSome2(project3)) {
35942
- let tsconfigToHandle = [project3.value ?? ""];
35943
- while (tsconfigToHandle.length > 0) {
35944
- const tsconfigPath = tsconfigToHandle.shift();
35945
- const tsconfigAbsolutePath = path2.resolve(tsconfigPath);
35946
- const configFile = tsInstance.readConfigFile(tsconfigAbsolutePath, tsInstance.sys.readFile);
35947
- if (configFile.error) {
35948
- if (!tsconfigAbsolutePath.endsWith("tsconfig.json")) {
35949
- tsconfigToHandle = [...tsconfigToHandle, path2.resolve(tsconfigPath, "tsconfig.json")];
35950
- }
35951
- continue;
35952
- }
35953
- const parsedConfig = tsInstance.parseJsonConfigFileContent(
35954
- configFile.config,
35955
- tsInstance.sys,
35956
- path2.dirname(tsconfigAbsolutePath)
35957
- );
35958
- tsconfigToHandle = [...tsconfigToHandle, ...parsedConfig.projectReferences?.map((_) => _.path) ?? []];
35959
- parsedConfig.fileNames.forEach((_) => filesToCheck.add(_));
35960
- }
36112
+ if (isSome2(project4)) {
36113
+ filesToCheck = yield* getFileNamesInTsConfig(project4.value);
36114
+ }
36115
+ if (isSome2(file6)) {
36116
+ filesToCheck.add(path2.resolve(file6.value));
35961
36117
  }
35962
36118
  if (filesToCheck.size === 0) {
35963
36119
  return yield* new NoFilesToCheckError();
35964
36120
  }
35965
36121
  const filesToCheckArray = fromIterable(filesToCheck);
35966
- const batches = chunksOf(filesToCheckArray, BATCH_SIZE);
36122
+ const batches = chunksOf(filesToCheckArray, BATCH_SIZE2);
35967
36123
  let lastLanguageService;
35968
36124
  const disposeIfLanguageServiceChanged = (languageService) => {
35969
36125
  if (lastLanguageService !== languageService) {
@@ -35972,14 +36128,14 @@ var diagnostics2 = make58(
35972
36128
  }
35973
36129
  };
35974
36130
  for (const batch of batches) {
35975
- const { service: service3 } = (0, import_project_service.createProjectService)({ options: { loadTypeScriptPlugins: false } });
36131
+ const { service: service3 } = (0, import_project_service2.createProjectService)({ options: { loadTypeScriptPlugins: false } });
35976
36132
  for (const filePath of batch) {
35977
36133
  service3.openClientFile(filePath);
35978
36134
  try {
35979
36135
  const scriptInfo = service3.getScriptInfo(filePath);
35980
36136
  if (!scriptInfo) continue;
35981
- const project4 = scriptInfo.getDefaultProject();
35982
- const languageService = project4.getLanguageService(true);
36137
+ const project5 = scriptInfo.getDefaultProject();
36138
+ const languageService = project5.getLanguageService(true);
35983
36139
  disposeIfLanguageServiceChanged(languageService);
35984
36140
  const program = languageService.getProgram();
35985
36141
  if (!program) continue;
@@ -36070,7 +36226,7 @@ var getPatchesForModule = fn("getPatchesForModule")(
36070
36226
  let insertCheckSourceFilePosition = none2();
36071
36227
  let insertSkipPrecedingCommentDirectivePosition = none2();
36072
36228
  let insertAppendMetadataRelationErrorPosition = none2();
36073
- const nodesToCheck = [];
36229
+ let nodesToCheck = [];
36074
36230
  function findNodeAtPositionIncludingTrivia(sourceFile2, position) {
36075
36231
  function find3(node) {
36076
36232
  if (position >= node.pos && position < node.end) {
@@ -36098,7 +36254,7 @@ var getPatchesForModule = fn("getPatchesForModule")(
36098
36254
  if (!pushFunctionDeclarationNode("checkSourceFileWorker")) requiresFullScan = true;
36099
36255
  if (!pushFunctionDeclarationNode("markPrecedingCommentDirectiveLine")) requiresFullScan = true;
36100
36256
  if (!pushFunctionDeclarationNode("reportRelationError")) requiresFullScan = true;
36101
- if (requiresFullScan) nodesToCheck.push(sourceFile);
36257
+ if (requiresFullScan) nodesToCheck = [sourceFile];
36102
36258
  while (nodesToCheck.length > 0) {
36103
36259
  const node = nodesToCheck.shift();
36104
36260
  if (!node) continue;
@@ -36328,7 +36484,7 @@ var cliCommand = make58(
36328
36484
  "effect-language-service",
36329
36485
  {},
36330
36486
  () => log3("Please select a command or run --help.")
36331
- ).pipe(withSubcommands3([patch9, unpatch, check2, diagnostics2]));
36487
+ ).pipe(withSubcommands3([patch9, unpatch, check2, diagnostics2, codegen]));
36332
36488
  var main = run8(cliCommand, {
36333
36489
  name: "effect-language-service",
36334
36490
  version: "0.0.2"