@effect/language-service 0.78.0 → 0.79.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 +64 -42
- package/cli.js +321 -8
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +317 -4
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +334 -12
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +311 -4
- package/transform.js.map +1 -1
package/cli.js
CHANGED
|
@@ -25719,7 +25719,7 @@ var runWith2 = (command, config) => {
|
|
|
25719
25719
|
// package.json
|
|
25720
25720
|
var package_default = {
|
|
25721
25721
|
name: "@effect/language-service",
|
|
25722
|
-
version: "0.
|
|
25722
|
+
version: "0.79.0",
|
|
25723
25723
|
publishConfig: {
|
|
25724
25724
|
access: "public",
|
|
25725
25725
|
directory: "dist"
|
|
@@ -25747,15 +25747,17 @@ var package_default = {
|
|
|
25747
25747
|
],
|
|
25748
25748
|
scripts: {
|
|
25749
25749
|
build: "tsup",
|
|
25750
|
+
codegen: "node --import tsx ./scripts/generate-diagnostics-readme-table.ts",
|
|
25750
25751
|
dev: "tsup --watch",
|
|
25751
25752
|
clean: "rimraf dist build .tsbuildinfo",
|
|
25752
25753
|
lint: "eslint src test",
|
|
25753
25754
|
"lint-fix": "eslint src test --fix",
|
|
25754
25755
|
check: "tsc -b tsconfig.json",
|
|
25756
|
+
"check:codegen": "node --import tsx ./scripts/generate-diagnostics-readme-table.ts --check",
|
|
25755
25757
|
circular: "madge --extensions ts --circular --no-color --no-spinner --warning src",
|
|
25756
25758
|
test: "vitest",
|
|
25757
25759
|
"test-update": "vitest --update",
|
|
25758
|
-
"test-patch": "pnpm clean && pnpm build &&
|
|
25760
|
+
"test-patch": "pnpm clean && pnpm build && node dist/cli.js unpatch && node dist/cli.js patch && pnpm check",
|
|
25759
25761
|
coverage: "vitest run --coverage",
|
|
25760
25762
|
perf: "tsx test/perf.ts"
|
|
25761
25763
|
},
|
|
@@ -27527,10 +27529,12 @@ var defaults = {
|
|
|
27527
27529
|
extendedKeyDetection: false,
|
|
27528
27530
|
ignoreEffectWarningsInTscExitCode: false,
|
|
27529
27531
|
ignoreEffectSuggestionsInTscExitCode: true,
|
|
27532
|
+
ignoreEffectErrorsInTscExitCode: false,
|
|
27530
27533
|
pipeableMinArgCount: 2,
|
|
27531
27534
|
effectFn: ["span"],
|
|
27532
27535
|
layerGraphFollowDepth: 0,
|
|
27533
|
-
mermaidProvider: "mermaid.live"
|
|
27536
|
+
mermaidProvider: "mermaid.live",
|
|
27537
|
+
skipDisabledOptimization: false
|
|
27534
27538
|
};
|
|
27535
27539
|
function parseKeyPatterns(patterns) {
|
|
27536
27540
|
const result3 = [];
|
|
@@ -27554,6 +27558,7 @@ function parse4(config) {
|
|
|
27554
27558
|
includeSuggestionsInTsc: isObject(config) && hasProperty(config, "includeSuggestionsInTsc") && isBoolean(config.includeSuggestionsInTsc) ? config.includeSuggestionsInTsc : defaults.includeSuggestionsInTsc,
|
|
27555
27559
|
ignoreEffectWarningsInTscExitCode: isObject(config) && hasProperty(config, "ignoreEffectWarningsInTscExitCode") && isBoolean(config.ignoreEffectWarningsInTscExitCode) ? config.ignoreEffectWarningsInTscExitCode : defaults.ignoreEffectWarningsInTscExitCode,
|
|
27556
27560
|
ignoreEffectSuggestionsInTscExitCode: isObject(config) && hasProperty(config, "ignoreEffectSuggestionsInTscExitCode") && isBoolean(config.ignoreEffectSuggestionsInTscExitCode) ? config.ignoreEffectSuggestionsInTscExitCode : defaults.ignoreEffectSuggestionsInTscExitCode,
|
|
27561
|
+
ignoreEffectErrorsInTscExitCode: isObject(config) && hasProperty(config, "ignoreEffectErrorsInTscExitCode") && isBoolean(config.ignoreEffectErrorsInTscExitCode) ? config.ignoreEffectErrorsInTscExitCode : defaults.ignoreEffectErrorsInTscExitCode,
|
|
27557
27562
|
quickinfo: isObject(config) && hasProperty(config, "quickinfo") && isBoolean(config.quickinfo) ? config.quickinfo : defaults.quickinfo,
|
|
27558
27563
|
quickinfoEffectParameters: isObject(config) && hasProperty(config, "quickinfoEffectParameters") && isString(config.quickinfoEffectParameters) && ["always", "never", "whentruncated"].includes(config.quickinfoEffectParameters.toLowerCase()) ? config.quickinfoEffectParameters.toLowerCase() : defaults.quickinfoEffectParameters,
|
|
27559
27564
|
quickinfoMaximumLength: isObject(config) && hasProperty(config, "quickinfoMaximumLength") && isNumber(config.quickinfoMaximumLength) ? config.quickinfoMaximumLength : defaults.quickinfoMaximumLength,
|
|
@@ -27574,7 +27579,8 @@ function parse4(config) {
|
|
|
27574
27579
|
(_) => _.toLowerCase()
|
|
27575
27580
|
) : defaults.effectFn,
|
|
27576
27581
|
layerGraphFollowDepth: isObject(config) && hasProperty(config, "layerGraphFollowDepth") && isNumber(config.layerGraphFollowDepth) ? config.layerGraphFollowDepth : defaults.layerGraphFollowDepth,
|
|
27577
|
-
mermaidProvider: isObject(config) && hasProperty(config, "mermaidProvider") && isString(config.mermaidProvider) ? config.mermaidProvider : defaults.mermaidProvider
|
|
27582
|
+
mermaidProvider: isObject(config) && hasProperty(config, "mermaidProvider") && isString(config.mermaidProvider) ? config.mermaidProvider : defaults.mermaidProvider,
|
|
27583
|
+
skipDisabledOptimization: isObject(config) && hasProperty(config, "skipDisabledOptimization") && isBoolean(config.skipDisabledOptimization) ? config.skipDisabledOptimization : defaults.skipDisabledOptimization
|
|
27578
27584
|
};
|
|
27579
27585
|
}
|
|
27580
27586
|
|
|
@@ -27758,7 +27764,7 @@ var createDiagnosticExecutor = fn3("LSP.createCommentDirectivesProcessor")(
|
|
|
27758
27764
|
if (skippedRules.indexOf(ruleNameLowered) > -1 || skippedRules.indexOf("*") > -1) {
|
|
27759
27765
|
return { diagnostics: diagnostics3, codeFixes };
|
|
27760
27766
|
}
|
|
27761
|
-
if (defaultLevel === "off" && (lineOverrides[ruleNameLowered] || sectionOverrides[ruleNameLowered] || lineOverrides["*"] || sectionOverrides["*"] || []).length === 0) {
|
|
27767
|
+
if (!pluginOptions.skipDisabledOptimization && defaultLevel === "off" && (lineOverrides[ruleNameLowered] || sectionOverrides[ruleNameLowered] || lineOverrides["*"] || sectionOverrides["*"] || []).length === 0) {
|
|
27762
27768
|
return { diagnostics: diagnostics3, codeFixes };
|
|
27763
27769
|
}
|
|
27764
27770
|
const fixByDisableNextLine = (node) => ({
|
|
@@ -31656,6 +31662,8 @@ var anyUnknownInErrorContext = createDiagnostic({
|
|
|
31656
31662
|
code: 28,
|
|
31657
31663
|
description: "Detects 'any' or 'unknown' types in Effect error or requirements channels",
|
|
31658
31664
|
severity: "off",
|
|
31665
|
+
fixable: false,
|
|
31666
|
+
supportedEffect: ["v3", "v4"],
|
|
31659
31667
|
apply: fn3("anyUnknownInErrorContext.apply")(function* (sourceFile, report) {
|
|
31660
31668
|
const ts = yield* service2(TypeScriptApi);
|
|
31661
31669
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -31759,6 +31767,8 @@ var catchAllToMapError = createDiagnostic({
|
|
|
31759
31767
|
code: 39,
|
|
31760
31768
|
description: "Suggests using Effect.mapError instead of Effect.catchAll when the callback only wraps the error with Effect.fail",
|
|
31761
31769
|
severity: "suggestion",
|
|
31770
|
+
fixable: true,
|
|
31771
|
+
supportedEffect: ["v3", "v4"],
|
|
31762
31772
|
apply: fn3("catchAllToMapError.apply")(function* (sourceFile, report) {
|
|
31763
31773
|
const ts = yield* service2(TypeScriptApi);
|
|
31764
31774
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -31856,6 +31866,8 @@ var catchUnfailableEffect = createDiagnostic({
|
|
|
31856
31866
|
code: 2,
|
|
31857
31867
|
description: "Warns when using error handling on Effects that never fail (error type is 'never')",
|
|
31858
31868
|
severity: "suggestion",
|
|
31869
|
+
fixable: false,
|
|
31870
|
+
supportedEffect: ["v3", "v4"],
|
|
31859
31871
|
apply: fn3("catchUnfailableEffect.apply")(function* (sourceFile, report) {
|
|
31860
31872
|
const ts = yield* service2(TypeScriptApi);
|
|
31861
31873
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -31905,6 +31917,8 @@ var classSelfMismatch = createDiagnostic({
|
|
|
31905
31917
|
code: 20,
|
|
31906
31918
|
description: "Ensures Self type parameter matches the class name in Service/Tag/Schema classes",
|
|
31907
31919
|
severity: "error",
|
|
31920
|
+
fixable: true,
|
|
31921
|
+
supportedEffect: ["v3", "v4"],
|
|
31908
31922
|
apply: fn3("classSelfMismatch.apply")(function* (sourceFile, report) {
|
|
31909
31923
|
const ts = yield* service2(TypeScriptApi);
|
|
31910
31924
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -32043,6 +32057,8 @@ var deterministicKeys = createDiagnostic({
|
|
|
32043
32057
|
code: 25,
|
|
32044
32058
|
description: "Enforces deterministic naming for service/tag/error identifiers based on class names",
|
|
32045
32059
|
severity: "off",
|
|
32060
|
+
fixable: true,
|
|
32061
|
+
supportedEffect: ["v3", "v4"],
|
|
32046
32062
|
apply: fn3("deterministicKeys.apply")(function* (sourceFile, report) {
|
|
32047
32063
|
const ts = yield* service2(TypeScriptApi);
|
|
32048
32064
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -32160,6 +32176,8 @@ var duplicatePackage = createDiagnostic({
|
|
|
32160
32176
|
code: 6,
|
|
32161
32177
|
description: "Detects when multiple versions of the same Effect package are loaded",
|
|
32162
32178
|
severity: "warning",
|
|
32179
|
+
fixable: false,
|
|
32180
|
+
supportedEffect: ["v3", "v4"],
|
|
32163
32181
|
apply: fn3("duplicatePackage.apply")(function* (sourceFile, report) {
|
|
32164
32182
|
const typeParser = yield* service2(TypeParser);
|
|
32165
32183
|
const options = yield* service2(LanguageServicePluginOptions);
|
|
@@ -32189,6 +32207,8 @@ var effectFnIife = createDiagnostic({
|
|
|
32189
32207
|
code: 46,
|
|
32190
32208
|
description: "Effect.fn or Effect.fnUntraced is called as an IIFE (Immediately Invoked Function Expression). Use Effect.gen instead.",
|
|
32191
32209
|
severity: "warning",
|
|
32210
|
+
fixable: true,
|
|
32211
|
+
supportedEffect: ["v3", "v4"],
|
|
32192
32212
|
apply: fn3("effectFnIife.apply")(function* (sourceFile, report) {
|
|
32193
32213
|
const ts = yield* service2(TypeScriptApi);
|
|
32194
32214
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -32291,6 +32311,8 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
32291
32311
|
code: 41,
|
|
32292
32312
|
description: "Suggests using Effect.fn for functions that returns an Effect",
|
|
32293
32313
|
severity: "suggestion",
|
|
32314
|
+
fixable: true,
|
|
32315
|
+
supportedEffect: ["v3", "v4"],
|
|
32294
32316
|
apply: fn3("effectFnOpportunity.apply")(function* (sourceFile, report) {
|
|
32295
32317
|
const ts = yield* service2(TypeScriptApi);
|
|
32296
32318
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -32883,6 +32905,8 @@ var effectGenUsesAdapter = createDiagnostic({
|
|
|
32883
32905
|
code: 23,
|
|
32884
32906
|
description: "Warns when using the deprecated adapter parameter in Effect.gen",
|
|
32885
32907
|
severity: "warning",
|
|
32908
|
+
fixable: false,
|
|
32909
|
+
supportedEffect: ["v3", "v4"],
|
|
32886
32910
|
apply: fn3("effectGenUsesAdapter.apply")(function* (sourceFile, report) {
|
|
32887
32911
|
const ts = yield* service2(TypeScriptApi);
|
|
32888
32912
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -32921,6 +32945,8 @@ var effectInFailure = createDiagnostic({
|
|
|
32921
32945
|
code: 49,
|
|
32922
32946
|
description: "Warns when an Effect is used inside an Effect failure channel",
|
|
32923
32947
|
severity: "warning",
|
|
32948
|
+
fixable: false,
|
|
32949
|
+
supportedEffect: ["v3", "v4"],
|
|
32924
32950
|
apply: fn3("effectInFailure.apply")(function* (sourceFile, report) {
|
|
32925
32951
|
const ts = yield* service2(TypeScriptApi);
|
|
32926
32952
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -32985,6 +33011,8 @@ var effectInVoidSuccess = createDiagnostic({
|
|
|
32985
33011
|
code: 14,
|
|
32986
33012
|
description: "Detects nested Effects in void success channels that may cause unexecuted effects",
|
|
32987
33013
|
severity: "warning",
|
|
33014
|
+
fixable: false,
|
|
33015
|
+
supportedEffect: ["v3", "v4"],
|
|
32988
33016
|
apply: fn3("effectInVoidSuccess.apply")(function* (sourceFile, report) {
|
|
32989
33017
|
const ts = yield* service2(TypeScriptApi);
|
|
32990
33018
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -33034,6 +33062,8 @@ var effectMapVoid = createDiagnostic({
|
|
|
33034
33062
|
code: 40,
|
|
33035
33063
|
description: "Suggests using Effect.asVoid instead of Effect.map(() => void 0), Effect.map(() => undefined), or Effect.map(() => {})",
|
|
33036
33064
|
severity: "suggestion",
|
|
33065
|
+
fixable: true,
|
|
33066
|
+
supportedEffect: ["v3", "v4"],
|
|
33037
33067
|
apply: fn3("effectMapVoid.apply")(function* (sourceFile, report) {
|
|
33038
33068
|
const ts = yield* service2(TypeScriptApi);
|
|
33039
33069
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33098,6 +33128,8 @@ var effectSucceedWithVoid = createDiagnostic({
|
|
|
33098
33128
|
code: 47,
|
|
33099
33129
|
description: "Suggests using Effect.void instead of Effect.succeed(undefined) or Effect.succeed(void 0)",
|
|
33100
33130
|
severity: "suggestion",
|
|
33131
|
+
fixable: true,
|
|
33132
|
+
supportedEffect: ["v3", "v4"],
|
|
33101
33133
|
apply: fn3("effectSucceedWithVoid.apply")(function* (sourceFile, report) {
|
|
33102
33134
|
const ts = yield* service2(TypeScriptApi);
|
|
33103
33135
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33143,12 +33175,66 @@ var effectSucceedWithVoid = createDiagnostic({
|
|
|
33143
33175
|
})
|
|
33144
33176
|
});
|
|
33145
33177
|
|
|
33178
|
+
// src/diagnostics/extendsNativeError.ts
|
|
33179
|
+
var extendsNativeError = createDiagnostic({
|
|
33180
|
+
name: "extendsNativeError",
|
|
33181
|
+
code: 50,
|
|
33182
|
+
description: "Warns when a class directly extends the native Error class",
|
|
33183
|
+
severity: "off",
|
|
33184
|
+
fixable: false,
|
|
33185
|
+
supportedEffect: ["v3", "v4"],
|
|
33186
|
+
apply: fn3("extendsNativeError.apply")(function* (sourceFile, report) {
|
|
33187
|
+
const ts = yield* service2(TypeScriptApi);
|
|
33188
|
+
const typeChecker = yield* service2(TypeCheckerApi);
|
|
33189
|
+
const errorSymbol = typeChecker.resolveName("Error", void 0, ts.SymbolFlags.Type, false);
|
|
33190
|
+
if (!errorSymbol) return;
|
|
33191
|
+
const nodeToVisit = [];
|
|
33192
|
+
const appendNodeToVisit = (node) => {
|
|
33193
|
+
nodeToVisit.push(node);
|
|
33194
|
+
return void 0;
|
|
33195
|
+
};
|
|
33196
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
33197
|
+
while (nodeToVisit.length > 0) {
|
|
33198
|
+
const node = nodeToVisit.shift();
|
|
33199
|
+
if (ts.isClassDeclaration(node) && node.heritageClauses) {
|
|
33200
|
+
for (const clause of node.heritageClauses) {
|
|
33201
|
+
if (clause.token === ts.SyntaxKind.ExtendsKeyword && clause.types.length > 0) {
|
|
33202
|
+
const typeExpression = clause.types[0].expression;
|
|
33203
|
+
const exprSymbol = typeChecker.getSymbolAtLocation(typeExpression);
|
|
33204
|
+
const resolvedSymbol = exprSymbol && exprSymbol.flags & ts.SymbolFlags.Alias ? typeChecker.getAliasedSymbol(exprSymbol) : exprSymbol;
|
|
33205
|
+
const isNativeError = resolvedSymbol === errorSymbol || (() => {
|
|
33206
|
+
if (!resolvedSymbol || resolvedSymbol === errorSymbol) return false;
|
|
33207
|
+
const exprType = typeChecker.getTypeAtLocation(typeExpression);
|
|
33208
|
+
const constructSignatures = typeChecker.getSignaturesOfType(exprType, ts.SignatureKind.Construct);
|
|
33209
|
+
if (constructSignatures.length > 0) {
|
|
33210
|
+
const instanceType = typeChecker.getReturnTypeOfSignature(constructSignatures[0]);
|
|
33211
|
+
return instanceType.symbol === errorSymbol;
|
|
33212
|
+
}
|
|
33213
|
+
return false;
|
|
33214
|
+
})();
|
|
33215
|
+
if (isNativeError) {
|
|
33216
|
+
report({
|
|
33217
|
+
location: node.name ?? typeExpression,
|
|
33218
|
+
messageText: "Avoid extending the native 'Error' class directly. Consider using a tagged error (e.g. Data.TaggedError) to maintain type safety in the Effect failure channel.",
|
|
33219
|
+
fixes: []
|
|
33220
|
+
});
|
|
33221
|
+
}
|
|
33222
|
+
}
|
|
33223
|
+
}
|
|
33224
|
+
}
|
|
33225
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
33226
|
+
}
|
|
33227
|
+
})
|
|
33228
|
+
});
|
|
33229
|
+
|
|
33146
33230
|
// src/diagnostics/floatingEffect.ts
|
|
33147
33231
|
var floatingEffect = createDiagnostic({
|
|
33148
33232
|
name: "floatingEffect",
|
|
33149
33233
|
code: 3,
|
|
33150
33234
|
description: "Ensures Effects are yielded or assigned to variables, not left floating",
|
|
33151
33235
|
severity: "error",
|
|
33236
|
+
fixable: false,
|
|
33237
|
+
supportedEffect: ["v3", "v4"],
|
|
33152
33238
|
apply: fn3("floatingEffect.apply")(function* (sourceFile, report) {
|
|
33153
33239
|
const ts = yield* service2(TypeScriptApi);
|
|
33154
33240
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -33200,6 +33286,8 @@ var genericEffectServices = createDiagnostic({
|
|
|
33200
33286
|
code: 10,
|
|
33201
33287
|
description: "Prevents services with type parameters that cannot be discriminated at runtime",
|
|
33202
33288
|
severity: "warning",
|
|
33289
|
+
fixable: false,
|
|
33290
|
+
supportedEffect: ["v3", "v4"],
|
|
33203
33291
|
apply: fn3("genericEffectServices.apply")(function* (sourceFile, report) {
|
|
33204
33292
|
const ts = yield* service2(TypeScriptApi);
|
|
33205
33293
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33247,6 +33335,8 @@ var globalErrorInEffectCatch = createDiagnostic({
|
|
|
33247
33335
|
code: 36,
|
|
33248
33336
|
description: "Warns when catch callbacks return global Error type instead of typed errors",
|
|
33249
33337
|
severity: "warning",
|
|
33338
|
+
fixable: false,
|
|
33339
|
+
supportedEffect: ["v3", "v4"],
|
|
33250
33340
|
apply: fn3("globalErrorInEffectCatch.apply")(function* (sourceFile, report) {
|
|
33251
33341
|
const ts = yield* service2(TypeScriptApi);
|
|
33252
33342
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33307,6 +33397,8 @@ var globalErrorInEffectFailure = createDiagnostic({
|
|
|
33307
33397
|
code: 35,
|
|
33308
33398
|
description: "Warns when the global Error type is used in an Effect failure channel",
|
|
33309
33399
|
severity: "warning",
|
|
33400
|
+
fixable: false,
|
|
33401
|
+
supportedEffect: ["v3", "v4"],
|
|
33310
33402
|
apply: fn3("globalErrorInEffectFailure.apply")(function* (sourceFile, report) {
|
|
33311
33403
|
const ts = yield* service2(TypeScriptApi);
|
|
33312
33404
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33360,6 +33452,8 @@ var importFromBarrel = createDiagnostic({
|
|
|
33360
33452
|
code: 12,
|
|
33361
33453
|
description: "Suggests importing from specific module paths instead of barrel exports",
|
|
33362
33454
|
severity: "off",
|
|
33455
|
+
fixable: true,
|
|
33456
|
+
supportedEffect: ["v3", "v4"],
|
|
33363
33457
|
apply: fn3("importFromBarrel.apply")(function* (sourceFile, report) {
|
|
33364
33458
|
const languageServicePluginOptions = yield* service2(LanguageServicePluginOptions);
|
|
33365
33459
|
if (languageServicePluginOptions.namespaceImportPackages.length === 0) return;
|
|
@@ -33500,6 +33594,8 @@ var instanceOfSchema = createDiagnostic({
|
|
|
33500
33594
|
code: 45,
|
|
33501
33595
|
description: "Suggests using Schema.is instead of instanceof for Effect Schema types",
|
|
33502
33596
|
severity: "off",
|
|
33597
|
+
fixable: true,
|
|
33598
|
+
supportedEffect: ["v3", "v4"],
|
|
33503
33599
|
apply: fn3("instanceOfSchema.apply")(function* (sourceFile, report) {
|
|
33504
33600
|
const ts = yield* service2(TypeScriptApi);
|
|
33505
33601
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33563,6 +33659,8 @@ var layerMergeAllWithDependencies = createDiagnostic({
|
|
|
33563
33659
|
code: 37,
|
|
33564
33660
|
description: "Detects interdependencies in Layer.mergeAll calls where one layer provides a service that another layer requires",
|
|
33565
33661
|
severity: "warning",
|
|
33662
|
+
fixable: true,
|
|
33663
|
+
supportedEffect: ["v3", "v4"],
|
|
33566
33664
|
apply: fn3("layerMergeAllWithDependencies.apply")(function* (sourceFile, report) {
|
|
33567
33665
|
const ts = yield* service2(TypeScriptApi);
|
|
33568
33666
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -33676,6 +33774,8 @@ var leakingRequirements = createDiagnostic({
|
|
|
33676
33774
|
code: 8,
|
|
33677
33775
|
description: "Detects implementation services leaked in service methods",
|
|
33678
33776
|
severity: "suggestion",
|
|
33777
|
+
fixable: false,
|
|
33778
|
+
supportedEffect: ["v3", "v4"],
|
|
33679
33779
|
apply: fn3("leakingRequirements.apply")(function* (sourceFile, report) {
|
|
33680
33780
|
const ts = yield* service2(TypeScriptApi);
|
|
33681
33781
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -33830,6 +33930,8 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
33830
33930
|
code: 26,
|
|
33831
33931
|
description: "Enforces the use of pipeable style for nested function calls",
|
|
33832
33932
|
severity: "off",
|
|
33933
|
+
fixable: true,
|
|
33934
|
+
supportedEffect: ["v3", "v4"],
|
|
33833
33935
|
apply: fn3("missedPipeableOpportunity.apply")(function* (sourceFile, report) {
|
|
33834
33936
|
const ts = yield* service2(TypeScriptApi);
|
|
33835
33937
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -34010,6 +34112,8 @@ var missingEffectContext = createDiagnostic({
|
|
|
34010
34112
|
code: 1,
|
|
34011
34113
|
description: "Reports missing service requirements in Effect context channel",
|
|
34012
34114
|
severity: "error",
|
|
34115
|
+
fixable: false,
|
|
34116
|
+
supportedEffect: ["v3", "v4"],
|
|
34013
34117
|
apply: fn3("missingEffectContext.apply")(function* (sourceFile, report) {
|
|
34014
34118
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
34015
34119
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -34059,6 +34163,8 @@ var missingEffectError = createDiagnostic({
|
|
|
34059
34163
|
code: 1,
|
|
34060
34164
|
description: "Reports missing error types in Effect error channel",
|
|
34061
34165
|
severity: "error",
|
|
34166
|
+
fixable: true,
|
|
34167
|
+
supportedEffect: ["v3", "v4"],
|
|
34062
34168
|
apply: fn3("missingEffectError.apply")(function* (sourceFile, report) {
|
|
34063
34169
|
const ts = yield* service2(TypeScriptApi);
|
|
34064
34170
|
const tsUtils = yield* service2(TypeScriptUtils);
|
|
@@ -34200,6 +34306,8 @@ var missingEffectServiceDependency = createDiagnostic({
|
|
|
34200
34306
|
code: 22,
|
|
34201
34307
|
description: "Checks that Effect.Service dependencies satisfy all required layer inputs",
|
|
34202
34308
|
severity: "off",
|
|
34309
|
+
fixable: false,
|
|
34310
|
+
supportedEffect: ["v3"],
|
|
34203
34311
|
apply: fn3("missingEffectServiceDependency.apply")(function* (sourceFile, report) {
|
|
34204
34312
|
const ts = yield* service2(TypeScriptApi);
|
|
34205
34313
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -34294,6 +34402,8 @@ var missingLayerContext = createDiagnostic({
|
|
|
34294
34402
|
code: 38,
|
|
34295
34403
|
description: "Reports missing service requirements in Layer context channel",
|
|
34296
34404
|
severity: "error",
|
|
34405
|
+
fixable: false,
|
|
34406
|
+
supportedEffect: ["v3", "v4"],
|
|
34297
34407
|
apply: fn3("missingLayerContext.apply")(function* (sourceFile, report) {
|
|
34298
34408
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
34299
34409
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -34343,6 +34453,8 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
34343
34453
|
code: 7,
|
|
34344
34454
|
description: "Suggests using 'return yield*' for Effects with never success for better type narrowing",
|
|
34345
34455
|
severity: "error",
|
|
34456
|
+
fixable: true,
|
|
34457
|
+
supportedEffect: ["v3", "v4"],
|
|
34346
34458
|
apply: fn3("missingReturnYieldStar.apply")(function* (sourceFile, report) {
|
|
34347
34459
|
const ts = yield* service2(TypeScriptApi);
|
|
34348
34460
|
const typeCheckerUtils = yield* service2(TypeCheckerUtils);
|
|
@@ -34393,6 +34505,8 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
34393
34505
|
code: 4,
|
|
34394
34506
|
description: "Enforces using 'yield*' instead of 'yield' when yielding Effects in generators",
|
|
34395
34507
|
severity: "error",
|
|
34508
|
+
fixable: true,
|
|
34509
|
+
supportedEffect: ["v3", "v4"],
|
|
34396
34510
|
apply: fn3("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
|
|
34397
34511
|
const ts = yield* service2(TypeScriptApi);
|
|
34398
34512
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -34468,6 +34582,8 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
34468
34582
|
code: 18,
|
|
34469
34583
|
description: "Warns against chaining Effect.provide calls which can cause service lifecycle issues",
|
|
34470
34584
|
severity: "warning",
|
|
34585
|
+
fixable: true,
|
|
34586
|
+
supportedEffect: ["v3", "v4"],
|
|
34471
34587
|
apply: fn3("multipleEffectProvide.apply")(function* (sourceFile, report) {
|
|
34472
34588
|
const ts = yield* service2(TypeScriptApi);
|
|
34473
34589
|
const tsUtils = yield* service2(TypeScriptUtils);
|
|
@@ -34554,12 +34670,85 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
34554
34670
|
})
|
|
34555
34671
|
});
|
|
34556
34672
|
|
|
34673
|
+
// src/diagnostics/nodeBuiltinImport.ts
|
|
34674
|
+
var moduleAlternativesV3 = /* @__PURE__ */ new Map([
|
|
34675
|
+
["fs", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
|
|
34676
|
+
["node:fs", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
|
|
34677
|
+
["fs/promises", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
|
|
34678
|
+
["node:fs/promises", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
|
|
34679
|
+
["path", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34680
|
+
["node:path", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34681
|
+
["path/posix", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34682
|
+
["node:path/posix", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34683
|
+
["path/win32", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34684
|
+
["node:path/win32", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34685
|
+
["child_process", { alternative: "CommandExecutor", module: "child_process", package: "@effect/platform" }],
|
|
34686
|
+
["node:child_process", { alternative: "CommandExecutor", module: "child_process", package: "@effect/platform" }]
|
|
34687
|
+
]);
|
|
34688
|
+
var moduleAlternativesV4 = /* @__PURE__ */ new Map([
|
|
34689
|
+
["fs", { alternative: "FileSystem", module: "fs", package: "effect" }],
|
|
34690
|
+
["node:fs", { alternative: "FileSystem", module: "fs", package: "effect" }],
|
|
34691
|
+
["fs/promises", { alternative: "FileSystem", module: "fs", package: "effect" }],
|
|
34692
|
+
["node:fs/promises", { alternative: "FileSystem", module: "fs", package: "effect" }],
|
|
34693
|
+
["path", { alternative: "Path", module: "path", package: "effect" }],
|
|
34694
|
+
["node:path", { alternative: "Path", module: "path", package: "effect" }],
|
|
34695
|
+
["path/posix", { alternative: "Path", module: "path", package: "effect" }],
|
|
34696
|
+
["node:path/posix", { alternative: "Path", module: "path", package: "effect" }],
|
|
34697
|
+
["path/win32", { alternative: "Path", module: "path", package: "effect" }],
|
|
34698
|
+
["node:path/win32", { alternative: "Path", module: "path", package: "effect" }],
|
|
34699
|
+
["child_process", { alternative: "ChildProcess", module: "child_process", package: "effect" }],
|
|
34700
|
+
["node:child_process", { alternative: "ChildProcess", module: "child_process", package: "effect" }]
|
|
34701
|
+
]);
|
|
34702
|
+
var nodeBuiltinImport = createDiagnostic({
|
|
34703
|
+
name: "nodeBuiltinImport",
|
|
34704
|
+
code: 52,
|
|
34705
|
+
description: "Warns when importing Node.js built-in modules that have Effect-native counterparts",
|
|
34706
|
+
severity: "off",
|
|
34707
|
+
fixable: false,
|
|
34708
|
+
supportedEffect: ["v3", "v4"],
|
|
34709
|
+
apply: fn3("nodeBuiltinImport.apply")(function* (sourceFile, report) {
|
|
34710
|
+
const ts = yield* service2(TypeScriptApi);
|
|
34711
|
+
const typeParser = yield* service2(TypeParser);
|
|
34712
|
+
const moduleAlternatives = typeParser.supportedEffect() === "v3" ? moduleAlternativesV3 : moduleAlternativesV4;
|
|
34713
|
+
for (const statement of sourceFile.statements) {
|
|
34714
|
+
if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
34715
|
+
const specifier = statement.moduleSpecifier.text;
|
|
34716
|
+
const match9 = moduleAlternatives.get(specifier);
|
|
34717
|
+
if (match9) {
|
|
34718
|
+
report({
|
|
34719
|
+
location: statement.moduleSpecifier,
|
|
34720
|
+
messageText: `Prefer using ${match9.alternative} from ${match9.package} instead of the Node.js '${match9.module}' module.`,
|
|
34721
|
+
fixes: []
|
|
34722
|
+
});
|
|
34723
|
+
}
|
|
34724
|
+
} else if (ts.isVariableStatement(statement)) {
|
|
34725
|
+
for (const decl of statement.declarationList.declarations) {
|
|
34726
|
+
if (decl.initializer && ts.isCallExpression(decl.initializer) && ts.isIdentifier(decl.initializer.expression) && ts.idText(decl.initializer.expression) === "require" && decl.initializer.arguments.length === 1 && ts.isStringLiteral(decl.initializer.arguments[0])) {
|
|
34727
|
+
const arg = decl.initializer.arguments[0];
|
|
34728
|
+
const specifier = arg.text;
|
|
34729
|
+
const match9 = moduleAlternatives.get(specifier);
|
|
34730
|
+
if (match9) {
|
|
34731
|
+
report({
|
|
34732
|
+
location: arg,
|
|
34733
|
+
messageText: `Prefer using ${match9.alternative} from ${match9.package} instead of the Node.js '${match9.module}' module.`,
|
|
34734
|
+
fixes: []
|
|
34735
|
+
});
|
|
34736
|
+
}
|
|
34737
|
+
}
|
|
34738
|
+
}
|
|
34739
|
+
}
|
|
34740
|
+
}
|
|
34741
|
+
})
|
|
34742
|
+
});
|
|
34743
|
+
|
|
34557
34744
|
// src/diagnostics/nonObjectEffectServiceType.ts
|
|
34558
34745
|
var nonObjectEffectServiceType = createDiagnostic({
|
|
34559
34746
|
name: "nonObjectEffectServiceType",
|
|
34560
34747
|
code: 24,
|
|
34561
34748
|
description: "Ensures Effect.Service types are objects, not primitives",
|
|
34562
34749
|
severity: "error",
|
|
34750
|
+
fixable: false,
|
|
34751
|
+
supportedEffect: ["v3"],
|
|
34563
34752
|
apply: fn3("nonObjectEffectServiceType.apply")(function* (sourceFile, report) {
|
|
34564
34753
|
const ts = yield* service2(TypeScriptApi);
|
|
34565
34754
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -35342,6 +35531,8 @@ var outdatedApi = createDiagnostic({
|
|
|
35342
35531
|
code: 48,
|
|
35343
35532
|
description: "Detects usage of APIs that have been removed or renamed in Effect v4",
|
|
35344
35533
|
severity: "warning",
|
|
35534
|
+
fixable: false,
|
|
35535
|
+
supportedEffect: ["v4"],
|
|
35345
35536
|
apply: fn3("outdatedApi.apply")(function* (sourceFile, report) {
|
|
35346
35537
|
const typeParser = yield* service2(TypeParser);
|
|
35347
35538
|
const ts = yield* service2(TypeScriptApi);
|
|
@@ -35409,6 +35600,8 @@ var outdatedEffectCodegen = createDiagnostic({
|
|
|
35409
35600
|
code: 19,
|
|
35410
35601
|
description: "Detects when generated code is outdated and needs to be regenerated",
|
|
35411
35602
|
severity: "warning",
|
|
35603
|
+
fixable: true,
|
|
35604
|
+
supportedEffect: ["v3", "v4"],
|
|
35412
35605
|
apply: fn3("outdatedEffectCodegen.apply")(function* (sourceFile, _report) {
|
|
35413
35606
|
const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
|
|
35414
35607
|
for (const { codegen: codegen2, hash: hash2, range: range2 } of codegensWithRanges) {
|
|
@@ -35455,6 +35648,8 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
35455
35648
|
code: 30,
|
|
35456
35649
|
description: "Prevents overriding constructors in Schema classes which breaks decoding behavior",
|
|
35457
35650
|
severity: "error",
|
|
35651
|
+
fixable: true,
|
|
35652
|
+
supportedEffect: ["v3", "v4"],
|
|
35458
35653
|
apply: fn3("overriddenSchemaConstructor.apply")(function* (sourceFile, report) {
|
|
35459
35654
|
const ts = yield* service2(TypeScriptApi);
|
|
35460
35655
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -35592,6 +35787,8 @@ var preferSchemaOverJson = createDiagnostic({
|
|
|
35592
35787
|
code: 44,
|
|
35593
35788
|
description: "Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify which may throw",
|
|
35594
35789
|
severity: "suggestion",
|
|
35790
|
+
fixable: false,
|
|
35791
|
+
supportedEffect: ["v3", "v4"],
|
|
35595
35792
|
apply: fn3("preferSchemaOverJson.apply")(function* (sourceFile, report) {
|
|
35596
35793
|
const ts = yield* service2(TypeScriptApi);
|
|
35597
35794
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -35702,6 +35899,8 @@ var redundantSchemaTagIdentifier = createDiagnostic({
|
|
|
35702
35899
|
code: 42,
|
|
35703
35900
|
description: "Suggests removing redundant identifier argument when it equals the tag value in Schema.TaggedClass/TaggedError/TaggedRequest",
|
|
35704
35901
|
severity: "suggestion",
|
|
35902
|
+
fixable: true,
|
|
35903
|
+
supportedEffect: ["v3", "v4"],
|
|
35705
35904
|
apply: fn3("redundantSchemaTagIdentifier.apply")(function* (sourceFile, report) {
|
|
35706
35905
|
const ts = yield* service2(TypeScriptApi);
|
|
35707
35906
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -35752,6 +35951,8 @@ var returnEffectInGen = createDiagnostic({
|
|
|
35752
35951
|
code: 11,
|
|
35753
35952
|
description: "Warns when returning an Effect in a generator causes nested Effect<Effect<...>>",
|
|
35754
35953
|
severity: "suggestion",
|
|
35954
|
+
fixable: true,
|
|
35955
|
+
supportedEffect: ["v3", "v4"],
|
|
35755
35956
|
apply: fn3("returnEffectInGen.apply")(function* (sourceFile, report) {
|
|
35756
35957
|
const ts = yield* service2(TypeScriptApi);
|
|
35757
35958
|
const typeCheckerUtils = yield* service2(TypeCheckerUtils);
|
|
@@ -35821,6 +36022,8 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
35821
36022
|
code: 32,
|
|
35822
36023
|
description: "Suggests using Runtime methods instead of Effect.run* inside Effect contexts",
|
|
35823
36024
|
severity: "suggestion",
|
|
36025
|
+
fixable: true,
|
|
36026
|
+
supportedEffect: ["v3"],
|
|
35824
36027
|
apply: fn3("runEffectInsideEffect.apply")(function* (sourceFile, report) {
|
|
35825
36028
|
const ts = yield* service2(TypeScriptApi);
|
|
35826
36029
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -35945,6 +36148,8 @@ var schemaStructWithTag = createDiagnostic({
|
|
|
35945
36148
|
code: 34,
|
|
35946
36149
|
description: "Suggests using Schema.TaggedStruct instead of Schema.Struct with _tag field",
|
|
35947
36150
|
severity: "suggestion",
|
|
36151
|
+
fixable: true,
|
|
36152
|
+
supportedEffect: ["v3", "v4"],
|
|
35948
36153
|
apply: fn3("schemaStructWithTag.apply")(function* (sourceFile, report) {
|
|
35949
36154
|
const ts = yield* service2(TypeScriptApi);
|
|
35950
36155
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36037,6 +36242,8 @@ var schemaSyncInEffect = createDiagnostic({
|
|
|
36037
36242
|
code: 43,
|
|
36038
36243
|
description: "Suggests using Effect-based Schema methods instead of sync methods inside Effect generators",
|
|
36039
36244
|
severity: "suggestion",
|
|
36245
|
+
fixable: false,
|
|
36246
|
+
supportedEffect: ["v3", "v4"],
|
|
36040
36247
|
apply: fn3("schemaSyncInEffect.apply")(function* (sourceFile, report) {
|
|
36041
36248
|
const ts = yield* service2(TypeScriptApi);
|
|
36042
36249
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36086,6 +36293,8 @@ var schemaUnionOfLiterals = createDiagnostic({
|
|
|
36086
36293
|
code: 33,
|
|
36087
36294
|
description: "Simplifies Schema.Union of multiple Schema.Literal calls into single Schema.Literal",
|
|
36088
36295
|
severity: "off",
|
|
36296
|
+
fixable: true,
|
|
36297
|
+
supportedEffect: ["v3"],
|
|
36089
36298
|
apply: fn3("schemaUnionOfLiterals.apply")(function* (sourceFile, report) {
|
|
36090
36299
|
const ts = yield* service2(TypeScriptApi);
|
|
36091
36300
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36161,6 +36370,8 @@ var scopeInLayerEffect = createDiagnostic({
|
|
|
36161
36370
|
code: 13,
|
|
36162
36371
|
description: "Suggests using Layer.scoped instead of Layer.effect when Scope is in requirements",
|
|
36163
36372
|
severity: "warning",
|
|
36373
|
+
fixable: true,
|
|
36374
|
+
supportedEffect: ["v3"],
|
|
36164
36375
|
apply: fn3("scopeInLayerEffect.apply")(function* (sourceFile, report) {
|
|
36165
36376
|
const ts = yield* service2(TypeScriptApi);
|
|
36166
36377
|
const tsUtils = yield* service2(TypeScriptUtils);
|
|
@@ -36250,12 +36461,91 @@ Consider using "scoped" instead to get rid of the scope in the requirements.`,
|
|
|
36250
36461
|
})
|
|
36251
36462
|
});
|
|
36252
36463
|
|
|
36464
|
+
// src/diagnostics/serviceNotAsClass.ts
|
|
36465
|
+
var serviceNotAsClass = createDiagnostic({
|
|
36466
|
+
name: "serviceNotAsClass",
|
|
36467
|
+
code: 51,
|
|
36468
|
+
description: "Warns when ServiceMap.Service is used as a variable instead of a class declaration",
|
|
36469
|
+
severity: "off",
|
|
36470
|
+
fixable: true,
|
|
36471
|
+
supportedEffect: ["v4"],
|
|
36472
|
+
apply: fn3("serviceNotAsClass.apply")(function* (sourceFile, report) {
|
|
36473
|
+
const ts = yield* service2(TypeScriptApi);
|
|
36474
|
+
const typeParser = yield* service2(TypeParser);
|
|
36475
|
+
if (typeParser.supportedEffect() === "v3") return;
|
|
36476
|
+
const nodeToVisit = [];
|
|
36477
|
+
const appendNodeToVisit = (node) => {
|
|
36478
|
+
nodeToVisit.push(node);
|
|
36479
|
+
return void 0;
|
|
36480
|
+
};
|
|
36481
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
36482
|
+
while (nodeToVisit.length > 0) {
|
|
36483
|
+
const node = nodeToVisit.shift();
|
|
36484
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
36485
|
+
if (!ts.isVariableDeclaration(node)) continue;
|
|
36486
|
+
if (!node.initializer || !ts.isCallExpression(node.initializer)) continue;
|
|
36487
|
+
const callExpr = node.initializer;
|
|
36488
|
+
if (!callExpr.typeArguments || callExpr.typeArguments.length === 0) continue;
|
|
36489
|
+
const typeArgs = callExpr.typeArguments;
|
|
36490
|
+
const declList = node.parent;
|
|
36491
|
+
if (!ts.isVariableDeclarationList(declList)) continue;
|
|
36492
|
+
if (!(declList.flags & ts.NodeFlags.Const)) continue;
|
|
36493
|
+
const isServiceMapService = yield* pipe(
|
|
36494
|
+
typeParser.isNodeReferenceToServiceMapModuleApi("Service")(callExpr.expression),
|
|
36495
|
+
orUndefined
|
|
36496
|
+
);
|
|
36497
|
+
if (!isServiceMapService) continue;
|
|
36498
|
+
const variableName = ts.isIdentifier(node.name) ? ts.idText(node.name) : sourceFile.text.substring(ts.getTokenPosOfNode(node.name, sourceFile), node.name.end);
|
|
36499
|
+
const variableStatement = declList.parent;
|
|
36500
|
+
const argsText = callExpr.arguments.length > 0 ? callExpr.arguments.map((a) => sourceFile.text.substring(ts.getTokenPosOfNode(a, sourceFile), a.end)).join(", ") : "";
|
|
36501
|
+
const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
|
|
36502
|
+
report({
|
|
36503
|
+
location: callExpr,
|
|
36504
|
+
messageText: `ServiceMap.Service should be used in a class declaration instead of as a variable. Use: class ${variableName} extends ServiceMap.Service<${variableName}, ${shapeText}>()("${argsText.replace(/['"]/g, "")}") {}`,
|
|
36505
|
+
fixes: [{
|
|
36506
|
+
fixName: "serviceNotAsClass",
|
|
36507
|
+
description: `Convert to class declaration`,
|
|
36508
|
+
apply: gen3(function* () {
|
|
36509
|
+
const changeTracker = yield* service2(ChangeTracker);
|
|
36510
|
+
const targetNode = ts.isVariableStatement(variableStatement) ? variableStatement : declList;
|
|
36511
|
+
const innerCall = ts.factory.createCallExpression(
|
|
36512
|
+
callExpr.expression,
|
|
36513
|
+
[ts.factory.createTypeReferenceNode(variableName), ...typeArgs],
|
|
36514
|
+
[]
|
|
36515
|
+
);
|
|
36516
|
+
const outerCall = ts.factory.createCallExpression(
|
|
36517
|
+
innerCall,
|
|
36518
|
+
void 0,
|
|
36519
|
+
[...callExpr.arguments]
|
|
36520
|
+
);
|
|
36521
|
+
const heritageClause = ts.factory.createHeritageClause(
|
|
36522
|
+
ts.SyntaxKind.ExtendsKeyword,
|
|
36523
|
+
[ts.factory.createExpressionWithTypeArguments(outerCall, void 0)]
|
|
36524
|
+
);
|
|
36525
|
+
const modifiers = ts.isVariableStatement(variableStatement) ? variableStatement.modifiers : void 0;
|
|
36526
|
+
const classDeclaration = ts.factory.createClassDeclaration(
|
|
36527
|
+
modifiers,
|
|
36528
|
+
ts.isIdentifier(node.name) ? node.name : ts.factory.createIdentifier(variableName),
|
|
36529
|
+
void 0,
|
|
36530
|
+
[heritageClause],
|
|
36531
|
+
[]
|
|
36532
|
+
);
|
|
36533
|
+
changeTracker.replaceNode(sourceFile, targetNode, classDeclaration);
|
|
36534
|
+
})
|
|
36535
|
+
}]
|
|
36536
|
+
});
|
|
36537
|
+
}
|
|
36538
|
+
})
|
|
36539
|
+
});
|
|
36540
|
+
|
|
36253
36541
|
// src/diagnostics/strictBooleanExpressions.ts
|
|
36254
36542
|
var strictBooleanExpressions = createDiagnostic({
|
|
36255
36543
|
name: "strictBooleanExpressions",
|
|
36256
36544
|
code: 17,
|
|
36257
36545
|
description: "Enforces boolean types in conditional expressions for type safety",
|
|
36258
36546
|
severity: "off",
|
|
36547
|
+
fixable: false,
|
|
36548
|
+
supportedEffect: ["v3", "v4"],
|
|
36259
36549
|
apply: fn3("strictBooleanExpressions.apply")(function* (sourceFile, report) {
|
|
36260
36550
|
const ts = yield* service2(TypeScriptApi);
|
|
36261
36551
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -36327,6 +36617,8 @@ var strictEffectProvide = createDiagnostic({
|
|
|
36327
36617
|
code: 27,
|
|
36328
36618
|
description: "Warns when using Effect.provide with layers outside of application entry points",
|
|
36329
36619
|
severity: "off",
|
|
36620
|
+
fixable: false,
|
|
36621
|
+
supportedEffect: ["v3", "v4"],
|
|
36330
36622
|
apply: fn3("strictEffectProvide.apply")(function* (sourceFile, report) {
|
|
36331
36623
|
const ts = yield* service2(TypeScriptApi);
|
|
36332
36624
|
const typeCheckerUtils = yield* service2(TypeCheckerUtils);
|
|
@@ -36378,6 +36670,8 @@ var tryCatchInEffectGen = createDiagnostic({
|
|
|
36378
36670
|
code: 15,
|
|
36379
36671
|
description: "Discourages try/catch in Effect generators in favor of Effect error handling",
|
|
36380
36672
|
severity: "suggestion",
|
|
36673
|
+
fixable: false,
|
|
36674
|
+
supportedEffect: ["v3", "v4"],
|
|
36381
36675
|
apply: fn3("tryCatchInEffectGen.apply")(function* (sourceFile, report) {
|
|
36382
36676
|
const ts = yield* service2(TypeScriptApi);
|
|
36383
36677
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36435,6 +36729,8 @@ var unknownInEffectCatch = createDiagnostic({
|
|
|
36435
36729
|
code: 31,
|
|
36436
36730
|
description: "Warns when catch callbacks return unknown instead of typed errors",
|
|
36437
36731
|
severity: "warning",
|
|
36732
|
+
fixable: false,
|
|
36733
|
+
supportedEffect: ["v3", "v4"],
|
|
36438
36734
|
apply: fn3("unknownInEffectCatch.apply")(function* (sourceFile, report) {
|
|
36439
36735
|
const ts = yield* service2(TypeScriptApi);
|
|
36440
36736
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36496,6 +36792,8 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
36496
36792
|
code: 5,
|
|
36497
36793
|
description: "Suggests removing Effect.gen when it contains only a single return statement",
|
|
36498
36794
|
severity: "suggestion",
|
|
36795
|
+
fixable: true,
|
|
36796
|
+
supportedEffect: ["v3", "v4"],
|
|
36499
36797
|
apply: fn3("unnecessaryEffectGen.apply")(function* (sourceFile, report) {
|
|
36500
36798
|
const ts = yield* service2(TypeScriptApi);
|
|
36501
36799
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36540,6 +36838,8 @@ var unnecessaryFailYieldableError = createDiagnostic({
|
|
|
36540
36838
|
code: 29,
|
|
36541
36839
|
description: "Suggests yielding yieldable errors directly instead of wrapping with Effect.fail",
|
|
36542
36840
|
severity: "suggestion",
|
|
36841
|
+
fixable: true,
|
|
36842
|
+
supportedEffect: ["v3", "v4"],
|
|
36543
36843
|
apply: fn3("unnecessaryFailYieldableError.apply")(function* (sourceFile, report) {
|
|
36544
36844
|
const ts = yield* service2(TypeScriptApi);
|
|
36545
36845
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36599,6 +36899,8 @@ var unnecessaryPipe = createDiagnostic({
|
|
|
36599
36899
|
code: 9,
|
|
36600
36900
|
description: "Removes pipe calls with no arguments",
|
|
36601
36901
|
severity: "suggestion",
|
|
36902
|
+
fixable: true,
|
|
36903
|
+
supportedEffect: ["v3", "v4"],
|
|
36602
36904
|
apply: fn3("unnecessaryPipe.apply")(function* (sourceFile, report) {
|
|
36603
36905
|
const ts = yield* service2(TypeScriptApi);
|
|
36604
36906
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36645,6 +36947,8 @@ var unnecessaryPipeChain = createDiagnostic({
|
|
|
36645
36947
|
code: 16,
|
|
36646
36948
|
description: "Simplifies chained pipe calls into a single pipe call",
|
|
36647
36949
|
severity: "suggestion",
|
|
36950
|
+
fixable: true,
|
|
36951
|
+
supportedEffect: ["v3", "v4"],
|
|
36648
36952
|
apply: fn3("unnecessaryPipeChain.apply")(function* (sourceFile, report) {
|
|
36649
36953
|
const ts = yield* service2(TypeScriptApi);
|
|
36650
36954
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36720,6 +37024,8 @@ var unsupportedServiceAccessors = createDiagnostic({
|
|
|
36720
37024
|
code: 21,
|
|
36721
37025
|
description: "Warns about service accessors that need codegen due to generic/complex signatures",
|
|
36722
37026
|
severity: "warning",
|
|
37027
|
+
fixable: true,
|
|
37028
|
+
supportedEffect: ["v3", "v4"],
|
|
36723
37029
|
apply: fn3("unsupportedServiceAccessors.apply")(function* (sourceFile, report) {
|
|
36724
37030
|
const ts = yield* service2(TypeScriptApi);
|
|
36725
37031
|
const nodeToVisit = [];
|
|
@@ -36822,7 +37128,10 @@ var diagnostics = [
|
|
|
36822
37128
|
effectFnOpportunity,
|
|
36823
37129
|
redundantSchemaTagIdentifier,
|
|
36824
37130
|
schemaSyncInEffect,
|
|
36825
|
-
preferSchemaOverJson
|
|
37131
|
+
preferSchemaOverJson,
|
|
37132
|
+
extendsNativeError,
|
|
37133
|
+
serviceNotAsClass,
|
|
37134
|
+
nodeBuiltinImport
|
|
36826
37135
|
];
|
|
36827
37136
|
|
|
36828
37137
|
// src/cli/diagnostics.ts
|
|
@@ -37757,7 +38066,10 @@ var import_project_service3 = __toESM(require_dist3());
|
|
|
37757
38066
|
var getLocationFromDeclaration = (declaration, tsInstance) => {
|
|
37758
38067
|
const sourceFile = declaration.getSourceFile();
|
|
37759
38068
|
if (!sourceFile) return void 0;
|
|
37760
|
-
const { character, line } = tsInstance.getLineAndCharacterOfPosition(
|
|
38069
|
+
const { character, line } = tsInstance.getLineAndCharacterOfPosition(
|
|
38070
|
+
sourceFile,
|
|
38071
|
+
tsInstance.getTokenPosOfNode(declaration, sourceFile)
|
|
38072
|
+
);
|
|
37761
38073
|
return {
|
|
37762
38074
|
filePath: sourceFile.fileName,
|
|
37763
38075
|
line: line + 1,
|
|
@@ -38359,7 +38671,8 @@ function getExpressionName(tsApi, expr) {
|
|
|
38359
38671
|
if (tsApi.isCallExpression(expr)) {
|
|
38360
38672
|
return getExpressionName(tsApi, expr.expression);
|
|
38361
38673
|
}
|
|
38362
|
-
const
|
|
38674
|
+
const sourceFile = expr.getSourceFile();
|
|
38675
|
+
const text2 = sourceFile.text.substring(tsApi.getTokenPosOfNode(expr, sourceFile), expr.end).replace(/\s+/g, " ");
|
|
38363
38676
|
return text2.length > 30 ? text2.slice(0, 27) + "..." : text2;
|
|
38364
38677
|
}
|
|
38365
38678
|
var collectLayerInfoByName = (sourceFile, layerName, selectedOutputIndices) => gen3(function* () {
|