@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.
package/transform.js CHANGED
@@ -24,7 +24,7 @@ __export(transform_exports, {
24
24
  });
25
25
  module.exports = __toCommonJS(transform_exports);
26
26
 
27
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Pipeable.js
27
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Pipeable.js
28
28
  var pipeArguments = (self, args3) => {
29
29
  switch (args3.length) {
30
30
  case 0:
@@ -57,7 +57,7 @@ var pipeArguments = (self, args3) => {
57
57
  }
58
58
  };
59
59
 
60
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Function.js
60
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Function.js
61
61
  var dual = function(arity, body) {
62
62
  if (typeof arity === "function") {
63
63
  return function() {
@@ -105,7 +105,7 @@ function pipe(a, ...args3) {
105
105
  return pipeArguments(a, args3);
106
106
  }
107
107
 
108
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/equal.js
108
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/equal.js
109
109
  var getAllObjectKeys = (obj) => {
110
110
  const keys2 = new Set(Reflect.ownKeys(obj));
111
111
  if (obj.constructor === Object) return keys2;
@@ -128,7 +128,7 @@ var getAllObjectKeys = (obj) => {
128
128
  };
129
129
  var byReferenceInstances = /* @__PURE__ */ new WeakSet();
130
130
 
131
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Predicate.js
131
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Predicate.js
132
132
  function isString(input) {
133
133
  return typeof input === "string";
134
134
  }
@@ -149,7 +149,7 @@ function isObjectKeyword(input) {
149
149
  }
150
150
  var hasProperty = /* @__PURE__ */ dual(2, (self, property) => isObjectKeyword(self) && property in self);
151
151
 
152
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Hash.js
152
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Hash.js
153
153
  var symbol = "~effect/interfaces/Hash";
154
154
  var hash = (self) => {
155
155
  switch (typeof self) {
@@ -268,7 +268,7 @@ function withVisitedTracking(obj, fn2) {
268
268
  return result;
269
269
  }
270
270
 
271
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Equal.js
271
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Equal.js
272
272
  var symbol2 = "~effect/interfaces/Equal";
273
273
  function equals() {
274
274
  if (arguments.length === 1) {
@@ -430,10 +430,10 @@ var compareSets = /* @__PURE__ */ makeCompareSet(compareBoth);
430
430
  var isEqual = (u) => hasProperty(u, symbol2);
431
431
  var asEquivalence = () => equals;
432
432
 
433
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/array.js
433
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/array.js
434
434
  var isArrayNonEmpty = (self) => self.length > 0;
435
435
 
436
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Redactable.js
436
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Redactable.js
437
437
  var symbolRedactable = /* @__PURE__ */ Symbol.for("~effect/Inspectable/redactable");
438
438
  var isRedactable = (u) => hasProperty(u, symbolRedactable);
439
439
  function redact(u) {
@@ -452,7 +452,7 @@ var emptyServiceMap = {
452
452
  }
453
453
  };
454
454
 
455
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Formatter.js
455
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Formatter.js
456
456
  function format(input, options) {
457
457
  const space = options?.space ?? 0;
458
458
  const seen = /* @__PURE__ */ new WeakSet();
@@ -531,7 +531,7 @@ function safeToString(input) {
531
531
  }
532
532
  }
533
533
 
534
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Inspectable.js
534
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Inspectable.js
535
535
  var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
536
536
  var toJson = (input) => {
537
537
  try {
@@ -575,30 +575,7 @@ var Class = class {
575
575
  }
576
576
  };
577
577
 
578
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Utils.js
579
- var GenKindTypeId = "~effect/Utils/GenKind";
580
- var GenKindImpl = class {
581
- value;
582
- constructor(value) {
583
- this.value = value;
584
- }
585
- get _F() {
586
- return identity;
587
- }
588
- get _R() {
589
- return (_) => _;
590
- }
591
- get _O() {
592
- return (_) => _;
593
- }
594
- get _E() {
595
- return (_) => _;
596
- }
597
- [GenKindTypeId] = GenKindTypeId;
598
- [Symbol.iterator]() {
599
- return new SingleShotGen(this);
600
- }
601
- };
578
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Utils.js
602
579
  var SingleShotGen = class _SingleShotGen {
603
580
  called = false;
604
581
  self;
@@ -624,7 +601,7 @@ var SingleShotGen = class _SingleShotGen {
624
601
  return new _SingleShotGen(this.self);
625
602
  }
626
603
  };
627
- var InternalTypeId = "~effect/Effect/internal";
604
+ var InternalTypeId = "~effect/Utils/internal";
628
605
  var standard = {
629
606
  [InternalTypeId]: (body) => {
630
607
  return body();
@@ -640,10 +617,8 @@ var forced = {
640
617
  };
641
618
  var isNotOptimizedAway = /* @__PURE__ */ standard[InternalTypeId](() => new Error().stack)?.includes(InternalTypeId) === true;
642
619
  var internalCall = isNotOptimizedAway ? standard[InternalTypeId] : forced[InternalTypeId];
643
- var genConstructor = function* () {
644
- }.constructor;
645
620
 
646
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/core.js
621
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/core.js
647
622
  var EffectTypeId = `~effect/Effect`;
648
623
  var ExitTypeId = `~effect/Exit`;
649
624
  var effectVariance = {
@@ -990,7 +965,7 @@ var DoneVoid = {
990
965
  value: void 0
991
966
  };
992
967
 
993
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/option.js
968
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/option.js
994
969
  var TypeId = "~effect/data/Option";
995
970
  var CommonProto = {
996
971
  [TypeId]: {
@@ -1022,10 +997,16 @@ var SomeProto = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create(Comm
1022
997
  return exitSucceed(this.value);
1023
998
  }
1024
999
  });
1000
+ Object.defineProperty(SomeProto, "valueOrUndefined", {
1001
+ get() {
1002
+ return this.value;
1003
+ }
1004
+ });
1025
1005
  var NoneHash = /* @__PURE__ */ hash("None");
1026
1006
  var NoneProto = /* @__PURE__ */ Object.assign(/* @__PURE__ */ Object.create(CommonProto), {
1027
1007
  _tag: "None",
1028
1008
  _op: "None",
1009
+ valueOrUndefined: void 0,
1029
1010
  [symbol2](that) {
1030
1011
  return isOption(that) && isNone(that);
1031
1012
  },
@@ -1055,7 +1036,7 @@ var some = (value) => {
1055
1036
  return a;
1056
1037
  };
1057
1038
 
1058
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/internal/result.js
1039
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/result.js
1059
1040
  var TypeId2 = "~effect/data/Result";
1060
1041
  var CommonProto2 = {
1061
1042
  [TypeId2]: {
@@ -1126,13 +1107,13 @@ var succeed = (success) => {
1126
1107
  return a;
1127
1108
  };
1128
1109
 
1129
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Order.js
1110
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Order.js
1130
1111
  function make(compare) {
1131
1112
  return (self, that) => self === that ? 0 : compare(self, that);
1132
1113
  }
1133
1114
  var String2 = /* @__PURE__ */ make((self, that) => self < that ? -1 : 1);
1134
1115
 
1135
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Option.js
1116
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Option.js
1136
1117
  var none2 = () => none;
1137
1118
  var some2 = some;
1138
1119
  var isNone2 = isNone;
@@ -1142,7 +1123,7 @@ var orElse = /* @__PURE__ */ dual(2, (self, that) => isNone2(self) ? that() : se
1142
1123
  var fromNullishOr = (a) => a == null ? none2() : some2(a);
1143
1124
  var getOrUndefined = /* @__PURE__ */ getOrElse(constUndefined);
1144
1125
 
1145
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Result.js
1126
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Result.js
1146
1127
  var succeed2 = succeed;
1147
1128
  var fail2 = fail;
1148
1129
  var isFailure2 = isFailure;
@@ -1150,7 +1131,7 @@ var isSuccess2 = isSuccess;
1150
1131
  var map = /* @__PURE__ */ dual(2, (self, f) => isSuccess2(self) ? succeed2(f(self.success)) : fail2(self.failure));
1151
1132
  var getOrElse2 = /* @__PURE__ */ dual(2, (self, onFailure) => isFailure2(self) ? onFailure(self.failure) : self.success);
1152
1133
 
1153
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Record.js
1134
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Record.js
1154
1135
  var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1155
1136
  const out = {
1156
1137
  ...self
@@ -1162,7 +1143,7 @@ var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1162
1143
  });
1163
1144
  var keys = (self) => Object.keys(self);
1164
1145
 
1165
- // ../../node_modules/.pnpm/effect@4.0.0-beta.27/node_modules/effect/dist/Array.js
1146
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Array.js
1166
1147
  var Array2 = globalThis.Array;
1167
1148
  var fromIterable = (collection) => Array2.isArray(collection) ? collection : Array2.from(collection);
1168
1149
  var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
@@ -5545,6 +5526,7 @@ var classSelfMismatch = createDiagnostic({
5545
5526
  if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
5546
5527
  const result = yield* pipe(
5547
5528
  typeParser.extendsEffectService(node),
5529
+ orElse2(() => typeParser.extendsServiceMapService(node)),
5548
5530
  orElse2(() => typeParser.extendsContextTag(node)),
5549
5531
  orElse2(() => typeParser.extendsEffectTag(node)),
5550
5532
  orElse2(() => typeParser.extendsSchemaClass(node)),
@@ -5920,6 +5902,89 @@ var effectFnIife = createDiagnostic({
5920
5902
  })
5921
5903
  });
5922
5904
 
5905
+ // src/diagnostics/effectFnImplicitAny.ts
5906
+ var getParameterName = (typescript, name) => {
5907
+ if (typescript.isIdentifier(name)) {
5908
+ return typescript.idText(name);
5909
+ }
5910
+ return "parameter";
5911
+ };
5912
+ var hasOuterContextualFunctionType = (typescript, typeChecker, node) => {
5913
+ const contextualType = typeChecker.getContextualType(node);
5914
+ if (!contextualType) {
5915
+ return false;
5916
+ }
5917
+ return typeChecker.getSignaturesOfType(contextualType, typescript.SignatureKind.Call).length > 0;
5918
+ };
5919
+ var effectFnImplicitAny = createDiagnostic({
5920
+ name: "effectFnImplicitAny",
5921
+ code: 54,
5922
+ description: "Mirrors noImplicitAny for unannotated Effect.fn and Effect.fnUntraced callback parameters when no outer contextual function type exists",
5923
+ group: "correctness",
5924
+ severity: "error",
5925
+ fixable: false,
5926
+ supportedEffect: ["v3", "v4"],
5927
+ apply: fn("effectFnImplicitAny.apply")(function* (sourceFile, report) {
5928
+ const ts = yield* service(TypeScriptApi);
5929
+ const program = yield* service(TypeScriptProgram);
5930
+ const typeChecker = yield* service(TypeCheckerApi);
5931
+ const typeParser = yield* service(TypeParser);
5932
+ const noImplicitAny = program.getCompilerOptions().noImplicitAny ?? program.getCompilerOptions().strict ?? false;
5933
+ if (!noImplicitAny) {
5934
+ return;
5935
+ }
5936
+ const nodeToVisit = [sourceFile];
5937
+ const appendNodeToVisit = (node) => {
5938
+ nodeToVisit.push(node);
5939
+ return void 0;
5940
+ };
5941
+ while (nodeToVisit.length > 0) {
5942
+ const node = nodeToVisit.pop();
5943
+ ts.forEachChild(node, appendNodeToVisit);
5944
+ const parsed = yield* pipe(
5945
+ typeParser.effectFn(node),
5946
+ map4((result) => ({
5947
+ call: result.node,
5948
+ fn: result.regularFunction
5949
+ })),
5950
+ orElse2(
5951
+ () => pipe(
5952
+ typeParser.effectFnGen(node),
5953
+ map4((result) => ({
5954
+ call: result.node,
5955
+ fn: result.generatorFunction
5956
+ }))
5957
+ )
5958
+ ),
5959
+ orElse2(
5960
+ () => pipe(
5961
+ typeParser.effectFnUntracedGen(node),
5962
+ map4((result) => ({
5963
+ call: result.node,
5964
+ fn: result.generatorFunction
5965
+ }))
5966
+ )
5967
+ ),
5968
+ orUndefined
5969
+ );
5970
+ if (!parsed || hasOuterContextualFunctionType(ts, typeChecker, parsed.call)) {
5971
+ continue;
5972
+ }
5973
+ for (const parameter of parsed.fn.parameters) {
5974
+ if (parameter.type || parameter.initializer) {
5975
+ continue;
5976
+ }
5977
+ const parameterName = getParameterName(ts, parameter.name);
5978
+ report({
5979
+ location: parameter.name,
5980
+ messageText: `Parameter '${parameterName}' implicitly has an 'any' type in Effect.fn/Effect.fnUntraced. Add an explicit type annotation or provide a contextual function type.`,
5981
+ fixes: []
5982
+ });
5983
+ }
5984
+ }
5985
+ })
5986
+ });
5987
+
5923
5988
  // src/diagnostics/effectFnOpportunity.ts
5924
5989
  var effectFnOpportunity = createDiagnostic({
5925
5990
  name: "effectFnOpportunity",
@@ -7454,6 +7519,24 @@ var leakingRequirements = createDiagnostic({
7454
7519
  const typeCheckerUtils = yield* service(TypeCheckerUtils);
7455
7520
  const typeParser = yield* service(TypeParser);
7456
7521
  const tsUtils = yield* service(TypeScriptUtils);
7522
+ const isExpectedLeakingServiceSuppressed = (leakedServiceName, startNode) => {
7523
+ const sourceFile2 = tsUtils.getSourceFileOfNode(startNode);
7524
+ if (!sourceFile2) return false;
7525
+ return !!ts.findAncestor(startNode, (current) => {
7526
+ const ranges = ts.getLeadingCommentRanges(sourceFile2.text, current.pos) ?? [];
7527
+ const isSuppressed = ranges.some((range) => {
7528
+ const commentText = sourceFile2.text.slice(range.pos, range.end);
7529
+ return commentText.split("\n").filter((line) => line.includes("@effect-expect-leaking")).some((line) => {
7530
+ const markerIndex = line.indexOf("@effect-expect-leaking");
7531
+ return markerIndex !== -1 && line.slice(markerIndex + "@effect-expect-leaking".length).includes(leakedServiceName);
7532
+ });
7533
+ });
7534
+ if (isSuppressed) {
7535
+ return true;
7536
+ }
7537
+ return ts.isClassDeclaration(current) || ts.isVariableStatement(current) || ts.isExpressionStatement(current) || ts.isStatement(current) ? "quit" : false;
7538
+ });
7539
+ };
7457
7540
  const parseLeakedRequirements = cachedBy(
7458
7541
  fn("leakingServices.checkServiceLeaking")(
7459
7542
  function* (service2, atLocation) {
@@ -7535,8 +7618,12 @@ var leakingRequirements = createDiagnostic({
7535
7618
  (_, service2) => service2
7536
7619
  );
7537
7620
  function reportLeakingRequirements(node, requirements) {
7538
- if (requirements.length === 0) return;
7539
- const requirementsStr = requirements.map((_) => typeChecker.typeToString(_)).join(" | ");
7621
+ const filteredRequirements = requirements.filter(
7622
+ (requirement) => !isExpectedLeakingServiceSuppressed(typeChecker.typeToString(requirement), node)
7623
+ );
7624
+ if (filteredRequirements.length === 0) return;
7625
+ const requirementsStr = filteredRequirements.map((_) => typeChecker.typeToString(_)).join(" | ");
7626
+ const firstStr = typeChecker.typeToString(filteredRequirements[0]);
7540
7627
  report({
7541
7628
  location: node,
7542
7629
  messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
@@ -7545,7 +7632,7 @@ This leaks implementation details into the service's public type \u2014 callers
7545
7632
 
7546
7633
  Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
7547
7634
 
7548
- 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.
7635
+ 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.
7549
7636
 
7550
7637
  More info and examples at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
7551
7638
  fixes: []
@@ -11866,6 +11953,7 @@ var diagnostics = [
11866
11953
  catchUnfailableEffect,
11867
11954
  classSelfMismatch,
11868
11955
  duplicatePackage,
11956
+ effectFnImplicitAny,
11869
11957
  effectGenUsesAdapter,
11870
11958
  missingEffectContext,
11871
11959
  missingEffectError,