@effect/language-service 0.75.0 → 0.75.1

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/cli.js CHANGED
@@ -30214,7 +30214,7 @@ var runMain3 = runMain2;
30214
30214
  // package.json
30215
30215
  var package_default = {
30216
30216
  name: "@effect/language-service",
30217
- version: "0.75.0",
30217
+ version: "0.75.1",
30218
30218
  publishConfig: {
30219
30219
  access: "public",
30220
30220
  directory: "dist"
@@ -30746,6 +30746,7 @@ var externals = (graph, config2 = {}) => {
30746
30746
  };
30747
30747
 
30748
30748
  // src/core/Nano.ts
30749
+ var debugPerformance = false;
30749
30750
  var NanoTag = class {
30750
30751
  constructor(key) {
30751
30752
  this.key = key;
@@ -30843,7 +30844,6 @@ var NanoFiber = class {
30843
30844
  _yielded = void 0;
30844
30845
  _services = {};
30845
30846
  _cache = {};
30846
- _perf = false;
30847
30847
  _lastSpan = "";
30848
30848
  runLoop(nano) {
30849
30849
  let current = nano;
@@ -30874,7 +30874,7 @@ var WithSpanProto = {
30874
30874
  ...PrimitiveProto,
30875
30875
  [evaluate2](fiber) {
30876
30876
  const [fa, name] = this[args2];
30877
- if (!fiber._perf) return fa;
30877
+ if (!debugPerformance) return fa;
30878
30878
  const previousSpan = fiber._lastSpan;
30879
30879
  fiber._lastSpan = name;
30880
30880
  const start4 = performance.now();
@@ -32119,6 +32119,26 @@ var getApplicableRefactors = fn2("LSP.getApplicableRefactors")(function* (refact
32119
32119
  }
32120
32120
  return effectRefactors;
32121
32121
  });
32122
+ function codeFixNameToFullyQualifiedName(name) {
32123
+ return `@effect/language-service/codefixes/${name}`;
32124
+ }
32125
+ var codeFixesToApplicableRefactor = fn2("LSP.codeFixesToApplicableRefactor")(function* (codeFixes, sourceFile, positionOrRange) {
32126
+ const effectRefactors = [];
32127
+ const range3 = typeof positionOrRange === "number" ? { pos: positionOrRange, end: positionOrRange } : positionOrRange;
32128
+ const inRangeCodeFixes = codeFixes.filter((_) => _.start <= range3.pos && _.end >= range3.end);
32129
+ for (const codeFix of inRangeCodeFixes) {
32130
+ effectRefactors.push({
32131
+ name: codeFixNameToFullyQualifiedName(codeFix.fixName),
32132
+ description: "Quick Fix: " + codeFix.description,
32133
+ actions: [{
32134
+ name: codeFixNameToFullyQualifiedName(codeFix.fixName),
32135
+ description: "Quick Fix: " + codeFix.description,
32136
+ kind: "refactor.rewrite.codeFixEffect." + codeFix.fixName
32137
+ }]
32138
+ });
32139
+ }
32140
+ return effectRefactors;
32141
+ });
32122
32142
  var getEditsForRefactor = fn2("LSP.getEditsForRefactor")(function* (refactors, sourceFile, positionOrRange, refactorName) {
32123
32143
  const refactor = refactors.find((refactor2) => refactorNameToFullyQualifiedName(refactor2.name) === refactorName);
32124
32144
  if (!refactor) {
@@ -32127,6 +32147,16 @@ var getEditsForRefactor = fn2("LSP.getEditsForRefactor")(function* (refactors, s
32127
32147
  const textRange = typeof positionOrRange === "number" ? { pos: positionOrRange, end: positionOrRange } : positionOrRange;
32128
32148
  return yield* refactor.apply(sourceFile, textRange);
32129
32149
  });
32150
+ var getEditsForCodeFixes = fn2("LSP.getEditsForCodeFixes")(function* (codeFixes, positionOrRange, refactorName) {
32151
+ const textRange = typeof positionOrRange === "number" ? { pos: positionOrRange, end: positionOrRange } : positionOrRange;
32152
+ const fixToRun = codeFixes.find(
32153
+ (_) => codeFixNameToFullyQualifiedName(_.fixName) === refactorName && _.start <= textRange.pos && _.end >= textRange.end
32154
+ );
32155
+ if (!fixToRun) {
32156
+ return yield* fail18(new RefactorNotApplicableError());
32157
+ }
32158
+ return fixToRun;
32159
+ });
32130
32160
  var getCompletionsAtPosition = fn2("LSP.getCompletionsAtPosition")(function* (completions, sourceFile, position, options3, formatCodeSettings) {
32131
32161
  let effectCompletions = [];
32132
32162
  for (const completion of completions) {
@@ -32210,7 +32240,7 @@ var createDiagnosticExecutor = fn2("LSP.createCommentDirectivesProcessor")(
32210
32240
  message: ts.DiagnosticCategory.Message,
32211
32241
  suggestion: ts.DiagnosticCategory.Suggestion
32212
32242
  };
32213
- const execute2 = (rule) => gen3(function* () {
32243
+ const execute2 = fn2("LSP.execute")(function* (rule) {
32214
32244
  const diagnostics3 = [];
32215
32245
  const codeFixes = [];
32216
32246
  const ruleNameLowered = rule.name.toLowerCase();
@@ -32991,6 +33021,9 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
32991
33021
  if (signatures.length !== 1) {
32992
33022
  return typeParserIssue("Covariant type has no call signature", type2);
32993
33023
  }
33024
+ if (signatures[0].typeParameters && signatures[0].typeParameters.length > 0) {
33025
+ return typeParserIssue("Invariant type should not have type parameters", type2);
33026
+ }
32994
33027
  return succeed17(typeChecker.getReturnTypeOfSignature(signatures[0]));
32995
33028
  }
32996
33029
  function contravariantTypeArgument(type2) {
@@ -32998,6 +33031,9 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
32998
33031
  if (signatures.length !== 1) {
32999
33032
  return typeParserIssue("Contravariant type has no call signature", type2);
33000
33033
  }
33034
+ if (signatures[0].typeParameters && signatures[0].typeParameters.length > 0) {
33035
+ return typeParserIssue("Invariant type should not have type parameters", type2);
33036
+ }
33001
33037
  return succeed17(typeCheckerUtils.getTypeParameterAtPosition(signatures[0], 0));
33002
33038
  }
33003
33039
  function invariantTypeArgument(type2) {
@@ -33005,6 +33041,9 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
33005
33041
  if (signatures.length !== 1) {
33006
33042
  return typeParserIssue("Invariant type has no call signature", type2);
33007
33043
  }
33044
+ if (signatures[0].typeParameters && signatures[0].typeParameters.length > 0) {
33045
+ return typeParserIssue("Invariant type should not have type parameters", type2);
33046
+ }
33008
33047
  return succeed17(typeChecker.getReturnTypeOfSignature(signatures[0]));
33009
33048
  }
33010
33049
  const pipeableType = cachedBy(
@@ -34916,25 +34955,27 @@ var generate = fn2("writeTagClassAccessors.generate")(function* (sourceFile, ser
34916
34955
  return succeed17(typeNode);
34917
34956
  })
34918
34957
  );
34919
- const proxySignature = (signature, atLocation2, className2) => gen3(function* () {
34920
- const signatureDeclaration = typeChecker.signatureToSignatureDeclaration(
34921
- signature,
34922
- ts.SyntaxKind.FunctionType,
34923
- atLocation2,
34924
- ts.NodeBuilderFlags.NoTruncation
34925
- );
34926
- if (!signatureDeclaration) return yield* fail18("error generating signature");
34927
- const returnType = yield* generateReturnType(
34928
- typeChecker.getReturnTypeOfSignature(signature),
34929
- atLocation2,
34930
- className2
34931
- );
34932
- return ts.factory.createFunctionTypeNode(
34933
- signatureDeclaration.typeParameters,
34934
- signatureDeclaration.parameters,
34935
- returnType
34936
- );
34937
- });
34958
+ const proxySignature = fn2("writeTagClassAccessors.proxySignature")(
34959
+ function* (signature, atLocation2, className2) {
34960
+ const signatureDeclaration = typeChecker.signatureToSignatureDeclaration(
34961
+ signature,
34962
+ ts.SyntaxKind.FunctionType,
34963
+ atLocation2,
34964
+ ts.NodeBuilderFlags.NoTruncation
34965
+ );
34966
+ if (!signatureDeclaration) return yield* fail18("error generating signature");
34967
+ const returnType = yield* generateReturnType(
34968
+ typeChecker.getReturnTypeOfSignature(signature),
34969
+ atLocation2,
34970
+ className2
34971
+ );
34972
+ return ts.factory.createFunctionTypeNode(
34973
+ signatureDeclaration.typeParameters,
34974
+ signatureDeclaration.parameters,
34975
+ returnType
34976
+ );
34977
+ }
34978
+ );
34938
34979
  for (const { property, propertyType } of involvedMembers) {
34939
34980
  const callSignatures = [];
34940
34981
  let propertyDeclaration = void 0;
@@ -35071,7 +35112,7 @@ var annotate3 = createCodegen({
35071
35112
  const tsUtils = yield* service2(TypeScriptUtils);
35072
35113
  const typeChecker = yield* service2(TypeCheckerApi);
35073
35114
  const typeCheckerUtils = yield* service2(TypeCheckerUtils);
35074
- const parse6 = (node) => gen3(function* () {
35115
+ const parse6 = fn2("annotate.parse")(function* (node) {
35075
35116
  let variableDeclarations = [];
35076
35117
  const result = [];
35077
35118
  if (ts.isVariableStatement(node)) {
@@ -35751,7 +35792,7 @@ var typeToSchema = createCodegen({
35751
35792
  new CodegenNotApplicableError("the typeToSchema codegen can be used only once per file")
35752
35793
  );
35753
35794
  }
35754
- const parse6 = (node) => gen3(function* () {
35795
+ const parse6 = fn2("typeToSchema.parse")(function* (node) {
35755
35796
  if (!ts.isTypeAliasDeclaration(node)) {
35756
35797
  return yield* fail18(
35757
35798
  new CodegenNotApplicableError(
@@ -36114,32 +36155,38 @@ var catchAllToMapError = createDiagnostic({
36114
36155
  return void 0;
36115
36156
  };
36116
36157
  const getEffectFailCallInfo = (body) => {
36117
- return gen3(function* () {
36118
- if (ts.isCallExpression(body)) {
36119
- const isFailCall = yield* pipe(
36120
- typeParser.isNodeReferenceToEffectModuleApi("fail")(body.expression),
36121
- orUndefined2
36122
- );
36123
- if (isFailCall && body.arguments.length >= 1) {
36124
- return { failCall: body, failArg: body.arguments[0] };
36125
- }
36126
- }
36127
- if (ts.isBlock(body)) {
36128
- const statements = body.statements;
36129
- if (statements.length === 1) {
36130
- const stmt = statements[0];
36131
- if (ts.isReturnStatement(stmt) && stmt.expression && ts.isCallExpression(stmt.expression)) {
36132
- const isFailCall = yield* pipe(
36133
- typeParser.isNodeReferenceToEffectModuleApi("fail")(stmt.expression.expression),
36134
- orUndefined2
36135
- );
36136
- if (isFailCall && stmt.expression.arguments.length >= 1) {
36137
- return { failCall: stmt.expression, failArg: stmt.expression.arguments[0] };
36138
- }
36158
+ if (ts.isCallExpression(body)) {
36159
+ return pipe(
36160
+ typeParser.isNodeReferenceToEffectModuleApi("fail")(body.expression),
36161
+ orUndefined2,
36162
+ map34((isFailCall) => {
36163
+ if (isFailCall && body.arguments.length >= 1) {
36164
+ return { failCall: body, failArg: body.arguments[0] };
36139
36165
  }
36166
+ return void 0;
36167
+ })
36168
+ );
36169
+ }
36170
+ if (ts.isBlock(body)) {
36171
+ const statements = body.statements;
36172
+ if (statements.length === 1) {
36173
+ const stmt = statements[0];
36174
+ if (ts.isReturnStatement(stmt) && stmt.expression && ts.isCallExpression(stmt.expression)) {
36175
+ const callExpr = stmt.expression;
36176
+ return pipe(
36177
+ typeParser.isNodeReferenceToEffectModuleApi("fail")(callExpr.expression),
36178
+ orUndefined2,
36179
+ map34((isFailCall) => {
36180
+ if (isFailCall && callExpr.arguments.length >= 1) {
36181
+ return { failCall: callExpr, failArg: callExpr.arguments[0] };
36182
+ }
36183
+ return void 0;
36184
+ })
36185
+ );
36140
36186
  }
36141
36187
  }
36142
- });
36188
+ }
36189
+ return void_8;
36143
36190
  };
36144
36191
  const flows = yield* typeParser.pipingFlows(true)(sourceFile);
36145
36192
  for (const flow2 of flows) {
@@ -36384,20 +36431,21 @@ var deterministicKeys = createDiagnostic({
36384
36431
  const typeScriptUtils = yield* service2(TypeScriptUtils);
36385
36432
  const options3 = yield* service2(LanguageServicePluginOptions);
36386
36433
  const parseExtendsCustom = cachedBy(
36387
- fn2("parseExtendsCustom")(function* (classDeclaration) {
36434
+ (classDeclaration) => {
36388
36435
  if (!options3.extendedKeyDetection) {
36389
- return yield* typeParserIssue("Extended key detection is disabled", void 0, classDeclaration);
36436
+ return TypeParserIssue.issue;
36390
36437
  }
36391
36438
  if (!classDeclaration.name) {
36392
- return yield* typeParserIssue("Class has no name", void 0, classDeclaration);
36439
+ return TypeParserIssue.issue;
36393
36440
  }
36394
36441
  if (!ts.isIdentifier(classDeclaration.name)) {
36395
- return yield* typeParserIssue("Class name is not an identifier", void 0, classDeclaration);
36442
+ return TypeParserIssue.issue;
36396
36443
  }
36397
36444
  const heritageClauses = classDeclaration.heritageClauses;
36398
36445
  if (!heritageClauses) {
36399
- return yield* typeParserIssue("Class has no heritage clauses", void 0, classDeclaration);
36446
+ return TypeParserIssue.issue;
36400
36447
  }
36448
+ const className = classDeclaration.name;
36401
36449
  const nodeToVisit2 = [...classDeclaration.heritageClauses];
36402
36450
  const appendNodeToVisit2 = (node) => {
36403
36451
  nodeToVisit2.push(node);
@@ -36418,7 +36466,7 @@ var deterministicKeys = createDiagnostic({
36418
36466
  const parameterSourceFile = typeScriptUtils.getSourceFileOfNode(declaration);
36419
36467
  const paramText = parameterSourceFile.text.substring(declaration.pos, declaration.end);
36420
36468
  if (paramText.toLowerCase().includes("@effect-identifier")) {
36421
- return { className: classDeclaration.name, keyStringLiteral: arg, target: "custom" };
36469
+ return succeed17({ className, keyStringLiteral: arg, target: "custom" });
36422
36470
  }
36423
36471
  }
36424
36472
  }
@@ -36427,12 +36475,8 @@ var deterministicKeys = createDiagnostic({
36427
36475
  }
36428
36476
  ts.forEachChild(node, appendNodeToVisit2);
36429
36477
  }
36430
- return yield* typeParserIssue(
36431
- "Class does not extend any custom pattern",
36432
- void 0,
36433
- classDeclaration
36434
- );
36435
- }),
36478
+ return TypeParserIssue.issue;
36479
+ },
36436
36480
  "deterministicKeys.parseExtendsCustom",
36437
36481
  (classDeclaration) => classDeclaration
36438
36482
  );
@@ -36711,7 +36755,7 @@ var effectFnOpportunity = createDiagnostic({
36711
36755
  }
36712
36756
  return false;
36713
36757
  };
36714
- const tryExtractWithSpanExpression = (expr) => gen3(function* () {
36758
+ const tryExtractWithSpanExpression = fn2("effectFnOpportunity.tryExtractWithSpanExpression")(function* (expr) {
36715
36759
  if (!ts.isCallExpression(expr)) return void 0;
36716
36760
  const callee = expr.expression;
36717
36761
  const isWithSpan = yield* pipe(
@@ -36723,7 +36767,9 @@ var effectFnOpportunity = createDiagnostic({
36723
36767
  if (expr.arguments.length === 0) return void 0;
36724
36768
  return expr.arguments[0];
36725
36769
  });
36726
- const tryParseGenOpportunity = (fnNode) => gen3(function* () {
36770
+ const tryParseGenOpportunity = fn2(
36771
+ "effectFnOpportunity.tryParseGenOpportunity"
36772
+ )(function* (fnNode) {
36727
36773
  const bodyExpression = getBodyExpression(fnNode);
36728
36774
  if (!bodyExpression) return yield* TypeParserIssue.issue;
36729
36775
  const { pipeArguments: pipeArguments2, subject } = yield* pipe(
@@ -36759,62 +36805,67 @@ var effectFnOpportunity = createDiagnostic({
36759
36805
  orElse15(() => succeed17(false))
36760
36806
  );
36761
36807
  };
36762
- const parseEffectFnOpportunityTarget = (node) => gen3(function* () {
36808
+ const parseEffectFnOpportunityTargetGen = fn2("effectFnOpportunity.parseEffectFnOpportunityTarget")(
36809
+ function* (node, returnType, traceName, nameIdentifier) {
36810
+ if (yield* isInsideEffectFn(node)) {
36811
+ return yield* TypeParserIssue.issue;
36812
+ }
36813
+ const unionMembers = typeCheckerUtils.unrollUnionMembers(returnType);
36814
+ yield* all9(...unionMembers.map((member) => typeParser.strictEffectType(member, node)));
36815
+ const opportunity = yield* pipe(
36816
+ tryParseGenOpportunity(node),
36817
+ orElse15(() => {
36818
+ if (ts.isArrowFunction(node) && !ts.isBlock(node.body)) {
36819
+ return TypeParserIssue.issue;
36820
+ }
36821
+ const body = ts.isArrowFunction(node) ? node.body : node.body;
36822
+ if (!body || !ts.isBlock(body) || body.statements.length <= 5) {
36823
+ return TypeParserIssue.issue;
36824
+ }
36825
+ return succeed17({
36826
+ effectModuleName: sourceEffectModuleName,
36827
+ pipeArguments: [],
36828
+ generatorFunction: void 0,
36829
+ explicitTraceExpression: void 0
36830
+ });
36831
+ })
36832
+ );
36833
+ return {
36834
+ node,
36835
+ nameIdentifier,
36836
+ effectModuleName: opportunity.effectModuleName,
36837
+ inferredTraceName: traceName,
36838
+ explicitTraceExpression: opportunity.explicitTraceExpression,
36839
+ pipeArguments: opportunity.pipeArguments,
36840
+ generatorFunction: opportunity.generatorFunction,
36841
+ hasParamsInPipeArgs: areParametersReferencedIn(node, opportunity.pipeArguments)
36842
+ };
36843
+ }
36844
+ );
36845
+ const parseEffectFnOpportunityTarget = (node) => {
36763
36846
  if (!ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isFunctionDeclaration(node)) {
36764
- return yield* TypeParserIssue.issue;
36847
+ return TypeParserIssue.issue;
36765
36848
  }
36766
36849
  if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.asteriskToken) {
36767
- return yield* TypeParserIssue.issue;
36850
+ return TypeParserIssue.issue;
36768
36851
  }
36769
36852
  if (ts.isFunctionExpression(node) && node.name) {
36770
- return yield* TypeParserIssue.issue;
36853
+ return TypeParserIssue.issue;
36771
36854
  }
36772
36855
  if (node.type) {
36773
- return yield* TypeParserIssue.issue;
36774
- }
36775
- if (yield* isInsideEffectFn(node)) {
36776
- return yield* TypeParserIssue.issue;
36856
+ return TypeParserIssue.issue;
36777
36857
  }
36778
36858
  const functionType = typeChecker.getTypeAtLocation(node);
36779
- if (!functionType) return yield* TypeParserIssue.issue;
36859
+ if (!functionType) return TypeParserIssue.issue;
36780
36860
  const callSignatures = typeChecker.getSignaturesOfType(functionType, ts.SignatureKind.Call);
36781
- if (callSignatures.length !== 1) return yield* TypeParserIssue.issue;
36861
+ if (callSignatures.length !== 1) return TypeParserIssue.issue;
36782
36862
  const signature = callSignatures[0];
36783
36863
  const returnType = typeChecker.getReturnTypeOfSignature(signature);
36784
- const unionMembers = typeCheckerUtils.unrollUnionMembers(returnType);
36785
- yield* all9(...unionMembers.map((member) => typeParser.strictEffectType(member, node)));
36786
36864
  const nameIdentifier = getNameIdentifier(node);
36787
36865
  const traceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
36788
- if (!traceName) return yield* TypeParserIssue.issue;
36789
- const opportunity = yield* pipe(
36790
- tryParseGenOpportunity(node),
36791
- orElse15(() => {
36792
- if (ts.isArrowFunction(node) && !ts.isBlock(node.body)) {
36793
- return TypeParserIssue.issue;
36794
- }
36795
- const body = ts.isArrowFunction(node) ? node.body : node.body;
36796
- if (!body || !ts.isBlock(body) || body.statements.length <= 5) {
36797
- return TypeParserIssue.issue;
36798
- }
36799
- return succeed17({
36800
- effectModuleName: sourceEffectModuleName,
36801
- pipeArguments: [],
36802
- generatorFunction: void 0,
36803
- explicitTraceExpression: void 0
36804
- });
36805
- })
36806
- );
36807
- return {
36808
- node,
36809
- nameIdentifier,
36810
- effectModuleName: opportunity.effectModuleName,
36811
- inferredTraceName: traceName,
36812
- explicitTraceExpression: opportunity.explicitTraceExpression,
36813
- pipeArguments: opportunity.pipeArguments,
36814
- generatorFunction: opportunity.generatorFunction,
36815
- hasParamsInPipeArgs: areParametersReferencedIn(node, opportunity.pipeArguments)
36816
- };
36817
- });
36866
+ if (!traceName) return TypeParserIssue.issue;
36867
+ return parseEffectFnOpportunityTargetGen(node, returnType, traceName, nameIdentifier);
36868
+ };
36818
36869
  const getFunctionBodyBlock = (node) => {
36819
36870
  if (ts.isArrowFunction(node)) {
36820
36871
  if (ts.isBlock(node.body)) {
@@ -37055,7 +37106,7 @@ var effectInVoidSuccess = createDiagnostic({
37055
37106
  );
37056
37107
  return { voidedEffect };
37057
37108
  }
37058
- return yield* fail18(typeParserIssue("expectedEffect success is not void"));
37109
+ return yield* TypeParserIssue.issue;
37059
37110
  });
37060
37111
  const entries3 = typeCheckerUtils.expectedAndRealType(sourceFile);
37061
37112
  for (const [node, expectedType, valueNode, realType] of entries3) {
@@ -38912,73 +38963,99 @@ var preferSchemaOverJson = createDiagnostic({
38912
38963
  apply: fn2("preferSchemaOverJson.apply")(function* (sourceFile, report) {
38913
38964
  const ts = yield* service2(TypeScriptApi);
38914
38965
  const typeParser = yield* service2(TypeParser);
38915
- const parseJsonMethod = (node) => gen3(function* () {
38916
- if (!ts.isCallExpression(node)) return yield* fail18("node is not a call expression");
38917
- const expression = node.expression;
38918
- if (!ts.isPropertyAccessExpression(expression)) return yield* fail18("expression is not a property access");
38919
- const objectExpr = expression.expression;
38920
- const methodName = ts.idText(expression.name);
38921
- if (!ts.isIdentifier(objectExpr) || ts.idText(objectExpr) !== "JSON") {
38922
- return yield* fail18("object is not JSON");
38966
+ const isJsonCall = (node) => ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.expression) && ts.idText(node.expression.expression) === "JSON" && (ts.idText(node.expression.name) === "parse" || ts.idText(node.expression.name) === "stringify");
38967
+ const findEnclosingEffectTry = (jsonCall) => {
38968
+ const parent = jsonCall.parent;
38969
+ let lazy;
38970
+ if (ts.isArrowFunction(parent) && parent.body === jsonCall && parent.parameters.length === 0 && (!parent.typeParameters || parent.typeParameters.length === 0)) {
38971
+ lazy = parent;
38972
+ }
38973
+ if (!lazy && ts.isReturnStatement(parent) && parent.expression === jsonCall) {
38974
+ const block = parent.parent;
38975
+ if (ts.isBlock(block) && block.statements.length === 1) {
38976
+ const fn3 = block.parent;
38977
+ if ((ts.isArrowFunction(fn3) || ts.isFunctionExpression(fn3)) && fn3.parameters.length === 0 && (!fn3.typeParameters || fn3.typeParameters.length === 0)) {
38978
+ lazy = fn3;
38979
+ }
38980
+ }
38923
38981
  }
38924
- if (methodName !== "parse" && methodName !== "stringify") {
38925
- return yield* fail18("method is not parse or stringify");
38982
+ if (!lazy) return void 0;
38983
+ const lazyParent = lazy.parent;
38984
+ if (ts.isCallExpression(lazyParent) && lazyParent.arguments.length > 0 && lazyParent.arguments[0] === lazy) {
38985
+ return lazyParent;
38926
38986
  }
38927
- return { node, methodName };
38928
- });
38929
- const effectTrySimple = (node) => gen3(function* () {
38930
- if (!ts.isCallExpression(node)) return yield* fail18("node is not a call expression");
38987
+ if (ts.isPropertyAssignment(lazyParent) && ts.isIdentifier(lazyParent.name) && ts.idText(lazyParent.name) === "try") {
38988
+ const objLiteral = lazyParent.parent;
38989
+ if (ts.isObjectLiteralExpression(objLiteral)) {
38990
+ const callExpr = objLiteral.parent;
38991
+ if (ts.isCallExpression(callExpr) && callExpr.arguments.length > 0 && callExpr.arguments[0] === objLiteral) {
38992
+ return callExpr;
38993
+ }
38994
+ }
38995
+ }
38996
+ return void 0;
38997
+ };
38998
+ const jsonCalls = [];
38999
+ const collectJsonCalls = (node) => {
39000
+ if (isJsonCall(node)) {
39001
+ jsonCalls.push(node);
39002
+ }
39003
+ ts.forEachChild(node, collectJsonCalls);
39004
+ };
39005
+ ts.forEachChild(sourceFile, collectJsonCalls);
39006
+ if (jsonCalls.length === 0) return;
39007
+ const effectTrySimple = fn2("preferSchemaOverJson.effectTrySimple")(function* (node) {
38931
39008
  yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
38932
- if (node.arguments.length === 0) return yield* fail18("Effect.try has no arguments");
39009
+ if (node.arguments.length === 0) return yield* TypeParserIssue.issue;
38933
39010
  const lazyFn = yield* typeParser.lazyExpression(node.arguments[0]);
38934
- const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
38935
- return { node: jsonMethod.node, methodName: jsonMethod.methodName };
39011
+ if (!isJsonCall(lazyFn.expression)) return yield* TypeParserIssue.issue;
39012
+ return lazyFn.expression;
38936
39013
  });
38937
- const effectTryObject = (node) => gen3(function* () {
38938
- if (!ts.isCallExpression(node)) return yield* fail18("node is not a call expression");
39014
+ const effectTryObject = fn2("preferSchemaOverJson.effectTryObject")(function* (node) {
38939
39015
  yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
38940
- if (node.arguments.length === 0) return yield* fail18("Effect.try has no arguments");
39016
+ if (node.arguments.length === 0) return yield* TypeParserIssue.issue;
38941
39017
  const arg = node.arguments[0];
38942
- if (!ts.isObjectLiteralExpression(arg)) return yield* fail18("argument is not an object literal");
39018
+ if (!ts.isObjectLiteralExpression(arg)) return yield* TypeParserIssue.issue;
38943
39019
  const tryProp = arg.properties.find(
38944
39020
  (p3) => ts.isPropertyAssignment(p3) && ts.isIdentifier(p3.name) && ts.idText(p3.name) === "try"
38945
39021
  );
38946
- if (!tryProp) return yield* fail18("object has no 'try' property");
39022
+ if (!tryProp) return yield* TypeParserIssue.issue;
38947
39023
  const lazyFn = yield* typeParser.lazyExpression(tryProp.initializer);
38948
- const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
38949
- return { node: jsonMethod.node, methodName: jsonMethod.methodName };
39024
+ if (!isJsonCall(lazyFn.expression)) return yield* TypeParserIssue.issue;
39025
+ return lazyFn.expression;
38950
39026
  });
38951
- const jsonMethodInEffectGen = (node) => gen3(function* () {
38952
- const jsonMethod = yield* parseJsonMethod(node);
38953
- const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
38954
- if (!effectGen || effectGen.body.statements.length === 0) {
38955
- return yield* fail18("not inside an Effect generator");
39027
+ const jsonMethodInEffectGen = fn2("preferSchemaOverJson.jsonMethodInEffectGen")(
39028
+ function* (jsonCall) {
39029
+ const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(jsonCall);
39030
+ if (!effectGen || effectGen.body.statements.length === 0) {
39031
+ return yield* TypeParserIssue.issue;
39032
+ }
39033
+ if (scopeNode && scopeNode !== effectGen.generatorFunction) {
39034
+ return yield* TypeParserIssue.issue;
39035
+ }
39036
+ return jsonCall;
38956
39037
  }
38957
- if (scopeNode && scopeNode !== effectGen.generatorFunction) {
38958
- return yield* fail18("inside a nested function scope");
39038
+ );
39039
+ for (const jsonCall of jsonCalls) {
39040
+ const effectTryCall = findEnclosingEffectTry(jsonCall);
39041
+ let match18;
39042
+ if (effectTryCall) {
39043
+ match18 = yield* pipe(
39044
+ firstSuccessOf2([
39045
+ effectTrySimple(effectTryCall),
39046
+ effectTryObject(effectTryCall)
39047
+ ]),
39048
+ option5
39049
+ );
39050
+ } else {
39051
+ match18 = yield* pipe(
39052
+ jsonMethodInEffectGen(jsonCall),
39053
+ option5
39054
+ );
38959
39055
  }
38960
- return { node: jsonMethod.node, methodName: jsonMethod.methodName };
38961
- });
38962
- const nodeToVisit = [];
38963
- const appendNodeToVisit = (node) => {
38964
- nodeToVisit.push(node);
38965
- return void 0;
38966
- };
38967
- ts.forEachChild(sourceFile, appendNodeToVisit);
38968
- while (nodeToVisit.length > 0) {
38969
- const node = nodeToVisit.shift();
38970
- ts.forEachChild(node, appendNodeToVisit);
38971
- const match18 = yield* pipe(
38972
- firstSuccessOf2([
38973
- effectTrySimple(node),
38974
- effectTryObject(node),
38975
- jsonMethodInEffectGen(node)
38976
- ]),
38977
- option5
38978
- );
38979
39056
  if (isSome2(match18)) {
38980
39057
  report({
38981
- location: match18.value.node,
39058
+ location: match18.value,
38982
39059
  messageText: "Consider using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify",
38983
39060
  fixes: []
38984
39061
  });
@@ -39622,19 +39699,24 @@ var strictEffectProvide = createDiagnostic({
39622
39699
  const ts = yield* service2(TypeScriptApi);
39623
39700
  const typeCheckerUtils = yield* service2(TypeCheckerUtils);
39624
39701
  const typeParser = yield* service2(TypeParser);
39625
- const parseEffectProvideWithLayer = (node) => gen3(function* () {
39702
+ const parseEffectProvideWithLayerGen = fn2("strictEffectProvide.parseEffectProvideWithLayer")(
39703
+ function* (node) {
39704
+ yield* typeParser.isNodeReferenceToEffectModuleApi("provide")(node.expression);
39705
+ return yield* firstSuccessOf2(
39706
+ node.arguments.map((arg) => {
39707
+ const argType = typeCheckerUtils.getTypeAtLocation(arg);
39708
+ if (!argType) return typeParserIssue("Could not get argument type");
39709
+ return typeParser.layerType(argType, arg);
39710
+ })
39711
+ );
39712
+ }
39713
+ );
39714
+ const parseEffectProvideWithLayer = (node) => {
39626
39715
  if (!ts.isCallExpression(node) || node.arguments.length === 0) {
39627
- return yield* typeParserIssue("Not an Effect.provide call");
39628
- }
39629
- yield* typeParser.isNodeReferenceToEffectModuleApi("provide")(node.expression);
39630
- return yield* firstSuccessOf2(
39631
- node.arguments.map((arg) => {
39632
- const argType = typeCheckerUtils.getTypeAtLocation(arg);
39633
- if (!argType) return typeParserIssue("Could not get argument type");
39634
- return typeParser.layerType(argType, arg);
39635
- })
39636
- );
39637
- });
39716
+ return TypeParserIssue.issue;
39717
+ }
39718
+ return parseEffectProvideWithLayerGen(node);
39719
+ };
39638
39720
  const nodeToVisit = [];
39639
39721
  const appendNodeToVisit = (node) => {
39640
39722
  nodeToVisit.push(node);