@effect/language-service 0.65.0 → 0.66.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 +2 -0
- package/cli.js +723 -336
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +719 -332
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +719 -332
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +719 -332
- package/transform.js.map +1 -1
package/index.js
CHANGED
|
@@ -5437,6 +5437,97 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5437
5437
|
"TypeParser.effectFnGen",
|
|
5438
5438
|
(node) => node
|
|
5439
5439
|
);
|
|
5440
|
+
const findEnclosingScopes = fn("TypeParser.findEnclosingScopes")(function* (startNode) {
|
|
5441
|
+
let currentParent = startNode.parent;
|
|
5442
|
+
let scopeNode = void 0;
|
|
5443
|
+
let effectGenResult = void 0;
|
|
5444
|
+
while (currentParent) {
|
|
5445
|
+
const nodeToCheck = currentParent;
|
|
5446
|
+
if (!scopeNode) {
|
|
5447
|
+
if (ts.isFunctionExpression(nodeToCheck) || ts.isFunctionDeclaration(nodeToCheck) || ts.isMethodDeclaration(nodeToCheck) || ts.isArrowFunction(nodeToCheck) || ts.isGetAccessorDeclaration(nodeToCheck) || ts.isSetAccessorDeclaration(nodeToCheck)) {
|
|
5448
|
+
scopeNode = nodeToCheck;
|
|
5449
|
+
}
|
|
5450
|
+
}
|
|
5451
|
+
if (!effectGenResult) {
|
|
5452
|
+
const isEffectGen = yield* pipe(
|
|
5453
|
+
effectGen(nodeToCheck),
|
|
5454
|
+
map8((result) => ({
|
|
5455
|
+
node: result.node,
|
|
5456
|
+
effectModule: result.effectModule,
|
|
5457
|
+
generatorFunction: result.generatorFunction,
|
|
5458
|
+
body: result.body
|
|
5459
|
+
})),
|
|
5460
|
+
orElse2(
|
|
5461
|
+
() => pipe(
|
|
5462
|
+
effectFnUntracedGen(nodeToCheck),
|
|
5463
|
+
map8((result) => ({
|
|
5464
|
+
node: result.node,
|
|
5465
|
+
effectModule: result.effectModule,
|
|
5466
|
+
generatorFunction: result.generatorFunction,
|
|
5467
|
+
body: result.body,
|
|
5468
|
+
pipeArguments: result.pipeArguments
|
|
5469
|
+
}))
|
|
5470
|
+
)
|
|
5471
|
+
),
|
|
5472
|
+
orElse2(
|
|
5473
|
+
() => pipe(
|
|
5474
|
+
effectFnGen(nodeToCheck),
|
|
5475
|
+
map8((result) => ({
|
|
5476
|
+
node: result.node,
|
|
5477
|
+
effectModule: result.effectModule,
|
|
5478
|
+
generatorFunction: result.generatorFunction,
|
|
5479
|
+
body: result.body,
|
|
5480
|
+
pipeArguments: result.pipeArguments
|
|
5481
|
+
}))
|
|
5482
|
+
)
|
|
5483
|
+
),
|
|
5484
|
+
option
|
|
5485
|
+
);
|
|
5486
|
+
if (isSome2(isEffectGen)) {
|
|
5487
|
+
effectGenResult = isEffectGen.value;
|
|
5488
|
+
}
|
|
5489
|
+
}
|
|
5490
|
+
if (scopeNode && effectGenResult) {
|
|
5491
|
+
break;
|
|
5492
|
+
}
|
|
5493
|
+
currentParent = nodeToCheck.parent;
|
|
5494
|
+
}
|
|
5495
|
+
return { scopeNode, effectGen: effectGenResult };
|
|
5496
|
+
});
|
|
5497
|
+
const effectFn = cachedBy(
|
|
5498
|
+
function(node) {
|
|
5499
|
+
if (!ts.isCallExpression(node)) {
|
|
5500
|
+
return typeParserIssue("Node is not a call expression", void 0, node);
|
|
5501
|
+
}
|
|
5502
|
+
if (node.arguments.length === 0) {
|
|
5503
|
+
return typeParserIssue("Node has no arguments", void 0, node);
|
|
5504
|
+
}
|
|
5505
|
+
const regularFunction = node.arguments[0];
|
|
5506
|
+
if (!ts.isFunctionExpression(regularFunction) && !ts.isArrowFunction(regularFunction)) {
|
|
5507
|
+
return typeParserIssue("Node is not a function expression or arrow function", void 0, node);
|
|
5508
|
+
}
|
|
5509
|
+
if (ts.isFunctionExpression(regularFunction) && regularFunction.asteriskToken !== void 0) {
|
|
5510
|
+
return typeParserIssue("Node is a generator function, not a regular function", void 0, node);
|
|
5511
|
+
}
|
|
5512
|
+
const expressionToTest = ts.isCallExpression(node.expression) ? node.expression.expression : node.expression;
|
|
5513
|
+
if (!ts.isPropertyAccessExpression(expressionToTest)) {
|
|
5514
|
+
return typeParserIssue("Node is not a property access expression", void 0, node);
|
|
5515
|
+
}
|
|
5516
|
+
const propertyAccess = expressionToTest;
|
|
5517
|
+
const pipeArguments2 = node.arguments.slice(1);
|
|
5518
|
+
return pipe(
|
|
5519
|
+
isNodeReferenceToEffectModuleApi("fn")(propertyAccess),
|
|
5520
|
+
map8(() => ({
|
|
5521
|
+
node,
|
|
5522
|
+
effectModule: propertyAccess.expression,
|
|
5523
|
+
regularFunction,
|
|
5524
|
+
pipeArguments: pipeArguments2
|
|
5525
|
+
}))
|
|
5526
|
+
);
|
|
5527
|
+
},
|
|
5528
|
+
"TypeParser.effectFn",
|
|
5529
|
+
(node) => node
|
|
5530
|
+
);
|
|
5440
5531
|
const unnecessaryEffectGen2 = cachedBy(
|
|
5441
5532
|
fn("TypeParser.unnecessaryEffectGen")(function* (node) {
|
|
5442
5533
|
const { body } = yield* effectGen(node);
|
|
@@ -5548,6 +5639,28 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
5548
5639
|
`TypeParser.isNodeReferenceToEffectSchemaModuleApi(${memberName})`,
|
|
5549
5640
|
(node) => node
|
|
5550
5641
|
);
|
|
5642
|
+
const isEffectParseResultSourceFile = cachedBy(
|
|
5643
|
+
fn("TypeParser.isEffectParseResultSourceFile")(function* (sourceFile) {
|
|
5644
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
5645
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
5646
|
+
const parseIssueSymbol = typeChecker.tryGetMemberInModuleExports("ParseIssue", moduleSymbol);
|
|
5647
|
+
if (!parseIssueSymbol) return yield* typeParserIssue("ParseIssue type not found", void 0, sourceFile);
|
|
5648
|
+
const decodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("decodeSync", moduleSymbol);
|
|
5649
|
+
if (!decodeSyncSymbol) return yield* typeParserIssue("decodeSync not found", void 0, sourceFile);
|
|
5650
|
+
const encodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("encodeSync", moduleSymbol);
|
|
5651
|
+
if (!encodeSyncSymbol) return yield* typeParserIssue("encodeSync not found", void 0, sourceFile);
|
|
5652
|
+
return sourceFile;
|
|
5653
|
+
}),
|
|
5654
|
+
"TypeParser.isEffectParseResultSourceFile",
|
|
5655
|
+
(sourceFile) => sourceFile
|
|
5656
|
+
);
|
|
5657
|
+
const isNodeReferenceToEffectParseResultModuleApi = (memberName) => cachedBy(
|
|
5658
|
+
fn("TypeParser.isNodeReferenceToEffectParseResultModuleApi")(function* (node) {
|
|
5659
|
+
return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectParseResultSourceFile, memberName);
|
|
5660
|
+
}),
|
|
5661
|
+
`TypeParser.isNodeReferenceToEffectParseResultModuleApi(${memberName})`,
|
|
5662
|
+
(node) => node
|
|
5663
|
+
);
|
|
5551
5664
|
const contextTagVarianceStruct = (type, atLocation) => map8(
|
|
5552
5665
|
all(
|
|
5553
5666
|
varianceStructInvariantType(type, atLocation, "_Identifier"),
|
|
@@ -6328,11 +6441,65 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
6328
6441
|
if (includeEffectFn) {
|
|
6329
6442
|
const effectFnGenParsed = yield* pipe(effectFnGen(node), option);
|
|
6330
6443
|
const effectFnUntracedGenParsed = isNone2(effectFnGenParsed) ? yield* pipe(effectFnUntracedGen(node), option) : none2();
|
|
6331
|
-
const
|
|
6332
|
-
const
|
|
6333
|
-
const
|
|
6334
|
-
|
|
6335
|
-
|
|
6444
|
+
const effectFnNonGenParsed = isNone2(effectFnGenParsed) && isNone2(effectFnUntracedGenParsed) ? yield* pipe(effectFn(node), option) : none2();
|
|
6445
|
+
const isEffectFnGen = isSome2(effectFnGenParsed);
|
|
6446
|
+
const isEffectFnUntracedGen = isSome2(effectFnUntracedGenParsed);
|
|
6447
|
+
const isEffectFnNonGen = isSome2(effectFnNonGenParsed);
|
|
6448
|
+
const transformationKind = isEffectFnUntracedGen ? "effectFnUntraced" : "effectFn";
|
|
6449
|
+
if (isEffectFnGen || isEffectFnUntracedGen) {
|
|
6450
|
+
const effectFnParsed = isEffectFnGen ? effectFnGenParsed : effectFnUntracedGenParsed;
|
|
6451
|
+
if (isSome2(effectFnParsed) && effectFnParsed.value.pipeArguments.length > 0) {
|
|
6452
|
+
const fnResult = effectFnParsed.value;
|
|
6453
|
+
const pipeArgs = fnResult.pipeArguments;
|
|
6454
|
+
const transformations = [];
|
|
6455
|
+
let subjectType;
|
|
6456
|
+
for (let i = 0; i < pipeArgs.length; i++) {
|
|
6457
|
+
const arg = pipeArgs[i];
|
|
6458
|
+
const contextualType = typeChecker.getContextualType(arg);
|
|
6459
|
+
const callSigs = contextualType ? typeChecker.getSignaturesOfType(contextualType, ts.SignatureKind.Call) : [];
|
|
6460
|
+
const outType = callSigs.length > 0 ? typeChecker.getReturnTypeOfSignature(callSigs[0]) : void 0;
|
|
6461
|
+
if (i === 0 && callSigs.length > 0) {
|
|
6462
|
+
const params = callSigs[0].parameters;
|
|
6463
|
+
if (params.length > 0) {
|
|
6464
|
+
subjectType = typeChecker.getTypeOfSymbol(params[0]);
|
|
6465
|
+
}
|
|
6466
|
+
}
|
|
6467
|
+
if (ts.isCallExpression(arg)) {
|
|
6468
|
+
transformations.push({
|
|
6469
|
+
callee: arg.expression,
|
|
6470
|
+
args: Array.from(arg.arguments),
|
|
6471
|
+
outType,
|
|
6472
|
+
kind: transformationKind
|
|
6473
|
+
});
|
|
6474
|
+
} else {
|
|
6475
|
+
transformations.push({
|
|
6476
|
+
callee: arg,
|
|
6477
|
+
args: void 0,
|
|
6478
|
+
outType,
|
|
6479
|
+
kind: transformationKind
|
|
6480
|
+
});
|
|
6481
|
+
}
|
|
6482
|
+
}
|
|
6483
|
+
const newFlow = {
|
|
6484
|
+
node,
|
|
6485
|
+
subject: {
|
|
6486
|
+
node,
|
|
6487
|
+
outType: subjectType
|
|
6488
|
+
},
|
|
6489
|
+
transformations
|
|
6490
|
+
};
|
|
6491
|
+
result.push(newFlow);
|
|
6492
|
+
workQueue.push([fnResult.body, void 0]);
|
|
6493
|
+
for (const arg of pipeArgs) {
|
|
6494
|
+
ts.forEachChild(arg, (c) => {
|
|
6495
|
+
workQueue.push([c, void 0]);
|
|
6496
|
+
});
|
|
6497
|
+
}
|
|
6498
|
+
continue;
|
|
6499
|
+
}
|
|
6500
|
+
}
|
|
6501
|
+
if (isEffectFnNonGen && isSome2(effectFnNonGenParsed) && effectFnNonGenParsed.value.pipeArguments.length > 0) {
|
|
6502
|
+
const fnResult = effectFnNonGenParsed.value;
|
|
6336
6503
|
const pipeArgs = fnResult.pipeArguments;
|
|
6337
6504
|
const transformations = [];
|
|
6338
6505
|
let subjectType;
|
|
@@ -6352,14 +6519,14 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
6352
6519
|
callee: arg.expression,
|
|
6353
6520
|
args: Array.from(arg.arguments),
|
|
6354
6521
|
outType,
|
|
6355
|
-
kind:
|
|
6522
|
+
kind: "effectFn"
|
|
6356
6523
|
});
|
|
6357
6524
|
} else {
|
|
6358
6525
|
transformations.push({
|
|
6359
6526
|
callee: arg,
|
|
6360
6527
|
args: void 0,
|
|
6361
6528
|
outType,
|
|
6362
|
-
kind:
|
|
6529
|
+
kind: "effectFn"
|
|
6363
6530
|
});
|
|
6364
6531
|
}
|
|
6365
6532
|
}
|
|
@@ -6372,7 +6539,16 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
6372
6539
|
transformations
|
|
6373
6540
|
};
|
|
6374
6541
|
result.push(newFlow);
|
|
6375
|
-
|
|
6542
|
+
const regularFn = fnResult.regularFunction;
|
|
6543
|
+
if (ts.isArrowFunction(regularFn)) {
|
|
6544
|
+
if (ts.isBlock(regularFn.body)) {
|
|
6545
|
+
workQueue.push([regularFn.body, void 0]);
|
|
6546
|
+
} else {
|
|
6547
|
+
workQueue.push([regularFn.body, void 0]);
|
|
6548
|
+
}
|
|
6549
|
+
} else if (regularFn.body) {
|
|
6550
|
+
workQueue.push([regularFn.body, void 0]);
|
|
6551
|
+
}
|
|
6376
6552
|
for (const arg of pipeArgs) {
|
|
6377
6553
|
ts.forEachChild(arg, (c) => {
|
|
6378
6554
|
workQueue.push([c, void 0]);
|
|
@@ -6435,6 +6611,7 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
6435
6611
|
return {
|
|
6436
6612
|
isNodeReferenceToEffectModuleApi,
|
|
6437
6613
|
isNodeReferenceToEffectSchemaModuleApi,
|
|
6614
|
+
isNodeReferenceToEffectParseResultModuleApi,
|
|
6438
6615
|
isNodeReferenceToEffectDataModuleApi,
|
|
6439
6616
|
isNodeReferenceToEffectContextModuleApi,
|
|
6440
6617
|
isNodeReferenceToEffectSqlModelModuleApi,
|
|
@@ -6448,6 +6625,8 @@ function make7(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
6448
6625
|
effectGen,
|
|
6449
6626
|
effectFnUntracedGen,
|
|
6450
6627
|
effectFnGen,
|
|
6628
|
+
findEnclosingScopes,
|
|
6629
|
+
effectFn,
|
|
6451
6630
|
extendsCauseYieldableError,
|
|
6452
6631
|
unnecessaryEffectGen: unnecessaryEffectGen2,
|
|
6453
6632
|
effectSchemaType,
|
|
@@ -8147,106 +8326,184 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
|
|
|
8147
8326
|
});
|
|
8148
8327
|
|
|
8149
8328
|
// src/diagnostics/effectFnOpportunity.ts
|
|
8150
|
-
var parseEffectFnOpportunityTarget = (node, sourceFile) => gen(function* () {
|
|
8151
|
-
const ts = yield* service(TypeScriptApi);
|
|
8152
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
8153
|
-
const typeParser = yield* service(TypeParser);
|
|
8154
|
-
const tsUtils = yield* service(TypeScriptUtils);
|
|
8155
|
-
if (!ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isFunctionDeclaration(node)) {
|
|
8156
|
-
return yield* TypeParserIssue.issue;
|
|
8157
|
-
}
|
|
8158
|
-
if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.asteriskToken) {
|
|
8159
|
-
return yield* TypeParserIssue.issue;
|
|
8160
|
-
}
|
|
8161
|
-
if (ts.isFunctionExpression(node) && node.name) {
|
|
8162
|
-
return yield* TypeParserIssue.issue;
|
|
8163
|
-
}
|
|
8164
|
-
let bodyExpression;
|
|
8165
|
-
if (ts.isArrowFunction(node)) {
|
|
8166
|
-
if (ts.isBlock(node.body)) {
|
|
8167
|
-
const returnStatement = findSingleReturnStatement(ts, node.body);
|
|
8168
|
-
if (returnStatement?.expression) {
|
|
8169
|
-
bodyExpression = returnStatement.expression;
|
|
8170
|
-
}
|
|
8171
|
-
} else {
|
|
8172
|
-
bodyExpression = node.body;
|
|
8173
|
-
}
|
|
8174
|
-
} else if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.body) {
|
|
8175
|
-
const returnStatement = findSingleReturnStatement(ts, node.body);
|
|
8176
|
-
if (returnStatement?.expression) {
|
|
8177
|
-
bodyExpression = returnStatement.expression;
|
|
8178
|
-
}
|
|
8179
|
-
}
|
|
8180
|
-
if (!bodyExpression) return yield* TypeParserIssue.issue;
|
|
8181
|
-
const { pipeArguments: pipeArguments2, subject } = yield* pipe(
|
|
8182
|
-
typeParser.pipeCall(bodyExpression),
|
|
8183
|
-
map8(({ args: args2, subject: subject2 }) => ({ subject: subject2, pipeArguments: args2 })),
|
|
8184
|
-
orElse2(() => succeed({ subject: bodyExpression, pipeArguments: [] }))
|
|
8185
|
-
);
|
|
8186
|
-
const { effectModule, generatorFunction } = yield* typeParser.effectGen(subject);
|
|
8187
|
-
const functionType = typeChecker.getTypeAtLocation(node);
|
|
8188
|
-
if (!functionType) return yield* TypeParserIssue.issue;
|
|
8189
|
-
const callSignatures = typeChecker.getSignaturesOfType(functionType, ts.SignatureKind.Call);
|
|
8190
|
-
if (callSignatures.length !== 1) return yield* TypeParserIssue.issue;
|
|
8191
|
-
const signature = callSignatures[0];
|
|
8192
|
-
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
8193
|
-
const { A, E, R } = yield* typeParser.strictEffectType(returnType, node);
|
|
8194
|
-
const effectModuleName = ts.isIdentifier(effectModule) ? ts.idText(effectModule) : tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
8195
|
-
sourceFile,
|
|
8196
|
-
"effect",
|
|
8197
|
-
"Effect"
|
|
8198
|
-
) || "Effect";
|
|
8199
|
-
const nameIdentifier = getNameIdentifier(ts, node);
|
|
8200
|
-
const traceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
|
|
8201
|
-
const hasReturnTypeAnnotation = !!node.type;
|
|
8202
|
-
return {
|
|
8203
|
-
node,
|
|
8204
|
-
nameIdentifier,
|
|
8205
|
-
effectModule,
|
|
8206
|
-
generatorFunction,
|
|
8207
|
-
effectModuleName,
|
|
8208
|
-
traceName,
|
|
8209
|
-
hasReturnTypeAnnotation,
|
|
8210
|
-
effectTypes: { A, E, R },
|
|
8211
|
-
pipeArguments: pipeArguments2
|
|
8212
|
-
};
|
|
8213
|
-
});
|
|
8214
8329
|
var effectFnOpportunity = createDiagnostic({
|
|
8215
8330
|
name: "effectFnOpportunity",
|
|
8216
8331
|
code: 41,
|
|
8217
|
-
description: "Suggests using Effect.fn for functions that
|
|
8332
|
+
description: "Suggests using Effect.fn for functions that returns an Effect",
|
|
8218
8333
|
severity: "suggestion",
|
|
8219
8334
|
apply: fn("effectFnOpportunity.apply")(function* (sourceFile, report) {
|
|
8220
8335
|
const ts = yield* service(TypeScriptApi);
|
|
8221
8336
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
8337
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
8338
|
+
const typeParser = yield* service(TypeParser);
|
|
8222
8339
|
const tsUtils = yield* service(TypeScriptUtils);
|
|
8223
|
-
const
|
|
8224
|
-
|
|
8225
|
-
|
|
8226
|
-
|
|
8227
|
-
|
|
8228
|
-
|
|
8229
|
-
|
|
8230
|
-
|
|
8231
|
-
|
|
8232
|
-
|
|
8233
|
-
|
|
8234
|
-
|
|
8235
|
-
|
|
8236
|
-
)
|
|
8237
|
-
|
|
8340
|
+
const sourceEffectModuleName = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
8341
|
+
sourceFile,
|
|
8342
|
+
"effect",
|
|
8343
|
+
"Effect"
|
|
8344
|
+
) || "Effect";
|
|
8345
|
+
const findSingleReturnStatement = (block) => {
|
|
8346
|
+
if (block.statements.length !== 1) return void 0;
|
|
8347
|
+
const statement = block.statements[0];
|
|
8348
|
+
if (!ts.isReturnStatement(statement)) return void 0;
|
|
8349
|
+
return statement;
|
|
8350
|
+
};
|
|
8351
|
+
const getBodyExpression = (fnNode) => {
|
|
8352
|
+
if (ts.isArrowFunction(fnNode)) {
|
|
8353
|
+
if (ts.isBlock(fnNode.body)) {
|
|
8354
|
+
return findSingleReturnStatement(fnNode.body)?.expression;
|
|
8355
|
+
}
|
|
8356
|
+
return fnNode.body;
|
|
8357
|
+
} else if ((ts.isFunctionExpression(fnNode) || ts.isFunctionDeclaration(fnNode)) && fnNode.body) {
|
|
8358
|
+
return findSingleReturnStatement(fnNode.body)?.expression;
|
|
8359
|
+
}
|
|
8360
|
+
return void 0;
|
|
8361
|
+
};
|
|
8362
|
+
const getNameIdentifier = (node) => {
|
|
8363
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
8364
|
+
return node.name;
|
|
8365
|
+
}
|
|
8366
|
+
if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
|
|
8367
|
+
return node.parent.name;
|
|
8368
|
+
}
|
|
8369
|
+
if (node.parent && ts.isPropertyAssignment(node.parent)) {
|
|
8370
|
+
const name = node.parent.name;
|
|
8371
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
|
|
8372
|
+
return name;
|
|
8373
|
+
}
|
|
8374
|
+
}
|
|
8375
|
+
if (node.parent && ts.isPropertyDeclaration(node.parent)) {
|
|
8376
|
+
const name = node.parent.name;
|
|
8377
|
+
if (ts.isIdentifier(name)) {
|
|
8378
|
+
return name;
|
|
8379
|
+
}
|
|
8380
|
+
}
|
|
8381
|
+
return void 0;
|
|
8382
|
+
};
|
|
8383
|
+
const areParametersReferencedIn = (fnNode, nodes2) => {
|
|
8384
|
+
if (fnNode.parameters.length === 0 || nodes2.length === 0) return false;
|
|
8385
|
+
const firstParam = fnNode.parameters[0];
|
|
8386
|
+
const lastParam = fnNode.parameters[fnNode.parameters.length - 1];
|
|
8387
|
+
const paramsStart = firstParam.pos;
|
|
8388
|
+
const paramsEnd = lastParam.end;
|
|
8389
|
+
const isSymbolDeclaredInParams = (symbol3) => {
|
|
8390
|
+
const declarations = symbol3.declarations;
|
|
8391
|
+
if (!declarations) return false;
|
|
8392
|
+
return declarations.some((decl) => decl.pos >= paramsStart && decl.end <= paramsEnd);
|
|
8393
|
+
};
|
|
8394
|
+
const nodesToVisit = [...nodes2];
|
|
8395
|
+
while (nodesToVisit.length > 0) {
|
|
8396
|
+
const node = nodesToVisit.shift();
|
|
8397
|
+
if (ts.isIdentifier(node)) {
|
|
8398
|
+
const symbol3 = typeChecker.getSymbolAtLocation(node);
|
|
8399
|
+
if (symbol3 && isSymbolDeclaredInParams(symbol3)) {
|
|
8400
|
+
return true;
|
|
8401
|
+
}
|
|
8402
|
+
}
|
|
8403
|
+
if (ts.isShorthandPropertyAssignment(node)) {
|
|
8404
|
+
const valueSymbol = typeChecker.getShorthandAssignmentValueSymbol(node);
|
|
8405
|
+
if (valueSymbol && isSymbolDeclaredInParams(valueSymbol)) {
|
|
8406
|
+
return true;
|
|
8407
|
+
}
|
|
8408
|
+
}
|
|
8409
|
+
ts.forEachChild(node, (child) => {
|
|
8410
|
+
nodesToVisit.push(child);
|
|
8411
|
+
return void 0;
|
|
8412
|
+
});
|
|
8413
|
+
}
|
|
8414
|
+
return false;
|
|
8415
|
+
};
|
|
8416
|
+
const tryParseGenOpportunity = (fnNode) => gen(function* () {
|
|
8417
|
+
const bodyExpression = getBodyExpression(fnNode);
|
|
8418
|
+
if (!bodyExpression) return yield* TypeParserIssue.issue;
|
|
8419
|
+
const { pipeArguments: pipeArguments2, subject } = yield* pipe(
|
|
8420
|
+
typeParser.pipeCall(bodyExpression),
|
|
8421
|
+
map8(({ args: args2, subject: subject2 }) => ({ subject: subject2, pipeArguments: args2 })),
|
|
8422
|
+
orElse2(() => succeed({ subject: bodyExpression, pipeArguments: [] }))
|
|
8238
8423
|
);
|
|
8424
|
+
const { effectModule, generatorFunction } = yield* typeParser.effectGen(subject);
|
|
8425
|
+
const effectModuleName = ts.isIdentifier(effectModule) ? ts.idText(effectModule) : sourceEffectModuleName;
|
|
8426
|
+
return { effectModuleName, generatorFunction, pipeArguments: pipeArguments2 };
|
|
8427
|
+
});
|
|
8428
|
+
const isInsideEffectFn = (fnNode) => {
|
|
8429
|
+
const parent = fnNode.parent;
|
|
8430
|
+
if (!parent || !ts.isCallExpression(parent)) {
|
|
8431
|
+
return succeed(false);
|
|
8432
|
+
}
|
|
8433
|
+
if (parent.arguments[0] !== fnNode) {
|
|
8434
|
+
return succeed(false);
|
|
8435
|
+
}
|
|
8436
|
+
return pipe(
|
|
8437
|
+
typeParser.effectFn(parent),
|
|
8438
|
+
orElse2(() => typeParser.effectFnGen(parent)),
|
|
8439
|
+
orElse2(() => typeParser.effectFnUntracedGen(parent)),
|
|
8440
|
+
map8(() => true),
|
|
8441
|
+
orElse2(() => succeed(false))
|
|
8442
|
+
);
|
|
8443
|
+
};
|
|
8444
|
+
const parseEffectFnOpportunityTarget = (node) => gen(function* () {
|
|
8445
|
+
if (!ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isFunctionDeclaration(node)) {
|
|
8446
|
+
return yield* TypeParserIssue.issue;
|
|
8447
|
+
}
|
|
8448
|
+
if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.asteriskToken) {
|
|
8449
|
+
return yield* TypeParserIssue.issue;
|
|
8450
|
+
}
|
|
8451
|
+
if (ts.isFunctionExpression(node) && node.name) {
|
|
8452
|
+
return yield* TypeParserIssue.issue;
|
|
8453
|
+
}
|
|
8454
|
+
if (yield* isInsideEffectFn(node)) {
|
|
8455
|
+
return yield* TypeParserIssue.issue;
|
|
8456
|
+
}
|
|
8457
|
+
const functionType = typeChecker.getTypeAtLocation(node);
|
|
8458
|
+
if (!functionType) return yield* TypeParserIssue.issue;
|
|
8459
|
+
const callSignatures = typeChecker.getSignaturesOfType(functionType, ts.SignatureKind.Call);
|
|
8460
|
+
if (callSignatures.length !== 1) return yield* TypeParserIssue.issue;
|
|
8461
|
+
const signature = callSignatures[0];
|
|
8462
|
+
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
8463
|
+
const unionMembers = typeCheckerUtils.unrollUnionMembers(returnType);
|
|
8464
|
+
yield* all(...unionMembers.map((member) => typeParser.strictEffectType(member, node)));
|
|
8465
|
+
const nameIdentifier = getNameIdentifier(node);
|
|
8466
|
+
const traceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
|
|
8467
|
+
if (!traceName) return yield* TypeParserIssue.issue;
|
|
8468
|
+
const opportunity = yield* pipe(
|
|
8469
|
+
tryParseGenOpportunity(node),
|
|
8470
|
+
orElse2(
|
|
8471
|
+
() => succeed({ effectModuleName: sourceEffectModuleName, pipeArguments: [], generatorFunction: void 0 })
|
|
8472
|
+
)
|
|
8473
|
+
);
|
|
8474
|
+
return {
|
|
8475
|
+
node,
|
|
8476
|
+
nameIdentifier,
|
|
8477
|
+
effectModuleName: opportunity.effectModuleName,
|
|
8478
|
+
traceName,
|
|
8479
|
+
pipeArguments: opportunity.pipeArguments,
|
|
8480
|
+
generatorFunction: opportunity.generatorFunction,
|
|
8481
|
+
hasParamsInPipeArgs: areParametersReferencedIn(node, opportunity.pipeArguments)
|
|
8482
|
+
};
|
|
8483
|
+
});
|
|
8484
|
+
const getFunctionBodyBlock = (node) => {
|
|
8485
|
+
if (ts.isArrowFunction(node)) {
|
|
8486
|
+
if (ts.isBlock(node.body)) {
|
|
8487
|
+
return node.body;
|
|
8488
|
+
}
|
|
8489
|
+
return ts.factory.createBlock([ts.factory.createReturnStatement(node.body)], true);
|
|
8490
|
+
}
|
|
8491
|
+
return node.body;
|
|
8239
8492
|
};
|
|
8240
|
-
const
|
|
8241
|
-
|
|
8242
|
-
|
|
8493
|
+
const isGeneratorFunction = (node) => {
|
|
8494
|
+
if (ts.isArrowFunction(node)) return false;
|
|
8495
|
+
return node.asteriskToken !== void 0;
|
|
8496
|
+
};
|
|
8497
|
+
const createEffectFnNode = (originalNode, innerFunction, effectModuleName, traceName, pipeArguments2) => {
|
|
8498
|
+
const isGenerator = isGeneratorFunction(innerFunction);
|
|
8499
|
+
const newFunction = ts.factory.createFunctionExpression(
|
|
8243
8500
|
void 0,
|
|
8244
|
-
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
8501
|
+
isGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : void 0,
|
|
8245
8502
|
void 0,
|
|
8246
8503
|
originalNode.typeParameters,
|
|
8247
8504
|
originalNode.parameters,
|
|
8248
|
-
|
|
8249
|
-
|
|
8505
|
+
void 0,
|
|
8506
|
+
getFunctionBodyBlock(innerFunction)
|
|
8250
8507
|
);
|
|
8251
8508
|
let fnExpression = ts.factory.createPropertyAccessExpression(
|
|
8252
8509
|
ts.factory.createIdentifier(effectModuleName),
|
|
@@ -8259,34 +8516,27 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
8259
8516
|
[ts.factory.createStringLiteral(traceName)]
|
|
8260
8517
|
);
|
|
8261
8518
|
}
|
|
8262
|
-
const effectFnCall = ts.factory.createCallExpression(
|
|
8263
|
-
fnExpression,
|
|
8264
|
-
void 0,
|
|
8265
|
-
[newGeneratorFunction, ...pipeArguments2]
|
|
8266
|
-
);
|
|
8519
|
+
const effectFnCall = ts.factory.createCallExpression(fnExpression, void 0, [newFunction, ...pipeArguments2]);
|
|
8267
8520
|
if (ts.isFunctionDeclaration(originalNode)) {
|
|
8268
8521
|
return tsUtils.tryPreserveDeclarationSemantics(originalNode, effectFnCall, false);
|
|
8269
8522
|
}
|
|
8270
8523
|
return effectFnCall;
|
|
8271
8524
|
};
|
|
8272
|
-
const createEffectFnUntracedNode = (originalNode,
|
|
8273
|
-
const
|
|
8274
|
-
const
|
|
8525
|
+
const createEffectFnUntracedNode = (originalNode, innerFunction, effectModuleName, pipeArguments2) => {
|
|
8526
|
+
const isGenerator = isGeneratorFunction(innerFunction);
|
|
8527
|
+
const newFunction = ts.factory.createFunctionExpression(
|
|
8275
8528
|
void 0,
|
|
8276
|
-
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
8529
|
+
isGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : void 0,
|
|
8277
8530
|
void 0,
|
|
8278
8531
|
originalNode.typeParameters,
|
|
8279
8532
|
originalNode.parameters,
|
|
8280
|
-
|
|
8281
|
-
|
|
8533
|
+
void 0,
|
|
8534
|
+
getFunctionBodyBlock(innerFunction)
|
|
8282
8535
|
);
|
|
8283
8536
|
const effectFnCall = ts.factory.createCallExpression(
|
|
8284
|
-
ts.factory.createPropertyAccessExpression(
|
|
8285
|
-
ts.factory.createIdentifier(effectModuleName),
|
|
8286
|
-
"fnUntraced"
|
|
8287
|
-
),
|
|
8537
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(effectModuleName), "fnUntraced"),
|
|
8288
8538
|
void 0,
|
|
8289
|
-
[
|
|
8539
|
+
[newFunction, ...pipeArguments2]
|
|
8290
8540
|
);
|
|
8291
8541
|
if (ts.isFunctionDeclaration(originalNode)) {
|
|
8292
8542
|
return tsUtils.tryPreserveDeclarationSemantics(originalNode, effectFnCall, false);
|
|
@@ -8302,88 +8552,41 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
8302
8552
|
while (nodeToVisit.length > 0) {
|
|
8303
8553
|
const node = nodeToVisit.shift();
|
|
8304
8554
|
ts.forEachChild(node, appendNodeToVisit);
|
|
8305
|
-
const target = yield* pipe(
|
|
8306
|
-
parseEffectFnOpportunityTarget(node, sourceFile),
|
|
8307
|
-
option
|
|
8308
|
-
);
|
|
8555
|
+
const target = yield* pipe(parseEffectFnOpportunityTarget(node), option);
|
|
8309
8556
|
if (isNone2(target)) continue;
|
|
8310
|
-
|
|
8311
|
-
|
|
8312
|
-
|
|
8313
|
-
generatorFunction,
|
|
8314
|
-
hasReturnTypeAnnotation,
|
|
8315
|
-
nameIdentifier,
|
|
8316
|
-
node: targetNode,
|
|
8317
|
-
pipeArguments: pipeArguments2,
|
|
8318
|
-
traceName
|
|
8319
|
-
} = target.value;
|
|
8557
|
+
if (target.value.hasParamsInPipeArgs) continue;
|
|
8558
|
+
const { effectModuleName, nameIdentifier, node: targetNode, pipeArguments: pipeArguments2, traceName } = target.value;
|
|
8559
|
+
const innerFunction = target.value.generatorFunction ?? targetNode;
|
|
8320
8560
|
const fixes = [];
|
|
8321
8561
|
fixes.push({
|
|
8322
8562
|
fixName: "effectFnOpportunity_toEffectFn",
|
|
8323
8563
|
description: traceName ? `Convert to Effect.fn("${traceName}")` : "Convert to Effect.fn",
|
|
8324
8564
|
apply: gen(function* () {
|
|
8325
8565
|
const changeTracker = yield* service(ChangeTracker);
|
|
8326
|
-
const newNode = createEffectFnNode(
|
|
8327
|
-
targetNode,
|
|
8328
|
-
generatorFunction,
|
|
8329
|
-
effectModuleName,
|
|
8330
|
-
traceName,
|
|
8331
|
-
hasReturnTypeAnnotation ? effectTypes : void 0,
|
|
8332
|
-
pipeArguments2
|
|
8333
|
-
);
|
|
8334
|
-
changeTracker.replaceNode(sourceFile, targetNode, newNode);
|
|
8335
|
-
})
|
|
8336
|
-
});
|
|
8337
|
-
fixes.push({
|
|
8338
|
-
fixName: "effectFnOpportunity_toEffectFnUntraced",
|
|
8339
|
-
description: "Convert to Effect.fnUntraced",
|
|
8340
|
-
apply: gen(function* () {
|
|
8341
|
-
const changeTracker = yield* service(ChangeTracker);
|
|
8342
|
-
const newNode = createEffectFnUntracedNode(
|
|
8343
|
-
targetNode,
|
|
8344
|
-
generatorFunction,
|
|
8345
|
-
effectModuleName,
|
|
8346
|
-
hasReturnTypeAnnotation ? effectTypes : void 0,
|
|
8347
|
-
pipeArguments2
|
|
8348
|
-
);
|
|
8566
|
+
const newNode = createEffectFnNode(targetNode, innerFunction, effectModuleName, traceName, pipeArguments2);
|
|
8349
8567
|
changeTracker.replaceNode(sourceFile, targetNode, newNode);
|
|
8350
8568
|
})
|
|
8351
8569
|
});
|
|
8570
|
+
if (target.value.generatorFunction) {
|
|
8571
|
+
fixes.push({
|
|
8572
|
+
fixName: "effectFnOpportunity_toEffectFnUntraced",
|
|
8573
|
+
description: "Convert to Effect.fnUntraced",
|
|
8574
|
+
apply: gen(function* () {
|
|
8575
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
8576
|
+
const newNode = createEffectFnUntracedNode(targetNode, innerFunction, effectModuleName, pipeArguments2);
|
|
8577
|
+
changeTracker.replaceNode(sourceFile, targetNode, newNode);
|
|
8578
|
+
})
|
|
8579
|
+
});
|
|
8580
|
+
}
|
|
8581
|
+
const pipeArgsSuffix = pipeArguments2.length > 0 ? ` Effect.fn also accepts the piped transformations as additional arguments.` : ``;
|
|
8352
8582
|
report({
|
|
8353
8583
|
location: nameIdentifier ?? targetNode,
|
|
8354
|
-
messageText: `This function could benefit from Effect.fn's automatic tracing and concise syntax, or Effect.fnUntraced to get just a more concise syntax
|
|
8584
|
+
messageText: target.value.generatorFunction ? `This function could benefit from Effect.fn's automatic tracing and concise syntax, or Effect.fnUntraced to get just a more concise syntax.${pipeArgsSuffix}` : `This function could benefit from Effect.fn's automatic tracing and concise syntax.${pipeArgsSuffix}`,
|
|
8355
8585
|
fixes
|
|
8356
8586
|
});
|
|
8357
8587
|
}
|
|
8358
8588
|
})
|
|
8359
8589
|
});
|
|
8360
|
-
function findSingleReturnStatement(ts, block) {
|
|
8361
|
-
if (block.statements.length !== 1) return void 0;
|
|
8362
|
-
const statement = block.statements[0];
|
|
8363
|
-
if (!ts.isReturnStatement(statement)) return void 0;
|
|
8364
|
-
return statement;
|
|
8365
|
-
}
|
|
8366
|
-
function getNameIdentifier(ts, node) {
|
|
8367
|
-
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
8368
|
-
return node.name;
|
|
8369
|
-
}
|
|
8370
|
-
if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
|
|
8371
|
-
return node.parent.name;
|
|
8372
|
-
}
|
|
8373
|
-
if (node.parent && ts.isPropertyAssignment(node.parent)) {
|
|
8374
|
-
const name = node.parent.name;
|
|
8375
|
-
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
|
|
8376
|
-
return name;
|
|
8377
|
-
}
|
|
8378
|
-
}
|
|
8379
|
-
if (node.parent && ts.isPropertyDeclaration(node.parent)) {
|
|
8380
|
-
const name = node.parent.name;
|
|
8381
|
-
if (ts.isIdentifier(name)) {
|
|
8382
|
-
return name;
|
|
8383
|
-
}
|
|
8384
|
-
}
|
|
8385
|
-
return void 0;
|
|
8386
|
-
}
|
|
8387
8590
|
|
|
8388
8591
|
// src/diagnostics/effectGenUsesAdapter.ts
|
|
8389
8592
|
var effectGenUsesAdapter = createDiagnostic({
|
|
@@ -9146,6 +9349,52 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
9146
9349
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
9147
9350
|
const typeParser = yield* service(TypeParser);
|
|
9148
9351
|
const options = yield* service(LanguageServicePluginOptions);
|
|
9352
|
+
const isSafelyPipeableCallee = (callee) => {
|
|
9353
|
+
if (ts.isCallExpression(callee)) {
|
|
9354
|
+
return true;
|
|
9355
|
+
}
|
|
9356
|
+
if (ts.isArrowFunction(callee)) {
|
|
9357
|
+
return true;
|
|
9358
|
+
}
|
|
9359
|
+
if (ts.isFunctionExpression(callee)) {
|
|
9360
|
+
return true;
|
|
9361
|
+
}
|
|
9362
|
+
if (ts.isParenthesizedExpression(callee)) {
|
|
9363
|
+
return isSafelyPipeableCallee(callee.expression);
|
|
9364
|
+
}
|
|
9365
|
+
if (ts.isIdentifier(callee)) {
|
|
9366
|
+
const symbol3 = typeChecker.getSymbolAtLocation(callee);
|
|
9367
|
+
if (!symbol3) return false;
|
|
9368
|
+
if (symbol3.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Namespace | ts.SymbolFlags.ValueModule)) {
|
|
9369
|
+
return true;
|
|
9370
|
+
}
|
|
9371
|
+
const declarations = symbol3.declarations;
|
|
9372
|
+
if (declarations && declarations.length > 0) {
|
|
9373
|
+
const decl = declarations[0];
|
|
9374
|
+
if (ts.isFunctionDeclaration(decl) || ts.isVariableDeclaration(decl) || ts.isImportSpecifier(decl) || ts.isImportClause(decl) || ts.isNamespaceImport(decl)) {
|
|
9375
|
+
return true;
|
|
9376
|
+
}
|
|
9377
|
+
}
|
|
9378
|
+
return false;
|
|
9379
|
+
}
|
|
9380
|
+
if (ts.isPropertyAccessExpression(callee)) {
|
|
9381
|
+
const subject = callee.expression;
|
|
9382
|
+
const symbol3 = typeChecker.getSymbolAtLocation(subject);
|
|
9383
|
+
if (!symbol3) return false;
|
|
9384
|
+
if (symbol3.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Namespace | ts.SymbolFlags.ValueModule)) {
|
|
9385
|
+
return true;
|
|
9386
|
+
}
|
|
9387
|
+
const declarations = symbol3.declarations;
|
|
9388
|
+
if (declarations && declarations.length > 0) {
|
|
9389
|
+
const decl = declarations[0];
|
|
9390
|
+
if (ts.isNamespaceImport(decl) || ts.isSourceFile(decl) || ts.isModuleDeclaration(decl)) {
|
|
9391
|
+
return true;
|
|
9392
|
+
}
|
|
9393
|
+
}
|
|
9394
|
+
return false;
|
|
9395
|
+
}
|
|
9396
|
+
return false;
|
|
9397
|
+
};
|
|
9149
9398
|
const flows = yield* typeParser.pipingFlows(false)(sourceFile);
|
|
9150
9399
|
for (const flow2 of flows) {
|
|
9151
9400
|
if (flow2.transformations.length < options.pipeableMinArgCount) {
|
|
@@ -9159,76 +9408,92 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
9159
9408
|
if (callSigs.length > 0) {
|
|
9160
9409
|
continue;
|
|
9161
9410
|
}
|
|
9162
|
-
|
|
9163
|
-
|
|
9164
|
-
|
|
9165
|
-
|
|
9166
|
-
|
|
9167
|
-
|
|
9168
|
-
|
|
9169
|
-
|
|
9170
|
-
|
|
9171
|
-
|
|
9172
|
-
|
|
9173
|
-
|
|
9174
|
-
|
|
9411
|
+
const isPipeableAtIndex = function* (index) {
|
|
9412
|
+
if (index === 0) {
|
|
9413
|
+
const subjectType = flow2.subject.outType;
|
|
9414
|
+
if (!subjectType) return false;
|
|
9415
|
+
const result = yield* pipe(
|
|
9416
|
+
typeParser.pipeableType(subjectType, flow2.subject.node),
|
|
9417
|
+
option
|
|
9418
|
+
);
|
|
9419
|
+
return result._tag === "Some";
|
|
9420
|
+
} else {
|
|
9421
|
+
const t = flow2.transformations[index - 1];
|
|
9422
|
+
if (!t.outType) return false;
|
|
9423
|
+
const result = yield* pipe(
|
|
9424
|
+
typeParser.pipeableType(t.outType, flow2.node),
|
|
9425
|
+
option
|
|
9426
|
+
);
|
|
9427
|
+
return result._tag === "Some";
|
|
9428
|
+
}
|
|
9429
|
+
};
|
|
9430
|
+
let searchStartIndex = 0;
|
|
9431
|
+
while (searchStartIndex <= flow2.transformations.length) {
|
|
9432
|
+
let firstPipeableIndex = -1;
|
|
9433
|
+
for (let i = searchStartIndex; i <= flow2.transformations.length; i++) {
|
|
9434
|
+
if (yield* isPipeableAtIndex(i)) {
|
|
9435
|
+
firstPipeableIndex = i;
|
|
9436
|
+
break;
|
|
9437
|
+
}
|
|
9438
|
+
}
|
|
9439
|
+
if (firstPipeableIndex === -1) {
|
|
9440
|
+
break;
|
|
9441
|
+
}
|
|
9442
|
+
const pipeableTransformations = [];
|
|
9443
|
+
for (let i = firstPipeableIndex; i < flow2.transformations.length; i++) {
|
|
9175
9444
|
const t = flow2.transformations[i];
|
|
9176
|
-
if (t.
|
|
9177
|
-
|
|
9178
|
-
typeParser.pipeableType(t.outType, flow2.node),
|
|
9179
|
-
option
|
|
9180
|
-
);
|
|
9181
|
-
if (isPipeable._tag === "Some") {
|
|
9182
|
-
firstPipeableIndex = i + 1;
|
|
9183
|
-
break;
|
|
9184
|
-
}
|
|
9445
|
+
if (!isSafelyPipeableCallee(t.callee)) {
|
|
9446
|
+
break;
|
|
9185
9447
|
}
|
|
9448
|
+
pipeableTransformations.push(t);
|
|
9186
9449
|
}
|
|
9187
|
-
|
|
9188
|
-
|
|
9189
|
-
|
|
9190
|
-
|
|
9191
|
-
|
|
9192
|
-
|
|
9193
|
-
|
|
9194
|
-
|
|
9195
|
-
|
|
9196
|
-
|
|
9197
|
-
|
|
9198
|
-
|
|
9199
|
-
|
|
9200
|
-
|
|
9201
|
-
|
|
9202
|
-
|
|
9203
|
-
|
|
9204
|
-
|
|
9205
|
-
|
|
9206
|
-
|
|
9207
|
-
|
|
9208
|
-
|
|
9209
|
-
|
|
9210
|
-
|
|
9211
|
-
|
|
9212
|
-
|
|
9450
|
+
const callKindCount = pipeableTransformations.filter((t) => t.kind === "call").length;
|
|
9451
|
+
if (callKindCount >= options.pipeableMinArgCount) {
|
|
9452
|
+
const pipeableEndIndex = firstPipeableIndex + pipeableTransformations.length;
|
|
9453
|
+
const pipeableSubjectNode = firstPipeableIndex === 0 ? flow2.subject.node : typeParser.reconstructPipingFlow({
|
|
9454
|
+
subject: flow2.subject,
|
|
9455
|
+
transformations: flow2.transformations.slice(0, firstPipeableIndex)
|
|
9456
|
+
});
|
|
9457
|
+
const afterTransformations = flow2.transformations.slice(pipeableEndIndex);
|
|
9458
|
+
report({
|
|
9459
|
+
location: flow2.node,
|
|
9460
|
+
messageText: `Nested function calls can be converted to pipeable style for better readability.`,
|
|
9461
|
+
fixes: [{
|
|
9462
|
+
fixName: "missedPipeableOpportunity_fix",
|
|
9463
|
+
description: "Convert to pipe style",
|
|
9464
|
+
apply: gen(function* () {
|
|
9465
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
9466
|
+
const pipeArgs = pipeableTransformations.map((t) => {
|
|
9467
|
+
if (t.args) {
|
|
9468
|
+
return ts.factory.createCallExpression(
|
|
9469
|
+
t.callee,
|
|
9470
|
+
void 0,
|
|
9471
|
+
t.args
|
|
9472
|
+
);
|
|
9473
|
+
} else {
|
|
9474
|
+
return t.callee;
|
|
9475
|
+
}
|
|
9476
|
+
});
|
|
9477
|
+
const pipeNode = ts.factory.createCallExpression(
|
|
9478
|
+
ts.factory.createPropertyAccessExpression(
|
|
9479
|
+
pipeableSubjectNode,
|
|
9480
|
+
"pipe"
|
|
9481
|
+
),
|
|
9213
9482
|
void 0,
|
|
9214
|
-
|
|
9483
|
+
pipeArgs
|
|
9215
9484
|
);
|
|
9216
|
-
|
|
9217
|
-
|
|
9218
|
-
|
|
9219
|
-
|
|
9220
|
-
|
|
9221
|
-
|
|
9222
|
-
|
|
9223
|
-
|
|
9224
|
-
|
|
9225
|
-
|
|
9226
|
-
|
|
9227
|
-
|
|
9228
|
-
changeTracker.replaceNode(sourceFile, flow2.node, newNode);
|
|
9229
|
-
})
|
|
9230
|
-
}]
|
|
9231
|
-
});
|
|
9485
|
+
const newNode = afterTransformations.length > 0 ? typeParser.reconstructPipingFlow({
|
|
9486
|
+
subject: { node: pipeNode, outType: void 0 },
|
|
9487
|
+
transformations: afterTransformations
|
|
9488
|
+
}) : pipeNode;
|
|
9489
|
+
changeTracker.replaceNode(sourceFile, flow2.node, newNode);
|
|
9490
|
+
})
|
|
9491
|
+
}]
|
|
9492
|
+
});
|
|
9493
|
+
break;
|
|
9494
|
+
}
|
|
9495
|
+
searchStartIndex = firstPipeableIndex + pipeableTransformations.length + 1;
|
|
9496
|
+
}
|
|
9232
9497
|
}
|
|
9233
9498
|
})
|
|
9234
9499
|
});
|
|
@@ -10074,6 +10339,90 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
10074
10339
|
})
|
|
10075
10340
|
});
|
|
10076
10341
|
|
|
10342
|
+
// src/diagnostics/preferSchemaOverJson.ts
|
|
10343
|
+
var preferSchemaOverJson = createDiagnostic({
|
|
10344
|
+
name: "preferSchemaOverJson",
|
|
10345
|
+
code: 44,
|
|
10346
|
+
description: "Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify which may throw",
|
|
10347
|
+
severity: "suggestion",
|
|
10348
|
+
apply: fn("preferSchemaOverJson.apply")(function* (sourceFile, report) {
|
|
10349
|
+
const ts = yield* service(TypeScriptApi);
|
|
10350
|
+
const typeParser = yield* service(TypeParser);
|
|
10351
|
+
const parseJsonMethod = (node) => gen(function* () {
|
|
10352
|
+
if (!ts.isCallExpression(node)) return yield* fail3("node is not a call expression");
|
|
10353
|
+
const expression = node.expression;
|
|
10354
|
+
if (!ts.isPropertyAccessExpression(expression)) return yield* fail3("expression is not a property access");
|
|
10355
|
+
const objectExpr = expression.expression;
|
|
10356
|
+
const methodName = ts.idText(expression.name);
|
|
10357
|
+
if (!ts.isIdentifier(objectExpr) || ts.idText(objectExpr) !== "JSON") {
|
|
10358
|
+
return yield* fail3("object is not JSON");
|
|
10359
|
+
}
|
|
10360
|
+
if (methodName !== "parse" && methodName !== "stringify") {
|
|
10361
|
+
return yield* fail3("method is not parse or stringify");
|
|
10362
|
+
}
|
|
10363
|
+
return { node, methodName };
|
|
10364
|
+
});
|
|
10365
|
+
const effectTrySimple = (node) => gen(function* () {
|
|
10366
|
+
if (!ts.isCallExpression(node)) return yield* fail3("node is not a call expression");
|
|
10367
|
+
yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
|
|
10368
|
+
if (node.arguments.length === 0) return yield* fail3("Effect.try has no arguments");
|
|
10369
|
+
const lazyFn = yield* typeParser.lazyExpression(node.arguments[0]);
|
|
10370
|
+
const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
|
|
10371
|
+
return { node: jsonMethod.node, methodName: jsonMethod.methodName };
|
|
10372
|
+
});
|
|
10373
|
+
const effectTryObject = (node) => gen(function* () {
|
|
10374
|
+
if (!ts.isCallExpression(node)) return yield* fail3("node is not a call expression");
|
|
10375
|
+
yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
|
|
10376
|
+
if (node.arguments.length === 0) return yield* fail3("Effect.try has no arguments");
|
|
10377
|
+
const arg = node.arguments[0];
|
|
10378
|
+
if (!ts.isObjectLiteralExpression(arg)) return yield* fail3("argument is not an object literal");
|
|
10379
|
+
const tryProp = arg.properties.find(
|
|
10380
|
+
(p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && ts.idText(p.name) === "try"
|
|
10381
|
+
);
|
|
10382
|
+
if (!tryProp) return yield* fail3("object has no 'try' property");
|
|
10383
|
+
const lazyFn = yield* typeParser.lazyExpression(tryProp.initializer);
|
|
10384
|
+
const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
|
|
10385
|
+
return { node: jsonMethod.node, methodName: jsonMethod.methodName };
|
|
10386
|
+
});
|
|
10387
|
+
const jsonMethodInEffectGen = (node) => gen(function* () {
|
|
10388
|
+
const jsonMethod = yield* parseJsonMethod(node);
|
|
10389
|
+
const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
|
|
10390
|
+
if (!effectGen || effectGen.body.statements.length === 0) {
|
|
10391
|
+
return yield* fail3("not inside an Effect generator");
|
|
10392
|
+
}
|
|
10393
|
+
if (scopeNode && scopeNode !== effectGen.generatorFunction) {
|
|
10394
|
+
return yield* fail3("inside a nested function scope");
|
|
10395
|
+
}
|
|
10396
|
+
return { node: jsonMethod.node, methodName: jsonMethod.methodName };
|
|
10397
|
+
});
|
|
10398
|
+
const nodeToVisit = [];
|
|
10399
|
+
const appendNodeToVisit = (node) => {
|
|
10400
|
+
nodeToVisit.push(node);
|
|
10401
|
+
return void 0;
|
|
10402
|
+
};
|
|
10403
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
10404
|
+
while (nodeToVisit.length > 0) {
|
|
10405
|
+
const node = nodeToVisit.shift();
|
|
10406
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
10407
|
+
const match3 = yield* pipe(
|
|
10408
|
+
firstSuccessOf([
|
|
10409
|
+
effectTrySimple(node),
|
|
10410
|
+
effectTryObject(node),
|
|
10411
|
+
jsonMethodInEffectGen(node)
|
|
10412
|
+
]),
|
|
10413
|
+
option
|
|
10414
|
+
);
|
|
10415
|
+
if (isSome2(match3)) {
|
|
10416
|
+
report({
|
|
10417
|
+
location: match3.value.node,
|
|
10418
|
+
messageText: "Consider using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify",
|
|
10419
|
+
fixes: []
|
|
10420
|
+
});
|
|
10421
|
+
}
|
|
10422
|
+
}
|
|
10423
|
+
})
|
|
10424
|
+
});
|
|
10425
|
+
|
|
10077
10426
|
// src/diagnostics/redundantSchemaTagIdentifier.ts
|
|
10078
10427
|
var redundantSchemaTagIdentifier = createDiagnostic({
|
|
10079
10428
|
name: "redundantSchemaTagIdentifier",
|
|
@@ -10226,108 +10575,91 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
10226
10575
|
option
|
|
10227
10576
|
);
|
|
10228
10577
|
if (isNone2(isEffectRunCall)) continue;
|
|
10229
|
-
|
|
10230
|
-
|
|
10231
|
-
|
|
10232
|
-
|
|
10233
|
-
|
|
10234
|
-
if (ts.isFunctionExpression(possiblyEffectGen) || ts.isFunctionDeclaration(possiblyEffectGen) || ts.isMethodDeclaration(possiblyEffectGen) || ts.isArrowFunction(possiblyEffectGen)) {
|
|
10235
|
-
nodeIntroduceScope = possiblyEffectGen;
|
|
10236
|
-
continue;
|
|
10237
|
-
}
|
|
10238
|
-
}
|
|
10239
|
-
const isInEffectGen = yield* pipe(
|
|
10240
|
-
typeParser.effectGen(possiblyEffectGen),
|
|
10241
|
-
orElse2(() => typeParser.effectFnUntracedGen(possiblyEffectGen)),
|
|
10242
|
-
orElse2(() => typeParser.effectFnGen(possiblyEffectGen)),
|
|
10243
|
-
option
|
|
10578
|
+
const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
|
|
10579
|
+
if (effectGen && effectGen.body.statements.length > 0) {
|
|
10580
|
+
const nodeText = sourceFile.text.substring(
|
|
10581
|
+
ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
10582
|
+
node.expression.end
|
|
10244
10583
|
);
|
|
10245
|
-
if (
|
|
10246
|
-
const
|
|
10247
|
-
|
|
10248
|
-
|
|
10249
|
-
|
|
10250
|
-
|
|
10251
|
-
const
|
|
10252
|
-
|
|
10253
|
-
|
|
10254
|
-
|
|
10255
|
-
|
|
10256
|
-
|
|
10257
|
-
|
|
10258
|
-
|
|
10259
|
-
|
|
10260
|
-
|
|
10261
|
-
if (ts.
|
|
10262
|
-
|
|
10263
|
-
typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
|
|
10264
|
-
option
|
|
10265
|
-
);
|
|
10266
|
-
if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
|
|
10267
|
-
runtimeIdentifier = ts.idText(declaration.name);
|
|
10268
|
-
}
|
|
10584
|
+
if (scopeNode && scopeNode !== effectGen.generatorFunction) {
|
|
10585
|
+
const fixAddRuntime = gen(function* () {
|
|
10586
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
10587
|
+
const runtimeModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Runtime") || "Runtime";
|
|
10588
|
+
const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Effect") || "Effect";
|
|
10589
|
+
let runtimeIdentifier = void 0;
|
|
10590
|
+
for (const statement of effectGen.generatorFunction.body.statements) {
|
|
10591
|
+
if (ts.isVariableStatement(statement) && statement.declarationList.declarations.length === 1) {
|
|
10592
|
+
const declaration = statement.declarationList.declarations[0];
|
|
10593
|
+
if (declaration.initializer && ts.isYieldExpression(declaration.initializer) && declaration.initializer.asteriskToken && declaration.initializer.expression) {
|
|
10594
|
+
const yieldedExpression = declaration.initializer.expression;
|
|
10595
|
+
if (ts.isCallExpression(yieldedExpression)) {
|
|
10596
|
+
const maybeEffectRuntime = yield* pipe(
|
|
10597
|
+
typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
|
|
10598
|
+
option
|
|
10599
|
+
);
|
|
10600
|
+
if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
|
|
10601
|
+
runtimeIdentifier = ts.idText(declaration.name);
|
|
10269
10602
|
}
|
|
10270
10603
|
}
|
|
10271
10604
|
}
|
|
10272
10605
|
}
|
|
10273
|
-
|
|
10274
|
-
|
|
10275
|
-
|
|
10276
|
-
|
|
10277
|
-
|
|
10606
|
+
}
|
|
10607
|
+
if (!runtimeIdentifier) {
|
|
10608
|
+
changeTracker.insertNodeAt(
|
|
10609
|
+
sourceFile,
|
|
10610
|
+
effectGen.body.statements[0].pos,
|
|
10611
|
+
ts.factory.createVariableStatement(
|
|
10612
|
+
void 0,
|
|
10613
|
+
ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(
|
|
10614
|
+
"effectRuntime",
|
|
10278
10615
|
void 0,
|
|
10279
|
-
|
|
10280
|
-
|
|
10281
|
-
|
|
10282
|
-
|
|
10283
|
-
|
|
10284
|
-
|
|
10285
|
-
|
|
10286
|
-
|
|
10287
|
-
|
|
10288
|
-
|
|
10289
|
-
),
|
|
10290
|
-
[ts.factory.createTypeReferenceNode("never")],
|
|
10291
|
-
[]
|
|
10292
|
-
)
|
|
10616
|
+
void 0,
|
|
10617
|
+
ts.factory.createYieldExpression(
|
|
10618
|
+
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
10619
|
+
ts.factory.createCallExpression(
|
|
10620
|
+
ts.factory.createPropertyAccessExpression(
|
|
10621
|
+
ts.factory.createIdentifier(effectModuleIdentifier),
|
|
10622
|
+
"runtime"
|
|
10623
|
+
),
|
|
10624
|
+
[ts.factory.createTypeReferenceNode("never")],
|
|
10625
|
+
[]
|
|
10293
10626
|
)
|
|
10294
|
-
)
|
|
10295
|
-
),
|
|
10296
|
-
|
|
10297
|
-
|
|
10298
|
-
|
|
10299
|
-
|
|
10300
|
-
|
|
10301
|
-
}
|
|
10302
|
-
changeTracker.deleteRange(sourceFile, {
|
|
10303
|
-
pos: ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
10304
|
-
end: node.arguments[0].pos
|
|
10305
|
-
});
|
|
10306
|
-
changeTracker.insertText(
|
|
10307
|
-
sourceFile,
|
|
10308
|
-
node.arguments[0].pos,
|
|
10309
|
-
`${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
|
|
10627
|
+
)
|
|
10628
|
+
)], ts.NodeFlags.Const)
|
|
10629
|
+
),
|
|
10630
|
+
{
|
|
10631
|
+
prefix: "\n",
|
|
10632
|
+
suffix: "\n"
|
|
10633
|
+
}
|
|
10310
10634
|
);
|
|
10635
|
+
}
|
|
10636
|
+
changeTracker.deleteRange(sourceFile, {
|
|
10637
|
+
pos: ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
10638
|
+
end: node.arguments[0].pos
|
|
10311
10639
|
});
|
|
10312
|
-
|
|
10313
|
-
|
|
10314
|
-
|
|
10640
|
+
changeTracker.insertText(
|
|
10641
|
+
sourceFile,
|
|
10642
|
+
node.arguments[0].pos,
|
|
10643
|
+
`${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
|
|
10644
|
+
);
|
|
10645
|
+
});
|
|
10646
|
+
report({
|
|
10647
|
+
location: node.expression,
|
|
10648
|
+
messageText: `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
|
|
10315
10649
|
Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`,
|
|
10316
|
-
|
|
10317
|
-
|
|
10318
|
-
|
|
10319
|
-
|
|
10320
|
-
|
|
10321
|
-
|
|
10322
|
-
|
|
10323
|
-
|
|
10324
|
-
|
|
10325
|
-
|
|
10326
|
-
|
|
10327
|
-
|
|
10328
|
-
}
|
|
10650
|
+
fixes: [{
|
|
10651
|
+
fixName: "runEffectInsideEffect_fix",
|
|
10652
|
+
description: "Use a runtime to run the Effect",
|
|
10653
|
+
apply: fixAddRuntime
|
|
10654
|
+
}]
|
|
10655
|
+
});
|
|
10656
|
+
} else {
|
|
10657
|
+
report({
|
|
10658
|
+
location: node.expression,
|
|
10659
|
+
messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
|
|
10660
|
+
fixes: []
|
|
10661
|
+
});
|
|
10329
10662
|
}
|
|
10330
|
-
currentParent = currentParent.parent;
|
|
10331
10663
|
}
|
|
10332
10664
|
}
|
|
10333
10665
|
})
|
|
@@ -10413,6 +10745,59 @@ var schemaStructWithTag = createDiagnostic({
|
|
|
10413
10745
|
})
|
|
10414
10746
|
});
|
|
10415
10747
|
|
|
10748
|
+
// src/diagnostics/schemaSyncInEffect.ts
|
|
10749
|
+
var syncToEffectMethod = {
|
|
10750
|
+
decodeSync: "decode",
|
|
10751
|
+
decodeUnknownSync: "decodeUnknown",
|
|
10752
|
+
encodeSync: "encode",
|
|
10753
|
+
encodeUnknownSync: "encodeUnknown"
|
|
10754
|
+
};
|
|
10755
|
+
var schemaSyncInEffect = createDiagnostic({
|
|
10756
|
+
name: "schemaSyncInEffect",
|
|
10757
|
+
code: 43,
|
|
10758
|
+
description: "Suggests using Effect-based Schema methods instead of sync methods inside Effect generators",
|
|
10759
|
+
severity: "suggestion",
|
|
10760
|
+
apply: fn("schemaSyncInEffect.apply")(function* (sourceFile, report) {
|
|
10761
|
+
const ts = yield* service(TypeScriptApi);
|
|
10762
|
+
const typeParser = yield* service(TypeParser);
|
|
10763
|
+
const parseSchemaSyncMethod = (node, methodName) => pipe(
|
|
10764
|
+
typeParser.isNodeReferenceToEffectParseResultModuleApi(methodName)(node),
|
|
10765
|
+
map8(() => ({ node, methodName }))
|
|
10766
|
+
);
|
|
10767
|
+
const nodeToVisit = [];
|
|
10768
|
+
const appendNodeToVisit = (node) => {
|
|
10769
|
+
nodeToVisit.push(node);
|
|
10770
|
+
return void 0;
|
|
10771
|
+
};
|
|
10772
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
10773
|
+
while (nodeToVisit.length > 0) {
|
|
10774
|
+
const node = nodeToVisit.shift();
|
|
10775
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
10776
|
+
if (!ts.isCallExpression(node)) continue;
|
|
10777
|
+
const isSchemaSyncCall = yield* pipe(
|
|
10778
|
+
firstSuccessOf(
|
|
10779
|
+
Object.keys(syncToEffectMethod).map((methodName) => parseSchemaSyncMethod(node.expression, methodName))
|
|
10780
|
+
),
|
|
10781
|
+
option
|
|
10782
|
+
);
|
|
10783
|
+
if (isNone2(isSchemaSyncCall)) continue;
|
|
10784
|
+
const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
|
|
10785
|
+
if (!effectGen || effectGen.body.statements.length === 0) continue;
|
|
10786
|
+
if (scopeNode && scopeNode !== effectGen.generatorFunction) continue;
|
|
10787
|
+
const nodeText = sourceFile.text.substring(
|
|
10788
|
+
ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
10789
|
+
node.expression.end
|
|
10790
|
+
);
|
|
10791
|
+
const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
|
|
10792
|
+
report({
|
|
10793
|
+
location: node.expression,
|
|
10794
|
+
messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed ParseError in the error channel.`,
|
|
10795
|
+
fixes: []
|
|
10796
|
+
});
|
|
10797
|
+
}
|
|
10798
|
+
})
|
|
10799
|
+
});
|
|
10800
|
+
|
|
10416
10801
|
// src/diagnostics/schemaUnionOfLiterals.ts
|
|
10417
10802
|
var schemaUnionOfLiterals = createDiagnostic({
|
|
10418
10803
|
name: "schemaUnionOfLiterals",
|
|
@@ -11127,7 +11512,9 @@ var diagnostics = [
|
|
|
11127
11512
|
layerMergeAllWithDependencies,
|
|
11128
11513
|
effectMapVoid,
|
|
11129
11514
|
effectFnOpportunity,
|
|
11130
|
-
redundantSchemaTagIdentifier
|
|
11515
|
+
redundantSchemaTagIdentifier,
|
|
11516
|
+
schemaSyncInEffect,
|
|
11517
|
+
preferSchemaOverJson
|
|
11131
11518
|
];
|
|
11132
11519
|
|
|
11133
11520
|
// src/completions/effectDiagnosticsComment.ts
|