@effect/language-service 0.33.2 → 0.35.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/README.md CHANGED
@@ -53,6 +53,7 @@ And you're done! You'll now be able to use a set of refactors and diagnostics th
53
53
  - Detect unnecessary pipe chains like `X.pipe(Y).pipe(Z)`
54
54
  - Warn when using `Effect.Service` with `accessors: true` but methods have generics or multiple signatures
55
55
  - Warn on missing service dependencies in `Effect.Service` declarations
56
+ - Warn when schema classes override the default constructor behavior
56
57
 
57
58
  ### Completions
58
59
 
@@ -68,6 +69,8 @@ And you're done! You'll now be able to use a set of refactors and diagnostics th
68
69
 
69
70
  - Transform an async function definition, into an Effect by using Effect.gen.
70
71
  - Transform an async function definition, into an Effect by using Effect.gen, and generating a tagged error for each promise call.
72
+ - Transform an async function definition, into an Effect by using Effect.fn.
73
+ - Transform an async function definition, into an Effect by using Effect.fn, and generating a tagged error for each promise call.
71
74
  - Transform a function returning an Effect.gen into a Effect.fn
72
75
  - Implement Service accessors in an `Effect.Service` or `Context.Tag` declaration
73
76
  - Function calls to pipe: Transform a set of function calls to a pipe() call.
@@ -137,9 +140,8 @@ Your `tsconfig.json` should look like this:
137
140
  To get diagnostics you need to install `ts-patch` which will make it possible to run `tspc`.
138
141
 
139
142
  Running `tspc` in your project will now also run the plugin and give you the error diagnostics at compile time.
140
- Effect diagnostics in watch mode with noEmit enabled are not supported by ts-patch unfortunately.
141
-
142
- If you use incremental builds, after enabling ts-patch, a full rebuild may be necessary to invalidate the previous diagnostics cache.
143
+ Effect error diagnostics will be shown only after standard TypeScript diagnostics have been satisfied.
144
+ Beware that setting noEmit will completely skip the effect diagnostics.
143
145
 
144
146
  ```ts
145
147
  $ npx tspc
@@ -148,7 +150,7 @@ index.ts:3:1 - error TS3: Effect must be yielded or assigned to a variable.
148
150
  3 Effect.succeed(1)
149
151
  ~~~~~~~~~~~~~~~~~
150
152
 
151
- Found 1 error in index.ts:3 
153
+ Found 1 error in index.ts:3
152
154
  ```
153
155
 
154
156
  ## Configuring diagnostics
package/cli.js CHANGED
@@ -28495,6 +28495,31 @@ var NanoTag = class {
28495
28495
  }
28496
28496
  };
28497
28497
  var Tag4 = (identifier2) => new NanoTag(identifier2);
28498
+ var SingleShotGen3 = class _SingleShotGen {
28499
+ called = false;
28500
+ self;
28501
+ constructor(self) {
28502
+ this.self = self;
28503
+ }
28504
+ /**
28505
+ * @since 2.0.0
28506
+ */
28507
+ next(a) {
28508
+ return this.called ? {
28509
+ value: a,
28510
+ done: true
28511
+ } : (this.called = true, {
28512
+ value: this.self,
28513
+ done: false
28514
+ });
28515
+ }
28516
+ /**
28517
+ * @since 2.0.0
28518
+ */
28519
+ [Symbol.iterator]() {
28520
+ return new _SingleShotGen(this.self);
28521
+ }
28522
+ };
28498
28523
  var evaluate2 = Symbol.for("Nano.evaluate");
28499
28524
  var contA = Symbol.for("Nano.contA");
28500
28525
  var contE = Symbol.for("Nano.contE");
@@ -28509,7 +28534,7 @@ var NanoDefectException = class {
28509
28534
  };
28510
28535
  var PrimitiveProto = {
28511
28536
  [Symbol.iterator]() {
28512
- return new SingleShotGen(new YieldWrap(this));
28537
+ return new SingleShotGen3(this);
28513
28538
  }
28514
28539
  };
