@effect/language-service 0.63.2 → 0.64.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 +44 -0
- package/cli.js +1250 -402
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +424 -62
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +445 -70
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +424 -62
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -751,6 +751,13 @@ var make2 = (compare) => (self, that) => self === that ? 0 : compare(self, that)
|
|
|
751
751
|
var string2 = /* @__PURE__ */ make2((self, that) => self < that ? -1 : 1);
|
|
752
752
|
var number2 = /* @__PURE__ */ make2((self, that) => self < that ? -1 : 1);
|
|
753
753
|
var reverse = (O) => make2((self, that) => O(that, self));
|
|
754
|
+
var combine2 = /* @__PURE__ */ dual(2, (self, that) => make2((a1, a2) => {
|
|
755
|
+
const out = self(a1, a2);
|
|
756
|
+
if (out !== 0) {
|
|
757
|
+
return out;
|
|
758
|
+
}
|
|
759
|
+
return that(a1, a2);
|
|
760
|
+
}));
|
|
754
761
|
var mapInput = /* @__PURE__ */ dual(2, (self, f) => make2((b1, b2) => self(f(b1), f(b2))));
|
|
755
762
|
|
|
756
763
|
// node_modules/.pnpm/effect@3.19.13/node_modules/effect/dist/esm/Option.js
|
|
@@ -5033,6 +5040,12 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5033
5040
|
);
|
|
5034
5041
|
const extendsCauseYieldableError = cachedBy(
|
|
5035
5042
|
fn("TypeParser.extendsCauseYieldableError")(function* (givenType) {
|
|
5043
|
+
if (givenType.flags & ts.TypeFlags.Never) {
|
|
5044
|
+
return yield* typeParserIssue("Type is never", givenType);
|
|
5045
|
+
}
|
|
5046
|
+
if (givenType.flags & ts.TypeFlags.Any) {
|
|
5047
|
+
return yield* typeParserIssue("Type is any", givenType);
|
|
5048
|
+
}
|
|
5036
5049
|
const symbols = yield* findSymbolsMatchingPackageAndExportedName("effect", "YieldableError")();
|
|
5037
5050
|
for (const [symbol3, sourceFile] of symbols) {
|
|
5038
5051
|
const causeFile = yield* pipe(isCauseTypeSourceFile(sourceFile), orElse2(() => void_));
|
|
@@ -5127,18 +5140,19 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5127
5140
|
);
|
|
5128
5141
|
const effectType = cachedBy(
|
|
5129
5142
|
fn("TypeParser.effectType")(function* (type, atLocation) {
|
|
5130
|
-
let result = typeParserIssue("Type has no effect variance struct", type, atLocation);
|
|
5131
5143
|
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
5132
|
-
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5144
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5133
5145
|
);
|
|
5146
|
+
if (propertiesSymbols.length === 0) {
|
|
5147
|
+
return yield* typeParserIssue("Type has no effect variance struct", type, atLocation);
|
|
5148
|
+
}
|
|
5134
5149
|
propertiesSymbols.sort(
|
|
5135
5150
|
(a, b) => ts.symbolName(b).indexOf("EffectTypeId") - ts.symbolName(a).indexOf("EffectTypeId")
|
|
5136
5151
|
);
|
|
5137
|
-
|
|
5152
|
+
return yield* firstSuccessOf(propertiesSymbols.map((propertySymbol) => {
|
|
5138
5153
|
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
5139
|
-
|
|
5140
|
-
}
|
|
5141
|
-
return yield* result;
|
|
5154
|
+
return effectVarianceStruct(propertyType, atLocation);
|
|
5155
|
+
}));
|
|
5142
5156
|
}),
|
|
5143
5157
|
"TypeParser.effectType",
|
|
5144
5158
|
(type) => type
|
|
@@ -5177,22 +5191,18 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5177
5191
|
fn("TypeParser.layerType")(function* (type, atLocation) {
|
|
5178
5192
|
yield* pipeableType(type, atLocation);
|
|
5179
5193
|
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
5180
|
-
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5194
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5181
5195
|
);
|
|
5196
|
+
if (propertiesSymbols.length === 0) {
|
|
5197
|
+
return yield* typeParserIssue("Type has no layer variance struct", type, atLocation);
|
|
5198
|
+
}
|
|
5182
5199
|
propertiesSymbols.sort(
|
|
5183
5200
|
(a, b) => ts.symbolName(b).indexOf("LayerTypeId") - ts.symbolName(a).indexOf("LayerTypeId")
|
|
5184
5201
|
);
|
|
5185
|
-
|
|
5202
|
+
return yield* firstSuccessOf(propertiesSymbols.map((propertySymbol) => {
|
|
5186
5203
|
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
5187
|
-
|
|
5188
|
-
|
|
5189
|
-
atLocation
|
|
5190
|
-
));
|
|
5191
|
-
if (isSome2(varianceArgs)) {
|
|
5192
|
-
return varianceArgs.value;
|
|
5193
|
-
}
|
|
5194
|
-
}
|
|
5195
|
-
return yield* typeParserIssue("Type has no layer variance struct", type, atLocation);
|
|
5204
|
+
return layerVarianceStruct(propertyType, atLocation);
|
|
5205
|
+
}));
|
|
5196
5206
|
}),
|
|
5197
5207
|
"TypeParser.layerType",
|
|
5198
5208
|
(type) => type
|
|
@@ -5489,20 +5499,16 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5489
5499
|
const ast = typeChecker.getPropertyOfType(type, "ast");
|
|
5490
5500
|
if (!ast) return yield* typeParserIssue("Has no 'ast' property", type, atLocation);
|
|
5491
5501
|
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
5492
|
-
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5502
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5493
5503
|
);
|
|
5504
|
+
if (propertiesSymbols.length === 0) {
|
|
5505
|
+
return yield* typeParserIssue("Type has no schema variance struct", type, atLocation);
|
|
5506
|
+
}
|
|
5494
5507
|
propertiesSymbols.sort((a, b) => ts.symbolName(b).indexOf("TypeId") - ts.symbolName(a).indexOf("TypeId"));
|
|
5495
|
-
|
|
5508
|
+
return yield* firstSuccessOf(propertiesSymbols.map((propertySymbol) => {
|
|
5496
5509
|
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
5497
|
-
|
|
5498
|
-
|
|
5499
|
-
atLocation
|
|
5500
|
-
));
|
|
5501
|
-
if (isSome2(varianceArgs)) {
|
|
5502
|
-
return varianceArgs.value;
|
|
5503
|
-
}
|
|
5504
|
-
}
|
|
5505
|
-
return yield* typeParserIssue("Type has no schema variance struct", type, atLocation);
|
|
5510
|
+
return effectSchemaVarianceStruct(propertyType, atLocation);
|
|
5511
|
+
}));
|
|
5506
5512
|
}),
|
|
5507
5513
|
"TypeParser.effectSchemaType",
|
|
5508
5514
|
(type) => type
|
|
@@ -5538,33 +5544,54 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5538
5544
|
fn("TypeParser.contextTag")(function* (type, atLocation) {
|
|
5539
5545
|
yield* pipeableType(type, atLocation);
|
|
5540
5546
|
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
5541
|
-
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5547
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5542
5548
|
);
|
|
5549
|
+
if (propertiesSymbols.length === 0) {
|
|
5550
|
+
return yield* typeParserIssue("Type has no tag variance struct", type, atLocation);
|
|
5551
|
+
}
|
|
5543
5552
|
propertiesSymbols.sort((a, b) => ts.symbolName(b).indexOf("TypeId") - ts.symbolName(a).indexOf("TypeId"));
|
|
5544
|
-
|
|
5553
|
+
return yield* firstSuccessOf(propertiesSymbols.map((propertySymbol) => {
|
|
5545
5554
|
const propertyType = typeChecker.getTypeOfSymbolAtLocation(propertySymbol, atLocation);
|
|
5546
|
-
|
|
5547
|
-
|
|
5548
|
-
atLocation
|
|
5549
|
-
));
|
|
5550
|
-
if (isSome2(varianceArgs)) {
|
|
5551
|
-
return varianceArgs.value;
|
|
5552
|
-
}
|
|
5553
|
-
}
|
|
5554
|
-
return yield* typeParserIssue("Type has no tag variance struct", type, atLocation);
|
|
5555
|
+
return contextTagVarianceStruct(propertyType, atLocation);
|
|
5556
|
+
}));
|
|
5555
5557
|
}),
|
|
5556
5558
|
"TypeParser.contextTag",
|
|
5557
5559
|
(type) => type
|
|
5558
5560
|
);
|
|
5561
|
+
const effectFunctionImportedName = cachedBy(
|
|
5562
|
+
fn("TypeParser.effectFunctionImportedName")(function* (sourceFile) {
|
|
5563
|
+
return tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Function");
|
|
5564
|
+
}),
|
|
5565
|
+
"TypeParser.effectFunctionImportedName",
|
|
5566
|
+
(node) => node
|
|
5567
|
+
);
|
|
5559
5568
|
const pipeCall = cachedBy(
|
|
5560
5569
|
function(node) {
|
|
5561
5570
|
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.name) && ts.idText(node.expression.name) === "pipe") {
|
|
5562
|
-
|
|
5563
|
-
|
|
5564
|
-
|
|
5565
|
-
|
|
5566
|
-
|
|
5567
|
-
|
|
5571
|
+
const baseExpression = node.expression.expression;
|
|
5572
|
+
return pipe(
|
|
5573
|
+
effectFunctionImportedName(tsUtils.getSourceFileOfNode(node)),
|
|
5574
|
+
flatMap4((functionIdentifier) => {
|
|
5575
|
+
if (functionIdentifier && ts.isIdentifier(baseExpression) && ts.idText(baseExpression) === functionIdentifier) {
|
|
5576
|
+
if (node.arguments.length === 0) {
|
|
5577
|
+
return typeParserIssue("Node is not a pipe call", void 0, node);
|
|
5578
|
+
}
|
|
5579
|
+
const [subject, ...args2] = node.arguments;
|
|
5580
|
+
return succeed({
|
|
5581
|
+
node,
|
|
5582
|
+
subject,
|
|
5583
|
+
args: args2,
|
|
5584
|
+
kind: "pipe"
|
|
5585
|
+
});
|
|
5586
|
+
}
|
|
5587
|
+
return succeed({
|
|
5588
|
+
node,
|
|
5589
|
+
subject: baseExpression,
|
|
5590
|
+
args: Array.from(node.arguments),
|
|
5591
|
+
kind: "pipeable"
|
|
5592
|
+
});
|
|
5593
|
+
})
|
|
5594
|
+
);
|
|
5568
5595
|
}
|
|
5569
5596
|
if (ts.isCallExpression(node) && ts.isIdentifier(node.expression) && ts.idText(node.expression) === "pipe" && node.arguments.length > 0) {
|
|
5570
5597
|
const [subject, ...args2] = node.arguments;
|
|
@@ -5579,17 +5606,10 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5579
5606
|
fn("TypeParser.scopeType")(function* (type, atLocation) {
|
|
5580
5607
|
yield* pipeableType(type, atLocation);
|
|
5581
5608
|
const propertiesSymbols = typeChecker.getPropertiesOfType(type).filter(
|
|
5582
|
-
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5583
|
-
);
|
|
5584
|
-
propertiesSymbols.sort(
|
|
5585
|
-
(a, b) => ts.symbolName(b).indexOf("ScopeTypeId") - ts.symbolName(a).indexOf("ScopeTypeId")
|
|
5609
|
+
(_) => _.flags & ts.SymbolFlags.Property && !(_.flags & ts.SymbolFlags.Optional) && _.valueDeclaration
|
|
5586
5610
|
);
|
|
5587
|
-
|
|
5588
|
-
|
|
5589
|
-
const symbol3 = typeChecker.getSymbolAtLocation(computedPropertyExpression.expression);
|
|
5590
|
-
if (symbol3 && ts.symbolName(symbol3) === "ScopeTypeId") {
|
|
5591
|
-
return type;
|
|
5592
|
-
}
|
|
5611
|
+
if (propertiesSymbols.some((s) => ts.symbolName(s).indexOf("ScopeTypeId") !== -1)) {
|
|
5612
|
+
return type;
|
|
5593
5613
|
}
|
|
5594
5614
|
return yield* typeParserIssue("Type has no scope type id", type, atLocation);
|
|
5595
5615
|
}),
|
|
@@ -6095,12 +6115,38 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
6095
6115
|
"TypeParser.extendsEffectSqlModelClass",
|
|
6096
6116
|
(atLocation) => atLocation
|
|
6097
6117
|
);
|
|
6118
|
+
const isEffectLayerTypeSourceFile = cachedBy(
|
|
6119
|
+
fn("TypeParser.isEffectLayerTypeSourceFile")(function* (sourceFile) {
|
|
6120
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
6121
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
6122
|
+
const layerTypeSymbol = typeChecker.tryGetMemberInModuleExports("Layer", moduleSymbol);
|
|
6123
|
+
if (!layerTypeSymbol) return yield* typeParserIssue("Layer type not found", void 0, sourceFile);
|
|
6124
|
+
const type = typeChecker.getDeclaredTypeOfSymbol(layerTypeSymbol);
|
|
6125
|
+
yield* layerType(type, sourceFile);
|
|
6126
|
+
return sourceFile;
|
|
6127
|
+
}),
|
|
6128
|
+
"TypeParser.isEffectLayerTypeSourceFile",
|
|
6129
|
+
(sourceFile) => sourceFile
|
|
6130
|
+
);
|
|
6131
|
+
const isNodeReferenceToEffectLayerModuleApi = (memberName) => cachedBy(
|
|
6132
|
+
fn("TypeParser.isNodeReferenceToEffectLayerModuleApi")(function* (node) {
|
|
6133
|
+
return yield* isNodeReferenceToExportOfPackageModule(
|
|
6134
|
+
node,
|
|
6135
|
+
"effect",
|
|
6136
|
+
isEffectLayerTypeSourceFile,
|
|
6137
|
+
memberName
|
|
6138
|
+
);
|
|
6139
|
+
}),
|
|
6140
|
+
`TypeParser.isNodeReferenceToEffectLayerModuleApi(${memberName})`,
|
|
6141
|
+
(node) => node
|
|
6142
|
+
);
|
|
6098
6143
|
return {
|
|
6099
6144
|
isNodeReferenceToEffectModuleApi,
|
|
6100
6145
|
isNodeReferenceToEffectSchemaModuleApi,
|
|
6101
6146
|
isNodeReferenceToEffectDataModuleApi,
|
|
6102
6147
|
isNodeReferenceToEffectContextModuleApi,
|
|
6103
6148
|
isNodeReferenceToEffectSqlModelModuleApi,
|
|
6149
|
+
isNodeReferenceToEffectLayerModuleApi,
|
|
6104
6150
|
effectType,
|
|
6105
6151
|
strictEffectType,
|
|
6106
6152
|
layerType,
|
|
@@ -6415,9 +6461,11 @@ var parse2 = fn("writeTagClassAccessors.parse")(function* (node) {
|
|
|
6415
6461
|
const typeParser = yield* service(TypeParser);
|
|
6416
6462
|
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
6417
6463
|
if (!ts.isClassDeclaration(node)) return yield* fail3("not a class declaration");
|
|
6418
|
-
const { Service, accessors: accessors2, className } = yield* pipe(
|
|
6419
|
-
typeParser.extendsEffectService(node),
|
|
6420
|
-
orElse2(
|
|
6464
|
+
const { Service, accessors: accessors2, className, kind } = yield* pipe(
|
|
6465
|
+
map8(typeParser.extendsEffectService(node), (_) => ({ kind: "effectService", ..._ })),
|
|
6466
|
+
orElse2(
|
|
6467
|
+
() => map8(typeParser.extendsEffectTag(node), (_) => ({ kind: "effectTag", accessors: true, ..._ }))
|
|
6468
|
+
),
|
|
6421
6469
|
orElse2(() => fail3("not a class extending Effect.Service call"))
|
|
6422
6470
|
);
|
|
6423
6471
|
if (accessors2 !== true) return yield* fail3("accessors are not enabled in the Effect.Service call");
|
|
@@ -6439,7 +6487,7 @@ var parse2 = fn("writeTagClassAccessors.parse")(function* (node) {
|
|
|
6439
6487
|
const hash2 = involvedMembers.map(({ property, propertyType }) => {
|
|
6440
6488
|
return ts.symbolName(property) + ": " + typeChecker.typeToString(propertyType);
|
|
6441
6489
|
}).concat([ts.idText(className)]).join("\n");
|
|
6442
|
-
return { Service, className, atLocation: node, hash: cyrb53(hash2), involvedMembers };
|
|
6490
|
+
return { Service, className, atLocation: node, hash: cyrb53(hash2), involvedMembers, kind };
|
|
6443
6491
|
});
|
|
6444
6492
|
var writeTagClassAccessors = createRefactor({
|
|
6445
6493
|
name: "writeTagClassAccessors",
|
|
@@ -7426,6 +7474,100 @@ var anyUnknownInErrorContext = createDiagnostic({
|
|
|
7426
7474
|
})
|
|
7427
7475
|
});
|
|
7428
7476
|
|
|
7477
|
+
// src/diagnostics/catchAllToMapError.ts
|
|
7478
|
+
var catchAllToMapError = createDiagnostic({
|
|
7479
|
+
name: "catchAllToMapError",
|
|
7480
|
+
code: 39,
|
|
7481
|
+
description: "Suggests using Effect.mapError instead of Effect.catchAll when the callback only wraps the error with Effect.fail",
|
|
7482
|
+
severity: "suggestion",
|
|
7483
|
+
apply: fn("catchAllToMapError.apply")(function* (sourceFile, report) {
|
|
7484
|
+
const ts = yield* service(TypeScriptApi);
|
|
7485
|
+
const typeParser = yield* service(TypeParser);
|
|
7486
|
+
const getFunctionBody = (node) => {
|
|
7487
|
+
if (ts.isArrowFunction(node)) {
|
|
7488
|
+
return node.body;
|
|
7489
|
+
}
|
|
7490
|
+
if (ts.isFunctionExpression(node)) {
|
|
7491
|
+
return node.body;
|
|
7492
|
+
}
|
|
7493
|
+
return void 0;
|
|
7494
|
+
};
|
|
7495
|
+
const getEffectFailCallInfo = (body) => {
|
|
7496
|
+
return gen(function* () {
|
|
7497
|
+
if (ts.isCallExpression(body)) {
|
|
7498
|
+
const isFailCall = yield* pipe(
|
|
7499
|
+
typeParser.isNodeReferenceToEffectModuleApi("fail")(body.expression),
|
|
7500
|
+
option
|
|
7501
|
+
);
|
|
7502
|
+
if (isSome2(isFailCall) && body.arguments.length >= 1) {
|
|
7503
|
+
return some2({ failCall: body, failArg: body.arguments[0] });
|
|
7504
|
+
}
|
|
7505
|
+
}
|
|
7506
|
+
if (ts.isBlock(body)) {
|
|
7507
|
+
const statements = body.statements;
|
|
7508
|
+
if (statements.length === 1) {
|
|
7509
|
+
const stmt = statements[0];
|
|
7510
|
+
if (ts.isReturnStatement(stmt) && stmt.expression && ts.isCallExpression(stmt.expression)) {
|
|
7511
|
+
const isFailCall = yield* pipe(
|
|
7512
|
+
typeParser.isNodeReferenceToEffectModuleApi("fail")(stmt.expression.expression),
|
|
7513
|
+
option
|
|
7514
|
+
);
|
|
7515
|
+
if (isSome2(isFailCall) && stmt.expression.arguments.length >= 1) {
|
|
7516
|
+
return some2({ failCall: stmt.expression, failArg: stmt.expression.arguments[0] });
|
|
7517
|
+
}
|
|
7518
|
+
}
|
|
7519
|
+
}
|
|
7520
|
+
}
|
|
7521
|
+
return none2();
|
|
7522
|
+
});
|
|
7523
|
+
};
|
|
7524
|
+
const nodeToVisit = [];
|
|
7525
|
+
const appendNodeToVisit = (node) => {
|
|
7526
|
+
nodeToVisit.push(node);
|
|
7527
|
+
return void 0;
|
|
7528
|
+
};
|
|
7529
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
7530
|
+
while (nodeToVisit.length > 0) {
|
|
7531
|
+
const node = nodeToVisit.shift();
|
|
7532
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
7533
|
+
if (ts.isCallExpression(node)) {
|
|
7534
|
+
const isCatchAllCall = yield* pipe(
|
|
7535
|
+
typeParser.isNodeReferenceToEffectModuleApi("catchAll")(node.expression),
|
|
7536
|
+
option
|
|
7537
|
+
);
|
|
7538
|
+
if (isSome2(isCatchAllCall)) {
|
|
7539
|
+
const callback = node.arguments[0];
|
|
7540
|
+
if (!callback) continue;
|
|
7541
|
+
const functionBody = getFunctionBody(callback);
|
|
7542
|
+
if (!functionBody) continue;
|
|
7543
|
+
const failCallInfo = yield* getEffectFailCallInfo(functionBody);
|
|
7544
|
+
if (isNone2(failCallInfo)) continue;
|
|
7545
|
+
const { failArg, failCall } = failCallInfo.value;
|
|
7546
|
+
report({
|
|
7547
|
+
location: node.expression,
|
|
7548
|
+
messageText: `You can use Effect.mapError instead of Effect.catchAll + Effect.fail to transform the error type.`,
|
|
7549
|
+
fixes: [{
|
|
7550
|
+
fixName: "catchAllToMapError_fix",
|
|
7551
|
+
description: "Replace with Effect.mapError",
|
|
7552
|
+
apply: gen(function* () {
|
|
7553
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
7554
|
+
if (ts.isPropertyAccessExpression(node.expression)) {
|
|
7555
|
+
changeTracker.replaceNode(
|
|
7556
|
+
sourceFile,
|
|
7557
|
+
node.expression.name,
|
|
7558
|
+
ts.factory.createIdentifier("mapError")
|
|
7559
|
+
);
|
|
7560
|
+
}
|
|
7561
|
+
changeTracker.replaceNode(sourceFile, failCall, failArg);
|
|
7562
|
+
})
|
|
7563
|
+
}]
|
|
7564
|
+
});
|
|
7565
|
+
}
|
|
7566
|
+
}
|
|
7567
|
+
}
|
|
7568
|
+
})
|
|
7569
|
+
});
|
|
7570
|
+
|
|
7429
7571
|
// src/diagnostics/catchUnfailableEffect.ts
|
|
7430
7572
|
var catchUnfailableEffect = createDiagnostic({
|
|
7431
7573
|
name: "catchUnfailableEffect",
|
|
@@ -7922,6 +8064,65 @@ var genericEffectServices = createDiagnostic({
|
|
|
7922
8064
|
})
|
|
7923
8065
|
});
|
|
7924
8066
|
|
|
8067
|
+
// src/diagnostics/globalErrorInEffectCatch.ts
|
|
8068
|
+
var globalErrorInEffectCatch = createDiagnostic({
|
|
8069
|
+
name: "globalErrorInEffectCatch",
|
|
8070
|
+
code: 36,
|
|
8071
|
+
description: "Warns when catch callbacks return global Error type instead of typed errors",
|
|
8072
|
+
severity: "warning",
|
|
8073
|
+
apply: fn("globalErrorInEffectCatch.apply")(function* (sourceFile, report) {
|
|
8074
|
+
const ts = yield* service(TypeScriptApi);
|
|
8075
|
+
const typeParser = yield* service(TypeParser);
|
|
8076
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
8077
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
8078
|
+
const nodeToVisit = [];
|
|
8079
|
+
const appendNodeToVisit = (node) => {
|
|
8080
|
+
nodeToVisit.push(node);
|
|
8081
|
+
return void 0;
|
|
8082
|
+
};
|
|
8083
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
8084
|
+
while (nodeToVisit.length > 0) {
|
|
8085
|
+
const node = nodeToVisit.shift();
|
|
8086
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
8087
|
+
if (ts.isCallExpression(node)) {
|
|
8088
|
+
const isEffectWithCatch = yield* pipe(
|
|
8089
|
+
typeParser.isNodeReferenceToEffectModuleApi("tryPromise")(node.expression),
|
|
8090
|
+
orElse2(() => typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression)),
|
|
8091
|
+
orElse2(() => typeParser.isNodeReferenceToEffectModuleApi("tryMap")(node.expression)),
|
|
8092
|
+
orElse2(() => typeParser.isNodeReferenceToEffectModuleApi("tryMapPromise")(node.expression)),
|
|
8093
|
+
orElse2(() => void_)
|
|
8094
|
+
);
|
|
8095
|
+
if (isEffectWithCatch) {
|
|
8096
|
+
const signature = typeChecker.getResolvedSignature(node);
|
|
8097
|
+
if (signature) {
|
|
8098
|
+
const objectType = typeChecker.getParameterType(signature, 0);
|
|
8099
|
+
const catchFunctionSymbol = typeChecker.getPropertyOfType(objectType, "catch");
|
|
8100
|
+
if (catchFunctionSymbol) {
|
|
8101
|
+
const catchFunctionType = typeChecker.getTypeOfSymbolAtLocation(catchFunctionSymbol, node);
|
|
8102
|
+
const signatures = typeChecker.getSignaturesOfType(catchFunctionType, ts.SignatureKind.Call);
|
|
8103
|
+
if (signatures.length > 0) {
|
|
8104
|
+
const returnType = typeChecker.getReturnTypeOfSignature(signatures[0]);
|
|
8105
|
+
if (returnType && typeCheckerUtils.isGlobalErrorType(returnType)) {
|
|
8106
|
+
const nodeText = sourceFile.text.substring(
|
|
8107
|
+
ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
8108
|
+
node.expression.end
|
|
8109
|
+
);
|
|
8110
|
+
report({
|
|
8111
|
+
location: node.expression,
|
|
8112
|
+
messageText: `The 'catch' callback in ${nodeText} returns the global Error type. It's not recommended to use the global Error type in Effect failures as they can get merged together.
|
|
8113
|
+
Instead, use tagged errors or custom errors with a discriminator property to get properly type-checked errors.`,
|
|
8114
|
+
fixes: []
|
|
8115
|
+
});
|
|
8116
|
+
}
|
|
8117
|
+
}
|
|
8118
|
+
}
|
|
8119
|
+
}
|
|
8120
|
+
}
|
|
8121
|
+
}
|
|
8122
|
+
}
|
|
8123
|
+
})
|
|
8124
|
+
});
|
|
8125
|
+
|
|
7925
8126
|
// src/diagnostics/globalErrorInEffectFailure.ts
|
|
7926
8127
|
var globalErrorInEffectFailure = createDiagnostic({
|
|
7927
8128
|
name: "globalErrorInEffectFailure",
|
|
@@ -7952,7 +8153,7 @@ var globalErrorInEffectFailure = createDiagnostic({
|
|
|
7952
8153
|
return sync(
|
|
7953
8154
|
() => report({
|
|
7954
8155
|
location: node,
|
|
7955
|
-
messageText: `Effect.fail is called with the global Error type. It's not recommended to use the global Error type in Effect failures as they can get merged together. Instead, use tagged errors
|
|
8156
|
+
messageText: `Effect.fail is called with the global Error type. It's not recommended to use the global Error type in Effect failures as they can get merged together. Instead, use tagged errors or custom errors with a discriminator property to get properly type-checked errors.`,
|
|
7956
8157
|
fixes: []
|
|
7957
8158
|
})
|
|
7958
8159
|
);
|
|
@@ -8107,6 +8308,119 @@ var importFromBarrel = createDiagnostic({
|
|
|
8107
8308
|
})
|
|
8108
8309
|
});
|
|
8109
8310
|
|
|
8311
|
+
// src/diagnostics/layerMergeAllWithDependencies.ts
|
|
8312
|
+
var layerMergeAllWithDependencies = createDiagnostic({
|
|
8313
|
+
name: "layerMergeAllWithDependencies",
|
|
8314
|
+
code: 37,
|
|
8315
|
+
description: "Detects interdependencies in Layer.mergeAll calls where one layer provides a service that another layer requires",
|
|
8316
|
+
severity: "warning",
|
|
8317
|
+
apply: fn("layerMergeAllWithDependencies.apply")(function* (sourceFile, report) {
|
|
8318
|
+
const ts = yield* service(TypeScriptApi);
|
|
8319
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
8320
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
8321
|
+
const typeParser = yield* service(TypeParser);
|
|
8322
|
+
const tsUtils = yield* service(TypeScriptUtils);
|
|
8323
|
+
const layerModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
8324
|
+
sourceFile,
|
|
8325
|
+
"effect",
|
|
8326
|
+
"Layer"
|
|
8327
|
+
) || "Layer";
|
|
8328
|
+
const nodeToVisit = [];
|
|
8329
|
+
const appendNodeToVisit = (node) => {
|
|
8330
|
+
nodeToVisit.push(node);
|
|
8331
|
+
return void 0;
|
|
8332
|
+
};
|
|
8333
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
8334
|
+
while (nodeToVisit.length > 0) {
|
|
8335
|
+
const node = nodeToVisit.shift();
|
|
8336
|
+
if (ts.isCallExpression(node)) {
|
|
8337
|
+
const checkLayerMergeAll = yield* pipe(
|
|
8338
|
+
typeParser.isNodeReferenceToEffectLayerModuleApi("mergeAll")(node.expression),
|
|
8339
|
+
orElse2(() => void_)
|
|
8340
|
+
);
|
|
8341
|
+
if (checkLayerMergeAll) {
|
|
8342
|
+
const layerArgs = node.arguments;
|
|
8343
|
+
if (layerArgs.length > 1) {
|
|
8344
|
+
const layerInfos = [];
|
|
8345
|
+
const actuallyProvidedMap = /* @__PURE__ */ new Map();
|
|
8346
|
+
for (const arg of layerArgs) {
|
|
8347
|
+
const argType = typeCheckerUtils.getTypeAtLocation(arg);
|
|
8348
|
+
if (!argType) continue;
|
|
8349
|
+
const layerTypeParsedOption = yield* option(typeParser.layerType(argType, arg));
|
|
8350
|
+
if (isNone2(layerTypeParsedOption)) continue;
|
|
8351
|
+
const layerTypeParsed = layerTypeParsedOption.value;
|
|
8352
|
+
const providedMembers = typeCheckerUtils.unrollUnionMembers(layerTypeParsed.ROut);
|
|
8353
|
+
for (const providedType of providedMembers) {
|
|
8354
|
+
if (providedType.flags & ts.TypeFlags.Never) continue;
|
|
8355
|
+
const isPassThrough = typeChecker.isTypeAssignableTo(providedType, layerTypeParsed.RIn);
|
|
8356
|
+
if (!isPassThrough) {
|
|
8357
|
+
actuallyProvidedMap.set(providedType, arg);
|
|
8358
|
+
}
|
|
8359
|
+
}
|
|
8360
|
+
layerInfos.push({
|
|
8361
|
+
arg,
|
|
8362
|
+
requirementsType: layerTypeParsed.RIn
|
|
8363
|
+
});
|
|
8364
|
+
}
|
|
8365
|
+
const providerToConsumers = /* @__PURE__ */ new Map();
|
|
8366
|
+
for (const layer of layerInfos) {
|
|
8367
|
+
for (const [providedType, providerArg] of actuallyProvidedMap) {
|
|
8368
|
+
if (providerArg === layer.arg) continue;
|
|
8369
|
+
if (typeChecker.isTypeAssignableTo(providedType, layer.requirementsType)) {
|
|
8370
|
+
const consumers = providerToConsumers.get(providerArg) || [];
|
|
8371
|
+
consumers.push({ consumer: layer.arg, providedType });
|
|
8372
|
+
providerToConsumers.set(providerArg, consumers);
|
|
8373
|
+
}
|
|
8374
|
+
}
|
|
8375
|
+
}
|
|
8376
|
+
for (const [providerArg, consumers] of providerToConsumers) {
|
|
8377
|
+
const providedTypes = Array.from(new Set(consumers.map((c) => typeChecker.typeToString(c.providedType)))).join(", ");
|
|
8378
|
+
report({
|
|
8379
|
+
location: providerArg,
|
|
8380
|
+
messageText: `This layer provides ${providedTypes} which is required by another layer in the same Layer.mergeAll call. Layer.mergeAll creates layers in parallel, so dependencies between layers will not be satisfied. Consider moving this layer into a Layer.provideMerge after the Layer.mergeAll.`,
|
|
8381
|
+
fixes: [{
|
|
8382
|
+
fixName: "layerMergeAllWithDependencies_fix",
|
|
8383
|
+
description: "Move layer to Layer.provideMerge",
|
|
8384
|
+
apply: gen(function* () {
|
|
8385
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
8386
|
+
const providerIndex = layerArgs.indexOf(providerArg);
|
|
8387
|
+
if (providerIndex === -1) return;
|
|
8388
|
+
const providerArgNode = providerArg;
|
|
8389
|
+
if (providerIndex === 0 && layerArgs.length > 1) {
|
|
8390
|
+
changeTracker.deleteRange(sourceFile, {
|
|
8391
|
+
pos: providerArgNode.pos,
|
|
8392
|
+
end: layerArgs[1].pos
|
|
8393
|
+
});
|
|
8394
|
+
} else if (providerIndex > 0) {
|
|
8395
|
+
changeTracker.deleteRange(sourceFile, {
|
|
8396
|
+
pos: layerArgs[providerIndex - 1].end,
|
|
8397
|
+
end: providerArgNode.end
|
|
8398
|
+
});
|
|
8399
|
+
}
|
|
8400
|
+
const provideMergeCall = ts.factory.createCallExpression(
|
|
8401
|
+
ts.factory.createPropertyAccessExpression(
|
|
8402
|
+
ts.factory.createIdentifier(layerModuleIdentifier),
|
|
8403
|
+
ts.factory.createIdentifier("provideMerge")
|
|
8404
|
+
),
|
|
8405
|
+
void 0,
|
|
8406
|
+
[providerArgNode]
|
|
8407
|
+
);
|
|
8408
|
+
changeTracker.insertNodeAt(sourceFile, node.end, provideMergeCall, {
|
|
8409
|
+
prefix: ".pipe("
|
|
8410
|
+
});
|
|
8411
|
+
changeTracker.insertText(sourceFile, node.end, ")");
|
|
8412
|
+
})
|
|
8413
|
+
}]
|
|
8414
|
+
});
|
|
8415
|
+
}
|
|
8416
|
+
}
|
|
8417
|
+
}
|
|
8418
|
+
}
|
|
8419
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
8420
|
+
}
|
|
8421
|
+
})
|
|
8422
|
+
});
|
|
8423
|
+
|
|
8110
8424
|
// src/diagnostics/leakingRequirements.ts
|
|
8111
8425
|
var leakingRequirements = createDiagnostic({
|
|
8112
8426
|
name: "leakingRequirements",
|
|
@@ -8205,6 +8519,7 @@ var leakingRequirements = createDiagnostic({
|
|
|
8205
8519
|
location: node,
|
|
8206
8520
|
messageText: `This Service is leaking the ${requirements.map((_) => typeChecker.typeToString(_)).join(" | ")} requirement.
|
|
8207
8521
|
If these requirements cannot be cached and are expected to be provided per method invocation (e.g. HttpServerRequest), you can either safely disable this diagnostic for this line through quickfixes or mark the service declaration with a JSDoc @effect-leakable-service.
|
|
8522
|
+
Services should usually be collected in the layer creation body, and then provided at each method that requires them.
|
|
8208
8523
|
More info at https://effect.website/docs/requirements-management/layers/#avoiding-requirement-leakage`,
|
|
8209
8524
|
fixes: []
|
|
8210
8525
|
});
|
|
@@ -8614,6 +8929,55 @@ var missingEffectServiceDependency = createDiagnostic({
|
|
|
8614
8929
|
})
|
|
8615
8930
|
});
|
|
8616
8931
|
|
|
8932
|
+
// src/diagnostics/missingLayerContext.ts
|
|
8933
|
+
var missingLayerContext = createDiagnostic({
|
|
8934
|
+
name: "missingLayerContext",
|
|
8935
|
+
code: 38,
|
|
8936
|
+
description: "Reports missing service requirements in Layer context channel",
|
|
8937
|
+
severity: "error",
|
|
8938
|
+
apply: fn("missingLayerContext.apply")(function* (sourceFile, report) {
|
|
8939
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
8940
|
+
const typeParser = yield* service(TypeParser);
|
|
8941
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
8942
|
+
const checkForMissingContextTypes = (node, expectedType, valueNode, realType) => pipe(
|
|
8943
|
+
all(
|
|
8944
|
+
typeParser.layerType(expectedType, node),
|
|
8945
|
+
typeParser.layerType(realType, valueNode)
|
|
8946
|
+
),
|
|
8947
|
+
map8(
|
|
8948
|
+
([expectedLayer, realLayer]) => typeCheckerUtils.getMissingTypeEntriesInTargetType(
|
|
8949
|
+
realLayer.RIn,
|
|
8950
|
+
expectedLayer.RIn
|
|
8951
|
+
)
|
|
8952
|
+
)
|
|
8953
|
+
);
|
|
8954
|
+
const sortTypes = sort(typeCheckerUtils.deterministicTypeOrder);
|
|
8955
|
+
const entries2 = getEffectLspPatchSourceFileMetadata(sourceFile)?.relationErrors || typeCheckerUtils.expectedAndRealType(sourceFile);
|
|
8956
|
+
for (const [node, expectedType, valueNode, realType] of entries2) {
|
|
8957
|
+
if (expectedType !== realType) {
|
|
8958
|
+
yield* pipe(
|
|
8959
|
+
checkForMissingContextTypes(
|
|
8960
|
+
node,
|
|
8961
|
+
expectedType,
|
|
8962
|
+
valueNode,
|
|
8963
|
+
realType
|
|
8964
|
+
),
|
|
8965
|
+
map8(
|
|
8966
|
+
(missingTypes) => missingTypes.length > 0 ? report(
|
|
8967
|
+
{
|
|
8968
|
+
location: node,
|
|
8969
|
+
messageText: `Missing '${sortTypes(missingTypes).map((_) => typeChecker.typeToString(_)).join(" | ")}' in the expected Layer context.`,
|
|
8970
|
+
fixes: []
|
|
8971
|
+
}
|
|
8972
|
+
) : void 0
|
|
8973
|
+
),
|
|
8974
|
+
ignore
|
|
8975
|
+
);
|
|
8976
|
+
}
|
|
8977
|
+
}
|
|
8978
|
+
})
|
|
8979
|
+
});
|
|
8980
|
+
|
|
8617
8981
|
// src/diagnostics/missingReturnYieldStar.ts
|
|
8618
8982
|
var missingReturnYieldStar = createDiagnostic({
|
|
8619
8983
|
name: "missingReturnYieldStar",
|
|
@@ -10069,9 +10433,10 @@ var unsupportedServiceAccessors = createDiagnostic({
|
|
|
10069
10433
|
);
|
|
10070
10434
|
if (missingMembers.length > 0) {
|
|
10071
10435
|
const memberNames = missingMembers.map(({ property }) => `'${ts.symbolName(property)}'`).join(", ");
|
|
10436
|
+
const suggestedFix = parseResult.kind === "effectTag" ? "\nEffect.Tag does not allow to disable accessors, so you may want to use Context.Tag instead." : "";
|
|
10072
10437
|
report({
|
|
10073
10438
|
location: parseResult.className,
|
|
10074
|
-
messageText: `Even if accessors are enabled, accessors for ${memberNames} won't be available because the signature have generic type parameters or multiple call signatures
|
|
10439
|
+
messageText: `Even if accessors are enabled, accessors for ${memberNames} won't be available because the signature have generic type parameters or multiple call signatures.${suggestedFix}`,
|
|
10075
10440
|
fixes: [{
|
|
10076
10441
|
fixName: "unsupportedServiceAccessors_enableCodegen",
|
|
10077
10442
|
description: "Enable accessors codegen",
|
|
@@ -10092,6 +10457,7 @@ var unsupportedServiceAccessors = createDiagnostic({
|
|
|
10092
10457
|
// src/diagnostics.ts
|
|
10093
10458
|
var diagnostics = [
|
|
10094
10459
|
anyUnknownInErrorContext,
|
|
10460
|
+
catchAllToMapError,
|
|
10095
10461
|
catchUnfailableEffect,
|
|
10096
10462
|
classSelfMismatch,
|
|
10097
10463
|
duplicatePackage,
|
|
@@ -10099,6 +10465,7 @@ var diagnostics = [
|
|
|
10099
10465
|
missingEffectContext,
|
|
10100
10466
|
missingEffectError,
|
|
10101
10467
|
missingEffectServiceDependency,
|
|
10468
|
+
missingLayerContext,
|
|
10102
10469
|
floatingEffect,
|
|
10103
10470
|
missingStarInYieldEffectGen,
|
|
10104
10471
|
unnecessaryEffectGen,
|
|
@@ -10126,7 +10493,9 @@ var diagnostics = [
|
|
|
10126
10493
|
runEffectInsideEffect,
|
|
10127
10494
|
schemaUnionOfLiterals,
|
|
10128
10495
|
schemaStructWithTag,
|
|
10129
|
-
|
|
10496
|
+
globalErrorInEffectCatch,
|
|
10497
|
+
globalErrorInEffectFailure,
|
|
10498
|
+
layerMergeAllWithDependencies
|
|
10130
10499
|
];
|
|
10131
10500
|
|
|
10132
10501
|
// src/completions/effectDiagnosticsComment.ts
|
|
@@ -15714,6 +16083,7 @@ var extractLayerGraph = fn("extractLayerGraph")(function* (node, opts) {
|
|
|
15714
16083
|
const extractNodeInfo = fn("extractNodeInfo")(function* (node2) {
|
|
15715
16084
|
let provides = [];
|
|
15716
16085
|
let requires = [];
|
|
16086
|
+
let actualProvides = [];
|
|
15717
16087
|
let layerType = void 0;
|
|
15718
16088
|
let layerTypes = void 0;
|
|
15719
16089
|
if (nodeInPipeContext.has(node2)) {
|
|
@@ -15736,12 +16106,13 @@ var extractLayerGraph = fn("extractLayerGraph")(function* (node, opts) {
|
|
|
15736
16106
|
if (layerTypes) {
|
|
15737
16107
|
provides = typeCheckerUtils.unrollUnionMembers(layerTypes.ROut).filter((_) => !(_.flags & ts.TypeFlags.Never));
|
|
15738
16108
|
requires = typeCheckerUtils.unrollUnionMembers(layerTypes.RIn).filter((_) => !(_.flags & ts.TypeFlags.Never));
|
|
16109
|
+
actualProvides = provides.filter((_) => !typeChecker.isTypeAssignableTo(_, layerTypes.RIn));
|
|
15739
16110
|
}
|
|
15740
16111
|
let displayNode = node2;
|
|
15741
16112
|
if (node2.parent && ts.isVariableDeclaration(node2.parent) && node2.parent.initializer === node2) {
|
|
15742
16113
|
displayNode = node2.parent.name;
|
|
15743
16114
|
}
|
|
15744
|
-
return { node: node2, displayNode, layerType, layerTypes, provides, requires };
|
|
16115
|
+
return { node: node2, displayNode, layerType, layerTypes, provides, actualProvides, requires };
|
|
15745
16116
|
});
|
|
15746
16117
|
const addNode2 = fn("addNode")(function* (node2, nodeInfo) {
|
|
15747
16118
|
const graphNode = addNode(mutableGraph, nodeInfo ? nodeInfo : yield* extractNodeInfo(node2));
|
|
@@ -15988,10 +16359,10 @@ var extractOutlineGraph = fn("extractOutlineGraph")(function* (layerGraph) {
|
|
|
15988
16359
|
node: leafNode.node,
|
|
15989
16360
|
displayNode: leafNode.displayNode,
|
|
15990
16361
|
requires: leafNode.requires,
|
|
15991
|
-
provides: leafNode.provides
|
|
16362
|
+
provides: leafNode.provides,
|
|
16363
|
+
actualProvides: leafNode.actualProvides
|
|
15992
16364
|
});
|
|
15993
|
-
for (const providedType of leafNode.
|
|
15994
|
-
if (leafNode.requires.indexOf(providedType) > -1) continue;
|
|
16365
|
+
for (const providedType of leafNode.actualProvides) {
|
|
15995
16366
|
const previousProviders = providers.get(providedType) || [];
|
|
15996
16367
|
providers.set(providedType, [...previousProviders, nodeIndex]);
|
|
15997
16368
|
}
|
|
@@ -16087,17 +16458,21 @@ var convertOutlineGraphToLayerMagic = fn("convertOutlineGraphToLayerMagic")(
|
|
|
16087
16458
|
reverse(number2),
|
|
16088
16459
|
(_) => _.provides.length
|
|
16089
16460
|
);
|
|
16461
|
+
const orderByRequiredCount = mapInput(
|
|
16462
|
+
reverse(number2),
|
|
16463
|
+
(_) => _.requires.length
|
|
16464
|
+
);
|
|
16465
|
+
const layerOrder = combine2(orderByProvidedCount, orderByRequiredCount);
|
|
16090
16466
|
const reversedGraph = mutate2(outlineGraph, reverse4);
|
|
16091
16467
|
const rootIndexes = fromIterable(indices(externals(reversedGraph, { direction: "incoming" })));
|
|
16092
16468
|
const allNodes = fromIterable(
|
|
16093
|
-
values2(dfsPostOrderWithOrder(reversedGraph, { start: rootIndexes, order:
|
|
16469
|
+
values2(dfsPostOrderWithOrder(reversedGraph, { start: rootIndexes, order: layerOrder }))
|
|
16094
16470
|
);
|
|
16095
16471
|
for (const nodeInfo of allNodes) {
|
|
16096
16472
|
if (!ts.isExpression(nodeInfo.node)) continue;
|
|
16097
|
-
const
|
|
16098
|
-
const shouldMerge = reallyProvidedTypes.some((_) => missingOutputTypes.has(_));
|
|
16473
|
+
const shouldMerge = nodeInfo.actualProvides.some((_) => missingOutputTypes.has(_));
|
|
16099
16474
|
if (shouldMerge) {
|
|
16100
|
-
|
|
16475
|
+
nodeInfo.actualProvides.forEach((_) => missingOutputTypes.delete(_));
|
|
16101
16476
|
}
|
|
16102
16477
|
nodeInfo.provides.forEach((_) => currentRequiredTypes.delete(_));
|
|
16103
16478
|
nodeInfo.requires.forEach((_) => currentRequiredTypes.add(_));
|