@effect/language-service 0.50.0 → 0.51.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 +3 -0
- package/cli.js +52 -2
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +53 -2
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +74 -8
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +53 -2
- package/transform.js.map +1 -1
package/README.md
CHANGED
|
@@ -5,6 +5,8 @@ This package implements a TypeScript language service plugin that allows additio
|
|
|
5
5
|
## Installation
|
|
6
6
|
|
|
7
7
|
1. `npm install @effect/language-service --save-dev` in your project
|
|
8
|
+
- For monorepos: We suggest installing `@effect/language-service` in the monorepo root and configuring it in the root `tsconfig.json` for consistent behavior across all packages
|
|
9
|
+
- For any other package: Install directly in the package where you want to use it
|
|
8
10
|
2. Inside your tsconfig.json, you should add the plugin configuration as follows:
|
|
9
11
|
```jsonc
|
|
10
12
|
{
|
|
@@ -53,6 +55,7 @@ And you're done! You'll now be able to use a set of refactors and diagnostics th
|
|
|
53
55
|
- Warn on leaking requirements in Effect services
|
|
54
56
|
- Warn on Scope as requirement of a Layer
|
|
55
57
|
- Warn on subsequent `Effect.provide` anti-pattern
|
|
58
|
+
- Warn when using `Effect.provide` with Layer outside of application entry points
|
|
56
59
|
- Detect wrong `Self` type parameter for APIs like `Effect.Service` or `Schema.TaggedError` and similar
|
|
57
60
|
- Unnecessary usages of `Effect.gen` or `pipe()`
|
|
58
61
|
- Warn when using `Effect.gen` with the old generator adapter pattern
|
package/cli.js
CHANGED
|
@@ -33773,7 +33773,12 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
33773
33773
|
"pipe"
|
|
33774
33774
|
),
|
|
33775
33775
|
void 0,
|
|
33776
|
-
|
|
33776
|
+
pipe(
|
|
33777
|
+
parentChain,
|
|
33778
|
+
filter2(ts.isCallExpression),
|
|
33779
|
+
map4((call) => call.expression),
|
|
33780
|
+
reverse
|
|
33781
|
+
)
|
|
33777
33782
|
)
|
|
33778
33783
|
);
|
|
33779
33784
|
})
|
|
@@ -35068,6 +35073,50 @@ var strictBooleanExpressions = createDiagnostic({
|
|
|
35068
35073
|
})
|
|
35069
35074
|
});
|
|
35070
35075
|
|
|
35076
|
+
// src/diagnostics/strictEffectProvide.ts
|
|
35077
|
+
var strictEffectProvide = createDiagnostic({
|
|
35078
|
+
name: "strictEffectProvide",
|
|
35079
|
+
code: 27,
|
|
35080
|
+
severity: "off",
|
|
35081
|
+
apply: fn2("strictEffectProvide.apply")(function* (sourceFile, report) {
|
|
35082
|
+
const ts = yield* service2(TypeScriptApi);
|
|
35083
|
+
const typeChecker = yield* service2(TypeCheckerApi);
|
|
35084
|
+
const typeParser = yield* service2(TypeParser);
|
|
35085
|
+
const parseEffectProvideWithLayer = (node) => gen3(function* () {
|
|
35086
|
+
if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression) || !ts.isIdentifier(node.expression.name) || ts.idText(node.expression.name) !== "provide" || node.arguments.length === 0) {
|
|
35087
|
+
return yield* typeParserIssue("Not an Effect.provide call");
|
|
35088
|
+
}
|
|
35089
|
+
yield* typeParser.importedEffectModule(node.expression.expression);
|
|
35090
|
+
return yield* firstSuccessOf2(
|
|
35091
|
+
node.arguments.map((arg) => {
|
|
35092
|
+
const argType = typeChecker.getTypeAtLocation(arg);
|
|
35093
|
+
return typeParser.layerType(argType, arg);
|
|
35094
|
+
})
|
|
35095
|
+
);
|
|
35096
|
+
});
|
|
35097
|
+
const nodeToVisit = [];
|
|
35098
|
+
const appendNodeToVisit = (node) => {
|
|
35099
|
+
nodeToVisit.push(node);
|
|
35100
|
+
return void 0;
|
|
35101
|
+
};
|
|
35102
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
35103
|
+
while (nodeToVisit.length > 0) {
|
|
35104
|
+
const node = nodeToVisit.shift();
|
|
35105
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
35106
|
+
if (ts.isCallExpression(node)) {
|
|
35107
|
+
const layerCheck = yield* pipe(parseEffectProvideWithLayer(node), option4);
|
|
35108
|
+
if (isSome2(layerCheck)) {
|
|
35109
|
+
report({
|
|
35110
|
+
location: node,
|
|
35111
|
+
messageText: "Effect.provide with a Layer should only be used at application entry points. If this is an entry point, you can safely disable this diagnostic. Otherwise, using Effect.provide may break scope lifetimes. Compose all layers at your entry point and provide them at once.",
|
|
35112
|
+
fixes: []
|
|
35113
|
+
});
|
|
35114
|
+
}
|
|
35115
|
+
}
|
|
35116
|
+
}
|
|
35117
|
+
})
|
|
35118
|
+
});
|
|
35119
|
+
|
|
35071
35120
|
// src/diagnostics/tryCatchInEffectGen.ts
|
|
35072
35121
|
var tryCatchInEffectGen = createDiagnostic({
|
|
35073
35122
|
name: "tryCatchInEffectGen",
|
|
@@ -35358,7 +35407,8 @@ var diagnostics = [
|
|
|
35358
35407
|
unsupportedServiceAccessors,
|
|
35359
35408
|
nonObjectEffectServiceType,
|
|
35360
35409
|
deterministicKeys,
|
|
35361
|
-
missedPipeableOpportunity
|
|
35410
|
+
missedPipeableOpportunity,
|
|
35411
|
+
strictEffectProvide
|
|
35362
35412
|
];
|
|
35363
35413
|
|
|
35364
35414
|
// src/cli/diagnostics.ts
|