@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/package.json
CHANGED
package/transform.js
CHANGED
|
@@ -3477,6 +3477,14 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3477
3477
|
),
|
|
3478
3478
|
([A, E, R]) => ({ A, E, R })
|
|
3479
3479
|
);
|
|
3480
|
+
const streamVarianceStruct = (type, atLocation) => map4(
|
|
3481
|
+
all(
|
|
3482
|
+
varianceStructCovariantType(type, atLocation, "_A"),
|
|
3483
|
+
varianceStructCovariantType(type, atLocation, "_E"),
|
|
3484
|
+
varianceStructCovariantType(type, atLocation, "_R")
|
|
3485
|
+
),
|
|
3486
|
+
([A, E, R]) => ({ A, E, R })
|
|
3487
|
+
);
|
|
3480
3488
|
const layerVarianceStruct = (type, atLocation) => map4(
|
|
3481
3489
|
all(
|
|
3482
3490
|
varianceStructContravariantType(type, atLocation, "_ROut"),
|
|
@@ -3523,6 +3531,21 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3523
3531
|
"TypeParser.strictEffectType",
|
|
3524
3532
|
(type) => type
|
|
3525
3533
|
);
|
|
3534
|
+
const streamType = cachedBy(
|
|
3535
|
+
fn("TypeParser.streamType")(function* (type, atLocation) {
|
|
3536
|
+
if (supportedEffect() === "v3") {
|
|
3537
|
+
return yield* effectType(type, atLocation);
|
|
3538
|
+
}
|
|
3539
|
+
const typeIdSymbol = typeChecker.getPropertyOfType(type, "~effect/Stream");
|
|
3540
|
+
if (!typeIdSymbol) {
|
|
3541
|
+
return yield* typeParserIssue("Type is not a stream", type, atLocation);
|
|
3542
|
+
}
|
|
3543
|
+
const typeIdType = typeChecker.getTypeOfSymbolAtLocation(typeIdSymbol, atLocation);
|
|
3544
|
+
return yield* streamVarianceStruct(typeIdType, atLocation);
|
|
3545
|
+
}),
|
|
3546
|
+
"TypeParser.streamType",
|
|
3547
|
+
(type) => type
|
|
3548
|
+
);
|
|
3526
3549
|
const isEffectTypeSourceFile = cachedBy(
|
|
3527
3550
|
fn("TypeParser.isEffectTypeSourceFile")(function* (sourceFile) {
|
|
3528
3551
|
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
@@ -5258,6 +5281,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5258
5281
|
isServiceMapTypeSourceFile,
|
|
5259
5282
|
isNodeReferenceToServiceMapModuleApi,
|
|
5260
5283
|
effectType,
|
|
5284
|
+
streamType,
|
|
5261
5285
|
strictEffectType,
|
|
5262
5286
|
layerType,
|
|
5263
5287
|
fiberType,
|
|
@@ -5485,7 +5509,7 @@ var catchAllToMapError = createDiagnostic({
|
|
|
5485
5509
|
const { failArg, failCall } = failCallInfo;
|
|
5486
5510
|
report({
|
|
5487
5511
|
location: transformation.callee,
|
|
5488
|
-
messageText:
|
|
5512
|
+
messageText: `\`Effect.mapError\` expresses the same error-type transformation more directly than \`Effect.${catchAllName}\` followed by \`Effect.fail\`.`,
|
|
5489
5513
|
fixes: [{
|
|
5490
5514
|
fixName: "catchAllToMapError_fix",
|
|
5491
5515
|
description: "Replace with Effect.mapError",
|
|
@@ -5549,7 +5573,7 @@ var catchUnfailableEffect = createDiagnostic({
|
|
|
5549
5573
|
if (E.flags & ts.TypeFlags.Never) {
|
|
5550
5574
|
report({
|
|
5551
5575
|
location: transformation.callee,
|
|
5552
|
-
messageText:
|
|
5576
|
+
messageText: "The previous Effect does not fail, so this error-handling branch will never run.",
|
|
5553
5577
|
fixes: []
|
|
5554
5578
|
});
|
|
5555
5579
|
}
|
|
@@ -5612,7 +5636,7 @@ var classSelfMismatch = createDiagnostic({
|
|
|
5612
5636
|
if (actualName !== expectedName) {
|
|
5613
5637
|
report({
|
|
5614
5638
|
location: selfTypeNode,
|
|
5615
|
-
messageText: `Self type parameter should be
|
|
5639
|
+
messageText: `The \`Self\` type parameter for this class should be \`${expectedName}\`.`,
|
|
5616
5640
|
fixes: [{
|
|
5617
5641
|
fixName: "classSelfMismatch_fix",
|
|
5618
5642
|
description: `Replace '${actualName}' with '${expectedName}'`,
|
|
@@ -5802,7 +5826,7 @@ var deterministicKeys = createDiagnostic({
|
|
|
5802
5826
|
if (actualIdentifier !== expectedKey) {
|
|
5803
5827
|
report({
|
|
5804
5828
|
location: keyStringLiteral,
|
|
5805
|
-
messageText: `
|
|
5829
|
+
messageText: `This key does not match the deterministic key for this declaration. The expected key is \`${expectedKey}\`.`,
|
|
5806
5830
|
fixes: [{
|
|
5807
5831
|
fixName: "deterministicKeys_fix",
|
|
5808
5832
|
description: `Replace '${actualIdentifier}' with '${expectedKey}'`,
|
|
@@ -5841,9 +5865,8 @@ var duplicatePackage = createDiagnostic({
|
|
|
5841
5865
|
const versions = Object.keys(resolvedPackages[packageName]);
|
|
5842
5866
|
report({
|
|
5843
5867
|
location: sourceFile.statements[0],
|
|
5844
|
-
messageText: `
|
|
5845
|
-
|
|
5846
|
-
If this is intended set the LSP config "allowedDuplicatedPackages" to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
|
|
5868
|
+
messageText: `Multiple versions of package \`${packageName}\` were detected: ${versions.join(", ")}. Package duplication can change runtime identity and type equality across Effect modules.
|
|
5869
|
+
If this is intentional, set the LSP config \`allowedDuplicatedPackages\` to ${JSON.stringify(options.allowedDuplicatedPackages.concat([packageName]))}.
|
|
5847
5870
|
|
|
5848
5871
|
${versions.map((version) => `- found ${version} at ${resolvedPackages[packageName][version]}`).join("\n")}`,
|
|
5849
5872
|
fixes: []
|
|
@@ -5951,7 +5974,7 @@ var effectFnIife = createDiagnostic({
|
|
|
5951
5974
|
const traceExpressionText = traceExpression ? sourceFile.text.slice(traceExpression.pos, traceExpression.end) : void 0;
|
|
5952
5975
|
report({
|
|
5953
5976
|
location: node,
|
|
5954
|
-
messageText:
|
|
5977
|
+
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` : ``}.`,
|
|
5955
5978
|
fixes
|
|
5956
5979
|
});
|
|
5957
5980
|
}
|
|
@@ -6036,7 +6059,7 @@ var effectFnImplicitAny = createDiagnostic({
|
|
|
6036
6059
|
const parameterName = getParameterName(ts, parameter.name);
|
|
6037
6060
|
report({
|
|
6038
6061
|
location: parameter.name,
|
|
6039
|
-
messageText: `Parameter
|
|
6062
|
+
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.`,
|
|
6040
6063
|
fixes: []
|
|
6041
6064
|
});
|
|
6042
6065
|
}
|
|
@@ -6632,7 +6655,7 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
6632
6655
|
const expectedSignature = generateExpectedSignature();
|
|
6633
6656
|
report({
|
|
6634
6657
|
location: nameIdentifier ?? targetNode,
|
|
6635
|
-
messageText: `
|
|
6658
|
+
messageText: `This expression can be rewritten in the reusable function form \`${expectedSignature}\`.`,
|
|
6636
6659
|
fixes
|
|
6637
6660
|
});
|
|
6638
6661
|
}
|
|
@@ -6844,7 +6867,7 @@ var effectMapVoid = createDiagnostic({
|
|
|
6844
6867
|
if (isNone2(match2)) continue;
|
|
6845
6868
|
report({
|
|
6846
6869
|
location: node.expression,
|
|
6847
|
-
messageText: "
|
|
6870
|
+
messageText: "This expression discards the success value through mapping. `Effect.asVoid` represents that form directly.",
|
|
6848
6871
|
fixes: [{
|
|
6849
6872
|
fixName: "effectMapVoid_fix",
|
|
6850
6873
|
description: "Replace with Effect.asVoid",
|
|
@@ -6899,7 +6922,7 @@ var effectSucceedWithVoid = createDiagnostic({
|
|
|
6899
6922
|
if (!tsUtils.isVoidExpression(argument)) continue;
|
|
6900
6923
|
report({
|
|
6901
6924
|
location: node,
|
|
6902
|
-
messageText: "Effect.void
|
|
6925
|
+
messageText: "`Effect.void` represents the same outcome as `Effect.succeed(undefined)` or `Effect.succeed(void 0)`.",
|
|
6903
6926
|
fixes: [{
|
|
6904
6927
|
fixName: "effectSucceedWithVoid_fix",
|
|
6905
6928
|
description: "Replace with Effect.void",
|
|
@@ -6961,7 +6984,7 @@ var extendsNativeError = createDiagnostic({
|
|
|
6961
6984
|
if (isNativeError) {
|
|
6962
6985
|
report({
|
|
6963
6986
|
location: node.name ?? typeExpression,
|
|
6964
|
-
messageText: "
|
|
6987
|
+
messageText: "This class extends the native `Error` type directly. Untagged native errors lose distinction in the Effect failure channel.",
|
|
6965
6988
|
fixes: []
|
|
6966
6989
|
});
|
|
6967
6990
|
}
|
|
@@ -7006,7 +7029,12 @@ var floatingEffect = createDiagnostic({
|
|
|
7006
7029
|
if (!isFloatingExpression(node)) continue;
|
|
7007
7030
|
const type = typeCheckerUtils.getTypeAtLocation(node.expression);
|
|
7008
7031
|
if (!type) continue;
|
|
7009
|
-
const effect = yield* option(
|
|
7032
|
+
const effect = yield* option(
|
|
7033
|
+
pipe(
|
|
7034
|
+
typeParser.effectType(type, node.expression),
|
|
7035
|
+
orElse2(() => typeParser.streamType(type, node.expression))
|
|
7036
|
+
)
|
|
7037
|
+
);
|
|
7010
7038
|
if (isSome2(effect)) {
|
|
7011
7039
|
const allowedFloatingEffects = yield* pipe(
|
|
7012
7040
|
typeParser.fiberType(type, node.expression),
|
|
@@ -7015,10 +7043,9 @@ var floatingEffect = createDiagnostic({
|
|
|
7015
7043
|
);
|
|
7016
7044
|
if (isNone2(allowedFloatingEffects)) {
|
|
7017
7045
|
const isStrictEffect = yield* option(typeParser.strictEffectType(type, node.expression));
|
|
7018
|
-
const name = isSome2(isStrictEffect) ? "Effect" : "Effect-able " + typeChecker.typeToString(type);
|
|
7019
7046
|
report({
|
|
7020
7047
|
location: node,
|
|
7021
|
-
messageText:
|
|
7048
|
+
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.`,
|
|
7022
7049
|
fixes: []
|
|
7023
7050
|
});
|
|
7024
7051
|
}
|
|
@@ -7113,7 +7140,7 @@ var makeGlobalConsoleApply = (checkInEffect) => fn(`globalConsole${checkInEffect
|
|
|
7113
7140
|
if (inEffect !== checkInEffect) continue;
|
|
7114
7141
|
report({
|
|
7115
7142
|
location: node,
|
|
7116
|
-
messageText: checkInEffect ? `
|
|
7143
|
+
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}\`.`,
|
|
7117
7144
|
fixes: []
|
|
7118
7145
|
});
|
|
7119
7146
|
}
|
|
@@ -7162,10 +7189,10 @@ var makeGlobalDateApply = (checkInEffect) => fn(`globalDate${checkInEffect ? "In
|
|
|
7162
7189
|
let objectNode;
|
|
7163
7190
|
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.idText(node.expression.name) === "now") {
|
|
7164
7191
|
objectNode = node.expression.expression;
|
|
7165
|
-
messageText = checkInEffect ? "
|
|
7192
|
+
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.";
|
|
7166
7193
|
} else if (ts.isNewExpression(node)) {
|
|
7167
7194
|
objectNode = node.expression;
|
|
7168
|
-
messageText = checkInEffect ? "
|
|
7195
|
+
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.";
|
|
7169
7196
|
}
|
|
7170
7197
|
if (!messageText || !objectNode) continue;
|
|
7171
7198
|
const symbol3 = typeChecker.getSymbolAtLocation(objectNode);
|
|
@@ -7248,7 +7275,7 @@ var globalErrorInEffectCatch = createDiagnostic({
|
|
|
7248
7275
|
);
|
|
7249
7276
|
report({
|
|
7250
7277
|
location: node.expression,
|
|
7251
|
-
messageText: `The
|
|
7278
|
+
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.`,
|
|
7252
7279
|
fixes: []
|
|
7253
7280
|
});
|
|
7254
7281
|
}
|
|
@@ -7328,7 +7355,7 @@ var makeGlobalFetchApply = (checkInEffect) => fn(`globalFetch${checkInEffect ? "
|
|
|
7328
7355
|
if (!fetchSymbol) return;
|
|
7329
7356
|
const effectVersion = typeParser.supportedEffect();
|
|
7330
7357
|
const packageName = effectVersion === "v3" ? "@effect/platform" : "effect/unstable/http";
|
|
7331
|
-
const messageText = checkInEffect ? `
|
|
7358
|
+
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}\`.`;
|
|
7332
7359
|
const nodeToVisit = [];
|
|
7333
7360
|
const appendNodeToVisit = (node) => {
|
|
7334
7361
|
nodeToVisit.push(node);
|
|
@@ -7401,7 +7428,7 @@ var makeGlobalRandomApply = (checkInEffect) => fn(`globalRandom${checkInEffect ?
|
|
|
7401
7428
|
if (inEffect !== checkInEffect) continue;
|
|
7402
7429
|
report({
|
|
7403
7430
|
location: node,
|
|
7404
|
-
messageText: checkInEffect ? "
|
|
7431
|
+
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.",
|
|
7405
7432
|
fixes: []
|
|
7406
7433
|
});
|
|
7407
7434
|
}
|
|
@@ -7432,12 +7459,12 @@ var globalRandom = createDiagnostic({
|
|
|
7432
7459
|
// src/diagnostics/globalTimersInEffect.ts
|
|
7433
7460
|
var timerAlternatives = {
|
|
7434
7461
|
"setTimeout": {
|
|
7435
|
-
inEffect: "
|
|
7436
|
-
outsideEffect: "
|
|
7462
|
+
inEffect: "This Effect code uses `setTimeout`, the corresponding timer API in this context is `Effect.sleep or Schedule` from Effect.",
|
|
7463
|
+
outsideEffect: "This code uses `setTimeout`, the corresponding Effect timer API is `Effect.sleep or Schedule` from Effect."
|
|
7437
7464
|
},
|
|
7438
7465
|
"setInterval": {
|
|
7439
|
-
inEffect: "
|
|
7440
|
-
outsideEffect: "
|
|
7466
|
+
inEffect: "This Effect code uses `setInterval`, the corresponding timer API in this context is `Schedule or Effect.repeat` from Effect.",
|
|
7467
|
+
outsideEffect: "This code uses `setInterval`, the corresponding Effect timer API is `Schedule or Effect.repeat` from Effect."
|
|
7441
7468
|
}
|
|
7442
7469
|
};
|
|
7443
7470
|
var makeGlobalTimersApply = (checkInEffect) => fn(`globalTimers${checkInEffect ? "InEffect" : ""}.apply`)(function* (sourceFile, report) {
|
|
@@ -7679,7 +7706,7 @@ var instanceOfSchema = createDiagnostic({
|
|
|
7679
7706
|
if (isSchemaType._tag === "Some") {
|
|
7680
7707
|
report({
|
|
7681
7708
|
location: node,
|
|
7682
|
-
messageText: "
|
|
7709
|
+
messageText: "This code uses `instanceof` with an Effect Schema type. `Schema.is` is the schema-aware runtime check for this case.",
|
|
7683
7710
|
fixes: [{
|
|
7684
7711
|
fixName: "instanceOfSchema_fix",
|
|
7685
7712
|
description: "Replace with Schema.is",
|
|
@@ -7949,7 +7976,7 @@ var leakingRequirements = createDiagnostic({
|
|
|
7949
7976
|
location: node,
|
|
7950
7977
|
messageText: `Methods of this Service require \`${requirementsStr}\` from every caller.
|
|
7951
7978
|
|
|
7952
|
-
|
|
7979
|
+
The requirement becomes part of the public service surface instead of remaining internal to Layer implementation.
|
|
7953
7980
|
|
|
7954
7981
|
Resolve these dependencies at Layer creation and provide them to each method, so the service's type reflects its purpose, not its implementation.
|
|
7955
7982
|
|
|
@@ -8146,7 +8173,7 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
8146
8173
|
).trim() : "";
|
|
8147
8174
|
report({
|
|
8148
8175
|
location: flow2.node,
|
|
8149
|
-
messageText: `
|
|
8176
|
+
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.`,
|
|
8150
8177
|
fixes: [{
|
|
8151
8178
|
fixName: "missedPipeableOpportunity_fix",
|
|
8152
8179
|
description: "Convert to pipe style",
|
|
@@ -8227,7 +8254,7 @@ var missingEffectContext = createDiagnostic({
|
|
|
8227
8254
|
(missingTypes) => missingTypes.length > 0 ? report(
|
|
8228
8255
|
{
|
|
8229
8256
|
location: node,
|
|
8230
|
-
messageText: `
|
|
8257
|
+
messageText: `This Effect requires a service that is missing from the expected Effect context: \`${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}\`.`,
|
|
8231
8258
|
fixes: []
|
|
8232
8259
|
}
|
|
8233
8260
|
) : void 0
|
|
@@ -8578,7 +8605,7 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
8578
8605
|
}];
|
|
8579
8606
|
report({
|
|
8580
8607
|
location: unwrapped,
|
|
8581
|
-
messageText:
|
|
8608
|
+
messageText: "This Effect never succeeds; using `return yield*` preserves a definitive generator exit point for type narrowing and tooling support.",
|
|
8582
8609
|
fixes: fix
|
|
8583
8610
|
});
|
|
8584
8611
|
}
|
|
@@ -8634,7 +8661,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
8634
8661
|
brokenGenerators.forEach(
|
|
8635
8662
|
(pos) => report({
|
|
8636
8663
|
location: { pos, end: pos + "function".length },
|
|
8637
|
-
messageText: `
|
|
8664
|
+
messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
|
|
8638
8665
|
fixes: []
|
|
8639
8666
|
})
|
|
8640
8667
|
);
|
|
@@ -8656,7 +8683,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
8656
8683
|
}] : [];
|
|
8657
8684
|
report({
|
|
8658
8685
|
location: node,
|
|
8659
|
-
messageText: `
|
|
8686
|
+
messageText: "This uses `yield` for an `Effect` value. `yield*` is the Effect-aware form in this context.",
|
|
8660
8687
|
fixes: fix
|
|
8661
8688
|
});
|
|
8662
8689
|
});
|
|
@@ -8724,7 +8751,7 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
8724
8751
|
if (chunk.length < 2) continue;
|
|
8725
8752
|
report({
|
|
8726
8753
|
location: chunk[0].node,
|
|
8727
|
-
messageText: "
|
|
8754
|
+
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.",
|
|
8728
8755
|
fixes: [{
|
|
8729
8756
|
fixName: "multipleEffectProvide_fix",
|
|
8730
8757
|
description: "Combine into a single provide",
|
|
@@ -8814,7 +8841,7 @@ var nodeBuiltinImport = createDiagnostic({
|
|
|
8814
8841
|
if (match2) {
|
|
8815
8842
|
report({
|
|
8816
8843
|
location: statement.moduleSpecifier,
|
|
8817
|
-
messageText: `
|
|
8844
|
+
messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
|
|
8818
8845
|
fixes: []
|
|
8819
8846
|
});
|
|
8820
8847
|
}
|
|
@@ -8827,7 +8854,7 @@ var nodeBuiltinImport = createDiagnostic({
|
|
|
8827
8854
|
if (match2) {
|
|
8828
8855
|
report({
|
|
8829
8856
|
location: arg,
|
|
8830
|
-
messageText: `
|
|
8857
|
+
messageText: `This module reference uses the \`${match2.module}\` module, the corresponding Effect API is \`${match2.alternative}\` from \`${match2.package}\`.`,
|
|
8831
8858
|
fixes: []
|
|
8832
8859
|
});
|
|
8833
8860
|
}
|
|
@@ -8881,7 +8908,7 @@ var nonObjectEffectServiceType = createDiagnostic({
|
|
|
8881
8908
|
const propertyValue = property.initializer;
|
|
8882
8909
|
const errorToReport = {
|
|
8883
8910
|
location: property.name,
|
|
8884
|
-
messageText: "Effect.Service
|
|
8911
|
+
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.",
|
|
8885
8912
|
fixes: []
|
|
8886
8913
|
};
|
|
8887
8914
|
if (propertyName === "succeed") {
|
|
@@ -9643,7 +9670,7 @@ var outdatedApi = createDiagnostic({
|
|
|
9643
9670
|
hasReported = true;
|
|
9644
9671
|
report({
|
|
9645
9672
|
location: propertyAccess.name,
|
|
9646
|
-
messageText:
|
|
9673
|
+
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.`,
|
|
9647
9674
|
fixes: []
|
|
9648
9675
|
});
|
|
9649
9676
|
}
|
|
@@ -9686,7 +9713,7 @@ var outdatedApi = createDiagnostic({
|
|
|
9686
9713
|
if (hasReported) {
|
|
9687
9714
|
report({
|
|
9688
9715
|
location: { pos: 0, end: 0 },
|
|
9689
|
-
messageText: "This project targets Effect v4, but
|
|
9716
|
+
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.",
|
|
9690
9717
|
fixes: []
|
|
9691
9718
|
});
|
|
9692
9719
|
}
|
|
@@ -10931,7 +10958,7 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
10931
10958
|
};
|
|
10932
10959
|
report({
|
|
10933
10960
|
location: member,
|
|
10934
|
-
messageText: "
|
|
10961
|
+
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.",
|
|
10935
10962
|
fixes: (member.body ? [fixAsStaticNew] : []).concat([{
|
|
10936
10963
|
fixName: "overriddenSchemaConstructor_fix",
|
|
10937
10964
|
description: "Remove the constructor override",
|
|
@@ -11053,7 +11080,7 @@ var preferSchemaOverJson = createDiagnostic({
|
|
|
11053
11080
|
if (isSome2(match2)) {
|
|
11054
11081
|
report({
|
|
11055
11082
|
location: match2.value,
|
|
11056
|
-
messageText: "
|
|
11083
|
+
messageText: "This code uses `JSON.parse` or `JSON.stringify`. Effect Schema provides Effect-aware APIs for JSON parsing and stringifying.",
|
|
11057
11084
|
fixes: []
|
|
11058
11085
|
});
|
|
11059
11086
|
}
|
|
@@ -11171,9 +11198,7 @@ var returnEffectInGen = createDiagnostic({
|
|
|
11171
11198
|
}] : [];
|
|
11172
11199
|
report({
|
|
11173
11200
|
location: node,
|
|
11174
|
-
messageText:
|
|
11175
|
-
Maybe you wanted to return yield* instead?
|
|
11176
|
-
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.`,
|
|
11201
|
+
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.",
|
|
11177
11202
|
fixes: fix
|
|
11178
11203
|
});
|
|
11179
11204
|
}),
|
|
@@ -11328,9 +11353,7 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
11328
11353
|
);
|
|
11329
11354
|
});
|
|
11330
11355
|
const v4MethodName = `${isEffectRunCall.value.methodName}With`;
|
|
11331
|
-
const messageText = supportedEffect === "v4" ?
|
|
11332
|
-
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.
|
|
11333
|
-
Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`;
|
|
11356
|
+
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}\`.`;
|
|
11334
11357
|
report({
|
|
11335
11358
|
location: node.expression,
|
|
11336
11359
|
messageText,
|
|
@@ -11343,7 +11366,7 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
|
|
|
11343
11366
|
} else {
|
|
11344
11367
|
report({
|
|
11345
11368
|
location: node.expression,
|
|
11346
|
-
messageText:
|
|
11369
|
+
messageText: `\`${nodeText}\` is called inside an existing Effect context. Here, the inner Effect can be used directly.`,
|
|
11347
11370
|
fixes: []
|
|
11348
11371
|
});
|
|
11349
11372
|
}
|
|
@@ -11398,7 +11421,7 @@ var schemaStructWithTag = createDiagnostic({
|
|
|
11398
11421
|
const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
|
|
11399
11422
|
report({
|
|
11400
11423
|
location: node,
|
|
11401
|
-
messageText: "Schema.Struct
|
|
11424
|
+
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.",
|
|
11402
11425
|
fixes: [{
|
|
11403
11426
|
fixName: "schemaStructWithTag_fix",
|
|
11404
11427
|
description: "Replace with Schema.TaggedStruct",
|
|
@@ -11491,7 +11514,7 @@ var schemaSyncInEffect = createDiagnostic({
|
|
|
11491
11514
|
const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
|
|
11492
11515
|
report({
|
|
11493
11516
|
location: node.expression,
|
|
11494
|
-
messageText:
|
|
11517
|
+
messageText: `\`${nodeText}\` is used inside an Effect generator. \`Schema.${effectMethodName}\` preserves the typed Effect error channel for this operation without throwing.`,
|
|
11495
11518
|
fixes: []
|
|
11496
11519
|
});
|
|
11497
11520
|
}
|
|
@@ -11551,7 +11574,7 @@ var schemaUnionOfLiterals = createDiagnostic({
|
|
|
11551
11574
|
const schemaLiteralExpression = firstLiteralCall.expression;
|
|
11552
11575
|
report({
|
|
11553
11576
|
location: node,
|
|
11554
|
-
messageText: "
|
|
11577
|
+
messageText: "This `Schema.Union` contains multiple `Schema.Literal` members and can be simplified to a single `Schema.Literal` call.",
|
|
11555
11578
|
fixes: [{
|
|
11556
11579
|
fixName: "schemaUnionOfLiterals_fix",
|
|
11557
11580
|
description: "Replace with a single Schema.Literal call",
|
|
@@ -11614,8 +11637,7 @@ var scopeInLayerEffect = createDiagnostic({
|
|
|
11614
11637
|
map4(
|
|
11615
11638
|
() => report({
|
|
11616
11639
|
location: node,
|
|
11617
|
-
messageText: `
|
|
11618
|
-
Consider using "scoped" instead to get rid of the scope in the requirements.`,
|
|
11640
|
+
messageText: "This layer construction leaves `Scope` in the requirement set. The scoped API removes `Scope` from the resulting requirements.",
|
|
11619
11641
|
fixes: methodIdentifier ? [{
|
|
11620
11642
|
fixName: "scopeInLayerEffect_scoped",
|
|
11621
11643
|
description: "Use scoped for Layer creation",
|
|
@@ -11715,7 +11737,7 @@ var serviceNotAsClass = createDiagnostic({
|
|
|
11715
11737
|
const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
|
|
11716
11738
|
report({
|
|
11717
11739
|
location: callExpr,
|
|
11718
|
-
messageText:
|
|
11740
|
+
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, "")}") {}\`.`,
|
|
11719
11741
|
fixes: [{
|
|
11720
11742
|
fixName: "serviceNotAsClass",
|
|
11721
11743
|
description: `Convert to class declaration`,
|
|
@@ -11928,7 +11950,7 @@ var tryCatchInEffectGen = createDiagnostic({
|
|
|
11928
11950
|
map4(() => {
|
|
11929
11951
|
report({
|
|
11930
11952
|
location: node,
|
|
11931
|
-
messageText: `
|
|
11953
|
+
messageText: `This Effect generator contains \`try/catch\`; in this context, error handling is expressed with Effect APIs such as ${alternatives.join(", ")}).`,
|
|
11932
11954
|
fixes: []
|
|
11933
11955
|
});
|
|
11934
11956
|
}),
|
|
@@ -11989,8 +12011,7 @@ var unknownInEffectCatch = createDiagnostic({
|
|
|
11989
12011
|
);
|
|
11990
12012
|
report({
|
|
11991
12013
|
location: node.expression,
|
|
11992
|
-
messageText: `The
|
|
11993
|
-
Consider wrapping unknown errors into Effect's Data.TaggedError for example, or narrow down the type to the specific error raised.`,
|
|
12014
|
+
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\`.`,
|
|
11994
12015
|
fixes: []
|
|
11995
12016
|
});
|
|
11996
12017
|
}
|
|
@@ -12087,7 +12108,7 @@ var unnecessaryFailYieldableError = createDiagnostic({
|
|
|
12087
12108
|
map4(
|
|
12088
12109
|
() => report({
|
|
12089
12110
|
location: node,
|
|
12090
|
-
messageText:
|
|
12111
|
+
messageText: "This `yield* Effect.fail(...)` passes a yieldable error value. `yield*` represents that value directly without wrapping it in `Effect.fail`.",
|
|
12091
12112
|
fixes: [{
|
|
12092
12113
|
fixName: "unnecessaryFailYieldableError_fix",
|
|
12093
12114
|
description: "Replace yield* Effect.fail with yield*",
|
|
@@ -12192,7 +12213,7 @@ var unnecessaryPipeChain = createDiagnostic({
|
|
|
12192
12213
|
map4(({ innerCall, pipeCall }) => {
|
|
12193
12214
|
report({
|
|
12194
12215
|
location: node,
|
|
12195
|
-
messageText: `
|
|
12216
|
+
messageText: "This expression contains chained `pipe` calls that can be simplified to a single `pipe` call.",
|
|
12196
12217
|
fixes: [{
|
|
12197
12218
|
fixName: "unnecessaryPipeChain_fix",
|
|
12198
12219
|
description: "Rewrite as single pipe call",
|