@effect/language-service 0.58.4 → 0.60.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 +3 -1
- package/cli.js +144 -58
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +144 -58
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +5886 -5705
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +144 -58
- 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
|
|
@@ -140,7 +141,8 @@ Few options can be provided alongside the initialization of the Language Service
|
|
|
140
141
|
"importAliases": { "Array": "Arr" }, // allows to chose some different names for import name aliases (only when not chosing to import the whole module) (default: {})
|
|
141
142
|
"noExternal": false, // disables features that provides links to external websites (such as links to mermaidchart.com) (default: false)
|
|
142
143
|
"keyPatterns": [{ "target": "service", "pattern": "default", "skipLeadingPath": ["src/"] }], // configure the key patterns; recommended reading more on the section "Configuring Key Patterns"
|
|
143
|
-
"layerGraphFollowDepth": 0 // controls the depth level that the layer graph will follow when resolving layer dependencies, depth is counted only when exiting the currently hovered/analyzed layer definition (default: 0)
|
|
144
|
+
"layerGraphFollowDepth": 0, // controls the depth level that the layer graph will follow when resolving layer dependencies, depth is counted only when exiting the currently hovered/analyzed layer definition (default: 0)
|
|
145
|
+
"mermaidProvider": "mermaid.live" // which provider to use for mermaid, can also be a uri like http://localhost:8080 if running mermaid-live-editor locally.
|
|
144
146
|
}
|
|
145
147
|
]
|
|
146
148
|
}
|
package/cli.js
CHANGED
|
@@ -31275,7 +31275,8 @@ var defaults = {
|
|
|
31275
31275
|
}],
|
|
31276
31276
|
extendedKeyDetection: false,
|
|
31277
31277
|
pipeableMinArgCount: 1,
|
|
31278
|
-
layerGraphFollowDepth: 0
|
|
31278
|
+
layerGraphFollowDepth: 0,
|
|
31279
|
+
mermaidProvider: "mermaid.live"
|
|
31279
31280
|
};
|
|
31280
31281
|
function parseKeyPatterns(patterns) {
|
|
31281
31282
|
const result = [];
|
|
@@ -31313,7 +31314,8 @@ function parse4(config2) {
|
|
|
31313
31314
|
keyPatterns: isObject(config2) && hasProperty(config2, "keyPatterns") && isArray(config2.keyPatterns) ? parseKeyPatterns(config2.keyPatterns) : defaults.keyPatterns,
|
|
31314
31315
|
extendedKeyDetection: isObject(config2) && hasProperty(config2, "extendedKeyDetection") && isBoolean(config2.extendedKeyDetection) ? config2.extendedKeyDetection : defaults.extendedKeyDetection,
|
|
31315
31316
|
pipeableMinArgCount: isObject(config2) && hasProperty(config2, "pipeableMinArgCount") && isNumber(config2.pipeableMinArgCount) ? config2.pipeableMinArgCount : defaults.pipeableMinArgCount,
|
|
31316
|
-
layerGraphFollowDepth: isObject(config2) && hasProperty(config2, "layerGraphFollowDepth") && isNumber(config2.layerGraphFollowDepth) ? config2.layerGraphFollowDepth : defaults.layerGraphFollowDepth
|
|
31317
|
+
layerGraphFollowDepth: isObject(config2) && hasProperty(config2, "layerGraphFollowDepth") && isNumber(config2.layerGraphFollowDepth) ? config2.layerGraphFollowDepth : defaults.layerGraphFollowDepth,
|
|
31318
|
+
mermaidProvider: isObject(config2) && hasProperty(config2, "mermaidProvider") && isString(config2.mermaidProvider) ? config2.mermaidProvider : defaults.mermaidProvider
|
|
31317
31319
|
};
|
|
31318
31320
|
}
|
|
31319
31321
|
|
|
@@ -32329,67 +32331,69 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
32329
32331
|
"TypeParser.effectSubtype",
|
|
32330
32332
|
(type2) => type2
|
|
32331
32333
|
);
|
|
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;
|
|
32334
|
+
const isEffectContextSourceFile = cachedBy(
|
|
32335
|
+
fn2("TypeParser.isEffectContextSourceFile")(function* (sourceFile) {
|
|
32336
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
32337
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
32338
|
+
const contextSymbol = typeChecker.tryGetMemberInModuleExports("Context", moduleSymbol);
|
|
32339
|
+
if (!contextSymbol) return yield* typeParserIssue("Context not found", void 0, sourceFile);
|
|
32340
|
+
const tagSymbol = typeChecker.tryGetMemberInModuleExports("Tag", moduleSymbol);
|
|
32341
|
+
if (!tagSymbol) return yield* typeParserIssue("Tag not found", void 0, sourceFile);
|
|
32342
|
+
const tagType = typeChecker.getDeclaredTypeOfSymbol(tagSymbol);
|
|
32343
|
+
yield* contextTag(tagType, sourceFile);
|
|
32344
|
+
return sourceFile;
|
|
32345
|
+
}),
|
|
32346
|
+
"TypeParser.isEffectContextSourceFile",
|
|
32347
|
+
(sourceFile) => sourceFile
|
|
32348
|
+
);
|
|
32349
|
+
const isNodeReferenceToEffectContextModuleApi = (memberName) => cachedBy(
|
|
32350
|
+
fn2("TypeParser.isNodeReferenceToEffectContextModuleApi")(function* (node) {
|
|
32351
|
+
return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectContextSourceFile, memberName);
|
|
32358
32352
|
}),
|
|
32353
|
+
`TypeParser.isNodeReferenceToEffectContextModuleApi(${memberName})`,
|
|
32354
|
+
(node) => node
|
|
32355
|
+
);
|
|
32356
|
+
const importedContextModule = cachedBy(
|
|
32357
|
+
(node) => pipe(
|
|
32358
|
+
isNodeReferenceToPackageModule(node, "effect", isEffectContextSourceFile),
|
|
32359
|
+
map34(() => node)
|
|
32360
|
+
),
|
|
32359
32361
|
"TypeParser.importedContextModule",
|
|
32360
32362
|
(node) => node
|
|
32361
32363
|
);
|
|
32362
|
-
const importedEffectModule = (
|
|
32363
|
-
|
|
32364
|
-
|
|
32364
|
+
const importedEffectModule = cachedBy(
|
|
32365
|
+
(node) => pipe(
|
|
32366
|
+
isNodeReferenceToPackageModule(node, "effect", isEffectTypeSourceFile),
|
|
32367
|
+
map34(() => node)
|
|
32368
|
+
),
|
|
32369
|
+
"TypeParser.importedEffectModule",
|
|
32370
|
+
(node) => node
|
|
32371
|
+
);
|
|
32372
|
+
const isEffectDataSourceFile = cachedBy(
|
|
32373
|
+
fn2("TypeParser.isEffectDataSourceFile")(function* (sourceFile) {
|
|
32374
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
32375
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
32376
|
+
const taggedEnumSymbol = typeChecker.tryGetMemberInModuleExports("TaggedEnum", moduleSymbol);
|
|
32377
|
+
if (!taggedEnumSymbol) return yield* typeParserIssue("TaggedEnum not found", void 0, sourceFile);
|
|
32378
|
+
const taggedErrorSymbol = typeChecker.tryGetMemberInModuleExports("TaggedError", moduleSymbol);
|
|
32379
|
+
if (!taggedErrorSymbol) return yield* typeParserIssue("TaggedError not found", void 0, sourceFile);
|
|
32380
|
+
return sourceFile;
|
|
32381
|
+
}),
|
|
32382
|
+
"TypeParser.isEffectDataSourceFile",
|
|
32383
|
+
(sourceFile) => sourceFile
|
|
32365
32384
|
);
|
|
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;
|
|
32385
|
+
const isNodeReferenceToEffectDataModuleApi = (memberName) => cachedBy(
|
|
32386
|
+
fn2("TypeParser.isNodeReferenceToEffectDataModuleApi")(function* (node) {
|
|
32387
|
+
return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectDataSourceFile, memberName);
|
|
32392
32388
|
}),
|
|
32389
|
+
`TypeParser.isNodeReferenceToEffectDataModuleApi(${memberName})`,
|
|
32390
|
+
(node) => node
|
|
32391
|
+
);
|
|
32392
|
+
const importedDataModule = cachedBy(
|
|
32393
|
+
(node) => pipe(
|
|
32394
|
+
isNodeReferenceToPackageModule(node, "effect", isEffectDataSourceFile),
|
|
32395
|
+
map34(() => node)
|
|
32396
|
+
),
|
|
32393
32397
|
"TypeParser.importedDataModule",
|
|
32394
32398
|
(node) => node
|
|
32395
32399
|
);
|
|
@@ -33128,6 +33132,8 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
33128
33132
|
return {
|
|
33129
33133
|
isNodeReferenceToEffectModuleApi,
|
|
33130
33134
|
isNodeReferenceToEffectSchemaModuleApi,
|
|
33135
|
+
isNodeReferenceToEffectDataModuleApi,
|
|
33136
|
+
isNodeReferenceToEffectContextModuleApi,
|
|
33131
33137
|
effectType,
|
|
33132
33138
|
strictEffectType,
|
|
33133
33139
|
layerType,
|
|
@@ -35680,6 +35686,85 @@ Consider extracting the Runtime by using for example Effect.runtime and then use
|
|
|
35680
35686
|
})
|
|
35681
35687
|
});
|
|
35682
35688
|
|
|
35689
|
+
// src/diagnostics/schemaStructWithTag.ts
|
|
35690
|
+
var schemaStructWithTag = createDiagnostic({
|
|
35691
|
+
name: "schemaStructWithTag",
|
|
35692
|
+
code: 34,
|
|
35693
|
+
severity: "suggestion",
|
|
35694
|
+
apply: fn2("schemaStructWithTag.apply")(function* (sourceFile, report) {
|
|
35695
|
+
const ts = yield* service2(TypeScriptApi);
|
|
35696
|
+
const typeParser = yield* service2(TypeParser);
|
|
35697
|
+
const nodeToVisit = [];
|
|
35698
|
+
const appendNodeToVisit = (node) => {
|
|
35699
|
+
nodeToVisit.push(node);
|
|
35700
|
+
return void 0;
|
|
35701
|
+
};
|
|
35702
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
35703
|
+
while (nodeToVisit.length > 0) {
|
|
35704
|
+
const node = nodeToVisit.shift();
|
|
35705
|
+
if (ts.isCallExpression(node)) {
|
|
35706
|
+
const isSchemaStructCall = yield* pipe(
|
|
35707
|
+
typeParser.isNodeReferenceToEffectSchemaModuleApi("Struct")(node.expression),
|
|
35708
|
+
orElse14(() => void_8)
|
|
35709
|
+
);
|
|
35710
|
+
if (isSchemaStructCall && node.arguments.length === 1) {
|
|
35711
|
+
const arg = node.arguments[0];
|
|
35712
|
+
if (ts.isObjectLiteralExpression(arg)) {
|
|
35713
|
+
const tagProperty = arg.properties.find(
|
|
35714
|
+
(prop) => ts.isPropertyAssignment(prop) && ts.isIdentifier(prop.name) && ts.idText(prop.name) === "_tag"
|
|
35715
|
+
);
|
|
35716
|
+
if (tagProperty && ts.isCallExpression(tagProperty.initializer)) {
|
|
35717
|
+
const isSchemaLiteralCall = yield* pipe(
|
|
35718
|
+
typeParser.isNodeReferenceToEffectSchemaModuleApi("Literal")(
|
|
35719
|
+
tagProperty.initializer.expression
|
|
35720
|
+
),
|
|
35721
|
+
option4
|
|
35722
|
+
);
|
|
35723
|
+
if (isSchemaLiteralCall._tag === "Some") {
|
|
35724
|
+
const literalCall = tagProperty.initializer;
|
|
35725
|
+
const literalArgs = fromIterable(literalCall.arguments);
|
|
35726
|
+
if (literalArgs.length === 1 && ts.isStringLiteral(literalArgs[0])) {
|
|
35727
|
+
const tagValue = literalArgs[0].text;
|
|
35728
|
+
const otherProperties = arg.properties.filter((prop) => prop !== tagProperty);
|
|
35729
|
+
report({
|
|
35730
|
+
location: node,
|
|
35731
|
+
messageText: "Schema.Struct with a _tag field can be simplified to Schema.TaggedStruct to make the tag optional in the constructor.",
|
|
35732
|
+
fixes: [{
|
|
35733
|
+
fixName: "schemaStructWithTag_fix",
|
|
35734
|
+
description: "Replace with Schema.TaggedStruct",
|
|
35735
|
+
apply: gen3(function* () {
|
|
35736
|
+
const changeTracker = yield* service2(ChangeTracker);
|
|
35737
|
+
const newObjectLiteral = ts.factory.createObjectLiteralExpression(
|
|
35738
|
+
otherProperties,
|
|
35739
|
+
true
|
|
35740
|
+
);
|
|
35741
|
+
const newNode = ts.factory.createCallExpression(
|
|
35742
|
+
ts.factory.createPropertyAccessExpression(
|
|
35743
|
+
// Reuse the Schema identifier from the original expression
|
|
35744
|
+
ts.isPropertyAccessExpression(node.expression) ? node.expression.expression : ts.factory.createIdentifier("Schema"),
|
|
35745
|
+
"TaggedStruct"
|
|
35746
|
+
),
|
|
35747
|
+
void 0,
|
|
35748
|
+
[
|
|
35749
|
+
ts.factory.createStringLiteral(tagValue),
|
|
35750
|
+
newObjectLiteral
|
|
35751
|
+
]
|
|
35752
|
+
);
|
|
35753
|
+
changeTracker.replaceNode(sourceFile, node, newNode);
|
|
35754
|
+
})
|
|
35755
|
+
}]
|
|
35756
|
+
});
|
|
35757
|
+
}
|
|
35758
|
+
}
|
|
35759
|
+
}
|
|
35760
|
+
}
|
|
35761
|
+
}
|
|
35762
|
+
}
|
|
35763
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
35764
|
+
}
|
|
35765
|
+
})
|
|
35766
|
+
});
|
|
35767
|
+
|
|
35683
35768
|
// src/diagnostics/schemaUnionOfLiterals.ts
|
|
35684
35769
|
var schemaUnionOfLiterals = createDiagnostic({
|
|
35685
35770
|
name: "schemaUnionOfLiterals",
|
|
@@ -36371,7 +36456,8 @@ var diagnostics = [
|
|
|
36371
36456
|
strictEffectProvide,
|
|
36372
36457
|
unknownInEffectCatch,
|
|
36373
36458
|
runEffectInsideEffect,
|
|
36374
|
-
schemaUnionOfLiterals
|
|
36459
|
+
schemaUnionOfLiterals,
|
|
36460
|
+
schemaStructWithTag
|
|
36375
36461
|
];
|
|
36376
36462
|
|
|
36377
36463
|
// src/cli/diagnostics.ts
|