@effect/language-service 0.20.0 → 0.21.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
@@ -3,9 +3,9 @@ var __defProp = Object.defineProperty;
3
3
  var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
4
  var __getOwnPropNames = Object.getOwnPropertyNames;
5
5
  var __hasOwnProp = Object.prototype.hasOwnProperty;
6
- var __export = (target, all) => {
7
- for (var name in all)
8
- __defProp(target, name, { get: all[name], enumerable: true });
6
+ var __export = (target, all2) => {
7
+ for (var name in all2)
8
+ __defProp(target, name, { get: all2[name], enumerable: true });
9
9
  };
10
10
  var __copyProps = (to, from, except, desc) => {
11
11
  if (from && typeof from === "object" || typeof from === "function") {
@@ -428,6 +428,7 @@ function compareBoth(self, that) {
428
428
  return structuralRegionState.enabled && structuralRegionState.tester ? structuralRegionState.tester(self, that) : false;
429
429
  }
430
430
  var isEqual = (u) => hasProperty(u, symbol2);
431
+ var equivalence = () => equals;
431
432
 
432
433
  // node_modules/.pnpm/effect@3.16.5/node_modules/effect/dist/esm/Inspectable.js
433
434
  var NodeInspectSymbol = /* @__PURE__ */ Symbol.for("nodejs.util.inspect.custom");
@@ -759,6 +760,20 @@ var sort = /* @__PURE__ */ dual(2, (self, O) => {
759
760
  out.sort(O);
760
761
  return out;
761
762
  });
763
+ var containsWith = (isEquivalent) => dual(2, (self, a) => {
764
+ for (const i of self) {
765
+ if (isEquivalent(a, i)) {
766
+ return true;
767
+ }
768
+ }
769
+ return false;
770
+ });
771
+ var _equivalence = /* @__PURE__ */ equivalence();
772
+ var intersectionWith = (isEquivalent) => {
773
+ const has = containsWith(isEquivalent);
774
+ return dual(2, (self, that) => fromIterable(self).filter((a) => has(that, a)));
775
+ };
776
+ var intersection = /* @__PURE__ */ intersectionWith(_equivalence);
762
777
  var empty = () => [];
763
778
  var map2 = /* @__PURE__ */ dual(2, (self, f) => self.map(f));
764
779
  var flatMap = /* @__PURE__ */ dual(2, (self, f) => {
@@ -837,7 +852,8 @@ function make2(run2) {
837
852
  return result;
838
853
  }
839
854
  var unsafeRun = (fa) => {
840
- const result = fa.run(contextEmpty);
855
+ const program = provideService(internalNanoCache, {})(fa);
856
+ const result = program.run(contextEmpty);
841
857
  switch (result._tag) {
842
858
  case "Left":
843
859
  return left2(result.value);
@@ -873,14 +889,14 @@ var orElse2 = (f) => (fa) => make2((ctx) => {
873
889
  return result;
874
890
  });
875
891
  var service = (tag) => make2(
876
- (ctx) => tag.key in ctx.value ? makeInternalSuccess(ctx.value[tag.key]) : makeInternalDefect(`Cannot find service ${tag.key}`)
892
+ (ctx) => tag.key in ctx.value ? ctx.value[tag.key] : makeInternalDefect(`Cannot find service ${tag.key}`)
877
893
  );
878
894
  var provideService = (tag, value) => (fa) => make2((ctx) => {
879
895
  return fa.run({
880
896
  ...ctx,
881
897
  value: {
882
898
  ...ctx.value,
883
- [tag.key]: value
899
+ [tag.key]: makeInternalSuccess(value)
884
900
  }
885
901
  });
886
902
  });
@@ -921,6 +937,41 @@ var option = (fa) => make2((ctx) => {
921
937
  return result;
922
938
  }
923
939
  });
940
+ var successUndefined = makeInternalSuccess(void 0);
941
+ var void_ = make2(() => successUndefined);
942
+ var ignore = (fa) => make2((ctx) => {
943
+ fa.run(ctx);
944
+ return successUndefined;
945
+ });
946
+ var all = (...args) => make2((ctx) => {
947
+ const results = [];
948
+ for (const arg of args) {
949
+ const result = arg.run(ctx);
950
+ if (result._tag !== "Right") return result;
951
+ results.push(result.value);
952
+ }
953
+ return makeInternalSuccess(results);
954
+ });
955
+ var internalNanoCache = Tag(
956
+ "@effect/language-service/internalNanoCache"
957
+ );
958
+ function cachedBy(fa, key, lookupKey) {
959
+ return (...args) => make2((ctx) => {
960
+ const cacheObj = ctx.value[internalNanoCache.key];
961
+ let cache = cacheObj[key];
962
+ if (!cache) {
963
+ cache = /* @__PURE__ */ new Map();
964
+ cacheObj[key] = cache;
965
+ }
966
+ const lookup = lookupKey(...args);
967
+ if (cache.has(lookup)) {
968
+ return cache.get(lookup);
969
+ }
970
+ const result = fa(...args).run(ctx);
971
+ cache.set(lookup, result);
972
+ return result;
973
+ });
974
+ }
924
975
 
925
976
  // src/core/LanguageServicePluginOptions.ts
926
977
  var LanguageServicePluginOptions = Tag("PluginOptions");
@@ -929,6 +980,7 @@ function parse(config) {
929
980
  diagnostics: isObject(config) && hasProperty(config, "diagnostics") && isBoolean(config.diagnostics) ? config.diagnostics : true,
930
981
  quickinfo: isObject(config) && hasProperty(config, "quickinfo") && isBoolean(config.quickinfo) ? config.quickinfo : true,
931
982
  completions: isObject(config) && hasProperty(config, "completions") && isBoolean(config.completions) ? config.completions : true,
983
+ goto: isObject(config) && hasProperty(config, "goto") && isBoolean(config.goto) ? config.goto : true,
932
984
  allowedDuplicatedPackages: isObject(config) && hasProperty(config, "allowedDuplicatedPackages") && isArray(config.allowedDuplicatedPackages) && config.allowedDuplicatedPackages.every(isString) ? config.allowedDuplicatedPackages.map((_) => _.toLowerCase()) : []
933
985
  };
934
986
  }
@@ -1452,55 +1504,6 @@ var appendToUniqueTypesMap = fn(
1452
1504
  }
1453
1505
  );
1454
1506
 
1455
- // src/diagnostics/duplicatePackage.ts
1456
- var checkedPackagesCache = /* @__PURE__ */ new Map();
1457
- var programResolvedCacheSize = /* @__PURE__ */ new Map();
1458
- var duplicatePackage = createDiagnostic({
1459
- name: "duplicatePackage",
1460
- code: 6,
1461
- apply: fn("duplicatePackage.apply")(function* (sourceFile) {
1462
- const ts = yield* service(TypeScriptApi);
1463
- const program = yield* service(TypeScriptProgram);
1464
- const options = yield* service(LanguageServicePluginOptions);
1465
- const effectDiagnostics = [];
1466
- if (sourceFile.statements.length < 1) return [];
1467
- let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
1468
- const newResolvedModuleSize = hasProperty(program, "resolvedModules") && hasProperty(program.resolvedModules, "size") && isNumber(program.resolvedModules.size) ? program.resolvedModules.size : 0;
1469
- const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || -1;
1470
- if (newResolvedModuleSize !== oldResolvedSize) {
1471
- const seenPackages = /* @__PURE__ */ new Set();
1472
- resolvedPackages = {};
1473
- program.getSourceFiles().map((_) => {
1474
- const packageInfo = parsePackageContentNameAndVersionFromScope(_);
1475
- if (!packageInfo) return;
1476
- const packageNameAndVersion = packageInfo.name + "@" + packageInfo.version;
1477
- if (seenPackages.has(packageNameAndVersion)) return;
1478
- seenPackages.add(packageNameAndVersion);
1479
- if (!(packageInfo.name === "effect" || packageInfo.hasEffectInPeerDependencies)) return;
1480
- if (options.allowedDuplicatedPackages.indexOf(packageInfo.name) > -1) return;
1481
- resolvedPackages[packageInfo.name] = resolvedPackages[packageInfo.name] || {};
1482
- resolvedPackages[packageInfo.name][packageInfo.version] = packageInfo.contents;
1483
- });
1484
- checkedPackagesCache.set(sourceFile.fileName, resolvedPackages);
1485
- programResolvedCacheSize.set(sourceFile.fileName, newResolvedModuleSize);
1486
- }
1487
- for (const packageName of Object.keys(resolvedPackages)) {
1488
- if (Object.keys(resolvedPackages[packageName]).length > 1) {
1489
- const versions = Object.keys(resolvedPackages[packageName]);
1490
- effectDiagnostics.push({
1491
- node: sourceFile.statements[0],
1492
- category: ts.DiagnosticCategory.Warning,
1493
- messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
1494
- Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
1495
- If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.`,
1496
- fixes: []
1497
- });
1498
- }
1499
- }
1500
- return effectDiagnostics;
1501
- })
1502
- });
1503
-
1504
1507
  // src/core/AST.ts
1505
1508
  function collectSelfAndAncestorNodesInRange(node, textRange) {
1506
1509
  return sync(() => {
@@ -1856,400 +1859,508 @@ var parsePipeCall = fn("AST.parsePipeCall")(
1856
1859
  }
1857
1860
  );
1858
1861
 
1859
- // src/utils/TypeParser.ts
1860
- var TypeParserIssue = class {
1861
- constructor(type, node, message) {
1862
- this.type = type;
1863
- this.node = node;
1864
- this.message = message;
1865
- }
1862
+ // src/core/TypeParser.ts
1863
+ var TypeParser = Tag("@effect/language-service/TypeParser");
1864
+ var TypeParserIssue = class _TypeParserIssue {
1866
1865
  _tag = "@effect/language-service/TypeParserIssue";
1866
+ static issue = fail(new _TypeParserIssue());
1867
1867
  };
1868
- function typeParserIssue(message, type, node) {
1869
- return fail(new TypeParserIssue(type, node, message));
1870
- }
1871
- function covariantTypeArgument(type) {
1872
- const signatures = type.getCallSignatures();
1873
- if (signatures.length !== 1) {
1874
- return typeParserIssue("Covariant type has no call signature", type);
1875
- }
1876
- return succeed(signatures[0].getReturnType());
1877
- }
1878
- function contravariantTypeArgument(type) {
1879
- const signatures = type.getCallSignatures();
1880
- if (signatures.length !== 1) {
1881
- return typeParserIssue("Contravariant type has no call signature", type);
1882
- }
1883
- return succeed(signatures[0].getTypeParameterAtPosition(0));
1884
- }
1885
- function invariantTypeArgument(type) {
1886
- const signatures = type.getCallSignatures();
1887
- if (signatures.length !== 1) {
1888
- return typeParserIssue("Invariant type has no call signature", type);
1868
+ function make3(ts, typeChecker) {
1869
+ function typeParserIssue(_message, _type, _node) {
1870
+ return TypeParserIssue.issue;
1871
+ }
1872
+ function covariantTypeArgument(type) {
1873
+ const signatures = type.getCallSignatures();
1874
+ if (signatures.length !== 1) {
1875
+ return typeParserIssue("Covariant type has no call signature", type);
1876
+ }
1877
+ return succeed(signatures[0].getReturnType());
1889
1878
  }
1890
- return succeed(signatures[0].getReturnType());
1891
- }
1892
- var pipeableType = fn("TypeParser.pipeableType")(function* (type, atLocation) {
1893
- const typeChecker = yield* service(TypeCheckerApi);
1894
- const pipeSymbol = typeChecker.getPropertyOfType(type, "pipe");
1895
- if (!pipeSymbol) {
1896
- return yield* typeParserIssue("Type has no 'pipe' property", type, atLocation);
1879
+ function contravariantTypeArgument(type) {
1880
+ const signatures = type.getCallSignatures();
1881
+ if (signatures.length !== 1) {
1882
+ return typeParserIssue("Contravariant type has no call signature", type);
1883
+ }
1884
+ return succeed(signatures[0].getTypeParameterAtPosition(0));
1897
1885
  }
1898
- const pipeType = typeChecker.getTypeOfSymbolAtLocation(pipeSymbol, atLocation);
1899
- const signatures = pipeType.getCallSignatures();
1900
- if (signatures.length === 0) {
1901
- return yield* typeParserIssue("'pipe' property is not callable", type, atLocation);
1886
+ function invariantTypeArgument(type) {
1887
+ const signatures = type.getCallSignatures();
1888
+ if (signatures.length !== 1) {
1889
+ return typeParserIssue("Invariant type has no call signature", type);
1890
+ }
1891
+ return succeed(signatures[0].getReturnType());
1902
1892
  }
1903
- return type;
1904
- });
1905
- var varianceStructCovariantType = fn("TypeParser.varianceStructCovariantType")(
1906
- function* (type, atLocation, propertyName) {
1907
- const typeChecker = yield* service(TypeCheckerApi);
1893
+ const pipeableType = cachedBy(
1894
+ fn("TypeParser.pipeableType")(function* (type, atLocation) {
1895
+ const pipeSymbol = typeChecker.getPropertyOfType(type, "pipe");
1896
+ if (!pipeSymbol) {
1897
+ return yield* typeParserIssue("Type has no 'pipe' property", type, atLocation);
1898
+ }
1899
+ const pipeType = typeChecker.getTypeOfSymbolAtLocation(pipeSymbol, atLocation);
1900
+ const signatures = pipeType.getCallSignatures();
1901
+ if (signatures.length === 0) {
1902
+ return yield* typeParserIssue("'pipe' property is not callable", type, atLocation);
1903
+ }
1904
+ return type;
1905
+ }),
1906
+ "TypeParser.pipeableType",
1907
+ (type) => type
1908
+ );
1909
+ const varianceStructCovariantType = (type, atLocation, propertyName) => {
1908
1910
  const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
1909
1911
  if (!propertySymbol) {
1910
- return yield* typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
1912
+ return typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
1911
1913
  }
1912
1914
  const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
1913
- return yield* covariantTypeArgument(propertyType);
1914
- }
1915
- );
1916
- var varianceStructContravariantType = fn(
1917
- "TypeParser.varianceStructContravariantType"
1918
- )(
1919
- function* (type, atLocation, propertyName) {
1920
- const typeChecker = yield* service(TypeCheckerApi);
1915
+ return covariantTypeArgument(propertyType);
1916
+ };
1917
+ const varianceStructContravariantType = (type, atLocation, propertyName) => {
1921
1918
  const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
1922
1919
  if (!propertySymbol) {
1923
- return yield* typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
1920
+ return typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
1924
1921
  }
1925
1922
  const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
1926
- return yield* contravariantTypeArgument(propertyType);
1927
- }
1928
- );
1929
- var varianceStructInvariantType = fn("TypeParser.varianceStructInvariantType")(
1930
- function* (type, atLocation, propertyName) {
1931
- const typeChecker = yield* service(TypeCheckerApi);
1923
+ return contravariantTypeArgument(propertyType);
1924
+ };
1925
+ const varianceStructInvariantType = (type, atLocation, propertyName) => {
1932
1926
  const propertySymbol = typeChecker.getPropertyOfType(type, propertyName);
1933
1927
  if (!propertySymbol) {
1934
- return yield* typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
1928
+ return typeParserIssue(`Type has no '${propertyName}' property`, type, atLocation);
1935
1929
  }
1936
1930
  const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
1937
- return yield* invariantTypeArgument(propertyType);
1938
- }
1939
- );
1940
- var effectVarianceStruct = fn("TypeParser.effectVarianceStruct")(function* (type, atLocation) {
1941
- return {
1942
- A: yield* varianceStructCovariantType(type, atLocation, "_A"),
1943
- E: yield* varianceStructCovariantType(type, atLocation, "_E"),
1944
- R: yield* varianceStructCovariantType(type, atLocation, "_R")
1931
+ return invariantTypeArgument(propertyType);
1945
1932
  };
1946
- });
1947
- var layerVarianceStruct = fn("TypeParser.layerVarianceStruct")(function* (type, atLocation) {
1948
- return {
1949
- ROut: yield* varianceStructContravariantType(type, atLocation, "_ROut"),
1950
- E: yield* varianceStructCovariantType(type, atLocation, "_E"),
1951
- RIn: yield* varianceStructCovariantType(type, atLocation, "_RIn")
1952
- };
1953
- });
1954
- var effectType = fn("TypeParser.effectType")(function* (type, atLocation) {
1955
- const ts = yield* service(TypeScriptApi);
1956
- const typeChecker = yield* service(TypeCheckerApi);
1957
- yield* pipeableType(type, atLocation);
1958
- const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
1959
- (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
1933
+ const effectVarianceStruct = (type, atLocation) => map3(
1934
+ all(
1935
+ varianceStructCovariantType(type, atLocation, "_A"),
1936
+ varianceStructCovariantType(type, atLocation, "_E"),
1937
+ varianceStructCovariantType(type, atLocation, "_R")
1938
+ ),
1939
+ ([A, E, R]) => ({ A, E, R })
1960
1940
  );
1961
- propertiesSymbols.sort((a, b) => b.name.indexOf("EffectTypeId") - a.name.indexOf("EffectTypeId"));
1962
- for (const propertySymbol of propertiesSymbols) {
1963
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
1964
- const varianceArgs = yield* option(effectVarianceStruct(
1965
- propertyType,
1966
- atLocation
1967
- ));
1968
- if (isSome2(varianceArgs)) {
1969
- return varianceArgs.value;
1970
- }
1971
- }
1972
- return yield* typeParserIssue("Type has no effect variance struct", type, atLocation);
1973
- });
1974
- var layerType = fn("TypeParser.layerType")(function* (type, atLocation) {
1975
- const ts = yield* service(TypeScriptApi);
1976
- const typeChecker = yield* service(TypeCheckerApi);
1977
- yield* pipeableType(type, atLocation);
1978
- const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
1979
- (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
1941
+ const layerVarianceStruct = (type, atLocation) => map3(
1942
+ all(
1943
+ varianceStructContravariantType(type, atLocation, "_ROut"),
1944
+ varianceStructCovariantType(type, atLocation, "_E"),
1945
+ varianceStructCovariantType(type, atLocation, "_RIn")
1946
+ ),
1947
+ ([ROut, E, RIn]) => ({ ROut, E, RIn })
1980
1948
  );
1981
- propertiesSymbols.sort((a, b) => b.name.indexOf("LayerTypeId") - a.name.indexOf("LayerTypeId"));
1982
- for (const propertySymbol of propertiesSymbols) {
1983
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
1984
- const varianceArgs = yield* option(layerVarianceStruct(
1985
- propertyType,
1986
- atLocation
1987
- ));
1988
- if (isSome2(varianceArgs)) {
1989
- return varianceArgs.value;
1990
- }
1991
- }
1992
- return yield* typeParserIssue("Type has no layer variance struct", type, atLocation);
1993
- });
1994
- var fiberType = fn("TypeParser.fiberType")(function* (type, atLocation) {
1995
- const typeChecker = yield* service(TypeCheckerApi);
1996
- const awaitSymbol = typeChecker.getPropertyOfType(type, "await");
1997
- const pollSymbol = typeChecker.getPropertyOfType(type, "poll");
1998
- if (!awaitSymbol || !pollSymbol) {
1999
- return yield* typeParserIssue(
2000
- "Type is not a fiber because it does not have 'await' or 'poll' property",
2001
- type,
2002
- atLocation
2003
- );
2004
- }
2005
- return yield* effectType(type, atLocation);
2006
- });
2007
- var effectSubtype = fn("TypeParser.effectSubtype")(function* (type, atLocation) {
2008
- const typeChecker = yield* service(TypeCheckerApi);
2009
- const tagSymbol = typeChecker.getPropertyOfType(type, "_tag");
2010
- const getSymbol = typeChecker.getPropertyOfType(type, "get");
2011
- if (!(tagSymbol || getSymbol)) {
2012
- return yield* typeParserIssue(
2013
- "Type is not a subtype of effect because it does not have '_tag' or 'get' property",
2014
- type,
2015
- atLocation
2016
- );
2017
- }
2018
- return yield* effectType(type, atLocation);
2019
- });
2020
- var importedEffectModule = fn("TypeParser.importedEffectModule")(function* (node) {
2021
- const ts = yield* service(TypeScriptApi);
2022
- const typeChecker = yield* service(TypeCheckerApi);
2023
- const type = typeChecker.getTypeAtLocation(node);
2024
- const propertySymbol = typeChecker.getPropertyOfType(type, "never");
2025
- if (!propertySymbol) {
2026
- return yield* typeParserIssue("Type has no 'never' property", type, node);
2027
- }
2028
- if (!ts.isExpression(node)) {
2029
- return yield* typeParserIssue("Node is not an expression", type, node);
2030
- }
2031
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, node);
2032
- yield* effectType(propertyType, node);
2033
- return node;
2034
- });
2035
- var effectGen = fn("TypeParser.effectGen")(function* (node) {
2036
- const ts = yield* service(TypeScriptApi);
2037
- if (!ts.isCallExpression(node)) {
2038
- return yield* typeParserIssue("Node is not a call expression", void 0, node);
2039
- }
2040
- if (node.arguments.length === 0) {
2041
- return yield* typeParserIssue("Node has no arguments", void 0, node);
2042
- }
2043
- const generatorFunction = node.arguments[0];
2044
- if (!ts.isFunctionExpression(generatorFunction)) {
2045
- return yield* typeParserIssue("Node is not a function expression", void 0, node);
2046
- }
2047
- if (generatorFunction.asteriskToken === void 0) {
2048
- return yield* typeParserIssue("Node is not a generator function", void 0, node);
2049
- }
2050
- if (!ts.isPropertyAccessExpression(node.expression)) {
2051
- return yield* typeParserIssue("Node is not a property access expression", void 0, node);
2052
- }
2053
- const propertyAccess = node.expression;
2054
- if (propertyAccess.name.text !== "gen") {
2055
- return yield* typeParserIssue("Call expression name is not 'gen'", void 0, node);
2056
- }
2057
- const effectModule = yield* importedEffectModule(propertyAccess.expression);
2058
- return {
2059
- node,
2060
- effectModule,
2061
- generatorFunction,
2062
- body: generatorFunction.body,
2063
- functionStar: generatorFunction.getFirstToken()
2064
- };
2065
- });
2066
- var effectFnUntracedGen = fn("TypeParser.effectFnUntracedGen")(
2067
- function* (node) {
2068
- const ts = yield* service(TypeScriptApi);
2069
- if (!ts.isCallExpression(node)) {
2070
- return yield* typeParserIssue("Node is not a call expression", void 0, node);
2071
- }
2072
- if (node.arguments.length === 0) {
2073
- return yield* typeParserIssue("Node has no arguments", void 0, node);
2074
- }
2075
- const generatorFunction = node.arguments[0];
2076
- if (!ts.isFunctionExpression(generatorFunction)) {
2077
- return yield* typeParserIssue("Node is not a function expression", void 0, node);
2078
- }
2079
- if (generatorFunction.asteriskToken === void 0) {
2080
- return yield* typeParserIssue(
2081
- "Node is not a generator function",
2082
- void 0,
2083
- node
1949
+ const effectType = cachedBy(
1950
+ fn("TypeParser.effectType")(function* (type, atLocation) {
1951
+ yield* pipeableType(type, atLocation);
1952
+ const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
1953
+ (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
2084
1954
  );
2085
- }
2086
- if (!ts.isPropertyAccessExpression(node.expression)) {
2087
- return yield* typeParserIssue(
2088
- "Node is not a property access expression",
2089
- void 0,
2090
- node
1955
+ propertiesSymbols.sort((a, b) => b.name.indexOf("EffectTypeId") - a.name.indexOf("EffectTypeId"));
1956
+ for (const propertySymbol of propertiesSymbols) {
1957
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
1958
+ const varianceArgs = yield* option(effectVarianceStruct(
1959
+ propertyType,
1960
+ atLocation
1961
+ ));
1962
+ if (isSome2(varianceArgs)) {
1963
+ return varianceArgs.value;
1964
+ }
1965
+ }
1966
+ return yield* typeParserIssue("Type has no effect variance struct", type, atLocation);
1967
+ }),
1968
+ "TypeParser.effectType",
1969
+ (type) => type
1970
+ );
1971
+ const layerType = cachedBy(
1972
+ fn("TypeParser.layerType")(function* (type, atLocation) {
1973
+ yield* pipeableType(type, atLocation);
1974
+ const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
1975
+ (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
2091
1976
  );
2092
- }
2093
- const propertyAccess = node.expression;
2094
- if (propertyAccess.name.text !== "fnUntraced") {
1977
+ propertiesSymbols.sort((a, b) => b.name.indexOf("LayerTypeId") - a.name.indexOf("LayerTypeId"));
1978
+ for (const propertySymbol of propertiesSymbols) {
1979
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
1980
+ const varianceArgs = yield* option(layerVarianceStruct(
1981
+ propertyType,
1982
+ atLocation
1983
+ ));
1984
+ if (isSome2(varianceArgs)) {
1985
+ return varianceArgs.value;
1986
+ }
1987
+ }
1988
+ return yield* typeParserIssue("Type has no layer variance struct", type, atLocation);
1989
+ }),
1990
+ "TypeParser.layerType",
1991
+ (type) => type
1992
+ );
1993
+ const fiberType = cachedBy(
1994
+ fn("TypeParser.fiberType")(function* (type, atLocation) {
1995
+ const awaitSymbol = typeChecker.getPropertyOfType(type, "await");
1996
+ const pollSymbol = typeChecker.getPropertyOfType(type, "poll");
1997
+ if (!awaitSymbol || !pollSymbol) {
1998
+ return yield* typeParserIssue(
1999
+ "Type is not a fiber because it does not have 'await' or 'poll' property",
2000
+ type,
2001
+ atLocation
2002
+ );
2003
+ }
2004
+ return yield* effectType(type, atLocation);
2005
+ }),
2006
+ "TypeParser.fiberType",
2007
+ (type) => type
2008
+ );
2009
+ const effectSubtype = cachedBy(
2010
+ fn("TypeParser.effectSubtype")(function* (type, atLocation) {
2011
+ const tagSymbol = typeChecker.getPropertyOfType(type, "_tag");
2012
+ const getSymbol = typeChecker.getPropertyOfType(type, "get");
2013
+ if (!(tagSymbol || getSymbol)) {
2014
+ return yield* typeParserIssue(
2015
+ "Type is not a subtype of effect because it does not have '_tag' or 'get' property",
2016
+ type,
2017
+ atLocation
2018
+ );
2019
+ }
2020
+ return yield* effectType(type, atLocation);
2021
+ }),
2022
+ "TypeParser.effectSubtype",
2023
+ (type) => type
2024
+ );
2025
+ const importedEffectModule = cachedBy(
2026
+ fn("TypeParser.importedEffectModule")(function* (node) {
2027
+ const type = typeChecker.getTypeAtLocation(node);
2028
+ const propertySymbol = typeChecker.getPropertyOfType(type, "never");
2029
+ if (!propertySymbol) {
2030
+ return yield* typeParserIssue("Type has no 'never' property", type, node);
2031
+ }
2032
+ if (!ts.isExpression(node)) {
2033
+ return yield* typeParserIssue("Node is not an expression", type, node);
2034
+ }
2035
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, node);
2036
+ yield* effectType(propertyType, node);
2037
+ return node;
2038
+ }),
2039
+ "TypeParser.importedEffectModule",
2040
+ (node) => node
2041
+ );
2042
+ const effectGen = cachedBy(
2043
+ fn("TypeParser.effectGen")(function* (node) {
2044
+ if (!ts.isCallExpression(node)) {
2045
+ return yield* typeParserIssue("Node is not a call expression", void 0, node);
2046
+ }
2047
+ if (node.arguments.length === 0) {
2048
+ return yield* typeParserIssue("Node has no arguments", void 0, node);
2049
+ }
2050
+ const generatorFunction = node.arguments[0];
2051
+ if (!ts.isFunctionExpression(generatorFunction)) {
2052
+ return yield* typeParserIssue("Node is not a function expression", void 0, node);
2053
+ }
2054
+ if (generatorFunction.asteriskToken === void 0) {
2055
+ return yield* typeParserIssue("Node is not a generator function", void 0, node);
2056
+ }
2057
+ if (!ts.isPropertyAccessExpression(node.expression)) {
2058
+ return yield* typeParserIssue("Node is not a property access expression", void 0, node);
2059
+ }
2060
+ const propertyAccess = node.expression;
2061
+ if (propertyAccess.name.text !== "gen") {
2062
+ return yield* typeParserIssue("Call expression name is not 'gen'", void 0, node);
2063
+ }
2064
+ const effectModule = yield* importedEffectModule(propertyAccess.expression);
2065
+ return {
2066
+ node,
2067
+ effectModule,
2068
+ generatorFunction,
2069
+ body: generatorFunction.body,
2070
+ functionStar: generatorFunction.getFirstToken()
2071
+ };
2072
+ }),
2073
+ "TypeParser.effectGen",
2074
+ (node) => node
2075
+ );
2076
+ const effectFnUntracedGen = cachedBy(
2077
+ fn("TypeParser.effectFnUntracedGen")(
2078
+ function* (node) {
2079
+ if (!ts.isCallExpression(node)) {
2080
+ return yield* typeParserIssue("Node is not a call expression", void 0, node);
2081
+ }
2082
+ if (node.arguments.length === 0) {
2083
+ return yield* typeParserIssue("Node has no arguments", void 0, node);
2084
+ }
2085
+ const generatorFunction = node.arguments[0];
2086
+ if (!ts.isFunctionExpression(generatorFunction)) {
2087
+ return yield* typeParserIssue("Node is not a function expression", void 0, node);
2088
+ }
2089
+ if (generatorFunction.asteriskToken === void 0) {
2090
+ return yield* typeParserIssue(
2091
+ "Node is not a generator function",
2092
+ void 0,
2093
+ node
2094
+ );
2095
+ }
2096
+ if (!ts.isPropertyAccessExpression(node.expression)) {
2097
+ return yield* typeParserIssue(
2098
+ "Node is not a property access expression",
2099
+ void 0,
2100
+ node
2101
+ );
2102
+ }
2103
+ const propertyAccess = node.expression;
2104
+ if (propertyAccess.name.text !== "fnUntraced") {
2105
+ return yield* typeParserIssue(
2106
+ "Call expression name is not 'fnUntraced'",
2107
+ void 0,
2108
+ node
2109
+ );
2110
+ }
2111
+ const effectModule = yield* importedEffectModule(propertyAccess.expression);
2112
+ return {
2113
+ node,
2114
+ effectModule,
2115
+ generatorFunction,
2116
+ body: generatorFunction.body,
2117
+ functionStar: generatorFunction.getFirstToken()
2118
+ };
2119
+ }
2120
+ ),
2121
+ "TypeParser.effectFnUntracedGen",
2122
+ (node) => node
2123
+ );
2124
+ const effectFnGen = cachedBy(
2125
+ fn("TypeParser.effectFnGen")(function* (node) {
2126
+ if (!ts.isCallExpression(node)) {
2127
+ return yield* typeParserIssue("Node is not a call expression", void 0, node);
2128
+ }
2129
+ if (node.arguments.length === 0) {
2130
+ return yield* typeParserIssue("Node has no arguments", void 0, node);
2131
+ }
2132
+ const generatorFunction = node.arguments[0];
2133
+ if (!ts.isFunctionExpression(generatorFunction)) {
2134
+ return yield* typeParserIssue(
2135
+ "Node is not a function expression",
2136
+ void 0,
2137
+ node
2138
+ );
2139
+ }
2140
+ if (generatorFunction.asteriskToken === void 0) {
2141
+ return yield* typeParserIssue(
2142
+ "Node is not a generator function",
2143
+ void 0,
2144
+ node
2145
+ );
2146
+ }
2147
+ const expressionToTest = ts.isCallExpression(node.expression) ? node.expression.expression : node.expression;
2148
+ if (!ts.isPropertyAccessExpression(expressionToTest)) {
2149
+ return yield* typeParserIssue(
2150
+ "Node is not a property access expression",
2151
+ void 0,
2152
+ node
2153
+ );
2154
+ }
2155
+ const propertyAccess = expressionToTest;
2156
+ if (propertyAccess.name.text !== "fn") {
2157
+ return yield* typeParserIssue(
2158
+ "Call expression name is not 'fn'",
2159
+ void 0,
2160
+ node
2161
+ );
2162
+ }
2163
+ const effectModule = yield* importedEffectModule(propertyAccess.expression);
2164
+ return {
2165
+ node,
2166
+ generatorFunction,
2167
+ effectModule,
2168
+ body: generatorFunction.body,
2169
+ functionStar: generatorFunction.getFirstToken()
2170
+ };
2171
+ }),
2172
+ "TypeParser.effectFnGen",
2173
+ (node) => node
2174
+ );
2175
+ const unnecessaryEffectGen2 = cachedBy(
2176
+ fn("TypeParser.unnecessaryEffectGen")(function* (node) {
2177
+ const { body } = yield* effectGen(node);
2178
+ if (body.statements.length !== 1) {
2179
+ return yield* typeParserIssue(
2180
+ "Generator body should have a single statement",
2181
+ void 0,
2182
+ node
2183
+ );
2184
+ }
2185
+ let explicitReturn = false;
2186
+ let nodeToCheck = body.statements[0];
2187
+ while (nodeToCheck) {
2188
+ if (ts.isReturnStatement(nodeToCheck) && nodeToCheck.expression) {
2189
+ nodeToCheck = nodeToCheck.expression;
2190
+ explicitReturn = true;
2191
+ continue;
2192
+ }
2193
+ if (ts.isExpressionStatement(nodeToCheck)) {
2194
+ nodeToCheck = nodeToCheck.expression;
2195
+ continue;
2196
+ }
2197
+ if (ts.isYieldExpression(nodeToCheck) && nodeToCheck.asteriskToken && nodeToCheck.expression) {
2198
+ const yieldedExpression = nodeToCheck.expression;
2199
+ const type = typeChecker.getTypeAtLocation(yieldedExpression);
2200
+ const { A: successType } = yield* effectType(type, yieldedExpression);
2201
+ let replacementNode = succeed(yieldedExpression);
2202
+ if (!explicitReturn && !(successType.flags & ts.TypeFlags.VoidLike)) {
2203
+ replacementNode = pipe(
2204
+ gen(function* () {
2205
+ const effectIdentifier = pipe(
2206
+ yield* option(
2207
+ findImportedModuleIdentifierByPackageAndNameOrBarrel(node.getSourceFile(), "effect", "Effect")
2208
+ ),
2209
+ match({
2210
+ onNone: () => "Effect",
2211
+ onSome: (_) => _.text
2212
+ })
2213
+ );
2214
+ return ts.factory.createCallExpression(
2215
+ ts.factory.createPropertyAccessExpression(
2216
+ ts.factory.createIdentifier(effectIdentifier),
2217
+ "asVoid"
2218
+ ),
2219
+ void 0,
2220
+ [
2221
+ yieldedExpression
2222
+ ]
2223
+ );
2224
+ }),
2225
+ provideService(TypeScriptApi, ts)
2226
+ );
2227
+ }
2228
+ return { node, body, yieldedExpression, replacementNode };
2229
+ }
2230
+ break;
2231
+ }
2095
2232
  return yield* typeParserIssue(
2096
- "Call expression name is not 'fnUntraced'",
2233
+ "Not an handled node",
2097
2234
  void 0,
2098
2235
  node
2099
2236
  );
2100
- }
2101
- const effectModule = yield* importedEffectModule(propertyAccess.expression);
2102
- return {
2103
- node,
2104
- effectModule,
2105
- generatorFunction,
2106
- body: generatorFunction.body,
2107
- functionStar: generatorFunction.getFirstToken()
2108
- };
2109
- }
2110
- );
2111
- var effectFnGen = fn("TypeParser.effectFnGen")(function* (node) {
2112
- const ts = yield* service(TypeScriptApi);
2113
- if (!ts.isCallExpression(node)) {
2114
- return yield* typeParserIssue("Node is not a call expression", void 0, node);
2115
- }
2116
- if (node.arguments.length === 0) {
2117
- return yield* typeParserIssue("Node has no arguments", void 0, node);
2118
- }
2119
- const generatorFunction = node.arguments[0];
2120
- if (!ts.isFunctionExpression(generatorFunction)) {
2121
- return yield* typeParserIssue(
2122
- "Node is not a function expression",
2123
- void 0,
2124
- node
2125
- );
2126
- }
2127
- if (generatorFunction.asteriskToken === void 0) {
2128
- return yield* typeParserIssue(
2129
- "Node is not a generator function",
2130
- void 0,
2131
- node
2132
- );
2133
- }
2134
- const expressionToTest = ts.isCallExpression(node.expression) ? node.expression.expression : node.expression;
2135
- if (!ts.isPropertyAccessExpression(expressionToTest)) {
2136
- return yield* typeParserIssue(
2137
- "Node is not a property access expression",
2138
- void 0,
2139
- node
2140
- );
2141
- }
2142
- const propertyAccess = expressionToTest;
2143
- if (propertyAccess.name.text !== "fn") {
2144
- return yield* typeParserIssue(
2145
- "Call expression name is not 'fn'",
2146
- void 0,
2147
- node
2148
- );
2149
- }
2150
- const effectModule = yield* importedEffectModule(propertyAccess.expression);
2237
+ }),
2238
+ "TypeParser.unnecessaryEffectGen",
2239
+ (node) => node
2240
+ );
2241
+ const effectSchemaVarianceStruct = (type, atLocation) => map3(
2242
+ all(
2243
+ varianceStructInvariantType(type, atLocation, "_A"),
2244
+ varianceStructInvariantType(type, atLocation, "_I"),
2245
+ varianceStructCovariantType(type, atLocation, "_R")
2246
+ ),
2247
+ ([A, I, R]) => ({ A, I, R })
2248
+ );
2249
+ const effectSchemaType = cachedBy(
2250
+ fn("TypeParser.effectSchemaType")(function* (type, atLocation) {
2251
+ yield* pipeableType(type, atLocation);
2252
+ const ast = typeChecker.getPropertyOfType(type, "ast");
2253
+ if (!ast) return yield* typeParserIssue("Has no 'ast' property", type, atLocation);
2254
+ const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
2255
+ (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
2256
+ );
2257
+ propertiesSymbols.sort((a, b) => b.name.indexOf("TypeId") - a.name.indexOf("TypeId"));
2258
+ for (const propertySymbol of propertiesSymbols) {
2259
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
2260
+ const varianceArgs = yield* option(effectSchemaVarianceStruct(
2261
+ propertyType,
2262
+ atLocation
2263
+ ));
2264
+ if (isSome2(varianceArgs)) {
2265
+ return varianceArgs.value;
2266
+ }
2267
+ }
2268
+ return yield* typeParserIssue("Type has no schema variance struct", type, atLocation);
2269
+ }),
2270
+ "TypeParser.effectSchemaType",
2271
+ (type) => type
2272
+ );
2273
+ const contextTagVarianceStruct = (type, atLocation) => map3(
2274
+ all(
2275
+ varianceStructInvariantType(type, atLocation, "_Identifier"),
2276
+ varianceStructInvariantType(type, atLocation, "_Service")
2277
+ ),
2278
+ ([Identifier, Service]) => ({ Identifier, Service })
2279
+ );
2280
+ const contextTag = cachedBy(
2281
+ fn("TypeParser.contextTag")(function* (type, atLocation) {
2282
+ yield* pipeableType(type, atLocation);
2283
+ const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
2284
+ (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
2285
+ );
2286
+ propertiesSymbols.sort((a, b) => b.name.indexOf("TypeId") - a.name.indexOf("TypeId"));
2287
+ for (const propertySymbol of propertiesSymbols) {
2288
+ const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
2289
+ const varianceArgs = yield* option(contextTagVarianceStruct(
2290
+ propertyType,
2291
+ atLocation
2292
+ ));
2293
+ if (isSome2(varianceArgs)) {
2294
+ return varianceArgs.value;
2295
+ }
2296
+ }
2297
+ return yield* typeParserIssue("Type has no tag variance struct", type, atLocation);
2298
+ }),
2299
+ "TypeParser.contextTag",
2300
+ (type) => type
2301
+ );
2151
2302
  return {
2152
- node,
2153
- generatorFunction,
2154
- effectModule,
2155
- body: generatorFunction.body,
2156
- functionStar: generatorFunction.getFirstToken()
2303
+ effectType,
2304
+ layerType,
2305
+ fiberType,
2306
+ effectSubtype,
2307
+ importedEffectModule,
2308
+ effectGen,
2309
+ effectFnUntracedGen,
2310
+ effectFnGen,
2311
+ unnecessaryEffectGen: unnecessaryEffectGen2,
2312
+ effectSchemaType,
2313
+ contextTag
2157
2314
  };
2158
- });
2159
- var unnecessaryEffectGen = fn("TypeParser.unnecessaryEffectGen")(function* (node) {
2160
- const ts = yield* service(TypeScriptApi);
2161
- const typeChecker = yield* service(TypeCheckerApi);
2162
- const { body } = yield* effectGen(node);
2163
- if (body.statements.length !== 1) {
2164
- return yield* typeParserIssue(
2165
- "Generator body should have a single statement",
2166
- void 0,
2167
- node
2168
- );
2169
- }
2170
- let explicitReturn = false;
2171
- let nodeToCheck = body.statements[0];
2172
- while (nodeToCheck) {
2173
- if (ts.isReturnStatement(nodeToCheck) && nodeToCheck.expression) {
2174
- nodeToCheck = nodeToCheck.expression;
2175
- explicitReturn = true;
2176
- continue;
2177
- }
2178
- if (ts.isExpressionStatement(nodeToCheck)) {
2179
- nodeToCheck = nodeToCheck.expression;
2180
- continue;
2315
+ }
2316
+
2317
+ // src/diagnostics/duplicatePackage.ts
2318
+ var checkedPackagesCache = /* @__PURE__ */ new Map();
2319
+ var programResolvedCacheSize = /* @__PURE__ */ new Map();
2320
+ var duplicatePackage = createDiagnostic({
2321
+ name: "duplicatePackage",
2322
+ code: 6,
2323
+ apply: fn("duplicatePackage.apply")(function* (sourceFile) {
2324
+ const ts = yield* service(TypeScriptApi);
2325
+ const program = yield* service(TypeScriptProgram);
2326
+ const options = yield* service(LanguageServicePluginOptions);
2327
+ const effectDiagnostics = [];
2328
+ if (sourceFile.statements.length < 1) return [];
2329
+ let resolvedPackages = checkedPackagesCache.get(sourceFile.fileName) || {};
2330
+ const newResolvedModuleSize = hasProperty(program, "resolvedModules") && hasProperty(program.resolvedModules, "size") && isNumber(program.resolvedModules.size) ? program.resolvedModules.size : 0;
2331
+ const oldResolvedSize = programResolvedCacheSize.get(sourceFile.fileName) || -1;
2332
+ if (newResolvedModuleSize !== oldResolvedSize) {
2333
+ const seenPackages = /* @__PURE__ */ new Set();
2334
+ resolvedPackages = {};
2335
+ program.getSourceFiles().map((_) => {
2336
+ const packageInfo = parsePackageContentNameAndVersionFromScope(_);
2337
+ if (!packageInfo) return;
2338
+ const packageNameAndVersion = packageInfo.name + "@" + packageInfo.version;
2339
+ if (seenPackages.has(packageNameAndVersion)) return;
2340
+ seenPackages.add(packageNameAndVersion);
2341
+ if (!(packageInfo.name === "effect" || packageInfo.hasEffectInPeerDependencies)) return;
2342
+ if (options.allowedDuplicatedPackages.indexOf(packageInfo.name) > -1) return;
2343
+ resolvedPackages[packageInfo.name] = resolvedPackages[packageInfo.name] || {};
2344
+ resolvedPackages[packageInfo.name][packageInfo.version] = packageInfo.contents;
2345
+ });
2346
+ checkedPackagesCache.set(sourceFile.fileName, resolvedPackages);
2347
+ programResolvedCacheSize.set(sourceFile.fileName, newResolvedModuleSize);
2181
2348
  }
2182
- if (ts.isYieldExpression(nodeToCheck) && nodeToCheck.asteriskToken && nodeToCheck.expression) {
2183
- const yieldedExpression = nodeToCheck.expression;
2184
- const type = typeChecker.getTypeAtLocation(yieldedExpression);
2185
- const { A: successType } = yield* effectType(type, yieldedExpression);
2186
- let replacementNode = succeed(yieldedExpression);
2187
- if (!explicitReturn && !(successType.flags & ts.TypeFlags.VoidLike)) {
2188
- replacementNode = pipe(
2189
- gen(function* () {
2190
- const effectIdentifier = pipe(
2191
- yield* option(
2192
- findImportedModuleIdentifierByPackageAndNameOrBarrel(node.getSourceFile(), "effect", "Effect")
2193
- ),
2194
- match({
2195
- onNone: () => "Effect",
2196
- onSome: (_) => _.text
2197
- })
2198
- );
2199
- return ts.factory.createCallExpression(
2200
- ts.factory.createPropertyAccessExpression(
2201
- ts.factory.createIdentifier(effectIdentifier),
2202
- "asVoid"
2203
- ),
2204
- void 0,
2205
- [
2206
- yieldedExpression
2207
- ]
2208
- );
2209
- }),
2210
- provideService(TypeScriptApi, ts)
2211
- );
2349
+ for (const packageName of Object.keys(resolvedPackages)) {
2350
+ if (Object.keys(resolvedPackages[packageName]).length > 1) {
2351
+ const versions = Object.keys(resolvedPackages[packageName]);
2352
+ effectDiagnostics.push({
2353
+ node: sourceFile.statements[0],
2354
+ category: ts.DiagnosticCategory.Warning,
2355
+ messageText: `Package ${packageName} is referenced multiple times with different versions (${versions.join(", ")}) and may cause unexpected type errors.
2356
+ Cleanup your dependencies and your package lockfile to avoid multiple instances of this package and reload the project.
2357
+ If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.`,
2358
+ fixes: []
2359
+ });
2212
2360
  }
2213
- return { node, body, yieldedExpression, replacementNode };
2214
2361
  }
2215
- break;
2216
- }
2217
- return yield* typeParserIssue(
2218
- "Not an handled node",
2219
- void 0,
2220
- node
2221
- );
2222
- });
2223
- var effectSchemaVarianceStruct = fn("TypeParser.effectSchemaVarianceStruct")(
2224
- function* (type, atLocation) {
2225
- return {
2226
- A: yield* varianceStructInvariantType(type, atLocation, "_A"),
2227
- I: yield* varianceStructInvariantType(type, atLocation, "_I"),
2228
- R: yield* varianceStructCovariantType(type, atLocation, "_R")
2229
- };
2230
- }
2231
- );
2232
- var effectSchemaType = fn("TypeParser.effectSchemaType")(function* (type, atLocation) {
2233
- const ts = yield* service(TypeScriptApi);
2234
- const typeChecker = yield* service(TypeCheckerApi);
2235
- yield* pipeableType(type, atLocation);
2236
- const ast = typeChecker.getPropertyOfType(type, "ast");
2237
- if (!ast) return yield* typeParserIssue("Has no 'ast' property", type, atLocation);
2238
- const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
2239
- (_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional)
2240
- );
2241
- propertiesSymbols.sort((a, b) => b.name.indexOf("TypeId") - a.name.indexOf("TypeId"));
2242
- for (const propertySymbol of propertiesSymbols) {
2243
- const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
2244
- const varianceArgs = yield* option(effectSchemaVarianceStruct(
2245
- propertyType,
2246
- atLocation
2247
- ));
2248
- if (isSome2(varianceArgs)) {
2249
- return varianceArgs.value;
2250
- }
2251
- }
2252
- return yield* typeParserIssue("Type has no schema variance struct", type, atLocation);
2362
+ return effectDiagnostics;
2363
+ })
2253
2364
  });
2254
2365
 
2255
2366
  // src/diagnostics/floatingEffect.ts
@@ -2259,6 +2370,7 @@ var floatingEffect = createDiagnostic({
2259
2370
  apply: fn("floatingEffect.apply")(function* (sourceFile) {
2260
2371
  const ts = yield* service(TypeScriptApi);
2261
2372
  const typeChecker = yield* service(TypeCheckerApi);
2373
+ const typeParser = yield* service(TypeParser);
2262
2374
  function isFloatingExpression(node) {
2263
2375
  if (!ts.isExpressionStatement(node)) return false;
2264
2376
  if (!(ts.isBlock(node.parent) || ts.isSourceFile(node.parent))) return false;
@@ -2278,11 +2390,11 @@ var floatingEffect = createDiagnostic({
2278
2390
  ts.forEachChild(node, appendNodeToVisit);
2279
2391
  if (!isFloatingExpression(node)) continue;
2280
2392
  const type = typeChecker.getTypeAtLocation(node.expression);
2281
- const effect = yield* option(effectType(type, node.expression));
2393
+ const effect = yield* option(typeParser.effectType(type, node.expression));
2282
2394
  if (isSome2(effect)) {
2283
2395
  const allowedFloatingEffects = yield* pipe(
2284
- fiberType(type, node.expression),
2285
- orElse2(() => effectSubtype(type, node.expression)),
2396
+ typeParser.fiberType(type, node.expression),
2397
+ orElse2(() => typeParser.effectSubtype(type, node.expression)),
2286
2398
  option
2287
2399
  );
2288
2400
  if (isNone2(allowedFloatingEffects)) {
@@ -2299,6 +2411,112 @@ var floatingEffect = createDiagnostic({
2299
2411
  })
2300
2412
  });
2301
2413
 
2414
+ // src/diagnostics/leakingRequirements.ts
2415
+ var leakingRequirements = createDiagnostic({
2416
+ name: "leakingRequirements",
2417
+ code: 8,
2418
+ apply: fn("leakingRequirements.apply")(function* (sourceFile) {
2419
+ const ts = yield* service(TypeScriptApi);
2420
+ const typeChecker = yield* service(TypeCheckerApi);
2421
+ const typeParser = yield* service(TypeParser);
2422
+ const typeOrder = yield* deterministicTypeOrder;
2423
+ const effectDiagnostics = [];
2424
+ const parseLeakedRequirements = cachedBy(
2425
+ fn("leakingServices.checkServiceLeaking")(
2426
+ function* (service2, atLocation) {
2427
+ const properties = typeChecker.getPropertiesOfType(service2);
2428
+ if (properties.length < 1) return [];
2429
+ const memory = /* @__PURE__ */ new Map();
2430
+ let sharedRequirementsKeys = void 0;
2431
+ let effectMembers = 0;
2432
+ for (const property of properties) {
2433
+ const servicePropertyType = typeChecker.getTypeOfSymbolAtLocation(property, atLocation);
2434
+ let effectContextType = void 0;
2435
+ yield* pipe(
2436
+ typeParser.effectType(servicePropertyType, atLocation),
2437
+ map3((_) => effectContextType = _.R),
2438
+ orElse2(() => {
2439
+ const servicePropertyCallSignatures = servicePropertyType.getCallSignatures();
2440
+ if (servicePropertyCallSignatures.length === 1) {
2441
+ return pipe(
2442
+ typeParser.effectType(servicePropertyCallSignatures[0].getReturnType(), atLocation),
2443
+ map3((_) => {
2444
+ effectContextType = _.R;
2445
+ })
2446
+ );
2447
+ }
2448
+ return void_;
2449
+ }),
2450
+ ignore
2451
+ );
2452
+ if (effectContextType) {
2453
+ effectMembers++;
2454
+ const { allIndexes } = yield* appendToUniqueTypesMap(memory, effectContextType, true);
2455
+ if (!sharedRequirementsKeys) {
2456
+ sharedRequirementsKeys = allIndexes;
2457
+ } else {
2458
+ sharedRequirementsKeys = intersection(sharedRequirementsKeys, allIndexes);
2459
+ if (sharedRequirementsKeys.length === 0) return [];
2460
+ }
2461
+ }
2462
+ }
2463
+ if (sharedRequirementsKeys && sharedRequirementsKeys.length > 0 && effectMembers >= 2) {
2464
+ return sharedRequirementsKeys.map((key) => memory.get(key));
2465
+ }
2466
+ return [];
2467
+ }
2468
+ ),
2469
+ "leakingServices.checkServiceLeaking",
2470
+ (_, service2) => service2
2471
+ );
2472
+ function reportLeakingRequirements(node, requirements) {
2473
+ if (requirements.length === 0) return;
2474
+ effectDiagnostics.push({
2475
+ node,
2476
+ category: ts.DiagnosticCategory.Warning,
2477
+ messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement`,
2478
+ fixes: []
2479
+ });
2480
+ }
2481
+ const nodeToVisit = [];
2482
+ const appendNodeToVisit = (node) => {
2483
+ nodeToVisit.push(node);
2484
+ return void 0;
2485
+ };
2486
+ ts.forEachChild(sourceFile, appendNodeToVisit);
2487
+ while (nodeToVisit.length > 0) {
2488
+ const node = nodeToVisit.shift();
2489
+ const typesToCheck = [];
2490
+ if (ts.isCallExpression(node)) {
2491
+ typesToCheck.push([typeChecker.getTypeAtLocation(node), node]);
2492
+ } else if (ts.isClassDeclaration(node) && node.name) {
2493
+ const classSym = typeChecker.getSymbolAtLocation(node.name);
2494
+ if (classSym) {
2495
+ const type = typeChecker.getTypeOfSymbol(classSym);
2496
+ typesToCheck.push([type, node.name]);
2497
+ }
2498
+ } else {
2499
+ ts.forEachChild(node, appendNodeToVisit);
2500
+ continue;
2501
+ }
2502
+ for (const [type, reportAt] of typesToCheck) {
2503
+ yield* pipe(
2504
+ typeParser.contextTag(type, node),
2505
+ flatMap2(
2506
+ ({ Service }) => pipe(
2507
+ parseLeakedRequirements(Service, node),
2508
+ map3((requirements) => reportLeakingRequirements(reportAt, sort(requirements, typeOrder)))
2509
+ )
2510
+ ),
2511
+ orElse2(() => sync(() => ts.forEachChild(node, appendNodeToVisit))),
2512
+ ignore
2513
+ );
2514
+ }
2515
+ }
2516
+ return effectDiagnostics;
2517
+ })
2518
+ });
2519
+
2302
2520
  // src/diagnostics/missingEffectContext.ts
2303
2521
  var missingEffectContext = createDiagnostic({
2304
2522
  name: "missingEffectContext",
@@ -2306,15 +2524,16 @@ var missingEffectContext = createDiagnostic({
2306
2524
  apply: fn("missingEffectContext.apply")(function* (sourceFile) {
2307
2525
  const ts = yield* service(TypeScriptApi);
2308
2526
  const typeChecker = yield* service(TypeCheckerApi);
2527
+ const typeParser = yield* service(TypeParser);
2309
2528
  const typeOrder = yield* deterministicTypeOrder;
2310
2529
  const checkForMissingContextTypes = fn(
2311
2530
  "missingEffectContext.apply.checkForMissingContextTypes"
2312
2531
  )(function* (node, expectedType, valueNode, realType) {
2313
- const expectedEffect = yield* effectType(
2532
+ const expectedEffect = yield* typeParser.effectType(
2314
2533
  expectedType,
2315
2534
  node
2316
2535
  );
2317
- const realEffect = yield* effectType(
2536
+ const realEffect = yield* typeParser.effectType(
2318
2537
  realType,
2319
2538
  valueNode
2320
2539
  );
@@ -2358,14 +2577,15 @@ var missingEffectError = createDiagnostic({
2358
2577
  apply: fn("missingEffectError.apply")(function* (sourceFile) {
2359
2578
  const ts = yield* service(TypeScriptApi);
2360
2579
  const typeChecker = yield* service(TypeCheckerApi);
2580
+ const typeParser = yield* service(TypeParser);
2361
2581
  const typeOrder = yield* deterministicTypeOrder;
2362
2582
  const checkForMissingErrorTypes = fn("missingEffectError.apply.checkForMissingErrorTypes")(
2363
2583
  function* (node, expectedType, valueNode, realType) {
2364
- const expectedEffect = yield* effectType(
2584
+ const expectedEffect = yield* typeParser.effectType(
2365
2585
  expectedType,
2366
2586
  node
2367
2587
  );
2368
- const realEffect = yield* effectType(
2588
+ const realEffect = yield* typeParser.effectType(
2369
2589
  realType,
2370
2590
  valueNode
2371
2591
  );
@@ -2410,6 +2630,7 @@ var missingReturnYieldStar = createDiagnostic({
2410
2630
  apply: fn("missingReturnYieldStar.apply")(function* (sourceFile) {
2411
2631
  const ts = yield* service(TypeScriptApi);
2412
2632
  const typeChecker = yield* service(TypeCheckerApi);
2633
+ const typeParser = yield* service(TypeParser);
2413
2634
  const effectDiagnostics = [];
2414
2635
  const brokenYields = /* @__PURE__ */ new Set();
2415
2636
  const nodeToVisit = [];
@@ -2423,7 +2644,7 @@ var missingReturnYieldStar = createDiagnostic({
2423
2644
  ts.forEachChild(node, appendNodeToVisit);
2424
2645
  if (ts.isYieldExpression(node) && node.expression && node.asteriskToken) {
2425
2646
  const type = typeChecker.getTypeAtLocation(node.expression);
2426
- const maybeEffect = yield* option(effectType(type, node.expression));
2647
+ const maybeEffect = yield* option(typeParser.effectType(type, node.expression));
2427
2648
  if (isSome2(maybeEffect) && maybeEffect.value.A.flags & ts.TypeFlags.Never) {
2428
2649
  const generatorFunctionOrReturnStatement = ts.findAncestor(
2429
2650
  node,
@@ -2433,9 +2654,9 @@ var missingReturnYieldStar = createDiagnostic({
2433
2654
  if (generatorFunctionOrReturnStatement && generatorFunctionOrReturnStatement.parent) {
2434
2655
  const effectGenNode = generatorFunctionOrReturnStatement.parent;
2435
2656
  const effectGenLike = yield* pipe(
2436
- effectGen(effectGenNode),
2437
- orElse2(() => effectFnUntracedGen(effectGenNode)),
2438
- orElse2(() => effectFnGen(effectGenNode)),
2657
+ typeParser.effectGen(effectGenNode),
2658
+ orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
2659
+ orElse2(() => typeParser.effectFnGen(effectGenNode)),
2439
2660
  option
2440
2661
  );
2441
2662
  if (isSome2(effectGenLike)) {
@@ -2478,6 +2699,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
2478
2699
  code: 4,
2479
2700
  apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile) {
2480
2701
  const ts = yield* service(TypeScriptApi);
2702
+ const typeParser = yield* service(TypeParser);
2481
2703
  const effectDiagnostics = [];
2482
2704
  const brokenGenerators = /* @__PURE__ */ new Set();
2483
2705
  const brokenYields = /* @__PURE__ */ new Set();
@@ -2497,18 +2719,18 @@ var missingStarInYieldEffectGen = createDiagnostic({
2497
2719
  );
2498
2720
  if (functionStarNode && functionStarNode.parent) {
2499
2721
  const effectGenNode = functionStarNode.parent;
2500
- const effectGenLike = yield* pipe(
2501
- effectGen(effectGenNode),
2502
- orElse2(() => effectFnUntracedGen(effectGenNode)),
2503
- orElse2(() => effectFnGen(effectGenNode)),
2504
- option
2722
+ yield* pipe(
2723
+ typeParser.effectGen(effectGenNode),
2724
+ orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
2725
+ orElse2(() => typeParser.effectFnGen(effectGenNode)),
2726
+ map3(({ functionStar }) => {
2727
+ if (functionStar) {
2728
+ brokenGenerators.add(functionStar);
2729
+ }
2730
+ brokenYields.add(node);
2731
+ }),
2732
+ ignore
2505
2733
  );
2506
- if (isSome2(effectGenLike)) {
2507
- if (effectGenLike.value.functionStar) {
2508
- brokenGenerators.add(effectGenLike.value.functionStar);
2509
- }
2510
- brokenYields.add(node);
2511
- }
2512
2734
  }
2513
2735
  }
2514
2736
  }
@@ -2548,11 +2770,12 @@ var missingStarInYieldEffectGen = createDiagnostic({
2548
2770
  });
2549
2771
 
2550
2772
  // src/diagnostics/unnecessaryEffectGen.ts
2551
- var unnecessaryEffectGen2 = createDiagnostic({
2773
+ var unnecessaryEffectGen = createDiagnostic({
2552
2774
  name: "unnecessaryEffectGen",
2553
2775
  code: 5,
2554
2776
  apply: fn("unnecessaryEffectGen.apply")(function* (sourceFile) {
2555
2777
  const ts = yield* service(TypeScriptApi);
2778
+ const typeParser = yield* service(TypeParser);
2556
2779
  const effectDiagnostics = [];
2557
2780
  const unnecessaryGenerators = /* @__PURE__ */ new Map();
2558
2781
  const nodeToVisit = [];
@@ -2564,9 +2787,12 @@ var unnecessaryEffectGen2 = createDiagnostic({
2564
2787
  while (nodeToVisit.length > 0) {
2565
2788
  const node = nodeToVisit.shift();
2566
2789
  ts.forEachChild(node, appendNodeToVisit);
2567
- const maybeNode = yield* option(unnecessaryEffectGen(node));
2568
- if (isSome2(maybeNode)) {
2569
- unnecessaryGenerators.set(node, maybeNode.value.replacementNode);
2790
+ if (ts.isCallExpression(node)) {
2791
+ yield* pipe(
2792
+ typeParser.unnecessaryEffectGen(node),
2793
+ map3(({ replacementNode }) => unnecessaryGenerators.set(node, replacementNode)),
2794
+ ignore
2795
+ );
2570
2796
  }
2571
2797
  }
2572
2798
  unnecessaryGenerators.forEach(
@@ -2597,8 +2823,9 @@ var diagnostics = [
2597
2823
  missingEffectError,
2598
2824
  floatingEffect,
2599
2825
  missingStarInYieldEffectGen,
2600
- unnecessaryEffectGen2,
2601
- missingReturnYieldStar
2826
+ unnecessaryEffectGen,
2827
+ missingReturnYieldStar,
2828
+ leakingRequirements
2602
2829
  ];
2603
2830
 
2604
2831
  // src/transform.ts
@@ -2610,6 +2837,7 @@ function transform_default(program, pluginConfig, { addDiagnostic, ts: tsInstanc
2610
2837
  provideService(TypeScriptApi, tsInstance),
2611
2838
  provideService(TypeScriptProgram, program),
2612
2839
  provideService(TypeCheckerApi, program.getTypeChecker()),
2840
+ provideService(TypeParser, make3(tsInstance, program.getTypeChecker())),
2613
2841
  provideService(
2614
2842
  TypeCheckerApiCache,
2615
2843
  makeTypeCheckerApiCache()