@effect/language-service 0.55.5 → 0.57.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: (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 {
@@ -32055,6 +32083,51 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
32055
32083
  if (!symbol3) return typeParserIssue("Node has no symbol", void 0, givenNode);
32056
32084
  return isSymbolExportOfPackageModule(symbol3, packageName, memberName, isCorrectSourceFile);
32057
32085
  };
32086
+ const findSymbolsMatchingPackageAndExportedName = (packageName, exportedSymbolName) => cachedBy(
32087
+ fn2("TypeParser.findSymbolsMatchingPackageAndExportedName")(function* (_fromSourceFile) {
32088
+ const result = [];
32089
+ for (const sourceFile of program.getSourceFiles()) {
32090
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
32091
+ if (!moduleSymbol) continue;
32092
+ const symbol3 = typeChecker.tryGetMemberInModuleExports(exportedSymbolName, moduleSymbol);
32093
+ if (!symbol3) continue;
32094
+ const packageInfo = yield* getSourceFilePackageInfo(sourceFile);
32095
+ if (!packageInfo || packageInfo.name.toLowerCase() !== packageName.toLowerCase()) continue;
32096
+ result.push([symbol3, sourceFile]);
32097
+ }
32098
+ return result;
32099
+ }),
32100
+ `TypeParser.findSymbolsMatchingPackageAndExportedName(${packageName}, ${exportedSymbolName})`,
32101
+ (sourceFile) => sourceFile
32102
+ );
32103
+ const isCauseTypeSourceFile = cachedBy(
32104
+ fn2("TypeParser.isCauseTypeSourceFile")(function* (sourceFile) {
32105
+ const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
32106
+ if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
32107
+ const causeTypeSymbol = typeChecker.tryGetMemberInModuleExports("Cause", moduleSymbol);
32108
+ if (!causeTypeSymbol) return yield* typeParserIssue("Cause type not found", void 0, sourceFile);
32109
+ const type2 = typeChecker.getDeclaredTypeOfSymbol(causeTypeSymbol);
32110
+ yield* pipeableType(type2, sourceFile);
32111
+ return sourceFile;
32112
+ }),
32113
+ "TypeParser.isCauseTypeSourceFile",
32114
+ (sourceFile) => sourceFile
32115
+ );
32116
+ const effectCauseYieldableErrorTypes = cachedBy(
32117
+ fn2("TypeParser.effectCauseYieldableErrorTypes")(function* (fromSourceFile) {
32118
+ const symbols = yield* findSymbolsMatchingPackageAndExportedName("effect", "YieldableError")(fromSourceFile);
32119
+ const result = [];
32120
+ for (const [symbol3, sourceFile] of symbols) {
32121
+ const causeFile = yield* isCauseTypeSourceFile(sourceFile);
32122
+ if (!causeFile) continue;
32123
+ const type2 = typeChecker.getDeclaredTypeOfSymbol(symbol3);
32124
+ result.push(type2);
32125
+ }
32126
+ return result;
32127
+ }),
32128
+ "TypeParser.effectCauseYieldableErrorTypes",
32129
+ (fromSourceFile) => fromSourceFile
32130
+ );
32058
32131
  function covariantTypeArgument(type2) {
32059
32132
  const signatures = typeChecker.getSignaturesOfType(type2, ts.SignatureKind.Call);
32060
32133
  if (signatures.length !== 1) {
@@ -33044,6 +33117,7 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
33044
33117
  effectGen,
33045
33118
  effectFnUntracedGen,
33046
33119
  effectFnGen,
33120
+ effectCauseYieldableErrorTypes,
33047
33121
  unnecessaryEffectGen: unnecessaryEffectGen2,
33048
33122
  effectSchemaType,
33049
33123
  contextTag,
@@ -33063,6 +33137,534 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
33063
33137
  };
33064
33138
  }
33065
33139
 
33140
+ // src/refactors/writeTagClassAccessors.ts
33141
+ var generate = fn2("writeTagClassAccessors.generate")(function* (sourceFile, service3, className, atLocation, involvedMembers) {
33142
+ const ts = yield* service2(TypeScriptApi);
33143
+ const tsUtils = yield* service2(TypeScriptUtils);
33144
+ const typeChecker = yield* service2(TypeCheckerApi);
33145
+ const typeParser = yield* service2(TypeParser);
33146
+ const changeTracker = yield* service2(ChangeTracker);
33147
+ const insertLocation = atLocation.members.length > 0 ? atLocation.members[0].pos : atLocation.end - 1;
33148
+ const effectIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
33149
+ sourceFile,
33150
+ "effect",
33151
+ "Effect"
33152
+ ) || "Effect";
33153
+ const createFunctionProperty = (className2, propertyName, type2, forceAny) => {
33154
+ const arrowBody = ts.factory.createCallExpression(
33155
+ ts.factory.createPropertyAccessExpression(
33156
+ ts.factory.createIdentifier(effectIdentifier),
33157
+ "andThen"
33158
+ ),
33159
+ void 0,
33160
+ [
33161
+ ts.factory.createIdentifier(ts.idText(className2)),
33162
+ ts.factory.createArrowFunction(
33163
+ void 0,
33164
+ void 0,
33165
+ [ts.factory.createParameterDeclaration(
33166
+ void 0,
33167
+ void 0,
33168
+ "_",
33169
+ void 0,
33170
+ forceAny ? ts.factory.createTypeReferenceNode("any") : void 0
33171
+ )],
33172
+ void 0,
33173
+ void 0,
33174
+ ts.factory.createCallExpression(
33175
+ ts.factory.createPropertyAccessExpression(
33176
+ ts.factory.createIdentifier("_"),
33177
+ propertyName
33178
+ ),
33179
+ void 0,
33180
+ [
33181
+ ts.factory.createSpreadElement(ts.factory.createIdentifier("args"))
33182
+ ]
33183
+ )
33184
+ )
33185
+ ]
33186
+ );
33187
+ return ts.factory.createPropertyDeclaration(
33188
+ [
33189
+ ts.factory.createModifier(ts.SyntaxKind.StaticKeyword),
33190
+ ts.factory.createModifier(ts.SyntaxKind.OverrideKeyword)
33191
+ ],
33192
+ propertyName,
33193
+ void 0,
33194
+ type2,
33195
+ ts.factory.createArrowFunction(
33196
+ void 0,
33197
+ void 0,
33198
+ [ts.factory.createParameterDeclaration(
33199
+ void 0,
33200
+ ts.factory.createToken(ts.SyntaxKind.DotDotDotToken),
33201
+ "args",
33202
+ void 0,
33203
+ forceAny ? ts.factory.createArrayTypeNode(ts.factory.createTypeReferenceNode("any")) : void 0
33204
+ )],
33205
+ void 0,
33206
+ void 0,
33207
+ forceAny ? ts.factory.createAsExpression(arrowBody, ts.factory.createTypeReferenceNode("any")) : arrowBody
33208
+ )
33209
+ );
33210
+ };
33211
+ const generateReturnType = (type2, atLocation2, className2) => pipe(
33212
+ typeParser.effectType(type2, atLocation2),
33213
+ flatMap18((returnedEffect) => {
33214
+ const contextType = returnedEffect.R.flags & ts.TypeFlags.Never ? ts.factory.createTypeReferenceNode(ts.idText(className2)) : ts.factory.createUnionTypeNode(
33215
+ [
33216
+ ts.factory.createTypeReferenceNode(ts.idText(className2)),
33217
+ typeChecker.typeToTypeNode(returnedEffect.R, atLocation2, ts.NodeBuilderFlags.NoTruncation)
33218
+ ]
33219
+ );
33220
+ const successType = typeChecker.typeToTypeNode(
33221
+ returnedEffect.A,
33222
+ atLocation2,
33223
+ ts.NodeBuilderFlags.NoTruncation
33224
+ );
33225
+ if (!successType) return fail18("error generating success type");
33226
+ const failureType = typeChecker.typeToTypeNode(
33227
+ returnedEffect.E,
33228
+ atLocation2,
33229
+ ts.NodeBuilderFlags.NoTruncation
33230
+ );
33231
+ if (!failureType) return fail18("error generating failure type");
33232
+ const typeNode = ts.factory.createTypeReferenceNode(
33233
+ ts.factory.createQualifiedName(
33234
+ ts.factory.createIdentifier(effectIdentifier),
33235
+ ts.factory.createIdentifier("Effect")
33236
+ ),
33237
+ [successType, failureType, contextType]
33238
+ );
33239
+ return succeed17(typeNode);
33240
+ }),
33241
+ orElse14(
33242
+ () => pipe(
33243
+ typeParser.promiseLike(type2, atLocation2),
33244
+ flatMap18(({ type: type3 }) => {
33245
+ const successType = typeChecker.typeToTypeNode(
33246
+ type3,
33247
+ atLocation2,
33248
+ ts.NodeBuilderFlags.NoTruncation
33249
+ );
33250
+ if (!successType) return fail18("error generating success type");
33251
+ return succeed17(ts.factory.createTypeReferenceNode(
33252
+ ts.factory.createQualifiedName(
33253
+ ts.factory.createIdentifier(effectIdentifier),
33254
+ ts.factory.createIdentifier("Effect")
33255
+ ),
33256
+ [
33257
+ successType,
33258
+ ts.factory.createTypeReferenceNode(
33259
+ ts.factory.createQualifiedName(
33260
+ ts.factory.createIdentifier("Cause"),
33261
+ ts.factory.createIdentifier("UnknownException")
33262
+ )
33263
+ ),
33264
+ ts.factory.createTypeReferenceNode(ts.idText(className2))
33265
+ ]
33266
+ ));
33267
+ })
33268
+ )
33269
+ ),
33270
+ orElse14(() => {
33271
+ const successType = typeChecker.typeToTypeNode(type2, atLocation2, ts.NodeBuilderFlags.NoTruncation);
33272
+ if (!successType) return fail18("error generating success type");
33273
+ const typeNode = ts.factory.createTypeReferenceNode(
33274
+ ts.factory.createQualifiedName(
33275
+ ts.factory.createIdentifier(effectIdentifier),
33276
+ ts.factory.createIdentifier("Effect")
33277
+ ),
33278
+ [
33279
+ successType,
33280
+ ts.factory.createTypeReferenceNode("never"),
33281
+ ts.factory.createTypeReferenceNode(ts.idText(className2))
33282
+ ]
33283
+ );
33284
+ return succeed17(typeNode);
33285
+ })
33286
+ );
33287
+ const proxySignature = (signature, atLocation2, className2) => gen3(function* () {
33288
+ const signatureDeclaration = typeChecker.signatureToSignatureDeclaration(
33289
+ signature,
33290
+ ts.SyntaxKind.FunctionType,
33291
+ atLocation2,
33292
+ ts.NodeBuilderFlags.NoTruncation
33293
+ );
33294
+ if (!signatureDeclaration) return yield* fail18("error generating signature");
33295
+ const returnType = yield* generateReturnType(
33296
+ typeChecker.getReturnTypeOfSignature(signature),
33297
+ atLocation2,
33298
+ className2
33299
+ );
33300
+ return ts.factory.createFunctionTypeNode(
33301
+ signatureDeclaration.typeParameters,
33302
+ signatureDeclaration.parameters,
33303
+ returnType
33304
+ );
33305
+ });
33306
+ for (const { property, propertyType } of involvedMembers) {
33307
+ const callSignatures = [];
33308
+ let propertyDeclaration = void 0;
33309
+ for (const signature of typeChecker.getSignaturesOfType(propertyType, ts.SignatureKind.Call)) {
33310
+ yield* pipe(
33311
+ proxySignature(signature, atLocation, className),
33312
+ map34((sig) => {
33313
+ callSignatures.push(sig);
33314
+ }),
33315
+ ignore3
33316
+ );
33317
+ }
33318
+ const allSignatures = ts.factory.createIntersectionTypeNode(callSignatures);
33319
+ const type2 = tsUtils.simplifyTypeNode(allSignatures);
33320
+ propertyDeclaration = createFunctionProperty(className, ts.symbolName(property), type2, callSignatures.length > 1);
33321
+ const oldProperty = atLocation.members.filter(ts.isPropertyDeclaration).find((p2) => {
33322
+ const symbol3 = typeChecker.getSymbolAtLocation(p2.name);
33323
+ return symbol3 && ts.symbolName(symbol3) === ts.symbolName(property);
33324
+ });
33325
+ if (oldProperty) {
33326
+ const start4 = ts.getTokenPosOfNode(oldProperty, sourceFile);
33327
+ changeTracker.deleteRange(sourceFile, {
33328
+ pos: start4,
33329
+ end: oldProperty.end
33330
+ });
33331
+ changeTracker.insertNodeAt(sourceFile, start4, propertyDeclaration);
33332
+ } else {
33333
+ changeTracker.insertNodeAt(sourceFile, insertLocation, propertyDeclaration, { suffix: "\n" });
33334
+ }
33335
+ }
33336
+ });
33337
+ var parse5 = fn2("writeTagClassAccessors.parse")(function* (node) {
33338
+ const ts = yield* service2(TypeScriptApi);
33339
+ const typeChecker = yield* service2(TypeCheckerApi);
33340
+ const typeParser = yield* service2(TypeParser);
33341
+ const typeCheckerUtils = yield* service2(TypeCheckerUtils);
33342
+ if (!ts.isClassDeclaration(node)) return yield* fail18("not a class declaration");
33343
+ const { Service, accessors: accessors2, className } = yield* pipe(
33344
+ typeParser.extendsEffectService(node),
33345
+ orElse14(() => map34(typeParser.extendsEffectTag(node), (_) => ({ accessors: true, ..._ }))),
33346
+ orElse14(() => fail18("not a class extending Effect.Service call"))
33347
+ );
33348
+ if (accessors2 !== true) return yield* fail18("accessors are not enabled in the Effect.Service call");
33349
+ const involvedMembers = [];
33350
+ const nonPrimitiveServices = typeCheckerUtils.unrollUnionMembers(Service).filter(
33351
+ (_) => !(_.flags & ts.TypeFlags.Number || _.flags & ts.TypeFlags.String || _.flags & ts.TypeFlags.Boolean || _.flags & ts.TypeFlags.Literal)
33352
+ );
33353
+ if (nonPrimitiveServices.length === 0) return yield* fail18("Service type is a primitive type");
33354
+ for (const serviceShape of nonPrimitiveServices) {
33355
+ for (const property of typeChecker.getPropertiesOfType(serviceShape)) {
33356
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(property, node);
33357
+ const callSignatures = typeChecker.getSignaturesOfType(propertyType, ts.SignatureKind.Call);
33358
+ if (callSignatures.length > 0) {
33359
+ const withTypeParameters = callSignatures.filter((_) => _.typeParameters && _.typeParameters.length > 0);
33360
+ if (callSignatures.length > 1 || withTypeParameters.length > 0) involvedMembers.push({ property, propertyType });
33361
+ }
33362
+ }
33363
+ }
33364
+ const hash2 = involvedMembers.map(({ property, propertyType }) => {
33365
+ return ts.symbolName(property) + ": " + typeChecker.typeToString(propertyType);
33366
+ }).concat([ts.idText(className)]).join("\n");
33367
+ return { Service, className, atLocation: node, hash: cyrb53(hash2), involvedMembers };
33368
+ });
33369
+ var writeTagClassAccessors = createRefactor({
33370
+ name: "writeTagClassAccessors",
33371
+ description: "Implement accessors methods with generics or multiple signatures",
33372
+ apply: fn2("writeTagClassAccessors.apply")(function* (sourceFile, textRange) {
33373
+ const ts = yield* service2(TypeScriptApi);
33374
+ const tsUtils = yield* service2(TypeScriptUtils);
33375
+ const typeChecker = yield* service2(TypeCheckerApi);
33376
+ const typeParser = yield* service2(TypeParser);
33377
+ const parseNode = (node) => pipe(
33378
+ parse5(node),
33379
+ map34(({ Service, atLocation, className, involvedMembers }) => ({
33380
+ kind: "refactor.rewrite.effect.writeTagClassAccessors",
33381
+ description: "Implement Service accessors",
33382
+ apply: pipe(
33383
+ generate(sourceFile, Service, className, atLocation, involvedMembers),
33384
+ provideService7(TypeScriptUtils, tsUtils),
33385
+ provideService7(TypeParser, typeParser),
33386
+ provideService7(TypeCheckerApi, typeChecker),
33387
+ provideService7(TypeScriptApi, ts)
33388
+ )
33389
+ }))
33390
+ );
33391
+ const parentNodes = tsUtils.getAncestorNodesInRange(sourceFile, textRange);
33392
+ return yield* pipe(
33393
+ firstSuccessOf2(parentNodes.map(parseNode)),
33394
+ orElse14(() => fail18(new RefactorNotApplicableError()))
33395
+ );
33396
+ })
33397
+ });
33398
+
33399
+ // src/codegens/accessors.ts
33400
+ var accessors = createCodegen({
33401
+ name: "accessors",
33402
+ apply: fn2("accessors.apply")(function* (sourceFile, textRange) {
33403
+ const ts = yield* service2(TypeScriptApi);
33404
+ const tsUtils = yield* service2(TypeScriptUtils);
33405
+ const typeChecker = yield* service2(TypeCheckerApi);
33406
+ const typeParser = yield* service2(TypeParser);
33407
+ const typeCheckerUtils = yield* service2(TypeCheckerUtils);
33408
+ const nodeAndCommentRange = tsUtils.findNodeWithLeadingCommentAtPosition(sourceFile, textRange.pos);
33409
+ if (!nodeAndCommentRange) return yield* fail18(new CodegenNotApplicableError("no node and comment range"));
33410
+ return yield* pipe(
33411
+ parse5(nodeAndCommentRange.node),
33412
+ map34(
33413
+ (_) => ({
33414
+ hash: _.hash,
33415
+ description: "Generate accessors for the service",
33416
+ apply: pipe(
33417
+ generate(sourceFile, _.Service, _.className, _.atLocation, _.involvedMembers),
33418
+ provideService7(TypeScriptApi, ts),
33419
+ provideService7(TypeScriptUtils, tsUtils),
33420
+ provideService7(TypeCheckerApi, typeChecker),
33421
+ provideService7(TypeParser, typeParser),
33422
+ provideService7(TypeCheckerUtils, typeCheckerUtils)
33423
+ )
33424
+ })
33425
+ ),
33426
+ orElse14((cause2) => fail18(new CodegenNotApplicableError(cause2)))
33427
+ );
33428
+ })
33429
+ });
33430
+
33431
+ // src/codegens/annotate.ts
33432
+ var annotate3 = createCodegen({
33433
+ name: "annotate",
33434
+ apply: fn2("annotate.apply")(function* (sourceFile, textRange) {
33435
+ const ts = yield* service2(TypeScriptApi);
33436
+ const tsUtils = yield* service2(TypeScriptUtils);
33437
+ const typeChecker = yield* service2(TypeCheckerApi);
33438
+ const typeCheckerUtils = yield* service2(TypeCheckerUtils);
33439
+ const parse6 = (node) => gen3(function* () {
33440
+ let variableDeclarations = [];
33441
+ const result = [];
33442
+ if (ts.isVariableStatement(node)) {
33443
+ variableDeclarations = [...variableDeclarations, ...node.declarationList.declarations];
33444
+ } else if (ts.isVariableDeclarationList(node)) {
33445
+ variableDeclarations = [...variableDeclarations, ...node.declarations];
33446
+ } else if (ts.isVariableDeclaration(node)) {
33447
+ variableDeclarations = [...variableDeclarations, node];
33448
+ }
33449
+ if (variableDeclarations.length === 0) {
33450
+ return yield* fail18(new CodegenNotApplicableError("not a variable declaration"));
33451
+ }
33452
+ for (const variableDeclaration of variableDeclarations) {
33453
+ if (!variableDeclaration.initializer) continue;
33454
+ const initializerType = typeChecker.getTypeAtLocation(variableDeclaration.initializer);
33455
+ const initializerTypeNode = fromNullable(typeCheckerUtils.typeToSimplifiedTypeNode(
33456
+ initializerType,
33457
+ node,
33458
+ ts.NodeBuilderFlags.NoTruncation
33459
+ )).pipe(
33460
+ orElse(
33461
+ () => fromNullable(typeCheckerUtils.typeToSimplifiedTypeNode(
33462
+ initializerType,
33463
+ void 0,
33464
+ ts.NodeBuilderFlags.NoTruncation
33465
+ ))
33466
+ ),
33467
+ getOrUndefined
33468
+ );
33469
+ if (!initializerTypeNode) continue;
33470
+ const typeNodeString = typeChecker.typeToString(initializerType, void 0, ts.TypeFormatFlags.NoTruncation);
33471
+ const hash3 = cyrb53(typeNodeString);
33472
+ result.push({ variableDeclaration, initializerTypeNode, hash: hash3 });
33473
+ }
33474
+ if (result.length === 0) {
33475
+ return yield* fail18(new CodegenNotApplicableError("no variable declarations with initializers"));
33476
+ }
33477
+ const hash2 = cyrb53(result.map((_) => _.hash).join("/"));
33478
+ return {
33479
+ hash: hash2,
33480
+ result
33481
+ };
33482
+ });
33483
+ const nodeAndCommentRange = tsUtils.findNodeWithLeadingCommentAtPosition(sourceFile, textRange.pos);
33484
+ if (!nodeAndCommentRange) return yield* fail18(new CodegenNotApplicableError("no node and comment range"));
33485
+ return yield* pipe(
33486
+ parse6(nodeAndCommentRange.node),
33487
+ map34(
33488
+ (_) => ({
33489
+ hash: _.hash,
33490
+ description: "Annotate with type",
33491
+ apply: gen3(function* () {
33492
+ const changeTracker = yield* service2(ChangeTracker);
33493
+ for (const { initializerTypeNode, variableDeclaration } of _.result) {
33494
+ if (variableDeclaration.type) {
33495
+ changeTracker.deleteRange(sourceFile, {
33496
+ pos: variableDeclaration.name.end,
33497
+ end: variableDeclaration.type.end
33498
+ });
33499
+ }
33500
+ changeTracker.insertNodeAt(
33501
+ sourceFile,
33502
+ variableDeclaration.name.end,
33503
+ initializerTypeNode,
33504
+ {
33505
+ prefix: ": "
33506
+ }
33507
+ );
33508
+ }
33509
+ })
33510
+ })
33511
+ )
33512
+ );
33513
+ })
33514
+ });
33515
+
33516
+ // src/codegens.ts
33517
+ var codegens = [accessors, annotate3];
33518
+
33519
+ // src/cli/codegen.ts
33520
+ var NoFilesToCodegenError = class extends TaggedError("NoFilesToCodegenError") {
33521
+ get message() {
33522
+ return "No files to codegen. Please provide an existing .ts file or a project tsconfig.json";
33523
+ }
33524
+ };
33525
+ var file4 = file3("file").pipe(
33526
+ optional4,
33527
+ withDescription3("The full path of the file to codegen.")
33528
+ );
33529
+ var project2 = file3("project").pipe(
33530
+ optional4,
33531
+ withDescription3("The full path of the project tsconfig.json file to codegen.")
33532
+ );
33533
+ var verbose = boolean5("verbose").pipe(
33534
+ withDefault3(false),
33535
+ withDescription3("Verbose output.")
33536
+ );
33537
+ var BATCH_SIZE = 50;
33538
+ var codegen = make58(
33539
+ "codegen",
33540
+ { file: file4, project: project2, verbose },
33541
+ fn("codegen")(function* ({ file: file6, project: project4, verbose: verbose2 }) {
33542
+ const path2 = yield* Path2;
33543
+ const fs = yield* FileSystem;
33544
+ const tsInstance = yield* getTypeScript;
33545
+ let filesToCodegen = /* @__PURE__ */ new Set();
33546
+ let checkedFilesCount = 0;
33547
+ let updatedFilesCount = 0;
33548
+ if (isSome2(project4)) {
33549
+ filesToCodegen = yield* getFileNamesInTsConfig(project4.value);
33550
+ }
33551
+ if (isSome2(file6)) {
33552
+ filesToCodegen.add(path2.resolve(file6.value));
33553
+ }
33554
+ if (filesToCodegen.size === 0) {
33555
+ return yield* new NoFilesToCodegenError();
33556
+ }
33557
+ const filesWithCodegenDirective = /* @__PURE__ */ new Set();
33558
+ for (const filePath of filesToCodegen) {
33559
+ const sourceText = yield* fs.readFileString(filePath);
33560
+ if (sourceText.toLowerCase().indexOf("@effect-codegens") !== -1) {
33561
+ filesWithCodegenDirective.add(filePath);
33562
+ }
33563
+ }
33564
+ if (filesWithCodegenDirective.size === 0) {
33565
+ return yield* new NoFilesToCodegenError();
33566
+ }
33567
+ const filesToCodegenArray = fromIterable(filesWithCodegenDirective);
33568
+ const batches = chunksOf(filesToCodegenArray, BATCH_SIZE);
33569
+ let lastLanguageService;
33570
+ const disposeIfLanguageServiceChanged = (languageService) => {
33571
+ if (lastLanguageService !== languageService) {
33572
+ lastLanguageService?.dispose();
33573
+ lastLanguageService = languageService;
33574
+ }
33575
+ };
33576
+ for (const batch of batches) {
33577
+ const { service: service3 } = (0, import_project_service.createProjectService)({ options: { loadTypeScriptPlugins: false } });
33578
+ for (const filePath of batch) {
33579
+ service3.openClientFile(filePath);
33580
+ try {
33581
+ const scriptInfo = service3.getScriptInfo(filePath);
33582
+ if (!scriptInfo) continue;
33583
+ const project5 = scriptInfo.getDefaultProject();
33584
+ const languageService = project5.getLanguageService(true);
33585
+ disposeIfLanguageServiceChanged(languageService);
33586
+ const program = languageService.getProgram();
33587
+ if (!program) continue;
33588
+ const sourceFile = program.getSourceFile(filePath);
33589
+ if (!sourceFile) continue;
33590
+ const pluginConfig = extractEffectLspOptions(program.getCompilerOptions());
33591
+ if (!pluginConfig) continue;
33592
+ const formatContext = tsInstance.formatting.getFormatContext(
33593
+ tsInstance.getDefaultFormatCodeSettings(project5.getNewLine()),
33594
+ project5
33595
+ );
33596
+ const allFileChanges = pipe(
33597
+ gen3(function* () {
33598
+ let allChanges = [];
33599
+ const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
33600
+ for (const { codegen: codegen2, hash: hash2, range: range3 } of codegensWithRanges) {
33601
+ const applicable = yield* pipe(
33602
+ getEditsForCodegen([codegen2], sourceFile, range3),
33603
+ orElse14(() => void_8)
33604
+ );
33605
+ if (applicable && applicable.hash !== hash2) {
33606
+ const changes2 = tsInstance.textChanges.ChangeTracker.with(
33607
+ {
33608
+ formatContext,
33609
+ host: project5,
33610
+ preferences: {}
33611
+ },
33612
+ (changeTracker) => pipe(
33613
+ applicable.apply,
33614
+ provideService7(ChangeTracker, changeTracker),
33615
+ run9
33616
+ )
33617
+ );
33618
+ allChanges = [...allChanges, ...changes2];
33619
+ }
33620
+ }
33621
+ return allChanges;
33622
+ }),
33623
+ nanoLayer3,
33624
+ nanoLayer2,
33625
+ nanoLayer,
33626
+ provideService7(TypeCheckerApi, program.getTypeChecker()),
33627
+ provideService7(TypeScriptProgram, program),
33628
+ provideService7(TypeScriptApi, tsInstance),
33629
+ provideService7(
33630
+ LanguageServicePluginOptions,
33631
+ { ...parse4(pluginConfig), diagnosticsName: false }
33632
+ ),
33633
+ run9,
33634
+ getOrElse(() => [])
33635
+ );
33636
+ checkedFilesCount++;
33637
+ const thisFileChanges = allFileChanges.filter((change) => change.fileName === sourceFile.fileName);
33638
+ const flattenedChanges = flatten(thisFileChanges.map((change) => change.textChanges));
33639
+ if (verbose2) {
33640
+ if (flattenedChanges.length > 0) {
33641
+ console.log(`${filePath}: with ${flattenedChanges.length} changes`);
33642
+ } else {
33643
+ console.log(`${filePath}: no changes`);
33644
+ }
33645
+ }
33646
+ if (flattenedChanges.length === 0) continue;
33647
+ const sourceText = yield* fs.readFileString(filePath);
33648
+ const newSourceText = yield* applyTextChanges(sourceText, flattenedChanges);
33649
+ yield* fs.writeFileString(filePath, newSourceText);
33650
+ updatedFilesCount++;
33651
+ } finally {
33652
+ service3.closeClientFile(filePath);
33653
+ }
33654
+ }
33655
+ yield* yieldNow4();
33656
+ }
33657
+ disposeIfLanguageServiceChanged(void 0);
33658
+ console.log(
33659
+ `${filesToCodegen.size} involved files, of which ${filesWithCodegenDirective.size} with codegens.
33660
+ ${checkedFilesCount} checked and ${updatedFilesCount} updated.`
33661
+ );
33662
+ })
33663
+ );
33664
+
33665
+ // src/cli/diagnostics.ts
33666
+ var import_project_service2 = __toESM(require_dist2());
33667
+
33066
33668
  // src/diagnostics/anyUnknownInErrorContext.ts
