@effect/language-service 0.29.0 → 0.31.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 +3 -24
- package/cli.js +467 -3
- package/cli.js.map +1 -1
- package/index.js +502 -38
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +467 -3
- package/transform.js.map +1 -1
package/README.md
CHANGED
|
@@ -46,10 +46,13 @@ And you're done! You'll now be able to use a set of refactors and diagnostics th
|
|
|
46
46
|
- Warn on leaking requirements in Effect services
|
|
47
47
|
- Warn on Scope as requirement of a Layer
|
|
48
48
|
- Warn on subsequent `Effect.provide` anti-pattern
|
|
49
|
+
- Detect wrong `Self` type parameter for APIs like `Effect.Service` or `Schema.TaggedError` and similar
|
|
49
50
|
- Unnecessary usages of `Effect.gen` or `pipe()`
|
|
50
51
|
- Warn when importing from a barrel file instead of from the module directly
|
|
51
52
|
- Warn on usage of try/catch inside `Effect.gen` and family
|
|
52
53
|
- Detect unnecessary pipe chains like `X.pipe(Y).pipe(Z)`
|
|
54
|
+
- Warn when using `Effect.Service` with `accessors: true` but methods have generics or multiple signatures
|
|
55
|
+
- Warn on missing service dependencies in `Effect.Service` declarations
|
|
53
56
|
|
|
54
57
|
### Completions
|
|
55
58
|
|
|
@@ -106,30 +109,6 @@ Few options can be provided alongside the initialization of the Language Service
|
|
|
106
109
|
### DiagnosticSeverty properties list
|
|
107
110
|
|
|
108
111
|
The full list can be found in the [diagnostics](https://github.com/Effect-TS/language-service/tree/main/src/diagnostics) folder.
|
|
109
|
-
Here is the current list of diagnostics you can use to override severity:
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
```bash
|
|
113
|
-
duplicatePackage
|
|
114
|
-
effectInVoidSuccess
|
|
115
|
-
floatingEffect
|
|
116
|
-
genericEffectServices
|
|
117
|
-
importFromBarrel
|
|
118
|
-
leakingRequirements
|
|
119
|
-
middlewareAutoImportQuickfixes
|
|
120
|
-
missingEffectContext
|
|
121
|
-
missingEffectError
|
|
122
|
-
missingReturnYieldStar
|
|
123
|
-
missingStarInYieldEffectGen
|
|
124
|
-
multipleEffectProvide
|
|
125
|
-
returnEffectInGen
|
|
126
|
-
scopeInLayerEffect
|
|
127
|
-
strictBooleanExpressions
|
|
128
|
-
tryCatchInEffectGen
|
|
129
|
-
unnecessaryEffectGen
|
|
130
|
-
unnecessaryPipe
|
|
131
|
-
unnecessaryPipeChain
|
|
132
|
-
```
|
|
133
112
|
|
|
134
113
|
## Why do diagnostics not appear at compile time?
|
|
135
114
|
|
package/cli.js
CHANGED
|
@@ -29927,6 +29927,36 @@ function make64(ts2, tsUtils, typeChecker) {
|
|
|
29927
29927
|
"TypeParser.effectSubtype",
|
|
29928
29928
|
(type2) => type2
|
|
29929
29929
|
);
|
|
29930
|
+
const importedSchemaModule = cachedBy(
|
|
29931
|
+
fn("TypeParser.importedSchemaModule")(function* (node) {
|
|
29932
|
+
const type2 = typeChecker.getTypeAtLocation(node);
|
|
29933
|
+
const propertySymbol = typeChecker.getPropertyOfType(type2, "Class");
|
|
29934
|
+
if (!propertySymbol) {
|
|
29935
|
+
return yield* typeParserIssue("Type has no 'Class' property", type2, node);
|
|
29936
|
+
}
|
|
29937
|
+
if (!ts2.isExpression(node)) {
|
|
29938
|
+
return yield* typeParserIssue("Node is not an expression", type2, node);
|
|
29939
|
+
}
|
|
29940
|
+
return node;
|
|
29941
|
+
}),
|
|
29942
|
+
"TypeParser.importedSchemaModule",
|
|
29943
|
+
(node) => node
|
|
29944
|
+
);
|
|
29945
|
+
const importedContextModule = cachedBy(
|
|
29946
|
+
fn("TypeParser.importedContextModule")(function* (node) {
|
|
29947
|
+
const type2 = typeChecker.getTypeAtLocation(node);
|
|
29948
|
+
const propertySymbol = typeChecker.getPropertyOfType(type2, "Tag");
|
|
29949
|
+
if (!propertySymbol) {
|
|
29950
|
+
return yield* typeParserIssue("Type has no 'Tag' property", type2, node);
|
|
29951
|
+
}
|
|
29952
|
+
if (!ts2.isExpression(node)) {
|
|
29953
|
+
return yield* typeParserIssue("Node is not an expression", type2, node);
|
|
29954
|
+
}
|
|
29955
|
+
return node;
|
|
29956
|
+
}),
|
|
29957
|
+
"TypeParser.importedContextModule",
|
|
29958
|
+
(node) => node
|
|
29959
|
+
);
|
|
29930
29960
|
const importedEffectModule = cachedBy(
|
|
29931
29961
|
fn("TypeParser.importedEffectModule")(function* (node) {
|
|
29932
29962
|
const type2 = typeChecker.getTypeAtLocation(node);
|
|
@@ -30283,6 +30313,226 @@ function make64(ts2, tsUtils, typeChecker) {
|
|
|
30283
30313
|
"TypeParser.promiseLike",
|
|
30284
30314
|
(type2) => type2
|
|
30285
30315
|
);
|
|
30316
|
+
const extendsSchemaClass = cachedBy(
|
|
30317
|
+
fn("TypeParser.extendsSchemaClass")(function* (atLocation) {
|
|
30318
|
+
if (!atLocation.name) {
|
|
30319
|
+
return yield* typeParserIssue("Class has no name", void 0, atLocation);
|
|
30320
|
+
}
|
|
30321
|
+
const heritageClauses = atLocation.heritageClauses;
|
|
30322
|
+
if (!heritageClauses) {
|
|
30323
|
+
return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
|
|
30324
|
+
}
|
|
30325
|
+
for (const heritageClause of heritageClauses) {
|
|
30326
|
+
for (const typeX of heritageClause.types) {
|
|
30327
|
+
if (ts2.isExpressionWithTypeArguments(typeX)) {
|
|
30328
|
+
const expression = typeX.expression;
|
|
30329
|
+
if (ts2.isCallExpression(expression)) {
|
|
30330
|
+
const schemaCall = expression.expression;
|
|
30331
|
+
if (ts2.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
|
|
30332
|
+
const selfTypeNode = schemaCall.typeArguments[0];
|
|
30333
|
+
const schemaIdentifier = schemaCall.expression;
|
|
30334
|
+
if (ts2.isPropertyAccessExpression(schemaIdentifier) && ts2.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "Class") {
|
|
30335
|
+
const parsedSchemaModule = yield* pipe(
|
|
30336
|
+
importedSchemaModule(schemaIdentifier.expression),
|
|
30337
|
+
option4
|
|
30338
|
+
);
|
|
30339
|
+
if (isSome2(parsedSchemaModule)) {
|
|
30340
|
+
return {
|
|
30341
|
+
className: atLocation.name,
|
|
30342
|
+
selfTypeNode,
|
|
30343
|
+
Schema: parsedSchemaModule.value
|
|
30344
|
+
};
|
|
30345
|
+
}
|
|
30346
|
+
}
|
|
30347
|
+
}
|
|
30348
|
+
}
|
|
30349
|
+
}
|
|
30350
|
+
}
|
|
30351
|
+
}
|
|
30352
|
+
return yield* typeParserIssue("Class does not extend Schema.Class", void 0, atLocation);
|
|
30353
|
+
}),
|
|
30354
|
+
"TypeParser.extendsSchemaClass",
|
|
30355
|
+
(atLocation) => atLocation
|
|
30356
|
+
);
|
|
30357
|
+
const extendsSchemaTaggedClass = cachedBy(
|
|
30358
|
+
fn("TypeParser.extendsSchemaTaggedClass")(function* (atLocation) {
|
|
30359
|
+
if (!atLocation.name) {
|
|
30360
|
+
return yield* typeParserIssue("Class has no name", void 0, atLocation);
|
|
30361
|
+
}
|
|
30362
|
+
const heritageClauses = atLocation.heritageClauses;
|
|
30363
|
+
if (!heritageClauses) {
|
|
30364
|
+
return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
|
|
30365
|
+
}
|
|
30366
|
+
for (const heritageClause of heritageClauses) {
|
|
30367
|
+
for (const typeX of heritageClause.types) {
|
|
30368
|
+
if (ts2.isExpressionWithTypeArguments(typeX)) {
|
|
30369
|
+
const expression = typeX.expression;
|
|
30370
|
+
if (ts2.isCallExpression(expression)) {
|
|
30371
|
+
const tagCall = expression.expression;
|
|
30372
|
+
if (ts2.isCallExpression(tagCall)) {
|
|
30373
|
+
const schemaCall = tagCall.expression;
|
|
30374
|
+
if (ts2.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
|
|
30375
|
+
const selfTypeNode = schemaCall.typeArguments[0];
|
|
30376
|
+
const schemaIdentifier = schemaCall.expression;
|
|
30377
|
+
if (ts2.isPropertyAccessExpression(schemaIdentifier) && ts2.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "TaggedClass") {
|
|
30378
|
+
const parsedSchemaModule = yield* pipe(
|
|
30379
|
+
importedSchemaModule(schemaIdentifier.expression),
|
|
30380
|
+
option4
|
|
30381
|
+
);
|
|
30382
|
+
if (isSome2(parsedSchemaModule)) {
|
|
30383
|
+
return {
|
|
30384
|
+
className: atLocation.name,
|
|
30385
|
+
selfTypeNode,
|
|
30386
|
+
Schema: parsedSchemaModule.value
|
|
30387
|
+
};
|
|
30388
|
+
}
|
|
30389
|
+
}
|
|
30390
|
+
}
|
|
30391
|
+
}
|
|
30392
|
+
}
|
|
30393
|
+
}
|
|
30394
|
+
}
|
|
30395
|
+
}
|
|
30396
|
+
return yield* typeParserIssue("Class does not extend Schema.TaggedClass", void 0, atLocation);
|
|
30397
|
+
}),
|
|
30398
|
+
"TypeParser.extendsSchemaTaggedClass",
|
|
30399
|
+
(atLocation) => atLocation
|
|
30400
|
+
);
|
|
30401
|
+
const extendsSchemaTaggedError = cachedBy(
|
|
30402
|
+
fn("TypeParser.extendsSchemaTaggedError")(function* (atLocation) {
|
|
30403
|
+
if (!atLocation.name) {
|
|
30404
|
+
return yield* typeParserIssue("Class has no name", void 0, atLocation);
|
|
30405
|
+
}
|
|
30406
|
+
const heritageClauses = atLocation.heritageClauses;
|
|
30407
|
+
if (!heritageClauses) {
|
|
30408
|
+
return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
|
|
30409
|
+
}
|
|
30410
|
+
for (const heritageClause of heritageClauses) {
|
|
30411
|
+
for (const typeX of heritageClause.types) {
|
|
30412
|
+
if (ts2.isExpressionWithTypeArguments(typeX)) {
|
|
30413
|
+
const expression = typeX.expression;
|
|
30414
|
+
if (ts2.isCallExpression(expression)) {
|
|
30415
|
+
const tagCall = expression.expression;
|
|
30416
|
+
if (ts2.isCallExpression(tagCall)) {
|
|
30417
|
+
const schemaCall = tagCall.expression;
|
|
30418
|
+
if (ts2.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
|
|
30419
|
+
const selfTypeNode = schemaCall.typeArguments[0];
|
|
30420
|
+
const schemaIdentifier = schemaCall.expression;
|
|
30421
|
+
if (ts2.isPropertyAccessExpression(schemaIdentifier) && ts2.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "TaggedError") {
|
|
30422
|
+
const parsedSchemaModule = yield* pipe(
|
|
30423
|
+
importedSchemaModule(schemaIdentifier.expression),
|
|
30424
|
+
option4
|
|
30425
|
+
);
|
|
30426
|
+
if (isSome2(parsedSchemaModule)) {
|
|
30427
|
+
return {
|
|
30428
|
+
className: atLocation.name,
|
|
30429
|
+
selfTypeNode,
|
|
30430
|
+
Schema: parsedSchemaModule.value
|
|
30431
|
+
};
|
|
30432
|
+
}
|
|
30433
|
+
}
|
|
30434
|
+
}
|
|
30435
|
+
}
|
|
30436
|
+
}
|
|
30437
|
+
}
|
|
30438
|
+
}
|
|
30439
|
+
}
|
|
30440
|
+
return yield* typeParserIssue("Class does not extend Schema.TaggedError", void 0, atLocation);
|
|
30441
|
+
}),
|
|
30442
|
+
"TypeParser.extendsSchemaTaggedError",
|
|
30443
|
+
(atLocation) => atLocation
|
|
30444
|
+
);
|
|
30445
|
+
const extendsSchemaTaggedRequest = cachedBy(
|
|
30446
|
+
fn("TypeParser.extendsSchemaTaggedRequest")(function* (atLocation) {
|
|
30447
|
+
if (!atLocation.name) {
|
|
30448
|
+
return yield* typeParserIssue("Class has no name", void 0, atLocation);
|
|
30449
|
+
}
|
|
30450
|
+
const heritageClauses = atLocation.heritageClauses;
|
|
30451
|
+
if (!heritageClauses) {
|
|
30452
|
+
return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
|
|
30453
|
+
}
|
|
30454
|
+
for (const heritageClause of heritageClauses) {
|
|
30455
|
+
for (const typeX of heritageClause.types) {
|
|
30456
|
+
if (ts2.isExpressionWithTypeArguments(typeX)) {
|
|
30457
|
+
const expression = typeX.expression;
|
|
30458
|
+
if (ts2.isCallExpression(expression)) {
|
|
30459
|
+
const tagCall = expression.expression;
|
|
30460
|
+
if (ts2.isCallExpression(tagCall)) {
|
|
30461
|
+
const schemaCall = tagCall.expression;
|
|
30462
|
+
if (ts2.isCallExpression(schemaCall) && schemaCall.typeArguments && schemaCall.typeArguments.length > 0) {
|
|
30463
|
+
const selfTypeNode = schemaCall.typeArguments[0];
|
|
30464
|
+
const schemaIdentifier = schemaCall.expression;
|
|
30465
|
+
if (ts2.isPropertyAccessExpression(schemaIdentifier) && ts2.isIdentifier(schemaIdentifier.name) && schemaIdentifier.name.text === "TaggedRequest") {
|
|
30466
|
+
const parsedSchemaModule = yield* pipe(
|
|
30467
|
+
importedSchemaModule(schemaIdentifier.expression),
|
|
30468
|
+
option4
|
|
30469
|
+
);
|
|
30470
|
+
if (isSome2(parsedSchemaModule)) {
|
|
30471
|
+
return {
|
|
30472
|
+
className: atLocation.name,
|
|
30473
|
+
selfTypeNode,
|
|
30474
|
+
Schema: parsedSchemaModule.value
|
|
30475
|
+
};
|
|
30476
|
+
}
|
|
30477
|
+
}
|
|
30478
|
+
}
|
|
30479
|
+
}
|
|
30480
|
+
}
|
|
30481
|
+
}
|
|
30482
|
+
}
|
|
30483
|
+
}
|
|
30484
|
+
return yield* typeParserIssue("Class does not extend Schema.TaggedRequest", void 0, atLocation);
|
|
30485
|
+
}),
|
|
30486
|
+
"TypeParser.extendsSchemaTaggedRequest",
|
|
30487
|
+
(atLocation) => atLocation
|
|
30488
|
+
);
|
|
30489
|
+
const extendsContextTag = cachedBy(
|
|
30490
|
+
fn("TypeParser.extendsContextTag")(function* (atLocation) {
|
|
30491
|
+
if (!atLocation.name) {
|
|
30492
|
+
return yield* typeParserIssue("Class has no name", void 0, atLocation);
|
|
30493
|
+
}
|
|
30494
|
+
const classSym = typeChecker.getSymbolAtLocation(atLocation.name);
|
|
30495
|
+
if (!classSym) return yield* typeParserIssue("Class has no symbol", void 0, atLocation);
|
|
30496
|
+
const type2 = typeChecker.getTypeOfSymbol(classSym);
|
|
30497
|
+
const heritageClauses = atLocation.heritageClauses;
|
|
30498
|
+
if (!heritageClauses) {
|
|
30499
|
+
return yield* typeParserIssue("Class has no heritage clauses", void 0, atLocation);
|
|
30500
|
+
}
|
|
30501
|
+
for (const heritageClause of heritageClauses) {
|
|
30502
|
+
for (const typeX of heritageClause.types) {
|
|
30503
|
+
if (ts2.isExpressionWithTypeArguments(typeX)) {
|
|
30504
|
+
const wholeCall = typeX.expression;
|
|
30505
|
+
if (ts2.isCallExpression(wholeCall)) {
|
|
30506
|
+
const contextTagCall = wholeCall.expression;
|
|
30507
|
+
if (ts2.isCallExpression(contextTagCall) && wholeCall.typeArguments && wholeCall.typeArguments.length > 0) {
|
|
30508
|
+
const contextTagIdentifier = contextTagCall.expression;
|
|
30509
|
+
const selfTypeNode = wholeCall.typeArguments[0];
|
|
30510
|
+
if (ts2.isPropertyAccessExpression(contextTagIdentifier) && ts2.isIdentifier(contextTagIdentifier.name) && contextTagIdentifier.name.text === "Tag") {
|
|
30511
|
+
const parsedContextModule = yield* pipe(
|
|
30512
|
+
importedContextModule(contextTagIdentifier.expression),
|
|
30513
|
+
option4
|
|
30514
|
+
);
|
|
30515
|
+
if (isSome2(parsedContextModule)) {
|
|
30516
|
+
const tagType = yield* contextTag(type2, atLocation);
|
|
30517
|
+
return {
|
|
30518
|
+
className: atLocation.name,
|
|
30519
|
+
selfTypeNode,
|
|
30520
|
+
args: contextTagCall.arguments,
|
|
30521
|
+
Identifier: tagType.Identifier,
|
|
30522
|
+
Tag: parsedContextModule.value
|
|
30523
|
+
};
|
|
30524
|
+
}
|
|
30525
|
+
}
|
|
30526
|
+
}
|
|
30527
|
+
}
|
|
30528
|
+
}
|
|
30529
|
+
}
|
|
30530
|
+
}
|
|
30531
|
+
return yield* typeParserIssue("Class does not extend Context.Tag", void 0, atLocation);
|
|
30532
|
+
}),
|
|
30533
|
+
"TypeParser.extendsContextTag",
|
|
30534
|
+
(atLocation) => atLocation
|
|
30535
|
+
);
|
|
30286
30536
|
const extendsEffectService = cachedBy(
|
|
30287
30537
|
fn("TypeParser.extendsEffectService")(function* (atLocation) {
|
|
30288
30538
|
if (!atLocation.name) {
|
|
@@ -30312,6 +30562,7 @@ function make64(ts2, tsUtils, typeChecker) {
|
|
|
30312
30562
|
);
|
|
30313
30563
|
if (isSome2(parsedContextTag)) {
|
|
30314
30564
|
let accessors2 = void 0;
|
|
30565
|
+
let dependencies = void 0;
|
|
30315
30566
|
if (wholeCall.arguments.length >= 2) {
|
|
30316
30567
|
const args3 = wholeCall.arguments[1];
|
|
30317
30568
|
if (ts2.isObjectLiteralExpression(args3)) {
|
|
@@ -30319,6 +30570,9 @@ function make64(ts2, tsUtils, typeChecker) {
|
|
|
30319
30570
|
if (ts2.isPropertyAssignment(property) && property.name && ts2.isIdentifier(property.name) && property.name.text === "accessors" && property.initializer && property.initializer.kind === ts2.SyntaxKind.TrueKeyword) {
|
|
30320
30571
|
accessors2 = true;
|
|
30321
30572
|
}
|
|
30573
|
+
if (ts2.isPropertyAssignment(property) && property.name && ts2.isIdentifier(property.name) && property.name.text === "dependencies" && property.initializer && ts2.isArrayLiteralExpression(property.initializer)) {
|
|
30574
|
+
dependencies = property.initializer.elements;
|
|
30575
|
+
}
|
|
30322
30576
|
}
|
|
30323
30577
|
}
|
|
30324
30578
|
}
|
|
@@ -30327,7 +30581,8 @@ function make64(ts2, tsUtils, typeChecker) {
|
|
|
30327
30581
|
className: atLocation.name,
|
|
30328
30582
|
selfTypeNode,
|
|
30329
30583
|
args: wholeCall.arguments,
|
|
30330
|
-
accessors: accessors2
|
|
30584
|
+
accessors: accessors2,
|
|
30585
|
+
dependencies
|
|
30331
30586
|
};
|
|
30332
30587
|
}
|
|
30333
30588
|
}
|
|
@@ -30358,10 +30613,78 @@ function make64(ts2, tsUtils, typeChecker) {
|
|
|
30358
30613
|
pipeCall,
|
|
30359
30614
|
scopeType,
|
|
30360
30615
|
promiseLike,
|
|
30361
|
-
extendsEffectService
|
|
30616
|
+
extendsEffectService,
|
|
30617
|
+
extendsContextTag,
|
|
30618
|
+
extendsSchemaClass,
|
|
30619
|
+
extendsSchemaTaggedClass,
|
|
30620
|
+
extendsSchemaTaggedError,
|
|
30621
|
+
extendsSchemaTaggedRequest
|
|
30362
30622
|
};
|
|
30363
30623
|
}
|
|
30364
30624
|
|
|
30625
|
+
// src/diagnostics/classSelfMismatch.ts
|
|
30626
|
+
var classSelfMismatch = createDiagnostic({
|
|
30627
|
+
name: "classSelfMismatch",
|
|
30628
|
+
code: 20,
|
|
30629
|
+
severity: "error",
|
|
30630
|
+
apply: fn("classSelfMismatch.apply")(function* (sourceFile, report) {
|
|
30631
|
+
const ts2 = yield* service2(TypeScriptApi);
|
|
30632
|
+
const typeParser = yield* service2(TypeParser);
|
|
30633
|
+
const nodeToVisit = [];
|
|
30634
|
+
const appendNodeToVisit = (node) => {
|
|
30635
|
+
nodeToVisit.push(node);
|
|
30636
|
+
return void 0;
|
|
30637
|
+
};
|
|
30638
|
+
ts2.forEachChild(sourceFile, appendNodeToVisit);
|
|
30639
|
+
while (nodeToVisit.length > 0) {
|
|
30640
|
+
const node = nodeToVisit.shift();
|
|
30641
|
+
if (ts2.isClassDeclaration(node) && node.name && node.heritageClauses) {
|
|
30642
|
+
const result = yield* pipe(
|
|
30643
|
+
typeParser.extendsEffectService(node),
|
|
30644
|
+
orElse14(() => typeParser.extendsContextTag(node)),
|
|
30645
|
+
orElse14(() => typeParser.extendsSchemaClass(node)),
|
|
30646
|
+
orElse14(() => typeParser.extendsSchemaTaggedClass(node)),
|
|
30647
|
+
orElse14(() => typeParser.extendsSchemaTaggedError(node)),
|
|
30648
|
+
orElse14(() => typeParser.extendsSchemaTaggedRequest(node)),
|
|
30649
|
+
orElse14(() => void_8)
|
|
30650
|
+
);
|
|
30651
|
+
if (result) {
|
|
30652
|
+
const { className, selfTypeNode } = result;
|
|
30653
|
+
let actualName = "";
|
|
30654
|
+
if (ts2.isTypeReferenceNode(selfTypeNode)) {
|
|
30655
|
+
if (ts2.isIdentifier(selfTypeNode.typeName)) {
|
|
30656
|
+
actualName = selfTypeNode.typeName.text;
|
|
30657
|
+
} else if (ts2.isQualifiedName(selfTypeNode.typeName)) {
|
|
30658
|
+
actualName = selfTypeNode.typeName.right.text;
|
|
30659
|
+
}
|
|
30660
|
+
}
|
|
30661
|
+
const expectedName = className.text;
|
|
30662
|
+
if (actualName !== expectedName) {
|
|
30663
|
+
report({
|
|
30664
|
+
location: selfTypeNode,
|
|
30665
|
+
messageText: `Self type parameter should be '${expectedName}'`,
|
|
30666
|
+
fixes: [{
|
|
30667
|
+
fixName: "classSelfMismatch_fix",
|
|
30668
|
+
description: `Replace '${actualName}' with '${expectedName}'`,
|
|
30669
|
+
apply: gen3(function* () {
|
|
30670
|
+
const changeTracker = yield* service2(ChangeTracker);
|
|
30671
|
+
const typeArgs = ts2.isTypeReferenceNode(selfTypeNode) ? selfTypeNode.typeArguments : void 0;
|
|
30672
|
+
const newTypeReference = ts2.factory.createTypeReferenceNode(
|
|
30673
|
+
ts2.factory.createIdentifier(expectedName),
|
|
30674
|
+
typeArgs
|
|
30675
|
+
);
|
|
30676
|
+
changeTracker.replaceNode(sourceFile, selfTypeNode, newTypeReference);
|
|
30677
|
+
})
|
|
30678
|
+
}]
|
|
30679
|
+
});
|
|
30680
|
+
}
|
|
30681
|
+
}
|
|
30682
|
+
}
|
|
30683
|
+
ts2.forEachChild(node, appendNodeToVisit);
|
|
30684
|
+
}
|
|
30685
|
+
})
|
|
30686
|
+
});
|
|
30687
|
+
|
|
30365
30688
|
// src/diagnostics/duplicatePackage.ts
|
|
30366
30689
|
var checkedPackagesCache = /* @__PURE__ */ new Map();
|
|
30367
30690
|
var programResolvedCacheSize = /* @__PURE__ */ new Map();
|
|
@@ -30981,6 +31304,89 @@ var missingEffectError = createDiagnostic({
|
|
|
30981
31304
|
})
|
|
30982
31305
|
});
|
|
30983
31306
|
|
|
31307
|
+
// src/diagnostics/missingEffectServiceDependency.ts
|
|
31308
|
+
var missingEffectServiceDependency = createDiagnostic({
|
|
31309
|
+
name: "missingEffectServiceDependency",
|
|
31310
|
+
code: 21,
|
|
31311
|
+
severity: "off",
|
|
31312
|
+
apply: fn("missingEffectServiceDependency.apply")(function* (sourceFile, report) {
|
|
31313
|
+
const ts2 = yield* service2(TypeScriptApi);
|
|
31314
|
+
const typeChecker = yield* service2(TypeCheckerApi);
|
|
31315
|
+
const typeParser = yield* service2(TypeParser);
|
|
31316
|
+
const nodeToVisit = [];
|
|
31317
|
+
const appendNodeToVisit = (node) => {
|
|
31318
|
+
nodeToVisit.push(node);
|
|
31319
|
+
return void 0;
|
|
31320
|
+
};
|
|
31321
|
+
ts2.forEachChild(sourceFile, appendNodeToVisit);
|
|
31322
|
+
while (nodeToVisit.length > 0) {
|
|
31323
|
+
const node = nodeToVisit.shift();
|
|
31324
|
+
if (ts2.isClassDeclaration(node) && node.name && node.heritageClauses) {
|
|
31325
|
+
const serviceResult = yield* pipe(
|
|
31326
|
+
typeParser.extendsEffectService(node),
|
|
31327
|
+
orElse14(() => void_8)
|
|
31328
|
+
);
|
|
31329
|
+
if (serviceResult) {
|
|
31330
|
+
const { className, dependencies } = serviceResult;
|
|
31331
|
+
const classSymbol = typeChecker.getSymbolAtLocation(className);
|
|
31332
|
+
if (classSymbol) {
|
|
31333
|
+
const classType = typeChecker.getTypeOfSymbol(classSymbol);
|
|
31334
|
+
const defaultWithoutDepsProperty = typeChecker.getPropertyOfType(classType, "DefaultWithoutDependencies");
|
|
31335
|
+
const defaultProperty = defaultWithoutDepsProperty || typeChecker.getPropertyOfType(classType, "Default");
|
|
31336
|
+
if (defaultProperty) {
|
|
31337
|
+
const defaultType = typeChecker.getTypeOfSymbolAtLocation(defaultProperty, node);
|
|
31338
|
+
const layerResult = yield* pipe(
|
|
31339
|
+
typeParser.layerType(defaultType, node),
|
|
31340
|
+
orElse14(() => void_8)
|
|
31341
|
+
);
|
|
31342
|
+
if (layerResult) {
|
|
31343
|
+
const servicesMemory = /* @__PURE__ */ new Map();
|
|
31344
|
+
const excludeNever = (type2) => succeed17((type2.flags & ts2.TypeFlags.Never) !== 0);
|
|
31345
|
+
const { allIndexes: requiredIndexes } = yield* appendToUniqueTypesMap(
|
|
31346
|
+
servicesMemory,
|
|
31347
|
+
layerResult.RIn,
|
|
31348
|
+
excludeNever
|
|
31349
|
+
);
|
|
31350
|
+
const providedIndexes = /* @__PURE__ */ new Set();
|
|
31351
|
+
const dependenciesToProcess = dependencies || [];
|
|
31352
|
+
for (const depExpression of dependenciesToProcess) {
|
|
31353
|
+
const depType = typeChecker.getTypeAtLocation(depExpression);
|
|
31354
|
+
const depLayerResult = yield* pipe(
|
|
31355
|
+
typeParser.layerType(depType, depExpression),
|
|
31356
|
+
orElse14(() => void_8)
|
|
31357
|
+
);
|
|
31358
|
+
if (depLayerResult) {
|
|
31359
|
+
const { allIndexes } = yield* appendToUniqueTypesMap(
|
|
31360
|
+
servicesMemory,
|
|
31361
|
+
depLayerResult.ROut,
|
|
31362
|
+
excludeNever
|
|
31363
|
+
);
|
|
31364
|
+
for (const index of allIndexes) {
|
|
31365
|
+
providedIndexes.add(index);
|
|
31366
|
+
}
|
|
31367
|
+
}
|
|
31368
|
+
}
|
|
31369
|
+
const missingIndexes = requiredIndexes.filter((index) => !providedIndexes.has(index));
|
|
31370
|
+
if (missingIndexes.length > 0) {
|
|
31371
|
+
const missingTypes = missingIndexes.map((index) => servicesMemory.get(index));
|
|
31372
|
+
const missingTypeNames = missingTypes.map((t) => typeChecker.typeToString(t));
|
|
31373
|
+
const message = missingTypeNames.length === 1 ? `Service '${missingTypeNames[0]}' is required but not provided by dependencies` : `Services ${missingTypeNames.map((s) => `'${s}'`).join(", ")} are required but not provided by dependencies`;
|
|
31374
|
+
report({
|
|
31375
|
+
location: className,
|
|
31376
|
+
messageText: message,
|
|
31377
|
+
fixes: []
|
|
31378
|
+
});
|
|
31379
|
+
}
|
|
31380
|
+
}
|
|
31381
|
+
}
|
|
31382
|
+
}
|
|
31383
|
+
}
|
|
31384
|
+
}
|
|
31385
|
+
ts2.forEachChild(node, appendNodeToVisit);
|
|
31386
|
+
}
|
|
31387
|
+
})
|
|
31388
|
+
});
|
|
31389
|
+
|
|
30984
31390
|
// src/diagnostics/missingReturnYieldStar.ts
|
|
30985
31391
|
var missingReturnYieldStar = createDiagnostic({
|
|
30986
31392
|
name: "missingReturnYieldStar",
|
|
@@ -31976,11 +32382,68 @@ var unnecessaryPipeChain = createDiagnostic({
|
|
|
31976
32382
|
})
|
|
31977
32383
|
});
|
|
31978
32384
|
|
|
32385
|
+
// src/diagnostics/unsupportedServiceAccessors.ts
|
|
32386
|
+
var unsupportedServiceAccessors = createDiagnostic({
|
|
32387
|
+
name: "unsupportedServiceAccessors",
|
|
32388
|
+
code: 21,
|
|
32389
|
+
severity: "warning",
|
|
32390
|
+
apply: fn("unsupportedServiceAccessors.apply")(function* (sourceFile, report) {
|
|
32391
|
+
const ts2 = yield* service2(TypeScriptApi);
|
|
32392
|
+
const nodeToVisit = [];
|
|
32393
|
+
const appendNodeToVisit = (node) => {
|
|
32394
|
+
nodeToVisit.push(node);
|
|
32395
|
+
return void 0;
|
|
32396
|
+
};
|
|
32397
|
+
ts2.forEachChild(sourceFile, appendNodeToVisit);
|
|
32398
|
+
while (nodeToVisit.length > 0) {
|
|
32399
|
+
const node = nodeToVisit.shift();
|
|
32400
|
+
ts2.forEachChild(node, appendNodeToVisit);
|
|
32401
|
+
if (ts2.isClassDeclaration(node)) {
|
|
32402
|
+
const parseResult = yield* pipe(
|
|
32403
|
+
parse5(node),
|
|
32404
|
+
orElse14(() => succeed17(null))
|
|
32405
|
+
);
|
|
32406
|
+
if (parseResult && parseResult.involvedMembers.length > 0) {
|
|
32407
|
+
const existingStaticMembers = /* @__PURE__ */ new Set();
|
|
32408
|
+
node.members?.forEach((member) => {
|
|
32409
|
+
if (ts2.isPropertyDeclaration(member) && member.modifiers?.some((mod) => mod.kind === ts2.SyntaxKind.StaticKeyword)) {
|
|
32410
|
+
if (member.name && ts2.isIdentifier(member.name)) {
|
|
32411
|
+
existingStaticMembers.add(member.name.text);
|
|
32412
|
+
}
|
|
32413
|
+
}
|
|
32414
|
+
});
|
|
32415
|
+
const missingMembers = parseResult.involvedMembers.filter(
|
|
32416
|
+
({ property }) => !existingStaticMembers.has(property.getName())
|
|
32417
|
+
);
|
|
32418
|
+
if (missingMembers.length > 0) {
|
|
32419
|
+
const memberNames = missingMembers.map(({ property }) => `'${property.getName()}'`).join(", ");
|
|
32420
|
+
report({
|
|
32421
|
+
location: parseResult.className,
|
|
32422
|
+
messageText: `Even if accessors are enabled, accessors for ${memberNames} won't be available because the signature have generic type parameters or multiple call signatures.`,
|
|
32423
|
+
fixes: [{
|
|
32424
|
+
fixName: "unsupportedServiceAccessors_enableCodegen",
|
|
32425
|
+
description: "Enable accessors codegen",
|
|
32426
|
+
apply: gen3(function* () {
|
|
32427
|
+
const changeTracker = yield* service2(ChangeTracker);
|
|
32428
|
+
const comment = "// @effect-codegens accessors\n";
|
|
32429
|
+
changeTracker.insertText(sourceFile, node.getStart(sourceFile), comment);
|
|
32430
|
+
})
|
|
32431
|
+
}]
|
|
32432
|
+
});
|
|
32433
|
+
}
|
|
32434
|
+
}
|
|
32435
|
+
}
|
|
32436
|
+
}
|
|
32437
|
+
})
|
|
32438
|
+
});
|
|
32439
|
+
|
|
31979
32440
|
// src/diagnostics.ts
|
|
31980
32441
|
var diagnostics = [
|
|
32442
|
+
classSelfMismatch,
|
|
31981
32443
|
duplicatePackage,
|
|
31982
32444
|
missingEffectContext,
|
|
31983
32445
|
missingEffectError,
|
|
32446
|
+
missingEffectServiceDependency,
|
|
31984
32447
|
floatingEffect,
|
|
31985
32448
|
missingStarInYieldEffectGen,
|
|
31986
32449
|
unnecessaryEffectGen,
|
|
@@ -31996,7 +32459,8 @@ var diagnostics = [
|
|
|
31996
32459
|
unnecessaryPipeChain,
|
|
31997
32460
|
strictBooleanExpressions,
|
|
31998
32461
|
multipleEffectProvide,
|
|
31999
|
-
outdatedEffectCodegen
|
|
32462
|
+
outdatedEffectCodegen,
|
|
32463
|
+
unsupportedServiceAccessors
|
|
32000
32464
|
];
|
|
32001
32465
|
|
|
32002
32466
|
// src/cli.ts
|