@effect/language-service 0.33.2 → 0.34.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/index.js CHANGED
@@ -4475,6 +4475,68 @@ var outdatedEffectCodegen = createDiagnostic({
4475
4475
  })
4476
4476
  });
4477
4477
 
4478
+ // src/diagnostics/overriddenSchemaConstructor.ts
4479
+ var overriddenSchemaConstructor = createDiagnostic({
4480
+ name: "overriddenSchemaConstructor",
4481
+ code: 30,
4482
+ severity: "error",
4483
+ apply: fn("overriddenSchemaConstructor.apply")(function* (sourceFile, report) {
4484
+ const ts = yield* service(TypeScriptApi);
4485
+ const typeParser = yield* service(TypeParser);
4486
+ const typeChecker = yield* service(TypeCheckerApi);
4487
+ const nodeToVisit = [];
4488
+ const appendNodeToVisit = (node) => {
4489
+ nodeToVisit.push(node);
4490
+ return void 0;
4491
+ };
4492
+ ts.forEachChild(sourceFile, appendNodeToVisit);
4493
+ while (nodeToVisit.length > 0) {
4494
+ const node = nodeToVisit.shift();
4495
+ if (ts.isClassDeclaration(node) && node.heritageClauses) {
4496
+ let extendsSchema = false;
4497
+ for (const heritageClause of node.heritageClauses) {
4498
+ if (heritageClause.token === ts.SyntaxKind.ExtendsKeyword) {
4499
+ for (const type of heritageClause.types) {
4500
+ const typeAtLocation = typeChecker.getTypeAtLocation(type.expression);
4501
+ const isSchema = yield* pipe(
4502
+ typeParser.effectSchemaType(typeAtLocation, type.expression),
4503
+ map3(() => true),
4504
+ orElse2(() => succeed(false))
4505
+ );
4506
+ if (isSchema) {
4507
+ extendsSchema = true;
4508
+ break;
4509
+ }
4510
+ }
4511
+ }
4512
+ if (extendsSchema) break;
4513
+ }
4514
+ if (extendsSchema) {
4515
+ const members = node.members;
4516
+ for (const member of members) {
4517
+ if (ts.isConstructorDeclaration(member)) {
4518
+ report({
4519
+ location: member,
4520
+ messageText: "Classes extending Schema must not override the constructor",
4521
+ fixes: [{
4522
+ fixName: "overriddenSchemaConstructor_fix",
4523
+ description: "Remove the constructor override",
4524
+ apply: gen(function* () {
4525
+ const changeTracker = yield* service(ChangeTracker);
4526
+ changeTracker.delete(sourceFile, member);
4527
+ })
4528
+ }]
4529
+ });
4530
+ break;
4531
+ }
4532
+ }
4533
+ }
4534
+ }
4535
+ ts.forEachChild(node, appendNodeToVisit);
4536
+ }
4537
+ })
4538
+ });
4539
+
4478
4540
  // src/diagnostics/returnEffectInGen.ts