33067
33669
  var anyUnknownInErrorContext = createDiagnostic({
33068
33670
  name: "anyUnknownInErrorContext",
@@ -34671,300 +35273,6 @@ var nonObjectEffectServiceType = createDiagnostic({
34671
35273
  })
34672
35274
  });
34673
35275
 
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
35276
  // src/diagnostics/outdatedEffectCodegen.ts
34969
35277
  var outdatedEffectCodegen = createDiagnostic({
34970
35278
  name: "outdatedEffectCodegen",
@@ -34972,23 +35280,23 @@ var outdatedEffectCodegen = createDiagnostic({
34972
35280
  severity: "warning",
34973
35281
  apply: fn2("outdatedEffectCodegen.apply")(function* (sourceFile, _report) {
34974
35282
  const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
34975
- for (const { codegen, hash: hash2, range: range3 } of codegensWithRanges) {
35283
+ for (const { codegen: codegen2, hash: hash2, range: range3 } of codegensWithRanges) {
34976
35284
  yield* pipe(
34977
- getEditsForCodegen([codegen], sourceFile, range3),
35285
+ getEditsForCodegen([codegen2], sourceFile, range3),
34978
35286
  map34((applicable) => {
34979
35287
  if (applicable.hash !== hash2) {
34980
35288
  _report({
34981
35289
  location: range3,
34982
- messageText: `Codegen ${codegen.name} result is outdated`,
35290
+ messageText: `Codegen ${codegen2.name} result is outdated`,
34983
35291
  fixes: [
34984
35292
  {
34985
35293
  fixName: "outdatedEffectCodegen_fix",
34986
- description: `Re-run ${codegen.name}`,
35294
+ description: `Re-run ${codegen2.name}`,
34987
35295
  apply: applicable.apply
34988
35296
  },
34989
35297
  {
34990
35298
  fixName: "outdatedEffectCodegen_ignore",
34991
- description: `Ignore this ${codegen.name} update`,
35299
+ description: `Ignore this ${codegen2.name} update`,
34992
35300
  apply: applicable.ignore
34993
35301
  }
34994
35302
  ]
@@ -34999,7 +35307,7 @@ var outdatedEffectCodegen = createDiagnostic({
34999
35307
  (e) => sync11(() => {
35000
35308
  _report({
35001
35309
  location: range3,
35002
- messageText: `Codegen ${codegen.name} is not applicable here: ${e.cause}`,
35310
+ messageText: `Codegen ${codegen2.name} is not applicable here: ${e.cause}`,
35003
35311
  fixes: []
35004
35312
  });
35005
35313
  })
@@ -35695,6 +36003,66 @@ var unnecessaryEffectGen = createDiagnostic({
35695
36003
  })
35696
36004
  });
35697
36005
 
36006
+ // src/diagnostics/unnecessaryFailYieldableError.ts
36007
+ var unnecessaryFailYieldableError = createDiagnostic({
36008
+ name: "unnecessaryFailYieldableError",
36009
+ code: 29,
36010
+ severity: "suggestion",
36011
+ apply: fn2("unnecessaryFailYieldableError.apply")(function* (sourceFile, report) {
36012
+ const ts = yield* service2(TypeScriptApi);
36013
+ const typeParser = yield* service2(TypeParser);
36014
+ const typeChecker = yield* service2(TypeCheckerApi);
36015
+ const yieldableErrorTypes = yield* pipe(
36016
+ typeParser.effectCauseYieldableErrorTypes(sourceFile),
36017
+ orElse14(() => succeed17([]))
36018
+ );
36019
+ const nodeToVisit = [];
36020
+ const appendNodeToVisit = (node) => {
36021
+ nodeToVisit.push(node);
36022
+ return void 0;
36023
+ };
36024
+ ts.forEachChild(sourceFile, appendNodeToVisit);
36025
+ while (nodeToVisit.length > 0) {
36026
+ const node = nodeToVisit.shift();
36027
+ ts.forEachChild(node, appendNodeToVisit);
36028
+ if (ts.isYieldExpression(node) && node.asteriskToken && node.expression && ts.isCallExpression(node.expression)) {
36029
+ const callExpression = node.expression;
36030
+ yield* pipe(
36031
+ typeParser.isNodeReferenceToEffectModuleApi("fail")(callExpression.expression),
36032
+ map34(() => {
36033
+ if (callExpression.arguments.length > 0) {
36034
+ const failArgument = callExpression.arguments[0];
36035
+ const argumentType = typeChecker.getTypeAtLocation(failArgument);
36036
+ const isYieldableError = yieldableErrorTypes.some(
36037
+ (yieldableType) => typeChecker.isTypeAssignableTo(argumentType, yieldableType)
36038
+ );
36039
+ if (isYieldableError) {
36040
+ report({
36041
+ location: node,
36042
+ messageText: `This Effect.fail call uses a yieldable error type as argument. You can yield* the error directly instead.`,
36043
+ fixes: [{
36044
+ fixName: "unnecessaryFailYieldableError_fix",
36045
+ description: "Replace yield* Effect.fail with yield*",
36046
+ apply: gen3(function* () {
36047
+ const changeTracker = yield* service2(ChangeTracker);
36048
+ changeTracker.replaceNode(
36049
+ sourceFile,
36050
+ callExpression,
36051
+ failArgument
36052
+ );
36053
+ })
36054
+ }]
36055
+ });
36056
+ }
36057
+ }
36058
+ }),
36059
+ ignore3
36060
+ );
36061
+ }
36062
+ }
36063
+ })
36064
+ });
36065
+
35698
36066
  // src/diagnostics/unnecessaryPipe.ts
35699
36067
  var unnecessaryPipe = createDiagnostic({
35700
36068
  name: "unnecessaryPipe",
@@ -35882,6 +36250,7 @@ var diagnostics = [
35882
36250
  floatingEffect,
35883
36251
  missingStarInYieldEffectGen,
35884
36252
  unnecessaryEffectGen,
36253
+ unnecessaryFailYieldableError,
35885
36254
  missingReturnYieldStar,
35886
36255
  leakingRequirements,
35887
36256
  unnecessaryPipe,
@@ -35912,58 +36281,37 @@ var NoFilesToCheckError = class extends TaggedError("NoFilesToCheckError") {
35912
36281
  return "No files to check. Please provide an existing .ts file or a project tsconfig.json";
35913
36282
  }
35914
36283
  };
35915
- var file4 = file3("file").pipe(
36284
+ var file5 = file3("file").pipe(
35916
36285
  optional4,
35917
36286
  withDescription3("The full path of the file to check for diagnostics.")
35918
36287
  );
35919
- var project2 = file3("project").pipe(
36288
+ var project3 = file3("project").pipe(
35920
36289
  optional4,
35921
36290
  withDescription3("The full path of the project tsconfig.json file to check for diagnostics.")
35922
36291
  );
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;
36292
+ var BATCH_SIZE2 = 50;
35927
36293
  var diagnostics2 = make58(
35928
36294
  "diagnostics",
35929
- { file: file4, project: project2 },
35930
- fn("diagnostics")(function* ({ file: file5, project: project3 }) {
36295
+ { file: file5, project: project3 },
36296
+ fn("diagnostics")(function* ({ file: file6, project: project4 }) {
35931
36297
  const path2 = yield* Path2;
35932
36298
  const tsInstance = yield* getTypeScript;
35933
- const filesToCheck = /* @__PURE__ */ new Set();
36299
+ let filesToCheck = /* @__PURE__ */ new Set();
35934
36300
  let checkedFilesCount = 0;
35935
36301
  let errorsCount = 0;
35936
36302
  let warningsCount = 0;
35937
36303
  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
- }
36304
+ if (isSome2(project4)) {
36305
+ filesToCheck = yield* getFileNamesInTsConfig(project4.value);
36306
+ }
36307
+ if (isSome2(file6)) {
36308
+ filesToCheck.add(path2.resolve(file6.value));
35961
36309
  }
35962
36310
  if (filesToCheck.size === 0) {
35963
36311
  return yield* new NoFilesToCheckError();
35964
36312
  }
35965
36313
  const filesToCheckArray = fromIterable(filesToCheck);
35966
- const batches = chunksOf(filesToCheckArray, BATCH_SIZE);
36314
+ const batches = chunksOf(filesToCheckArray, BATCH_SIZE2);
35967
36315
  let lastLanguageService;
35968
36316
  const disposeIfLanguageServiceChanged = (languageService) => {
35969
36317
  if (lastLanguageService !== languageService) {
@@ -35972,14 +36320,14 @@ var diagnostics2 = make58(
35972
36320
  }
35973
36321
  };
35974
36322
  for (const batch of batches) {
35975
- const { service: service3 } = (0, import_project_service.createProjectService)({ options: { loadTypeScriptPlugins: false } });
36323
+ const { service: service3 } = (0, import_project_service2.createProjectService)({ options: { loadTypeScriptPlugins: false } });
35976
36324
  for (const filePath of batch) {
35977
36325
  service3.openClientFile(filePath);
35978
36326
  try {
35979
36327
  const scriptInfo = service3.getScriptInfo(filePath);
35980
36328
  if (!scriptInfo) continue;
35981
- const project4 = scriptInfo.getDefaultProject();
35982
- const languageService = project4.getLanguageService(true);
36329
+ const project5 = scriptInfo.getDefaultProject();
36330
+ const languageService = project5.getLanguageService(true);
35983
36331
  disposeIfLanguageServiceChanged(languageService);
35984
36332
  const program = languageService.getProgram();
35985
36333
  if (!program) continue;
@@ -36070,7 +36418,7 @@ var getPatchesForModule = fn("getPatchesForModule")(
36070
36418
  let insertCheckSourceFilePosition = none2();
36071
36419
  let insertSkipPrecedingCommentDirectivePosition = none2();
36072
36420
  let insertAppendMetadataRelationErrorPosition = none2();
36073
- const nodesToCheck = [];
36421
+ let nodesToCheck = [];
36074
36422
  function findNodeAtPositionIncludingTrivia(sourceFile2, position) {
36075
36423
  function find3(node) {
36076
36424
  if (position >= node.pos && position < node.end) {
@@ -36098,7 +36446,7 @@ var getPatchesForModule = fn("getPatchesForModule")(
36098
36446
  if (!pushFunctionDeclarationNode("checkSourceFileWorker")) requiresFullScan = true;
36099
36447
  if (!pushFunctionDeclarationNode("markPrecedingCommentDirectiveLine")) requiresFullScan = true;
36100
36448
  if (!pushFunctionDeclarationNode("reportRelationError")) requiresFullScan = true;
36101
- if (requiresFullScan) nodesToCheck.push(sourceFile);
36449
+ if (requiresFullScan) nodesToCheck = [sourceFile];
36102
36450
  while (nodesToCheck.length > 0) {
36103
36451
  const node = nodesToCheck.shift();
36104
36452
  if (!node) continue;
@@ -36328,7 +36676,7 @@ var cliCommand = make58(
36328
36676
  "effect-language-service",
36329
36677
  {},
36330
36678
  () => log3("Please select a command or run --help.")
36331
- ).pipe(withSubcommands3([patch9, unpatch, check2, diagnostics2]));
36679
+ ).pipe(withSubcommands3([patch9, unpatch, check2, diagnostics2, codegen]));
36332
36680
  var main = run8(cliCommand, {
36333
36681
  name: "effect-language-service",
36334
36682
  version: "0.0.2"