@effect/language-service 0.40.1 → 0.41.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 +1 -0
- package/effect-lsp-patch-utils.js +93 -2
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +93 -2
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +93 -2
- package/transform.js.map +1 -1
package/README.md
CHANGED
|
@@ -61,6 +61,7 @@ And you're done! You'll now be able to use a set of refactors and diagnostics th
|
|
|
61
61
|
- Detect unnecessary pipe chains like `X.pipe(Y).pipe(Z)`
|
|
62
62
|
- Warn when using `Effect.Service` with `accessors: true` but methods have generics or multiple signatures
|
|
63
63
|
- Warn on missing service dependencies in `Effect.Service` declarations
|
|
64
|
+
- Warn when `Effect.Service` is used with a primitive type instead of an object type
|
|
64
65
|
- Warn when schema classes override the default constructor behavior
|
|
65
66
|
|
|
66
67
|
### Completions
|
|
@@ -4098,7 +4098,7 @@ var missingEffectError = createDiagnostic({
|
|
|
4098
4098
|
// src/diagnostics/missingEffectServiceDependency.ts
|
|
4099
4099
|
var missingEffectServiceDependency = createDiagnostic({
|
|
4100
4100
|
name: "missingEffectServiceDependency",
|
|
4101
|
-
code:
|
|
4101
|
+
code: 22,
|
|
4102
4102
|
severity: "off",
|
|
4103
4103
|
apply: fn("missingEffectServiceDependency.apply")(function* (sourceFile, report) {
|
|
4104
4104
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -4420,6 +4420,96 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
4420
4420
|
})
|
|
4421
4421
|
});
|
|
4422
4422
|
|
|
4423
|
+
// src/diagnostics/nonObjectEffectServiceType.ts
|
|
4424
|
+
var nonObjectEffectServiceType = createDiagnostic({
|
|
4425
|
+
name: "nonObjectEffectServiceType",
|
|
4426
|
+
code: 24,
|
|
4427
|
+
severity: "error",
|
|
4428
|
+
apply: fn("nonObjectEffectServiceType.apply")(function* (sourceFile, report) {
|
|
4429
|
+
const ts = yield* service(TypeScriptApi);
|
|
4430
|
+
const typeChecker = yield* service(TypeCheckerApi);
|
|
4431
|
+
const typeCheckerUtils = yield* service(TypeCheckerUtils);
|
|
4432
|
+
const typeParser = yield* service(TypeParser);
|
|
4433
|
+
function isPrimitiveType(type) {
|
|
4434
|
+
return typeCheckerUtils.unrollUnionMembers(type).some(
|
|
4435
|
+
(type2) => !!(type2.flags & ts.TypeFlags.String || type2.flags & ts.TypeFlags.Number || type2.flags & ts.TypeFlags.Boolean || type2.flags & ts.TypeFlags.StringLiteral || type2.flags & ts.TypeFlags.NumberLiteral || type2.flags & ts.TypeFlags.BooleanLiteral || type2.flags & ts.TypeFlags.Undefined || type2.flags & ts.TypeFlags.Null)
|
|
4436
|
+
);
|
|
4437
|
+
}
|
|
4438
|
+
const nodeToVisit = [];
|
|
4439
|
+
const appendNodeToVisit = (node) => {
|
|
4440
|
+
nodeToVisit.push(node);
|
|
4441
|
+
return void 0;
|
|
4442
|
+
};
|
|
4443
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
4444
|
+
while (nodeToVisit.length > 0) {
|
|
4445
|
+
const node = nodeToVisit.shift();
|
|
4446
|
+
if (ts.isClassDeclaration(node) && node.name && node.heritageClauses) {
|
|
4447
|
+
const serviceResult = yield* pipe(
|
|
4448
|
+
typeParser.extendsEffectService(node),
|
|
4449
|
+
orElse2(() => void_)
|
|
4450
|
+
);
|
|
4451
|
+
if (serviceResult && serviceResult.options && ts.isObjectLiteralExpression(serviceResult.options)) {
|
|
4452
|
+
const options = serviceResult.options;
|
|
4453
|
+
for (const property of options.properties) {
|
|
4454
|
+
if (!ts.isPropertyAssignment(property) || !ts.isIdentifier(property.name)) {
|
|
4455
|
+
continue;
|
|
4456
|
+
}
|
|
4457
|
+
const propertyName = ts.idText(property.name);
|
|
4458
|
+
const propertyValue = property.initializer;
|
|
4459
|
+
const errorToReport = {
|
|
4460
|
+
location: property.name,
|
|
4461
|
+
messageText: "Effect.Service requires the service type to be an object {} and not a primitive type. \nConsider wrapping the value in an object, or manually using Context.Tag or Effect.Tag if you want to use a primitive instead.",
|
|
4462
|
+
fixes: []
|
|
4463
|
+
};
|
|
4464
|
+
if (propertyName === "succeed") {
|
|
4465
|
+
const valueType = typeChecker.getTypeAtLocation(propertyValue);
|
|
4466
|
+
if (isPrimitiveType(valueType)) {
|
|
4467
|
+
report(errorToReport);
|
|
4468
|
+
}
|
|
4469
|
+
} else if (propertyName === "sync") {
|
|
4470
|
+
const valueType = typeChecker.getTypeAtLocation(propertyValue);
|
|
4471
|
+
const signatures = typeChecker.getSignaturesOfType(valueType, ts.SignatureKind.Call);
|
|
4472
|
+
for (const signature of signatures) {
|
|
4473
|
+
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
4474
|
+
if (isPrimitiveType(returnType)) {
|
|
4475
|
+
report(errorToReport);
|
|
4476
|
+
break;
|
|
4477
|
+
}
|
|
4478
|
+
}
|
|
4479
|
+
} else if (propertyName === "effect" || propertyName === "scoped") {
|
|
4480
|
+
const valueType = typeChecker.getTypeAtLocation(propertyValue);
|
|
4481
|
+
const effectResult = yield* pipe(
|
|
4482
|
+
typeParser.effectType(valueType, propertyValue),
|
|
4483
|
+
orElse2(() => void_)
|
|
4484
|
+
);
|
|
4485
|
+
if (effectResult) {
|
|
4486
|
+
if (isPrimitiveType(effectResult.A)) {
|
|
4487
|
+
report(errorToReport);
|
|
4488
|
+
continue;
|
|
4489
|
+
}
|
|
4490
|
+
} else {
|
|
4491
|
+
const signatures = typeChecker.getSignaturesOfType(valueType, ts.SignatureKind.Call);
|
|
4492
|
+
for (const signature of signatures) {
|
|
4493
|
+
const returnType = typeChecker.getReturnTypeOfSignature(signature);
|
|
4494
|
+
const effectReturnResult = yield* pipe(
|
|
4495
|
+
typeParser.effectType(returnType, propertyValue),
|
|
4496
|
+
orElse2(() => void_)
|
|
4497
|
+
);
|
|
4498
|
+
if (effectReturnResult && isPrimitiveType(effectReturnResult.A)) {
|
|
4499
|
+
report(errorToReport);
|
|
4500
|
+
break;
|
|
4501
|
+
}
|
|
4502
|
+
}
|
|
4503
|
+
}
|
|
4504
|
+
}
|
|
4505
|
+
}
|
|
4506
|
+
}
|
|
4507
|
+
}
|
|
4508
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
4509
|
+
}
|
|
4510
|
+
})
|
|
4511
|
+
});
|
|
4512
|
+
|
|
4423
4513
|
// src/refactors/writeTagClassAccessors.ts
|
|
4424
4514
|
var generate = fn("writeTagClassAccessors.generate")(function* (sourceFile, service2, className, atLocation, involvedMembers) {
|
|
4425
4515
|
const ts = yield* service(TypeScriptApi);
|
|
@@ -5334,7 +5424,8 @@ var diagnostics = [
|
|
|
5334
5424
|
multipleEffectProvide,
|
|
5335
5425
|
outdatedEffectCodegen,
|
|
5336
5426
|
overriddenSchemaConstructor,
|
|
5337
|
-
unsupportedServiceAccessors
|
|
5427
|
+
unsupportedServiceAccessors,
|
|
5428
|
+
nonObjectEffectServiceType
|
|
5338
5429
|
];
|
|
5339
5430
|
|
|
5340
5431
|
// src/effect-lsp-patch-utils.ts
|