@effect/language-service 0.84.2 → 0.84.3
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 +127 -106
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +80 -59
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +80 -59
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +80 -59
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -4130,6 +4130,14 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
4130
4130
|
),
|
|
4131
4131
|
([A, E, R]) => ({ A, E, R })
|
|
4132
4132
|
);
|
|
4133
|
+
const streamVarianceStruct = (type, atLocation) => map5(
|
|
4134
|
+
all(
|
|
4135
|
+
varianceStructCovariantType(type, atLocation, "_A"),
|
|
4136
|
+
varianceStructCovariantType(type, atLocation, "_E"),
|
|
4137
|
+
varianceStructCovariantType(type, atLocation, "_R")
|
|
4138
|
+
),
|
|
4139
|
+
([A, E, R]) => ({ A, E, R })
|
|
4140
|
+
);
|
|
4133
4141
|
const layerVarianceStruct = (type, atLocation) => map5(
|
|
4134
4142
|
all(
|
|
4135
4143
|
varianceStructContravariantType(type, atLocation, "_ROut"),
|
|
@@ -4176,6 +4184,21 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
4176
4184
|
"TypeParser.strictEffectType",
|
|
4177
4185
|
(type) => type
|
|
4178
4186
|
);
|
|
4187
|
+
const streamType = cachedBy(
|
|
4188
|
+
fn("TypeParser.streamType")(function* (type, atLocation) {
|
|
4189
|
+
if (supportedEffect() === "v3") {
|
|
4190
|
+
return yield* effectType(type, atLocation);
|
|
4191
|
+
}
|
|
4192
|
+
const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/Stream");
|
|
4193
|
+
if (!typeIdSymbol) {
|
|
4194
|
+
return yield* typeParserIssue("Type is not a stream", type, atLocation);
|
|
4195
|
+
}
|
|
4196
|
+
const typeIdType = typeChecker.getTypeOfSymbolAtLocation(typeIdSymbol, atLocation);
|
|
4197
|
+
return yield* streamVarianceStruct(typeIdType, atLocation);
|
|
4198
|
+
}),
|
|
4199
|
+
"TypeParser.streamType",
|
|
4200
|
+
(type) => type
|
|
4201
|
+
);
|
|
4179
4202
|
const isEffectTypeSourceFile = cachedBy(
|
|
4180
4203
|
fn("TypeParser.isEffectTypeSourceFile")(function* (sourceFile) {
|
|
4181
4204
|
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
@@ -5911,6 +5934,7 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5911
5934
|
isServiceMapTypeSourceFile,
|
|
5912
5935
|
isNodeReferenceToServiceMapModuleApi,
|
|
5913
5936
|
effectType,
|
|
5937
|
+
streamType,
|
|
5914
5938
|
strictEffectType,
|
|
5915
5939
|
layerType,
|
|
5916
5940
|
fiberType,
|
|
@@ -7369,7 +7393,7 @@ var catchAllToMapError = createDiagnostic({
|
|
|
7369
7393
|
const { failArg, failCall } = failCallInfo;
|
|
7370
7394
|
report({
|
|
7371
7395
|
location: transformation.callee,
|
|
7372
|
-
messageText:
|
|
7396
|
+
messageText: `\`Effect.mapError\` expresses the same error-type transformation more directly than \`Effect.${catchAllName}\` followed by \`Effect.fail\`.`,
|
|
7373
7397
|
fixes: [{
|
|
7374
7398
|
fixName: "catchAllToMapError_fix",
|
|
7375
7399
|
description: "Replace with Effect.mapError",
|
|
@@ -7433,7 +7457,7 @@ var catchUnfailableEffect = createDiagnostic({
|
|
|
7433
7457
|
if (E.flags & ts.TypeFlags.Never) {
|
|
7434
7458
|
report({
|
|
7435
7459
|
location: transformation.callee,
|
|
7436
|
-
messageText:
|
|
7460
|
+
messageText: "The previous Effect does not fail, so this error-handling branch will never run.",
|
|
7437
7461
|
fixes: []
|
|
7438
7462
|
});
|
|
7439
7463
|
}
|
|
@@ -7496,7 +7520,7 @@ var classSelfMismatch = createDiagnostic({
|
|
|
7496
7520
|
if (actualName !== expectedName) {
|
|
7497
7521
|
report({
|
|
7498
7522
|
location: selfTypeNode,
|
|
7499
|
-
messageText: `Self type parameter should be
|
|
7523
|
+
messageText: `The \`Self\` type parameter for this class should be \`${expectedName}\`.`,
|
|
7500
7524
|
fixes: [{
|
|
7501
7525
|
fixName: "classSelfMismatch_fix",
|
|
7502
7526
|
description: `Replace '${actualName}' with '${expectedName}'`,
|
|
@@ -7620,7 +7644,7 @@ var deterministicKeys = createDiagnostic({
|
|
|
7620
7644
|
if (actualIdentifier !== expectedKey) {
|
|
7621
7645
|
report({
|
|
7622
7646
|
location: keyStringLiteral,
|
|
7623
|
-
messageText: `
|
|
7647
|
+
messageText: `This key does not match the deterministic key for this declaration. The expected key is \`${expectedKey}\`.`,
|
|
7624
7648
|
fixes: [{
|
|
7625
7649
|
fixName: "deterministicKeys_fix",
|
|
7626
7650
|
description: `Replace '${actualIdentifier}' with '${expectedKey}'`,
|
|
@@ -7659,9 +7683,8 @@ var duplicatePackage = createDiagnostic({
|
|
|
7659
7683
|
const versions = Object.keys(resolvedPackages[packageName]);
|
|
7660
7684
|
report({
|
|
7661
7685
|
location: sourceFile.statements[0],
|
|
7662
|
-
messageText: `
|
|
7663
|
-
|
|
7664
|
-
If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
|
|
7686
|
+
messageText: `Multiple versions of package \`${packageName}\` were detected: ${versions.join(", ")}. Package duplication can change runtime identity and type equality across Effect modules.
|
|
7687
|
+
If this is intentional, set the LSP config \`allowedDuplicatedPackages\` to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
|
|
7665
7688
|
|
|
7666
7689
|
${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
|
|
7667
7690
|
fixes: []
|
|
@@ -7769,7 +7792,7 @@ var effectFnIife = createDiagnostic({
|
|
|
7769
7792
|
const traceExpressionText = traceExpression ? sourceFile.text.slice(traceExpression.pos, traceExpression.end) : void 0;
|
|
7770
7793
|
report({
|
|
7771
7794
|
location: node,
|
|
7772
|
-
messageText:
|
|
7795
|
+
messageText: `\`${effectModuleName}.${kind}\` returns a reusable function that can take arguments, but it is invoked immediately here. \`Effect.gen\` represents the immediate-use form for this pattern${traceExpressionText ? ` with \`Effect.withSpan(${traceExpressionText})\` piped at the end to maintain tracing spans` : ``}.`,
|
|
7773
7796
|
fixes
|
|
7774
7797
|
});
|
|
7775
7798
|
}
|
|
@@ -7854,7 +7877,7 @@ var effectFnImplicitAny = createDiagnostic({
|
|
|
7854
7877
|
const parameterName = getParameterName(ts, parameter.name);
|
|
7855
7878
|
report({
|
|
7856
7879
|
location: parameter.name,
|
|
7857
|
-
messageText: `Parameter
|
|
7880
|
+
messageText: `Parameter \`${parameterName}\` implicitly has type \`any\` in \`Effect.fn\`, \`Effect.fnUntraced\`, or \`Effect.fnUntracedEager\`. No parameter type is available from an explicit annotation or contextual function type.`,
|
|
7858
7881
|
fixes: []
|
|
7859
7882
|
});
|
|
7860
7883
|
}
|
|
@@ -8450,7 +8473,7 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
8450
8473
|
const expectedSignature = generateExpectedSignature();
|
|
8451
8474
|
report({
|
|
8452
8475
|
location: nameIdentifier ?? targetNode,
|
|
8453
|
-
messageText: `
|
|
8476
|
+
messageText: `This expression can be rewritten in the reusable function form \`${expectedSignature}\`.`,
|
|
8454
8477
|
fixes
|
|
8455
8478
|
});
|
|
8456
8479
|
}
|
|
@@ -8662,7 +8685,7 @@ var effectMapVoid = createDiagnostic({
|
|
|
8662
8685
|
if (isNone2(match2)) continue;
|
|
8663
8686
|
report({
|
|
8664
8687
|
location: node.expression,
|
|
8665
|
-
messageText: "
|
|
8688
|
+
messageText: "This expression discards the success value through mapping. `Effect.asVoid` represents that form directly.",
|
|
8666
8689
|
fixes: [{
|
|
8667
8690
|
fixName: "effectMapVoid_fix",
|
|
8668
8691
|
description: "Replace with Effect.asVoid",
|
|
@@ -8717,7 +8740,7 @@ var effectSucceedWithVoid = createDiagnostic({
|
|
|
8717
8740
|
if (!tsUtils.isVoidExpression(argument)) continue;
|
|
8718
8741
|
report({
|
|
8719
8742
|
location: node,
|
|
8720
|
-
messageText: "Effect.void
|
|
8743
|
+
messageText: "`Effect.void` represents the same outcome as `Effect.succeed(undefined)` or `Effect.succeed(void 0)`.",
|
|
8721
8744
|
fixes: [{
|
|
8722
8745
|
fixName: "effectSucceedWithVoid_fix",
|
|
8723
8746
|
description: "Replace with Effect.void",
|
|
@@ -8779,7 +8802,7 @@ var extendsNativeError = createDiagnostic({
|
|
|
8779
8802
|
if (isNativeError) {
|
|
8780
8803
|
report({
|
|
8781
8804
|
location: node.name ?? typeExpression,
|
|
8782
|
-
messageText: "
|
|
8805
|
+
messageText: "This class extends the native `Error` type directly. Untagged native errors lose distinction in the Effect failure channel.",
|
|
8783
8806
|
fixes: []
|
|
8784
8807
|
});
|
|
8785
8808
|
}
|
|
@@ -8824,7 +8847,12 @@ var floatingEffect = createDiagnostic({
|
|
|
8824
8847
|
if (!isFloatingExpression(node)) continue;
|
|
8825
8848
|
const type = typeCheckerUtils.getTypeAtLocation(node.expression);
|
|
8826
8849
|
if (!type) continue;
|
|
8827
|
-
const effect = yield* option(
|
|
8850
|
+
const effect = yield* option(
|
|
8851
|
+
pipe(
|
|
8852
|
+
typeParser.effectType(type, node.expression),
|
|
8853
|
+
orElse2(() => typeParser.streamType(type, node.expression))
|
|
8854
|
+
)
|
|
8855
|
+
);
|
|
8828
8856
|
if (isSome2(effect)) {
|
|
8829
8857
|
const allowedFloatingEffects = yield* pipe(
|
|
8830
8858
|
typeParser.fiberType(type, node.expression),
|
|
@@ -8833,10 +8861,9 @@ var floatingEffect = createDiagnostic({
|
|
|
8833
8861
|
);
|
|
8834
8862
|
if (isNone2(allowedFloatingEffects)) {
|
|
8835
8863
|
const isStrictEffect = yield* option(typeParser.strictEffectType(type, node.expression));
|
|
8836
|
-
const name = isSome2(isStrictEffect) ? "Effect" : "Effect-able " + typeChecker.typeToString(type);
|
|
8837
8864
|
report({
|
|
8838
8865
|
location: node,
|
|
8839
|
-
messageText:
|
|
8866
|
+
messageText: isSome2(isStrictEffect) ? "This Effect value is neither yielded nor used in an assignment." : `This Effect-able \`${typeChecker.typeToString(type)}\` value is neither yielded nor assigned to a variable.`,
|
|
8840
8867
|
fixes: []
|
|
8841
8868
|
});
|
|
8842
8869
|
}
|
|
@@ -8931,7 +8958,7 @@ var makeGlobalConsoleApply = (checkInEffect) => fn(`globalConsole${checkInEffect
|
|
|
8931
8958
|
if (inEffect !== checkInEffect) continue;
|
|
8932
8959
|
report({
|
|
8933
8960
|
location: node,
|
|
8934
|
-
messageText: checkInEffect ? `
|
|
8961
|
+
messageText: checkInEffect ? `This Effect code uses \`console.${method}\`, logging in Effect code is represented through \`${alternative}\`.` : `This code uses \`console.${method}\`, the corresponding Effect logging API is \`${alternative}\`.`,
|
|
8935
8962
|
fixes: []
|
|
8936
8963
|
});
|
|
8937
8964
|
}
|
|
@@ -8980,10 +9007,10 @@ var makeGlobalDateApply = (checkInEffect) => fn(`globalDate${checkInEffect ? "In
|
|
|
8980
9007
|
let objectNode;
|
|
8981
9008
|
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.idText(node.expression.name) === "now") {
|
|
8982
9009
|
objectNode = node.expression.expression;
|
|
8983
|
-
messageText = checkInEffect ? "
|
|
9010
|
+
messageText = checkInEffect ? "This Effect code uses `Date.now()`, time access in Effect code is represented through `Clock` from Effect." : "This code uses `Date.now()`, time access is represented through `Clock` from Effect.";
|
|
8984
9011
|
} else if (ts.isNewExpression(node)) {
|
|
8985
9012
|
objectNode = node.expression;
|
|
8986
|
-
messageText = checkInEffect ? "
|
|
9013
|
+
messageText = checkInEffect ? "This Effect code constructs `new Date()`, date values in Effect code are represented through `DateTime` from Effect." : "This code constructs `new Date()`, date values are represented through `DateTime` from Effect.";
|
|
8987
9014
|
}
|
|
8988
9015
|
if (!messageText || !objectNode) continue;
|
|
8989
9016
|
const symbol3 = typeChecker.getSymbolAtLocation(objectNode);
|
|
@@ -9066,7 +9093,7 @@ var globalErrorInEffectCatch = createDiagnostic({
|
|
|
9066
9093
|
);
|
|
9067
9094
|
report({
|
|
9068
9095
|
location: node.expression,
|
|
9069
|
-
messageText: `The
|
|
9096
|
+
messageText: `The \`catch\` callback in \`${nodeText}\` returns the global \`Error\` type. Untagged errors merge together in the Effect error channel and lose type-level distinction; a tagged error preserves that distinction and can wrap the original error in a \`cause\` property.`,
|
|
9070
9097
|
fixes: []
|
|
9071
9098
|
});
|
|
9072
9099
|
}
|
|
@@ -9146,7 +9173,7 @@ var makeGlobalFetchApply = (checkInEffect) => fn(`globalFetch${checkInEffect ? "
|
|
|
9146
9173
|
if (!fetchSymbol) return;
|
|
9147
9174
|
const effectVersion = typeParser.supportedEffect();
|
|
9148
9175
|
const packageName = effectVersion === "v3" ? "@effect/platform" : "effect/unstable/http";
|
|
9149
|
-
const messageText = checkInEffect ? `
|
|
9176
|
+
const messageText = checkInEffect ? `This Effect code calls the global \`fetch\` function, HTTP requests in Effect code are represented through \`HttpClient\` from \`${packageName}\`.` : `This code uses the global \`fetch\` function, HTTP requests are represented through \`HttpClient\` from \`${packageName}\`.`;
|
|
9150
9177
|
const nodeToVisit = [];
|
|
9151
9178
|
const appendNodeToVisit = (node) => {
|
|
9152
9179
|
nodeToVisit.push(node);
|
|
@@ -9219,7 +9246,7 @@ var makeGlobalRandomApply = (checkInEffect) => fn(`globalRandom${checkInEffect ?
|
|
|
9219
9246
|
if (inEffect !== checkInEffect) continue;
|
|
9220
9247
|
report({
|
|
9221
9248
|
location: node,
|
|
9222
|
-
messageText: checkInEffect ? "
|
|
9249
|
+
messageText: checkInEffect ? "This Effect code uses `Math.random()`, randomness is represented through the Effect `Random` service." : "This code uses `Math.random()`, randomness is represented through the Effect `Random` service.",
|
|
9223
9250
|
fixes: []
|
|
9224
9251
|
});
|
|
9225
9252
|
}
|
|
@@ -9250,12 +9277,12 @@ var globalRandom = createDiagnostic({
|
|
|
9250
9277
|
// src/diagnostics/globalTimersInEffect.ts
|
|
9251
9278
|
var timerAlternatives = {
|
|
9252
9279
|
"setTimeout": {
|
|
9253
|
-
inEffect: "
|
|
9254
|
-
outsideEffect: "
|
|
9280
|
+
inEffect: "This Effect code uses `setTimeout`, the corresponding timer API in this context is `Effect.sleep or Schedule` from Effect.",
|
|
9281
|
+
outsideEffect: "This code uses `setTimeout`, the corresponding Effect timer API is `Effect.sleep or Schedule` from Effect."
|
|
9255
9282
|
},
|
|
9256
9283
|
"setInterval": {
|
|
9257
|
-
inEffect: "
|
|
9258
|
-
outsideEffect: "
|
|
9284
|
+
inEffect: "This Effect code uses `setInterval`, the corresponding timer API in this context is `Schedule or Effect.repeat` from Effect.",
|
|
9285
|
+
outsideEffect: "This code uses `setInterval`, the corresponding Effect timer API is `Schedule or Effect.repeat` from Effect."
|
|
9259
9286
|
}
|
|
9260
9287
|
};
|
|
9261
9288
|
var makeGlobalTimersApply = (checkInEffect) => fn(`globalTimers${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
|
|
@@ -9497,7 +9524,7 @@ var instanceOfSchema = createDiagnostic({
|
|
|
9497
9524
|
if (isSchemaType._tag === "Some") {
|
|
9498
9525
|
report({
|
|
9499
9526
|
location: node,
|
|
9500
|
-
messageText: "
|
|
9527
|
+
messageText: "This code uses `instanceof` with an Effect Schema type. `Schema.is` is the schema-aware runtime check for this case.",
|
|
9501
9528
|
fixes: [{
|
|
9502
9529
|
fixName: "instanceOfSchema_fix",
|
|
9503
9530
|
description: "Replace with Schema.is",
|
|
@@ -9767,7 +9794,7 @@ var leakingRequirements = createDiagnostic({
|
|
|
9767
9794
|
location: node,
|
|
9768
9795
|
messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
|
|
9769
9796
|
|
|
9770
|
-
|
|
9797
|
+
The requirement becomes part of the public service surface instead of remaining internal to Layer implementation.
|
|
9771
9798
|
|
|
9772
9799
|
Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
|
|
9773
9800
|
|
|
@@ -9964,7 +9991,7 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
9964
9991
|
).trim() : "";
|
|
9965
9992
|
report({
|
|
9966
9993
|
location: flow2.node,
|
|
9967
|
-
messageText: `
|
|
9994
|
+
messageText: `This nested call structure has a pipeable form. \`${subjectText}.pipe(...)\` represents the same call sequence in pipe style and may be easier to read.`,
|
|
9968
9995
|
fixes: [{
|
|
9969
9996
|
fixName: "missedPipeableOpportunity_fix",
|
|
9970
9997
|
description: "Convert to pipe style",
|
|
@@ -10045,7 +10072,7 @@ var missingEffectContext = createDiagnostic({
|
|
|
10045
10072
|
(missingTypes) => missingTypes.length > 0 ? report(
|
|
10046
10073
|
{
|
|
10047
10074
|
location: node,
|
|
10048
|
-
messageText: `
|
|
10075
|
+
messageText: `This Effect requires a service that is missing from the expected Effect context: \`${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}\`.`,
|
|
10049
10076
|
fixes: []
|
|
10050
10077
|
}
|
|
10051
10078
|
) : void 0
|
|
@@ -10396,7 +10423,7 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
10396
10423
|
}];
|
|
10397
10424
|
report({
|
|
10398
10425
|
location: unwrapped,
|
|
10399
|
-
messageText:
|
|
10426
|
+
messageText: "This Effect never succeeds; using `return yield*` preserves a definitive generator exit point for type narrowing and tooling support.",
|
|
10400
10427
|
fixes: fix
|
|
10401
10428
|
});
|
|
10402
10429
|
}
|
|
@@ -10452,7 +10479,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
10452
10479
|
brokenGenerators.forEach(
|
|
10453
10480
|
(pos) => report({
|
|
10454
10481
|
location: { pos, end: pos + "function".length },
|
|
10455
|
-
messageText: `
|
|
10482
|
+
messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
|
|
10456
10483
|
fixes: []
|
|
10457
10484
|
})
|
|
10458
10485
|
);
|
|
@@ -10474,7 +10501,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
10474
10501
|
}] : [];
|
|
10475
10502
|
report({
|
|
10476
10503
|
location: node,
|
|
10477
|
-
messageText: `
|
|
10504
|
+
messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
|
|
10478
10505
|
fixes: fix
|
|
10479
10506
|
});
|
|
10480
10507
|
});
|
|
@@ -10542,7 +10569,7 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
10542
10569
|
if (chunk.length < 2) continue;
|
|
10543
10570
|
report({
|
|
10544
10571
|
location: chunk[0].node,
|
|
10545
|
-
messageText: "
|
|
10572
|
+
messageText: "This expression chains multiple `Effect.provide` calls. Providing Layers in multiple calls in a chain can break service lifecycle behavior compared with a single combined provide with merged layers.",
|
|
10546
10573
|
fixes: [{
|
|
10547
10574
|
fixName: "multipleEffectProvide_fix",
|
|
10548
10575
|
description: "Combine into a single provide",
|
|
@@ -10632,7 +10659,7 @@ var nodeBuiltinImport = createDiagnostic({
|
|
|
10632
10659
|
if (match2) {
|
|
10633
10660
|
report({
|
|
10634
10661
|
location: statement.moduleSpecifier,
|
|
10635
|
-
messageText: `
|
|
10662
|
+
messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
|
|
10636
10663
|
fixes: []
|
|
10637
10664
|
});
|
|
10638
10665
|
}
|
|
@@ -10645,7 +10672,7 @@ var nodeBuiltinImport = createDiagnostic({
|
|
|
10645
10672
|
if (match2) {
|
|
10646
10673
|
report({
|
|
10647
10674
|
location: arg,
|
|
10648
|
-
messageText: `
|
|
10675
|
+
messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
|
|
10649
10676
|
fixes: []
|
|
10650
10677
|
});
|
|
10651
10678
|
}
|
|
@@ -10699,7 +10726,7 @@ var nonObjectEffectServiceType = createDiagnostic({
|
|
|
10699
10726
|
const propertyValue = property.initializer;
|
|
10700
10727
|
const errorToReport = {
|
|
10701
10728
|
location: property.name,
|
|
10702
|
-
messageText: "Effect.Service
|
|
10729
|
+
messageText: "`Effect.Service` is declared with a primitive service type. `Effect.Service` models object-shaped services; primitive values use `Context.Tag` or `Effect.Tag` directly.",
|
|
10703
10730
|
fixes: []
|
|
10704
10731
|
};
|
|
10705
10732
|
if (propertyName === "succeed") {
|
|
@@ -11461,7 +11488,7 @@ var outdatedApi = createDiagnostic({
|
|
|
11461
11488
|
hasReported = true;
|
|
11462
11489
|
report({
|
|
11463
11490
|
location: propertyAccess.name,
|
|
11464
|
-
messageText:
|
|
11491
|
+
messageText: `This project targets Effect v4, but this code uses the Effect v3 API \`${propertyName}\`. The referenced API belongs to the v3 surface rather than the configured v4 surface.`,
|
|
11465
11492
|
fixes: []
|
|
11466
11493
|
});
|
|
11467
11494
|
}
|
|
@@ -11504,7 +11531,7 @@ var outdatedApi = createDiagnostic({
|
|
|
11504
11531
|
if (hasReported) {
|
|
11505
11532
|
report({
|
|
11506
11533
|
location: { pos: 0, end: 0 },
|
|
11507
|
-
messageText: "This project targets Effect v4, but
|
|
11534
|
+
messageText: "This project targets Effect v4, but this code uses Effect v3 APIs. The referenced API belongs to the v3 surface rather than the configured v4 surface.",
|
|
11508
11535
|
fixes: []
|
|
11509
11536
|
});
|
|
11510
11537
|
}
|
|
@@ -11680,7 +11707,7 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
11680
11707
|
};
|
|
11681
11708
|
report({
|
|
11682
11709
|
location: member,
|
|
11683
|
-
messageText: "
|
|
11710
|
+
messageText: "This Schema subclass defines its own constructor. For Schema classes, constructor overrides break decoding behavior for the class shape. Custom construction can be expressed through a static `new` method instead.",
|
|
11684
11711
|
fixes: (member.body ? [fixAsStaticNew] : []).concat([{
|
|
11685
11712
|
fixName: "overriddenSchemaConstructor_fix",
|
|
11686
11713
|
description: "Remove the constructor override",
|
|
@@ -11802,7 +11829,7 @@ var preferSchemaOverJson = createDiagnostic({
|
|
|
11802
11829
|
if (isSome2(match2)) {
|
|
11803
11830
|
report({
|
|
11804
11831
|
location: match2.value,
|
|
11805
|
-
messageText: "
|
|
11832
|
+
messageText: "This code uses `JSON.parse` or `JSON.stringify`. Effect Schema provides Effect-aware APIs for JSON parsing and stringifying.",
|
|
11806
11833
|
fixes: []
|
|
11807
11834
|
});
|
|
11808
11835
|
}
|
|
@@ -11920,9 +11947,7 @@ var returnEffectInGen = createDiagnostic({
|
|
|
11920
11947
|
}] : [];
|
|
11921
11948
|
report({
|
|
11922
11949
|
location: node,
|
|
11923
|
-
messageText:
|
|
11924
|
-
Maybe you wanted to return yield* instead?
|
|
11925
|
-
Nested Effect-able types may be intended if you plan to later manually flatten or unwrap this Effect, if so you can safely disable this diagnostic for this line through quickfixes.`,
|
|
11950
|
+
messageText: "This generator returns an Effect-able value directly, which produces a nested `Effect<Effect<...>>`. If the intended result is the inner Effect value, `return yield*` represents that form.",
|
|
11926
11951
|
fixes: fix
|
|
11927
11952
|
});
|
|
11928
11953
|
}),
|
|
@@ -12077,9 +12102,7 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
12077
12102
|
);
|
|
12078
12103
|
});
|
|
12079
12104
|
const v4MethodName = `${isEffectRunCall.value.methodName}With`;
|
|
12080
|
-
const messageText = supportedEffect === "v4" ?
|
|
12081
|
-
Consider extracting the current services by using for example Effect.services and then use Effect.${v4MethodName} with the extracted services instead.` : `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
|
|
12082
|
-
Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`;
|
|
12105
|
+
const messageText = supportedEffect === "v4" ? `\`${nodeText}\` is called inside an Effect with a separate services invocation. In this context, child Effects run with the surrounding services, which can be accessed through \`Effect.services\` and \`Effect.${v4MethodName}\`.` : `\`${nodeText}\` is called inside an Effect with a separate runtime invocation. In this context, run child Effects with the surrounding runtime, which can be accessed through \`Effect.runtime\` and \`Runtime.${isEffectRunCall.value.methodName}\`.`;
|
|
12083
12106
|
report({
|
|
12084
12107
|
location: node.expression,
|
|
12085
12108
|
messageText,
|
|
@@ -12092,7 +12115,7 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
|
|
|
12092
12115
|
} else {
|
|
12093
12116
|
report({
|
|
12094
12117
|
location: node.expression,
|
|
12095
|
-
messageText:
|
|
12118
|
+
messageText: `\`${nodeText}\` is called inside an existing Effect context. Here, the inner Effect can be used directly.`,
|
|
12096
12119
|
fixes: []
|
|
12097
12120
|
});
|
|
12098
12121
|
}
|
|
@@ -12147,7 +12170,7 @@ var schemaStructWithTag = createDiagnostic({
|
|
|
12147
12170
|
const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
|
|
12148
12171
|
report({
|
|
12149
12172
|
location: node,
|
|
12150
|
-
messageText: "Schema.Struct
|
|
12173
|
+
messageText: "This `Schema.Struct` includes a `_tag` field. `Schema.TaggedStruct` is the tagged-struct form for this pattern and makes the tag optional in the constructor.",
|
|
12151
12174
|
fixes: [{
|
|
12152
12175
|
fixName: "schemaStructWithTag_fix",
|
|
12153
12176
|
description: "Replace with Schema.TaggedStruct",
|
|
@@ -12240,7 +12263,7 @@ var schemaSyncInEffect = createDiagnostic({
|
|
|
12240
12263
|
const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
|
|
12241
12264
|
report({
|
|
12242
12265
|
location: node.expression,
|
|
12243
|
-
messageText:
|
|
12266
|
+
messageText: `\`${nodeText}\` is used inside an Effect generator. \`Schema.${effectMethodName}\` preserves the typed Effect error channel for this operation without throwing.`,
|
|
12244
12267
|
fixes: []
|
|
12245
12268
|
});
|
|
12246
12269
|
}
|
|
@@ -12300,7 +12323,7 @@ var schemaUnionOfLiterals = createDiagnostic({
|
|
|
12300
12323
|
const schemaLiteralExpression = firstLiteralCall.expression;
|
|
12301
12324
|
report({
|
|
12302
12325
|
location: node,
|
|
12303
|
-
messageText: "
|
|
12326
|
+
messageText: "This `Schema.Union` contains multiple `Schema.Literal` members and can be simplified to a single `Schema.Literal` call.",
|
|
12304
12327
|
fixes: [{
|
|
12305
12328
|
fixName: "schemaUnionOfLiterals_fix",
|
|
12306
12329
|
description: "Replace with a single Schema.Literal call",
|
|
@@ -12363,8 +12386,7 @@ var scopeInLayerEffect = createDiagnostic({
|
|
|
12363
12386
|
map5(
|
|
12364
12387
|
() => report({
|
|
12365
12388
|
location: node,
|
|
12366
|
-
messageText: `
|
|
12367
|
-
Consider using "scoped" instead to get rid of the scope in the requirements.`,
|
|
12389
|
+
messageText: "This layer construction leaves `Scope` in the requirement set. The scoped API removes `Scope` from the resulting requirements.",
|
|
12368
12390
|
fixes: methodIdentifier ? [{
|
|
12369
12391
|
fixName: "scopeInLayerEffect_scoped",
|
|
12370
12392
|
description: "Use scoped for Layer creation",
|
|
@@ -12464,7 +12486,7 @@ var serviceNotAsClass = createDiagnostic({
|
|
|
12464
12486
|
const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
|
|
12465
12487
|
report({
|
|
12466
12488
|
location: callExpr,
|
|
12467
|
-
messageText:
|
|
12489
|
+
messageText: `\`ServiceMap.Service\` is assigned to a variable here, but this API is intended for a class declaration shape such as \`class ${variableName} extends ServiceMap.Service<${variableName}, ${shapeText}>()("${argsText.replace(/['"]/g, "")}") {}\`.`,
|
|
12468
12490
|
fixes: [{
|
|
12469
12491
|
fixName: "serviceNotAsClass",
|
|
12470
12492
|
description: `Convert to class declaration`,
|
|
@@ -12677,7 +12699,7 @@ var tryCatchInEffectGen = createDiagnostic({
|
|
|
12677
12699
|
map5(() => {
|
|
12678
12700
|
report({
|
|
12679
12701
|
location: node,
|
|
12680
|
-
messageText: `
|
|
12702
|
+
messageText: `This Effect generator contains \`try/catch\`; in this context, error handling is expressed with Effect APIs such as ${alternatives.join(", ")}).`,
|
|
12681
12703
|
fixes: []
|
|
12682
12704
|
});
|
|
12683
12705
|
}),
|
|
@@ -12738,8 +12760,7 @@ var unknownInEffectCatch = createDiagnostic({
|
|
|
12738
12760
|
);
|
|
12739
12761
|
report({
|
|
12740
12762
|
location: node.expression,
|
|
12741
|
-
messageText: `The
|
|
12742
|
-
Consider wrapping unknown errors into Effect's Data.TaggedError for example, or narrow down the type to the specific error raised.`,
|
|
12763
|
+
messageText: `The \`catch\` callback in \`${nodeText}\` returns \`unknown\`, so the Effect error type stays untyped. A specific typed error preserves error-channel information, for example by narrowing the value or wrapping it in \`Data.TaggedError\`.`,
|
|
12743
12764
|
fixes: []
|
|
12744
12765
|
});
|
|
12745
12766
|
}
|
|
@@ -12836,7 +12857,7 @@ var unnecessaryFailYieldableError = createDiagnostic({
|
|
|
12836
12857
|
map5(
|
|
12837
12858
|
() => report({
|
|
12838
12859
|
location: node,
|
|
12839
|
-
messageText:
|
|
12860
|
+
messageText: "This `yield* Effect.fail(...)` passes a yieldable error value. `yield*` represents that value directly without wrapping it in `Effect.fail`.",
|
|
12840
12861
|
fixes: [{
|
|
12841
12862
|
fixName: "unnecessaryFailYieldableError_fix",
|
|
12842
12863
|
description: "Replace yield* Effect.fail with yield*",
|
|
@@ -12941,7 +12962,7 @@ var unnecessaryPipeChain = createDiagnostic({
|
|
|
12941
12962
|
map5(({ innerCall, pipeCall }) => {
|
|
12942
12963
|
report({
|
|
12943
12964
|
location: node,
|
|
12944
|
-
messageText: `
|
|
12965
|
+
messageText: "This expression contains chained `pipe` calls that can be simplified to a single `pipe` call.",
|
|
12945
12966
|
fixes: [{
|
|
12946
12967
|
fixName: "unnecessaryPipeChain_fix",
|
|
12947
12968
|
description: "Rewrite as single pipe call",
|