@effect/language-service 0.83.0 → 0.84.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.37/node_modules/effect/dist/Pipeable.js
27
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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.37/node_modules/effect/dist/Function.js
60
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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.37/node_modules/effect/dist/internal/equal.js
108
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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.37/node_modules/effect/dist/Predicate.js
131
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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.37/node_modules/effect/dist/Hash.js
152
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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.37/node_modules/effect/dist/Equal.js
271
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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.37/node_modules/effect/dist/internal/array.js
433
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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.37/node_modules/effect/dist/Redactable.js
436
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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.37/node_modules/effect/dist/Formatter.js
455
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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.37/node_modules/effect/dist/Inspectable.js
534
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/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,7 +575,7 @@ var Class = class {
575
575
  }
576
576
  };
577
577
 
578
- // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Utils.js
578
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Utils.js
579
579
  var SingleShotGen = class _SingleShotGen {
580
580
  called = false;
581
581
  self;
@@ -618,7 +618,7 @@ var forced = {
618
618
  var isNotOptimizedAway = /* @__PURE__ */ standard[InternalTypeId](() => new Error().stack)?.includes(InternalTypeId) === true;
619
619
  var internalCall = isNotOptimizedAway ? standard[InternalTypeId] : forced[InternalTypeId];
620
620
 
621
- // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/core.js
621
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/core.js
622
622
  var EffectTypeId = `~effect/Effect`;
623
623
  var ExitTypeId = `~effect/Exit`;
624
624
  var effectVariance = {
@@ -965,7 +965,7 @@ var DoneVoid = {
965
965
  value: void 0
966
966
  };
967
967
 
968
- // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/option.js
968
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/option.js
969
969
  var TypeId = "~effect/data/Option";
970
970
  var CommonProto = {
971
971
  [TypeId]: {
@@ -1036,7 +1036,7 @@ var some = (value) => {
1036
1036
  return a;
1037
1037
  };
1038
1038
 
1039
- // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/internal/result.js
1039
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/internal/result.js
1040
1040
  var TypeId2 = "~effect/data/Result";
1041
1041
  var CommonProto2 = {
1042
1042
  [TypeId2]: {
@@ -1107,13 +1107,13 @@ var succeed = (success) => {
1107
1107
  return a;
1108
1108
  };
1109
1109
 
1110
- // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Order.js
1110
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Order.js
1111
1111
  function make(compare) {
1112
1112
  return (self, that) => self === that ? 0 : compare(self, that);
1113
1113
  }
1114
1114
  var String2 = /* @__PURE__ */ make((self, that) => self < that ? -1 : 1);
1115
1115
 
1116
- // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Option.js
1116
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Option.js
1117
1117
  var none2 = () => none;
1118
1118
  var some2 = some;
1119
1119
  var isNone2 = isNone;
@@ -1123,7 +1123,7 @@ var orElse = /* @__PURE__ */ dual(2, (self, that) => isNone2(self) ? that() : se
1123
1123
  var fromNullishOr = (a) => a == null ? none2() : some2(a);
1124
1124
  var getOrUndefined = /* @__PURE__ */ getOrElse(constUndefined);
1125
1125
 
1126
- // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Result.js
1126
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Result.js
1127
1127
  var succeed2 = succeed;
1128
1128
  var fail2 = fail;
1129
1129
  var isFailure2 = isFailure;
@@ -1131,7 +1131,7 @@ var isSuccess2 = isSuccess;
1131
1131
  var map = /* @__PURE__ */ dual(2, (self, f) => isSuccess2(self) ? succeed2(f(self.success)) : fail2(self.failure));
1132
1132
  var getOrElse2 = /* @__PURE__ */ dual(2, (self, onFailure) => isFailure2(self) ? onFailure(self.failure) : self.success);
1133
1133
 
1134
- // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Record.js
1134
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Record.js
1135
1135
  var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1136
1136
  const out = {
1137
1137
  ...self
@@ -1143,7 +1143,7 @@ var map2 = /* @__PURE__ */ dual(2, (self, f) => {
1143
1143
  });
1144
1144
  var keys = (self) => Object.keys(self);
1145
1145
 
1146
- // ../../node_modules/.pnpm/effect@4.0.0-beta.37/node_modules/effect/dist/Array.js
1146
+ // ../../node_modules/.pnpm/effect@4.0.0-beta.38/node_modules/effect/dist/Array.js
1147
1147
  var Array2 = globalThis.Array;
1148
1148
  var fromIterable = (collection) => Array2.isArray(collection) ? collection : Array2.from(collection);
1149
1149
  var append = /* @__PURE__ */ dual(2, (self, last) => [...self, last]);
@@ -3122,6 +3122,25 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
3122
3122
  return typeChecker.getTypeAtLocation(node);
3123
3123
  }
3124
3124
  }
3125
+ function resolveToGlobalSymbol(symbol3) {
3126
+ if (symbol3.flags & ts.SymbolFlags.Alias) {
3127
+ symbol3 = typeChecker.getAliasedSymbol(symbol3);
3128
+ }
3129
+ let depth = 0;
3130
+ while (depth < 2 && symbol3.valueDeclaration && ts.isVariableDeclaration(symbol3.valueDeclaration)) {
3131
+ const initializer = symbol3.valueDeclaration.initializer;
3132
+ if (!initializer) break;
3133
+ let nextSymbol = typeChecker.getSymbolAtLocation(initializer);
3134
+ if (!nextSymbol) break;
3135
+ if (nextSymbol.flags & ts.SymbolFlags.Alias) {
3136
+ nextSymbol = typeChecker.getAliasedSymbol(nextSymbol);
3137
+ }
3138
+ if (nextSymbol === symbol3) break;
3139
+ symbol3 = nextSymbol;
3140
+ depth++;
3141
+ }
3142
+ return symbol3;
3143
+ }
3125
3144
  return {
3126
3145
  isUnion,
3127
3146
  isReadonlyArrayType,
@@ -3135,7 +3154,8 @@ function makeTypeCheckerUtils(ts, typeChecker, tsUtils) {
3135
3154
  expectedAndRealType,
3136
3155
  typeToSimplifiedTypeNode,
3137
3156
  isGlobalErrorType,
3138
- getTypeAtLocation
3157
+ getTypeAtLocation,
3158
+ resolveToGlobalSymbol
3139
3159
  };
3140
3160
  }
3141
3161
 
@@ -3823,7 +3843,11 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
3823
3843
  }
3824
3844
  currentParent = nodeToCheck.parent;
3825
3845
  }
3826
- return { scopeNode, effectGen: effectGenResult };
3846
+ return {
3847
+ inEffect: effectGenResult !== void 0 && effectGenResult.body.statements.length > 0 && scopeNode === effectGenResult.generatorFunction,
3848
+ scopeNode,
3849
+ effectGen: effectGenResult
3850
+ };
3827
3851
  });
3828
3852
  const effectFn = cachedBy(
3829
3853
  function(node) {
@@ -7018,6 +7042,128 @@ var genericEffectServices = createDiagnostic({
7018
7042
  })
7019
7043
  });
7020
7044
 
7045
+ // src/diagnostics/globalConsoleInEffect.ts
7046
+ var consoleMethodAlternatives = {
7047
+ "log": "Effect.log or Logger",
7048
+ "warn": "Effect.logWarning or Logger",
7049
+ "error": "Effect.logError or Logger",
7050
+ "info": "Effect.logInfo or Logger",
7051
+ "debug": "Effect.logDebug or Logger",
7052
+ "trace": "Effect.logTrace or Logger"
7053
+ };
7054
+ var makeGlobalConsoleApply = (checkInEffect) => fn(`globalConsole${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
7055
+ const ts = yield* service(TypeScriptApi);
7056
+ const typeChecker = yield* service(TypeCheckerApi);
7057
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
7058
+ const typeParser = yield* service(TypeParser);
7059
+ const consoleSymbol = typeChecker.resolveName("console", void 0, ts.SymbolFlags.Value, false);
7060
+ if (!consoleSymbol) return;
7061
+ const nodeToVisit = [];
7062
+ const appendNodeToVisit = (node) => {
7063
+ nodeToVisit.push(node);
7064
+ return void 0;
7065
+ };
7066
+ ts.forEachChild(sourceFile, appendNodeToVisit);
7067
+ while (nodeToVisit.length > 0) {
7068
+ const node = nodeToVisit.shift();
7069
+ ts.forEachChild(node, appendNodeToVisit);
7070
+ if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression)) continue;
7071
+ const method = ts.idText(node.expression.name);
7072
+ const alternative = consoleMethodAlternatives[method];
7073
+ if (!alternative) continue;
7074
+ const symbol3 = typeChecker.getSymbolAtLocation(node.expression.expression);
7075
+ if (!symbol3) continue;
7076
+ if (typeCheckerUtils.resolveToGlobalSymbol(symbol3) !== consoleSymbol) continue;
7077
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
7078
+ if (inEffect !== checkInEffect) continue;
7079
+ report({
7080
+ location: node,
7081
+ messageText: checkInEffect ? `Prefer using ${alternative} instead of console.${method} inside Effect generators.` : `Prefer using ${alternative} instead of console.${method}.`,
7082
+ fixes: []
7083
+ });
7084
+ }
7085
+ });
7086
+ var globalConsoleInEffect = createDiagnostic({
7087
+ name: "globalConsoleInEffect",
7088
+ code: 56,
7089
+ description: "Warns when using console methods inside Effect generators instead of Effect.log/Logger",
7090
+ group: "effectNative",
7091
+ severity: "off",
7092
+ fixable: false,
7093
+ supportedEffect: ["v3", "v4"],
7094
+ apply: makeGlobalConsoleApply(true)
7095
+ });
7096
+
7097
+ // src/diagnostics/globalConsole.ts
7098
+ var globalConsole = createDiagnostic({
7099
+ name: "globalConsole",
7100
+ code: 60,
7101
+ description: "Warns when using console methods outside Effect generators instead of Effect.log/Logger",
7102
+ group: "effectNative",
7103
+ severity: "off",
7104
+ fixable: false,
7105
+ supportedEffect: ["v3", "v4"],
7106
+ apply: makeGlobalConsoleApply(false)
7107
+ });
7108
+
7109
+ // src/diagnostics/globalDateInEffect.ts
7110
+ var makeGlobalDateApply = (checkInEffect) => fn(`globalDate${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
7111
+ const ts = yield* service(TypeScriptApi);
7112
+ const typeChecker = yield* service(TypeCheckerApi);
7113
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
7114
+ const typeParser = yield* service(TypeParser);
7115
+ const dateSymbol = typeChecker.resolveName("Date", void 0, ts.SymbolFlags.Value, false);
7116
+ if (!dateSymbol) return;
7117
+ const nodeToVisit = [];
7118
+ const appendNodeToVisit = (node) => {
7119
+ nodeToVisit.push(node);
7120
+ return void 0;
7121
+ };
7122
+ ts.forEachChild(sourceFile, appendNodeToVisit);
7123
+ while (nodeToVisit.length > 0) {
7124
+ const node = nodeToVisit.shift();
7125
+ ts.forEachChild(node, appendNodeToVisit);
7126
+ let messageText;
7127
+ let objectNode;
7128
+ if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.idText(node.expression.name) === "now") {
7129
+ objectNode = node.expression.expression;
7130
+ messageText = checkInEffect ? "Prefer using Clock or DateTime from Effect instead of Date.now() inside Effect generators." : "Prefer using Clock or DateTime from Effect instead of Date.now().";
7131
+ } else if (ts.isNewExpression(node)) {
7132
+ objectNode = node.expression;
7133
+ messageText = checkInEffect ? "Prefer using DateTime from Effect instead of new Date() inside Effect generators." : "Prefer using DateTime from Effect instead of new Date().";
7134
+ }
7135
+ if (!messageText || !objectNode) continue;
7136
+ const symbol3 = typeChecker.getSymbolAtLocation(objectNode);
7137
+ if (!symbol3) continue;
7138
+ if (typeCheckerUtils.resolveToGlobalSymbol(symbol3) !== dateSymbol) continue;
7139
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
7140
+ if (inEffect !== checkInEffect) continue;
7141
+ report({ location: node, messageText, fixes: [] });
7142
+ }
7143
+ });
7144
+ var globalDateInEffect = createDiagnostic({
7145
+ name: "globalDateInEffect",
7146
+ code: 55,
7147
+ description: "Warns when using Date.now() or new Date() inside Effect generators instead of Clock/DateTime",
7148
+ group: "effectNative",
7149
+ severity: "off",
7150
+ fixable: false,
7151
+ supportedEffect: ["v3", "v4"],
7152
+ apply: makeGlobalDateApply(true)
7153
+ });
7154
+
7155
+ // src/diagnostics/globalDate.ts
7156
+ var globalDate = createDiagnostic({
7157
+ name: "globalDate",
7158
+ code: 59,
7159
+ description: "Warns when using Date.now() or new Date() outside Effect generators instead of Clock/DateTime",
7160
+ group: "effectNative",
7161
+ severity: "off",
7162
+ fixable: false,
7163
+ supportedEffect: ["v3", "v4"],
7164
+ apply: makeGlobalDateApply(false)
7165
+ });
7166
+
7021
7167
  // src/diagnostics/globalErrorInEffectCatch.ts
7022
7168
  var globalErrorInEffectCatch = createDiagnostic({
7023
7169
  name: "globalErrorInEffectCatch",
@@ -7137,46 +7283,186 @@ var globalErrorInEffectFailure = createDiagnostic({
7137
7283
  })
7138
7284
  });
7139
7285
 
7286
+ // src/diagnostics/globalFetchInEffect.ts
7287
+ var makeGlobalFetchApply = (checkInEffect) => fn(`globalFetch${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
7288
+ const ts = yield* service(TypeScriptApi);
7289
+ const typeChecker = yield* service(TypeCheckerApi);
7290
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
7291
+ const typeParser = yield* service(TypeParser);
7292
+ const fetchSymbol = typeChecker.resolveName("fetch", void 0, ts.SymbolFlags.Value, false);
7293
+ if (!fetchSymbol) return;
7294
+ const effectVersion = typeParser.supportedEffect();
7295
+ const packageName = effectVersion === "v3" ? "@effect/platform" : "effect/unstable/http";
7296
+ const messageText = checkInEffect ? `Prefer using HttpClient from ${packageName} instead of the global 'fetch' function inside Effect generators.` : `Prefer using HttpClient from ${packageName} instead of the global 'fetch' function.`;
7297
+ const nodeToVisit = [];
7298
+ const appendNodeToVisit = (node) => {
7299
+ nodeToVisit.push(node);
7300
+ return void 0;
7301
+ };
7302
+ ts.forEachChild(sourceFile, appendNodeToVisit);
7303
+ while (nodeToVisit.length > 0) {
7304
+ const node = nodeToVisit.shift();
7305
+ if (ts.isCallExpression(node)) {
7306
+ const symbol3 = typeChecker.getSymbolAtLocation(node.expression);
7307
+ if (symbol3 && typeCheckerUtils.resolveToGlobalSymbol(symbol3) === fetchSymbol) {
7308
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
7309
+ if (inEffect === checkInEffect) {
7310
+ report({
7311
+ location: node.expression,
7312
+ messageText,
7313
+ fixes: []
7314
+ });
7315
+ }
7316
+ }
7317
+ }
7318
+ ts.forEachChild(node, appendNodeToVisit);
7319
+ }
7320
+ });
7321
+ var globalFetchInEffect = createDiagnostic({
7322
+ name: "globalFetchInEffect",
7323
+ code: 63,
7324
+ description: "Warns when using the global fetch function inside Effect generators instead of the Effect HTTP client",
7325
+ group: "effectNative",
7326
+ severity: "off",
7327
+ fixable: false,
7328
+ supportedEffect: ["v3", "v4"],
7329
+ apply: makeGlobalFetchApply(true)
7330
+ });
7331
+
7140
7332
  // src/diagnostics/globalFetch.ts
7141
7333
  var globalFetch = createDiagnostic({
7142
7334
  name: "globalFetch",
7143
7335
  code: 53,
7144
- description: "Warns when using the global fetch function instead of the Effect HTTP client",
7336
+ description: "Warns when using the global fetch function outside Effect generators instead of the Effect HTTP client",
7145
7337
  group: "effectNative",
7146
7338
  severity: "off",
7147
7339
  fixable: false,
7148
7340
  supportedEffect: ["v3", "v4"],
7149
- apply: fn("globalFetch.apply")(function* (sourceFile, report) {
7150
- const ts = yield* service(TypeScriptApi);
7151
- const typeChecker = yield* service(TypeCheckerApi);
7152
- const typeParser = yield* service(TypeParser);
7153
- const fetchSymbol = typeChecker.resolveName("fetch", void 0, ts.SymbolFlags.Value, false);
7154
- if (!fetchSymbol) return;
7155
- const effectVersion = typeParser.supportedEffect();
7156
- const packageName = effectVersion === "v3" ? "@effect/platform" : "effect/unstable/http";
7157
- const messageText = `Prefer using HttpClient from ${packageName} instead of the global 'fetch' function.`;
7158
- const nodeToVisit = [];
7159
- const appendNodeToVisit = (node) => {
7160
- nodeToVisit.push(node);
7161
- return void 0;
7162
- };
7163
- ts.forEachChild(sourceFile, appendNodeToVisit);
7164
- while (nodeToVisit.length > 0) {
7165
- const node = nodeToVisit.shift();
7166
- if (ts.isCallExpression(node)) {
7167
- const symbol3 = typeChecker.getSymbolAtLocation(node.expression);
7168
- const resolvedSymbol = symbol3 && symbol3.flags & ts.SymbolFlags.Alias ? typeChecker.getAliasedSymbol(symbol3) : symbol3;
7169
- if (resolvedSymbol === fetchSymbol) {
7170
- report({
7171
- location: node.expression,
7172
- messageText,
7173
- fixes: []
7174
- });
7175
- }
7341
+ apply: makeGlobalFetchApply(false)
7342
+ });
7343
+
7344
+ // src/diagnostics/globalRandomInEffect.ts
7345
+ var makeGlobalRandomApply = (checkInEffect) => fn(`globalRandom${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
7346
+ const ts = yield* service(TypeScriptApi);
7347
+ const typeChecker = yield* service(TypeCheckerApi);
7348
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
7349
+ const typeParser = yield* service(TypeParser);
7350
+ const mathSymbol = typeChecker.resolveName("Math", void 0, ts.SymbolFlags.Value, false);
7351
+ if (!mathSymbol) return;
7352
+ const nodeToVisit = [];
7353
+ const appendNodeToVisit = (node) => {
7354
+ nodeToVisit.push(node);
7355
+ return void 0;
7356
+ };
7357
+ ts.forEachChild(sourceFile, appendNodeToVisit);
7358
+ while (nodeToVisit.length > 0) {
7359
+ const node = nodeToVisit.shift();
7360
+ ts.forEachChild(node, appendNodeToVisit);
7361
+ if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression) || ts.idText(node.expression.name) !== "random") continue;
7362
+ const symbol3 = typeChecker.getSymbolAtLocation(node.expression.expression);
7363
+ if (!symbol3) continue;
7364
+ if (typeCheckerUtils.resolveToGlobalSymbol(symbol3) !== mathSymbol) continue;
7365
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
7366
+ if (inEffect !== checkInEffect) continue;
7367
+ report({
7368
+ location: node,
7369
+ messageText: checkInEffect ? "Prefer using the Random service from Effect instead of Math.random() inside Effect generators." : "Prefer using the Random service from Effect instead of Math.random().",
7370
+ fixes: []
7371
+ });
7372
+ }
7373
+ });
7374
+ var globalRandomInEffect = createDiagnostic({
7375
+ name: "globalRandomInEffect",
7376
+ code: 57,
7377
+ description: "Warns when using Math.random() inside Effect generators instead of the Random service",
7378
+ group: "effectNative",
7379
+ severity: "off",
7380
+ fixable: false,
7381
+ supportedEffect: ["v3", "v4"],
7382
+ apply: makeGlobalRandomApply(true)
7383
+ });
7384
+
7385
+ // src/diagnostics/globalRandom.ts
7386
+ var globalRandom = createDiagnostic({
7387
+ name: "globalRandom",
7388
+ code: 61,
7389
+ description: "Warns when using Math.random() outside Effect generators instead of the Random service",
7390
+ group: "effectNative",
7391
+ severity: "off",
7392
+ fixable: false,
7393
+ supportedEffect: ["v3", "v4"],
7394
+ apply: makeGlobalRandomApply(false)
7395
+ });
7396
+
7397
+ // src/diagnostics/globalTimersInEffect.ts
7398
+ var timerAlternatives = {
7399
+ "setTimeout": {
7400
+ inEffect: "Prefer using Effect.sleep or Schedule from Effect instead of setTimeout inside Effect generators.",
7401
+ outsideEffect: "Prefer using Effect.sleep or Schedule from Effect instead of setTimeout."
7402
+ },
7403
+ "setInterval": {
7404
+ inEffect: "Prefer using Schedule or Effect.repeat from Effect instead of setInterval inside Effect generators.",
7405
+ outsideEffect: "Prefer using Schedule or Effect.repeat from Effect instead of setInterval."
7406
+ }
7407
+ };
7408
+ var makeGlobalTimersApply = (checkInEffect) => fn(`globalTimers${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
7409
+ const ts = yield* service(TypeScriptApi);
7410
+ const typeChecker = yield* service(TypeCheckerApi);
7411
+ const typeCheckerUtils = yield* service(TypeCheckerUtils);
7412
+ const typeParser = yield* service(TypeParser);
7413
+ const globalSymbols = /* @__PURE__ */ new Map();
7414
+ for (const name of Object.keys(timerAlternatives)) {
7415
+ const symbol3 = typeChecker.resolveName(name, void 0, ts.SymbolFlags.Value, false);
7416
+ if (symbol3) globalSymbols.set(name, symbol3);
7417
+ }
7418
+ if (globalSymbols.size === 0) return;
7419
+ const nodeToVisit = [];
7420
+ const appendNodeToVisit = (node) => {
7421
+ nodeToVisit.push(node);
7422
+ return void 0;
7423
+ };
7424
+ ts.forEachChild(sourceFile, appendNodeToVisit);
7425
+ while (nodeToVisit.length > 0) {
7426
+ const node = nodeToVisit.shift();
7427
+ ts.forEachChild(node, appendNodeToVisit);
7428
+ if (!ts.isCallExpression(node)) continue;
7429
+ const symbol3 = typeChecker.getSymbolAtLocation(node.expression);
7430
+ if (!symbol3) continue;
7431
+ const resolvedSymbol = typeCheckerUtils.resolveToGlobalSymbol(symbol3);
7432
+ let messageText;
7433
+ for (const [name, symbol4] of globalSymbols) {
7434
+ if (resolvedSymbol === symbol4) {
7435
+ messageText = checkInEffect ? timerAlternatives[name].inEffect : timerAlternatives[name].outsideEffect;
7436
+ break;
7176
7437
  }
7177
- ts.forEachChild(node, appendNodeToVisit);
7178
7438
  }
7179
- })
7439
+ if (!messageText) continue;
7440
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
7441
+ if (inEffect !== checkInEffect) continue;
7442
+ report({ location: node, messageText, fixes: [] });
7443
+ }
7444
+ });
7445
+ var globalTimersInEffect = createDiagnostic({
7446
+ name: "globalTimersInEffect",
7447
+ code: 58,
7448
+ description: "Warns when using setTimeout/setInterval inside Effect generators instead of Effect.sleep/Schedule",
7449
+ group: "effectNative",
7450
+ severity: "off",
7451
+ fixable: false,
7452
+ supportedEffect: ["v3", "v4"],
7453
+ apply: makeGlobalTimersApply(true)
7454
+ });
7455
+
7456
+ // src/diagnostics/globalTimers.ts
7457
+ var globalTimers = createDiagnostic({
7458
+ name: "globalTimers",
7459
+ code: 62,
7460
+ description: "Warns when using setTimeout/setInterval outside Effect generators instead of Effect.sleep/Schedule",
7461
+ group: "effectNative",
7462
+ severity: "off",
7463
+ fixable: false,
7464
+ supportedEffect: ["v3", "v4"],
7465
+ apply: makeGlobalTimersApply(false)
7180
7466
  });
7181
7467
 
7182
7468
  // src/diagnostics/importFromBarrel.ts
@@ -8241,8 +8527,8 @@ var missingReturnYieldStar = createDiagnostic({
8241
8527
  if (!type) continue;
8242
8528
  const maybeEffect = yield* option(typeParser.effectYieldableType(type, unwrapped.expression));
8243
8529
  if (!(isSome2(maybeEffect) && maybeEffect.value.A.flags & ts.TypeFlags.Never)) continue;
8244
- const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
8245
- if (!effectGen || scopeNode && scopeNode !== effectGen.generatorFunction) continue;
8530
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
8531
+ if (!inEffect) continue;
8246
8532
  const fix = [{
8247
8533
  fixName: "missingReturnYieldStar_fix",
8248
8534
  description: "Add return statement",
@@ -10705,11 +10991,8 @@ var preferSchemaOverJson = createDiagnostic({
10705
10991
  });
10706
10992
  const jsonMethodInEffectGen = fn("preferSchemaOverJson.jsonMethodInEffectGen")(
10707
10993
  function* (jsonCall) {
10708
- const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(jsonCall);
10709
- if (!effectGen || effectGen.body.statements.length === 0) {
10710
- return yield* TypeParserIssue.issue;
10711
- }
10712
- if (scopeNode && scopeNode !== effectGen.generatorFunction) {
10994
+ const { inEffect } = yield* typeParser.findEnclosingScopes(jsonCall);
10995
+ if (!inEffect) {
10713
10996
  return yield* TypeParserIssue.issue;
10714
10997
  }
10715
10998
  return jsonCall;
@@ -11125,9 +11408,8 @@ var schemaSyncInEffect = createDiagnostic({
11125
11408
  option
11126
11409
  );
11127
11410
  if (isNone2(isSchemaSyncCall)) continue;
11128
- const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
11129
- if (!effectGen || effectGen.body.statements.length === 0) continue;
11130
- if (scopeNode && scopeNode !== effectGen.generatorFunction) continue;
11411
+ const { inEffect } = yield* typeParser.findEnclosingScopes(node);
11412
+ if (!inEffect) continue;
11131
11413
  const nodeText = sourceFile.text.substring(
11132
11414
  ts.getTokenPosOfNode(node.expression, sourceFile),
11133
11415
  node.expression.end
@@ -11969,6 +12251,7 @@ var diagnostics = [
11969
12251
  unnecessaryPipe,
11970
12252
  genericEffectServices,
11971
12253
  globalFetch,
12254
+ globalFetchInEffect,
11972
12255
  returnEffectInGen,
11973
12256
  tryCatchInEffectGen,
11974
12257
  importFromBarrel,
@@ -12000,7 +12283,15 @@ var diagnostics = [
12000
12283
  preferSchemaOverJson,
12001
12284
  extendsNativeError,
12002
12285
  serviceNotAsClass,
12003
- nodeBuiltinImport
12286
+ nodeBuiltinImport,
12287
+ globalDate,
12288
+ globalDateInEffect,
12289
+ globalConsole,
12290
+ globalConsoleInEffect,
12291
+ globalRandom,
12292
+ globalRandomInEffect,
12293
+ globalTimers,
12294
+ globalTimersInEffect
12004
12295
  ];
12005
12296
 
12006
12297
  // src/transform.ts