@effect/language-service 0.65.0 → 0.67.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +5 -0
- package/cli.js +1254 -668
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +730 -332
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +730 -332
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +730 -332
- package/transform.js.map +1 -1
package/cli.js
CHANGED
|
@@ -945,7 +945,7 @@ var require_createProjectService = __commonJS({
|
|
|
945
945
|
return mod && mod.__esModule ? mod : { "default": mod };
|
|
946
946
|
};
|
|
947
947
|
Object.defineProperty(exports2, "__esModule", { value: true });
|
|
948
|
-
exports2.createProjectService =
|
|
948
|
+
exports2.createProjectService = createProjectService6;
|
|
949
949
|
var debug_1 = __importDefault(require_src());
|
|
950
950
|
var getParsedConfigFileFromTSServer_js_1 = require_getParsedConfigFileFromTSServer();
|
|
951
951
|
var DEFAULT_PROJECT_MATCHED_FILES_THRESHOLD = 8;
|
|
@@ -959,7 +959,7 @@ var require_createProjectService = __commonJS({
|
|
|
959
959
|
var createStubFileWatcher = () => ({
|
|
960
960
|
close: doNothing
|
|
961
961
|
});
|
|
962
|
-
function
|
|
962
|
+
function createProjectService6({ jsDocParsingMode, options: optionsRaw = {}, tsconfigRootDir } = {}) {
|
|
963
963
|
const options3 = {
|
|
964
964
|
defaultProject: "tsconfig.json",
|
|
965
965
|
...optionsRaw
|
|
@@ -30211,7 +30211,7 @@ var runMain3 = runMain2;
|
|
|
30211
30211
|
// package.json
|
|
30212
30212
|
var package_default = {
|
|
30213
30213
|
name: "@effect/language-service",
|
|
30214
|
-
version: "0.
|
|
30214
|
+
version: "0.67.0",
|
|
30215
30215
|
packageManager: "pnpm@8.11.0",
|
|
30216
30216
|
publishConfig: {
|
|
30217
30217
|
access: "public",
|
|
@@ -33315,6 +33315,97 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
33315
33315
|
"TypeParser.effectFnGen",
|
|
33316
33316
|
(node) => node
|
|
33317
33317
|
);
|
|
33318
|
+
const findEnclosingScopes = fn2("TypeParser.findEnclosingScopes")(function* (startNode) {
|
|
33319
|
+
let currentParent = startNode.parent;
|
|
33320
|
+
let scopeNode = void 0;
|
|
33321
|
+
let effectGenResult = void 0;
|
|
33322
|
+
while (currentParent) {
|
|
33323
|
+
const nodeToCheck = currentParent;
|
|
33324
|
+
if (!scopeNode) {
|
|
33325
|
+
if (ts.isFunctionExpression(nodeToCheck) || ts.isFunctionDeclaration(nodeToCheck) || ts.isMethodDeclaration(nodeToCheck) || ts.isArrowFunction(nodeToCheck) || ts.isGetAccessorDeclaration(nodeToCheck) || ts.isSetAccessorDeclaration(nodeToCheck)) {
|
|
33326
|
+
scopeNode = nodeToCheck;
|
|
33327
|
+
}
|
|
33328
|
+
}
|
|
33329
|
+
if (!effectGenResult) {
|
|
33330
|
+
const isEffectGen = yield* pipe(
|
|
33331
|
+
effectGen(nodeToCheck),
|
|
33332
|
+
map34((result) => ({
|
|
33333
|
+
node: result.node,
|
|
33334
|
+
effectModule: result.effectModule,
|
|
33335
|
+
generatorFunction: result.generatorFunction,
|
|
33336
|
+
body: result.body
|
|
33337
|
+
})),
|
|
33338
|
+
orElse15(
|
|
33339
|
+
() => pipe(
|
|
33340
|
+
effectFnUntracedGen(nodeToCheck),
|
|
33341
|
+
map34((result) => ({
|
|
33342
|
+
node: result.node,
|
|
33343
|
+
effectModule: result.effectModule,
|
|
33344
|
+
generatorFunction: result.generatorFunction,
|
|
33345
|
+
body: result.body,
|
|
33346
|
+
pipeArguments: result.pipeArguments
|
|
33347
|
+
}))
|
|
33348
|
+
)
|
|
33349
|
+
),
|
|
33350
|
+
orElse15(
|
|
33351
|
+
() => pipe(
|
|
33352
|
+
effectFnGen(nodeToCheck),
|
|
33353
|
+
map34((result) => ({
|
|
33354
|
+
node: result.node,
|
|
33355
|
+
effectModule: result.effectModule,
|
|
33356
|
+
generatorFunction: result.generatorFunction,
|
|
33357
|
+
body: result.body,
|
|
33358
|
+
pipeArguments: result.pipeArguments
|
|
33359
|
+
}))
|
|
33360
|
+
)
|
|
33361
|
+
),
|
|
33362
|
+
option5
|
|
33363
|
+
);
|
|
33364
|
+
if (isSome2(isEffectGen)) {
|
|
33365
|
+
effectGenResult = isEffectGen.value;
|
|
33366
|
+
}
|
|
33367
|
+
}
|
|
33368
|
+
if (scopeNode && effectGenResult) {
|
|
33369
|
+
break;
|
|
33370
|
+
}
|
|
33371
|
+
currentParent = nodeToCheck.parent;
|
|
33372
|
+
}
|
|
33373
|
+
return { scopeNode, effectGen: effectGenResult };
|
|
33374
|
+
});
|
|
33375
|
+
const effectFn = cachedBy(
|
|
33376
|
+
function(node) {
|
|
33377
|
+
if (!ts.isCallExpression(node)) {
|
|
33378
|
+
return typeParserIssue("Node is not a call expression", void 0, node);
|
|
33379
|
+
}
|
|
33380
|
+
if (node.arguments.length === 0) {
|
|
33381
|
+
return typeParserIssue("Node has no arguments", void 0, node);
|
|
33382
|
+
}
|
|
33383
|
+
const regularFunction = node.arguments[0];
|
|
33384
|
+
if (!ts.isFunctionExpression(regularFunction) && !ts.isArrowFunction(regularFunction)) {
|
|
33385
|
+
return typeParserIssue("Node is not a function expression or arrow function", void 0, node);
|
|
33386
|
+
}
|
|
33387
|
+
if (ts.isFunctionExpression(regularFunction) && regularFunction.asteriskToken !== void 0) {
|
|
33388
|
+
return typeParserIssue("Node is a generator function, not a regular function", void 0, node);
|
|
33389
|
+
}
|
|
33390
|
+
const expressionToTest = ts.isCallExpression(node.expression) ? node.expression.expression : node.expression;
|
|
33391
|
+
if (!ts.isPropertyAccessExpression(expressionToTest)) {
|
|
33392
|
+
return typeParserIssue("Node is not a property access expression", void 0, node);
|
|
33393
|
+
}
|
|
33394
|
+
const propertyAccess = expressionToTest;
|
|
33395
|
+
const pipeArguments2 = node.arguments.slice(1);
|
|
33396
|
+
return pipe(
|
|
33397
|
+
isNodeReferenceToEffectModuleApi("fn")(propertyAccess),
|
|
33398
|
+
map34(() => ({
|
|
33399
|
+
node,
|
|
33400
|
+
effectModule: propertyAccess.expression,
|
|
33401
|
+
regularFunction,
|
|
33402
|
+
pipeArguments: pipeArguments2
|
|
33403
|
+
}))
|
|
33404
|
+
);
|
|
33405
|
+
},
|
|
33406
|
+
"TypeParser.effectFn",
|
|
33407
|
+
(node) => node
|
|
33408
|
+
);
|
|
33318
33409
|
const unnecessaryEffectGen2 = cachedBy(
|
|
33319
33410
|
fn2("TypeParser.unnecessaryEffectGen")(function* (node) {
|
|
33320
33411
|
const { body } = yield* effectGen(node);
|
|
@@ -33426,6 +33517,28 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
33426
33517
|
`TypeParser.isNodeReferenceToEffectSchemaModuleApi(${memberName})`,
|
|
33427
33518
|
(node) => node
|
|
33428
33519
|
);
|
|
33520
|
+
const isEffectParseResultSourceFile = cachedBy(
|
|
33521
|
+
fn2("TypeParser.isEffectParseResultSourceFile")(function* (sourceFile) {
|
|
33522
|
+
const moduleSymbol = typeChecker.getSymbolAtLocation(sourceFile);
|
|
33523
|
+
if (!moduleSymbol) return yield* typeParserIssue("Node has no symbol", void 0, sourceFile);
|
|
33524
|
+
const parseIssueSymbol = typeChecker.tryGetMemberInModuleExports("ParseIssue", moduleSymbol);
|
|
33525
|
+
if (!parseIssueSymbol) return yield* typeParserIssue("ParseIssue type not found", void 0, sourceFile);
|
|
33526
|
+
const decodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("decodeSync", moduleSymbol);
|
|
33527
|
+
if (!decodeSyncSymbol) return yield* typeParserIssue("decodeSync not found", void 0, sourceFile);
|
|
33528
|
+
const encodeSyncSymbol = typeChecker.tryGetMemberInModuleExports("encodeSync", moduleSymbol);
|
|
33529
|
+
if (!encodeSyncSymbol) return yield* typeParserIssue("encodeSync not found", void 0, sourceFile);
|
|
33530
|
+
return sourceFile;
|
|
33531
|
+
}),
|
|
33532
|
+
"TypeParser.isEffectParseResultSourceFile",
|
|
33533
|
+
(sourceFile) => sourceFile
|
|
33534
|
+
);
|
|
33535
|
+
const isNodeReferenceToEffectParseResultModuleApi = (memberName) => cachedBy(
|
|
33536
|
+
fn2("TypeParser.isNodeReferenceToEffectParseResultModuleApi")(function* (node) {
|
|
33537
|
+
return yield* isNodeReferenceToExportOfPackageModule(node, "effect", isEffectParseResultSourceFile, memberName);
|
|
33538
|
+
}),
|
|
33539
|
+
`TypeParser.isNodeReferenceToEffectParseResultModuleApi(${memberName})`,
|
|
33540
|
+
(node) => node
|
|
33541
|
+
);
|
|
33429
33542
|
const contextTagVarianceStruct = (type2, atLocation) => map34(
|
|
33430
33543
|
all9(
|
|
33431
33544
|
varianceStructInvariantType(type2, atLocation, "_Identifier"),
|
|
@@ -34206,11 +34319,65 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
34206
34319
|
if (includeEffectFn) {
|
|
34207
34320
|
const effectFnGenParsed = yield* pipe(effectFnGen(node), option5);
|
|
34208
34321
|
const effectFnUntracedGenParsed = isNone2(effectFnGenParsed) ? yield* pipe(effectFnUntracedGen(node), option5) : none2();
|
|
34209
|
-
const
|
|
34210
|
-
const
|
|
34211
|
-
const
|
|
34212
|
-
|
|
34213
|
-
|
|
34322
|
+
const effectFnNonGenParsed = isNone2(effectFnGenParsed) && isNone2(effectFnUntracedGenParsed) ? yield* pipe(effectFn(node), option5) : none2();
|
|
34323
|
+
const isEffectFnGen = isSome2(effectFnGenParsed);
|
|
34324
|
+
const isEffectFnUntracedGen = isSome2(effectFnUntracedGenParsed);
|
|
34325
|
+
const isEffectFnNonGen = isSome2(effectFnNonGenParsed);
|
|
34326
|
+
const transformationKind = isEffectFnUntracedGen ? "effectFnUntraced" : "effectFn";
|
|
34327
|
+
if (isEffectFnGen || isEffectFnUntracedGen) {
|
|
34328
|
+
const effectFnParsed = isEffectFnGen ? effectFnGenParsed : effectFnUntracedGenParsed;
|
|
34329
|
+
if (isSome2(effectFnParsed) && effectFnParsed.value.pipeArguments.length > 0) {
|
|
34330
|
+
const fnResult = effectFnParsed.value;
|
|
34331
|
+
const pipeArgs = fnResult.pipeArguments;
|
|
34332
|
+
const transformations = [];
|
|
34333
|
+
let subjectType;
|
|
34334
|
+
for (let i = 0; i < pipeArgs.length; i++) {
|
|
34335
|
+
const arg = pipeArgs[i];
|
|
34336
|
+
const contextualType = typeChecker.getContextualType(arg);
|
|
34337
|
+
const callSigs = contextualType ? typeChecker.getSignaturesOfType(contextualType, ts.SignatureKind.Call) : [];
|
|
34338
|
+
const outType = callSigs.length > 0 ? typeChecker.getReturnTypeOfSignature(callSigs[0]) : void 0;
|
|
34339
|
+
if (i === 0 && callSigs.length > 0) {
|
|
34340
|
+
const params = callSigs[0].parameters;
|
|
34341
|
+
if (params.length > 0) {
|
|
34342
|
+
subjectType = typeChecker.getTypeOfSymbol(params[0]);
|
|
34343
|
+
}
|
|
34344
|
+
}
|
|
34345
|
+
if (ts.isCallExpression(arg)) {
|
|
34346
|
+
transformations.push({
|
|
34347
|
+
callee: arg.expression,
|
|
34348
|
+
args: Array.from(arg.arguments),
|
|
34349
|
+
outType,
|
|
34350
|
+
kind: transformationKind
|
|
34351
|
+
});
|
|
34352
|
+
} else {
|
|
34353
|
+
transformations.push({
|
|
34354
|
+
callee: arg,
|
|
34355
|
+
args: void 0,
|
|
34356
|
+
outType,
|
|
34357
|
+
kind: transformationKind
|
|
34358
|
+
});
|
|
34359
|
+
}
|
|
34360
|
+
}
|
|
34361
|
+
const newFlow = {
|
|
34362
|
+
node,
|
|
34363
|
+
subject: {
|
|
34364
|
+
node,
|
|
34365
|
+
outType: subjectType
|
|
34366
|
+
},
|
|
34367
|
+
transformations
|
|
34368
|
+
};
|
|
34369
|
+
result.push(newFlow);
|
|
34370
|
+
workQueue.push([fnResult.body, void 0]);
|
|
34371
|
+
for (const arg of pipeArgs) {
|
|
34372
|
+
ts.forEachChild(arg, (c) => {
|
|
34373
|
+
workQueue.push([c, void 0]);
|
|
34374
|
+
});
|
|
34375
|
+
}
|
|
34376
|
+
continue;
|
|
34377
|
+
}
|
|
34378
|
+
}
|
|
34379
|
+
if (isEffectFnNonGen && isSome2(effectFnNonGenParsed) && effectFnNonGenParsed.value.pipeArguments.length > 0) {
|
|
34380
|
+
const fnResult = effectFnNonGenParsed.value;
|
|
34214
34381
|
const pipeArgs = fnResult.pipeArguments;
|
|
34215
34382
|
const transformations = [];
|
|
34216
34383
|
let subjectType;
|
|
@@ -34230,14 +34397,14 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
34230
34397
|
callee: arg.expression,
|
|
34231
34398
|
args: Array.from(arg.arguments),
|
|
34232
34399
|
outType,
|
|
34233
|
-
kind:
|
|
34400
|
+
kind: "effectFn"
|
|
34234
34401
|
});
|
|
34235
34402
|
} else {
|
|
34236
34403
|
transformations.push({
|
|
34237
34404
|
callee: arg,
|
|
34238
34405
|
args: void 0,
|
|
34239
34406
|
outType,
|
|
34240
|
-
kind:
|
|
34407
|
+
kind: "effectFn"
|
|
34241
34408
|
});
|
|
34242
34409
|
}
|
|
34243
34410
|
}
|
|
@@ -34250,7 +34417,16 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
34250
34417
|
transformations
|
|
34251
34418
|
};
|
|
34252
34419
|
result.push(newFlow);
|
|
34253
|
-
|
|
34420
|
+
const regularFn = fnResult.regularFunction;
|
|
34421
|
+
if (ts.isArrowFunction(regularFn)) {
|
|
34422
|
+
if (ts.isBlock(regularFn.body)) {
|
|
34423
|
+
workQueue.push([regularFn.body, void 0]);
|
|
34424
|
+
} else {
|
|
34425
|
+
workQueue.push([regularFn.body, void 0]);
|
|
34426
|
+
}
|
|
34427
|
+
} else if (regularFn.body) {
|
|
34428
|
+
workQueue.push([regularFn.body, void 0]);
|
|
34429
|
+
}
|
|
34254
34430
|
for (const arg of pipeArgs) {
|
|
34255
34431
|
ts.forEachChild(arg, (c) => {
|
|
34256
34432
|
workQueue.push([c, void 0]);
|
|
@@ -34313,6 +34489,7 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
34313
34489
|
return {
|
|
34314
34490
|
isNodeReferenceToEffectModuleApi,
|
|
34315
34491
|
isNodeReferenceToEffectSchemaModuleApi,
|
|
34492
|
+
isNodeReferenceToEffectParseResultModuleApi,
|
|
34316
34493
|
isNodeReferenceToEffectDataModuleApi,
|
|
34317
34494
|
isNodeReferenceToEffectContextModuleApi,
|
|
34318
34495
|
isNodeReferenceToEffectSqlModelModuleApi,
|
|
@@ -34326,6 +34503,8 @@ function make64(ts, tsUtils, typeChecker, typeCheckerUtils, program) {
|
|
|
34326
34503
|
effectGen,
|
|
34327
34504
|
effectFnUntracedGen,
|
|
34328
34505
|
effectFnGen,
|
|
34506
|
+
findEnclosingScopes,
|
|
34507
|
+
effectFn,
|
|
34329
34508
|
extendsCauseYieldableError,
|
|
34330
34509
|
unnecessaryEffectGen: unnecessaryEffectGen2,
|
|
34331
34510
|
effectSchemaType,
|
|
@@ -36085,106 +36264,195 @@ ${versions.map((version) => `- found ${version} at ${resolvedPackages[packageNam
|
|
|
36085
36264
|
});
|
|
36086
36265
|
|
|
36087
36266
|
// src/diagnostics/effectFnOpportunity.ts
|
|
36088
|
-
var parseEffectFnOpportunityTarget = (node, sourceFile) => gen3(function* () {
|
|
36089
|
-
const ts = yield* service2(TypeScriptApi);
|
|
36090
|
-
const typeChecker = yield* service2(TypeCheckerApi);
|
|
36091
|
-
const typeParser = yield* service2(TypeParser);
|
|
36092
|
-
const tsUtils = yield* service2(TypeScriptUtils);
|
|
36093
|
-
if (!ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isFunctionDeclaration(node)) {
|
|
36094
|
-
return yield* TypeParserIssue.issue;
|
|
36095
|
-
}
|
|
36096
|
-
if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.asteriskToken) {
|
|
36097
|
-
return yield* TypeParserIssue.issue;
|
|
36098
|
-
}
|
|
36099
|
-
if (ts.isFunctionExpression(node) && node.name) {
|
|
36100
|
-
return yield* TypeParserIssue.issue;
|
|
36101
|
-
}
|
|
36102
|
-
let bodyExpression;
|
|
36103
|
-
if (ts.isArrowFunction(node)) {
|
|
36104
|
-
if (ts.isBlock(node.body)) {
|
|
36105
|
-
const returnStatement = findSingleReturnStatement(ts, node.body);
|
|
36106
|
-
if (returnStatement?.expression) {
|
|
36107
|
-
bodyExpression = returnStatement.expression;
|
|
36108
|
-
}
|
|
36109
|
-
} else {
|
|
36110
|
-
bodyExpression = node.body;
|
|
36111
|
-
}
|
|
36112
|
-
} else if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.body) {
|
|
36113
|
-
const returnStatement = findSingleReturnStatement(ts, node.body);
|
|
36114
|
-
if (returnStatement?.expression) {
|
|
36115
|
-
bodyExpression = returnStatement.expression;
|
|
36116
|
-
}
|
|
36117
|
-
}
|
|
36118
|
-
if (!bodyExpression) return yield* TypeParserIssue.issue;
|
|
36119
|
-
const { pipeArguments: pipeArguments2, subject } = yield* pipe(
|
|
36120
|
-
typeParser.pipeCall(bodyExpression),
|
|
36121
|
-
map34(({ args: args3, subject: subject2 }) => ({ subject: subject2, pipeArguments: args3 })),
|
|
36122
|
-
orElse15(() => succeed17({ subject: bodyExpression, pipeArguments: [] }))
|
|
36123
|
-
);
|
|
36124
|
-
const { effectModule, generatorFunction } = yield* typeParser.effectGen(subject);
|
|
36125
|
-
const functionType = typeChecker.getTypeAtLocation(node);
|
|
36126
|
-
if (!functionType) return yield* TypeParserIssue.issue;
|
|
36127
|
-
const callSignatures = typeChecker.getSignaturesOfType(functionType, ts.SignatureKind.Call);
|
|
36128
|
-
if (callSignatures.length !== 1) return yield* TypeParserIssue.issue;
|
|
36129
|
-
const signature = callSignatures[0];
|
|
36130
|
-
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
36131
|
-
const { A, E, R } = yield* typeParser.strictEffectType(returnType, node);
|
|
36132
|
-
const effectModuleName = ts.isIdentifier(effectModule) ? ts.idText(effectModule) : tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
36133
|
-
sourceFile,
|
|
36134
|
-
"effect",
|
|
36135
|
-
"Effect"
|
|
36136
|
-
) || "Effect";
|
|
36137
|
-
const nameIdentifier = getNameIdentifier(ts, node);
|
|
36138
|
-
const traceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
|
|
36139
|
-
const hasReturnTypeAnnotation = !!node.type;
|
|
36140
|
-
return {
|
|
36141
|
-
node,
|
|
36142
|
-
nameIdentifier,
|
|
36143
|
-
effectModule,
|
|
36144
|
-
generatorFunction,
|
|
36145
|
-
effectModuleName,
|
|
36146
|
-
traceName,
|
|
36147
|
-
hasReturnTypeAnnotation,
|
|
36148
|
-
effectTypes: { A, E, R },
|
|
36149
|
-
pipeArguments: pipeArguments2
|
|
36150
|
-
};
|
|
36151
|
-
});
|
|
36152
36267
|
var effectFnOpportunity = createDiagnostic({
|
|
36153
36268
|
name: "effectFnOpportunity",
|
|
36154
36269
|
code: 41,
|
|
36155
|
-
description: "Suggests using Effect.fn for functions that
|
|
36270
|
+
description: "Suggests using Effect.fn for functions that returns an Effect",
|
|
36156
36271
|
severity: "suggestion",
|
|
36157
36272
|
apply: fn2("effectFnOpportunity.apply")(function* (sourceFile, report) {
|
|
36158
36273
|
const ts = yield* service2(TypeScriptApi);
|
|
36159
36274
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
36275
|
+
const typeCheckerUtils = yield* service2(TypeCheckerUtils);
|
|
36276
|
+
const typeParser = yield* service2(TypeParser);
|
|
36160
36277
|
const tsUtils = yield* service2(TypeScriptUtils);
|
|
36161
|
-
const
|
|
36162
|
-
|
|
36163
|
-
|
|
36164
|
-
|
|
36165
|
-
|
|
36166
|
-
|
|
36167
|
-
|
|
36168
|
-
|
|
36169
|
-
|
|
36170
|
-
|
|
36171
|
-
|
|
36172
|
-
|
|
36173
|
-
|
|
36174
|
-
)
|
|
36175
|
-
|
|
36278
|
+
const sourceEffectModuleName = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(
|
|
36279
|
+
sourceFile,
|
|
36280
|
+
"effect",
|
|
36281
|
+
"Effect"
|
|
36282
|
+
) || "Effect";
|
|
36283
|
+
const findSingleReturnStatement = (block) => {
|
|
36284
|
+
if (block.statements.length !== 1) return void 0;
|
|
36285
|
+
const statement = block.statements[0];
|
|
36286
|
+
if (!ts.isReturnStatement(statement)) return void 0;
|
|
36287
|
+
return statement;
|
|
36288
|
+
};
|
|
36289
|
+
const getBodyExpression = (fnNode) => {
|
|
36290
|
+
if (ts.isArrowFunction(fnNode)) {
|
|
36291
|
+
if (ts.isBlock(fnNode.body)) {
|
|
36292
|
+
return findSingleReturnStatement(fnNode.body)?.expression;
|
|
36293
|
+
}
|
|
36294
|
+
return fnNode.body;
|
|
36295
|
+
} else if ((ts.isFunctionExpression(fnNode) || ts.isFunctionDeclaration(fnNode)) && fnNode.body) {
|
|
36296
|
+
return findSingleReturnStatement(fnNode.body)?.expression;
|
|
36297
|
+
}
|
|
36298
|
+
return void 0;
|
|
36299
|
+
};
|
|
36300
|
+
const getNameIdentifier = (node) => {
|
|
36301
|
+
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
36302
|
+
return node.name;
|
|
36303
|
+
}
|
|
36304
|
+
if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
|
|
36305
|
+
return node.parent.name;
|
|
36306
|
+
}
|
|
36307
|
+
if (node.parent && ts.isPropertyAssignment(node.parent)) {
|
|
36308
|
+
const name = node.parent.name;
|
|
36309
|
+
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
|
|
36310
|
+
return name;
|
|
36311
|
+
}
|
|
36312
|
+
}
|
|
36313
|
+
if (node.parent && ts.isPropertyDeclaration(node.parent)) {
|
|
36314
|
+
const name = node.parent.name;
|
|
36315
|
+
if (ts.isIdentifier(name)) {
|
|
36316
|
+
return name;
|
|
36317
|
+
}
|
|
36318
|
+
}
|
|
36319
|
+
return void 0;
|
|
36320
|
+
};
|
|
36321
|
+
const areParametersReferencedIn = (fnNode, nodes2) => {
|
|
36322
|
+
if (fnNode.parameters.length === 0 || nodes2.length === 0) return false;
|
|
36323
|
+
const firstParam = fnNode.parameters[0];
|
|
36324
|
+
const lastParam = fnNode.parameters[fnNode.parameters.length - 1];
|
|
36325
|
+
const paramsStart = firstParam.pos;
|
|
36326
|
+
const paramsEnd = lastParam.end;
|
|
36327
|
+
const isSymbolDeclaredInParams = (symbol3) => {
|
|
36328
|
+
const declarations = symbol3.declarations;
|
|
36329
|
+
if (!declarations) return false;
|
|
36330
|
+
return declarations.some((decl) => decl.pos >= paramsStart && decl.end <= paramsEnd);
|
|
36331
|
+
};
|
|
36332
|
+
const nodesToVisit = [...nodes2];
|
|
36333
|
+
while (nodesToVisit.length > 0) {
|
|
36334
|
+
const node = nodesToVisit.shift();
|
|
36335
|
+
if (ts.isIdentifier(node)) {
|
|
36336
|
+
const symbol3 = typeChecker.getSymbolAtLocation(node);
|
|
36337
|
+
if (symbol3 && isSymbolDeclaredInParams(symbol3)) {
|
|
36338
|
+
return true;
|
|
36339
|
+
}
|
|
36340
|
+
}
|
|
36341
|
+
if (ts.isShorthandPropertyAssignment(node)) {
|
|
36342
|
+
const valueSymbol = typeChecker.getShorthandAssignmentValueSymbol(node);
|
|
36343
|
+
if (valueSymbol && isSymbolDeclaredInParams(valueSymbol)) {
|
|
36344
|
+
return true;
|
|
36345
|
+
}
|
|
36346
|
+
}
|
|
36347
|
+
ts.forEachChild(node, (child) => {
|
|
36348
|
+
nodesToVisit.push(child);
|
|
36349
|
+
return void 0;
|
|
36350
|
+
});
|
|
36351
|
+
}
|
|
36352
|
+
return false;
|
|
36353
|
+
};
|
|
36354
|
+
const tryParseGenOpportunity = (fnNode) => gen3(function* () {
|
|
36355
|
+
const bodyExpression = getBodyExpression(fnNode);
|
|
36356
|
+
if (!bodyExpression) return yield* TypeParserIssue.issue;
|
|
36357
|
+
const { pipeArguments: pipeArguments2, subject } = yield* pipe(
|
|
36358
|
+
typeParser.pipeCall(bodyExpression),
|
|
36359
|
+
map34(({ args: args3, subject: subject2 }) => ({ subject: subject2, pipeArguments: args3 })),
|
|
36360
|
+
orElse15(() => succeed17({ subject: bodyExpression, pipeArguments: [] }))
|
|
36361
|
+
);
|
|
36362
|
+
const { effectModule, generatorFunction } = yield* typeParser.effectGen(subject);
|
|
36363
|
+
const effectModuleName = ts.isIdentifier(effectModule) ? ts.idText(effectModule) : sourceEffectModuleName;
|
|
36364
|
+
return { effectModuleName, generatorFunction, pipeArguments: pipeArguments2 };
|
|
36365
|
+
});
|
|
36366
|
+
const isInsideEffectFn = (fnNode) => {
|
|
36367
|
+
const parent = fnNode.parent;
|
|
36368
|
+
if (!parent || !ts.isCallExpression(parent)) {
|
|
36369
|
+
return succeed17(false);
|
|
36370
|
+
}
|
|
36371
|
+
if (parent.arguments[0] !== fnNode) {
|
|
36372
|
+
return succeed17(false);
|
|
36373
|
+
}
|
|
36374
|
+
return pipe(
|
|
36375
|
+
typeParser.effectFn(parent),
|
|
36376
|
+
orElse15(() => typeParser.effectFnGen(parent)),
|
|
36377
|
+
orElse15(() => typeParser.effectFnUntracedGen(parent)),
|
|
36378
|
+
map34(() => true),
|
|
36379
|
+
orElse15(() => succeed17(false))
|
|
36176
36380
|
);
|
|
36177
36381
|
};
|
|
36178
|
-
const
|
|
36179
|
-
|
|
36180
|
-
|
|
36382
|
+
const parseEffectFnOpportunityTarget = (node) => gen3(function* () {
|
|
36383
|
+
if (!ts.isFunctionExpression(node) && !ts.isArrowFunction(node) && !ts.isFunctionDeclaration(node)) {
|
|
36384
|
+
return yield* TypeParserIssue.issue;
|
|
36385
|
+
}
|
|
36386
|
+
if ((ts.isFunctionExpression(node) || ts.isFunctionDeclaration(node)) && node.asteriskToken) {
|
|
36387
|
+
return yield* TypeParserIssue.issue;
|
|
36388
|
+
}
|
|
36389
|
+
if (ts.isFunctionExpression(node) && node.name) {
|
|
36390
|
+
return yield* TypeParserIssue.issue;
|
|
36391
|
+
}
|
|
36392
|
+
if (yield* isInsideEffectFn(node)) {
|
|
36393
|
+
return yield* TypeParserIssue.issue;
|
|
36394
|
+
}
|
|
36395
|
+
const functionType = typeChecker.getTypeAtLocation(node);
|
|
36396
|
+
if (!functionType) return yield* TypeParserIssue.issue;
|
|
36397
|
+
const callSignatures = typeChecker.getSignaturesOfType(functionType, ts.SignatureKind.Call);
|
|
36398
|
+
if (callSignatures.length !== 1) return yield* TypeParserIssue.issue;
|
|
36399
|
+
const signature = callSignatures[0];
|
|
36400
|
+
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
36401
|
+
const unionMembers = typeCheckerUtils.unrollUnionMembers(returnType);
|
|
36402
|
+
yield* all9(...unionMembers.map((member) => typeParser.strictEffectType(member, node)));
|
|
36403
|
+
const nameIdentifier = getNameIdentifier(node);
|
|
36404
|
+
const traceName = nameIdentifier ? ts.isIdentifier(nameIdentifier) ? ts.idText(nameIdentifier) : nameIdentifier.text : void 0;
|
|
36405
|
+
if (!traceName) return yield* TypeParserIssue.issue;
|
|
36406
|
+
const opportunity = yield* pipe(
|
|
36407
|
+
tryParseGenOpportunity(node),
|
|
36408
|
+
orElse15(() => {
|
|
36409
|
+
if (ts.isArrowFunction(node) && !ts.isBlock(node.body)) {
|
|
36410
|
+
return TypeParserIssue.issue;
|
|
36411
|
+
}
|
|
36412
|
+
const body = ts.isArrowFunction(node) ? node.body : node.body;
|
|
36413
|
+
if (!body || !ts.isBlock(body) || body.statements.length <= 5) {
|
|
36414
|
+
return TypeParserIssue.issue;
|
|
36415
|
+
}
|
|
36416
|
+
return succeed17({
|
|
36417
|
+
effectModuleName: sourceEffectModuleName,
|
|
36418
|
+
pipeArguments: [],
|
|
36419
|
+
generatorFunction: void 0
|
|
36420
|
+
});
|
|
36421
|
+
})
|
|
36422
|
+
);
|
|
36423
|
+
return {
|
|
36424
|
+
node,
|
|
36425
|
+
nameIdentifier,
|
|
36426
|
+
effectModuleName: opportunity.effectModuleName,
|
|
36427
|
+
traceName,
|
|
36428
|
+
pipeArguments: opportunity.pipeArguments,
|
|
36429
|
+
generatorFunction: opportunity.generatorFunction,
|
|
36430
|
+
hasParamsInPipeArgs: areParametersReferencedIn(node, opportunity.pipeArguments)
|
|
36431
|
+
};
|
|
36432
|
+
});
|
|
36433
|
+
const getFunctionBodyBlock = (node) => {
|
|
36434
|
+
if (ts.isArrowFunction(node)) {
|
|
36435
|
+
if (ts.isBlock(node.body)) {
|
|
36436
|
+
return node.body;
|
|
36437
|
+
}
|
|
36438
|
+
return ts.factory.createBlock([ts.factory.createReturnStatement(node.body)], true);
|
|
36439
|
+
}
|
|
36440
|
+
return node.body;
|
|
36441
|
+
};
|
|
36442
|
+
const isGeneratorFunction2 = (node) => {
|
|
36443
|
+
if (ts.isArrowFunction(node)) return false;
|
|
36444
|
+
return node.asteriskToken !== void 0;
|
|
36445
|
+
};
|
|
36446
|
+
const createEffectFnNode = (originalNode, innerFunction, effectModuleName, traceName, pipeArguments2) => {
|
|
36447
|
+
const isGenerator = isGeneratorFunction2(innerFunction);
|
|
36448
|
+
const newFunction = ts.factory.createFunctionExpression(
|
|
36181
36449
|
void 0,
|
|
36182
|
-
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
36450
|
+
isGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : void 0,
|
|
36183
36451
|
void 0,
|
|
36184
36452
|
originalNode.typeParameters,
|
|
36185
36453
|
originalNode.parameters,
|
|
36186
|
-
|
|
36187
|
-
|
|
36454
|
+
void 0,
|
|
36455
|
+
getFunctionBodyBlock(innerFunction)
|
|
36188
36456
|
);
|
|
36189
36457
|
let fnExpression = ts.factory.createPropertyAccessExpression(
|
|
36190
36458
|
ts.factory.createIdentifier(effectModuleName),
|
|
@@ -36197,34 +36465,27 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
36197
36465
|
[ts.factory.createStringLiteral(traceName)]
|
|
36198
36466
|
);
|
|
36199
36467
|
}
|
|
36200
|
-
const effectFnCall = ts.factory.createCallExpression(
|
|
36201
|
-
fnExpression,
|
|
36202
|
-
void 0,
|
|
36203
|
-
[newGeneratorFunction, ...pipeArguments2]
|
|
36204
|
-
);
|
|
36468
|
+
const effectFnCall = ts.factory.createCallExpression(fnExpression, void 0, [newFunction, ...pipeArguments2]);
|
|
36205
36469
|
if (ts.isFunctionDeclaration(originalNode)) {
|
|
36206
36470
|
return tsUtils.tryPreserveDeclarationSemantics(originalNode, effectFnCall, false);
|
|
36207
36471
|
}
|
|
36208
36472
|
return effectFnCall;
|
|
36209
36473
|
};
|
|
36210
|
-
const createEffectFnUntracedNode = (originalNode,
|
|
36211
|
-
const
|
|
36212
|
-
const
|
|
36474
|
+
const createEffectFnUntracedNode = (originalNode, innerFunction, effectModuleName, pipeArguments2) => {
|
|
36475
|
+
const isGenerator = isGeneratorFunction2(innerFunction);
|
|
36476
|
+
const newFunction = ts.factory.createFunctionExpression(
|
|
36213
36477
|
void 0,
|
|
36214
|
-
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
36478
|
+
isGenerator ? ts.factory.createToken(ts.SyntaxKind.AsteriskToken) : void 0,
|
|
36215
36479
|
void 0,
|
|
36216
36480
|
originalNode.typeParameters,
|
|
36217
36481
|
originalNode.parameters,
|
|
36218
|
-
|
|
36219
|
-
|
|
36482
|
+
void 0,
|
|
36483
|
+
getFunctionBodyBlock(innerFunction)
|
|
36220
36484
|
);
|
|
36221
36485
|
const effectFnCall = ts.factory.createCallExpression(
|
|
36222
|
-
ts.factory.createPropertyAccessExpression(
|
|
36223
|
-
ts.factory.createIdentifier(effectModuleName),
|
|
36224
|
-
"fnUntraced"
|
|
36225
|
-
),
|
|
36486
|
+
ts.factory.createPropertyAccessExpression(ts.factory.createIdentifier(effectModuleName), "fnUntraced"),
|
|
36226
36487
|
void 0,
|
|
36227
|
-
[
|
|
36488
|
+
[newFunction, ...pipeArguments2]
|
|
36228
36489
|
);
|
|
36229
36490
|
if (ts.isFunctionDeclaration(originalNode)) {
|
|
36230
36491
|
return tsUtils.tryPreserveDeclarationSemantics(originalNode, effectFnCall, false);
|
|
@@ -36240,88 +36501,41 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
36240
36501
|
while (nodeToVisit.length > 0) {
|
|
36241
36502
|
const node = nodeToVisit.shift();
|
|
36242
36503
|
ts.forEachChild(node, appendNodeToVisit);
|
|
36243
|
-
const target = yield* pipe(
|
|
36244
|
-
parseEffectFnOpportunityTarget(node, sourceFile),
|
|
36245
|
-
option5
|
|
36246
|
-
);
|
|
36504
|
+
const target = yield* pipe(parseEffectFnOpportunityTarget(node), option5);
|
|
36247
36505
|
if (isNone2(target)) continue;
|
|
36248
|
-
|
|
36249
|
-
|
|
36250
|
-
|
|
36251
|
-
generatorFunction,
|
|
36252
|
-
hasReturnTypeAnnotation,
|
|
36253
|
-
nameIdentifier,
|
|
36254
|
-
node: targetNode,
|
|
36255
|
-
pipeArguments: pipeArguments2,
|
|
36256
|
-
traceName
|
|
36257
|
-
} = target.value;
|
|
36506
|
+
if (target.value.hasParamsInPipeArgs) continue;
|
|
36507
|
+
const { effectModuleName, nameIdentifier, node: targetNode, pipeArguments: pipeArguments2, traceName } = target.value;
|
|
36508
|
+
const innerFunction = target.value.generatorFunction ?? targetNode;
|
|
36258
36509
|
const fixes = [];
|
|
36259
36510
|
fixes.push({
|
|
36260
36511
|
fixName: "effectFnOpportunity_toEffectFn",
|
|
36261
36512
|
description: traceName ? `Convert to Effect.fn("${traceName}")` : "Convert to Effect.fn",
|
|
36262
36513
|
apply: gen3(function* () {
|
|
36263
36514
|
const changeTracker = yield* service2(ChangeTracker);
|
|
36264
|
-
const newNode = createEffectFnNode(
|
|
36265
|
-
targetNode,
|
|
36266
|
-
generatorFunction,
|
|
36267
|
-
effectModuleName,
|
|
36268
|
-
traceName,
|
|
36269
|
-
hasReturnTypeAnnotation ? effectTypes : void 0,
|
|
36270
|
-
pipeArguments2
|
|
36271
|
-
);
|
|
36272
|
-
changeTracker.replaceNode(sourceFile, targetNode, newNode);
|
|
36273
|
-
})
|
|
36274
|
-
});
|
|
36275
|
-
fixes.push({
|
|
36276
|
-
fixName: "effectFnOpportunity_toEffectFnUntraced",
|
|
36277
|
-
description: "Convert to Effect.fnUntraced",
|
|
36278
|
-
apply: gen3(function* () {
|
|
36279
|
-
const changeTracker = yield* service2(ChangeTracker);
|
|
36280
|
-
const newNode = createEffectFnUntracedNode(
|
|
36281
|
-
targetNode,
|
|
36282
|
-
generatorFunction,
|
|
36283
|
-
effectModuleName,
|
|
36284
|
-
hasReturnTypeAnnotation ? effectTypes : void 0,
|
|
36285
|
-
pipeArguments2
|
|
36286
|
-
);
|
|
36515
|
+
const newNode = createEffectFnNode(targetNode, innerFunction, effectModuleName, traceName, pipeArguments2);
|
|
36287
36516
|
changeTracker.replaceNode(sourceFile, targetNode, newNode);
|
|
36288
36517
|
})
|
|
36289
36518
|
});
|
|
36519
|
+
if (target.value.generatorFunction) {
|
|
36520
|
+
fixes.push({
|
|
36521
|
+
fixName: "effectFnOpportunity_toEffectFnUntraced",
|
|
36522
|
+
description: "Convert to Effect.fnUntraced",
|
|
36523
|
+
apply: gen3(function* () {
|
|
36524
|
+
const changeTracker = yield* service2(ChangeTracker);
|
|
36525
|
+
const newNode = createEffectFnUntracedNode(targetNode, innerFunction, effectModuleName, pipeArguments2);
|
|
36526
|
+
changeTracker.replaceNode(sourceFile, targetNode, newNode);
|
|
36527
|
+
})
|
|
36528
|
+
});
|
|
36529
|
+
}
|
|
36530
|
+
const pipeArgsSuffix = pipeArguments2.length > 0 ? ` Effect.fn also accepts the piped transformations as additional arguments.` : ``;
|
|
36290
36531
|
report({
|
|
36291
36532
|
location: nameIdentifier ?? targetNode,
|
|
36292
|
-
messageText: `This function could benefit from Effect.fn's automatic tracing and concise syntax, or Effect.fnUntraced to get just a more concise syntax
|
|
36533
|
+
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}`,
|
|
36293
36534
|
fixes
|
|
36294
36535
|
});
|
|
36295
36536
|
}
|
|
36296
36537
|
})
|
|
36297
36538
|
});
|
|
36298
|
-
function findSingleReturnStatement(ts, block) {
|
|
36299
|
-
if (block.statements.length !== 1) return void 0;
|
|
36300
|
-
const statement = block.statements[0];
|
|
36301
|
-
if (!ts.isReturnStatement(statement)) return void 0;
|
|
36302
|
-
return statement;
|
|
36303
|
-
}
|
|
36304
|
-
function getNameIdentifier(ts, node) {
|
|
36305
|
-
if (ts.isFunctionDeclaration(node) && node.name) {
|
|
36306
|
-
return node.name;
|
|
36307
|
-
}
|
|
36308
|
-
if (node.parent && ts.isVariableDeclaration(node.parent) && ts.isIdentifier(node.parent.name)) {
|
|
36309
|
-
return node.parent.name;
|
|
36310
|
-
}
|
|
36311
|
-
if (node.parent && ts.isPropertyAssignment(node.parent)) {
|
|
36312
|
-
const name = node.parent.name;
|
|
36313
|
-
if (ts.isIdentifier(name) || ts.isStringLiteral(name)) {
|
|
36314
|
-
return name;
|
|
36315
|
-
}
|
|
36316
|
-
}
|
|
36317
|
-
if (node.parent && ts.isPropertyDeclaration(node.parent)) {
|
|
36318
|
-
const name = node.parent.name;
|
|
36319
|
-
if (ts.isIdentifier(name)) {
|
|
36320
|
-
return name;
|
|
36321
|
-
}
|
|
36322
|
-
}
|
|
36323
|
-
return void 0;
|
|
36324
|
-
}
|
|
36325
36539
|
|
|
36326
36540
|
// src/diagnostics/effectGenUsesAdapter.ts
|
|
36327
36541
|
var effectGenUsesAdapter = createDiagnostic({
|
|
@@ -37084,6 +37298,52 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
37084
37298
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
37085
37299
|
const typeParser = yield* service2(TypeParser);
|
|
37086
37300
|
const options3 = yield* service2(LanguageServicePluginOptions);
|
|
37301
|
+
const isSafelyPipeableCallee = (callee) => {
|
|
37302
|
+
if (ts.isCallExpression(callee)) {
|
|
37303
|
+
return true;
|
|
37304
|
+
}
|
|
37305
|
+
if (ts.isArrowFunction(callee)) {
|
|
37306
|
+
return true;
|
|
37307
|
+
}
|
|
37308
|
+
if (ts.isFunctionExpression(callee)) {
|
|
37309
|
+
return true;
|
|
37310
|
+
}
|
|
37311
|
+
if (ts.isParenthesizedExpression(callee)) {
|
|
37312
|
+
return isSafelyPipeableCallee(callee.expression);
|
|
37313
|
+
}
|
|
37314
|
+
if (ts.isIdentifier(callee)) {
|
|
37315
|
+
const symbol3 = typeChecker.getSymbolAtLocation(callee);
|
|
37316
|
+
if (!symbol3) return false;
|
|
37317
|
+
if (symbol3.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Namespace | ts.SymbolFlags.ValueModule)) {
|
|
37318
|
+
return true;
|
|
37319
|
+
}
|
|
37320
|
+
const declarations = symbol3.declarations;
|
|
37321
|
+
if (declarations && declarations.length > 0) {
|
|
37322
|
+
const decl = declarations[0];
|
|
37323
|
+
if (ts.isFunctionDeclaration(decl) || ts.isVariableDeclaration(decl) || ts.isImportSpecifier(decl) || ts.isImportClause(decl) || ts.isNamespaceImport(decl)) {
|
|
37324
|
+
return true;
|
|
37325
|
+
}
|
|
37326
|
+
}
|
|
37327
|
+
return false;
|
|
37328
|
+
}
|
|
37329
|
+
if (ts.isPropertyAccessExpression(callee)) {
|
|
37330
|
+
const subject = callee.expression;
|
|
37331
|
+
const symbol3 = typeChecker.getSymbolAtLocation(subject);
|
|
37332
|
+
if (!symbol3) return false;
|
|
37333
|
+
if (symbol3.flags & (ts.SymbolFlags.Module | ts.SymbolFlags.Namespace | ts.SymbolFlags.ValueModule)) {
|
|
37334
|
+
return true;
|
|
37335
|
+
}
|
|
37336
|
+
const declarations = symbol3.declarations;
|
|
37337
|
+
if (declarations && declarations.length > 0) {
|
|
37338
|
+
const decl = declarations[0];
|
|
37339
|
+
if (ts.isNamespaceImport(decl) || ts.isSourceFile(decl) || ts.isModuleDeclaration(decl)) {
|
|
37340
|
+
return true;
|
|
37341
|
+
}
|
|
37342
|
+
}
|
|
37343
|
+
return false;
|
|
37344
|
+
}
|
|
37345
|
+
return false;
|
|
37346
|
+
};
|
|
37087
37347
|
const flows = yield* typeParser.pipingFlows(false)(sourceFile);
|
|
37088
37348
|
for (const flow2 of flows) {
|
|
37089
37349
|
if (flow2.transformations.length < options3.pipeableMinArgCount) {
|
|
@@ -37097,76 +37357,92 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
37097
37357
|
if (callSigs.length > 0) {
|
|
37098
37358
|
continue;
|
|
37099
37359
|
}
|
|
37100
|
-
|
|
37101
|
-
|
|
37102
|
-
|
|
37103
|
-
|
|
37104
|
-
|
|
37105
|
-
|
|
37106
|
-
|
|
37107
|
-
|
|
37108
|
-
|
|
37109
|
-
|
|
37110
|
-
|
|
37111
|
-
|
|
37112
|
-
|
|
37113
|
-
|
|
37114
|
-
|
|
37115
|
-
|
|
37116
|
-
|
|
37117
|
-
|
|
37118
|
-
|
|
37119
|
-
|
|
37120
|
-
|
|
37121
|
-
|
|
37122
|
-
|
|
37360
|
+
const isPipeableAtIndex = function* (index) {
|
|
37361
|
+
if (index === 0) {
|
|
37362
|
+
const subjectType = flow2.subject.outType;
|
|
37363
|
+
if (!subjectType) return false;
|
|
37364
|
+
const result = yield* pipe(
|
|
37365
|
+
typeParser.pipeableType(subjectType, flow2.subject.node),
|
|
37366
|
+
option5
|
|
37367
|
+
);
|
|
37368
|
+
return result._tag === "Some";
|
|
37369
|
+
} else {
|
|
37370
|
+
const t = flow2.transformations[index - 1];
|
|
37371
|
+
if (!t.outType) return false;
|
|
37372
|
+
const result = yield* pipe(
|
|
37373
|
+
typeParser.pipeableType(t.outType, flow2.node),
|
|
37374
|
+
option5
|
|
37375
|
+
);
|
|
37376
|
+
return result._tag === "Some";
|
|
37377
|
+
}
|
|
37378
|
+
};
|
|
37379
|
+
let searchStartIndex = 0;
|
|
37380
|
+
while (searchStartIndex <= flow2.transformations.length) {
|
|
37381
|
+
let firstPipeableIndex = -1;
|
|
37382
|
+
for (let i = searchStartIndex; i <= flow2.transformations.length; i++) {
|
|
37383
|
+
if (yield* isPipeableAtIndex(i)) {
|
|
37384
|
+
firstPipeableIndex = i;
|
|
37385
|
+
break;
|
|
37123
37386
|
}
|
|
37124
37387
|
}
|
|
37125
|
-
|
|
37126
|
-
|
|
37127
|
-
|
|
37128
|
-
|
|
37129
|
-
|
|
37130
|
-
|
|
37131
|
-
|
|
37132
|
-
|
|
37133
|
-
|
|
37134
|
-
|
|
37135
|
-
|
|
37136
|
-
|
|
37137
|
-
|
|
37138
|
-
|
|
37139
|
-
|
|
37140
|
-
|
|
37141
|
-
|
|
37142
|
-
|
|
37143
|
-
|
|
37144
|
-
|
|
37145
|
-
|
|
37146
|
-
|
|
37147
|
-
|
|
37148
|
-
|
|
37149
|
-
|
|
37150
|
-
|
|
37388
|
+
if (firstPipeableIndex === -1) {
|
|
37389
|
+
break;
|
|
37390
|
+
}
|
|
37391
|
+
const pipeableTransformations = [];
|
|
37392
|
+
for (let i = firstPipeableIndex; i < flow2.transformations.length; i++) {
|
|
37393
|
+
const t = flow2.transformations[i];
|
|
37394
|
+
if (!isSafelyPipeableCallee(t.callee)) {
|
|
37395
|
+
break;
|
|
37396
|
+
}
|
|
37397
|
+
pipeableTransformations.push(t);
|
|
37398
|
+
}
|
|
37399
|
+
const callKindCount = pipeableTransformations.filter((t) => t.kind === "call").length;
|
|
37400
|
+
if (callKindCount >= options3.pipeableMinArgCount) {
|
|
37401
|
+
const pipeableEndIndex = firstPipeableIndex + pipeableTransformations.length;
|
|
37402
|
+
const pipeableSubjectNode = firstPipeableIndex === 0 ? flow2.subject.node : typeParser.reconstructPipingFlow({
|
|
37403
|
+
subject: flow2.subject,
|
|
37404
|
+
transformations: flow2.transformations.slice(0, firstPipeableIndex)
|
|
37405
|
+
});
|
|
37406
|
+
const afterTransformations = flow2.transformations.slice(pipeableEndIndex);
|
|
37407
|
+
report({
|
|
37408
|
+
location: flow2.node,
|
|
37409
|
+
messageText: `Nested function calls can be converted to pipeable style for better readability.`,
|
|
37410
|
+
fixes: [{
|
|
37411
|
+
fixName: "missedPipeableOpportunity_fix",
|
|
37412
|
+
description: "Convert to pipe style",
|
|
37413
|
+
apply: gen3(function* () {
|
|
37414
|
+
const changeTracker = yield* service2(ChangeTracker);
|
|
37415
|
+
const pipeArgs = pipeableTransformations.map((t) => {
|
|
37416
|
+
if (t.args) {
|
|
37417
|
+
return ts.factory.createCallExpression(
|
|
37418
|
+
t.callee,
|
|
37419
|
+
void 0,
|
|
37420
|
+
t.args
|
|
37421
|
+
);
|
|
37422
|
+
} else {
|
|
37423
|
+
return t.callee;
|
|
37424
|
+
}
|
|
37425
|
+
});
|
|
37426
|
+
const pipeNode = ts.factory.createCallExpression(
|
|
37427
|
+
ts.factory.createPropertyAccessExpression(
|
|
37428
|
+
pipeableSubjectNode,
|
|
37429
|
+
"pipe"
|
|
37430
|
+
),
|
|
37151
37431
|
void 0,
|
|
37152
|
-
|
|
37432
|
+
pipeArgs
|
|
37153
37433
|
);
|
|
37154
|
-
|
|
37155
|
-
|
|
37156
|
-
|
|
37157
|
-
|
|
37158
|
-
|
|
37159
|
-
|
|
37160
|
-
|
|
37161
|
-
|
|
37162
|
-
|
|
37163
|
-
|
|
37164
|
-
|
|
37165
|
-
|
|
37166
|
-
changeTracker.replaceNode(sourceFile, flow2.node, newNode);
|
|
37167
|
-
})
|
|
37168
|
-
}]
|
|
37169
|
-
});
|
|
37434
|
+
const newNode = afterTransformations.length > 0 ? typeParser.reconstructPipingFlow({
|
|
37435
|
+
subject: { node: pipeNode, outType: void 0 },
|
|
37436
|
+
transformations: afterTransformations
|
|
37437
|
+
}) : pipeNode;
|
|
37438
|
+
changeTracker.replaceNode(sourceFile, flow2.node, newNode);
|
|
37439
|
+
})
|
|
37440
|
+
}]
|
|
37441
|
+
});
|
|
37442
|
+
break;
|
|
37443
|
+
}
|
|
37444
|
+
searchStartIndex = firstPipeableIndex + pipeableTransformations.length + 1;
|
|
37445
|
+
}
|
|
37170
37446
|
}
|
|
37171
37447
|
})
|
|
37172
37448
|
});
|
|
@@ -38012,6 +38288,90 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
38012
38288
|
})
|
|
38013
38289
|
});
|
|
38014
38290
|
|
|
38291
|
+
// src/diagnostics/preferSchemaOverJson.ts
|
|
38292
|
+
var preferSchemaOverJson = createDiagnostic({
|
|
38293
|
+
name: "preferSchemaOverJson",
|
|
38294
|
+
code: 44,
|
|
38295
|
+
description: "Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify which may throw",
|
|
38296
|
+
severity: "suggestion",
|
|
38297
|
+
apply: fn2("preferSchemaOverJson.apply")(function* (sourceFile, report) {
|
|
38298
|
+
const ts = yield* service2(TypeScriptApi);
|
|
38299
|
+
const typeParser = yield* service2(TypeParser);
|
|
38300
|
+
const parseJsonMethod = (node) => gen3(function* () {
|
|
38301
|
+
if (!ts.isCallExpression(node)) return yield* fail18("node is not a call expression");
|
|
38302
|
+
const expression = node.expression;
|
|
38303
|
+
if (!ts.isPropertyAccessExpression(expression)) return yield* fail18("expression is not a property access");
|
|
38304
|
+
const objectExpr = expression.expression;
|
|
38305
|
+
const methodName = ts.idText(expression.name);
|
|
38306
|
+
if (!ts.isIdentifier(objectExpr) || ts.idText(objectExpr) !== "JSON") {
|
|
38307
|
+
return yield* fail18("object is not JSON");
|
|
38308
|
+
}
|
|
38309
|
+
if (methodName !== "parse" && methodName !== "stringify") {
|
|
38310
|
+
return yield* fail18("method is not parse or stringify");
|
|
38311
|
+
}
|
|
38312
|
+
return { node, methodName };
|
|
38313
|
+
});
|
|
38314
|
+
const effectTrySimple = (node) => gen3(function* () {
|
|
38315
|
+
if (!ts.isCallExpression(node)) return yield* fail18("node is not a call expression");
|
|
38316
|
+
yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
|
|
38317
|
+
if (node.arguments.length === 0) return yield* fail18("Effect.try has no arguments");
|
|
38318
|
+
const lazyFn = yield* typeParser.lazyExpression(node.arguments[0]);
|
|
38319
|
+
const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
|
|
38320
|
+
return { node: jsonMethod.node, methodName: jsonMethod.methodName };
|
|
38321
|
+
});
|
|
38322
|
+
const effectTryObject = (node) => gen3(function* () {
|
|
38323
|
+
if (!ts.isCallExpression(node)) return yield* fail18("node is not a call expression");
|
|
38324
|
+
yield* typeParser.isNodeReferenceToEffectModuleApi("try")(node.expression);
|
|
38325
|
+
if (node.arguments.length === 0) return yield* fail18("Effect.try has no arguments");
|
|
38326
|
+
const arg = node.arguments[0];
|
|
38327
|
+
if (!ts.isObjectLiteralExpression(arg)) return yield* fail18("argument is not an object literal");
|
|
38328
|
+
const tryProp = arg.properties.find(
|
|
38329
|
+
(p3) => ts.isPropertyAssignment(p3) && ts.isIdentifier(p3.name) && ts.idText(p3.name) === "try"
|
|
38330
|
+
);
|
|
38331
|
+
if (!tryProp) return yield* fail18("object has no 'try' property");
|
|
38332
|
+
const lazyFn = yield* typeParser.lazyExpression(tryProp.initializer);
|
|
38333
|
+
const jsonMethod = yield* parseJsonMethod(lazyFn.expression);
|
|
38334
|
+
return { node: jsonMethod.node, methodName: jsonMethod.methodName };
|
|
38335
|
+
});
|
|
38336
|
+
const jsonMethodInEffectGen = (node) => gen3(function* () {
|
|
38337
|
+
const jsonMethod = yield* parseJsonMethod(node);
|
|
38338
|
+
const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
|
|
38339
|
+
if (!effectGen || effectGen.body.statements.length === 0) {
|
|
38340
|
+
return yield* fail18("not inside an Effect generator");
|
|
38341
|
+
}
|
|
38342
|
+
if (scopeNode && scopeNode !== effectGen.generatorFunction) {
|
|
38343
|
+
return yield* fail18("inside a nested function scope");
|
|
38344
|
+
}
|
|
38345
|
+
return { node: jsonMethod.node, methodName: jsonMethod.methodName };
|
|
38346
|
+
});
|
|
38347
|
+
const nodeToVisit = [];
|
|
38348
|
+
const appendNodeToVisit = (node) => {
|
|
38349
|
+
nodeToVisit.push(node);
|
|
38350
|
+
return void 0;
|
|
38351
|
+
};
|
|
38352
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
38353
|
+
while (nodeToVisit.length > 0) {
|
|
38354
|
+
const node = nodeToVisit.shift();
|
|
38355
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
38356
|
+
const match18 = yield* pipe(
|
|
38357
|
+
firstSuccessOf2([
|
|
38358
|
+
effectTrySimple(node),
|
|
38359
|
+
effectTryObject(node),
|
|
38360
|
+
jsonMethodInEffectGen(node)
|
|
38361
|
+
]),
|
|
38362
|
+
option5
|
|
38363
|
+
);
|
|
38364
|
+
if (isSome2(match18)) {
|
|
38365
|
+
report({
|
|
38366
|
+
location: match18.value.node,
|
|
38367
|
+
messageText: "Consider using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify",
|
|
38368
|
+
fixes: []
|
|
38369
|
+
});
|
|
38370
|
+
}
|
|
38371
|
+
}
|
|
38372
|
+
})
|
|
38373
|
+
});
|
|
38374
|
+
|
|
38015
38375
|
// src/diagnostics/redundantSchemaTagIdentifier.ts
|
|
38016
38376
|
var redundantSchemaTagIdentifier = createDiagnostic({
|
|
38017
38377
|
name: "redundantSchemaTagIdentifier",
|
|
@@ -38164,108 +38524,91 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
38164
38524
|
option5
|
|
38165
38525
|
);
|
|
38166
38526
|
if (isNone2(isEffectRunCall)) continue;
|
|
38167
|
-
|
|
38168
|
-
|
|
38169
|
-
|
|
38170
|
-
|
|
38171
|
-
|
|
38172
|
-
if (ts.isFunctionExpression(possiblyEffectGen) || ts.isFunctionDeclaration(possiblyEffectGen) || ts.isMethodDeclaration(possiblyEffectGen) || ts.isArrowFunction(possiblyEffectGen)) {
|
|
38173
|
-
nodeIntroduceScope = possiblyEffectGen;
|
|
38174
|
-
continue;
|
|
38175
|
-
}
|
|
38176
|
-
}
|
|
38177
|
-
const isInEffectGen = yield* pipe(
|
|
38178
|
-
typeParser.effectGen(possiblyEffectGen),
|
|
38179
|
-
orElse15(() => typeParser.effectFnUntracedGen(possiblyEffectGen)),
|
|
38180
|
-
orElse15(() => typeParser.effectFnGen(possiblyEffectGen)),
|
|
38181
|
-
option5
|
|
38527
|
+
const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
|
|
38528
|
+
if (effectGen && effectGen.body.statements.length > 0) {
|
|
38529
|
+
const nodeText = sourceFile.text.substring(
|
|
38530
|
+
ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
38531
|
+
node.expression.end
|
|
38182
38532
|
);
|
|
38183
|
-
if (
|
|
38184
|
-
const
|
|
38185
|
-
|
|
38186
|
-
|
|
38187
|
-
|
|
38188
|
-
|
|
38189
|
-
const
|
|
38190
|
-
|
|
38191
|
-
|
|
38192
|
-
|
|
38193
|
-
|
|
38194
|
-
|
|
38195
|
-
|
|
38196
|
-
|
|
38197
|
-
|
|
38198
|
-
|
|
38199
|
-
if (ts.
|
|
38200
|
-
|
|
38201
|
-
typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
|
|
38202
|
-
option5
|
|
38203
|
-
);
|
|
38204
|
-
if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
|
|
38205
|
-
runtimeIdentifier = ts.idText(declaration.name);
|
|
38206
|
-
}
|
|
38533
|
+
if (scopeNode && scopeNode !== effectGen.generatorFunction) {
|
|
38534
|
+
const fixAddRuntime = gen3(function* () {
|
|
38535
|
+
const changeTracker = yield* service2(ChangeTracker);
|
|
38536
|
+
const runtimeModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Runtime") || "Runtime";
|
|
38537
|
+
const effectModuleIdentifier = tsUtils.findImportedModuleIdentifierByPackageAndNameOrBarrel(sourceFile, "effect", "Effect") || "Effect";
|
|
38538
|
+
let runtimeIdentifier = void 0;
|
|
38539
|
+
for (const statement of effectGen.generatorFunction.body.statements) {
|
|
38540
|
+
if (ts.isVariableStatement(statement) && statement.declarationList.declarations.length === 1) {
|
|
38541
|
+
const declaration = statement.declarationList.declarations[0];
|
|
38542
|
+
if (declaration.initializer && ts.isYieldExpression(declaration.initializer) && declaration.initializer.asteriskToken && declaration.initializer.expression) {
|
|
38543
|
+
const yieldedExpression = declaration.initializer.expression;
|
|
38544
|
+
if (ts.isCallExpression(yieldedExpression)) {
|
|
38545
|
+
const maybeEffectRuntime = yield* pipe(
|
|
38546
|
+
typeParser.isNodeReferenceToEffectModuleApi("runtime")(yieldedExpression.expression),
|
|
38547
|
+
option5
|
|
38548
|
+
);
|
|
38549
|
+
if (isSome2(maybeEffectRuntime) && ts.isIdentifier(declaration.name)) {
|
|
38550
|
+
runtimeIdentifier = ts.idText(declaration.name);
|
|
38207
38551
|
}
|
|
38208
38552
|
}
|
|
38209
38553
|
}
|
|
38210
38554
|
}
|
|
38211
|
-
|
|
38212
|
-
|
|
38213
|
-
|
|
38214
|
-
|
|
38215
|
-
|
|
38555
|
+
}
|
|
38556
|
+
if (!runtimeIdentifier) {
|
|
38557
|
+
changeTracker.insertNodeAt(
|
|
38558
|
+
sourceFile,
|
|
38559
|
+
effectGen.body.statements[0].pos,
|
|
38560
|
+
ts.factory.createVariableStatement(
|
|
38561
|
+
void 0,
|
|
38562
|
+
ts.factory.createVariableDeclarationList([ts.factory.createVariableDeclaration(
|
|
38563
|
+
"effectRuntime",
|
|
38216
38564
|
void 0,
|
|
38217
|
-
|
|
38218
|
-
|
|
38219
|
-
|
|
38220
|
-
|
|
38221
|
-
|
|
38222
|
-
|
|
38223
|
-
|
|
38224
|
-
|
|
38225
|
-
|
|
38226
|
-
|
|
38227
|
-
),
|
|
38228
|
-
[ts.factory.createTypeReferenceNode("never")],
|
|
38229
|
-
[]
|
|
38230
|
-
)
|
|
38565
|
+
void 0,
|
|
38566
|
+
ts.factory.createYieldExpression(
|
|
38567
|
+
ts.factory.createToken(ts.SyntaxKind.AsteriskToken),
|
|
38568
|
+
ts.factory.createCallExpression(
|
|
38569
|
+
ts.factory.createPropertyAccessExpression(
|
|
38570
|
+
ts.factory.createIdentifier(effectModuleIdentifier),
|
|
38571
|
+
"runtime"
|
|
38572
|
+
),
|
|
38573
|
+
[ts.factory.createTypeReferenceNode("never")],
|
|
38574
|
+
[]
|
|
38231
38575
|
)
|
|
38232
|
-
)
|
|
38233
|
-
),
|
|
38234
|
-
|
|
38235
|
-
|
|
38236
|
-
|
|
38237
|
-
|
|
38238
|
-
|
|
38239
|
-
}
|
|
38240
|
-
changeTracker.deleteRange(sourceFile, {
|
|
38241
|
-
pos: ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
38242
|
-
end: node.arguments[0].pos
|
|
38243
|
-
});
|
|
38244
|
-
changeTracker.insertText(
|
|
38245
|
-
sourceFile,
|
|
38246
|
-
node.arguments[0].pos,
|
|
38247
|
-
`${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
|
|
38576
|
+
)
|
|
38577
|
+
)], ts.NodeFlags.Const)
|
|
38578
|
+
),
|
|
38579
|
+
{
|
|
38580
|
+
prefix: "\n",
|
|
38581
|
+
suffix: "\n"
|
|
38582
|
+
}
|
|
38248
38583
|
);
|
|
38584
|
+
}
|
|
38585
|
+
changeTracker.deleteRange(sourceFile, {
|
|
38586
|
+
pos: ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
38587
|
+
end: node.arguments[0].pos
|
|
38249
38588
|
});
|
|
38250
|
-
|
|
38251
|
-
|
|
38252
|
-
|
|
38589
|
+
changeTracker.insertText(
|
|
38590
|
+
sourceFile,
|
|
38591
|
+
node.arguments[0].pos,
|
|
38592
|
+
`${runtimeModuleIdentifier}.${isEffectRunCall.value.methodName}(${runtimeIdentifier || "effectRuntime"}, `
|
|
38593
|
+
);
|
|
38594
|
+
});
|
|
38595
|
+
report({
|
|
38596
|
+
location: node.expression,
|
|
38597
|
+
messageText: `Using ${nodeText} inside an Effect is not recommended. The same runtime should generally be used instead to run child effects.
|
|
38253
38598
|
Consider extracting the Runtime by using for example Effect.runtime and then use Runtime.${isEffectRunCall.value.methodName} with the extracted runtime instead.`,
|
|
38254
|
-
|
|
38255
|
-
|
|
38256
|
-
|
|
38257
|
-
|
|
38258
|
-
|
|
38259
|
-
|
|
38260
|
-
|
|
38261
|
-
|
|
38262
|
-
|
|
38263
|
-
|
|
38264
|
-
|
|
38265
|
-
|
|
38266
|
-
}
|
|
38599
|
+
fixes: [{
|
|
38600
|
+
fixName: "runEffectInsideEffect_fix",
|
|
38601
|
+
description: "Use a runtime to run the Effect",
|
|
38602
|
+
apply: fixAddRuntime
|
|
38603
|
+
}]
|
|
38604
|
+
});
|
|
38605
|
+
} else {
|
|
38606
|
+
report({
|
|
38607
|
+
location: node.expression,
|
|
38608
|
+
messageText: `Using ${nodeText} inside an Effect is not recommended. Effects inside generators can usually just be yielded.`,
|
|
38609
|
+
fixes: []
|
|
38610
|
+
});
|
|
38267
38611
|
}
|
|
38268
|
-
currentParent = currentParent.parent;
|
|
38269
38612
|
}
|
|
38270
38613
|
}
|
|
38271
38614
|
})
|
|
@@ -38351,6 +38694,59 @@ var schemaStructWithTag = createDiagnostic({
|
|
|
38351
38694
|
})
|
|
38352
38695
|
});
|
|
38353
38696
|
|
|
38697
|
+
// src/diagnostics/schemaSyncInEffect.ts
|
|
38698
|
+
var syncToEffectMethod = {
|
|
38699
|
+
decodeSync: "decode",
|
|
38700
|
+
decodeUnknownSync: "decodeUnknown",
|
|
38701
|
+
encodeSync: "encode",
|
|
38702
|
+
encodeUnknownSync: "encodeUnknown"
|
|
38703
|
+
};
|
|
38704
|
+
var schemaSyncInEffect = createDiagnostic({
|
|
38705
|
+
name: "schemaSyncInEffect",
|
|
38706
|
+
code: 43,
|
|
38707
|
+
description: "Suggests using Effect-based Schema methods instead of sync methods inside Effect generators",
|
|
38708
|
+
severity: "suggestion",
|
|
38709
|
+
apply: fn2("schemaSyncInEffect.apply")(function* (sourceFile, report) {
|
|
38710
|
+
const ts = yield* service2(TypeScriptApi);
|
|
38711
|
+
const typeParser = yield* service2(TypeParser);
|
|
38712
|
+
const parseSchemaSyncMethod = (node, methodName) => pipe(
|
|
38713
|
+
typeParser.isNodeReferenceToEffectParseResultModuleApi(methodName)(node),
|
|
38714
|
+
map34(() => ({ node, methodName }))
|
|
38715
|
+
);
|
|
38716
|
+
const nodeToVisit = [];
|
|
38717
|
+
const appendNodeToVisit = (node) => {
|
|
38718
|
+
nodeToVisit.push(node);
|
|
38719
|
+
return void 0;
|
|
38720
|
+
};
|
|
38721
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
38722
|
+
while (nodeToVisit.length > 0) {
|
|
38723
|
+
const node = nodeToVisit.shift();
|
|
38724
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
38725
|
+
if (!ts.isCallExpression(node)) continue;
|
|
38726
|
+
const isSchemaSyncCall = yield* pipe(
|
|
38727
|
+
firstSuccessOf2(
|
|
38728
|
+
Object.keys(syncToEffectMethod).map((methodName) => parseSchemaSyncMethod(node.expression, methodName))
|
|
38729
|
+
),
|
|
38730
|
+
option5
|
|
38731
|
+
);
|
|
38732
|
+
if (isNone2(isSchemaSyncCall)) continue;
|
|
38733
|
+
const { effectGen, scopeNode } = yield* typeParser.findEnclosingScopes(node);
|
|
38734
|
+
if (!effectGen || effectGen.body.statements.length === 0) continue;
|
|
38735
|
+
if (scopeNode && scopeNode !== effectGen.generatorFunction) continue;
|
|
38736
|
+
const nodeText = sourceFile.text.substring(
|
|
38737
|
+
ts.getTokenPosOfNode(node.expression, sourceFile),
|
|
38738
|
+
node.expression.end
|
|
38739
|
+
);
|
|
38740
|
+
const effectMethodName = syncToEffectMethod[isSchemaSyncCall.value.methodName];
|
|
38741
|
+
report({
|
|
38742
|
+
location: node.expression,
|
|
38743
|
+
messageText: `Using ${nodeText} inside an Effect generator is not recommended. Use Schema.${effectMethodName} instead to get properly typed ParseError in the error channel.`,
|
|
38744
|
+
fixes: []
|
|
38745
|
+
});
|
|
38746
|
+
}
|
|
38747
|
+
})
|
|
38748
|
+
});
|
|
38749
|
+
|
|
38354
38750
|
// src/diagnostics/schemaUnionOfLiterals.ts
|
|
38355
38751
|
var schemaUnionOfLiterals = createDiagnostic({
|
|
38356
38752
|
name: "schemaUnionOfLiterals",
|
|
@@ -39065,7 +39461,9 @@ var diagnostics = [
|
|
|
39065
39461
|
layerMergeAllWithDependencies,
|
|
39066
39462
|
effectMapVoid,
|
|
39067
39463
|
effectFnOpportunity,
|
|
39068
|
-
redundantSchemaTagIdentifier
|
|
39464
|
+
redundantSchemaTagIdentifier,
|
|
39465
|
+
schemaSyncInEffect,
|
|
39466
|
+
preferSchemaOverJson
|
|
39069
39467
|
];
|
|
39070
39468
|
|
|
39071
39469
|
// src/cli/diagnostics.ts
|
|
@@ -39991,7 +40389,7 @@ var collectSourceFileExportedSymbols = (sourceFile, tsInstance, typeChecker, max
|
|
|
39991
40389
|
}
|
|
39992
40390
|
const exports2 = typeChecker.getExportsOfModule(moduleSymbol);
|
|
39993
40391
|
const workQueue = exports2.map((s) => {
|
|
39994
|
-
const declarations = s.
|
|
40392
|
+
const declarations = s.declarations;
|
|
39995
40393
|
const location = declarations && declarations.length > 0 ? getLocationFromDeclaration(declarations[0], tsInstance) : void 0;
|
|
39996
40394
|
return [s, tsInstance.symbolName(s), location, 0];
|
|
39997
40395
|
});
|
|
@@ -40153,7 +40551,7 @@ function collectExportedItems(sourceFile, tsInstance, typeChecker, maxSymbolDept
|
|
|
40153
40551
|
maxSymbolDepth
|
|
40154
40552
|
);
|
|
40155
40553
|
for (const { description, location, name, symbol: symbol3, type: type2 } of exportedSymbols) {
|
|
40156
|
-
const declarations = symbol3.
|
|
40554
|
+
const declarations = symbol3.declarations;
|
|
40157
40555
|
const declaration = declarations && declarations.length > 0 ? declarations[0] : sourceFile;
|
|
40158
40556
|
const contextTagResult = yield* pipe(
|
|
40159
40557
|
typeParser.contextTag(type2, declaration),
|
|
@@ -40971,6 +41369,523 @@ var patch9 = make58(
|
|
|
40971
41369
|
)
|
|
40972
41370
|
);
|
|
40973
41371
|
|
|
41372
|
+
// src/cli/quickfixes.ts
|
|
41373
|
+
var import_project_service5 = __toESM(require_dist2());
|
|
41374
|
+
|
|
41375
|
+
// src/cli/setup/text-diff-renderer.ts
|
|
41376
|
+
function getLines(text10) {
|
|
41377
|
+
return text10.split("\n");
|
|
41378
|
+
}
|
|
41379
|
+
function getLineAndCharacterOfPosition(text10, position) {
|
|
41380
|
+
const lines3 = text10.split("\n");
|
|
41381
|
+
let currentPos = 0;
|
|
41382
|
+
for (let lineIndex = 0; lineIndex < lines3.length; lineIndex++) {
|
|
41383
|
+
const lineLength = lines3[lineIndex].length;
|
|
41384
|
+
const lineEndPos = currentPos + lineLength;
|
|
41385
|
+
if (position <= lineEndPos) {
|
|
41386
|
+
return { line: lineIndex, character: position - currentPos };
|
|
41387
|
+
}
|
|
41388
|
+
currentPos = lineEndPos + 1;
|
|
41389
|
+
}
|
|
41390
|
+
const lastLineIndex = lines3.length - 1;
|
|
41391
|
+
return { line: lastLineIndex, character: lines3[lastLineIndex]?.length ?? 0 };
|
|
41392
|
+
}
|
|
41393
|
+
function renderLine(lineNum, symbol3, text10, color3) {
|
|
41394
|
+
const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
|
|
41395
|
+
return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
|
|
41396
|
+
}
|
|
41397
|
+
function renderPlainTextChange(text10, textChange) {
|
|
41398
|
+
const startPos = textChange.span.start;
|
|
41399
|
+
const endPos = textChange.span.start + textChange.span.length;
|
|
41400
|
+
const startLineAndChar = getLineAndCharacterOfPosition(text10, startPos);
|
|
41401
|
+
const endLineAndChar = getLineAndCharacterOfPosition(text10, endPos);
|
|
41402
|
+
const startLine = startLineAndChar.line;
|
|
41403
|
+
const endLine = endLineAndChar.line;
|
|
41404
|
+
const startCol = startLineAndChar.character;
|
|
41405
|
+
const endCol = endLineAndChar.character;
|
|
41406
|
+
const lines3 = [];
|
|
41407
|
+
const allLines = getLines(text10);
|
|
41408
|
+
if (startLine > 0) {
|
|
41409
|
+
const contextBefore = allLines[startLine - 1];
|
|
41410
|
+
lines3.push(renderLine(startLine, "|", contextBefore, blackBright2));
|
|
41411
|
+
}
|
|
41412
|
+
if (startLine <= endLine) {
|
|
41413
|
+
const firstLineText = allLines[startLine];
|
|
41414
|
+
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
41415
|
+
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
41416
|
+
if (hasNonWhitespaceKept) {
|
|
41417
|
+
lines3.push(renderLine(startLine + 1, "|", keptBeforeDeletion, blackBright2));
|
|
41418
|
+
}
|
|
41419
|
+
const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
|
|
41420
|
+
if (deletedOnFirstLine.length > 0) {
|
|
41421
|
+
const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
|
|
41422
|
+
lines3.push(renderLine(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
|
|
41423
|
+
}
|
|
41424
|
+
}
|
|
41425
|
+
for (let i = startLine + 1; i < endLine; i++) {
|
|
41426
|
+
const lineText = allLines[i];
|
|
41427
|
+
if (lineText !== void 0) {
|
|
41428
|
+
lines3.push(renderLine(void 0, "-", lineText, red4));
|
|
41429
|
+
}
|
|
41430
|
+
}
|
|
41431
|
+
if (endLine > startLine) {
|
|
41432
|
+
const lastLineText = allLines[endLine];
|
|
41433
|
+
const deletedOnLastLine = lastLineText.slice(0, endCol);
|
|
41434
|
+
if (deletedOnLastLine.length > 0) {
|
|
41435
|
+
lines3.push(renderLine(void 0, "-", deletedOnLastLine, red4));
|
|
41436
|
+
}
|
|
41437
|
+
}
|
|
41438
|
+
if (textChange.newText.length > 0) {
|
|
41439
|
+
const newTextLines = textChange.newText.split("\n");
|
|
41440
|
+
const firstLineText = allLines[startLine];
|
|
41441
|
+
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
41442
|
+
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
41443
|
+
const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
|
|
41444
|
+
for (let i = 0; i < newTextLines.length; i++) {
|
|
41445
|
+
const newLine = newTextLines[i];
|
|
41446
|
+
if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
|
|
41447
|
+
continue;
|
|
41448
|
+
}
|
|
41449
|
+
const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
|
|
41450
|
+
lines3.push(renderLine(void 0, "+", `${padding}${newLine}`, green3));
|
|
41451
|
+
}
|
|
41452
|
+
}
|
|
41453
|
+
let alignmentForKeptPart = 0;
|
|
41454
|
+
if (textChange.newText.length > 0) {
|
|
41455
|
+
const newTextLines = textChange.newText.split("\n");
|
|
41456
|
+
const lastNewLine = newTextLines[newTextLines.length - 1];
|
|
41457
|
+
if (lastNewLine.length === 0 && newTextLines.length > 1) {
|
|
41458
|
+
alignmentForKeptPart = 0;
|
|
41459
|
+
} else {
|
|
41460
|
+
const firstLineText = allLines[startLine];
|
|
41461
|
+
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
41462
|
+
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
41463
|
+
if (hasNonWhitespaceKept) {
|
|
41464
|
+
if (newTextLines.length === 1) {
|
|
41465
|
+
alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
|
|
41466
|
+
} else {
|
|
41467
|
+
alignmentForKeptPart = lastNewLine.length;
|
|
41468
|
+
}
|
|
41469
|
+
} else {
|
|
41470
|
+
alignmentForKeptPart = lastNewLine.length;
|
|
41471
|
+
}
|
|
41472
|
+
}
|
|
41473
|
+
} else {
|
|
41474
|
+
alignmentForKeptPart = endCol;
|
|
41475
|
+
}
|
|
41476
|
+
if (endLine > startLine) {
|
|
41477
|
+
const lastLineText = allLines[endLine];
|
|
41478
|
+
const keptAfterDeletion = lastLineText.slice(endCol);
|
|
41479
|
+
if (keptAfterDeletion.trim().length > 0) {
|
|
41480
|
+
const alignment = " ".repeat(alignmentForKeptPart);
|
|
41481
|
+
lines3.push(renderLine(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
|
|
41482
|
+
}
|
|
41483
|
+
} else if (startLine === endLine) {
|
|
41484
|
+
const firstLineText = allLines[startLine];
|
|
41485
|
+
const keptAfterDeletion = firstLineText.slice(endCol);
|
|
41486
|
+
if (keptAfterDeletion.trim().length > 0) {
|
|
41487
|
+
const alignment = " ".repeat(alignmentForKeptPart);
|
|
41488
|
+
lines3.push(renderLine(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
|
|
41489
|
+
}
|
|
41490
|
+
}
|
|
41491
|
+
if (endLine + 1 < allLines.length) {
|
|
41492
|
+
const contextAfter = allLines[endLine + 1];
|
|
41493
|
+
lines3.push(renderLine(endLine + 2, "|", contextAfter, blackBright2));
|
|
41494
|
+
}
|
|
41495
|
+
return lines3;
|
|
41496
|
+
}
|
|
41497
|
+
function renderPlainTextFileChanges(text10, textChanges) {
|
|
41498
|
+
const lines3 = [];
|
|
41499
|
+
const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
|
|
41500
|
+
for (let i = 0; i < sortedChanges.length; i++) {
|
|
41501
|
+
const change = sortedChanges[i];
|
|
41502
|
+
const changeLines = renderPlainTextChange(text10, change);
|
|
41503
|
+
for (const line4 of changeLines) {
|
|
41504
|
+
lines3.push(line4);
|
|
41505
|
+
}
|
|
41506
|
+
if (i < sortedChanges.length - 1) {
|
|
41507
|
+
lines3.push(text3(""));
|
|
41508
|
+
}
|
|
41509
|
+
}
|
|
41510
|
+
return lines3;
|
|
41511
|
+
}
|
|
41512
|
+
|
|
41513
|
+
// src/cli/setup/diff-renderer.ts
|
|
41514
|
+
function getLines2(text10) {
|
|
41515
|
+
return text10.split("\n");
|
|
41516
|
+
}
|
|
41517
|
+
function renderLine2(lineNum, symbol3, text10, color3) {
|
|
41518
|
+
const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
|
|
41519
|
+
return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
|
|
41520
|
+
}
|
|
41521
|
+
function renderTextChange(sourceFile, textChange) {
|
|
41522
|
+
const startPos = textChange.span.start;
|
|
41523
|
+
const endPos = textChange.span.start + textChange.span.length;
|
|
41524
|
+
const startLineAndChar = sourceFile.getLineAndCharacterOfPosition(startPos);
|
|
41525
|
+
const endLineAndChar = sourceFile.getLineAndCharacterOfPosition(endPos);
|
|
41526
|
+
const startLine = startLineAndChar.line;
|
|
41527
|
+
const endLine = endLineAndChar.line;
|
|
41528
|
+
const startCol = startLineAndChar.character;
|
|
41529
|
+
const endCol = endLineAndChar.character;
|
|
41530
|
+
const lines3 = [];
|
|
41531
|
+
const allLines = getLines2(sourceFile.text);
|
|
41532
|
+
if (startLine > 0) {
|
|
41533
|
+
const contextBefore = allLines[startLine - 1];
|
|
41534
|
+
lines3.push(renderLine2(startLine, "|", contextBefore, blackBright2));
|
|
41535
|
+
}
|
|
41536
|
+
if (startLine <= endLine) {
|
|
41537
|
+
const firstLineText = allLines[startLine];
|
|
41538
|
+
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
41539
|
+
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
41540
|
+
if (hasNonWhitespaceKept) {
|
|
41541
|
+
lines3.push(renderLine2(startLine + 1, "|", keptBeforeDeletion, blackBright2));
|
|
41542
|
+
}
|
|
41543
|
+
const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
|
|
41544
|
+
if (deletedOnFirstLine.length > 0) {
|
|
41545
|
+
const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
|
|
41546
|
+
lines3.push(renderLine2(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
|
|
41547
|
+
}
|
|
41548
|
+
}
|
|
41549
|
+
for (let i = startLine + 1; i < endLine; i++) {
|
|
41550
|
+
const lineText = allLines[i];
|
|
41551
|
+
if (lineText !== void 0) {
|
|
41552
|
+
lines3.push(renderLine2(void 0, "-", lineText, red4));
|
|
41553
|
+
}
|
|
41554
|
+
}
|
|
41555
|
+
if (endLine > startLine) {
|
|
41556
|
+
const lastLineText = allLines[endLine];
|
|
41557
|
+
const deletedOnLastLine = lastLineText.slice(0, endCol);
|
|
41558
|
+
if (deletedOnLastLine.length > 0) {
|
|
41559
|
+
lines3.push(renderLine2(void 0, "-", deletedOnLastLine, red4));
|
|
41560
|
+
}
|
|
41561
|
+
}
|
|
41562
|
+
if (textChange.newText.length > 0) {
|
|
41563
|
+
const newTextLines = textChange.newText.split("\n");
|
|
41564
|
+
const firstLineText = allLines[startLine];
|
|
41565
|
+
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
41566
|
+
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
41567
|
+
const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
|
|
41568
|
+
for (let i = 0; i < newTextLines.length; i++) {
|
|
41569
|
+
const newLine = newTextLines[i];
|
|
41570
|
+
if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
|
|
41571
|
+
continue;
|
|
41572
|
+
}
|
|
41573
|
+
const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
|
|
41574
|
+
lines3.push(renderLine2(void 0, "+", `${padding}${newLine}`, green3));
|
|
41575
|
+
}
|
|
41576
|
+
}
|
|
41577
|
+
let alignmentForKeptPart = 0;
|
|
41578
|
+
if (textChange.newText.length > 0) {
|
|
41579
|
+
const newTextLines = textChange.newText.split("\n");
|
|
41580
|
+
const lastNewLine = newTextLines[newTextLines.length - 1];
|
|
41581
|
+
if (lastNewLine.length === 0 && newTextLines.length > 1) {
|
|
41582
|
+
alignmentForKeptPart = 0;
|
|
41583
|
+
} else {
|
|
41584
|
+
const firstLineText = allLines[startLine];
|
|
41585
|
+
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
41586
|
+
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
41587
|
+
if (hasNonWhitespaceKept) {
|
|
41588
|
+
if (newTextLines.length === 1) {
|
|
41589
|
+
alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
|
|
41590
|
+
} else {
|
|
41591
|
+
alignmentForKeptPart = lastNewLine.length;
|
|
41592
|
+
}
|
|
41593
|
+
} else {
|
|
41594
|
+
alignmentForKeptPart = lastNewLine.length;
|
|
41595
|
+
}
|
|
41596
|
+
}
|
|
41597
|
+
} else {
|
|
41598
|
+
alignmentForKeptPart = endCol;
|
|
41599
|
+
}
|
|
41600
|
+
if (endLine > startLine) {
|
|
41601
|
+
const lastLineText = allLines[endLine];
|
|
41602
|
+
const keptAfterDeletion = lastLineText.slice(endCol);
|
|
41603
|
+
if (keptAfterDeletion.trim().length > 0) {
|
|
41604
|
+
const alignment = " ".repeat(alignmentForKeptPart);
|
|
41605
|
+
lines3.push(renderLine2(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
|
|
41606
|
+
}
|
|
41607
|
+
} else if (startLine === endLine) {
|
|
41608
|
+
const firstLineText = allLines[startLine];
|
|
41609
|
+
const keptAfterDeletion = firstLineText.slice(endCol);
|
|
41610
|
+
if (keptAfterDeletion.trim().length > 0) {
|
|
41611
|
+
const alignment = " ".repeat(alignmentForKeptPart);
|
|
41612
|
+
lines3.push(renderLine2(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
|
|
41613
|
+
}
|
|
41614
|
+
}
|
|
41615
|
+
if (endLine + 1 < allLines.length) {
|
|
41616
|
+
const contextAfter = allLines[endLine + 1];
|
|
41617
|
+
lines3.push(renderLine2(endLine + 2, "|", contextAfter, blackBright2));
|
|
41618
|
+
}
|
|
41619
|
+
return lines3;
|
|
41620
|
+
}
|
|
41621
|
+
function renderFileChanges(sourceFile, textChanges) {
|
|
41622
|
+
const lines3 = [];
|
|
41623
|
+
const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
|
|
41624
|
+
for (let i = 0; i < sortedChanges.length; i++) {
|
|
41625
|
+
const change = sortedChanges[i];
|
|
41626
|
+
const changeLines = renderTextChange(sourceFile, change);
|
|
41627
|
+
for (const line4 of changeLines) {
|
|
41628
|
+
lines3.push(line4);
|
|
41629
|
+
}
|
|
41630
|
+
if (i < sortedChanges.length - 1) {
|
|
41631
|
+
lines3.push(text3(""));
|
|
41632
|
+
}
|
|
41633
|
+
}
|
|
41634
|
+
return lines3;
|
|
41635
|
+
}
|
|
41636
|
+
var renderCodeActions = (result, assessmentState) => gen2(function* () {
|
|
41637
|
+
if (result.codeActions.length === 0) {
|
|
41638
|
+
const noChanges = annotate2(
|
|
41639
|
+
text3("No changes needed - your configuration is already up to date!"),
|
|
41640
|
+
green3
|
|
41641
|
+
);
|
|
41642
|
+
const noChangesStr = noChanges.pipe(render3({ style: "pretty" }));
|
|
41643
|
+
yield* log3(noChangesStr);
|
|
41644
|
+
return;
|
|
41645
|
+
}
|
|
41646
|
+
const sourceFiles = [
|
|
41647
|
+
assessmentState.packageJson.sourceFile,
|
|
41648
|
+
assessmentState.tsconfig.sourceFile
|
|
41649
|
+
];
|
|
41650
|
+
if (isSome2(assessmentState.vscodeSettings)) {
|
|
41651
|
+
sourceFiles.push(assessmentState.vscodeSettings.value.sourceFile);
|
|
41652
|
+
}
|
|
41653
|
+
const plainTextFiles = [];
|
|
41654
|
+
if (isSome2(assessmentState.agentsMd)) {
|
|
41655
|
+
plainTextFiles.push({
|
|
41656
|
+
path: assessmentState.agentsMd.value.path,
|
|
41657
|
+
text: assessmentState.agentsMd.value.text
|
|
41658
|
+
});
|
|
41659
|
+
}
|
|
41660
|
+
if (isSome2(assessmentState.claudeMd)) {
|
|
41661
|
+
plainTextFiles.push({
|
|
41662
|
+
path: assessmentState.claudeMd.value.path,
|
|
41663
|
+
text: assessmentState.claudeMd.value.text
|
|
41664
|
+
});
|
|
41665
|
+
}
|
|
41666
|
+
for (const codeAction of result.codeActions) {
|
|
41667
|
+
for (const fileChange of codeAction.changes) {
|
|
41668
|
+
const sourceFile = sourceFiles.find((sf) => sf.fileName === fileChange.fileName);
|
|
41669
|
+
const plainTextFile = plainTextFiles.find((pf) => pf.path === fileChange.fileName);
|
|
41670
|
+
const header = vsep2([
|
|
41671
|
+
empty32,
|
|
41672
|
+
annotate2(text3(codeAction.description), bold2),
|
|
41673
|
+
annotate2(text3(fileChange.fileName), cyan4),
|
|
41674
|
+
empty32
|
|
41675
|
+
]);
|
|
41676
|
+
const headerStr = header.pipe(render3({ style: "pretty" }));
|
|
41677
|
+
yield* log3(headerStr);
|
|
41678
|
+
if (sourceFile) {
|
|
41679
|
+
const diffLines = renderFileChanges(sourceFile, fileChange.textChanges);
|
|
41680
|
+
const diff8 = vsep2(diffLines);
|
|
41681
|
+
const diffStr = diff8.pipe(render3({ style: "pretty" }));
|
|
41682
|
+
yield* log3(diffStr);
|
|
41683
|
+
} else if (plainTextFile) {
|
|
41684
|
+
const diffLines = renderPlainTextFileChanges(plainTextFile.text, fileChange.textChanges);
|
|
41685
|
+
const diff8 = vsep2(diffLines);
|
|
41686
|
+
const diffStr = diff8.pipe(render3({ style: "pretty" }));
|
|
41687
|
+
yield* log3(diffStr);
|
|
41688
|
+
} else {
|
|
41689
|
+
const noticeStr = text3(" (file will be modified)").pipe(render3({ style: "pretty" }));
|
|
41690
|
+
yield* log3(noticeStr);
|
|
41691
|
+
}
|
|
41692
|
+
}
|
|
41693
|
+
}
|
|
41694
|
+
if (result.messages.length > 0) {
|
|
41695
|
+
yield* log3("");
|
|
41696
|
+
for (const message of result.messages) {
|
|
41697
|
+
const messageDoc = message.includes("WARNING") ? annotate2(text3(message), yellow3) : text3(message);
|
|
41698
|
+
const messageStr = messageDoc.pipe(render3({ style: "pretty" }));
|
|
41699
|
+
yield* log3(messageStr);
|
|
41700
|
+
}
|
|
41701
|
+
}
|
|
41702
|
+
});
|
|
41703
|
+
|
|
41704
|
+
// src/cli/quickfixes.ts
|
|
41705
|
+
var isSkipFix = (fixName) => fixName.endsWith("_skipNextLine") || fixName.endsWith("_skipFile");
|
|
41706
|
+
var renderQuickFix = (sourceFile, fix) => {
|
|
41707
|
+
const lines3 = [];
|
|
41708
|
+
lines3.push(empty32);
|
|
41709
|
+
lines3.push(
|
|
41710
|
+
cat2(
|
|
41711
|
+
cat2(
|
|
41712
|
+
cat2(
|
|
41713
|
+
annotate2(text3(" Fix: "), bold2),
|
|
41714
|
+
annotate2(text3(fix.fixName), cyan4)
|
|
41715
|
+
),
|
|
41716
|
+
text3(" - ")
|
|
41717
|
+
),
|
|
41718
|
+
text3(fix.description)
|
|
41719
|
+
)
|
|
41720
|
+
);
|
|
41721
|
+
lines3.push(annotate2(text3(" " + "\u2500".repeat(60)), blackBright2));
|
|
41722
|
+
for (const fileChange of fix.changes) {
|
|
41723
|
+
if (fileChange.fileName === sourceFile.fileName) {
|
|
41724
|
+
for (const textChange of fileChange.textChanges) {
|
|
41725
|
+
const diffLines = renderTextChange(sourceFile, textChange);
|
|
41726
|
+
for (const diffLine of diffLines) {
|
|
41727
|
+
lines3.push(cat2(text3(" "), diffLine));
|
|
41728
|
+
}
|
|
41729
|
+
}
|
|
41730
|
+
}
|
|
41731
|
+
}
|
|
41732
|
+
return vsep2(lines3);
|
|
41733
|
+
};
|
|
41734
|
+
var renderDiagnosticWithFixes = (sourceFile, info2, tsInstance) => {
|
|
41735
|
+
const lines3 = [];
|
|
41736
|
+
const { character, line: line4 } = tsInstance.getLineAndCharacterOfPosition(sourceFile, info2.diagnostic.start);
|
|
41737
|
+
const locationStr = `${sourceFile.fileName}:${line4 + 1}:${character + 1}`;
|
|
41738
|
+
lines3.push(
|
|
41739
|
+
cat2(
|
|
41740
|
+
cat2(
|
|
41741
|
+
cat2(
|
|
41742
|
+
cat2(
|
|
41743
|
+
annotate2(text3(locationStr), cyan4),
|
|
41744
|
+
text3(" ")
|
|
41745
|
+
),
|
|
41746
|
+
annotate2(text3(`effect(${info2.diagnostic.ruleName})`), yellow3)
|
|
41747
|
+
),
|
|
41748
|
+
text3(": ")
|
|
41749
|
+
),
|
|
41750
|
+
text3(info2.diagnostic.messageText)
|
|
41751
|
+
)
|
|
41752
|
+
);
|
|
41753
|
+
for (const fix of info2.fixes) {
|
|
41754
|
+
lines3.push(renderQuickFix(sourceFile, fix));
|
|
41755
|
+
}
|
|
41756
|
+
lines3.push(empty32);
|
|
41757
|
+
return vsep2(lines3);
|
|
41758
|
+
};
|
|
41759
|
+
var BATCH_SIZE4 = 50;
|
|
41760
|
+
var quickfixes = make58(
|
|
41761
|
+
"quickfixes",
|
|
41762
|
+
{
|
|
41763
|
+
file: file3("file").pipe(
|
|
41764
|
+
optional4,
|
|
41765
|
+
withDescription3("The full path of the file to check for quick fixes.")
|
|
41766
|
+
),
|
|
41767
|
+
project: file3("project").pipe(
|
|
41768
|
+
optional4,
|
|
41769
|
+
withDescription3("The full path of the project tsconfig.json file to check for quick fixes.")
|
|
41770
|
+
)
|
|
41771
|
+
},
|
|
41772
|
+
fn("quickfixes")(function* ({ file: file5, project: project3 }) {
|
|
41773
|
+
const path2 = yield* Path2;
|
|
41774
|
+
const tsInstance = yield* TypeScriptContext;
|
|
41775
|
+
const filesToCheck = isSome2(project3) ? yield* getFileNamesInTsConfig(project3.value) : /* @__PURE__ */ new Set();
|
|
41776
|
+
if (isSome2(file5)) {
|
|
41777
|
+
filesToCheck.add(path2.resolve(file5.value));
|
|
41778
|
+
}
|
|
41779
|
+
if (filesToCheck.size === 0) {
|
|
41780
|
+
return yield* new NoFilesToCheckError();
|
|
41781
|
+
}
|
|
41782
|
+
let totalDiagnosticsWithFixes = 0;
|
|
41783
|
+
for (const batch of chunksOf(filesToCheck, BATCH_SIZE4)) {
|
|
41784
|
+
const { service: service3 } = (0, import_project_service5.createProjectService)({ options: { loadTypeScriptPlugins: false } });
|
|
41785
|
+
for (const filePath of batch) {
|
|
41786
|
+
service3.openClientFile(filePath);
|
|
41787
|
+
try {
|
|
41788
|
+
const scriptInfo = service3.getScriptInfo(filePath);
|
|
41789
|
+
if (!scriptInfo) continue;
|
|
41790
|
+
const projectInfo = scriptInfo.getDefaultProject();
|
|
41791
|
+
const languageService = projectInfo.getLanguageService(true);
|
|
41792
|
+
const program = languageService.getProgram();
|
|
41793
|
+
if (!program) continue;
|
|
41794
|
+
const sourceFile = program.getSourceFile(filePath);
|
|
41795
|
+
if (!sourceFile) continue;
|
|
41796
|
+
const pluginConfig = extractEffectLspOptions(program.getCompilerOptions());
|
|
41797
|
+
if (!pluginConfig) continue;
|
|
41798
|
+
const result = pipe(
|
|
41799
|
+
getSemanticDiagnosticsWithCodeFixes(diagnostics, sourceFile),
|
|
41800
|
+
nanoLayer3,
|
|
41801
|
+
nanoLayer2,
|
|
41802
|
+
nanoLayer,
|
|
41803
|
+
provideService7(TypeCheckerApi, program.getTypeChecker()),
|
|
41804
|
+
provideService7(TypeScriptProgram, program),
|
|
41805
|
+
provideService7(TypeScriptApi, tsInstance),
|
|
41806
|
+
provideService7(
|
|
41807
|
+
LanguageServicePluginOptions,
|
|
41808
|
+
{ ...parse4(pluginConfig), diagnosticsName: false }
|
|
41809
|
+
),
|
|
41810
|
+
run9,
|
|
41811
|
+
getOrElse(() => ({ diagnostics: [], codeFixes: [] }))
|
|
41812
|
+
);
|
|
41813
|
+
const diagnosticMap = /* @__PURE__ */ new Map();
|
|
41814
|
+
for (const diagnostic of result.diagnostics) {
|
|
41815
|
+
if (diagnostic.start === void 0) continue;
|
|
41816
|
+
const key = `${diagnostic.start}-${diagnostic.start + (diagnostic.length ?? 0)}-${diagnostic.code}`;
|
|
41817
|
+
const ruleName = Object.values(diagnostics).find((_) => _.code === diagnostic.code)?.name ?? `unknown(${diagnostic.code})`;
|
|
41818
|
+
if (!diagnosticMap.has(key)) {
|
|
41819
|
+
diagnosticMap.set(key, {
|
|
41820
|
+
diagnostic: {
|
|
41821
|
+
start: diagnostic.start,
|
|
41822
|
+
end: diagnostic.start + (diagnostic.length ?? 0),
|
|
41823
|
+
messageText: tsInstance.flattenDiagnosticMessageText(diagnostic.messageText, "\n"),
|
|
41824
|
+
code: diagnostic.code,
|
|
41825
|
+
ruleName
|
|
41826
|
+
},
|
|
41827
|
+
fixes: []
|
|
41828
|
+
});
|
|
41829
|
+
}
|
|
41830
|
+
}
|
|
41831
|
+
const formatContext = tsInstance.formatting.getFormatContext(
|
|
41832
|
+
tsInstance.getDefaultFormatCodeSettings(),
|
|
41833
|
+
{ getNewLine: () => "\n" }
|
|
41834
|
+
);
|
|
41835
|
+
for (const codeFix of result.codeFixes) {
|
|
41836
|
+
if (isSkipFix(codeFix.fixName)) continue;
|
|
41837
|
+
const key = `${codeFix.start}-${codeFix.end}-${codeFix.code}`;
|
|
41838
|
+
const info2 = diagnosticMap.get(key);
|
|
41839
|
+
if (!info2) continue;
|
|
41840
|
+
const changes2 = tsInstance.textChanges.ChangeTracker.with(
|
|
41841
|
+
{
|
|
41842
|
+
formatContext,
|
|
41843
|
+
host: { getNewLine: () => "\n" },
|
|
41844
|
+
preferences: {}
|
|
41845
|
+
},
|
|
41846
|
+
(changeTracker) => pipe(
|
|
41847
|
+
codeFix.apply,
|
|
41848
|
+
provideService7(ChangeTracker, changeTracker),
|
|
41849
|
+
run9
|
|
41850
|
+
)
|
|
41851
|
+
);
|
|
41852
|
+
info2.fixes.push({
|
|
41853
|
+
fixName: codeFix.fixName,
|
|
41854
|
+
description: codeFix.description,
|
|
41855
|
+
changes: changes2
|
|
41856
|
+
});
|
|
41857
|
+
}
|
|
41858
|
+
const diagnosticsWithFixes = Array.from(diagnosticMap.values()).filter(
|
|
41859
|
+
(info2) => info2.fixes.length > 0
|
|
41860
|
+
);
|
|
41861
|
+
if (diagnosticsWithFixes.length === 0) continue;
|
|
41862
|
+
diagnosticsWithFixes.sort((a, b) => a.diagnostic.start - b.diagnostic.start);
|
|
41863
|
+
totalDiagnosticsWithFixes += diagnosticsWithFixes.length;
|
|
41864
|
+
for (const info2 of diagnosticsWithFixes) {
|
|
41865
|
+
const doc = renderDiagnosticWithFixes(sourceFile, info2, tsInstance);
|
|
41866
|
+
yield* log3(doc.pipe(render3({ style: "pretty" })));
|
|
41867
|
+
}
|
|
41868
|
+
} finally {
|
|
41869
|
+
service3.closeClientFile(filePath);
|
|
41870
|
+
}
|
|
41871
|
+
}
|
|
41872
|
+
yield* yieldNow4();
|
|
41873
|
+
}
|
|
41874
|
+
if (totalDiagnosticsWithFixes === 0) {
|
|
41875
|
+
yield* log3("No quick fixes available.");
|
|
41876
|
+
} else {
|
|
41877
|
+
yield* log3(
|
|
41878
|
+
annotate2(
|
|
41879
|
+
text3(`Found ${totalDiagnosticsWithFixes} diagnostic(s) with quick fixes.`),
|
|
41880
|
+
bold2
|
|
41881
|
+
).pipe(render3({ style: "pretty" }))
|
|
41882
|
+
);
|
|
41883
|
+
}
|
|
41884
|
+
})
|
|
41885
|
+
).pipe(
|
|
41886
|
+
withDescription6("Shows diagnostics with available quick fixes and their proposed changes.")
|
|
41887
|
+
);
|
|
41888
|
+
|
|
40974
41889
|
// node_modules/.pnpm/@effect+cli@0.73.0_@effect+platform@0.94.1_@effect+printer-ansi@0.47.0_@effect+printer@0.47.0_effect@3.19.14/node_modules/@effect/cli/dist/esm/internal/prompt/confirm.js
|
|
40975
41890
|
var renderBeep7 = /* @__PURE__ */ render3(beep3, {
|
|
40976
41891
|
style: "pretty"
|
|
@@ -42047,335 +42962,6 @@ var computeVSCodeSettingsChanges = (current, target) => {
|
|
|
42047
42962
|
});
|
|
42048
42963
|
};
|
|
42049
42964
|
|
|
42050
|
-
// src/cli/setup/text-diff-renderer.ts
|
|
42051
|
-
function getLines(text10) {
|
|
42052
|
-
return text10.split("\n");
|
|
42053
|
-
}
|
|
42054
|
-
function getLineAndCharacterOfPosition(text10, position) {
|
|
42055
|
-
const lines3 = text10.split("\n");
|
|
42056
|
-
let currentPos = 0;
|
|
42057
|
-
for (let lineIndex = 0; lineIndex < lines3.length; lineIndex++) {
|
|
42058
|
-
const lineLength = lines3[lineIndex].length;
|
|
42059
|
-
const lineEndPos = currentPos + lineLength;
|
|
42060
|
-
if (position <= lineEndPos) {
|
|
42061
|
-
return { line: lineIndex, character: position - currentPos };
|
|
42062
|
-
}
|
|
42063
|
-
currentPos = lineEndPos + 1;
|
|
42064
|
-
}
|
|
42065
|
-
const lastLineIndex = lines3.length - 1;
|
|
42066
|
-
return { line: lastLineIndex, character: lines3[lastLineIndex]?.length ?? 0 };
|
|
42067
|
-
}
|
|
42068
|
-
function renderLine(lineNum, symbol3, text10, color3) {
|
|
42069
|
-
const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
|
|
42070
|
-
return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
|
|
42071
|
-
}
|
|
42072
|
-
function renderPlainTextChange(text10, textChange) {
|
|
42073
|
-
const startPos = textChange.span.start;
|
|
42074
|
-
const endPos = textChange.span.start + textChange.span.length;
|
|
42075
|
-
const startLineAndChar = getLineAndCharacterOfPosition(text10, startPos);
|
|
42076
|
-
const endLineAndChar = getLineAndCharacterOfPosition(text10, endPos);
|
|
42077
|
-
const startLine = startLineAndChar.line;
|
|
42078
|
-
const endLine = endLineAndChar.line;
|
|
42079
|
-
const startCol = startLineAndChar.character;
|
|
42080
|
-
const endCol = endLineAndChar.character;
|
|
42081
|
-
const lines3 = [];
|
|
42082
|
-
const allLines = getLines(text10);
|
|
42083
|
-
if (startLine > 0) {
|
|
42084
|
-
const contextBefore = allLines[startLine - 1];
|
|
42085
|
-
lines3.push(renderLine(startLine, "|", contextBefore, blackBright2));
|
|
42086
|
-
}
|
|
42087
|
-
if (startLine <= endLine) {
|
|
42088
|
-
const firstLineText = allLines[startLine];
|
|
42089
|
-
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
42090
|
-
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
42091
|
-
if (hasNonWhitespaceKept) {
|
|
42092
|
-
lines3.push(renderLine(startLine + 1, "|", keptBeforeDeletion, blackBright2));
|
|
42093
|
-
}
|
|
42094
|
-
const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
|
|
42095
|
-
if (deletedOnFirstLine.length > 0) {
|
|
42096
|
-
const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
|
|
42097
|
-
lines3.push(renderLine(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
|
|
42098
|
-
}
|
|
42099
|
-
}
|
|
42100
|
-
for (let i = startLine + 1; i < endLine; i++) {
|
|
42101
|
-
const lineText = allLines[i];
|
|
42102
|
-
if (lineText !== void 0) {
|
|
42103
|
-
lines3.push(renderLine(void 0, "-", lineText, red4));
|
|
42104
|
-
}
|
|
42105
|
-
}
|
|
42106
|
-
if (endLine > startLine) {
|
|
42107
|
-
const lastLineText = allLines[endLine];
|
|
42108
|
-
const deletedOnLastLine = lastLineText.slice(0, endCol);
|
|
42109
|
-
if (deletedOnLastLine.length > 0) {
|
|
42110
|
-
lines3.push(renderLine(void 0, "-", deletedOnLastLine, red4));
|
|
42111
|
-
}
|
|
42112
|
-
}
|
|
42113
|
-
if (textChange.newText.length > 0) {
|
|
42114
|
-
const newTextLines = textChange.newText.split("\n");
|
|
42115
|
-
const firstLineText = allLines[startLine];
|
|
42116
|
-
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
42117
|
-
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
42118
|
-
const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
|
|
42119
|
-
for (let i = 0; i < newTextLines.length; i++) {
|
|
42120
|
-
const newLine = newTextLines[i];
|
|
42121
|
-
if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
|
|
42122
|
-
continue;
|
|
42123
|
-
}
|
|
42124
|
-
const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
|
|
42125
|
-
lines3.push(renderLine(void 0, "+", `${padding}${newLine}`, green3));
|
|
42126
|
-
}
|
|
42127
|
-
}
|
|
42128
|
-
let alignmentForKeptPart = 0;
|
|
42129
|
-
if (textChange.newText.length > 0) {
|
|
42130
|
-
const newTextLines = textChange.newText.split("\n");
|
|
42131
|
-
const lastNewLine = newTextLines[newTextLines.length - 1];
|
|
42132
|
-
if (lastNewLine.length === 0 && newTextLines.length > 1) {
|
|
42133
|
-
alignmentForKeptPart = 0;
|
|
42134
|
-
} else {
|
|
42135
|
-
const firstLineText = allLines[startLine];
|
|
42136
|
-
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
42137
|
-
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
42138
|
-
if (hasNonWhitespaceKept) {
|
|
42139
|
-
if (newTextLines.length === 1) {
|
|
42140
|
-
alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
|
|
42141
|
-
} else {
|
|
42142
|
-
alignmentForKeptPart = lastNewLine.length;
|
|
42143
|
-
}
|
|
42144
|
-
} else {
|
|
42145
|
-
alignmentForKeptPart = lastNewLine.length;
|
|
42146
|
-
}
|
|
42147
|
-
}
|
|
42148
|
-
} else {
|
|
42149
|
-
alignmentForKeptPart = endCol;
|
|
42150
|
-
}
|
|
42151
|
-
if (endLine > startLine) {
|
|
42152
|
-
const lastLineText = allLines[endLine];
|
|
42153
|
-
const keptAfterDeletion = lastLineText.slice(endCol);
|
|
42154
|
-
if (keptAfterDeletion.trim().length > 0) {
|
|
42155
|
-
const alignment = " ".repeat(alignmentForKeptPart);
|
|
42156
|
-
lines3.push(renderLine(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
|
|
42157
|
-
}
|
|
42158
|
-
} else if (startLine === endLine) {
|
|
42159
|
-
const firstLineText = allLines[startLine];
|
|
42160
|
-
const keptAfterDeletion = firstLineText.slice(endCol);
|
|
42161
|
-
if (keptAfterDeletion.trim().length > 0) {
|
|
42162
|
-
const alignment = " ".repeat(alignmentForKeptPart);
|
|
42163
|
-
lines3.push(renderLine(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
|
|
42164
|
-
}
|
|
42165
|
-
}
|
|
42166
|
-
if (endLine + 1 < allLines.length) {
|
|
42167
|
-
const contextAfter = allLines[endLine + 1];
|
|
42168
|
-
lines3.push(renderLine(endLine + 2, "|", contextAfter, blackBright2));
|
|
42169
|
-
}
|
|
42170
|
-
return lines3;
|
|
42171
|
-
}
|
|
42172
|
-
function renderPlainTextFileChanges(text10, textChanges) {
|
|
42173
|
-
const lines3 = [];
|
|
42174
|
-
const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
|
|
42175
|
-
for (let i = 0; i < sortedChanges.length; i++) {
|
|
42176
|
-
const change = sortedChanges[i];
|
|
42177
|
-
const changeLines = renderPlainTextChange(text10, change);
|
|
42178
|
-
for (const line4 of changeLines) {
|
|
42179
|
-
lines3.push(line4);
|
|
42180
|
-
}
|
|
42181
|
-
if (i < sortedChanges.length - 1) {
|
|
42182
|
-
lines3.push(text3(""));
|
|
42183
|
-
}
|
|
42184
|
-
}
|
|
42185
|
-
return lines3;
|
|
42186
|
-
}
|
|
42187
|
-
|
|
42188
|
-
// src/cli/setup/diff-renderer.ts
|
|
42189
|
-
function getLines2(text10) {
|
|
42190
|
-
return text10.split("\n");
|
|
42191
|
-
}
|
|
42192
|
-
function renderLine2(lineNum, symbol3, text10, color3) {
|
|
42193
|
-
const lineNumPart = lineNum !== void 0 ? String(lineNum).padStart(4, " ") : " ";
|
|
42194
|
-
return annotate2(text3(`${lineNumPart} ${symbol3} ${text10}`), color3);
|
|
42195
|
-
}
|
|
42196
|
-
function renderTextChange(sourceFile, textChange) {
|
|
42197
|
-
const startPos = textChange.span.start;
|
|
42198
|
-
const endPos = textChange.span.start + textChange.span.length;
|
|
42199
|
-
const startLineAndChar = sourceFile.getLineAndCharacterOfPosition(startPos);
|
|
42200
|
-
const endLineAndChar = sourceFile.getLineAndCharacterOfPosition(endPos);
|
|
42201
|
-
const startLine = startLineAndChar.line;
|
|
42202
|
-
const endLine = endLineAndChar.line;
|
|
42203
|
-
const startCol = startLineAndChar.character;
|
|
42204
|
-
const endCol = endLineAndChar.character;
|
|
42205
|
-
const lines3 = [];
|
|
42206
|
-
const allLines = getLines2(sourceFile.text);
|
|
42207
|
-
if (startLine > 0) {
|
|
42208
|
-
const contextBefore = allLines[startLine - 1];
|
|
42209
|
-
lines3.push(renderLine2(startLine, "|", contextBefore, blackBright2));
|
|
42210
|
-
}
|
|
42211
|
-
if (startLine <= endLine) {
|
|
42212
|
-
const firstLineText = allLines[startLine];
|
|
42213
|
-
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
42214
|
-
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
42215
|
-
if (hasNonWhitespaceKept) {
|
|
42216
|
-
lines3.push(renderLine2(startLine + 1, "|", keptBeforeDeletion, blackBright2));
|
|
42217
|
-
}
|
|
42218
|
-
const deletedOnFirstLine = startLine === endLine ? firstLineText.slice(startCol, endCol) : firstLineText.slice(startCol);
|
|
42219
|
-
if (deletedOnFirstLine.length > 0) {
|
|
42220
|
-
const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
|
|
42221
|
-
lines3.push(renderLine2(void 0, "-", `${spacePadding}${deletedOnFirstLine}`, red4));
|
|
42222
|
-
}
|
|
42223
|
-
}
|
|
42224
|
-
for (let i = startLine + 1; i < endLine; i++) {
|
|
42225
|
-
const lineText = allLines[i];
|
|
42226
|
-
if (lineText !== void 0) {
|
|
42227
|
-
lines3.push(renderLine2(void 0, "-", lineText, red4));
|
|
42228
|
-
}
|
|
42229
|
-
}
|
|
42230
|
-
if (endLine > startLine) {
|
|
42231
|
-
const lastLineText = allLines[endLine];
|
|
42232
|
-
const deletedOnLastLine = lastLineText.slice(0, endCol);
|
|
42233
|
-
if (deletedOnLastLine.length > 0) {
|
|
42234
|
-
lines3.push(renderLine2(void 0, "-", deletedOnLastLine, red4));
|
|
42235
|
-
}
|
|
42236
|
-
}
|
|
42237
|
-
if (textChange.newText.length > 0) {
|
|
42238
|
-
const newTextLines = textChange.newText.split("\n");
|
|
42239
|
-
const firstLineText = allLines[startLine];
|
|
42240
|
-
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
42241
|
-
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
42242
|
-
const spacePadding = hasNonWhitespaceKept ? " ".repeat(keptBeforeDeletion.length) : "";
|
|
42243
|
-
for (let i = 0; i < newTextLines.length; i++) {
|
|
42244
|
-
const newLine = newTextLines[i];
|
|
42245
|
-
if (i === newTextLines.length - 1 && newLine.length === 0 && newTextLines.length > 1) {
|
|
42246
|
-
continue;
|
|
42247
|
-
}
|
|
42248
|
-
const padding = i === 0 && hasNonWhitespaceKept ? spacePadding : "";
|
|
42249
|
-
lines3.push(renderLine2(void 0, "+", `${padding}${newLine}`, green3));
|
|
42250
|
-
}
|
|
42251
|
-
}
|
|
42252
|
-
let alignmentForKeptPart = 0;
|
|
42253
|
-
if (textChange.newText.length > 0) {
|
|
42254
|
-
const newTextLines = textChange.newText.split("\n");
|
|
42255
|
-
const lastNewLine = newTextLines[newTextLines.length - 1];
|
|
42256
|
-
if (lastNewLine.length === 0 && newTextLines.length > 1) {
|
|
42257
|
-
alignmentForKeptPart = 0;
|
|
42258
|
-
} else {
|
|
42259
|
-
const firstLineText = allLines[startLine];
|
|
42260
|
-
const keptBeforeDeletion = firstLineText.slice(0, startCol);
|
|
42261
|
-
const hasNonWhitespaceKept = keptBeforeDeletion.trim().length > 0;
|
|
42262
|
-
if (hasNonWhitespaceKept) {
|
|
42263
|
-
if (newTextLines.length === 1) {
|
|
42264
|
-
alignmentForKeptPart = keptBeforeDeletion.length + lastNewLine.length;
|
|
42265
|
-
} else {
|
|
42266
|
-
alignmentForKeptPart = lastNewLine.length;
|
|
42267
|
-
}
|
|
42268
|
-
} else {
|
|
42269
|
-
alignmentForKeptPart = lastNewLine.length;
|
|
42270
|
-
}
|
|
42271
|
-
}
|
|
42272
|
-
} else {
|
|
42273
|
-
alignmentForKeptPart = endCol;
|
|
42274
|
-
}
|
|
42275
|
-
if (endLine > startLine) {
|
|
42276
|
-
const lastLineText = allLines[endLine];
|
|
42277
|
-
const keptAfterDeletion = lastLineText.slice(endCol);
|
|
42278
|
-
if (keptAfterDeletion.trim().length > 0) {
|
|
42279
|
-
const alignment = " ".repeat(alignmentForKeptPart);
|
|
42280
|
-
lines3.push(renderLine2(endLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
|
|
42281
|
-
}
|
|
42282
|
-
} else if (startLine === endLine) {
|
|
42283
|
-
const firstLineText = allLines[startLine];
|
|
42284
|
-
const keptAfterDeletion = firstLineText.slice(endCol);
|
|
42285
|
-
if (keptAfterDeletion.trim().length > 0) {
|
|
42286
|
-
const alignment = " ".repeat(alignmentForKeptPart);
|
|
42287
|
-
lines3.push(renderLine2(startLine + 1, "|", `${alignment}${keptAfterDeletion}`, blackBright2));
|
|
42288
|
-
}
|
|
42289
|
-
}
|
|
42290
|
-
if (endLine + 1 < allLines.length) {
|
|
42291
|
-
const contextAfter = allLines[endLine + 1];
|
|
42292
|
-
lines3.push(renderLine2(endLine + 2, "|", contextAfter, blackBright2));
|
|
42293
|
-
}
|
|
42294
|
-
return lines3;
|
|
42295
|
-
}
|
|
42296
|
-
function renderFileChanges(sourceFile, textChanges) {
|
|
42297
|
-
const lines3 = [];
|
|
42298
|
-
const sortedChanges = [...textChanges].sort((a, b) => a.span.start - b.span.start);
|
|
42299
|
-
for (let i = 0; i < sortedChanges.length; i++) {
|
|
42300
|
-
const change = sortedChanges[i];
|
|
42301
|
-
const changeLines = renderTextChange(sourceFile, change);
|
|
42302
|
-
for (const line4 of changeLines) {
|
|
42303
|
-
lines3.push(line4);
|
|
42304
|
-
}
|
|
42305
|
-
if (i < sortedChanges.length - 1) {
|
|
42306
|
-
lines3.push(text3(""));
|
|
42307
|
-
}
|
|
42308
|
-
}
|
|
42309
|
-
return lines3;
|
|
42310
|
-
}
|
|
42311
|
-
var renderCodeActions = (result, assessmentState) => gen2(function* () {
|
|
42312
|
-
if (result.codeActions.length === 0) {
|
|
42313
|
-
const noChanges = annotate2(
|
|
42314
|
-
text3("No changes needed - your configuration is already up to date!"),
|
|
42315
|
-
green3
|
|
42316
|
-
);
|
|
42317
|
-
const noChangesStr = noChanges.pipe(render3({ style: "pretty" }));
|
|
42318
|
-
yield* log3(noChangesStr);
|
|
42319
|
-
return;
|
|
42320
|
-
}
|
|
42321
|
-
const sourceFiles = [
|
|
42322
|
-
assessmentState.packageJson.sourceFile,
|
|
42323
|
-
assessmentState.tsconfig.sourceFile
|
|
42324
|
-
];
|
|
42325
|
-
if (isSome2(assessmentState.vscodeSettings)) {
|
|
42326
|
-
sourceFiles.push(assessmentState.vscodeSettings.value.sourceFile);
|
|
42327
|
-
}
|
|
42328
|
-
const plainTextFiles = [];
|
|
42329
|
-
if (isSome2(assessmentState.agentsMd)) {
|
|
42330
|
-
plainTextFiles.push({
|
|
42331
|
-
path: assessmentState.agentsMd.value.path,
|
|
42332
|
-
text: assessmentState.agentsMd.value.text
|
|
42333
|
-
});
|
|
42334
|
-
}
|
|
42335
|
-
if (isSome2(assessmentState.claudeMd)) {
|
|
42336
|
-
plainTextFiles.push({
|
|
42337
|
-
path: assessmentState.claudeMd.value.path,
|
|
42338
|
-
text: assessmentState.claudeMd.value.text
|
|
42339
|
-
});
|
|
42340
|
-
}
|
|
42341
|
-
for (const codeAction of result.codeActions) {
|
|
42342
|
-
for (const fileChange of codeAction.changes) {
|
|
42343
|
-
const sourceFile = sourceFiles.find((sf) => sf.fileName === fileChange.fileName);
|
|
42344
|
-
const plainTextFile = plainTextFiles.find((pf) => pf.path === fileChange.fileName);
|
|
42345
|
-
const header = vsep2([
|
|
42346
|
-
empty32,
|
|
42347
|
-
annotate2(text3(codeAction.description), bold2),
|
|
42348
|
-
annotate2(text3(fileChange.fileName), cyan4),
|
|
42349
|
-
empty32
|
|
42350
|
-
]);
|
|
42351
|
-
const headerStr = header.pipe(render3({ style: "pretty" }));
|
|
42352
|
-
yield* log3(headerStr);
|
|
42353
|
-
if (sourceFile) {
|
|
42354
|
-
const diffLines = renderFileChanges(sourceFile, fileChange.textChanges);
|
|
42355
|
-
const diff8 = vsep2(diffLines);
|
|
42356
|
-
const diffStr = diff8.pipe(render3({ style: "pretty" }));
|
|
42357
|
-
yield* log3(diffStr);
|
|
42358
|
-
} else if (plainTextFile) {
|
|
42359
|
-
const diffLines = renderPlainTextFileChanges(plainTextFile.text, fileChange.textChanges);
|
|
42360
|
-
const diff8 = vsep2(diffLines);
|
|
42361
|
-
const diffStr = diff8.pipe(render3({ style: "pretty" }));
|
|
42362
|
-
yield* log3(diffStr);
|
|
42363
|
-
} else {
|
|
42364
|
-
const noticeStr = text3(" (file will be modified)").pipe(render3({ style: "pretty" }));
|
|
42365
|
-
yield* log3(noticeStr);
|
|
42366
|
-
}
|
|
42367
|
-
}
|
|
42368
|
-
}
|
|
42369
|
-
if (result.messages.length > 0) {
|
|
42370
|
-
yield* log3("");
|
|
42371
|
-
for (const message of result.messages) {
|
|
42372
|
-
const messageDoc = message.includes("WARNING") ? annotate2(text3(message), yellow3) : text3(message);
|
|
42373
|
-
const messageStr = messageDoc.pipe(render3({ style: "pretty" }));
|
|
42374
|
-
yield* log3(messageStr);
|
|
42375
|
-
}
|
|
42376
|
-
}
|
|
42377
|
-
});
|
|
42378
|
-
|
|
42379
42965
|
// src/cli/setup/errors.ts
|
|
42380
42966
|
var PackageJsonNotFoundError = class extends TaggedError("PackageJsonNotFoundError") {
|
|
42381
42967
|
get message() {
|
|
@@ -43017,7 +43603,7 @@ var cliCommand = make58(
|
|
|
43017
43603
|
"effect-language-service",
|
|
43018
43604
|
{},
|
|
43019
43605
|
() => log3("Please select a command or run --help.")
|
|
43020
|
-
).pipe(withSubcommands3([setup, patch9, unpatch, check2, diagnostics2, codegen, overview, layerInfo]));
|
|
43606
|
+
).pipe(withSubcommands3([setup, patch9, unpatch, check2, diagnostics2, quickfixes, codegen, overview, layerInfo]));
|
|
43021
43607
|
var main = run8(cliCommand, {
|
|
43022
43608
|
name: "effect-language-service",
|
|
43023
43609
|
version: package_default.version
|