@effect/language-service 0.49.0 → 0.51.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 +4 -0
- package/cli.js +119 -3
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +120 -3
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +119 -3
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +120 -3
- package/transform.js.map +1 -1
package/package.json
CHANGED
package/transform.js
CHANGED
|
@@ -769,6 +769,7 @@ var unsafeGet = /* @__PURE__ */ dual(2, (self, index) => {
|
|
|
769
769
|
});
|
|
770
770
|
var headNonEmpty = /* @__PURE__ */ unsafeGet(0);
|
|
771
771
|
var tailNonEmpty = (self) => self.slice(1);
|
|
772
|
+
var reverse = (self) => Array.from(self).reverse();
|
|
772
773
|
var sort = /* @__PURE__ */ dual(2, (self, O) => {
|
|
773
774
|
const out = Array.from(self);
|
|
774
775
|
out.sort(O);
|
|
@@ -1202,7 +1203,8 @@ var defaults = {
|
|
|
1202
1203
|
pattern: "default",
|
|
1203
1204
|
skipLeadingPath: ["src/"]
|
|
1204
1205
|
}],
|
|
1205
|
-
extendedKeyDetection: false
|
|
1206
|
+
extendedKeyDetection: false,
|
|
1207
|
+
pipeableMinArgCount: 1
|
|
1206
1208
|
};
|
|
1207
1209
|
function parseKeyPatterns(patterns) {
|
|
1208
1210
|
const result = [];
|
|
@@ -1237,7 +1239,8 @@ function parse(config) {
|
|
|
1237
1239
|
renames: isObject(config) && hasProperty(config, "renames") && isBoolean(config.renames) ? config.renames : defaults.renames,
|
|
1238
1240
|
noExternal: isObject(config) && hasProperty(config, "noExternal") && isBoolean(config.noExternal) ? config.noExternal : defaults.noExternal,
|
|
1239
1241
|
keyPatterns: isObject(config) && hasProperty(config, "keyPatterns") && isArray(config.keyPatterns) ? parseKeyPatterns(config.keyPatterns) : defaults.keyPatterns,
|
|
1240
|
-
extendedKeyDetection: isObject(config) && hasProperty(config, "extendedKeyDetection") && isBoolean(config.extendedKeyDetection) ? config.extendedKeyDetection : defaults.extendedKeyDetection
|
|
1242
|
+
extendedKeyDetection: isObject(config) && hasProperty(config, "extendedKeyDetection") && isBoolean(config.extendedKeyDetection) ? config.extendedKeyDetection : defaults.extendedKeyDetection,
|
|
1243
|
+
pipeableMinArgCount: isObject(config) && hasProperty(config, "pipeableMinArgCount") && isNumber(config.pipeableMinArgCount) ? config.pipeableMinArgCount : defaults.pipeableMinArgCount
|
|
1241
1244
|
};
|
|
1242
1245
|
}
|
|
1243
1246
|
|
|
@@ -4271,6 +4274,74 @@ More info at https://effect.website/docs/requirements-management/layers/#avoidin
|
|
|
4271
4274
|
})
|
|
4272
4275
|
});
|
|
4273
4276
|
|
|
4277
|
+
// src/diagnostics/missedPipeableOpportunity.ts
|
|
4278
|
+
var missedPipeableOpportunity = createDiagnostic({
|
|
4279
|
+
name: "missedPipeableOpportunity",
|
|
4280
|
+
code: 26,
|
|
4281
|
+
severity: "off",
|
|
4282
|
+
apply: fn("missedPipeableOpportunity.apply")(function* (sourceFile, report) {
|
|
4283
|
+
const ts = yield* service(TypeScriptApi);
|
|
4284
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
4285
|
+
const typeParser = yield* service(TypeParser);
|
|
4286
|
+
const options = yield* service(LanguageServicePluginOptions);
|
|
4287
|
+
const nodeToVisit = [sourceFile];
|
|
4288
|
+
const prependNodeToVisit = (node) => {
|
|
4289
|
+
nodeToVisit.unshift(node);
|
|
4290
|
+
return void 0;
|
|
4291
|
+
};
|
|
4292
|
+
const callChainNodes = /* @__PURE__ */ new WeakMap();
|
|
4293
|
+
while (nodeToVisit.length > 0) {
|
|
4294
|
+
const node = nodeToVisit.shift();
|
|
4295
|
+
if (ts.isCallExpression(node) && node.arguments.length === 1 && node.parent) {
|
|
4296
|
+
const parentChain = callChainNodes.get(node.parent) || [];
|
|
4297
|
+
callChainNodes.set(node, parentChain.concat(node));
|
|
4298
|
+
} else if (node.parent && callChainNodes.has(node.parent) && ts.isExpression(node)) {
|
|
4299
|
+
const parentChain = callChainNodes.get(node.parent) || [];
|
|
4300
|
+
const originalParentChain = parentChain.slice();
|
|
4301
|
+
parentChain.push(node);
|
|
4302
|
+
while (parentChain.length > options.pipeableMinArgCount) {
|
|
4303
|
+
const subject = parentChain.pop();
|
|
4304
|
+
const resultType = typeChecker.getTypeAtLocation(subject);
|
|
4305
|
+
const pipeableType = yield* pipe(typeParser.pipeableType(resultType, subject), orElse2(() => void_));
|
|
4306
|
+
if (pipeableType) {
|
|
4307
|
+
report({
|
|
4308
|
+
location: parentChain[0],
|
|
4309
|
+
messageText: `Nested function calls can be converted to pipeable style for better readability.`,
|
|
4310
|
+
fixes: [{
|
|
4311
|
+
fixName: "missedPipeableOpportunity_fix",
|
|
4312
|
+
description: "Convert to pipe style",
|
|
4313
|
+
apply: gen(function* () {
|
|
4314
|
+
const changeTracker = yield* service(ChangeTracker);
|
|
4315
|
+
changeTracker.replaceNode(
|
|
4316
|
+
sourceFile,
|
|
4317
|
+
parentChain[0],
|
|
4318
|
+
ts.factory.createCallExpression(
|
|
4319
|
+
ts.factory.createPropertyAccessExpression(
|
|
4320
|
+
subject,
|
|
4321
|
+
"pipe"
|
|
4322
|
+
),
|
|
4323
|
+
void 0,
|
|
4324
|
+
pipe(
|
|
4325
|
+
parentChain,
|
|
4326
|
+
filter(ts.isCallExpression),
|
|
4327
|
+
map3((call) => call.expression),
|
|
4328
|
+
reverse
|
|
4329
|
+
)
|
|
4330
|
+
)
|
|
4331
|
+
);
|
|
4332
|
+
})
|
|
4333
|
+
}]
|
|
4334
|
+
});
|
|
4335
|
+
originalParentChain.forEach((node2) => callChainNodes.delete(node2));
|
|
4336
|
+
break;
|
|
4337
|
+
}
|
|
4338
|
+
}
|
|
4339
|
+
}
|
|
4340
|
+
ts.forEachChild(node, prependNodeToVisit);
|
|
4341
|
+
}
|
|
4342
|
+
})
|
|
4343
|
+
});
|
|
4344
|
+
|
|
4274
4345
|
// src/diagnostics/missingEffectContext.ts
|
|
4275
4346
|
var missingEffectContext = createDiagnostic({
|
|
4276
4347
|
name: "missingEffectContext",
|
|
@@ -5550,6 +5621,50 @@ var strictBooleanExpressions = createDiagnostic({
|
|
|
5550
5621
|
})
|
|
5551
5622
|
});
|
|
5552
5623
|
|
|
5624
|
+
// src/diagnostics/strictEffectProvide.ts
|
|
5625
|
+
var strictEffectProvide = createDiagnostic({
|
|
5626
|
+
name: "strictEffectProvide",
|
|
5627
|
+
code: 27,
|
|
5628
|
+
severity: "off",
|
|
5629
|
+
apply: fn("strictEffectProvide.apply")(function* (sourceFile, report) {
|
|
5630
|
+
const ts = yield* service(TypeScriptApi);
|
|
5631
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
5632
|
+
const typeParser = yield* service(TypeParser);
|
|
5633
|
+
const parseEffectProvideWithLayer = (node) => gen(function* () {
|
|
5634
|
+
if (!ts.isCallExpression(node) || !ts.isPropertyAccessExpression(node.expression) || !ts.isIdentifier(node.expression.name) || ts.idText(node.expression.name) !== "provide" || node.arguments.length === 0) {
|
|
5635
|
+
return yield* typeParserIssue("Not an Effect.provide call");
|
|
5636
|
+
}
|
|
5637
|
+
yield* typeParser.importedEffectModule(node.expression.expression);
|
|
5638
|
+
return yield* firstSuccessOf(
|
|
5639
|
+
node.arguments.map((arg) => {
|
|
5640
|
+
const argType = typeChecker.getTypeAtLocation(arg);
|
|
5641
|
+
return typeParser.layerType(argType, arg);
|
|
5642
|
+
})
|
|
5643
|
+
);
|
|
5644
|
+
});
|
|
5645
|
+
const nodeToVisit = [];
|
|
5646
|
+
const appendNodeToVisit = (node) => {
|
|
5647
|
+
nodeToVisit.push(node);
|
|
5648
|
+
return void 0;
|
|
5649
|
+
};
|
|
5650
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
5651
|
+
while (nodeToVisit.length > 0) {
|
|
5652
|
+
const node = nodeToVisit.shift();
|
|
5653
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
5654
|
+
if (ts.isCallExpression(node)) {
|
|
5655
|
+
const layerCheck = yield* pipe(parseEffectProvideWithLayer(node), option);
|
|
5656
|
+
if (isSome2(layerCheck)) {
|
|
5657
|
+
report({
|
|
5658
|
+
location: node,
|
|
5659
|
+
messageText: "Effect.provide with a Layer should only be used at application entry points. If this is an entry point, you can safely disable this diagnostic. Otherwise, using Effect.provide may break scope lifetimes. Compose all layers at your entry point and provide them at once.",
|
|
5660
|
+
fixes: []
|
|
5661
|
+
});
|
|
5662
|
+
}
|
|
5663
|
+
}
|
|
5664
|
+
}
|
|
5665
|
+
})
|
|
5666
|
+
});
|
|
5667
|
+
|
|
5553
5668
|
// src/diagnostics/tryCatchInEffectGen.ts
|
|
5554
5669
|
var tryCatchInEffectGen = createDiagnostic({
|
|
5555
5670
|
name: "tryCatchInEffectGen",
|
|
@@ -5839,7 +5954,9 @@ var diagnostics = [
|
|
|
5839
5954
|
overriddenSchemaConstructor,
|
|
5840
5955
|
unsupportedServiceAccessors,
|
|
5841
5956
|
nonObjectEffectServiceType,
|
|
5842
|
-
deterministicKeys
|
|
5957
|
+
deterministicKeys,
|
|
5958
|
+
missedPipeableOpportunity,
|
|
5959
|
+
strictEffectProvide
|
|
5843
5960
|
];
|
|
5844
5961
|
|
|
5845
5962
|
// src/transform.ts
|