@effect/language-service 0.84.0 → 0.84.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/README.md +1 -1
- package/cli.js +59 -16
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +54 -12
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +54 -12
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/schema.json +1 -1
- package/transform.js +54 -12
- package/transform.js.map +1 -1
package/README.md
CHANGED
|
@@ -81,7 +81,7 @@ Some diagnostics are off by default or have a default severity of suggestion, bu
|
|
|
81
81
|
<tr><td><code>leakingRequirements</code></td><td>💡</td><td></td><td>Detects implementation services leaked in service methods</td><td>✓</td><td>✓</td></tr>
|
|
82
82
|
<tr><td><code>multipleEffectProvide</code></td><td>⚠️</td><td>🔧</td><td>Warns against chaining Effect.provide calls which can cause service lifecycle issues</td><td>✓</td><td>✓</td></tr>
|
|
83
83
|
<tr><td><code>returnEffectInGen</code></td><td>💡</td><td>🔧</td><td>Warns when returning an Effect in a generator causes nested Effect<Effect<...>></td><td>✓</td><td>✓</td></tr>
|
|
84
|
-
<tr><td><code>runEffectInsideEffect</code></td><td>💡</td><td>🔧</td><td>Suggests using Runtime methods instead of Effect.run* inside Effect contexts</td><td>✓</td><td
|
|
84
|
+
<tr><td><code>runEffectInsideEffect</code></td><td>💡</td><td>🔧</td><td>Suggests using Runtime or Effect.run*With methods instead of Effect.run* inside Effect contexts</td><td>✓</td><td>✓</td></tr>
|
|
85
85
|
<tr><td><code>schemaSyncInEffect</code></td><td>💡</td><td></td><td>Suggests using Effect-based Schema methods instead of sync methods inside Effect generators</td><td>✓</td><td></td></tr>
|
|
86
86
|
<tr><td><code>scopeInLayerEffect</code></td><td>⚠️</td><td>🔧</td><td>Suggests using Layer.scoped instead of Layer.effect when Scope is in requirements</td><td>✓</td><td></td></tr>
|
|
87
87
|
<tr><td><code>strictEffectProvide</code></td><td>➖</td><td></td><td>Warns when using Effect.provide with layers outside of application entry points</td><td>✓</td><td>✓</td></tr>
|
package/cli.js
CHANGED
|
@@ -25942,7 +25942,7 @@ var runWith2 = (command, config2) => {
|
|
|
25942
25942
|
// package.json
|
|
25943
25943
|
var package_default = {
|
|
25944
25944
|
name: "@effect/language-service",
|
|
25945
|
-
version: "0.84.
|
|
25945
|
+
version: "0.84.1",
|
|
25946
25946
|
publishConfig: {
|
|
25947
25947
|
access: "public",
|
|
25948
25948
|
directory: "dist"
|
|
@@ -33935,12 +33935,14 @@ var getParameterName = (typescript, name) => {
|
|
|
33935
33935
|
}
|
|
33936
33936
|
return "parameter";
|
|
33937
33937
|
};
|
|
33938
|
-
var hasOuterContextualFunctionType = (typescript, typeChecker, node) => {
|
|
33938
|
+
var hasOuterContextualFunctionType = (typescript, typeChecker, typeCheckerUtils, node) => {
|
|
33939
33939
|
const contextualType = typeChecker.getContextualType(node);
|
|
33940
33940
|
if (!contextualType) {
|
|
33941
33941
|
return false;
|
|
33942
33942
|
}
|
|
33943
|
-
return
|
|
33943
|
+
return typeCheckerUtils.unrollUnionMembers(contextualType).some(
|
|
33944
|
+
(type) => typeChecker.getSignaturesOfType(type, typescript.SignatureKind.Call).length > 0
|
|
33945
|
+
);
|
|
33944
33946
|
};
|
|
33945
33947
|
var effectFnImplicitAny = createDiagnostic({
|
|
33946
33948
|
name: "effectFnImplicitAny",
|
|
@@ -33954,6 +33956,7 @@ var effectFnImplicitAny = createDiagnostic({
|
|
|
33954
33956
|
const ts = yield* service2(TypeScriptApi);
|
|
33955
33957
|
const program = yield* service2(TypeScriptProgram);
|
|
33956
33958
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
33959
|
+
const typeCheckerUtils = yield* service2(TypeCheckerUtils);
|
|
33957
33960
|
const typeParser = yield* service2(TypeParser);
|
|
33958
33961
|
const noImplicitAny = program.getCompilerOptions().noImplicitAny ?? program.getCompilerOptions().strict ?? false;
|
|
33959
33962
|
if (!noImplicitAny) {
|
|
@@ -33993,7 +33996,7 @@ var effectFnImplicitAny = createDiagnostic({
|
|
|
33993
33996
|
),
|
|
33994
33997
|
orUndefined
|
|
33995
33998
|
);
|
|
33996
|
-
if (!parsed || hasOuterContextualFunctionType(ts, typeChecker, parsed.call)) {
|
|
33999
|
+
if (!parsed || hasOuterContextualFunctionType(ts, typeChecker, typeCheckerUtils, parsed.call)) {
|
|
33997
34000
|
continue;
|
|
33998
34001
|
}
|
|
33999
34002
|
for (const parameter of parsed.fn.parameters) {
|
|
@@ -38088,16 +38091,16 @@ Nested Effect-able types may be intended if you plan to later manually flatten o
|
|
|
38088
38091
|
var runEffectInsideEffect = createDiagnostic({
|
|
38089
38092
|
name: "runEffectInsideEffect",
|
|
38090
38093
|
code: 32,
|
|
38091
|
-
description: "Suggests using Runtime methods instead of Effect.run* inside Effect contexts",
|
|
38094
|
+
description: "Suggests using Runtime or Effect.run*With methods instead of Effect.run* inside Effect contexts",
|
|
38092
38095
|
group: "antipattern",
|
|
38093
38096
|
severity: "suggestion",
|
|
38094
38097
|
fixable: true,
|
|
38095
|
-
supportedEffect: ["v3"],
|
|
38098
|
+
supportedEffect: ["v3", "v4"],
|
|
38096
38099
|
apply: fn3("runEffectInsideEffect.apply")(function* (sourceFile, report) {
|
|
38097
38100
|
const ts = yield* service2(TypeScriptApi);
|
|
38098
38101
|
const typeParser = yield* service2(TypeParser);
|
|
38099
38102
|
const tsUtils = yield* service2(TypeScriptUtils);
|
|
38100
|
-
|
|
38103
|
+
const supportedEffect = typeParser.supportedEffect();
|
|
38101
38104
|
const parseEffectMethod = (node, methodName) => pipe(
|
|
38102
38105
|
typeParser.isNodeReferenceToEffectModuleApi(methodName)(node),
|
|
38103
38106
|
map12(() => ({ node, methodName }))
|
|
@@ -38130,9 +38133,10 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
38130
38133
|
if (scopeNode && scopeNode !== effectGen.generatorFunction) {
|
|
38131
38134
|
const fixAddRuntime = gen3(function* () {
|
|
38132
38135
|
const changeTracker = yield* service2(ChangeTracker);
|
|
38133
|
-
const runtimeModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Runtime") || "Runtime";
|
|
38134
38136
|
const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Effect") || "Effect";
|
|
38137
|
+
const runtimeModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Runtime") || "Runtime";
|
|
38135
38138
|
let runtimeIdentifier = void 0;
|
|
38139
|
+
let servicesIdentifier = void 0;
|
|
38136
38140
|
for (const statement of effectGen.generatorFunction.body.statements) {
|
|
38137
38141
|
if (ts.isVariableStatement(statement) && statement.declarationList.declarations.length === 1) {
|
|
38138
38142
|
const declaration = statement.declarationList.declarations[0];
|
|
@@ -38146,11 +38150,46 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
38146
38150
|
if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
|
|
38147
38151
|
runtimeIdentifier = ts.idText(declaration.name);
|
|
38148
38152
|
}
|
|
38153
|
+
const maybeEffectServices = yield* pipe(
|
|
38154
|
+
typeParser.isNodeReferenceToEffectModuleApi("services")(yieldedExpression.expression),
|
|
38155
|
+
option4
|
|
38156
|
+
);
|
|
38157
|
+
if (isSome2(maybeEffectServices) && ts.isIdentifier(declaration.name)) {
|
|
38158
|
+
servicesIdentifier = ts.idText(declaration.name);
|
|
38159
|
+
}
|
|
38149
38160
|
}
|
|
38150
38161
|
}
|
|
38151
38162
|
}
|
|
38152
38163
|
}
|
|
38153
|
-
if (!
|
|
38164
|
+
if (supportedEffect === "v4" && !servicesIdentifier) {
|
|
38165
|
+
changeTracker.insertNodeAt(
|
|
38166
|
+
sourceFile,
|
|
38167
|
+
effectGen.body.statements[0].pos,
|
|
38168
|
+
ts.factory.createVariableStatement(
|
|
38169
|
+
void 0,
|
|
38170
|
+
ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(
|
|
38171
|
+
"effectServices",
|
|
38172
|
+
void 0,
|
|
38173
|
+
void 0,
|
|
38174
|
+
ts.factory.createYieldExpression(
|
|
38175
|
+
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
38176
|
+
ts.factory.createCallExpression(
|
|
38177
|
+
ts.factory.createPropertyAccessExpression(
|
|
38178
|
+
ts.factory.createIdentifier(effectModuleIdentifier),
|
|
38179
|
+
"services"
|
|
38180
|
+
),
|
|
38181
|
+
[ts.factory.createKeywordTypeNode(ts.SyntaxKind.NeverKeyword)],
|
|
38182
|
+
[]
|
|
38183
|
+
)
|
|
38184
|
+
)
|
|
38185
|
+
)], ts.NodeFlags.Const)
|
|
38186
|
+
),
|
|
38187
|
+
{
|
|
38188
|
+
prefix: "\n",
|
|
38189
|
+
suffix: "\n"
|
|
38190
|
+
}
|
|
38191
|
+
);
|
|
38192
|
+
} else if (supportedEffect === "v3" && !runtimeIdentifier) {
|
|
38154
38193
|
changeTracker.insertNodeAt(
|
|
38155
38194
|
sourceFile,
|
|
38156
38195
|
effectGen.body.statements[0].pos,
|
|
@@ -38186,16 +38225,19 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
38186
38225
|
changeTracker.insertText(
|
|
38187
38226
|
sourceFile,
|
|
38188
38227
|
node.arguments[0].pos,
|
|
38189
|
-
`${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
|
|
38228
|
+
supportedEffect === "v4" ? `${effectModuleIdentifier}.${isEffectRunCall.value.methodName}With(${servicesIdentifier || "effectServices"})(` : `${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
|
|
38190
38229
|
);
|
|
38191
38230
|
});
|
|
38231
|
+
const v4MethodName = `${isEffectRunCall.value.methodName}With`;
|
|
38232
|
+
const messageText = supportedEffect === "v4" ? `Using ${nodeText} inside an Effect is not recommended. The same services should generally be used instead to run child effects.
|
|
38233
|
+
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.
|
|
38234
|
+
Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`;
|
|
38192
38235
|
report({
|
|
38193
38236
|
location: node.expression,
|
|
38194
|
-
messageText
|
|
38195
|
-
Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`,
|
|
38237
|
+
messageText,
|
|
38196
38238
|
fixes: [{
|
|
38197
38239
|
fixName: "runEffectInsideEffect_fix",
|
|
38198
|
-
description: "Use a runtime to run the Effect",
|
|
38240
|
+
description: supportedEffect === "v4" ? "Use the current services to run the Effect" : "Use a runtime to run the Effect",
|
|
38199
38241
|
apply: fixAddRuntime
|
|
38200
38242
|
}]
|
|
38201
38243
|
});
|
|
@@ -39861,11 +39903,12 @@ var metadata_default = {
|
|
|
39861
39903
|
{
|
|
39862
39904
|
name: "runEffectInsideEffect",
|
|
39863
39905
|
group: "antipattern",
|
|
39864
|
-
description: "Suggests using Runtime methods instead of Effect.run* inside Effect contexts",
|
|
39906
|
+
description: "Suggests using Runtime or Effect.run*With methods instead of Effect.run* inside Effect contexts",
|
|
39865
39907
|
defaultSeverity: "suggestion",
|
|
39866
39908
|
fixable: true,
|
|
39867
39909
|
supportedEffect: [
|
|
39868
|
-
"v3"
|
|
39910
|
+
"v3",
|
|
39911
|
+
"v4"
|
|
39869
39912
|
],
|
|
39870
39913
|
preview: {
|
|
39871
39914
|
sourceText: 'import { Effect } from "effect"\n\nexport const preview = Effect.gen(function*() {\n const run = () => Effect.runSync(Effect.succeed(1))\n return run()\n})\n',
|
|
@@ -39873,7 +39916,7 @@ var metadata_default = {
|
|
|
39873
39916
|
{
|
|
39874
39917
|
start: 101,
|
|
39875
39918
|
end: 115,
|
|
39876
|
-
text: "Using Effect.runSync inside an Effect is not recommended. The same
|
|
39919
|
+
text: "Using Effect.runSync inside an Effect is not recommended. The same services should generally be used instead to run child effects.\nConsider extracting the current services by using for example Effect.services and then use Effect.runSyncWith with the extracted services instead. effect(runEffectInsideEffect)"
|
|
39877
39920
|
}
|
|
39878
39921
|
]
|
|
39879
39922
|
}
|