@effect/language-service 0.37.0 → 0.38.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 -0
- package/cli.js +2 -1
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +9 -11
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +305 -11
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +9 -11
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -2622,8 +2622,7 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
|
|
|
2622
2622
|
node,
|
|
2623
2623
|
effectModule,
|
|
2624
2624
|
generatorFunction,
|
|
2625
|
-
body: generatorFunction.body
|
|
2626
|
-
functionStar: generatorFunction.getFirstToken()
|
|
2625
|
+
body: generatorFunction.body
|
|
2627
2626
|
}))
|
|
2628
2627
|
);
|
|
2629
2628
|
},
|
|
@@ -2670,8 +2669,7 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
|
|
|
2670
2669
|
node,
|
|
2671
2670
|
effectModule,
|
|
2672
2671
|
generatorFunction,
|
|
2673
|
-
body: generatorFunction.body
|
|
2674
|
-
functionStar: generatorFunction.getFirstToken()
|
|
2672
|
+
body: generatorFunction.body
|
|
2675
2673
|
}))
|
|
2676
2674
|
);
|
|
2677
2675
|
},
|
|
@@ -2723,8 +2721,7 @@ function make3(ts, tsUtils, typeChecker, typeCheckerUtils) {
|
|
|
2723
2721
|
node,
|
|
2724
2722
|
generatorFunction,
|
|
2725
2723
|
effectModule,
|
|
2726
|
-
body: generatorFunction.body
|
|
2727
|
-
functionStar: generatorFunction.getFirstToken()
|
|
2724
|
+
body: generatorFunction.body
|
|
2728
2725
|
}))
|
|
2729
2726
|
);
|
|
2730
2727
|
},
|
|
@@ -4564,6 +4561,7 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
4564
4561
|
apply: fn("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
|
|
4565
4562
|
const ts = yield* service(TypeScriptApi);
|
|
4566
4563
|
const typeParser = yield* service(TypeParser);
|
|
4564
|
+
const tsUtils = yield* service(TypeScriptUtils);
|
|
4567
4565
|
const brokenGenerators = /* @__PURE__ */ new Set();
|
|
4568
4566
|
const brokenYields = /* @__PURE__ */ new Set();
|
|
4569
4567
|
const nodeToVisit = [];
|
|
@@ -4586,9 +4584,9 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
4586
4584
|
typeParser.effectGen(effectGenNode),
|
|
4587
4585
|
orElse2(() => typeParser.effectFnUntracedGen(effectGenNode)),
|
|
4588
4586
|
orElse2(() => typeParser.effectFnGen(effectGenNode)),
|
|
4589
|
-
map3(({
|
|
4590
|
-
if (
|
|
4591
|
-
brokenGenerators.add(
|
|
4587
|
+
map3(({ generatorFunction }) => {
|
|
4588
|
+
if (generatorFunction) {
|
|
4589
|
+
brokenGenerators.add(ts.getTokenPosOfNode(generatorFunction, tsUtils.getSourceFileOfNode(node)));
|
|
4592
4590
|
}
|
|
4593
4591
|
brokenYields.add(node);
|
|
4594
4592
|
}),
|
|
@@ -4598,8 +4596,8 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
4598
4596
|
}
|
|
4599
4597
|
}
|
|
4600
4598
|
brokenGenerators.forEach(
|
|
4601
|
-
(
|
|
4602
|
-
location:
|
|
4599
|
+
(pos) => report({
|
|
4600
|
+
location: { pos, end: pos + "function".length },
|
|
4603
4601
|
messageText: `Seems like you used yield instead of yield* inside this Effect.gen.`,
|
|
4604
4602
|
fixes: []
|
|
4605
4603
|
})
|
|
@@ -11520,6 +11518,301 @@ var functionToArrow = createRefactor({
|
|
|
11520
11518
|
})
|
|
11521
11519
|
});
|
|
11522
11520
|
|
|
11521
|
+
// src/refactors/layerMagic.ts
|
|
11522
|
+
function sortDependencies(nodes) {
|
|
11523
|
+
const result = [];
|
|
11524
|
+
const visited = /* @__PURE__ */ new Set();
|
|
11525
|
+
const visiting = /* @__PURE__ */ new Set();
|
|
11526
|
+
const cycles = [];
|
|
11527
|
+
const providesMap = /* @__PURE__ */ new Map();
|
|
11528
|
+
Object.entries(nodes).forEach(([nodeId, node]) => {
|
|
11529
|
+
node.provides.forEach((service2) => {
|
|
11530
|
+
if (!providesMap.has(service2)) {
|
|
11531
|
+
providesMap.set(service2, []);
|
|
11532
|
+
}
|
|
11533
|
+
providesMap.get(service2).push(nodeId);
|
|
11534
|
+
});
|
|
11535
|
+
});
|
|
11536
|
+
providesMap.forEach((nodeIds) => {
|
|
11537
|
+
nodeIds.sort((a, b) => {
|
|
11538
|
+
const nodeA = nodes[a];
|
|
11539
|
+
const nodeB = nodes[b];
|
|
11540
|
+
return nodeA.requires.length - nodeB.requires.length;
|
|
11541
|
+
});
|
|
11542
|
+
});
|
|
11543
|
+
const visit = (nodeId, path) => {
|
|
11544
|
+
if (visited.has(nodeId)) {
|
|
11545
|
+
return;
|
|
11546
|
+
}
|
|
11547
|
+
if (visiting.has(nodeId)) {
|
|
11548
|
+
const cycleStart = path.indexOf(nodeId);
|
|
11549
|
+
const cycle = path.slice(cycleStart).concat([nodeId]);
|
|
11550
|
+
const cycleServices = cycle.map((id) => {
|
|
11551
|
+
const node2 = nodes[id];
|
|
11552
|
+
return `${node2.provides.join(", ")} (requires: ${node2.requires.join(", ")})`;
|
|
11553
|
+
});
|
|
11554
|
+
cycles.push(cycleServices);
|
|
11555
|
+
return;
|
|
11556
|
+
}
|
|
11557
|
+
visiting.add(nodeId);
|
|
11558
|
+
const currentPath = [...path, nodeId];
|
|
11559
|
+
const dependencies = /* @__PURE__ */ new Set();
|
|
11560
|
+
const node = nodes[nodeId];
|
|
11561
|
+
node.requires.forEach((requiredService) => {
|
|
11562
|
+
const providers = providesMap.get(requiredService) || [];
|
|
11563
|
+
providers.forEach((providerId) => {
|
|
11564
|
+
if (providerId !== nodeId) {
|
|
11565
|
+
dependencies.add(providerId);
|
|
11566
|
+
}
|
|
11567
|
+
});
|
|
11568
|
+
});
|
|
11569
|
+
dependencies.forEach((depId) => {
|
|
11570
|
+
visit(depId, currentPath);
|
|
11571
|
+
});
|
|
11572
|
+
visiting.delete(nodeId);
|
|
11573
|
+
visited.add(nodeId);
|
|
11574
|
+
result.push(node);
|
|
11575
|
+
};
|
|
11576
|
+
Object.keys(nodes).forEach((nodeId) => {
|
|
11577
|
+
if (!visited.has(nodeId)) {
|
|
11578
|
+
visit(nodeId, []);
|
|
11579
|
+
}
|
|
11580
|
+
});
|
|
11581
|
+
return {
|
|
11582
|
+
sorted: result,
|
|
11583
|
+
cycles,
|
|
11584
|
+
hasCycles: cycles.length > 0
|
|
11585
|
+
};
|
|
11586
|
+
}
|
|
11587
|
+
var layerMagic = createRefactor({
|
|
11588
|
+
name: "layerMagic",
|
|
11589
|
+
description: "Layer Magic",
|
|
11590
|
+
apply: fn("layerMagic.apply")(function* (sourceFile, textRange) {
|
|
11591
|
+
const ts = yield* service(TypeScriptApi);
|
|
11592
|
+
const tsUtils = yield* service(TypeScriptUtils);
|
|
11593
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
11594
|
+
const typeParser = yield* service(TypeParser);
|
|
11595
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
11596
|
+
const layerIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
11597
|
+
sourceFile,
|
|
11598
|
+
"effect",
|
|
11599
|
+
"Layer"
|
|
11600
|
+
) || "Layer";
|
|
11601
|
+
const extractArrayLiteral = (node) => {
|
|
11602
|
+
if (ts.isArrayLiteralExpression(node)) {
|
|
11603
|
+
return pipe(
|
|
11604
|
+
all(...node.elements.map((element) => extractLayers(element, false))),
|
|
11605
|
+
map3(flatten)
|
|
11606
|
+
);
|
|
11607
|
+
}
|
|
11608
|
+
return TypeParserIssue.issue;
|
|
11609
|
+
};
|
|
11610
|
+
const extractLayerExpression = (node) => {
|
|
11611
|
+
if (ts.isExpression(node)) {
|
|
11612
|
+
return pipe(
|
|
11613
|
+
typeParser.layerType(typeChecker.getTypeAtLocation(node), node),
|
|
11614
|
+
map3((_) => [{ node, ..._ }])
|
|
11615
|
+
);
|
|
11616
|
+
}
|
|
11617
|
+
return TypeParserIssue.issue;
|
|
11618
|
+
};
|
|
11619
|
+
const extractLayerApi = (node) => {
|
|
11620
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.expression) && ts.idText(node.expression.expression) === layerIdentifier && ts.isIdentifier(node.expression.name) && ["provide", "provideMerge", "merge", "mergeAll"].map((_) => _.toLowerCase()).indexOf(
|
|
11621
|
+
ts.idText(node.expression.name).toLowerCase()
|
|
11622
|
+
) > -1) {
|
|
11623
|
+
return pipe(
|
|
11624
|
+
all(...node.arguments.map((element) => extractLayers(element, false))),
|
|
11625
|
+
map3(flatten)
|
|
11626
|
+
);
|
|
11627
|
+
}
|
|
11628
|
+
return TypeParserIssue.issue;
|
|
11629
|
+
};
|
|
11630
|
+
const extractPipeSequencing = (node) => {
|
|
11631
|
+
return pipe(
|
|
11632
|
+
typeParser.pipeCall(node),
|
|
11633
|
+
flatMap((_) => {
|
|
11634
|
+
return all(...[_.subject, ..._.args].map((element) => extractLayers(element, true)));
|
|
11635
|
+
}),
|
|
11636
|
+
map3(flatten)
|
|
11637
|
+
);
|
|
11638
|
+
};
|
|
11639
|
+
const extractLayers = cachedBy(
|
|
11640
|
+
fn("layerMagic.apply.extractLayerArray")(function* (node, _inPipeContext) {
|
|
11641
|
+
return yield* pipe(
|
|
11642
|
+
extractArrayLiteral(node),
|
|
11643
|
+
orElse2(() => extractLayerApi(node)),
|
|
11644
|
+
_inPipeContext ? (x) => x : orElse2(() => extractPipeSequencing(node)),
|
|
11645
|
+
orElse2(() => extractLayerExpression(node))
|
|
11646
|
+
);
|
|
11647
|
+
}),
|
|
11648
|
+
"layerMagic.apply.extractLayerArray",
|
|
11649
|
+
(node) => node
|
|
11650
|
+
);
|
|
11651
|
+
const adjustedNode = (node) => {
|
|
11652
|
+
if (ts.isIdentifier(node) && ts.isVariableDeclaration(node.parent) && node.parent.initializer) {
|
|
11653
|
+
return adjustedNode(node.parent.initializer);
|
|
11654
|
+
}
|
|
11655
|
+
if (ts.isIdentifier(node) && ts.isPropertyDeclaration(node.parent) && node.parent.initializer) {
|
|
11656
|
+
return adjustedNode(node.parent.initializer);
|
|
11657
|
+
}
|
|
11658
|
+
return node;
|
|
11659
|
+
};
|
|
11660
|
+
const computeAsAnyAsLayerRefactor = (node) => {
|
|
11661
|
+
const atLocation = adjustedNode(node);
|
|
11662
|
+
return pipe(
|
|
11663
|
+
extractLayers(atLocation, false),
|
|
11664
|
+
flatMap(
|
|
11665
|
+
(extractedLayer) => extractedLayer.length < 1 ? TypeParserIssue.issue : succeed(extractedLayer)
|
|
11666
|
+
),
|
|
11667
|
+
map3((extractedLayers) => ({
|
|
11668
|
+
kind: "refactor.rewrite.effect.layerMagicPrepare",
|
|
11669
|
+
description: "Prepare layers for automatic composition",
|
|
11670
|
+
apply: pipe(
|
|
11671
|
+
gen(function* () {
|
|
11672
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
11673
|
+
const memory = /* @__PURE__ */ new Map();
|
|
11674
|
+
for (const layer of extractedLayers) {
|
|
11675
|
+
yield* typeCheckerUtils.appendToUniqueTypesMap(
|
|
11676
|
+
memory,
|
|
11677
|
+
layer.ROut,
|
|
11678
|
+
(_) => succeed((_.flags & ts.TypeFlags.Never) !== 0)
|
|
11679
|
+
);
|
|
11680
|
+
}
|
|
11681
|
+
const typeReferences = pipe(
|
|
11682
|
+
fromIterable(memory.values()),
|
|
11683
|
+
sort(typeCheckerUtils.deterministicTypeOrder),
|
|
11684
|
+
map5((_) => typeChecker.typeToTypeNode(_, void 0, ts.NodeBuilderFlags.NoTruncation)),
|
|
11685
|
+
filter((_) => !!_)
|
|
11686
|
+
);
|
|
11687
|
+
const newDeclaration = ts.factory.createAsExpression(
|
|
11688
|
+
ts.factory.createAsExpression(
|
|
11689
|
+
ts.factory.createArrayLiteralExpression(extractedLayers.map((_) => _.node)),
|
|
11690
|
+
ts.factory.createTypeReferenceNode("any")
|
|
11691
|
+
),
|
|
11692
|
+
ts.factory.createTypeReferenceNode(
|
|
11693
|
+
ts.factory.createQualifiedName(ts.factory.createIdentifier(layerIdentifier), "Layer"),
|
|
11694
|
+
typeReferences.length === 0 ? [
|
|
11695
|
+
ts.factory.createTypeReferenceNode("never")
|
|
11696
|
+
] : [ts.factory.createUnionTypeNode(typeReferences)]
|
|
11697
|
+
)
|
|
11698
|
+
);
|
|
11699
|
+
changeTracker.replaceNode(sourceFile, atLocation, newDeclaration, {
|
|
11700
|
+
leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll,
|
|
11701
|
+
trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude
|
|
11702
|
+
});
|
|
11703
|
+
}),
|
|
11704
|
+
provideService(TypeScriptApi, ts)
|
|
11705
|
+
)
|
|
11706
|
+
}))
|
|
11707
|
+
);
|
|
11708
|
+
};
|
|
11709
|
+
const parseAsAnyAsLayer = (node) => {
|
|
11710
|
+
if (ts.isAsExpression(node) && ts.isTypeReferenceNode(node.type)) {
|
|
11711
|
+
const expression = node.expression;
|
|
11712
|
+
if (ts.isAsExpression(expression) && expression.type.kind === ts.SyntaxKind.AnyKeyword) {
|
|
11713
|
+
return pipe(
|
|
11714
|
+
typeParser.layerType(typeChecker.getTypeAtLocation(node.type), node.type),
|
|
11715
|
+
map3((_) => ({ node, ..._, castedStructure: expression.expression }))
|
|
11716
|
+
);
|
|
11717
|
+
}
|
|
11718
|
+
}
|
|
11719
|
+
return TypeParserIssue.issue;
|
|
11720
|
+
};
|
|
11721
|
+
const computeBuildRefactor = (node) => {
|
|
11722
|
+
const atLocation = adjustedNode(node);
|
|
11723
|
+
return pipe(
|
|
11724
|
+
parseAsAnyAsLayer(atLocation),
|
|
11725
|
+
flatMap(
|
|
11726
|
+
(_targetLayer) => pipe(
|
|
11727
|
+
extractArrayLiteral(_targetLayer.castedStructure),
|
|
11728
|
+
orElse2(() => extractLayers(_targetLayer.castedStructure, false)),
|
|
11729
|
+
flatMap(
|
|
11730
|
+
(extractedLayer) => extractedLayer.length < 1 ? TypeParserIssue.issue : succeed(extractedLayer)
|
|
11731
|
+
),
|
|
11732
|
+
map3((extractedLayers) => ({
|
|
11733
|
+
kind: "refactor.rewrite.effect.layerMagicBuild",
|
|
11734
|
+
description: "Compose layers automatically with target output services",
|
|
11735
|
+
apply: gen(function* () {
|
|
11736
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
11737
|
+
const memory = /* @__PURE__ */ new Map();
|
|
11738
|
+
const { allIndexes: outputIndexes } = yield* typeCheckerUtils.appendToUniqueTypesMap(
|
|
11739
|
+
memory,
|
|
11740
|
+
_targetLayer.ROut,
|
|
11741
|
+
(_) => succeed((_.flags & ts.TypeFlags.Never) !== 0)
|
|
11742
|
+
);
|
|
11743
|
+
const nodes = {};
|
|
11744
|
+
for (let i = 0; i < extractedLayers.length; i++) {
|
|
11745
|
+
const layer = extractedLayers[i];
|
|
11746
|
+
const { allIndexes: providedIndexes } = yield* typeCheckerUtils.appendToUniqueTypesMap(
|
|
11747
|
+
memory,
|
|
11748
|
+
layer.ROut,
|
|
11749
|
+
(_) => succeed((_.flags & ts.TypeFlags.Never) !== 0)
|
|
11750
|
+
);
|
|
11751
|
+
const { allIndexes: requiredIndexes } = yield* typeCheckerUtils.appendToUniqueTypesMap(
|
|
11752
|
+
memory,
|
|
11753
|
+
layer.RIn,
|
|
11754
|
+
(_) => succeed((_.flags & ts.TypeFlags.Never) !== 0)
|
|
11755
|
+
);
|
|
11756
|
+
nodes[`node_${i}`] = {
|
|
11757
|
+
provides: providedIndexes.filter((_) => requiredIndexes.indexOf(_) === -1),
|
|
11758
|
+
// only provide indexes that are not required
|
|
11759
|
+
requires: requiredIndexes,
|
|
11760
|
+
node: layer.node
|
|
11761
|
+
};
|
|
11762
|
+
}
|
|
11763
|
+
const sortResult = sortDependencies(nodes);
|
|
11764
|
+
const sortedNodes = sortResult.sorted.reverse();
|
|
11765
|
+
const missingOutput = new Set(outputIndexes);
|
|
11766
|
+
const missingInternal = /* @__PURE__ */ new Set();
|
|
11767
|
+
const outputEntry = [];
|
|
11768
|
+
for (const graphNode of sortedNodes) {
|
|
11769
|
+
const mergeOutput = graphNode.provides.filter((_) => missingOutput.has(_));
|
|
11770
|
+
const provideInternal = graphNode.provides.filter((_) => missingInternal.has(_));
|
|
11771
|
+
graphNode.requires.forEach((_) => missingInternal.add(_));
|
|
11772
|
+
mergeOutput.forEach((_) => missingOutput.delete(_));
|
|
11773
|
+
outputEntry.push({
|
|
11774
|
+
merges: mergeOutput.length > 0,
|
|
11775
|
+
provides: provideInternal.length > 0,
|
|
11776
|
+
node: graphNode.node
|
|
11777
|
+
});
|
|
11778
|
+
}
|
|
11779
|
+
const newDeclaration = ts.factory.createCallExpression(
|
|
11780
|
+
ts.factory.createPropertyAccessExpression(
|
|
11781
|
+
outputEntry[0].node,
|
|
11782
|
+
"pipe"
|
|
11783
|
+
),
|
|
11784
|
+
[],
|
|
11785
|
+
outputEntry.slice(1).map(
|
|
11786
|
+
(_) => ts.factory.createCallExpression(
|
|
11787
|
+
ts.factory.createPropertyAccessExpression(
|
|
11788
|
+
ts.factory.createIdentifier(layerIdentifier),
|
|
11789
|
+
_.merges && _.provides ? "provideMerge" : _.merges ? "merge" : "provide"
|
|
11790
|
+
),
|
|
11791
|
+
[],
|
|
11792
|
+
[_.node]
|
|
11793
|
+
)
|
|
11794
|
+
)
|
|
11795
|
+
);
|
|
11796
|
+
changeTracker.replaceNode(sourceFile, atLocation, newDeclaration, {
|
|
11797
|
+
leadingTriviaOption: ts.textChanges.LeadingTriviaOption.IncludeAll,
|
|
11798
|
+
trailingTriviaOption: ts.textChanges.TrailingTriviaOption.Exclude
|
|
11799
|
+
});
|
|
11800
|
+
})
|
|
11801
|
+
}))
|
|
11802
|
+
)
|
|
11803
|
+
)
|
|
11804
|
+
);
|
|
11805
|
+
};
|
|
11806
|
+
const parentNodes = tsUtils.getAncestorNodesInRange(sourceFile, textRange);
|
|
11807
|
+
if (parentNodes.length === 0) return yield* fail(new RefactorNotApplicableError());
|
|
11808
|
+
return yield* pipe(
|
|
11809
|
+
firstSuccessOf(parentNodes.map(computeBuildRefactor)),
|
|
11810
|
+
orElse2(() => firstSuccessOf(parentNodes.map(computeAsAnyAsLayerRefactor))),
|
|
11811
|
+
orElse2(() => fail(new RefactorNotApplicableError()))
|
|
11812
|
+
);
|
|
11813
|
+
})
|
|
11814
|
+
});
|
|
11815
|
+
|
|
11523
11816
|
// src/refactors/makeSchemaOpaque.ts
|
|
11524
11817
|
var _findSchemaVariableDeclaration = fn(
|
|
11525
11818
|
"makeSchemaOpaque._findSchemaVariableDeclaration"
|
|
@@ -12732,6 +13025,7 @@ var wrapWithPipe = createRefactor({
|
|
|
12732
13025
|
|
|
12733
13026
|
// src/refactors.ts
|
|
12734
13027
|
var refactors = [
|
|
13028
|
+
layerMagic,
|
|
12735
13029
|
asyncAwaitToGen,
|
|
12736
13030
|
asyncAwaitToGenTryPromise,
|
|
12737
13031
|
asyncAwaitToFn,
|