@effect/language-service 0.58.4 → 0.59.0
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 -0
- package/cli.js +140 -56
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +140 -56
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +5877 -5704
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +140 -56
- package/transform.js.map +1 -1
package/README.md
CHANGED
|
@@ -72,6 +72,7 @@ And you're done! You'll now be able to use a set of refactors and diagnostics th
|
|
|
72
72
|
- Warn when catch callbacks in `Effect.tryPromise`, `Effect.tryMap`, or `Effect.tryMapPromise` return `unknown` or `any` types
|
|
73
73
|
- Warn when using `Effect.runSync`, `Effect.runPromise`, `Effect.runFork`, or `Effect.runCallback` inside an Effect
|
|
74
74
|
- Warn when using `Schema.Union` with multiple `Schema.Literal` calls that can be simplified to a single `Schema.Literal` call
|
|
75
|
+
- Suggest using `Schema.TaggedStruct` instead of `Schema.Struct` when a `_tag` field with `Schema.Literal` is present to make the tag optional in the constructor
|
|
75
76
|
- Warn when using `yield* Effect.fail()` with yieldable error types that can be yielded directly
|
|
76
77
|
|
|
77
78
|
### Completions
|
package/cli.js
CHANGED
|
@@ -32329,67 +32329,69 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
32329
32329
|
"TypeParser.effectSubtype",
|
|
32330
32330
|
(type2) => type2
|
|
32331
32331
|
);
|
|
32332
|
-
const
|
|
32333
|
-
fn2("TypeParser.
|
|
32334
|
-
|
|
32335
|
-
|
|
32336
|
-
|
|
32337
|
-
|
|
32338
|
-
const
|
|
32339
|
-
if (!
|
|
32340
|
-
|
|
32341
|
-
|
|
32342
|
-
|
|
32343
|
-
|
|
32344
|
-
|
|
32345
|
-
|
|
32346
|
-
|
|
32347
|
-
|
|
32348
|
-
|
|
32349
|
-
|
|
32350
|
-
);
|
|
32351
|
-
if (!contextIdentifier) {
|
|
32352
|
-
return yield* typeParserIssue("Context module not found", void 0, node);
|
|
32353
|
-
}
|
|
32354
|
-
if (ts.idText(node) !== contextIdentifier) {
|
|
32355
|
-
return yield* typeParserIssue("Node is not a context module reference", void 0, node);
|
|
32356
|
-
}
|
|
32357
|
-
return node;
|
|
32332
|
+
const isEffectContextSourceFile = cachedBy(
|
|
32333
|
+
fn2("TypeParser.isEffectContextSourceFile")(function* (sourceFile) {
|
|
32334
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
32335
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
32336
|
+
const contextSymbol = typeChecker.tryGetMemberInModuleExports("Context", moduleSymbol);
|
|
32337
|
+
if (!contextSymbol) return yield* typeParserIssue("Context not found", void 0, sourceFile);
|
|
32338
|
+
const tagSymbol = typeChecker.tryGetMemberInModuleExports("Tag", moduleSymbol);
|
|
32339
|
+
if (!tagSymbol) return yield* typeParserIssue("Tag not found", void 0, sourceFile);
|
|
32340
|
+
const tagType = typeChecker.getDeclaredTypeOfSymbol(tagSymbol);
|
|
32341
|
+
yield* contextTag(tagType, sourceFile);
|
|
32342
|
+
return sourceFile;
|
|
32343
|
+
}),
|
|
32344
|
+
"TypeParser.isEffectContextSourceFile",
|
|
32345
|
+
(sourceFile) => sourceFile
|
|
32346
|
+
);
|
|
32347
|
+
const isNodeReferenceToEffectContextModuleApi = (memberName) => cachedBy(
|
|
32348
|
+
fn2("TypeParser.isNodeReferenceToEffectContextModuleApi")(function* (node) {
|
|
32349
|
+
return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectContextSourceFile, memberName);
|
|
32358
32350
|
}),
|
|
32351
|
+
`TypeParser.isNodeReferenceToEffectContextModuleApi(${memberName})`,
|
|
32352
|
+
(node) => node
|
|
32353
|
+
);
|
|
32354
|
+
const importedContextModule = cachedBy(
|
|
32355
|
+
(node) => pipe(
|
|
32356
|
+
isNodeReferenceToPackageModule(node, "effect", isEffectContextSourceFile),
|
|
32357
|
+
map34(() => node)
|
|
32358
|
+
),
|
|
32359
32359
|
"TypeParser.importedContextModule",
|
|
32360
32360
|
(node) => node
|
|
32361
32361
|
);
|
|
32362
|
-
const importedEffectModule = (
|
|
32363
|
-
|
|
32364
|
-
|
|
32362
|
+
const importedEffectModule = cachedBy(
|
|
32363
|
+
(node) => pipe(
|
|
32364
|
+
isNodeReferenceToPackageModule(node, "effect", isEffectTypeSourceFile),
|
|
32365
|
+
map34(() => node)
|
|
32366
|
+
),
|
|
32367
|
+
"TypeParser.importedEffectModule",
|
|
32368
|
+
(node) => node
|
|
32369
|
+
);
|
|
32370
|
+
const isEffectDataSourceFile = cachedBy(
|
|
32371
|
+
fn2("TypeParser.isEffectDataSourceFile")(function* (sourceFile) {
|
|
32372
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
32373
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
32374
|
+
const taggedEnumSymbol = typeChecker.tryGetMemberInModuleExports("TaggedEnum", moduleSymbol);
|
|
32375
|
+
if (!taggedEnumSymbol) return yield* typeParserIssue("TaggedEnum not found", void 0, sourceFile);
|
|
32376
|
+
const taggedErrorSymbol = typeChecker.tryGetMemberInModuleExports("TaggedError", moduleSymbol);
|
|
32377
|
+
if (!taggedErrorSymbol) return yield* typeParserIssue("TaggedError not found", void 0, sourceFile);
|
|
32378
|
+
return sourceFile;
|
|
32379
|
+
}),
|
|
32380
|
+
"TypeParser.isEffectDataSourceFile",
|
|
32381
|
+
(sourceFile) => sourceFile
|
|
32365
32382
|
);
|
|
32366
|
-
const
|
|
32367
|
-
fn2("TypeParser.
|
|
32368
|
-
|
|
32369
|
-
return yield* typeParserIssue("Node is not an expression", void 0, node);
|
|
32370
|
-
}
|
|
32371
|
-
const type2 = typeChecker.getTypeAtLocation(node);
|
|
32372
|
-
const propertySymbol = typeChecker.getPropertyOfType(type2, "TaggedError");
|
|
32373
|
-
if (!propertySymbol) {
|
|
32374
|
-
return yield* typeParserIssue("Type has no 'TaggedError' property", type2, node);
|
|
32375
|
-
}
|
|
32376
|
-
const sourceFile = tsUtils.getSourceFileOfNode(node);
|
|
32377
|
-
if (!sourceFile) {
|
|
32378
|
-
return yield* typeParserIssue("Node is not in a source file", void 0, node);
|
|
32379
|
-
}
|
|
32380
|
-
const dataIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
32381
|
-
sourceFile,
|
|
32382
|
-
"effect",
|
|
32383
|
-
"Data"
|
|
32384
|
-
);
|
|
32385
|
-
if (!dataIdentifier) {
|
|
32386
|
-
return yield* typeParserIssue("Data module not found", void 0, node);
|
|
32387
|
-
}
|
|
32388
|
-
if (ts.idText(node) !== dataIdentifier) {
|
|
32389
|
-
return yield* typeParserIssue("Node is not a data module reference", void 0, node);
|
|
32390
|
-
}
|
|
32391
|
-
return node;
|
|
32383
|
+
const isNodeReferenceToEffectDataModuleApi = (memberName) => cachedBy(
|
|
32384
|
+
fn2("TypeParser.isNodeReferenceToEffectDataModuleApi")(function* (node) {
|
|
32385
|
+
return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectDataSourceFile, memberName);
|
|
32392
32386
|
}),
|
|
32387
|
+
`TypeParser.isNodeReferenceToEffectDataModuleApi(${memberName})`,
|
|
32388
|
+
(node) => node
|
|
32389
|
+
);
|
|
32390
|
+
const importedDataModule = cachedBy(
|
|
32391
|
+
(node) => pipe(
|
|
32392
|
+
isNodeReferenceToPackageModule(node, "effect", isEffectDataSourceFile),
|
|
32393
|
+
map34(() => node)
|
|
32394
|
+
),
|
|
32393
32395
|
"TypeParser.importedDataModule",
|
|
32394
32396
|
(node) => node
|
|
32395
32397
|
);
|
|
@@ -33128,6 +33130,8 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
33128
33130
|
return {
|
|
33129
33131
|
isNodeReferenceToEffectModuleApi,
|
|
33130
33132
|
isNodeReferenceToEffectSchemaModuleApi,
|
|
33133
|
+
isNodeReferenceToEffectDataModuleApi,
|
|
33134
|
+
isNodeReferenceToEffectContextModuleApi,
|
|
33131
33135
|
effectType,
|
|
33132
33136
|
strictEffectType,
|
|
33133
33137
|
layerType,
|
|
@@ -35680,6 +35684,85 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
|
|
|
35680
35684
|
})
|
|
35681
35685
|
});
|
|
35682
35686
|
|
|
35687
|
+
// src/diagnostics/schemaStructWithTag.ts
|
|
35688
|
+
var schemaStructWithTag = createDiagnostic({
|
|
35689
|
+
name: "schemaStructWithTag",
|
|
35690
|
+
code: 34,
|
|
35691
|
+
severity: "suggestion",
|
|
35692
|
+
apply: fn2("schemaStructWithTag.apply")(function* (sourceFile, report) {
|
|
35693
|
+
const ts = yield* service2(TypeScriptApi);
|
|
35694
|
+
const typeParser = yield* service2(TypeParser);
|
|
35695
|
+
const nodeToVisit = [];
|
|
35696
|
+
const appendNodeToVisit = (node) => {
|
|
35697
|
+
nodeToVisit.push(node);
|
|
35698
|
+
return void 0;
|
|
35699
|
+
};
|
|
35700
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
35701
|
+
while (nodeToVisit.length > 0) {
|
|
35702
|
+
const node = nodeToVisit.shift();
|
|
35703
|
+
if (ts.isCallExpression(node)) {
|
|
35704
|
+
const isSchemaStructCall = yield* pipe(
|
|
35705
|
+
typeParser.isNodeReferenceToEffectSchemaModuleApi("Struct")(node.expression),
|
|
35706
|
+
orElse14(() => void_8)
|
|
35707
|
+
);
|
|
35708
|
+
if (isSchemaStructCall && node.arguments.length === 1) {
|
|
35709
|
+
const arg = node.arguments[0];
|
|
35710
|
+
if (ts.isObjectLiteralExpression(arg)) {
|
|
35711
|
+
const tagProperty = arg.properties.find(
|
|
35712
|
+
(prop) => ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && ts.idText(prop.name) === "_tag"
|
|
35713
|
+
);
|
|
35714
|
+
if (tagProperty && ts.isCallExpression(tagProperty.initializer)) {
|
|
35715
|
+
const isSchemaLiteralCall = yield* pipe(
|
|
35716
|
+
typeParser.isNodeReferenceToEffectSchemaModuleApi("Literal")(
|
|
35717
|
+
tagProperty.initializer.expression
|
|
35718
|
+
),
|
|
35719
|
+
option4
|
|
35720
|
+
);
|
|
35721
|
+
if (isSchemaLiteralCall._tag === "Some") {
|
|
35722
|
+
const literalCall = tagProperty.initializer;
|
|
35723
|
+
const literalArgs = fromIterable(literalCall.arguments);
|
|
35724
|
+
if (literalArgs.length === 1 && ts.isStringLiteral(literalArgs[0])) {
|
|
35725
|
+
const tagValue = literalArgs[0].text;
|
|
35726
|
+
const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
|
|
35727
|
+
report({
|
|
35728
|
+
location: node,
|
|
35729
|
+
messageText: "Schema.Struct with a _tag field can be simplified to Schema.TaggedStruct to make the tag optional in the constructor.",
|
|
35730
|
+
fixes: [{
|
|
35731
|
+
fixName: "schemaStructWithTag_fix",
|
|
35732
|
+
description: "Replace with Schema.TaggedStruct",
|
|
35733
|
+
apply: gen3(function* () {
|
|
35734
|
+
const changeTracker = yield* service2(ChangeTracker);
|
|
35735
|
+
const newObjectLiteral = ts.factory.createObjectLiteralExpression(
|
|
35736
|
+
otherProperties,
|
|
35737
|
+
true
|
|
35738
|
+
);
|
|
35739
|
+
const newNode = ts.factory.createCallExpression(
|
|
35740
|
+
ts.factory.createPropertyAccessExpression(
|
|
35741
|
+
// Reuse the Schema identifier from the original expression
|
|
35742
|
+
ts.isPropertyAccessExpression(node.expression) ? node.expression.expression : ts.factory.createIdentifier("Schema"),
|
|
35743
|
+
"TaggedStruct"
|
|
35744
|
+
),
|
|
35745
|
+
void 0,
|
|
35746
|
+
[
|
|
35747
|
+
ts.factory.createStringLiteral(tagValue),
|
|
35748
|
+
newObjectLiteral
|
|
35749
|
+
]
|
|
35750
|
+
);
|
|
35751
|
+
changeTracker.replaceNode(sourceFile, node, newNode);
|
|
35752
|
+
})
|
|
35753
|
+
}]
|
|
35754
|
+
});
|
|
35755
|
+
}
|
|
35756
|
+
}
|
|
35757
|
+
}
|
|
35758
|
+
}
|
|
35759
|
+
}
|
|
35760
|
+
}
|
|
35761
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
35762
|
+
}
|
|
35763
|
+
})
|
|
35764
|
+
});
|
|
35765
|
+
|
|
35683
35766
|
// src/diagnostics/schemaUnionOfLiterals.ts
|
|
35684
35767
|
var schemaUnionOfLiterals = createDiagnostic({
|
|
35685
35768
|
name: "schemaUnionOfLiterals",
|
|
@@ -36371,7 +36454,8 @@ var diagnostics = [
|
|
|
36371
36454
|
strictEffectProvide,
|
|
36372
36455
|
unknownInEffectCatch,
|
|
36373
36456
|
runEffectInsideEffect,
|
|
36374
|
-
schemaUnionOfLiterals
|
|
36457
|
+
schemaUnionOfLiterals,
|
|
36458
|
+
schemaStructWithTag
|
|
36375
36459
|
];
|
|
36376
36460
|
|
|
36377
36461
|
// src/cli/diagnostics.ts
|