4479
4541
  var returnEffectInGen = createDiagnostic({
4480
4542
  name: "returnEffectInGen",
@@ -4993,6 +5055,7 @@ var diagnostics = [
4993
5055
  strictBooleanExpressions,
4994
5056
  multipleEffectProvide,
4995
5057
  outdatedEffectCodegen,
5058
+ overriddenSchemaConstructor,
4996
5059
  unsupportedServiceAccessors
4997
5060
  ];
4998
5061
 
@@ -10817,61 +10880,51 @@ var effectGenToFn = createRefactor({
10817
10880
  const ts = yield* service(TypeScriptApi);
10818
10881
  const tsUtils = yield* service(TypeScriptUtils);
10819
10882
  const typeParser = yield* service(TypeParser);
10820
- const parseEffectGenNode = fn("asyncAwaitToGen.apply")(function* (node) {
10821
- const effectGen = yield* typeParser.effectGen(node);
10822
- let pipeArgs2 = ts.factory.createNodeArray([]);
10823
- let nodeToReplace2 = node;
10824
- while (nodeToReplace2.parent) {
10825
- const parent = nodeToReplace2.parent;
10826
- if (ts.isConciseBody(nodeToReplace2) && ts.isArrowFunction(parent) && parent.body === nodeToReplace2) {
10827
- return { ...effectGen, pipeArgs: pipeArgs2, nodeToReplace: parent };
10828
- }
10829
- if ((ts.isFunctionDeclaration(parent) || ts.isMethodDeclaration(parent)) && parent.body === nodeToReplace2) {
10830
- return { ...effectGen, pipeArgs: pipeArgs2, nodeToReplace: parent };
10883
+ const skipReturnBlock = (node) => ts.isBlock(node) && node.statements.length === 1 && ts.isReturnStatement(node.statements[0]) && node.statements[0].expression ? node.statements[0].expression : node;
10884
+ const parseFunctionLikeReturnEffectGen = fn("parseFunctionLikeReturnEffect.apply")(function* (node) {
10885
+ if ((ts.isArrowFunction(node) || ts.isMethodDeclaration(node) || ts.isFunctionDeclaration(node)) && node.body) {
10886
+ let subject = skipReturnBlock(node.body);
10887
+ let pipeArgs2 = [];
10888
+ while (true) {
10889
+ const maybePipe = yield* option(typeParser.pipeCall(subject));
10890
+ if (isNone2(maybePipe)) break;
10891
+ subject = maybePipe.value.subject;
10892
+ pipeArgs2 = maybePipe.value.args.concat(pipeArgs2);
10831
10893
  }
10832
- if (ts.isBlock(parent) && parent.statements.length === 1 && parent.statements[0] === nodeToReplace2) {
10833
- nodeToReplace2 = parent;
10834
- continue;
10835
- }
10836
- if (ts.isReturnStatement(parent) && parent.expression === nodeToReplace2) {
10837
- nodeToReplace2 = parent;
10838
- continue;
10839
- }
10840
- const maybePipe = yield* pipe(
10841
- typeParser.pipeCall(parent),
10842
- orElse2((e) => parent.parent ? typeParser.pipeCall(parent.parent) : fail(e)),
10843
- option
10844
- );
10845
- if (isSome2(maybePipe) && maybePipe.value.subject === nodeToReplace2) {
10846
- pipeArgs2 = ts.factory.createNodeArray(pipeArgs2.concat(maybePipe.value.args));
10847
- nodeToReplace2 = maybePipe.value.node;
10848
- continue;
10849
- }
10850
- break;
10894
+ const fnIdentifier2 = node.name && ts.isIdentifier(node.name) ? node.name : ts.isVariableDeclaration(node.parent) && node.parent.name && ts.isIdentifier(node.parent.name) ? node.parent.name : void 0;
10895
+ const effectGen = yield* typeParser.effectGen(subject);
10896
+ return { ...effectGen, nodeToReplace: node, pipeArgs: pipeArgs2, fnIdentifier: fnIdentifier2 };
10851
10897
  }
10852
10898
  return yield* fail(new RefactorNotApplicableError());
10853
10899
  });
10900
+ const parentNodes = tsUtils.getAncestorNodesInRange(sourceFile, textRange);
10901
+ if (parentNodes.length === 0) return yield* fail(new RefactorNotApplicableError());
10902
+ const nodesFromInitializers = pipe(
10903
+ parentNodes,
10904
+ filter((_) => ts.isVariableDeclaration(_) && _.initializer ? true : false),
10905
+ map4((_) => _.initializer)
10906
+ );
10854
10907
  const maybeNode = yield* pipe(
10855
- tsUtils.getAncestorNodesInRange(sourceFile, textRange),
10856
- map4(parseEffectGenNode),
10908
+ nodesFromInitializers.concat(parentNodes),
10909
+ map4(parseFunctionLikeReturnEffectGen),
10857
10910
  firstSuccessOf,
10858
10911
  option
10859
10912
  );
10860
10913
  if (isNone2(maybeNode)) return yield* fail(new RefactorNotApplicableError());
10861
- const { effectModule, generatorFunction, nodeToReplace, pipeArgs } = maybeNode.value;
10914
+ const { effectModule, fnIdentifier, generatorFunction, nodeToReplace, pipeArgs } = maybeNode.value;
10862
10915
  return {
10863
10916
  kind: "refactor.rewrite.effect.effectGenToFn",
10864
- description: "Convert to Effect.fn",
10917
+ description: fnIdentifier ? `Convert to Effect.fn("${fnIdentifier.text}")` : "Convert to Effect.fn",
10865
10918
  apply: pipe(
10866
10919
  gen(function* () {
10867
10920
  const changeTracker = yield* service(ChangeTracker);
10868
- const effectFn = nodeToReplace.name && ts.isIdentifier(nodeToReplace.name) ? ts.factory.createCallExpression(
10921
+ const effectFn = fnIdentifier ? ts.factory.createCallExpression(
10869
10922
  ts.factory.createPropertyAccessExpression(
10870
10923
  effectModule,
10871
10924
  "fn"
10872
10925
  ),
10873
10926
  void 0,
10874
- [ts.factory.createStringLiteral(nodeToReplace.name.text)]
10927
+ [ts.factory.createStringLiteral(fnIdentifier.text)]
10875
10928
  ) : ts.factory.createPropertyAccessExpression(
10876
10929
  effectModule,
10877
10930
  "fn"