@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/transform.js
CHANGED
|
@@ -3091,6 +3091,97 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3091
3091
|
"TypeParser.effectFnGen",
|
|
3092
3092
|
(node) => node
|
|
3093
3093
|
);
|
|
3094
|
+
const findEnclosingScopes = fn("TypeParser.findEnclosingScopes")(function* (startNode) {
|
|
3095
|
+
let currentParent = startNode.parent;
|
|
3096
|
+
let scopeNode = void 0;
|
|
3097
|
+
let effectGenResult = void 0;
|
|
3098
|
+
while (currentParent) {
|
|
3099
|
+
const nodeToCheck = currentParent;
|
|
3100
|
+
if (!scopeNode) {
|
|
3101
|
+
if (ts.isFunctionExpression(nodeToCheck) || ts.isFunctionDeclaration(nodeToCheck) || ts.isMethodDeclaration(nodeToCheck) || ts.isArrowFunction(nodeToCheck) || ts.isGetAccessorDeclaration(nodeToCheck) || ts.isSetAccessorDeclaration(nodeToCheck)) {
|
|
3102
|
+
scopeNode = nodeToCheck;
|
|
3103
|
+
}
|
|
3104
|
+
}
|
|
3105
|
+
if (!effectGenResult) {
|
|
3106
|
+
const isEffectGen = yield* pipe(
|
|
3107
|
+
effectGen(nodeToCheck),
|
|
3108
|
+
map4((result) => ({
|
|
3109
|
+
node: result.node,
|
|
3110
|
+
effectModule: result.effectModule,
|
|
3111
|
+
generatorFunction: result.generatorFunction,
|
|
3112
|
+
body: result.body
|
|
3113
|
+
})),
|
|
3114
|
+
orElse2(
|
|
3115
|
+
() => pipe(
|
|
3116
|
+
effectFnUntracedGen(nodeToCheck),
|
|
3117
|
+
map4((result) => ({
|
|
3118
|
+
node: result.node,
|
|
3119
|
+
effectModule: result.effectModule,
|
|
3120
|
+
generatorFunction: result.generatorFunction,
|
|
3121
|
+
body: result.body,
|
|
3122
|
+
pipeArguments: result.pipeArguments
|
|
3123
|
+
}))
|
|
3124
|
+
)
|
|
3125
|
+
),
|
|
3126
|
+
orElse2(
|
|
3127
|
+
() => pipe(
|
|
3128
|
+
effectFnGen(nodeToCheck),
|
|
3129
|
+
map4((result) => ({
|
|
3130
|
+
node: result.node,
|
|
3131
|
+
effectModule: result.effectModule,
|
|
3132
|
+
generatorFunction: result.generatorFunction,
|
|
3133
|
+
body: result.body,
|
|
3134
|
+
pipeArguments: result.pipeArguments
|
|
3135
|
+
}))
|
|
3136
|
+
)
|
|
3137
|
+
),
|
|
3138
|
+
option
|
|
3139
|
+
);
|
|
3140
|
+
if (isSome2(isEffectGen)) {
|
|
3141
|
+
effectGenResult = isEffectGen.value;
|
|
3142
|
+
}
|
|
3143
|
+
}
|
|
3144
|
+
if (scopeNode && effectGenResult) {
|
|
3145
|
+
break;
|
|
3146
|
+
}
|
|
3147
|
+
currentParent = nodeToCheck.parent;
|
|
3148
|
+
}
|
|
3149
|
+
return { scopeNode, effectGen: effectGenResult };
|
|
3150
|
+
});
|
|
3151
|
+
const effectFn = cachedBy(
|
|
3152
|
+
function(node) {
|
|
3153
|
+
if (!ts.isCallExpression(node)) {
|
|
3154
|
+
return typeParserIssue("Node is not a call expression", void 0, node);
|
|
3155
|
+
}
|
|
3156
|
+
if (node.arguments.length === 0) {
|
|
3157
|
+
return typeParserIssue("Node has no arguments", void 0, node);
|
|
3158
|
+
}
|
|
3159
|
+
const regularFunction = node.arguments[0];
|
|
3160
|
+
if (!ts.isFunctionExpression(regularFunction) && !ts.isArrowFunction(regularFunction)) {
|
|
3161
|
+
return typeParserIssue("Node is not a function expression or arrow function", void 0, node);
|
|
3162
|
+
}
|
|
3163
|
+
if (ts.isFunctionExpression(regularFunction) && regularFunction.asteriskToken !== void 0) {
|
|
3164
|
+
return typeParserIssue("Node is a generator function, not a regular function", void 0, node);
|
|
3165
|
+
}
|
|
3166
|
+
const expressionToTest = ts.isCallExpression(node.expression) ? node.expression.expression : node.expression;
|
|
3167
|
+
if (!ts.isPropertyAccessExpression(expressionToTest)) {
|
|
3168
|
+
return typeParserIssue("Node is not a property access expression", void 0, node);
|
|
3169
|
+
}
|
|
3170
|
+
const propertyAccess = expressionToTest;
|
|
3171
|
+
const pipeArguments2 = node.arguments.slice(1);
|
|
3172
|
+
return pipe(
|
|
3173
|
+
isNodeReferenceToEffectModuleApi("fn")(propertyAccess),
|
|
3174
|
+
map4(() => ({
|
|
3175
|
+
node,
|
|
3176
|
+
effectModule: propertyAccess.expression,
|
|
3177
|
+
regularFunction,
|
|
3178
|
+
pipeArguments: pipeArguments2
|
|
3179
|
+
}))
|
|
3180
|
+
);
|
|
3181
|
+
},
|
|
3182
|
+
"TypeParser.effectFn",
|
|
3183
|
+
(node) => node
|
|
3184
|
+
);
|
|
3094
3185
|
const unnecessaryEffectGen2 = cachedBy(
|
|
3095
3186
|
fn("TypeParser.unnecessaryEffectGen")(function* (node) {
|
|
3096
3187
|
const { body } = yield* effectGen(node);
|
|
@@ -3202,6 +3293,28 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3202
3293
|
`TypeParser.isNodeReferenceToEffectSchemaModuleApi(${memberName})`,
|
|
3203
3294
|
(node) => node
|
|
3204
3295
|
);
|
|
3296
|
+
const isEffectParseResultSourceFile = cachedBy(
|
|
3297
|
+
fn("TypeParser.isEffectParseResultSourceFile")(function* (sourceFile) {
|
|
3298
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
3299
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
3300
|
+
const parseIssueSymbol = typeChecker.tryGetMemberInModuleExports("ParseIssue", moduleSymbol);
|
|
3301
|
+
if (!parseIssueSymbol) return yield* typeParserIssue("ParseIssue type not found", void 0, sourceFile);
|
|
3302
|
+
const decodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("decodeSync", moduleSymbol);
|
|
3303
|
+
if (!decodeSyncSymbol) return yield* typeParserIssue("decodeSync not found", void 0, sourceFile);
|
|
3304
|
+
const encodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("encodeSync", moduleSymbol);
|
|
3305
|
+
if (!encodeSyncSymbol) return yield* typeParserIssue("encodeSync not found", void 0, sourceFile);
|
|
3306
|
+
return sourceFile;
|
|
3307
|
+
}),
|
|
3308
|
+
"TypeParser.isEffectParseResultSourceFile",
|
|
3309
|
+
(sourceFile) => sourceFile
|
|
3310
|
+
);
|
|
3311
|
+
const isNodeReferenceToEffectParseResultModuleApi = (memberName) => cachedBy(
|
|
3312
|
+
fn("TypeParser.isNodeReferenceToEffectParseResultModuleApi")(function* (node) {
|
|
3313
|
+
return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectParseResultSourceFile, memberName);
|
|
3314
|
+
}),
|
|
3315
|
+
`TypeParser.isNodeReferenceToEffectParseResultModuleApi(${memberName})`,
|
|
3316
|
+
(node) => node
|
|
3317
|
+
);
|
|
3205
3318
|
const contextTagVarianceStruct = (type, atLocation) => map4(
|
|
3206
3319
|
all(
|
|
3207
3320
|
varianceStructInvariantType(type, atLocation, "_Identifier"),
|
|
@@ -3982,11 +4095,65 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
3982
4095
|
if (includeEffectFn) {
|
|
3983
4096
|
const effectFnGenParsed = yield* pipe(effectFnGen(node), option);
|
|
3984
4097
|
const effectFnUntracedGenParsed = isNone2(effectFnGenParsed) ? yield* pipe(effectFnUntracedGen(node), option) : none2();
|
|
3985
|
-
const
|
|
3986
|
-
const
|
|
3987
|
-
const
|
|
3988
|
-
|
|
3989
|
-
|
|
4098
|
+
const effectFnNonGenParsed = isNone2(effectFnGenParsed) && isNone2(effectFnUntracedGenParsed) ? yield* pipe(effectFn(node), option) : none2();
|
|
4099
|
+
const isEffectFnGen = isSome2(effectFnGenParsed);
|
|
4100
|
+
const isEffectFnUntracedGen = isSome2(effectFnUntracedGenParsed);
|
|
4101
|
+
const isEffectFnNonGen = isSome2(effectFnNonGenParsed);
|
|
4102
|
+
const transformationKind = isEffectFnUntracedGen ? "effectFnUntraced" : "effectFn";
|
|
4103
|
+
if (isEffectFnGen || isEffectFnUntracedGen) {
|
|
4104
|
+
const effectFnParsed = isEffectFnGen ? effectFnGenParsed : effectFnUntracedGenParsed;
|
|
4105
|
+
if (isSome2(effectFnParsed) && effectFnParsed.value.pipeArguments.length > 0) {
|
|
4106
|
+
const fnResult = effectFnParsed.value;
|
|
4107
|
+
const pipeArgs = fnResult.pipeArguments;
|
|
4108
|
+
const transformations = [];
|
|
4109
|
+
let subjectType;
|
|
4110
|
+
for (let i = 0; i < pipeArgs.length; i++) {
|
|
4111
|
+
const arg = pipeArgs[i];
|
|
4112
|
+
const contextualType = typeChecker.getContextualType(arg);
|
|
4113
|
+
const callSigs = contextualType ? typeChecker.getSignaturesOfType(contextualType, ts.SignatureKind.Call) : [];
|
|
4114
|
+
const outType = callSigs.length > 0 ? typeChecker.getReturnTypeOfSignature(callSigs[0]) : void 0;
|
|
4115
|
+
if (i === 0 && callSigs.length > 0) {
|
|
4116
|
+
const params = callSigs[0].parameters;
|
|
4117
|
+
if (params.length > 0) {
|
|
4118
|
+
subjectType = typeChecker.getTypeOfSymbol(params[0]);
|
|
4119
|
+
}
|
|
4120
|
+
}
|
|
4121
|
+
if (ts.isCallExpression(arg)) {
|
|
4122
|
+
transformations.push({
|
|
4123
|
+
callee: arg.expression,
|
|
4124
|
+
args: Array.from(arg.arguments),
|
|
4125
|
+
outType,
|
|
4126
|
+
kind: transformationKind
|
|
4127
|
+
});
|
|
4128
|
+
} else {
|
|
4129
|
+
transformations.push({
|
|
4130
|
+
callee: arg,
|
|
4131
|
+
args: void 0,
|
|
4132
|
+
outType,
|
|
4133
|
+
kind: transformationKind
|
|
4134
|
+
});
|
|
4135
|
+
}
|
|
4136
|
+
}
|
|
4137
|
+
const newFlow = {
|
|
4138
|
+
node,
|
|
4139
|
+
subject: {
|
|
4140
|
+
node,
|
|
4141
|
+
outType: subjectType
|
|
4142
|
+
},
|
|
4143
|
+
transformations
|
|
4144
|
+
};
|
|
4145
|
+
result.push(newFlow);
|
|
4146
|
+
workQueue.push([fnResult.body, void 0]);
|
|
4147
|
+
for (const arg of pipeArgs) {
|
|
4148
|
+
ts.forEachChild(arg, (c) => {
|
|
4149
|
+
workQueue.push([c, void 0]);
|
|
4150
|
+
});
|
|
4151
|
+
}
|
|
4152
|
+
continue;
|
|
4153
|
+
}
|
|
4154
|
+
}
|
|
4155
|
+
if (isEffectFnNonGen && isSome2(effectFnNonGenParsed) && effectFnNonGenParsed.value.pipeArguments.length > 0) {
|
|
4156
|
+
const fnResult = effectFnNonGenParsed.value;
|
|
3990
4157
|
const pipeArgs = fnResult.pipeArguments;
|
|
3991
4158
|
const transformations = [];
|
|
3992
4159
|
let subjectType;
|
|
@@ -4006,14 +4173,14 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
4006
4173
|
callee: arg.expression,
|
|
4007
4174
|
args: Array.from(arg.arguments),
|
|
4008
4175
|
outType,
|
|
4009
|
-
kind:
|
|
4176
|
+
kind: "effectFn"
|
|
4010
4177
|
});
|
|
4011
4178
|
} else {
|
|
4012
4179
|
transformations.push({
|
|
4013
4180
|
callee: arg,
|
|
4014
4181
|
args: void 0,
|
|
4015
4182
|
outType,
|
|
4016
|
-
kind:
|
|
4183
|
+
kind: "effectFn"
|
|
4017
4184
|
});
|
|
4018
4185
|
}
|
|
4019
4186
|
}
|
|
@@ -4026,7 +4193,16 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
4026
4193
|
transformations
|
|
4027
4194
|
};
|
|
4028
4195
|
result.push(newFlow);
|
|
4029
|
-
|
|
4196
|
+
const regularFn = fnResult.regularFunction;
|
|
4197
|
+
if (ts.isArrowFunction(regularFn)) {
|
|
4198
|
+
if (ts.isBlock(regularFn.body)) {
|
|
4199
|
+
workQueue.push([regularFn.body, void 0]);
|
|
4200
|
+
} else {
|
|
4201
|
+
workQueue.push([regularFn.body, void 0]);
|
|
4202
|
+
}
|
|
4203
|
+
} else if (regularFn.body) {
|
|
4204
|
+
workQueue.push([regularFn.body, void 0]);
|
|
4205
|
+
}
|
|
4030
4206
|
for (const arg of pipeArgs) {
|
|
4031
4207
|
ts.forEachChild(arg, (c) => {
|
|
4032
4208
|
workQueue.push([c, void 0]);
|
|
@@ -4089,6 +4265,7 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
4089
4265
|
return {
|
|
4090
4266
|
isNodeReferenceToEffectModuleApi,
|
|
4091
4267
|
isNodeReferenceToEffectSchemaModuleApi,
|
|
4268
|
+
isNodeReferenceToEffectParseResultModuleApi,
|
|
4092
4269
|
isNodeReferenceToEffectDataModuleApi,
|
|
4093
4270
|
isNodeReferenceToEffectContextModuleApi,
|
|
4094
4271
|
isNodeReferenceToEffectSqlModelModuleApi,
|
|
@@ -4102,6 +4279,8 @@ function make2(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
4102
4279
|
effectGen,
|
|
4103
4280
|
effectFnUntracedGen,
|
|
4104
4281
|
effectFnGen,
|
|
4282
|
+
findEnclosingScopes,
|
|
4283
|
+
effectFn,
|
|
4105
4284
|
extendsCauseYieldableError,
|
|
4106
4285
|
unnecessaryEffectGen: unnecessaryEffectGen2,
|
|
4107
4286
|
effectSchemaType,
|
|
@@ -4673,106 +4852,184 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
|
|
|
4673
4852
|
});
|
|
4674
4853
|
|
|
4675
4854
|
// src/diagnostics/effectFnOpportunity.ts
|
|
4676
|
-
var parseEffectFnOpportunityTarget = (node, sourceFile) => gen(function* () {
|
|
4677
|
-
const ts = yield* service(TypeScriptApi);
|
|
4678
|
-
const typeChecker = yield* service(TypeCheckerApi);
|
|
4679
|
-
const typeParser = yield* service(TypeParser);
|
|
4680
|
-
const tsUtils = yield* service(TypeScriptUtils);
|
|
4681
|
-
if (!ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isFunctionDeclaration(node)) {
|
|
4682
|
-
return yield* TypeParserIssue.issue;
|
|
4683
|
-
}
|
|
4684
|
-
if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.asteriskToken) {
|
|
4685
|
-
return yield* TypeParserIssue.issue;
|
|
4686
|
-
}
|
|
4687
|
-
if (ts.isFunctionExpression(node) && node.name) {
|
|
4688
|
-
return yield* TypeParserIssue.issue;
|
|
4689
|
-
}
|
|
4690
|
-
let bodyExpression;
|
|
4691
|
-
if (ts.isArrowFunction(node)) {
|
|
4692
|
-
if (ts.isBlock(node.body)) {
|
|
4693
|
-
const returnStatement = findSingleReturnStatement(ts, node.body);
|
|
4694
|
-
if (returnStatement?.expression) {
|
|
4695
|
-
bodyExpression = returnStatement.expression;
|
|
4696
|
-
}
|
|
4697
|
-
} else {
|
|
4698
|
-
bodyExpression = node.body;
|
|
4699
|
-
}
|
|
4700
|
-
} else if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.body) {
|
|
4701
|
-
const returnStatement = findSingleReturnStatement(ts, node.body);
|
|
4702
|
-
if (returnStatement?.expression) {
|
|
4703
|
-
bodyExpression = returnStatement.expression;
|
|
4704
|
-
}
|
|
4705
|
-
}
|
|
4706
|
-
if (!bodyExpression) return yield* TypeParserIssue.issue;
|
|
4707
|
-
const { pipeArguments: pipeArguments2, subject } = yield* pipe(
|
|
4708
|
-
typeParser.pipeCall(bodyExpression),
|
|
4709
|
-
map4(({ args: args2, subject: subject2 }) => ({ subject: subject2, pipeArguments: args2 })),
|
|
4710
|
-
orElse2(() => succeed({ subject: bodyExpression, pipeArguments: [] }))
|
|
4711
|
-
);
|
|
4712
|
-
const { effectModule, generatorFunction } = yield* typeParser.effectGen(subject);
|
|
4713
|
-
const functionType = typeChecker.getTypeAtLocation(node);
|
|
4714
|
-
if (!functionType) return yield* TypeParserIssue.issue;
|
|
4715
|
-
const callSignatures = typeChecker.getSignaturesOfType(functionType, ts.SignatureKind.Call);
|
|
4716
|
-
if (callSignatures.length !== 1) return yield* TypeParserIssue.issue;
|
|
4717
|
-
const signature = callSignatures[0];
|
|
4718
|
-
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
4719
|
-
const { A, E, R } = yield* typeParser.strictEffectType(returnType, node);
|
|
4720
|
-
const effectModuleName = ts.isIdentifier(effectModule) ? ts.idText(effectModule) : tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
4721
|
-
sourceFile,
|
|
4722
|
-
"effect",
|
|
4723
|
-
"Effect"
|
|
4724
|
-
) || "Effect";
|
|
4725
|
-
const nameIdentifier = getNameIdentifier(ts, node);
|
|
4726
|
-
const traceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
|
|
4727
|
-
const hasReturnTypeAnnotation = !!node.type;
|
|
4728
|
-
return {
|
|
4729
|
-
node,
|
|
4730
|
-
nameIdentifier,
|
|
4731
|
-
effectModule,
|
|
4732
|
-
generatorFunction,
|
|
4733
|
-
effectModuleName,
|
|
4734
|
-
traceName,
|
|
4735
|
-
hasReturnTypeAnnotation,
|
|
4736
|
-
effectTypes: { A, E, R },
|
|
4737
|
-
pipeArguments: pipeArguments2
|
|
4738
|
-
};
|
|
4739
|
-
});
|
|
4740
4855
|
var effectFnOpportunity = createDiagnostic({
|
|
4741
4856
|
name: "effectFnOpportunity",
|
|
4742
4857
|
code: 41,
|
|
4743
|
-
description: "Suggests using Effect.fn for functions that
|
|
4858
|
+
description: "Suggests using Effect.fn for functions that returns an Effect",
|
|
4744
4859
|
severity: "suggestion",
|
|
4745
4860
|
apply: fn("effectFnOpportunity.apply")(function* (sourceFile, report) {
|
|
4746
4861
|
const ts = yield* service(TypeScriptApi);
|
|
4747
4862
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
4863
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4864
|
+
const typeParser = yield* service(TypeParser);
|
|
4748
4865
|
const tsUtils = yield* service(TypeScriptUtils);
|
|
4749
|
-
const
|
|
4750
|
-
|
|
4751
|
-
|
|
4752
|
-
|
|
4753
|
-
|
|
4754
|
-
|
|
4755
|
-
|
|
4756
|
-
|
|
4757
|
-
|
|
4758
|
-
|
|
4759
|
-
|
|
4760
|
-
|
|
4761
|
-
|
|
4762
|
-
)
|
|
4763
|
-
|
|
4866
|
+
const sourceEffectModuleName = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
4867
|
+
sourceFile,
|
|
4868
|
+
"effect",
|
|
4869
|
+
"Effect"
|
|
4870
|
+
) || "Effect";
|
|
4871
|
+
const findSingleReturnStatement = (block) => {
|
|
4872
|
+
if (block.statements.length !== 1) return void 0;
|
|
4873
|
+
const statement = block.statements[0];
|
|
4874
|
+
if (!ts.isReturnStatement(statement)) return void 0;
|
|
4875
|
+
return statement;
|
|
4876
|
+
};
|
|
4877
|
+
const getBodyExpression = (fnNode) => {
|
|
4878
|
+
if (ts.isArrowFunction(fnNode)) {
|
|
4879
|
+
if (ts.isBlock(fnNode.body)) {
|
|
4880
|
+
return findSingleReturnStatement(fnNode.body)?.expression;
|
|
4881
|
+
}
|
|
4882
|
+
return fnNode.body;
|
|
4883
|
+
} else if ((ts.isFunctionExpression(fnNode) || ts.isFunctionDeclaration(fnNode)) && fnNode.body) {
|
|
4884
|
+
return findSingleReturnStatement(fnNode.body)?.expression;
|
|
4885
|
+
}
|
|
4886
|
+
return void 0;
|
|
4887
|
+
};
|
|
4888
|
+
const getNameIdentifier = (node) => {
|
|
4889
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
4890
|
+
return node.name;
|
|
4891
|
+
}
|
|
4892
|
+
if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
|
|
4893
|
+
return node.parent.name;
|
|
4894
|
+
}
|
|
4895
|
+
if (node.parent && ts.isPropertyAssignment(node.parent)) {
|
|
4896
|
+
const name = node.parent.name;
|
|
4897
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
|
|
4898
|
+
return name;
|
|
4899
|
+
}
|
|
4900
|
+
}
|
|
4901
|
+
if (node.parent && ts.isPropertyDeclaration(node.parent)) {
|
|
4902
|
+
const name = node.parent.name;
|
|
4903
|
+
if (ts.isIdentifier(name)) {
|
|
4904
|
+
return name;
|
|
4905
|
+
}
|
|
4906
|
+
}
|
|
4907
|
+
return void 0;
|
|
4908
|
+
};
|
|
4909
|
+
const areParametersReferencedIn = (fnNode, nodes) => {
|
|
4910
|
+
if (fnNode.parameters.length === 0 || nodes.length === 0) return false;
|
|
4911
|
+
const firstParam = fnNode.parameters[0];
|
|
4912
|
+
const lastParam = fnNode.parameters[fnNode.parameters.length - 1];
|
|
4913
|
+
const paramsStart = firstParam.pos;
|
|
4914
|
+
const paramsEnd = lastParam.end;
|
|
4915
|
+
const isSymbolDeclaredInParams = (symbol3) => {
|
|
4916
|
+
const declarations = symbol3.declarations;
|
|
4917
|
+
if (!declarations) return false;
|
|
4918
|
+
return declarations.some((decl) => decl.pos >= paramsStart && decl.end <= paramsEnd);
|
|
4919
|
+
};
|
|
4920
|
+
const nodesToVisit = [...nodes];
|
|
4921
|
+
while (nodesToVisit.length > 0) {
|
|
4922
|
+
const node = nodesToVisit.shift();
|
|
4923
|
+
if (ts.isIdentifier(node)) {
|
|
4924
|
+
const symbol3 = typeChecker.getSymbolAtLocation(node);
|
|
4925
|
+
if (symbol3 && isSymbolDeclaredInParams(symbol3)) {
|
|
4926
|
+
return true;
|
|
4927
|
+
}
|
|
4928
|
+
}
|
|
4929
|
+
if (ts.isShorthandPropertyAssignment(node)) {
|
|
4930
|
+
const valueSymbol = typeChecker.getShorthandAssignmentValueSymbol(node);
|
|
4931
|
+
if (valueSymbol && isSymbolDeclaredInParams(valueSymbol)) {
|
|
4932
|
+
return true;
|
|
4933
|
+
}
|
|
4934
|
+
}
|
|
4935
|
+
ts.forEachChild(node, (child) => {
|
|
4936
|
+
nodesToVisit.push(child);
|
|
4937
|
+
return void 0;
|
|
4938
|
+
});
|
|
4939
|
+
}
|
|
4940
|
+
return false;
|
|
4941
|
+
};
|
|
4942
|
+
const tryParseGenOpportunity = (fnNode) => gen(function* () {
|
|
4943
|
+
const bodyExpression = getBodyExpression(fnNode);
|
|
4944
|
+
if (!bodyExpression) return yield* TypeParserIssue.issue;
|
|
4945
|
+
const { pipeArguments: pipeArguments2, subject } = yield* pipe(
|
|
4946
|
+
typeParser.pipeCall(bodyExpression),
|
|
4947
|
+
map4(({ args: args2, subject: subject2 }) => ({ subject: subject2, pipeArguments: args2 })),
|
|
4948
|
+
orElse2(() => succeed({ subject: bodyExpression, pipeArguments: [] }))
|
|
4949
|
+
);
|
|
4950
|
+
const { effectModule, generatorFunction } = yield* typeParser.effectGen(subject);
|
|
4951
|
+
const effectModuleName = ts.isIdentifier(effectModule) ? ts.idText(effectModule) : sourceEffectModuleName;
|
|
4952
|
+
return { effectModuleName, generatorFunction, pipeArguments: pipeArguments2 };
|
|
4953
|
+
});
|
|
4954
|
+
const isInsideEffectFn = (fnNode) => {
|
|
4955
|
+
const parent = fnNode.parent;
|
|
4956
|
+
if (!parent || !ts.isCallExpression(parent)) {
|
|
4957
|
+
return succeed(false);
|
|
4958
|
+
}
|
|
4959
|
+
if (parent.arguments[0] !== fnNode) {
|
|
4960
|
+
return succeed(false);
|
|
4961
|
+
}
|
|
4962
|
+
return pipe(
|
|
4963
|
+
typeParser.effectFn(parent),
|
|
4964
|
+
orElse2(() => typeParser.effectFnGen(parent)),
|
|
4965
|
+
orElse2(() => typeParser.effectFnUntracedGen(parent)),
|
|
4966
|
+
map4(() => true),
|
|
4967
|
+
orElse2(() => succeed(false))
|
|
4968
|
+
);
|
|
4969
|
+
};
|
|
4970
|
+
const parseEffectFnOpportunityTarget = (node) => gen(function* () {
|
|
4971
|
+
if (!ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isFunctionDeclaration(node)) {
|
|
4972
|
+
return yield* TypeParserIssue.issue;
|
|
4973
|
+
}
|
|
4974
|
+
if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.asteriskToken) {
|
|
4975
|
+
return yield* TypeParserIssue.issue;
|
|
4976
|
+
}
|
|
4977
|
+
if (ts.isFunctionExpression(node) && node.name) {
|
|
4978
|
+
return yield* TypeParserIssue.issue;
|
|
4979
|
+
}
|
|
4980
|
+
if (yield* isInsideEffectFn(node)) {
|
|
4981
|
+
return yield* TypeParserIssue.issue;
|
|
4982
|
+
}
|
|
4983
|
+
const functionType = typeChecker.getTypeAtLocation(node);
|
|
4984
|
+
if (!functionType) return yield* TypeParserIssue.issue;
|
|
4985
|
+
const callSignatures = typeChecker.getSignaturesOfType(functionType, ts.SignatureKind.Call);
|
|
4986
|
+
if (callSignatures.length !== 1) return yield* TypeParserIssue.issue;
|
|
4987
|
+
const signature = callSignatures[0];
|
|
4988
|
+
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
4989
|
+
const unionMembers = typeCheckerUtils.unrollUnionMembers(returnType);
|
|
4990
|
+
yield* all(...unionMembers.map((member) => typeParser.strictEffectType(member, node)));
|
|
4991
|
+
const nameIdentifier = getNameIdentifier(node);
|
|
4992
|
+
const traceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
|
|
4993
|
+
if (!traceName) return yield* TypeParserIssue.issue;
|
|
4994
|
+
const opportunity = yield* pipe(
|
|
4995
|
+
tryParseGenOpportunity(node),
|
|
4996
|
+
orElse2(
|
|
4997
|
+
() => succeed({ effectModuleName: sourceEffectModuleName, pipeArguments: [], generatorFunction: void 0 })
|
|
4998
|
+
)
|
|
4764
4999
|
);
|
|
5000
|
+
return {
|
|
5001
|
+
node,
|
|
5002
|
+
nameIdentifier,
|
|
5003
|
+
effectModuleName: opportunity.effectModuleName,
|
|
5004
|
+
traceName,
|
|
5005
|
+
pipeArguments: opportunity.pipeArguments,
|
|
5006
|
+
generatorFunction: opportunity.generatorFunction,
|
|
5007
|
+
hasParamsInPipeArgs: areParametersReferencedIn(node, opportunity.pipeArguments)
|
|
5008
|
+
};
|
|
5009
|
+
});
|
|
5010
|
+
const getFunctionBodyBlock = (node) => {
|
|
5011
|
+
if (ts.isArrowFunction(node)) {
|
|
5012
|
+
if (ts.isBlock(node.body)) {
|
|
5013
|
+
return node.body;
|
|
5014
|
+
}
|
|
5015
|
+
return ts.factory.createBlock([ts.factory.createReturnStatement(node.body)], true);
|
|
5016
|
+
}
|
|
5017
|
+
return node.body;
|
|
5018
|
+
};
|
|
5019
|
+
const isGeneratorFunction = (node) => {
|
|
5020
|
+
if (ts.isArrowFunction(node)) return false;
|
|
5021
|
+
return node.asteriskToken !== void 0;
|
|
4765
5022
|
};
|
|
4766
|
-
const createEffectFnNode = (originalNode,
|
|
4767
|
-
const
|
|
4768
|
-
const
|
|
5023
|
+
const createEffectFnNode = (originalNode, innerFunction, effectModuleName, traceName, pipeArguments2) => {
|
|
5024
|
+
const isGenerator = isGeneratorFunction(innerFunction);
|
|
5025
|
+
const newFunction = ts.factory.createFunctionExpression(
|
|
4769
5026
|
void 0,
|
|
4770
|
-
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
5027
|
+
isGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : void 0,
|
|
4771
5028
|
void 0,
|
|
4772
5029
|
originalNode.typeParameters,
|
|
4773
5030
|
originalNode.parameters,
|
|
4774
|
-
|
|
4775
|
-
|
|
5031
|
+
void 0,
|
|
5032
|
+
getFunctionBodyBlock(innerFunction)
|
|
4776
5033
|
);
|
|
4777
5034
|
let fnExpression = ts.factory.createPropertyAccessExpression(
|
|
4778
5035
|
ts.factory.createIdentifier(effectModuleName),
|
|
@@ -4785,34 +5042,27 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
4785
5042
|
[ts.factory.createStringLiteral(traceName)]
|
|
4786
5043
|
);
|
|
4787
5044
|
}
|
|
4788
|
-
const effectFnCall = ts.factory.createCallExpression(
|
|
4789
|
-
fnExpression,
|
|
4790
|
-
void 0,
|
|
4791
|
-
[newGeneratorFunction, ...pipeArguments2]
|
|
4792
|
-
);
|
|
5045
|
+
const effectFnCall = ts.factory.createCallExpression(fnExpression, void 0, [newFunction, ...pipeArguments2]);
|
|
4793
5046
|
if (ts.isFunctionDeclaration(originalNode)) {
|
|
4794
5047
|
return tsUtils.tryPreserveDeclarationSemantics(originalNode, effectFnCall, false);
|
|
4795
5048
|
}
|
|
4796
5049
|
return effectFnCall;
|
|
4797
5050
|
};
|
|
4798
|
-
const createEffectFnUntracedNode = (originalNode,
|
|
4799
|
-
const
|
|
4800
|
-
const
|
|
5051
|
+
const createEffectFnUntracedNode = (originalNode, innerFunction, effectModuleName, pipeArguments2) => {
|
|
5052
|
+
const isGenerator = isGeneratorFunction(innerFunction);
|
|
5053
|
+
const newFunction = ts.factory.createFunctionExpression(
|
|
4801
5054
|
void 0,
|
|
4802
|
-
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
5055
|
+
isGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : void 0,
|
|
4803
5056
|
void 0,
|
|
4804
5057
|
originalNode.typeParameters,
|
|
4805
5058
|
originalNode.parameters,
|
|
4806
|
-
|
|
4807
|
-
|
|
5059
|
+
void 0,
|
|
5060
|
+
getFunctionBodyBlock(innerFunction)
|
|
4808
5061
|
);
|
|
4809
5062
|
const effectFnCall = ts.factory.createCallExpression(
|
|
4810
|
-
ts.factory.createPropertyAccessExpression(
|
|
4811
|
-
ts.factory.createIdentifier(effectModuleName),
|
|
4812
|
-
"fnUntraced"
|
|
4813
|
-
),
|
|
5063
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(effectModuleName), "fnUntraced"),
|
|
4814
5064
|
void 0,
|
|
4815
|
-
[
|
|
5065
|
+
[newFunction, ...pipeArguments2]
|
|
4816
5066
|
);
|
|
4817
5067
|
if (ts.isFunctionDeclaration(originalNode)) {
|
|
4818
5068
|
return tsUtils.tryPreserveDeclarationSemantics(originalNode, effectFnCall, false);
|
|
@@ -4828,88 +5078,41 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
4828
5078
|
while (nodeToVisit.length > 0) {
|
|
4829
5079
|
const node = nodeToVisit.shift();
|
|
4830
5080
|
ts.forEachChild(node, appendNodeToVisit);
|
|
4831
|
-
const target = yield* pipe(
|
|
4832
|
-
parseEffectFnOpportunityTarget(node, sourceFile),
|
|
4833
|
-
option
|
|
4834
|
-
);
|
|
5081
|
+
const target = yield* pipe(parseEffectFnOpportunityTarget(node), option);
|
|
4835
5082
|
if (isNone2(target)) continue;
|
|
4836
|
-
|
|
4837
|
-
|
|
4838
|
-
|
|
4839
|
-
generatorFunction,
|
|
4840
|
-
hasReturnTypeAnnotation,
|
|
4841
|
-
nameIdentifier,
|
|
4842
|
-
node: targetNode,
|
|
4843
|
-
pipeArguments: pipeArguments2,
|
|
4844
|
-
traceName
|
|
4845
|
-
} = target.value;
|
|
5083
|
+
if (target.value.hasParamsInPipeArgs) continue;
|
|
5084
|
+
const { effectModuleName, nameIdentifier, node: targetNode, pipeArguments: pipeArguments2, traceName } = target.value;
|
|
5085
|
+
const innerFunction = target.value.generatorFunction ?? targetNode;
|
|
4846
5086
|
const fixes = [];
|
|
4847
5087
|
fixes.push({
|
|
4848
5088
|
fixName: "effectFnOpportunity_toEffectFn",
|
|
4849
5089
|
description: traceName ? `Convert to Effect.fn("${traceName}")` : "Convert to Effect.fn",
|
|
4850
5090
|
apply: gen(function* () {
|
|
4851
5091
|
const changeTracker = yield* service(ChangeTracker);
|
|
4852
|
-
const newNode = createEffectFnNode(
|
|
4853
|
-
targetNode,
|
|
4854
|
-
generatorFunction,
|
|
4855
|
-
effectModuleName,
|
|
4856
|
-
traceName,
|
|
4857
|
-
hasReturnTypeAnnotation ? effectTypes : void 0,
|
|
4858
|
-
pipeArguments2
|
|
4859
|
-
);
|
|
4860
|
-
changeTracker.replaceNode(sourceFile, targetNode, newNode);
|
|
4861
|
-
})
|
|
4862
|
-
});
|
|
4863
|
-
fixes.push({
|
|
4864
|
-
fixName: "effectFnOpportunity_toEffectFnUntraced",
|
|
4865
|
-
description: "Convert to Effect.fnUntraced",
|
|
4866
|
-
apply: gen(function* () {
|
|
4867
|
-
const changeTracker = yield* service(ChangeTracker);
|
|
4868
|
-
const newNode = createEffectFnUntracedNode(
|
|
4869
|
-
targetNode,
|
|
4870
|
-
generatorFunction,
|
|
4871
|
-
effectModuleName,
|
|
4872
|
-
hasReturnTypeAnnotation ? effectTypes : void 0,
|
|
4873
|
-
pipeArguments2
|
|
4874
|
-
);
|
|
5092
|
+
const newNode = createEffectFnNode(targetNode, innerFunction, effectModuleName, traceName, pipeArguments2);
|
|
4875
5093
|
changeTracker.replaceNode(sourceFile, targetNode, newNode);
|
|
4876
5094
|
})
|
|
4877
5095
|
});
|
|
5096
|
+
if (target.value.generatorFunction) {
|
|
5097
|
+
fixes.push({
|
|
5098
|
+
fixName: "effectFnOpportunity_toEffectFnUntraced",
|
|
5099
|
+
description: "Convert to Effect.fnUntraced",
|
|
5100
|
+
apply: gen(function* () {
|
|
5101
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
5102
|
+
const newNode = createEffectFnUntracedNode(targetNode, innerFunction, effectModuleName, pipeArguments2);
|
|
5103
|
+
changeTracker.replaceNode(sourceFile, targetNode, newNode);
|
|
5104
|
+
})
|
|
5105
|
+
});
|
|
5106
|
+
}
|
|
5107
|
+
const pipeArgsSuffix = pipeArguments2.length > 0 ? ` Effect.fn also accepts the piped transformations as additional arguments.` : ``;
|
|
4878
5108
|
report({
|
|
4879
5109
|
location: nameIdentifier ?? targetNode,
|
|
4880
|
-
messageText: `This function could benefit from Effect.fn's automatic tracing and concise syntax, or Effect.fnUntraced to get just a more concise syntax
|
|
5110
|
+
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}`,
|
|
4881
5111
|
fixes
|
|
4882
5112
|
});
|
|
4883
5113
|
}
|
|
4884
5114
|
})
|
|
4885
5115
|
});
|
|
4886
|
-
function findSingleReturnStatement(ts, block) {
|
|
4887
|
-
if (block.statements.length !== 1) return void 0;
|
|
4888
|
-
const statement = block.statements[0];
|
|
4889
|
-
if (!ts.isReturnStatement(statement)) return void 0;
|
|
4890
|
-
return statement;
|
|
4891
|
-
}
|
|
4892
|
-
function getNameIdentifier(ts, node) {
|
|
4893
|
-
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
4894
|
-
return node.name;
|
|
4895
|
-
}
|
|
4896
|
-
if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
|
|
4897
|
-
return node.parent.name;
|
|
4898
|
-
}
|
|
4899
|
-
if (node.parent && ts.isPropertyAssignment(node.parent)) {
|
|
4900
|
-
const name = node.parent.name;
|
|
4901
|
-
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
|
|
4902
|
-
return name;
|
|
4903
|
-
}
|
|
4904
|
-
}
|
|
4905
|
-
if (node.parent && ts.isPropertyDeclaration(node.parent)) {
|
|
4906
|
-
const name = node.parent.name;
|
|
4907
|
-
if (ts.isIdentifier(name)) {
|
|
4908
|
-
return name;
|
|
4909
|
-
}
|
|
4910
|
-
}
|
|
4911
|
-
return void 0;
|
|
4912
|
-
}
|
|
4913
5116
|
|
|
4914
5117
|
// src/diagnostics/effectGenUsesAdapter.ts
|
|
4915
5118
|
var effectGenUsesAdapter = createDiagnostic({
|
|
@@ -5672,6 +5875,52 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
5672
5875
|
const typeChecker = yield* service(TypeCheckerApi);
|
|
5673
5876
|
const typeParser = yield* service(TypeParser);
|
|
5674
5877
|
const options = yield* service(LanguageServicePluginOptions);
|
|
5878
|
+
const isSafelyPipeableCallee = (callee) => {
|
|
5879
|
+
if (ts.isCallExpression(callee)) {
|
|
5880
|
+
return true;
|
|
5881
|
+
}
|
|
5882
|
+
if (ts.isArrowFunction(callee)) {
|
|
5883
|
+
return true;
|
|
5884
|
+
}
|
|
5885
|
+
if (ts.isFunctionExpression(callee)) {
|
|
5886
|
+
return true;
|
|
5887
|
+
}
|
|
5888
|
+
if (ts.isParenthesizedExpression(callee)) {
|
|
5889
|
+
return isSafelyPipeableCallee(callee.expression);
|
|
5890
|
+
}
|
|
5891
|
+
if (ts.isIdentifier(callee)) {
|
|
5892
|
+
const symbol3 = typeChecker.getSymbolAtLocation(callee);
|
|
5893
|
+
if (!symbol3) return false;
|
|
5894
|
+
if (symbol3.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Namespace | ts.SymbolFlags.ValueModule)) {
|
|
5895
|
+
return true;
|
|
5896
|
+
}
|
|
5897
|
+
const declarations = symbol3.declarations;
|
|
5898
|
+
if (declarations && declarations.length > 0) {
|
|
5899
|
+
const decl = declarations[0];
|
|
5900
|
+
if (ts.isFunctionDeclaration(decl) || ts.isVariableDeclaration(decl) || ts.isImportSpecifier(decl) || ts.isImportClause(decl) || ts.isNamespaceImport(decl)) {
|
|
5901
|
+
return true;
|
|
5902
|
+
}
|
|
5903
|
+
}
|
|
5904
|
+
return false;
|
|
5905
|
+
}
|
|
5906
|
+
if (ts.isPropertyAccessExpression(callee)) {
|
|
5907
|
+
const subject = callee.expression;
|
|
5908
|
+
const symbol3 = typeChecker.getSymbolAtLocation(subject);
|
|
5909
|
+
if (!symbol3) return false;
|
|
5910
|
+
if (symbol3.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Namespace | ts.SymbolFlags.ValueModule)) {
|
|
5911
|
+
return true;
|
|
5912
|
+
}
|
|
5913
|
+
const declarations = symbol3.declarations;
|
|
5914
|
+
if (declarations && declarations.length > 0) {
|
|
5915
|
+
const decl = declarations[0];
|
|
5916
|
+
if (ts.isNamespaceImport(decl) || ts.isSourceFile(decl) || ts.isModuleDeclaration(decl)) {
|
|
5917
|
+
return true;
|
|
5918
|
+
}
|
|
5919
|
+
}
|
|
5920
|
+
return false;
|
|
5921
|
+
}
|
|
5922
|
+
return false;
|
|
5923
|
+
};
|
|
5675
5924
|
const flows = yield* typeParser.pipingFlows(false)(sourceFile);
|
|
5676
5925
|
for (const flow2 of flows) {
|
|
5677
5926
|
if (flow2.transformations.length < options.pipeableMinArgCount) {
|
|
@@ -5685,76 +5934,92 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
5685
5934
|
if (callSigs.length > 0) {
|
|
5686
5935
|
continue;
|
|
5687
5936
|
}
|
|
5688
|
-
|
|
5689
|
-
|
|
5690
|
-
|
|
5691
|
-
|
|
5692
|
-
|
|
5693
|
-
|
|
5694
|
-
|
|
5695
|
-
|
|
5696
|
-
|
|
5697
|
-
|
|
5698
|
-
|
|
5699
|
-
|
|
5700
|
-
|
|
5937
|
+
const isPipeableAtIndex = function* (index) {
|
|
5938
|
+
if (index === 0) {
|
|
5939
|
+
const subjectType = flow2.subject.outType;
|
|
5940
|
+
if (!subjectType) return false;
|
|
5941
|
+
const result = yield* pipe(
|
|
5942
|
+
typeParser.pipeableType(subjectType, flow2.subject.node),
|
|
5943
|
+
option
|
|
5944
|
+
);
|
|
5945
|
+
return result._tag === "Some";
|
|
5946
|
+
} else {
|
|
5947
|
+
const t = flow2.transformations[index - 1];
|
|
5948
|
+
if (!t.outType) return false;
|
|
5949
|
+
const result = yield* pipe(
|
|
5950
|
+
typeParser.pipeableType(t.outType, flow2.node),
|
|
5951
|
+
option
|
|
5952
|
+
);
|
|
5953
|
+
return result._tag === "Some";
|
|
5954
|
+
}
|
|
5955
|
+
};
|
|
5956
|
+
let searchStartIndex = 0;
|
|
5957
|
+
while (searchStartIndex <= flow2.transformations.length) {
|
|
5958
|
+
let firstPipeableIndex = -1;
|
|
5959
|
+
for (let i = searchStartIndex; i <= flow2.transformations.length; i++) {
|
|
5960
|
+
if (yield* isPipeableAtIndex(i)) {
|
|
5961
|
+
firstPipeableIndex = i;
|
|
5962
|
+
break;
|
|
5963
|
+
}
|
|
5964
|
+
}
|
|
5965
|
+
if (firstPipeableIndex === -1) {
|
|
5966
|
+
break;
|
|
5967
|
+
}
|
|
5968
|
+
const pipeableTransformations = [];
|
|
5969
|
+
for (let i = firstPipeableIndex; i < flow2.transformations.length; i++) {
|
|
5701
5970
|
const t = flow2.transformations[i];
|
|
5702
|
-
if (t.
|
|
5703
|
-
|
|
5704
|
-
typeParser.pipeableType(t.outType, flow2.node),
|
|
5705
|
-
option
|
|
5706
|
-
);
|
|
5707
|
-
if (isPipeable._tag === "Some") {
|
|
5708
|
-
firstPipeableIndex = i + 1;
|
|
5709
|
-
break;
|
|
5710
|
-
}
|
|
5971
|
+
if (!isSafelyPipeableCallee(t.callee)) {
|
|
5972
|
+
break;
|
|
5711
5973
|
}
|
|
5974
|
+
pipeableTransformations.push(t);
|
|
5712
5975
|
}
|
|
5713
|
-
|
|
5714
|
-
|
|
5715
|
-
|
|
5716
|
-
|
|
5717
|
-
|
|
5718
|
-
|
|
5719
|
-
|
|
5720
|
-
|
|
5721
|
-
|
|
5722
|
-
|
|
5723
|
-
|
|
5724
|
-
|
|
5725
|
-
|
|
5726
|
-
|
|
5727
|
-
|
|
5728
|
-
|
|
5729
|
-
|
|
5730
|
-
|
|
5731
|
-
|
|
5732
|
-
|
|
5733
|
-
|
|
5734
|
-
|
|
5735
|
-
|
|
5736
|
-
|
|
5737
|
-
|
|
5738
|
-
|
|
5976
|
+
const callKindCount = pipeableTransformations.filter((t) => t.kind === "call").length;
|
|
5977
|
+
if (callKindCount >= options.pipeableMinArgCount) {
|
|
5978
|
+
const pipeableEndIndex = firstPipeableIndex + pipeableTransformations.length;
|
|
5979
|
+
const pipeableSubjectNode = firstPipeableIndex === 0 ? flow2.subject.node : typeParser.reconstructPipingFlow({
|
|
5980
|
+
subject: flow2.subject,
|
|
5981
|
+
transformations: flow2.transformations.slice(0, firstPipeableIndex)
|
|
5982
|
+
});
|
|
5983
|
+
const afterTransformations = flow2.transformations.slice(pipeableEndIndex);
|
|
5984
|
+
report({
|
|
5985
|
+
location: flow2.node,
|
|
5986
|
+
messageText: `Nested function calls can be converted to pipeable style for better readability.`,
|
|
5987
|
+
fixes: [{
|
|
5988
|
+
fixName: "missedPipeableOpportunity_fix",
|
|
5989
|
+
description: "Convert to pipe style",
|
|
5990
|
+
apply: gen(function* () {
|
|
5991
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
5992
|
+
const pipeArgs = pipeableTransformations.map((t) => {
|
|
5993
|
+
if (t.args) {
|
|
5994
|
+
return ts.factory.createCallExpression(
|
|
5995
|
+
t.callee,
|
|
5996
|
+
void 0,
|
|
5997
|
+
t.args
|
|
5998
|
+
);
|
|
5999
|
+
} else {
|
|
6000
|
+
return t.callee;
|
|
6001
|
+
}
|
|
6002
|
+
});
|
|
6003
|
+
const pipeNode = ts.factory.createCallExpression(
|
|
6004
|
+
ts.factory.createPropertyAccessExpression(
|
|
6005
|
+
pipeableSubjectNode,
|
|
6006
|
+
"pipe"
|
|
6007
|
+
),
|
|
5739
6008
|
void 0,
|
|
5740
|
-
|
|
6009
|
+
pipeArgs
|
|
5741
6010
|
);
|
|
5742
|
-
|
|
5743
|
-
|
|
5744
|
-
|
|
5745
|
-
|
|
5746
|
-
|
|
5747
|
-
|
|
5748
|
-
|
|
5749
|
-
|
|
5750
|
-
|
|
5751
|
-
|
|
5752
|
-
|
|
5753
|
-
|
|
5754
|
-
changeTracker.replaceNode(sourceFile, flow2.node, newNode);
|
|
5755
|
-
})
|
|
5756
|
-
}]
|
|
5757
|
-
});
|
|
6011
|
+
const newNode = afterTransformations.length > 0 ? typeParser.reconstructPipingFlow({
|
|
6012
|
+
subject: { node: pipeNode, outType: void 0 },
|
|
6013
|
+
transformations: afterTransformations
|
|
6014
|
+
}) : pipeNode;
|
|
6015
|
+
changeTracker.replaceNode(sourceFile, flow2.node, newNode);
|
|
6016
|
+
})
|
|
6017
|
+
}]
|
|
6018
|
+
});
|
|
6019
|
+
break;
|
|
6020
|
+
}
|
|
6021
|
+
searchStartIndex = firstPipeableIndex + pipeableTransformations.length + 1;
|
|
6022
|
+
}
|
|
5758
6023
|
}
|
|
5759
6024
|
})
|
|
5760
6025
|
});
|
|
@@ -7633,6 +7898,90 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
7633
7898
|
})
|
|
7634
7899
|
});
|
|
7635
7900
|
|
|
7901
|
+
// src/diagnostics/preferSchemaOverJson.ts
|
|
7902
|
+
var preferSchemaOverJson = createDiagnostic({
|
|
7903
|
+
name: "preferSchemaOverJson",
|
|
7904
|
+
code: 44,
|
|
7905
|
+
description: "Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify which may throw",
|
|
7906
|
+
severity: "suggestion",
|
|
7907
|
+
apply: fn("preferSchemaOverJson.apply")(function* (sourceFile, report) {
|
|
7908
|
+
const ts = yield* service(TypeScriptApi);
|
|
7909
|
+
const typeParser = yield* service(TypeParser);
|
|
7910
|
+
const parseJsonMethod = (node) => gen(function* () {
|
|
7911
|
+
if (!ts.isCallExpression(node)) return yield* fail("node is not a call expression");
|
|
7912
|
+
const expression = node.expression;
|
|
7913
|
+
if (!ts.isPropertyAccessExpression(expression)) return yield* fail("expression is not a property access");
|
|
7914
|
+
const objectExpr = expression.expression;
|
|
7915
|
+
const methodName = ts.idText(expression.name);
|
|
7916
|
+
if (!ts.isIdentifier(objectExpr) || ts.idText(objectExpr) !== "JSON") {
|
|
7917
|
+
return yield* fail("object is not JSON");
|
|
7918
|
+
}
|
|
7919
|
+
if (methodName !== "parse" && methodName !== "stringify") {
|
|
7920
|
+
return yield* fail("method is not parse or stringify");
|
|
7921
|
+
}
|
|
7922
|
+
return { node, methodName };
|
|
7923
|
+
});
|
|
7924
|
+
const effectTrySimple = (node) => gen(function* () {
|
|
7925
|
+
if (!ts.isCallExpression(node)) return yield* fail("node is not a call expression");
|
|
7926
|
+
yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
|
|
7927
|
+
if (node.arguments.length === 0) return yield* fail("Effect.try has no arguments");
|
|
7928
|
+
const lazyFn = yield* typeParser.lazyExpression(node.arguments[0]);
|
|
7929
|
+
const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
|
|
7930
|
+
return { node: jsonMethod.node, methodName: jsonMethod.methodName };
|
|
7931
|
+
});
|
|
7932
|
+
const effectTryObject = (node) => gen(function* () {
|
|
7933
|
+
if (!ts.isCallExpression(node)) return yield* fail("node is not a call expression");
|
|
7934
|
+
yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
|
|
7935
|
+
if (node.arguments.length === 0) return yield* fail("Effect.try has no arguments");
|
|
7936
|
+
const arg = node.arguments[0];
|
|
7937
|
+
if (!ts.isObjectLiteralExpression(arg)) return yield* fail("argument is not an object literal");
|
|
7938
|
+
const tryProp = arg.properties.find(
|
|
7939
|
+
(p) => ts.isPropertyAssignment(p) && ts.isIdentifier(p.name) && ts.idText(p.name) === "try"
|
|
7940
|
+
);
|
|
7941
|
+
if (!tryProp) return yield* fail("object has no 'try' property");
|
|
7942
|
+
const lazyFn = yield* typeParser.lazyExpression(tryProp.initializer);
|
|
7943
|
+
const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
|
|
7944
|
+
return { node: jsonMethod.node, methodName: jsonMethod.methodName };
|
|
7945
|
+
});
|
|
7946
|
+
const jsonMethodInEffectGen = (node) => gen(function* () {
|
|
7947
|
+
const jsonMethod = yield* parseJsonMethod(node);
|
|
7948
|
+
const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
|
|
7949
|
+
if (!effectGen || effectGen.body.statements.length === 0) {
|
|
7950
|
+
return yield* fail("not inside an Effect generator");
|
|
7951
|
+
}
|
|
7952
|
+
if (scopeNode && scopeNode !== effectGen.generatorFunction) {
|
|
7953
|
+
return yield* fail("inside a nested function scope");
|
|
7954
|
+
}
|
|
7955
|
+
return { node: jsonMethod.node, methodName: jsonMethod.methodName };
|
|
7956
|
+
});
|
|
7957
|
+
const nodeToVisit = [];
|
|
7958
|
+
const appendNodeToVisit = (node) => {
|
|
7959
|
+
nodeToVisit.push(node);
|
|
7960
|
+
return void 0;
|
|
7961
|
+
};
|
|
7962
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
7963
|
+
while (nodeToVisit.length > 0) {
|
|
7964
|
+
const node = nodeToVisit.shift();
|
|
7965
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
7966
|
+
const match2 = yield* pipe(
|
|
7967
|
+
firstSuccessOf([
|
|
7968
|
+
effectTrySimple(node),
|
|
7969
|
+
effectTryObject(node),
|
|
7970
|
+
jsonMethodInEffectGen(node)
|
|
7971
|
+
]),
|
|
7972
|
+
option
|
|
7973
|
+
);
|
|
7974
|
+
if (isSome2(match2)) {
|
|
7975
|
+
report({
|
|
7976
|
+
location: match2.value.node,
|
|
7977
|
+
messageText: "Consider using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify",
|
|
7978
|
+
fixes: []
|
|
7979
|
+
});
|
|
7980
|
+
}
|
|
7981
|
+
}
|
|
7982
|
+
})
|
|
7983
|
+
});
|
|
7984
|
+
|
|
7636
7985
|
// src/diagnostics/redundantSchemaTagIdentifier.ts
|
|
7637
7986
|
var redundantSchemaTagIdentifier = createDiagnostic({
|
|
7638
7987
|
name: "redundantSchemaTagIdentifier",
|
|
@@ -7785,108 +8134,91 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
7785
8134
|
option
|
|
7786
8135
|
);
|
|
7787
8136
|
if (isNone2(isEffectRunCall)) continue;
|
|
7788
|
-
|
|
7789
|
-
|
|
7790
|
-
|
|
7791
|
-
|
|
7792
|
-
|
|
7793
|
-
if (ts.isFunctionExpression(possiblyEffectGen) || ts.isFunctionDeclaration(possiblyEffectGen) || ts.isMethodDeclaration(possiblyEffectGen) || ts.isArrowFunction(possiblyEffectGen)) {
|
|
7794
|
-
nodeIntroduceScope = possiblyEffectGen;
|
|
7795
|
-
continue;
|
|
7796
|
-
}
|
|
7797
|
-
}
|
|
7798
|
-
const isInEffectGen = yield* pipe(
|
|
7799
|
-
typeParser.effectGen(possiblyEffectGen),
|
|
7800
|
-
orElse2(() => typeParser.effectFnUntracedGen(possiblyEffectGen)),
|
|
7801
|
-
orElse2(() => typeParser.effectFnGen(possiblyEffectGen)),
|
|
7802
|
-
option
|
|
8137
|
+
const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
|
|
8138
|
+
if (effectGen && effectGen.body.statements.length > 0) {
|
|
8139
|
+
const nodeText = sourceFile.text.substring(
|
|
8140
|
+
ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
8141
|
+
node.expression.end
|
|
7803
8142
|
);
|
|
7804
|
-
if (
|
|
7805
|
-
const
|
|
7806
|
-
|
|
7807
|
-
|
|
7808
|
-
|
|
7809
|
-
|
|
7810
|
-
const
|
|
7811
|
-
|
|
7812
|
-
|
|
7813
|
-
|
|
7814
|
-
|
|
7815
|
-
|
|
7816
|
-
|
|
7817
|
-
|
|
7818
|
-
|
|
7819
|
-
|
|
7820
|
-
if (ts.
|
|
7821
|
-
|
|
7822
|
-
typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
|
|
7823
|
-
option
|
|
7824
|
-
);
|
|
7825
|
-
if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
|
|
7826
|
-
runtimeIdentifier = ts.idText(declaration.name);
|
|
7827
|
-
}
|
|
8143
|
+
if (scopeNode && scopeNode !== effectGen.generatorFunction) {
|
|
8144
|
+
const fixAddRuntime = gen(function* () {
|
|
8145
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
8146
|
+
const runtimeModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Runtime") || "Runtime";
|
|
8147
|
+
const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Effect") || "Effect";
|
|
8148
|
+
let runtimeIdentifier = void 0;
|
|
8149
|
+
for (const statement of effectGen.generatorFunction.body.statements) {
|
|
8150
|
+
if (ts.isVariableStatement(statement) && statement.declarationList.declarations.length === 1) {
|
|
8151
|
+
const declaration = statement.declarationList.declarations[0];
|
|
8152
|
+
if (declaration.initializer && ts.isYieldExpression(declaration.initializer) && declaration.initializer.asteriskToken && declaration.initializer.expression) {
|
|
8153
|
+
const yieldedExpression = declaration.initializer.expression;
|
|
8154
|
+
if (ts.isCallExpression(yieldedExpression)) {
|
|
8155
|
+
const maybeEffectRuntime = yield* pipe(
|
|
8156
|
+
typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
|
|
8157
|
+
option
|
|
8158
|
+
);
|
|
8159
|
+
if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
|
|
8160
|
+
runtimeIdentifier = ts.idText(declaration.name);
|
|
7828
8161
|
}
|
|
7829
8162
|
}
|
|
7830
8163
|
}
|
|
7831
8164
|
}
|
|
7832
|
-
|
|
7833
|
-
|
|
7834
|
-
|
|
7835
|
-
|
|
7836
|
-
|
|
8165
|
+
}
|
|
8166
|
+
if (!runtimeIdentifier) {
|
|
8167
|
+
changeTracker.insertNodeAt(
|
|
8168
|
+
sourceFile,
|
|
8169
|
+
effectGen.body.statements[0].pos,
|
|
8170
|
+
ts.factory.createVariableStatement(
|
|
8171
|
+
void 0,
|
|
8172
|
+
ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(
|
|
8173
|
+
"effectRuntime",
|
|
7837
8174
|
void 0,
|
|
7838
|
-
|
|
7839
|
-
|
|
7840
|
-
|
|
7841
|
-
|
|
7842
|
-
|
|
7843
|
-
|
|
7844
|
-
|
|
7845
|
-
|
|
7846
|
-
|
|
7847
|
-
|
|
7848
|
-
),
|
|
7849
|
-
[ts.factory.createTypeReferenceNode("never")],
|
|
7850
|
-
[]
|
|
7851
|
-
)
|
|
8175
|
+
void 0,
|
|
8176
|
+
ts.factory.createYieldExpression(
|
|
8177
|
+
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
8178
|
+
ts.factory.createCallExpression(
|
|
8179
|
+
ts.factory.createPropertyAccessExpression(
|
|
8180
|
+
ts.factory.createIdentifier(effectModuleIdentifier),
|
|
8181
|
+
"runtime"
|
|
8182
|
+
),
|
|
8183
|
+
[ts.factory.createTypeReferenceNode("never")],
|
|
8184
|
+
[]
|
|
7852
8185
|
)
|
|
7853
|
-
)
|
|
7854
|
-
),
|
|
7855
|
-
|
|
7856
|
-
|
|
7857
|
-
|
|
7858
|
-
|
|
7859
|
-
|
|
7860
|
-
}
|
|
7861
|
-
changeTracker.deleteRange(sourceFile, {
|
|
7862
|
-
pos: ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
7863
|
-
end: node.arguments[0].pos
|
|
7864
|
-
});
|
|
7865
|
-
changeTracker.insertText(
|
|
7866
|
-
sourceFile,
|
|
7867
|
-
node.arguments[0].pos,
|
|
7868
|
-
`${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
|
|
8186
|
+
)
|
|
8187
|
+
)], ts.NodeFlags.Const)
|
|
8188
|
+
),
|
|
8189
|
+
{
|
|
8190
|
+
prefix: "\n",
|
|
8191
|
+
suffix: "\n"
|
|
8192
|
+
}
|
|
7869
8193
|
);
|
|
8194
|
+
}
|
|
8195
|
+
changeTracker.deleteRange(sourceFile, {
|
|
8196
|
+
pos: ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
8197
|
+
end: node.arguments[0].pos
|
|
7870
8198
|
});
|
|
7871
|
-
|
|
7872
|
-
|
|
7873
|
-
|
|
8199
|
+
changeTracker.insertText(
|
|
8200
|
+
sourceFile,
|
|
8201
|
+
node.arguments[0].pos,
|
|
8202
|
+
`${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
|
|
8203
|
+
);
|
|
8204
|
+
});
|
|
8205
|
+
report({
|
|
8206
|
+
location: node.expression,
|
|
8207
|
+
messageText: `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
|
|
7874
8208
|
Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`,
|
|
7875
|
-
|
|
7876
|
-
|
|
7877
|
-
|
|
7878
|
-
|
|
7879
|
-
|
|
7880
|
-
|
|
7881
|
-
|
|
7882
|
-
|
|
7883
|
-
|
|
7884
|
-
|
|
7885
|
-
|
|
7886
|
-
|
|
7887
|
-
}
|
|
8209
|
+
fixes: [{
|
|
8210
|
+
fixName: "runEffectInsideEffect_fix",
|
|
8211
|
+
description: "Use a runtime to run the Effect",
|
|
8212
|
+
apply: fixAddRuntime
|
|
8213
|
+
}]
|
|
8214
|
+
});
|
|
8215
|
+
} else {
|
|
8216
|
+
report({
|
|
8217
|
+
location: node.expression,
|
|
8218
|
+
messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
|
|
8219
|
+
fixes: []
|
|
8220
|
+
});
|
|
7888
8221
|
}
|
|
7889
|
-
currentParent = currentParent.parent;
|
|
7890
8222
|
}
|
|
7891
8223
|
}
|
|
7892
8224
|
})
|
|
@@ -7972,6 +8304,59 @@ var schemaStructWithTag = createDiagnostic({
|
|
|
7972
8304
|
})
|
|
7973
8305
|
});
|
|
7974
8306
|
|
|
8307
|
+
// src/diagnostics/schemaSyncInEffect.ts
|
|
8308
|
+
var syncToEffectMethod = {
|
|
8309
|
+
decodeSync: "decode",
|
|
8310
|
+
decodeUnknownSync: "decodeUnknown",
|
|
8311
|
+
encodeSync: "encode",
|
|
8312
|
+
encodeUnknownSync: "encodeUnknown"
|
|
8313
|
+
};
|
|
8314
|
+
var schemaSyncInEffect = createDiagnostic({
|
|
8315
|
+
name: "schemaSyncInEffect",
|
|
8316
|
+
code: 43,
|
|
8317
|
+
description: "Suggests using Effect-based Schema methods instead of sync methods inside Effect generators",
|
|
8318
|
+
severity: "suggestion",
|
|
8319
|
+
apply: fn("schemaSyncInEffect.apply")(function* (sourceFile, report) {
|
|
8320
|
+
const ts = yield* service(TypeScriptApi);
|
|
8321
|
+
const typeParser = yield* service(TypeParser);
|
|
8322
|
+
const parseSchemaSyncMethod = (node, methodName) => pipe(
|
|
8323
|
+
typeParser.isNodeReferenceToEffectParseResultModuleApi(methodName)(node),
|
|
8324
|
+
map4(() => ({ node, methodName }))
|
|
8325
|
+
);
|
|
8326
|
+
const nodeToVisit = [];
|
|
8327
|
+
const appendNodeToVisit = (node) => {
|
|
8328
|
+
nodeToVisit.push(node);
|
|
8329
|
+
return void 0;
|
|
8330
|
+
};
|
|
8331
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
8332
|
+
while (nodeToVisit.length > 0) {
|
|
8333
|
+
const node = nodeToVisit.shift();
|
|
8334
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
8335
|
+
if (!ts.isCallExpression(node)) continue;
|
|
8336
|
+
const isSchemaSyncCall = yield* pipe(
|
|
8337
|
+
firstSuccessOf(
|
|
8338
|
+
Object.keys(syncToEffectMethod).map((methodName) => parseSchemaSyncMethod(node.expression, methodName))
|
|
8339
|
+
),
|
|
8340
|
+
option
|
|
8341
|
+
);
|
|
8342
|
+
if (isNone2(isSchemaSyncCall)) continue;
|
|
8343
|
+
const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
|
|
8344
|
+
if (!effectGen || effectGen.body.statements.length === 0) continue;
|
|
8345
|
+
if (scopeNode && scopeNode !== effectGen.generatorFunction) continue;
|
|
8346
|
+
const nodeText = sourceFile.text.substring(
|
|
8347
|
+
ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
8348
|
+
node.expression.end
|
|
8349
|
+
);
|
|
8350
|
+
const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
|
|
8351
|
+
report({
|
|
8352
|
+
location: node.expression,
|
|
8353
|
+
messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed ParseError in the error channel.`,
|
|
8354
|
+
fixes: []
|
|
8355
|
+
});
|
|
8356
|
+
}
|
|
8357
|
+
})
|
|
8358
|
+
});
|
|
8359
|
+
|
|
7975
8360
|
// src/diagnostics/schemaUnionOfLiterals.ts
|
|
7976
8361
|
var schemaUnionOfLiterals = createDiagnostic({
|
|
7977
8362
|
name: "schemaUnionOfLiterals",
|
|
@@ -8686,7 +9071,9 @@ var diagnostics = [
|
|
|
8686
9071
|
layerMergeAllWithDependencies,
|
|
8687
9072
|
effectMapVoid,
|
|
8688
9073
|
effectFnOpportunity,
|
|
8689
|
-
redundantSchemaTagIdentifier
|
|
9074
|
+
redundantSchemaTagIdentifier,
|
|
9075
|
+
schemaSyncInEffect,
|
|
9076
|
+
preferSchemaOverJson
|
|
8690
9077
|
];
|
|
8691
9078
|
|
|
8692
9079
|
// src/transform.ts
|