@effect/language-service 0.9.0 → 0.9.2
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/LICENSE +21 -0
- package/README.md +69 -0
- package/index.js +48 -17
- package/index.js.map +1 -1
- package/package.json +1 -1
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Effectful Technologies Inc
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,69 @@
|
|
|
1
|
+
# language-service
|
|
2
|
+
|
|
3
|
+
This package implements a TypeScript language service plugin that allows additional refactors and diagnostics with your VSCode editor (or any editor that supports TypeScript's LSP).
|
|
4
|
+
|
|
5
|
+
## Installation
|
|
6
|
+
|
|
7
|
+
1) `npm install @effect/language-service --save-dev` in your project
|
|
8
|
+
2) inside your tsconfig.json, you should add the plugin configuration as follows:
|
|
9
|
+
|
|
10
|
+
```json
|
|
11
|
+
{
|
|
12
|
+
"compilerOptions": {
|
|
13
|
+
"plugins": [
|
|
14
|
+
{
|
|
15
|
+
"name": "@effect/language-service"
|
|
16
|
+
}
|
|
17
|
+
]
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
```
|
|
21
|
+
3) Ensure that you set your editor to use your workspace TypeScript version.
|
|
22
|
+
|
|
23
|
+
- In VSCode you can do this by pressing "F1" and typing "TypeScript: Select TypeScript version". Then select "Use workspace version".
|
|
24
|
+
- In JetBrains you may have to disable the Vue language service, and chose the workspace version of TypeScript in the settings from the dropdown.
|
|
25
|
+
|
|
26
|
+
And you're done! You'll now be able to use a set of refactor and diagnostics that targets Effect!
|
|
27
|
+
|
|
28
|
+
## Options
|
|
29
|
+
|
|
30
|
+
Few options can be provided alongside the initialization of the Language Service Plugin.
|
|
31
|
+
|
|
32
|
+
```json
|
|
33
|
+
{
|
|
34
|
+
"compilerOptions": {
|
|
35
|
+
"plugins": [
|
|
36
|
+
{
|
|
37
|
+
"name": "@effect/language-service",
|
|
38
|
+
"diagnostics": true, // controls Effect diagnostics (on by default)
|
|
39
|
+
"quickinfo": true // controls quickinfo over Effect (on by default)
|
|
40
|
+
}
|
|
41
|
+
]
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## Provided functionalities
|
|
47
|
+
|
|
48
|
+
### Quickinfo
|
|
49
|
+
- Show the extended type of the current Effect
|
|
50
|
+
|
|
51
|
+
### Diagnostics
|
|
52
|
+
|
|
53
|
+
- Better error readability when you're missing errors or service types in your Effect definitions
|
|
54
|
+
- Detect floating Effects that are not yielded or run
|
|
55
|
+
- Detect wrong usage of yield inside Effect.gen
|
|
56
|
+
- Detect unnecessary usages of Effect.gen
|
|
57
|
+
|
|
58
|
+
### Completions
|
|
59
|
+
- Autocomplete 'Self' in Effect.Service, Context.Tag, Schema.TaggedClass, Schema.TaggedRequest and family
|
|
60
|
+
|
|
61
|
+
### Refactors
|
|
62
|
+
|
|
63
|
+
- Transform an async function definition, into an Effect by using Effect.gen.
|
|
64
|
+
- Transform an async function definition, into an Effect by using Effect.gen, and generating a tagged error for each promise call.
|
|
65
|
+
- Transform a function returning an Effect.gen into a Effect.fn
|
|
66
|
+
- Function calls to pipe: Transform a set of function calls to a pipe() call.
|
|
67
|
+
- Pipe to datafirst: Transform a pipe() call into a series of datafirst function calls (where available).
|
|
68
|
+
- Toggle return type signature: With a single refactor, adds or removes type annotations from the definition.
|
|
69
|
+
- Remove unnecessary `Effect.gen` definitions that contains a single `yield` statement.
|
package/index.js
CHANGED
|
@@ -2892,10 +2892,9 @@ function collectSelfAndAncestorNodesInRange(node, textRange) {
|
|
|
2892
2892
|
});
|
|
2893
2893
|
}
|
|
2894
2894
|
var getAncestorNodesInRange = fn("AST.getAncestorNodesInRange")(function* (sourceFile, textRange) {
|
|
2895
|
-
const
|
|
2896
|
-
|
|
2897
|
-
|
|
2898
|
-
return yield* collectSelfAndAncestorNodesInRange(precedingToken, textRange);
|
|
2895
|
+
const nodeAtPosition = yield* option(findNodeAtPosition(sourceFile, textRange.pos));
|
|
2896
|
+
if (isNone2(nodeAtPosition)) return empty();
|
|
2897
|
+
return yield* collectSelfAndAncestorNodesInRange(nodeAtPosition.value, textRange);
|
|
2899
2898
|
});
|
|
2900
2899
|
var NodeNotFoundError = class extends TaggedError("@effect/language-service/NodeNotFoundError") {
|
|
2901
2900
|
};
|
|
@@ -2911,13 +2910,6 @@ var findNodeAtPosition = fn("AST.findNodeAtPosition")(function* (sourceFile, pos
|
|
|
2911
2910
|
if (!result) return yield* fail3(new NodeNotFoundError());
|
|
2912
2911
|
return result;
|
|
2913
2912
|
});
|
|
2914
|
-
var collectDescendantsAndAncestorsInRange = fn(
|
|
2915
|
-
"AST.collectDescendantsAndAncestorsInRange"
|
|
2916
|
-
)(function* (sourceFile, textRange) {
|
|
2917
|
-
const nodeAtPosition = yield* option(findNodeAtPosition(sourceFile, textRange.pos));
|
|
2918
|
-
if (isNone2(nodeAtPosition)) return empty();
|
|
2919
|
-
return yield* collectSelfAndAncestorNodesInRange(nodeAtPosition.value, textRange);
|
|
2920
|
-
});
|
|
2921
2913
|
function toTextRange(positionOrRange) {
|
|
2922
2914
|
return typeof positionOrRange === "number" ? { end: positionOrRange, pos: positionOrRange } : positionOrRange;
|
|
2923
2915
|
}
|
|
@@ -3208,6 +3200,43 @@ var contextSelfInClasses = createCompletion({
|
|
|
3208
3200
|
})
|
|
3209
3201
|
});
|
|
3210
3202
|
|
|
3203
|
+
// src/completions/effectDataClasses.ts
|
|
3204
|
+
var effectDataClasses = createCompletion({
|
|
3205
|
+
name: "effect/effectDataClasses",
|
|
3206
|
+
apply: fn("effectDataClasses")(function* (sourceFile, position) {
|
|
3207
|
+
const ts = yield* service(TypeScriptApi);
|
|
3208
|
+
const maybeInfos = yield* parseDataForExtendsClassCompletion(sourceFile, position);
|
|
3209
|
+
if (isNone2(maybeInfos)) return [];
|
|
3210
|
+
const { accessedObject, className, replacementSpan } = maybeInfos.value;
|
|
3211
|
+
const dataName = yield* option(
|
|
3212
|
+
findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
3213
|
+
sourceFile,
|
|
3214
|
+
"effect",
|
|
3215
|
+
"Data"
|
|
3216
|
+
)
|
|
3217
|
+
);
|
|
3218
|
+
const effectDataIdentifier = match2(dataName, {
|
|
3219
|
+
onNone: () => "Data",
|
|
3220
|
+
onSome: (_) => _.text
|
|
3221
|
+
});
|
|
3222
|
+
if (effectDataIdentifier !== accessedObject.text) return [];
|
|
3223
|
+
const name = className.text;
|
|
3224
|
+
return [{
|
|
3225
|
+
name: `TaggedError("${name}")`,
|
|
3226
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3227
|
+
insertText: `${effectDataIdentifier}.TaggedError("${name}")<{${"${0}"}}>{}`,
|
|
3228
|
+
replacementSpan,
|
|
3229
|
+
isSnippet: true
|
|
3230
|
+
}, {
|
|
3231
|
+
name: `TaggedClass("${name}")`,
|
|
3232
|
+
kind: ts.ScriptElementKind.constElement,
|
|
3233
|
+
insertText: `${effectDataIdentifier}.TaggedClass("${name}")<{${"${0}"}}>{}`,
|
|
3234
|
+
replacementSpan,
|
|
3235
|
+
isSnippet: true
|
|
3236
|
+
}];
|
|
3237
|
+
})
|
|
3238
|
+
});
|
|
3239
|
+
|
|
3211
3240
|
// src/completions/effectSchemaSelfInClasses.ts
|
|
3212
3241
|
var effectSchemaSelfInClasses = createCompletion({
|
|
3213
3242
|
name: "effect/effectSchemaSelfInClasses",
|
|
@@ -3289,7 +3318,12 @@ var effectSelfInClasses = createCompletion({
|
|
|
3289
3318
|
});
|
|
3290
3319
|
|
|
3291
3320
|
// src/completions.ts
|
|
3292
|
-
var completions = [
|
|
3321
|
+
var completions = [
|
|
3322
|
+
effectSchemaSelfInClasses,
|
|
3323
|
+
effectSelfInClasses,
|
|
3324
|
+
contextSelfInClasses,
|
|
3325
|
+
effectDataClasses
|
|
3326
|
+
];
|
|
3293
3327
|
|
|
3294
3328
|
// src/utils/TypeCheckerApi.ts
|
|
3295
3329
|
var TypeCheckerApi = Tag("TypeChecker");
|
|
@@ -4462,10 +4496,7 @@ var removeUnnecessaryEffectGen = createRefactor({
|
|
|
4462
4496
|
name: "effect/removeUnnecessaryEffectGen",
|
|
4463
4497
|
description: "Remove unnecessary Effect.gen",
|
|
4464
4498
|
apply: (sourceFile, textRange) => gen2(function* () {
|
|
4465
|
-
for (const nodeToReplace of yield*
|
|
4466
|
-
sourceFile,
|
|
4467
|
-
textRange
|
|
4468
|
-
)) {
|
|
4499
|
+
for (const nodeToReplace of yield* getAncestorNodesInRange(sourceFile, textRange)) {
|
|
4469
4500
|
const maybeNode = yield* pipe(
|
|
4470
4501
|
effectGen(nodeToReplace),
|
|
4471
4502
|
flatMap4(({ body }) => returnYieldEffectBlock(body)),
|
|
@@ -4489,7 +4520,7 @@ var removeUnnecessaryEffectGen = createRefactor({
|
|
|
4489
4520
|
// src/refactors/toggleLazyConst.ts
|
|
4490
4521
|
var toggleLazyConst = createRefactor({
|
|
4491
4522
|
name: "effect/toggleLazyConst",
|
|
4492
|
-
description: "Toggle
|
|
4523
|
+
description: "Toggle lazy const",
|
|
4493
4524
|
apply: (sourceFile, textRange) => gen2(function* () {
|
|
4494
4525
|
const ts = yield* service(TypeScriptApi);
|
|
4495
4526
|
const maybeNode = pipe(
|