@effect/language-service 0.17.0 → 0.18.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@3.12.5/node_modules/effect/dist/esm/Function.js
27
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Function.js
28
28
  var isFunction = (input) => typeof input === "function";
29
29
  var dual = function(arity, body) {
30
30
  if (typeof arity === "function") {
@@ -118,11 +118,11 @@ function pipe(a, ab, bc, cd, de, ef, fg, gh, hi) {
118
118
  }
119
119
  }
120
120
 
121
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/internal/version.js
122
- var moduleVersion = "3.12.5";
121
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/internal/version.js
122
+ var moduleVersion = "3.16.3";
123
123
  var getCurrentVersion = () => moduleVersion;
124
124
 
125
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/GlobalValue.js
125
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/GlobalValue.js
126
126
  var globalStoreId = `effect/GlobalValue/globalStoreId/${/* @__PURE__ */ getCurrentVersion()}`;
127
127
  var globalStore;
128
128
  var globalValue = (id, compute) => {
@@ -136,16 +136,19 @@ var globalValue = (id, compute) => {
136
136
  return globalStore.get(id);
137
137
  };
138
138
 
139
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Predicate.js
139
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Predicate.js
140
+ var isString = (input) => typeof input === "string";
141
+ var isNumber = (input) => typeof input === "number";
142
+ var isBoolean = (input) => typeof input === "boolean";
140
143
  var isFunction2 = isFunction;
141
144
  var isRecordOrArray = (input) => typeof input === "object" && input !== null;
142
145
  var isObject = (input) => isRecordOrArray(input) || isFunction2(input);
143
146
  var hasProperty = /* @__PURE__ */ dual(2, (self, property) => isObject(self) && property in self);
144
147
 
145
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/internal/errors.js
148
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/internal/errors.js
146
149
  var getBugErrorMessage = (message) => `BUG: ${message} - please report an issue at https://github.com/Effect-TS/effect/issues`;
147
150
 
148
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Utils.js
151
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Utils.js
149
152
  var GenKindTypeId = /* @__PURE__ */ Symbol.for("effect/Gen/GenKind");
150
153
  var isGenKind = (u) => isObject(u) && GenKindTypeId in u;
151
154
  var GenKindImpl = class {
@@ -256,10 +259,25 @@ var structuralRegionState = /* @__PURE__ */ globalValue("effect/Utils/isStructur
256
259
  enabled: false,
257
260
  tester: void 0
258
261
  }));
262
+ var standard = {
263
+ effect_internal_function: (body) => {
264
+ return body();
265
+ }
266
+ };
267
+ var forced = {
268
+ effect_internal_function: (body) => {
269
+ try {
270
+ return body();
271
+ } finally {
272
+ }
273
+ }
274
+ };
275
+ var isNotOptimizedAway = /* @__PURE__ */ standard.effect_internal_function(() => new Error().stack)?.includes("effect_internal_function") === true;
276
+ var internalCall = isNotOptimizedAway ? standard.effect_internal_function : forced.effect_internal_function;
259
277
  var genConstructor = function* () {
260
278
  }.constructor;
261
279
 
262
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Hash.js
280
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Hash.js
263
281
  var randomHashCache = /* @__PURE__ */ globalValue(/* @__PURE__ */ Symbol.for("effect/Hash/randomHashCache"), () => /* @__PURE__ */ new WeakMap());
264
282
  var symbol = /* @__PURE__ */ Symbol.for("effect/Hash");
265
283
  var hash = (self) => {
@@ -285,6 +303,8 @@ var hash = (self) => {
285
303
  return string("null");
286
304
  } else if (self instanceof Date) {
287
305
  return hash(self.toISOString());
306
+ } else if (self instanceof URL) {
307
+ return hash(self.href);
288
308
  } else if (isHash(self)) {
289
309
  return self[symbol]();
290
310
  } else {
@@ -356,7 +376,7 @@ var cached = function() {
356
376
  return hash2;
357
377
  };
358
378
 
359
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Equal.js
379
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Equal.js
360
380
  var symbol2 = /* @__PURE__ */ Symbol.for("effect/Equal");
361
381
  function equals() {
362
382
  if (arguments.length === 1) {
@@ -382,6 +402,8 @@ function compareBoth(self, that) {
382
402
  }
383
403
  } else if (self instanceof Date && that instanceof Date) {
384
404
  return self.toISOString() === that.toISOString();
405
+ } else if (self instanceof URL && that instanceof URL) {
406
+ return self.href === that.href;
385
407
  }
386
408
  }
387
409
  if (structuralRegionState.enabled) {
@@ -407,7 +429,7 @@ function compareBoth(self, that) {
407
429
  }
408
430
  var isEqual = (u) => hasProperty(u, symbol2);
409
431
 
410
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Inspectable.js
432
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Inspectable.js
411
433
  var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
412
434
  var toJSON = (x) => {
413
435
  try {
@@ -416,7 +438,7 @@ var toJSON = (x) => {
416
438
  } else if (Array.isArray(x)) {
417
439
  return x.map(toJSON);
418
440
  }
419
- } catch (_) {
441
+ } catch {
420
442
  return {};
421
443
  }
422
444
  return redact(x);
@@ -459,7 +481,7 @@ var redact = (u) => {
459
481
  return u;
460
482
  };
461
483
 
462
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Pipeable.js
484
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Pipeable.js
463
485
  var pipeArguments = (self, args) => {
464
486
  switch (args.length) {
465
487
  case 0:
@@ -492,10 +514,10 @@ var pipeArguments = (self, args) => {
492
514
  }
493
515
  };
494
516
 
495
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/internal/opCodes/effect.js
517
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/internal/opCodes/effect.js
496
518
  var OP_COMMIT = "Commit";
497
519
 
498
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/internal/effectable.js
520
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/internal/effectable.js
499
521
  var EffectTypeId = /* @__PURE__ */ Symbol.for("effect/Effect");
500
522
  var StreamTypeId = /* @__PURE__ */ Symbol.for("effect/Stream");
501
523
  var SinkTypeId = /* @__PURE__ */ Symbol.for("effect/Sink");
@@ -582,7 +604,7 @@ var StructuralCommitPrototype = {
582
604
  ...StructuralPrototype
583
605
  };
584
606
 
585
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/internal/option.js
607
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/internal/option.js
586
608
  var TypeId = /* @__PURE__ */ Symbol.for("effect/Option");
587
609
  var CommonProto = {
588
610
  ...EffectPrototype,
@@ -640,7 +662,7 @@ var some = (value) => {
640
662
  return a;
641
663
  };
642
664
 
643
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/internal/either.js
665
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/internal/either.js
644
666
  var TypeId2 = /* @__PURE__ */ Symbol.for("effect/Either");
645
667
  var CommonProto2 = {
646
668
  ...EffectPrototype,
@@ -702,7 +724,7 @@ var right = (right3) => {
702
724
  return a;
703
725
  };
704
726
 
705
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Either.js
727
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Either.js
706
728
  var right2 = right;
707
729
  var left2 = left;
708
730
  var isLeft2 = isLeft;
@@ -710,16 +732,16 @@ var isRight2 = isRight;
710
732
  var map = /* @__PURE__ */ dual(2, (self, f) => isRight2(self) ? right2(f(self.right)) : left2(self.left));
711
733
  var getOrElse = /* @__PURE__ */ dual(2, (self, onLeft) => isLeft2(self) ? onLeft(self.left) : self.right);
712
734
 
713
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Order.js
735
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Order.js
714
736
  var make = (compare) => (self, that) => self === that ? 0 : compare(self, that);
715
737
 
716
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Option.js
738
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Option.js
717
739
  var none2 = () => none;
718
740
  var some2 = some;
719
741
  var isNone2 = isNone;
720
742
  var isSome2 = isSome;
721
743
 
722
- // node_modules/.pnpm/effect@3.12.5/node_modules/effect/dist/esm/Array.js
744
+ // node_modules/.pnpm/effect@3.16.3/node_modules/effect/dist/esm/Array.js
723
745
  var fromIterable = (collection) => Array.isArray(collection) ? collection : Array.from(collection);
724
746
  var isArray = Array.isArray;
725
747
  var isEmptyArray = (self) => self.length === 0;
@@ -891,6 +913,17 @@ var option = (fa) => make2((ctx) => {
891
913
  }
892
914
  });
893
915
 
916
+ // src/core/LanguageServicePluginOptions.ts
917
+ var LanguageServicePluginOptions = Tag("PluginOptions");
918
+ function parse(config) {
919
+ return {
920
+ diagnostics: isObject(config) && hasProperty(config, "diagnostics") && isBoolean(config.diagnostics) ? config.diagnostics : true,
921
+ quickinfo: isObject(config) && hasProperty(config, "quickinfo") && isBoolean(config.quickinfo) ? config.quickinfo : true,
922
+ completions: isObject(config) && hasProperty(config, "completions") && isBoolean(config.completions) ? config.completions : true,
923
+ allowedDuplicatedPackages: isObject(config) && hasProperty(config, "allowedDuplicatedPackages") && isArray(config.allowedDuplicatedPackages) && config.allowedDuplicatedPackages.every(isString) ? config.allowedDuplicatedPackages.map((_) => _.toLowerCase()) : []
924
+ };
925
+ }
926
+
894
927
  // src/core/TypeScriptApi.ts
895
928
  var TypeScriptApi = Tag("TypeScriptApi");
896
929
  var TypeScriptProgram = Tag("TypeScriptProgram");
@@ -903,26 +936,17 @@ var RefactorNotApplicableError = class {
903
936
  function createDiagnostic(definition) {
904
937
  return definition;
905
938
  }
906
- function parsePluginOptions(config) {
907
- return {
908
- diagnostics: config && "diagnostics" in config && typeof config.diagnostics === "boolean" ? config.diagnostics : true,
909
- quickinfo: config && "quickinfo" in config && typeof config.quickinfo === "boolean" ? config.quickinfo : true,
910
- completions: config && "completions" in config && typeof config.completions === "boolean" ? config.completions : true,
911
- multipleEffectCheck: config && "multipleEffectCheck" in config && typeof config.multipleEffectCheck === "boolean" ? config.multipleEffectCheck : true
912
- };
913
- }
914
- var PluginOptions = Tag("PluginOptions");
915
939
  var getSemanticDiagnosticsWithCodeFixes = fn(
916
940
  "LSP.getSemanticDiagnosticsWithCodeFixes"
917
941
  )(function* (rules, sourceFile) {
918
- const effectDiagnostics = [];
919
- const effectCodeFixes = [];
942
+ let effectDiagnostics = [];
943
+ let effectCodeFixes = [];
920
944
  const executor = yield* createDiagnosticExecutor(sourceFile);
921
945
  for (const rule of rules) {
922
946
  const result = yield* option(executor.execute(rule));
923
947
  if (isSome2(result)) {
924
- effectDiagnostics.push(
925
- ...pipe(
948
+ effectDiagnostics = effectDiagnostics.concat(
949
+ pipe(
926
950
  result.value,
927
951
  map2((_) => ({
928
952
  file: sourceFile,
@@ -935,8 +959,8 @@ var getSemanticDiagnosticsWithCodeFixes = fn(
935
959
  }))
936
960
  )
937
961
  );
938
- effectCodeFixes.push(
939
- ...pipe(
962
+ effectCodeFixes = effectCodeFixes.concat(
963
+ pipe(
940
964
  result.value,
941
965
  map2(
942
966
  (_) => map2(
@@ -959,6 +983,9 @@ var getSemanticDiagnosticsWithCodeFixes = fn(
959
983
  codeFixes: effectCodeFixes
960
984
  };
961
985
  });
986
+ function refactorNameToFullyQualifiedName(name) {
987
+ return `@effect/language-service/refactors/${name}`;
988
+ }
962
989
  var getApplicableRefactors = fn("LSP.getApplicableRefactors")(function* (refactors, sourceFile, positionOrRange) {
963
990
  const textRange = typeof positionOrRange === "number" ? { pos: positionOrRange, end: positionOrRange } : positionOrRange;
964
991
  const effectRefactors = [];
@@ -966,10 +993,10 @@ var getApplicableRefactors = fn("LSP.getApplicableRefactors")(function* (refacto
966
993
  const result = yield* option(refactor.apply(sourceFile, textRange));
967
994
  if (isSome2(result)) {
968
995
  effectRefactors.push({
969
- name: refactor.name,
996
+ name: refactorNameToFullyQualifiedName(refactor.name),
970
997
  description: refactor.description,
971
998
  actions: [{
972
- name: refactor.name,
999
+ name: refactorNameToFullyQualifiedName(refactor.name),
973
1000
  description: result.value.description,
974
1001
  kind: result.value.kind
975
1002
  }]
@@ -979,7 +1006,7 @@ var getApplicableRefactors = fn("LSP.getApplicableRefactors")(function* (refacto
979
1006
  return effectRefactors;
980
1007
  });
981
1008
  var getEditsForRefactor = fn("LSP.getEditsForRefactor")(function* (refactors, sourceFile, positionOrRange, refactorName) {
982
- const refactor = refactors.find((refactor2) => refactor2.name === refactorName);
1009
+ const refactor = refactors.find((refactor2) => refactorNameToFullyQualifiedName(refactor2.name) === refactorName);
983
1010
  if (!refactor) {
984
1011
  return yield* fail(new RefactorNotApplicableError());
985
1012
  }
@@ -987,11 +1014,11 @@ var getEditsForRefactor = fn("LSP.getEditsForRefactor")(function* (refactors, so
987
1014
  return yield* refactor.apply(sourceFile, textRange);
988
1015
  });
989
1016
  var getCompletionsAtPosition = fn("LSP.getCompletionsAtPosition")(function* (completions, sourceFile, position, options, formatCodeSettings) {
990
- const effectCompletions = [];
1017
+ let effectCompletions = [];
991
1018
  for (const completion of completions) {
992
1019
  const result = yield* completion.apply(sourceFile, position, options, formatCodeSettings);
993
- effectCompletions.push(
994
- ...result.map((_) => ({ sortText: "11", ..._ }))
1020
+ effectCompletions = effectCompletions.concat(
1021
+ result.map((_) => ({ sortText: "11", ..._ }))
995
1022
  );
996
1023
  }
997
1024
  return effectCompletions;
@@ -999,27 +1026,74 @@ var getCompletionsAtPosition = fn("LSP.getCompletionsAtPosition")(function* (com
999
1026
  var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1000
1027
  function* (sourceFile) {
1001
1028
  const ts = yield* service(TypeScriptApi);
1002
- const ruleOverrides = {};
1029
+ function findNodeWithLeadingCommentAtPosition(position) {
1030
+ const sourceText = sourceFile.text;
1031
+ let result;
1032
+ function find(node) {
1033
+ const leading = ts.getLeadingCommentRanges(sourceText, node.getFullStart());
1034
+ if (leading) {
1035
+ for (const r of leading) {
1036
+ if (r.pos <= position && position < r.end) {
1037
+ result = node;
1038
+ return;
1039
+ }
1040
+ }
1041
+ }
1042
+ if (node.getFullStart() <= position && position < node.getEnd()) {
1043
+ node.forEachChild(find);
1044
+ }
1045
+ }
1046
+ find(sourceFile);
1047
+ return result;
1048
+ }
1049
+ function findParentStatementForDisableNextLine(node) {
1050
+ let result;
1051
+ function find(node2) {
1052
+ if (ts.isStatement(node2)) {
1053
+ result = node2;
1054
+ return;
1055
+ }
1056
+ if (result) return;
1057
+ if (node2.parent) find(node2.parent);
1058
+ }
1059
+ find(node);
1060
+ return result || node;
1061
+ }
1062
+ const lineOverrides = {};
1063
+ const sectionOverrides = {};
1003
1064
  const skippedRules = [];
1004
- const regex = /@effect-diagnostics((?:\s[a-zA-Z0-9/]+:(?:off|warning|error|message|suggestion|skip-file))+)?/gm;
1065
+ const regex = /@effect-diagnostics(-next-line)?((?:\s[a-zA-Z0-9/]+:(?:off|warning|error|message|suggestion|skip-file))+)?/gm;
1005
1066
  let match;
1006
1067
  while ((match = regex.exec(sourceFile.text)) !== null) {
1007
- const rulesCaptureGroup = match[1];
1068
+ const nextLineCaptureGroup = match[1];
1069
+ const rulesCaptureGroup = match[2];
1008
1070
  if (rulesCaptureGroup) {
1009
1071
  const trimmedRuleString = rulesCaptureGroup.trim();
1010
1072
  if (trimmedRuleString) {
1011
1073
  const individualRules = trimmedRuleString.split(/\s+/);
1012
1074
  for (const rulePair of individualRules) {
1013
- const [ruleName, ruleLevel] = rulePair.toLowerCase().split(":");
1075
+ const [rawRuleName, ruleLevel] = rulePair.toLowerCase().split(":");
1076
+ const ruleName = rawRuleName.startsWith("effect/") ? rawRuleName.substring("effect/".length) : rawRuleName;
1014
1077
  if (ruleName && ruleLevel) {
1015
1078
  if (ruleLevel === "skip-file") skippedRules.push(ruleName);
1016
- ruleOverrides[ruleName] = ruleOverrides[ruleName] || [];
1017
- const newLength = ruleOverrides[ruleName].push({
1018
- start: match.index,
1019
- end: Number.MAX_SAFE_INTEGER,
1020
- level: ruleLevel
1021
- });
1022
- if (newLength > 1) ruleOverrides[ruleName][newLength - 2].end = match.index;
1079
+ const isOverrideNextLine = nextLineCaptureGroup && nextLineCaptureGroup.trim().toLowerCase() === "-next-line";
1080
+ if (isOverrideNextLine) {
1081
+ const node = findNodeWithLeadingCommentAtPosition(match.index);
1082
+ if (node) {
1083
+ lineOverrides[ruleName] = lineOverrides[ruleName] || [];
1084
+ lineOverrides[ruleName].unshift({
1085
+ pos: node.getFullStart(),
1086
+ end: node.end,
1087
+ level: ruleLevel
1088
+ });
1089
+ }
1090
+ } else {
1091
+ sectionOverrides[ruleName] = sectionOverrides[ruleName] || [];
1092
+ sectionOverrides[ruleName].unshift({
1093
+ pos: match.index,
1094
+ level: ruleLevel
1095
+ });
1096
+ }
1023
1097
  }
1024
1098
  }
1025
1099
  }
@@ -1035,22 +1109,46 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1035
1109
  const ruleNameLowered = rule.name.toLowerCase();
1036
1110
  if (skippedRules.indexOf(ruleNameLowered) > -1) return [];
1037
1111
  let modifiedDiagnostics = yield* rule.apply(sourceFile);
1038
- for (const override of ruleOverrides[ruleNameLowered] || []) {
1039
- if (override.level === "off") {
1040
- modifiedDiagnostics = modifiedDiagnostics.filter(
1041
- (_) => !(_.node.getStart(sourceFile) >= override.start && _.node.getEnd() <= override.end)
1112
+ for (const emitted of modifiedDiagnostics.slice(0)) {
1113
+ let newLevel = void 0;
1114
+ if (!(ruleNameLowered in sectionOverrides || ruleNameLowered in lineOverrides)) continue;
1115
+ const lineOverride = (lineOverrides[ruleNameLowered] || []).find(
1116
+ (_) => _.pos < emitted.node.getStart(sourceFile) && _.end >= emitted.node.getEnd()
1117
+ );
1118
+ if (lineOverride) {
1119
+ newLevel = lineOverride.level;
1120
+ } else {
1121
+ const sectionOverride = (sectionOverrides[ruleNameLowered] || []).find(
1122
+ (_) => _.pos < emitted.node.getStart(sourceFile)
1042
1123
  );
1124
+ if (sectionOverride) newLevel = sectionOverride.level;
1125
+ }
1126
+ if (newLevel === "off") {
1127
+ modifiedDiagnostics = modifiedDiagnostics.filter((_) => _ !== emitted);
1043
1128
  } else {
1044
- for (const message of modifiedDiagnostics.filter(
1045
- (_) => _.node.getStart(sourceFile) >= override.start && _.node.getEnd() <= override.end
1046
- )) {
1047
- message.category = override.level in levelToDiagnosticCategory ? levelToDiagnosticCategory[override.level] : message.category;
1048
- }
1129
+ emitted.category = newLevel && newLevel in levelToDiagnosticCategory ? levelToDiagnosticCategory[newLevel] : emitted.category;
1049
1130
  }
1050
1131
  }
1132
+ const fixByDisableNextLine = (_) => ({
1133
+ fixName: rule.name + "_skipNextLine",
1134
+ description: "Disable " + rule.name + " for this line",
1135
+ apply: flatMap2(
1136
+ service(ChangeTracker),
1137
+ (changeTracker) => sync(() => {
1138
+ const disableAtNode = findParentStatementForDisableNextLine(_.node);
1139
+ const { line } = ts.getLineAndCharacterOfPosition(sourceFile, disableAtNode.getStart());
1140
+ changeTracker.insertCommentBeforeLine(
1141
+ sourceFile,
1142
+ line,
1143
+ disableAtNode.getStart(),
1144
+ ` @effect-diagnostics-next-line ${rule.name}:off`
1145
+ );
1146
+ })
1147
+ )
1148
+ });
1051
1149
  const fixByDisableEntireFile = {
1052
1150
  fixName: rule.name + "_skipFile",
1053
- description: "Disable " + rule.name + " for this file",
1151
+ description: "Disable " + rule.name + " for this entire file",
1054
1152
  apply: flatMap2(
1055
1153
  service(ChangeTracker),
1056
1154
  (changeTracker) => sync(
@@ -1065,7 +1163,7 @@ var createDiagnosticExecutor = fn("LSP.createCommentDirectivesProcessor")(
1065
1163
  };
1066
1164
  const rulesWithDisableFix = modifiedDiagnostics.map((diagnostic) => ({
1067
1165
  ...diagnostic,
1068
- fixes: diagnostic.fixes.concat([fixByDisableEntireFile])
1166
+ fixes: diagnostic.fixes.concat([fixByDisableNextLine(diagnostic), fixByDisableEntireFile])
1069
1167
  }));
1070
1168
  return rulesWithDisableFix;
1071
1169
  });
@@ -1097,12 +1195,12 @@ var getMissingTypeEntriesInTargetType = fn(
1097
1195
  function* (realType, expectedType) {
1098
1196
  const typeChecker = yield* service(TypeCheckerApi);
1099
1197
  const result = [];
1100
- const toTest = [realType];
1198
+ let toTest = [realType];
1101
1199
  while (toTest.length > 0) {
1102
1200
  const type = toTest.pop();
1103
1201
  if (!type) return result;
1104
1202
  if (type.isUnion()) {
1105
- toTest.push(...type.types);
1203
+ toTest = toTest.concat(type.types);
1106
1204
  } else {
1107
1205
  const assignable = typeChecker.isTypeAssignableTo(type, expectedType);
1108
1206
  if (!assignable) {
@@ -1279,6 +1377,76 @@ var expectedAndRealType = fn("TypeCheckerApi.expectedAndRealType")(function* (so
1279
1377
  return result;
1280
1378
  });
1281
1379
 
1380
+ // src/diagnostics/duplicatePackage.ts
1381
+ var checkedPackagesCache = /* @__PURE__ */ new Map();
1382
+ var programResolvedCacheSize = /* @__PURE__ */ new Map();
1383
+ function parsePackageContentNameAndVersion(v) {
1384
+ if (!isObject(v)) return;
1385
+ if (!hasProperty(v, "packageJsonScope")) return;
1386
+ if (!v.packageJsonScope) return;
1387
+ const packageJsonScope = v.packageJsonScope;
1388
+ if (!hasProperty(packageJsonScope, "contents")) return;
1389
+ if (!hasProperty(packageJsonScope.contents, "packageJsonContent")) return;
1390
+ const packageJsonContent = packageJsonScope.contents.packageJsonContent;
1391
+ if (!hasProperty(packageJsonContent, "name")) return;
1392
+ if (!hasProperty(packageJsonContent, "version")) return;
1393
+ const { name, version } = packageJsonContent;
1394
+ if (!isString(name)) return;
1395
+ if (!isString(version)) return;
1396
+ const hasEffectInPeerDependencies = hasProperty(packageJsonContent, "peerDependencies") && isObject(packageJsonContent.peerDependencies) && hasProperty(packageJsonContent.peerDependencies, "effect");
1397
+ return {
1398
+ name: name.toLowerCase(),
1399
+ version: version.toLowerCase(),
1400
+ hasEffectInPeerDependencies,
1401
+ contents: packageJsonContent
1402
+ };
1403
+ }
1404
+ var duplicatePackage = createDiagnostic({
1405
+ name: "duplicatePackage",
1406
+ code: 6,
1407
+ apply: fn("duplicatePackage.apply")(function* (sourceFile) {
1408
+ const ts = yield* service(TypeScriptApi);
1409
+ const program = yield* service(TypeScriptProgram);
1410
+ const options = yield* service(LanguageServicePluginOptions);
1411
+ const effectDiagnostics = [];
1412
+ if (sourceFile.statements.length < 1) return [];
1413
+ let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
1414
+ const newResolvedModuleSize = hasProperty(program, "resolvedModules") && hasProperty(program.resolvedModules, "size") && isNumber(program.resolvedModules.size) ? program.resolvedModules.size : 0;
1415
+ const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || -1;
1416
+ if (newResolvedModuleSize !== oldResolvedSize) {
1417
+ const seenPackages = /* @__PURE__ */ new Set();
1418
+ resolvedPackages = {};
1419
+ program.getSourceFiles().map((_) => {
1420
+ const packageInfo = parsePackageContentNameAndVersion(_);
1421
+ if (!packageInfo) return;
1422
+ const packageNameAndVersion = packageInfo.name + "@" + packageInfo.version;
1423
+ if (seenPackages.has(packageNameAndVersion)) return;
1424
+ seenPackages.add(packageNameAndVersion);
1425
+ if (!(packageInfo.name === "effect" || packageInfo.hasEffectInPeerDependencies)) return;
1426
+ if (options.allowedDuplicatedPackages.indexOf(packageInfo.name) > -1) return;
1427
+ resolvedPackages[packageInfo.name] = resolvedPackages[packageInfo.name] || {};
1428
+ resolvedPackages[packageInfo.name][packageInfo.version] = packageInfo.contents;
1429
+ });
1430
+ checkedPackagesCache.set(sourceFile.fileName, resolvedPackages);
1431
+ programResolvedCacheSize.set(sourceFile.fileName, newResolvedModuleSize);
1432
+ }
1433
+ for (const packageName of Object.keys(resolvedPackages)) {
1434
+ if (Object.keys(resolvedPackages[packageName]).length > 1) {
1435
+ const versions = Object.keys(resolvedPackages[packageName]);
1436
+ effectDiagnostics.push({
1437
+ node: sourceFile.statements[0],
1438
+ category: ts.DiagnosticCategory.Warning,
1439
+ messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
1440
+ Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
1441
+ If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.`,
1442
+ fixes: []
1443
+ });
1444
+ }
1445
+ }
1446
+ return effectDiagnostics;
1447
+ })
1448
+ });
1449
+
1282
1450
  // src/utils/TypeParser.ts
1283
1451
  var TypeParserIssue = class {
1284
1452
  constructor(type, node, message) {
@@ -1383,9 +1551,10 @@ var fiberType = fn("TypeParser.fiberType")(function* (type, atLocation) {
1383
1551
  var effectSubtype = fn("TypeParser.effectSubtype")(function* (type, atLocation) {
1384
1552
  const typeChecker = yield* service(TypeCheckerApi);
1385
1553
  const tagSymbol = typeChecker.getPropertyOfType(type, "_tag");
1386
- if (!tagSymbol) {
1554
+ const getSymbol = typeChecker.getPropertyOfType(type, "get");
1555
+ if (!(tagSymbol || getSymbol)) {
1387
1556
  return yield* typeParserIssue(
1388
- "Type is not a subtype of effect because it does not have '_tag' property",
1557
+ "Type is not a subtype of effect because it does not have '_tag' or 'get' property",
1389
1558
  type,
1390
1559
  atLocation
1391
1560
  );
@@ -1580,7 +1749,7 @@ var effectSchemaType = fn("TypeParser.effectSchemaType")(function* (type, atLoca
1580
1749
 
1581
1750
  // src/diagnostics/floatingEffect.ts
1582
1751
  var floatingEffect = createDiagnostic({
1583
- name: "effect/floatingEffect",
1752
+ name: "floatingEffect",
1584
1753
  code: 3,
1585
1754
  apply: fn("floatingEffect.apply")(function* (sourceFile) {
1586
1755
  const ts = yield* service(TypeScriptApi);
@@ -1589,7 +1758,7 @@ var floatingEffect = createDiagnostic({
1589
1758
  if (!ts.isExpressionStatement(node)) return false;
1590
1759
  if (!(ts.isBlock(node.parent) || ts.isSourceFile(node.parent))) return false;
1591
1760
  const expression = node.expression;
1592
- if (ts.isBinaryExpression(expression) && expression.operatorToken && expression.operatorToken.kind === ts.SyntaxKind.EqualsToken) return false;
1761
+ if (ts.isBinaryExpression(expression) && expression.operatorToken && (expression.operatorToken.kind === ts.SyntaxKind.EqualsToken || expression.operatorToken.kind === ts.SyntaxKind.QuestionQuestionEqualsToken || expression.operatorToken.kind === ts.SyntaxKind.AmpersandAmpersandEqualsToken || expression.operatorToken.kind === ts.SyntaxKind.BarBarEqualsToken)) return false;
1593
1762
  return true;
1594
1763
  }
1595
1764
  const effectDiagnostics = [];
@@ -1627,7 +1796,7 @@ var floatingEffect = createDiagnostic({
1627
1796
 
1628
1797
  // src/diagnostics/missingEffectContext.ts
1629
1798
  var missingEffectContext = createDiagnostic({
1630
- name: "effect/missingEffectContext",
1799
+ name: "missingEffectContext",
1631
1800
  code: 1,
1632
1801
  apply: fn("missingEffectContext.apply")(function* (sourceFile) {
1633
1802
  const ts = yield* service(TypeScriptApi);
@@ -1679,7 +1848,7 @@ var missingEffectContext = createDiagnostic({
1679
1848
 
1680
1849
  // src/diagnostics/missingEffectError.ts
1681
1850
  var missingEffectError = createDiagnostic({
1682
- name: "effect/missingEffectError",
1851
+ name: "missingEffectError",
1683
1852
  code: 1,
1684
1853
  apply: fn("missingEffectError.apply")(function* (sourceFile) {
1685
1854
  const ts = yield* service(TypeScriptApi);
@@ -1731,7 +1900,7 @@ var missingEffectError = createDiagnostic({
1731
1900
 
1732
1901
  // src/diagnostics/missingStarInYieldEffectGen.ts
1733
1902
  var missingStarInYieldEffectGen = createDiagnostic({
1734
- name: "effect/missingStarInYieldEffectGen",
1903
+ name: "missingStarInYieldEffectGen",
1735
1904
  code: 4,
1736
1905
  apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile) {
1737
1906
  const ts = yield* service(TypeScriptApi);
@@ -1750,7 +1919,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
1750
1919
  if (ts.isYieldExpression(node) && node.expression && node.asteriskToken === void 0) {
1751
1920
  const functionStarNode = ts.findAncestor(
1752
1921
  node,
1753
- (_) => (ts.isFunctionExpression(_) || ts.isMethodDeclaration(_)) && _.asteriskToken !== void 0
1922
+ (_) => ts.isFunctionExpression(_) || ts.isFunctionDeclaration(_) || ts.isMethodDeclaration(_)
1754
1923
  );
1755
1924
  if (functionStarNode && functionStarNode.parent) {
1756
1925
  const effectGenNode = functionStarNode.parent;
@@ -1804,51 +1973,9 @@ var missingStarInYieldEffectGen = createDiagnostic({
1804
1973
  })
1805
1974
  });
1806
1975
 
1807
- // src/diagnostics/multipleEffectVersions.ts
1808
- var effectVersionsCache = /* @__PURE__ */ new Map();
1809
- var programResolvedCacheSize = /* @__PURE__ */ new Map();
1810
- var multipleEffectVersions = createDiagnostic({
1811
- name: "effect/multipleEffectVersions",
1812
- code: 6,
1813
- apply: fn("multipleEffectVersions.apply")(function* (sourceFile) {
1814
- const ts = yield* service(TypeScriptApi);
1815
- const program = yield* service(TypeScriptProgram);
1816
- const options = yield* service(PluginOptions);
1817
- const effectDiagnostics = [];
1818
- if (!options.multipleEffectCheck) return [];
1819
- if (sourceFile.statements.length < 1) return [];
1820
- const effectVersions = effectVersionsCache.get(sourceFile.fileName) || {};
1821
- const newResolvedModuleSize = "resolvedModules" in program && typeof program.resolvedModules === "object" && "size" in program.resolvedModules ? program.resolvedModules.size : 0;
1822
- const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || 0;
1823
- if (newResolvedModuleSize !== oldResolvedSize) {
1824
- if ("forEachResolvedModule" in program && typeof program.forEachResolvedModule === "function") {
1825
- program.forEachResolvedModule((_) => {
1826
- if (_ && _.resolvedModule && _.resolvedModule.packageId && _.resolvedModule.packageId.name === "effect" && !(_.resolvedModule.packageId.version in effectVersions)) {
1827
- effectVersions[_.resolvedModule.packageId.version] = {
1828
- resolvedFileName: _.resolvedModule.resolvedFileName
1829
- };
1830
- }
1831
- });
1832
- }
1833
- effectVersionsCache.set(sourceFile.fileName, effectVersions);
1834
- programResolvedCacheSize.set(sourceFile.fileName, newResolvedModuleSize);
1835
- }
1836
- if (Object.keys(effectVersions).length > 1) {
1837
- const versions = Object.keys(effectVersions).map((version) => `version ${version}`);
1838
- effectDiagnostics.push({
1839
- node: sourceFile.statements[0],
1840
- category: ts.DiagnosticCategory.Warning,
1841
- messageText: `Seems like in this project there are multiple effect versions loaded (${versions.join(", ")}). This may cause unexpected type errors and runtime behaviours. If you are ok with that, you can disable this warning by adding "multipleEffectCheck": false to the Effect LSP options inside your tsconfig.json`,
1842
- fixes: []
1843
- });
1844
- }
1845
- return effectDiagnostics;
1846
- })
1847
- });
1848
-
1849
1976
  // src/diagnostics/unnecessaryEffectGen.ts
1850
1977
  var unnecessaryEffectGen = createDiagnostic({
1851
- name: "effect/unnecessaryEffectGen",
1978
+ name: "unnecessaryEffectGen",
1852
1979
  code: 5,
1853
1980
  apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile) {
1854
1981
  const ts = yield* service(TypeScriptApi);
@@ -1895,7 +2022,7 @@ var unnecessaryEffectGen = createDiagnostic({
1895
2022
 
1896
2023
  // src/diagnostics.ts
1897
2024
  var diagnostics = [
1898
- multipleEffectVersions,
2025
+ duplicatePackage,
1899
2026
  missingEffectContext,
1900
2027
  missingEffectError,
1901
2028
  floatingEffect,
@@ -1916,7 +2043,10 @@ function transform_default(program, pluginConfig, { addDiagnostic, ts: tsInstanc
1916
2043
  TypeCheckerApiCache,
1917
2044
  makeTypeCheckerApiCache()
1918
2045
  ),
1919
- provideService(PluginOptions, parsePluginOptions(pluginConfig)),
2046
+ provideService(
2047
+ LanguageServicePluginOptions,
2048
+ parse(pluginConfig)
2049
+ ),
1920
2050
  run,
1921
2051
  map((_2) => _2.diagnostics),
1922
2052
  map(