@effect/language-service 0.81.0 → 0.83.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.
@@ -27,7 +27,7 @@ __export(effect_lsp_patch_utils_exports, {
27
27
  });
28
28
  module.exports = __toCommonJS(effect_lsp_patch_utils_exports);
29
29
 
30
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Pipeable.js
30
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Pipeable.js
31
31
  var pipeArguments = (self, args3) => {
32
32
  switch (args3.length) {
33
33
  case 0:
@@ -60,7 +60,7 @@ var pipeArguments = (self, args3) => {
60
60
  }
61
61
  };
62
62
 
63
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Function.js
63
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Function.js
64
64
  var dual = function(arity, body) {
65
65
  if (typeof arity === "function") {
66
66
  return function() {
@@ -108,7 +108,7 @@ function pipe(a, ...args3) {
108
108
  return pipeArguments(a, args3);
109
109
  }
110
110
 
111
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/equal.js
111
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/equal.js
112
112
  var getAllObjectKeys = (obj) => {
113
113
  const keys2 = new Set(Reflect.ownKeys(obj));
114
114
  if (obj.constructor === Object) return keys2;
@@ -131,7 +131,7 @@ var getAllObjectKeys = (obj) => {
131
131
  };
132
132
  var byReferenceInstances = /* @__PURE__ */ new WeakSet();
133
133
 
134
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Predicate.js
134
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Predicate.js
135
135
  function isString(input) {
136
136
  return typeof input === "string";
137
137
  }
@@ -152,7 +152,7 @@ function isObjectKeyword(input) {
152
152
  }
153
153
  var hasProperty = /* @__PURE__ */ dual(2, (self, property) => isObjectKeyword(self) && property in self);
154
154
 
155
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Hash.js
155
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Hash.js
156
156
  var symbol = "~effect/interfaces/Hash";
157
157
  var hash = (self) => {
158
158
  switch (typeof self) {
@@ -271,7 +271,7 @@ function withVisitedTracking(obj, fn2) {
271
271
  return result;
272
272
  }
273
273
 
274
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Equal.js
274
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Equal.js
275
275
  var symbol2 = "~effect/interfaces/Equal";
276
276
  function equals() {
277
277
  if (arguments.length === 1) {
@@ -433,10 +433,10 @@ var compareSets = /* @__PURE__ */ makeCompareSet(compareBoth);
433
433
  var isEqual = (u) => hasProperty(u, symbol2);
434
434
  var asEquivalence = () => equals;
435
435
 
436
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/array.js
436
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/array.js
437
437
  var isArrayNonEmpty = (self) => self.length > 0;
438
438
 
439
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Redactable.js
439
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Redactable.js
440
440
  var symbolRedactable = /* @__PURE__ */ Symbol.for("~effect/Inspectable/redactable");
441
441
  var isRedactable = (u) => hasProperty(u, symbolRedactable);
442
442
  function redact(u) {
@@ -455,7 +455,7 @@ var emptyServiceMap = {
455
455
  }
456
456
  };
457
457
 
458
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Formatter.js
458
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Formatter.js
459
459
  function format(input, options) {
460
460
  const space = options?.space ?? 0;
461
461
  const seen = /* @__PURE__ */ new WeakSet();
@@ -534,7 +534,7 @@ function safeToString(input) {
534
534
  }
535
535
  }
536
536
 
537
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Inspectable.js
537
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Inspectable.js
538
538
  var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
539
539
  var toJson = (input) => {
540
540
  try {
@@ -578,30 +578,7 @@ var Class = class {
578
578
  }
579
579
  };
580
580
 
581
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Utils.js
582
- var GenKindTypeId = "~effect/Utils/GenKind";
583
- var GenKindImpl = class {
584
- value;
585
- constructor(value) {
586
- this.value = value;
587
- }
588
- get _F() {
589
- return identity;
590
- }
591
- get _R() {
592
- return (_) => _;
593
- }
594
- get _O() {
595
- return (_) => _;
596
- }
597
- get _E() {
598
- return (_) => _;
599
- }
600
- [GenKindTypeId] = GenKindTypeId;
601
- [Symbol.iterator]() {
602
- return new SingleShotGen(this);
603
- }
604
- };
581
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Utils.js
605
582
  var SingleShotGen = class _SingleShotGen {
606
583
  called = false;
607
584
  self;
@@ -627,7 +604,7 @@ var SingleShotGen = class _SingleShotGen {
627
604
  return new _SingleShotGen(this.self);
628
605
  }
629
606
  };
630
- var InternalTypeId = "~effect/Effect/internal";
607
+ var InternalTypeId = "~effect/Utils/internal";
631
608
  var standard = {
632
609
  [InternalTypeId]: (body) => {
633
610
  return body();
@@ -643,10 +620,8 @@ var forced = {
643
620
  };
644
621
  var isNotOptimizedAway = /* @__PURE__ */ standard[InternalTypeId](() => new Error().stack)?.includes(InternalTypeId) === true;
645
622
  var internalCall = isNotOptimizedAway ? standard[InternalTypeId] : forced[InternalTypeId];
646
- var genConstructor = function* () {
647
- }.constructor;
648
623
 
649
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/core.js
624
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/core.js
650
625
  var EffectTypeId = `~effect/Effect`;
651
626
  var ExitTypeId = `~effect/Exit`;
652
627
  var effectVariance = {
@@ -993,7 +968,7 @@ var DoneVoid = {
993
968
  value: void 0
994
969
  };
995
970
 
996
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/option.js
971
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/option.js
997
972
  var TypeId = "~effect/data/Option";
998
973
  var CommonProto = {
999
974
  [TypeId]: {
@@ -1025,10 +1000,16 @@ var SomeProto = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create(Comm
1025
1000
  return exitSucceed(this.value);
1026
1001
  }
1027
1002
  });
1003
+ Object.defineProperty(SomeProto, "valueOrUndefined", {
1004
+ get() {
1005
+ return this.value;
1006
+ }
1007
+ });
1028
1008
  var NoneHash = /* @__PURE__ */ hash("None");
1029
1009
  var NoneProto = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create(CommonProto), {
1030
1010
  _tag: "None",
1031
1011
  _op: "None",
1012
+ valueOrUndefined: void 0,
1032
1013
  [symbol2](that) {
1033
1014
  return isOption(that) && isNone(that);
1034
1015
  },
@@ -1058,7 +1039,7 @@ var some = (value) => {
1058
1039
  return a;
1059
1040
  };
1060
1041
 
1061
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/result.js
1042
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/result.js
1062
1043
  var TypeId2 = "~effect/data/Result";
1063
1044
  var CommonProto2 = {
1064
1045
  [TypeId2]: {
@@ -1129,13 +1110,13 @@ var succeed = (success) => {
1129
1110
  return a;
1130
1111
  };
1131
1112
 
1132
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Order.js
1113
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Order.js
1133
1114
  function make(compare) {
1134
1115
  return (self, that) => self === that ? 0 : compare(self, that);
1135
1116
  }
1136
1117
  var String2 = /* @__PURE__ */ make((self, that) => self < that ? -1 : 1);
1137
1118
 
1138
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Option.js
1119
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Option.js
1139
1120
  var none2 = () => none;
1140
1121
  var some2 = some;
1141
1122
  var isNone2 = isNone;
@@ -1145,7 +1126,7 @@ var orElse = /* @__PURE__ */ dual(2, (self, that) => isNone2(self) ? that() : se
1145
1126
  var fromNullishOr = (a) => a == null ? none2() : some2(a);
1146
1127
  var getOrUndefined = /* @__PURE__ */ getOrElse(constUndefined);
1147
1128
 
1148
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Result.js
1129
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Result.js
1149
1130
  var succeed2 = succeed;
1150
1131
  var fail2 = fail;
1151
1132
  var isFailure2 = isFailure;
@@ -1153,7 +1134,7 @@ var isSuccess2 = isSuccess;
1153
1134
  var map = /* @__PURE__ */ dual(2, (self, f) => isSuccess2(self) ? succeed2(f(self.success)) : fail2(self.failure));
1154
1135
  var getOrElse2 = /* @__PURE__ */ dual(2, (self, onFailure) => isFailure2(self) ? onFailure(self.failure) : self.success);
1155
1136
 
1156
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Record.js
1137
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Record.js
1157
1138
  var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1158
1139
  const out = {
1159
1140
  ...self
@@ -1165,7 +1146,7 @@ var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1165
1146
  });
1166
1147
  var keys = (self) => Object.keys(self);
1167
1148
 
1168
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Array.js
1149
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Array.js
1169
1150
  var Array2 = globalThis.Array;
1170
1151
  var fromIterable = (collection) => Array2.isArray(collection) ? collection : Array2.from(collection);
1171
1152
  var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
@@ -5549,6 +5530,7 @@ var classSelfMismatch = createDiagnostic({
5549
5530
  if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
5550
5531
  const result = yield* pipe(
5551
5532
  typeParser.extendsEffectService(node),
5533
+ orElse2(() => typeParser.extendsServiceMapService(node)),
5552
5534
  orElse2(() => typeParser.extendsContextTag(node)),
5553
5535
  orElse2(() => typeParser.extendsEffectTag(node)),
5554
5536
  orElse2(() => typeParser.extendsSchemaClass(node)),
@@ -5924,6 +5906,89 @@ var effectFnIife = createDiagnostic({
5924
5906
  })
5925
5907
  });
5926
5908
 
5909
+ // src/diagnostics/effectFnImplicitAny.ts
5910
+ var getParameterName = (typescript, name) => {
5911
+ if (typescript.isIdentifier(name)) {
5912
+ return typescript.idText(name);
5913
+ }
5914
+ return "parameter";
5915
+ };
5916
+ var hasOuterContextualFunctionType = (typescript, typeChecker, node) => {
5917
+ const contextualType = typeChecker.getContextualType(node);
5918
+ if (!contextualType) {
5919
+ return false;
5920
+ }
5921
+ return typeChecker.getSignaturesOfType(contextualType, typescript.SignatureKind.Call).length > 0;
5922
+ };
5923
+ var effectFnImplicitAny = createDiagnostic({
5924
+ name: "effectFnImplicitAny",
5925
+ code: 54,
5926
+ description: "Mirrors noImplicitAny for unannotated Effect.fn and Effect.fnUntraced callback parameters when no outer contextual function type exists",
5927
+ group: "correctness",
5928
+ severity: "error",
5929
+ fixable: false,
5930
+ supportedEffect: ["v3", "v4"],
5931
+ apply: fn("effectFnImplicitAny.apply")(function* (sourceFile, report) {
5932
+ const ts = yield* service(TypeScriptApi);
5933
+ const program = yield* service(TypeScriptProgram);
5934
+ const typeChecker = yield* service(TypeCheckerApi);
5935
+ const typeParser = yield* service(TypeParser);
5936
+ const noImplicitAny = program.getCompilerOptions().noImplicitAny ?? program.getCompilerOptions().strict ?? false;
5937
+ if (!noImplicitAny) {
5938
+ return;
5939
+ }
5940
+ const nodeToVisit = [sourceFile];
5941
+ const appendNodeToVisit = (node) => {
5942
+ nodeToVisit.push(node);
5943
+ return void 0;
5944
+ };
5945
+ while (nodeToVisit.length > 0) {
5946
+ const node = nodeToVisit.pop();
5947
+ ts.forEachChild(node, appendNodeToVisit);
5948
+ const parsed = yield* pipe(
5949
+ typeParser.effectFn(node),
5950
+ map4((result) => ({
5951
+ call: result.node,
5952
+ fn: result.regularFunction
5953
+ })),
5954
+ orElse2(
5955
+ () => pipe(
5956
+ typeParser.effectFnGen(node),
5957
+ map4((result) => ({
5958
+ call: result.node,
5959
+ fn: result.generatorFunction
5960
+ }))
5961
+ )
5962
+ ),
5963
+ orElse2(
5964
+ () => pipe(
5965
+ typeParser.effectFnUntracedGen(node),
5966
+ map4((result) => ({
5967
+ call: result.node,
5968
+ fn: result.generatorFunction
5969
+ }))
5970
+ )
5971
+ ),
5972
+ orUndefined
5973
+ );
5974
+ if (!parsed || hasOuterContextualFunctionType(ts, typeChecker, parsed.call)) {
5975
+ continue;
5976
+ }
5977
+ for (const parameter of parsed.fn.parameters) {
5978
+ if (parameter.type || parameter.initializer) {
5979
+ continue;
5980
+ }
5981
+ const parameterName = getParameterName(ts, parameter.name);
5982
+ report({
5983
+ location: parameter.name,
5984
+ messageText: `Parameter '${parameterName}' implicitly has an 'any' type in Effect.fn/Effect.fnUntraced. Add an explicit type annotation or provide a contextual function type.`,
5985
+ fixes: []
5986
+ });
5987
+ }
5988
+ }
5989
+ })
5990
+ });
5991
+
5927
5992
  // src/diagnostics/effectFnOpportunity.ts
5928
5993
  var effectFnOpportunity = createDiagnostic({
5929
5994
  name: "effectFnOpportunity",
@@ -7458,6 +7523,24 @@ var leakingRequirements = createDiagnostic({
7458
7523
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
7459
7524
  const typeParser = yield* service(TypeParser);
7460
7525
  const tsUtils = yield* service(TypeScriptUtils);
7526
+ const isExpectedLeakingServiceSuppressed = (leakedServiceName, startNode) => {
7527
+ const sourceFile2 = tsUtils.getSourceFileOfNode(startNode);
7528
+ if (!sourceFile2) return false;
7529
+ return !!ts.findAncestor(startNode, (current) => {
7530
+ const ranges = ts.getLeadingCommentRanges(sourceFile2.text, current.pos) ?? [];
7531
+ const isSuppressed = ranges.some((range) => {
7532
+ const commentText = sourceFile2.text.slice(range.pos, range.end);
7533
+ return commentText.split("\n").filter((line) => line.includes("@effect-expect-leaking")).some((line) => {
7534
+ const markerIndex = line.indexOf("@effect-expect-leaking");
7535
+ return markerIndex !== -1 && line.slice(markerIndex + "@effect-expect-leaking".length).includes(leakedServiceName);
7536
+ });
7537
+ });
7538
+ if (isSuppressed) {
7539
+ return true;
7540
+ }
7541
+ return ts.isClassDeclaration(current) || ts.isVariableStatement(current) || ts.isExpressionStatement(current) || ts.isStatement(current) ? "quit" : false;
7542
+ });
7543
+ };
7461
7544
  const parseLeakedRequirements = cachedBy(
7462
7545
  fn("leakingServices.checkServiceLeaking")(
7463
7546
  function* (service2, atLocation) {
@@ -7539,8 +7622,12 @@ var leakingRequirements = createDiagnostic({
7539
7622
  (_, service2) => service2
7540
7623
  );
7541
7624
  function reportLeakingRequirements(node, requirements) {
7542
- if (requirements.length === 0) return;
7543
- const requirementsStr = requirements.map((_) => typeChecker.typeToString(_)).join(" | ");
7625
+ const filteredRequirements = requirements.filter(
7626
+ (requirement) => !isExpectedLeakingServiceSuppressed(typeChecker.typeToString(requirement), node)
7627
+ );
7628
+ if (filteredRequirements.length === 0) return;
7629
+ const requirementsStr = filteredRequirements.map((_) => typeChecker.typeToString(_)).join(" | ");
7630
+ const firstStr = typeChecker.typeToString(filteredRequirements[0]);
7544
7631
  report({
7545
7632
  location: node,
7546
7633
  messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
@@ -7549,7 +7636,7 @@ This leaks implementation details into the service's public type \u2014 callers
7549
7636
 
7550
7637
  Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
7551
7638
 
7552
- To suppress this diagnostic for specific dependency types that are intentionally passed through (e.g., HttpServerRequest), add \`@effect-leakable-service\` JSDoc to their interface declarations (e.g., the \`${typeChecker.typeToString(requirements[0])}\` interface), not to this service.
7639
+ To suppress this diagnostic for specific dependency types that are intentionally passed through (e.g., HttpServerRequest), add \`@effect-leakable-service\` JSDoc to their interface declarations (e.g., the \`${firstStr}\` interface), or to this service by adding a \`@effect-expect-leaking ${firstStr}\` JSDoc.
7553
7640
 
7554
7641
  More info and examples at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
7555
7642
  fixes: []
@@ -11870,6 +11957,7 @@ var diagnostics = [
11870
11957
  catchUnfailableEffect,
11871
11958
  classSelfMismatch,
11872
11959
  duplicatePackage,
11960
+ effectFnImplicitAny,
11873
11961
  effectGenUsesAdapter,
11874
11962
  missingEffectContext,
11875
11963
  missingEffectError,