28515
28540
  var SucceedProto = {
@@ -28632,7 +28657,7 @@ var FromIteratorProto = {
28632
28657
  const state = this[args2][0].next(value5);
28633
28658
  if (state.done) return succeed17(state.value);
28634
28659
  fiber._stack.push(this);
28635
- return yieldWrapGet(state.value);
28660
+ return state.value;
28636
28661
  },
28637
28662
  [evaluate2](fiber) {
28638
28663
  return this[contA](this[args2][1], fiber);
@@ -28961,7 +28986,7 @@ function makeTypeScriptUtils(ts2) {
28961
28986
  function isNodeInRange(textRange) {
28962
28987
  return (node) => node.pos <= textRange.pos && node.end >= textRange.end;
28963
28988
  }
28964
- function transformAsyncAwaitToEffectGen(node, effectModuleName, onAwait) {
28989
+ function transformAsyncAwaitToEffectGeneratorBody(body, onAwait) {
28965
28990
  function visitor(_) {
28966
28991
  if (ts2.isAwaitExpression(_)) {
28967
28992
  const expression = ts2.visitEachChild(_.expression, visitor, ts2.nullTransformationContext);
@@ -28972,7 +28997,44 @@ function makeTypeScriptUtils(ts2) {
28972
28997
  }
28973
28998
  return ts2.visitEachChild(_, visitor, ts2.nullTransformationContext);
28974
28999
  }
28975
- const generatorBody = visitor(node.body);
29000
+ return visitor(body);
29001
+ }
29002
+ function transformAsyncAwaitToEffectFn(node, effectModuleName, onAwait) {
29003
+ const generatorBody = transformAsyncAwaitToEffectGeneratorBody(node.body, onAwait);
29004
+ const fnName = node.name && ts2.isIdentifier(node.name) ? node.name : ts2.isVariableDeclaration(node.parent) && ts2.isIdentifier(node.parent.name) && node.parent.initializer === node ? node.parent.name : void 0;
29005
+ let fnCall = ts2.factory.createPropertyAccessExpression(
29006
+ ts2.factory.createIdentifier(effectModuleName),
29007
+ "fn"
29008
+ );
29009
+ if (fnName) {
29010
+ fnCall = ts2.factory.createCallExpression(
29011
+ fnName,
29012
+ void 0,
29013
+ [ts2.factory.createStringLiteral(fnName.text)]
29014
+ );
29015
+ }
29016
+ return tryPreserveDeclarationSemantics(
29017
+ node,
29018
+ ts2.factory.createCallExpression(
29019
+ fnCall,
29020
+ void 0,
29021
+ [
29022
+ ts2.factory.createFunctionExpression(
29023
+ void 0,
29024
+ ts2.factory.createToken(ts2.SyntaxKind.AsteriskToken),
29025
+ void 0,
29026
+ node.typeParameters,
29027
+ node.parameters,
29028
+ void 0,
29029
+ ts2.isBlock(generatorBody) ? generatorBody : ts2.factory.createBlock([ts2.factory.createReturnStatement(generatorBody)])
29030
+ )
29031
+ ]
29032
+ ),
29033
+ true
29034
+ );
29035
+ }
29036
+ function transformAsyncAwaitToEffectGen(node, effectModuleName, onAwait) {
29037
+ const generatorBody = transformAsyncAwaitToEffectGeneratorBody(node.body, onAwait);
28976
29038
  const effectGenCallExp = createEffectGenCallExpression(effectModuleName, generatorBody);
28977
29039
  let currentFlags = ts2.getCombinedModifierFlags(node);
28978
29040
  currentFlags &= ~ts2.ModifierFlags.Async;
@@ -29076,12 +29138,15 @@ function makeTypeScriptUtils(ts2) {
29076
29138
  }
29077
29139
  return typeNode;
29078
29140
  }
29079
- function tryPreserveDeclarationSemantics(nodeToReplace, node) {
29141
+ function tryPreserveDeclarationSemantics(nodeToReplace, node, dropAsync) {
29080
29142
  if (!ts2.isExpression(node)) return node;
29081
29143
  if (ts2.isFunctionDeclaration(nodeToReplace)) {
29082
29144
  if (!nodeToReplace.name) return node;
29145
+ let currentFlags = ts2.getCombinedModifierFlags(nodeToReplace);
29146
+ currentFlags &= ~ts2.ModifierFlags.Async;
29147
+ const newModifiers = dropAsync ? ts2.factory.createModifiersFromModifierFlags(currentFlags) : nodeToReplace.modifiers;
29083
29148
  return ts2.factory.createVariableStatement(
29084
- nodeToReplace.modifiers,
29149
+ newModifiers,
29085
29150
  ts2.factory.createVariableDeclarationList(
29086
29151
  [ts2.factory.createVariableDeclaration(
29087
29152
  nodeToReplace.name,
@@ -29093,8 +29158,11 @@ function makeTypeScriptUtils(ts2) {
29093
29158
  )
29094
29159
  );
29095
29160
  } else if (ts2.isMethodDeclaration(nodeToReplace)) {
29161
+ let currentFlags = ts2.getCombinedModifierFlags(nodeToReplace);
29162
+ currentFlags &= ~ts2.ModifierFlags.Async;
29163
+ const newModifiers = dropAsync ? ts2.factory.createModifiersFromModifierFlags(currentFlags) : nodeToReplace.modifiers;
29096
29164
  return ts2.factory.createPropertyDeclaration(
29097
- nodeToReplace.modifiers,
29165
+ newModifiers,
29098
29166
  nodeToReplace.name,
29099
29167
  void 0,
29100
29168
  void 0,
@@ -29197,6 +29265,7 @@ function makeTypeScriptUtils(ts2) {
29197
29265
  getAncestorNodesInRange,
29198
29266
  toTextRange,
29199
29267
  isNodeInRange,
29268
+ transformAsyncAwaitToEffectFn,
29200
29269
  transformAsyncAwaitToEffectGen,
29201
29270
  findImportedModuleIdentifierByPackageAndNameOrBarrel,
29202
29271
  simplifyTypeNode,
@@ -31969,6 +32038,68 @@ var outdatedEffectCodegen = createDiagnostic({
31969
32038
  })
31970
32039
  });
31971
32040
 
32041
+ // src/diagnostics/overriddenSchemaConstructor.ts
32042
+ var overriddenSchemaConstructor = createDiagnostic({
32043
+ name: "overriddenSchemaConstructor",
32044
+ code: 30,
32045
+ severity: "error",
32046
+ apply: fn("overriddenSchemaConstructor.apply")(function* (sourceFile, report) {
32047
+ const ts2 = yield* service2(TypeScriptApi);
32048
+ const typeParser = yield* service2(TypeParser);
32049
+ const typeChecker = yield* service2(TypeCheckerApi);
32050
+ const nodeToVisit = [];
32051
+ const appendNodeToVisit = (node) => {
32052
+ nodeToVisit.push(node);
32053
+ return void 0;
32054
+ };
32055
+ ts2.forEachChild(sourceFile, appendNodeToVisit);
32056
+ while (nodeToVisit.length > 0) {
32057
+ const node = nodeToVisit.shift();
32058
+ if (ts2.isClassDeclaration(node) && node.heritageClauses) {
32059
+ let extendsSchema = false;
32060
+ for (const heritageClause of node.heritageClauses) {
32061
+ if (heritageClause.token === ts2.SyntaxKind.ExtendsKeyword) {
32062
+ for (const type2 of heritageClause.types) {
32063
+ const typeAtLocation = typeChecker.getTypeAtLocation(type2.expression);
32064
+ const isSchema2 = yield* pipe(
32065
+ typeParser.effectSchemaType(typeAtLocation, type2.expression),
32066
+ map33(() => true),
32067
+ orElse14(() => succeed17(false))
32068
+ );
32069
+ if (isSchema2) {
32070
+ extendsSchema = true;
32071
+ break;
32072
+ }
32073
+ }
32074
+ }
32075
+ if (extendsSchema) break;
32076
+ }
32077
+ if (extendsSchema) {
32078
+ const members = node.members;
32079
+ for (const member of members) {
32080
+ if (ts2.isConstructorDeclaration(member)) {
32081
+ report({
32082
+ location: member,
32083
+ messageText: "Classes extending Schema must not override the constructor",
32084
+ fixes: [{
32085
+ fixName: "overriddenSchemaConstructor_fix",
32086
+ description: "Remove the constructor override",
32087
+ apply: gen3(function* () {
32088
+ const changeTracker = yield* service2(ChangeTracker);
32089
+ changeTracker.delete(sourceFile, member);
32090
+ })
32091
+ }]
32092
+ });
32093
+ break;
32094
+ }
32095
+ }
32096
+ }
32097
+ }
32098
+ ts2.forEachChild(node, appendNodeToVisit);
32099
+ }
32100
+ })
32101
+ });
32102
+
31972
32103
  // src/diagnostics/returnEffectInGen.ts
31973
32104
  var returnEffectInGen = createDiagnostic({
31974
32105
  name: "returnEffectInGen",
@@ -32487,6 +32618,7 @@ var diagnostics = [
32487
32618
  strictBooleanExpressions,
32488
32619
  multipleEffectProvide,
32489
32620
  outdatedEffectCodegen,
32621
+ overriddenSchemaConstructor,
32490
32622
  unsupportedServiceAccessors
32491
32623
  ];
32492
32624