@effect/language-service 0.78.0 → 0.80.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 +67 -44
- package/cli.js +497 -10
- package/cli.js.map +1 -1
- package/effect-lsp-patch-utils.js +456 -4
- package/effect-lsp-patch-utils.js.map +1 -1
- package/index.js +473 -12
- package/index.js.map +1 -1
- package/package.json +1 -1
- package/transform.js +450 -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.80.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/codegen.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/codegen.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,151 @@ 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
|
|
27538
|
+
};
|
|
27539
|
+
var booleanSchema = (description, defaultValue) => ({
|
|
27540
|
+
type: "boolean",
|
|
27541
|
+
description,
|
|
27542
|
+
default: defaultValue
|
|
27543
|
+
});
|
|
27544
|
+
var stringArraySchema = (description, defaultValue) => ({
|
|
27545
|
+
type: "array",
|
|
27546
|
+
description,
|
|
27547
|
+
default: defaultValue,
|
|
27548
|
+
items: { type: "string" }
|
|
27549
|
+
});
|
|
27550
|
+
var stringEnumSchema = (description, values2, defaultValue) => ({
|
|
27551
|
+
type: "string",
|
|
27552
|
+
description,
|
|
27553
|
+
enum: values2,
|
|
27554
|
+
default: defaultValue
|
|
27555
|
+
});
|
|
27556
|
+
var languageServicePluginAdditionalPropertiesJsonSchema = {
|
|
27557
|
+
refactors: booleanSchema("Controls Effect refactors.", defaults.refactors),
|
|
27558
|
+
diagnostics: booleanSchema("Controls Effect diagnostics.", defaults.diagnostics),
|
|
27559
|
+
diagnosticsName: booleanSchema(
|
|
27560
|
+
"Controls whether to include the rule name in diagnostic messages.",
|
|
27561
|
+
defaults.diagnosticsName
|
|
27562
|
+
),
|
|
27563
|
+
missingDiagnosticNextLine: stringEnumSchema(
|
|
27564
|
+
"Controls the severity of warnings for unused @effect-diagnostics-next-line comments.",
|
|
27565
|
+
["off", "error", "warning", "message", "suggestion"],
|
|
27566
|
+
defaults.missingDiagnosticNextLine
|
|
27567
|
+
),
|
|
27568
|
+
includeSuggestionsInTsc: booleanSchema(
|
|
27569
|
+
"When patch mode is enabled, reports suggestion diagnostics as messages in TSC with a [suggestion] prefix.",
|
|
27570
|
+
defaults.includeSuggestionsInTsc
|
|
27571
|
+
),
|
|
27572
|
+
ignoreEffectWarningsInTscExitCode: booleanSchema(
|
|
27573
|
+
"When enabled, Effect warnings do not affect the patched tsc exit code.",
|
|
27574
|
+
defaults.ignoreEffectWarningsInTscExitCode
|
|
27575
|
+
),
|
|
27576
|
+
ignoreEffectErrorsInTscExitCode: booleanSchema(
|
|
27577
|
+
"When enabled, Effect errors do not affect the patched tsc exit code.",
|
|
27578
|
+
defaults.ignoreEffectErrorsInTscExitCode
|
|
27579
|
+
),
|
|
27580
|
+
ignoreEffectSuggestionsInTscExitCode: booleanSchema(
|
|
27581
|
+
"When enabled, Effect suggestions do not affect the patched tsc exit code.",
|
|
27582
|
+
defaults.ignoreEffectSuggestionsInTscExitCode
|
|
27583
|
+
),
|
|
27584
|
+
quickinfoEffectParameters: stringEnumSchema(
|
|
27585
|
+
"Controls when Effect quickinfo should include full type parameters.",
|
|
27586
|
+
["always", "never", "whentruncated"],
|
|
27587
|
+
defaults.quickinfoEffectParameters
|
|
27588
|
+
),
|
|
27589
|
+
quickinfo: booleanSchema("Controls Effect quickinfo.", defaults.quickinfo),
|
|
27590
|
+
quickinfoMaximumLength: {
|
|
27591
|
+
type: "number",
|
|
27592
|
+
description: "Controls the maximum quickinfo length. Use -1 to disable truncation.",
|
|
27593
|
+
default: defaults.quickinfoMaximumLength
|
|
27594
|
+
},
|
|
27595
|
+
keyPatterns: {
|
|
27596
|
+
type: "array",
|
|
27597
|
+
description: "Configures key patterns used for generated Effect service and error keys.",
|
|
27598
|
+
default: defaults.keyPatterns,
|
|
27599
|
+
items: {
|
|
27600
|
+
type: "object",
|
|
27601
|
+
properties: {
|
|
27602
|
+
target: stringEnumSchema("The key builder target.", ["service", "error", "custom"], "service"),
|
|
27603
|
+
pattern: stringEnumSchema(
|
|
27604
|
+
"The key generation pattern.",
|
|
27605
|
+
["package-identifier", "default", "default-hashed"],
|
|
27606
|
+
"default"
|
|
27607
|
+
),
|
|
27608
|
+
skipLeadingPath: stringArraySchema("Path prefixes to strip before generating keys.", ["src/"])
|
|
27609
|
+
}
|
|
27610
|
+
}
|
|
27611
|
+
},
|
|
27612
|
+
extendedKeyDetection: booleanSchema(
|
|
27613
|
+
"Enables extended heuristics when detecting key sources.",
|
|
27614
|
+
defaults.extendedKeyDetection
|
|
27615
|
+
),
|
|
27616
|
+
completions: booleanSchema("Controls Effect completions.", defaults.completions),
|
|
27617
|
+
goto: booleanSchema("Controls Effect goto references support.", defaults.goto),
|
|
27618
|
+
inlays: booleanSchema("Controls Effect inlay hints.", defaults.inlays),
|
|
27619
|
+
allowedDuplicatedPackages: stringArraySchema(
|
|
27620
|
+
"Package names that are allowed to duplicate Effect as a peer dependency.",
|
|
27621
|
+
defaults.allowedDuplicatedPackages
|
|
27622
|
+
),
|
|
27623
|
+
namespaceImportPackages: stringArraySchema(
|
|
27624
|
+
"Package names that should prefer namespace imports.",
|
|
27625
|
+
defaults.namespaceImportPackages
|
|
27626
|
+
),
|
|
27627
|
+
topLevelNamedReexports: stringEnumSchema(
|
|
27628
|
+
"For namespaceImportPackages, controls how top-level named re-exports are handled.",
|
|
27629
|
+
["ignore", "follow"],
|
|
27630
|
+
defaults.topLevelNamedReexports
|
|
27631
|
+
),
|
|
27632
|
+
barrelImportPackages: stringArraySchema(
|
|
27633
|
+
"Package names that should prefer imports from their top-level barrel file.",
|
|
27634
|
+
defaults.barrelImportPackages
|
|
27635
|
+
),
|
|
27636
|
+
importAliases: {
|
|
27637
|
+
type: "object",
|
|
27638
|
+
description: "Custom aliases to use for imported identifiers.",
|
|
27639
|
+
default: defaults.importAliases,
|
|
27640
|
+
additionalProperties: {
|
|
27641
|
+
type: "string"
|
|
27642
|
+
}
|
|
27643
|
+
},
|
|
27644
|
+
renames: booleanSchema("Controls Effect rename helpers.", defaults.renames),
|
|
27645
|
+
noExternal: booleanSchema(
|
|
27646
|
+
"Disables features that link to external websites.",
|
|
27647
|
+
defaults.noExternal
|
|
27648
|
+
),
|
|
27649
|
+
pipeableMinArgCount: {
|
|
27650
|
+
type: "number",
|
|
27651
|
+
description: "Minimum argument count required before pipeable suggestions are emitted.",
|
|
27652
|
+
default: defaults.pipeableMinArgCount
|
|
27653
|
+
},
|
|
27654
|
+
effectFn: {
|
|
27655
|
+
type: "array",
|
|
27656
|
+
description: "Configures which Effect.fn variants should be suggested.",
|
|
27657
|
+
default: defaults.effectFn,
|
|
27658
|
+
items: {
|
|
27659
|
+
type: "string",
|
|
27660
|
+
enum: ["untraced", "span", "suggested-span", "inferred-span", "no-span"]
|
|
27661
|
+
}
|
|
27662
|
+
},
|
|
27663
|
+
layerGraphFollowDepth: {
|
|
27664
|
+
type: "number",
|
|
27665
|
+
description: "Controls how deeply layer graph analysis follows dependencies.",
|
|
27666
|
+
default: defaults.layerGraphFollowDepth
|
|
27667
|
+
},
|
|
27668
|
+
mermaidProvider: {
|
|
27669
|
+
type: "string",
|
|
27670
|
+
description: "Controls which Mermaid renderer is used for layer graphs.",
|
|
27671
|
+
default: defaults.mermaidProvider
|
|
27672
|
+
},
|
|
27673
|
+
skipDisabledOptimization: booleanSchema(
|
|
27674
|
+
"When enabled, disabled diagnostics are still processed so comment-based overrides can be honored.",
|
|
27675
|
+
defaults.skipDisabledOptimization
|
|
27676
|
+
)
|
|
27534
27677
|
};
|
|
27535
27678
|
function parseKeyPatterns(patterns) {
|
|
27536
27679
|
const result3 = [];
|
|
@@ -27554,6 +27697,7 @@ function parse4(config) {
|
|
|
27554
27697
|
includeSuggestionsInTsc: isObject(config) && hasProperty(config, "includeSuggestionsInTsc") && isBoolean(config.includeSuggestionsInTsc) ? config.includeSuggestionsInTsc : defaults.includeSuggestionsInTsc,
|
|
27555
27698
|
ignoreEffectWarningsInTscExitCode: isObject(config) && hasProperty(config, "ignoreEffectWarningsInTscExitCode") && isBoolean(config.ignoreEffectWarningsInTscExitCode) ? config.ignoreEffectWarningsInTscExitCode : defaults.ignoreEffectWarningsInTscExitCode,
|
|
27556
27699
|
ignoreEffectSuggestionsInTscExitCode: isObject(config) && hasProperty(config, "ignoreEffectSuggestionsInTscExitCode") && isBoolean(config.ignoreEffectSuggestionsInTscExitCode) ? config.ignoreEffectSuggestionsInTscExitCode : defaults.ignoreEffectSuggestionsInTscExitCode,
|
|
27700
|
+
ignoreEffectErrorsInTscExitCode: isObject(config) && hasProperty(config, "ignoreEffectErrorsInTscExitCode") && isBoolean(config.ignoreEffectErrorsInTscExitCode) ? config.ignoreEffectErrorsInTscExitCode : defaults.ignoreEffectErrorsInTscExitCode,
|
|
27557
27701
|
quickinfo: isObject(config) && hasProperty(config, "quickinfo") && isBoolean(config.quickinfo) ? config.quickinfo : defaults.quickinfo,
|
|
27558
27702
|
quickinfoEffectParameters: isObject(config) && hasProperty(config, "quickinfoEffectParameters") && isString(config.quickinfoEffectParameters) && ["always", "never", "whentruncated"].includes(config.quickinfoEffectParameters.toLowerCase()) ? config.quickinfoEffectParameters.toLowerCase() : defaults.quickinfoEffectParameters,
|
|
27559
27703
|
quickinfoMaximumLength: isObject(config) && hasProperty(config, "quickinfoMaximumLength") && isNumber(config.quickinfoMaximumLength) ? config.quickinfoMaximumLength : defaults.quickinfoMaximumLength,
|
|
@@ -27574,7 +27718,8 @@ function parse4(config) {
|
|
|
27574
27718
|
(_) => _.toLowerCase()
|
|
27575
27719
|
) : defaults.effectFn,
|
|
27576
27720
|
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
|
|
27721
|
+
mermaidProvider: isObject(config) && hasProperty(config, "mermaidProvider") && isString(config.mermaidProvider) ? config.mermaidProvider : defaults.mermaidProvider,
|
|
27722
|
+
skipDisabledOptimization: isObject(config) && hasProperty(config, "skipDisabledOptimization") && isBoolean(config.skipDisabledOptimization) ? config.skipDisabledOptimization : defaults.skipDisabledOptimization
|
|
27578
27723
|
};
|
|
27579
27724
|
}
|
|
27580
27725
|
|
|
@@ -27758,7 +27903,7 @@ var createDiagnosticExecutor = fn3("LSP.createCommentDirectivesProcessor")(
|
|
|
27758
27903
|
if (skippedRules.indexOf(ruleNameLowered) > -1 || skippedRules.indexOf("*") > -1) {
|
|
27759
27904
|
return { diagnostics: diagnostics3, codeFixes };
|
|
27760
27905
|
}
|
|
27761
|
-
if (defaultLevel === "off" && (lineOverrides[ruleNameLowered] || sectionOverrides[ruleNameLowered] || lineOverrides["*"] || sectionOverrides["*"] || []).length === 0) {
|
|
27906
|
+
if (!pluginOptions.skipDisabledOptimization && defaultLevel === "off" && (lineOverrides[ruleNameLowered] || sectionOverrides[ruleNameLowered] || lineOverrides["*"] || sectionOverrides["*"] || []).length === 0) {
|
|
27762
27907
|
return { diagnostics: diagnostics3, codeFixes };
|
|
27763
27908
|
}
|
|
27764
27909
|
const fixByDisableNextLine = (node) => ({
|
|
@@ -31656,6 +31801,8 @@ var anyUnknownInErrorContext = createDiagnostic({
|
|
|
31656
31801
|
code: 28,
|
|
31657
31802
|
description: "Detects 'any' or 'unknown' types in Effect error or requirements channels",
|
|
31658
31803
|
severity: "off",
|
|
31804
|
+
fixable: false,
|
|
31805
|
+
supportedEffect: ["v3", "v4"],
|
|
31659
31806
|
apply: fn3("anyUnknownInErrorContext.apply")(function* (sourceFile, report) {
|
|
31660
31807
|
const ts = yield* service2(TypeScriptApi);
|
|
31661
31808
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -31759,6 +31906,8 @@ var catchAllToMapError = createDiagnostic({
|
|
|
31759
31906
|
code: 39,
|
|
31760
31907
|
description: "Suggests using Effect.mapError instead of Effect.catchAll when the callback only wraps the error with Effect.fail",
|
|
31761
31908
|
severity: "suggestion",
|
|
31909
|
+
fixable: true,
|
|
31910
|
+
supportedEffect: ["v3", "v4"],
|
|
31762
31911
|
apply: fn3("catchAllToMapError.apply")(function* (sourceFile, report) {
|
|
31763
31912
|
const ts = yield* service2(TypeScriptApi);
|
|
31764
31913
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -31856,6 +32005,8 @@ var catchUnfailableEffect = createDiagnostic({
|
|
|
31856
32005
|
code: 2,
|
|
31857
32006
|
description: "Warns when using error handling on Effects that never fail (error type is 'never')",
|
|
31858
32007
|
severity: "suggestion",
|
|
32008
|
+
fixable: false,
|
|
32009
|
+
supportedEffect: ["v3", "v4"],
|
|
31859
32010
|
apply: fn3("catchUnfailableEffect.apply")(function* (sourceFile, report) {
|
|
31860
32011
|
const ts = yield* service2(TypeScriptApi);
|
|
31861
32012
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -31905,6 +32056,8 @@ var classSelfMismatch = createDiagnostic({
|
|
|
31905
32056
|
code: 20,
|
|
31906
32057
|
description: "Ensures Self type parameter matches the class name in Service/Tag/Schema classes",
|
|
31907
32058
|
severity: "error",
|
|
32059
|
+
fixable: true,
|
|
32060
|
+
supportedEffect: ["v3", "v4"],
|
|
31908
32061
|
apply: fn3("classSelfMismatch.apply")(function* (sourceFile, report) {
|
|
31909
32062
|
const ts = yield* service2(TypeScriptApi);
|
|
31910
32063
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -32043,6 +32196,8 @@ var deterministicKeys = createDiagnostic({
|
|
|
32043
32196
|
code: 25,
|
|
32044
32197
|
description: "Enforces deterministic naming for service/tag/error identifiers based on class names",
|
|
32045
32198
|
severity: "off",
|
|
32199
|
+
fixable: true,
|
|
32200
|
+
supportedEffect: ["v3", "v4"],
|
|
32046
32201
|
apply: fn3("deterministicKeys.apply")(function* (sourceFile, report) {
|
|
32047
32202
|
const ts = yield* service2(TypeScriptApi);
|
|
32048
32203
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -32160,6 +32315,8 @@ var duplicatePackage = createDiagnostic({
|
|
|
32160
32315
|
code: 6,
|
|
32161
32316
|
description: "Detects when multiple versions of the same Effect package are loaded",
|
|
32162
32317
|
severity: "warning",
|
|
32318
|
+
fixable: false,
|
|
32319
|
+
supportedEffect: ["v3", "v4"],
|
|
32163
32320
|
apply: fn3("duplicatePackage.apply")(function* (sourceFile, report) {
|
|
32164
32321
|
const typeParser = yield* service2(TypeParser);
|
|
32165
32322
|
const options = yield* service2(LanguageServicePluginOptions);
|
|
@@ -32189,6 +32346,8 @@ var effectFnIife = createDiagnostic({
|
|
|
32189
32346
|
code: 46,
|
|
32190
32347
|
description: "Effect.fn or Effect.fnUntraced is called as an IIFE (Immediately Invoked Function Expression). Use Effect.gen instead.",
|
|
32191
32348
|
severity: "warning",
|
|
32349
|
+
fixable: true,
|
|
32350
|
+
supportedEffect: ["v3", "v4"],
|
|
32192
32351
|
apply: fn3("effectFnIife.apply")(function* (sourceFile, report) {
|
|
32193
32352
|
const ts = yield* service2(TypeScriptApi);
|
|
32194
32353
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -32291,6 +32450,8 @@ var effectFnOpportunity = createDiagnostic({
|
|
|
32291
32450
|
code: 41,
|
|
32292
32451
|
description: "Suggests using Effect.fn for functions that returns an Effect",
|
|
32293
32452
|
severity: "suggestion",
|
|
32453
|
+
fixable: true,
|
|
32454
|
+
supportedEffect: ["v3", "v4"],
|
|
32294
32455
|
apply: fn3("effectFnOpportunity.apply")(function* (sourceFile, report) {
|
|
32295
32456
|
const ts = yield* service2(TypeScriptApi);
|
|
32296
32457
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -32883,6 +33044,8 @@ var effectGenUsesAdapter = createDiagnostic({
|
|
|
32883
33044
|
code: 23,
|
|
32884
33045
|
description: "Warns when using the deprecated adapter parameter in Effect.gen",
|
|
32885
33046
|
severity: "warning",
|
|
33047
|
+
fixable: false,
|
|
33048
|
+
supportedEffect: ["v3", "v4"],
|
|
32886
33049
|
apply: fn3("effectGenUsesAdapter.apply")(function* (sourceFile, report) {
|
|
32887
33050
|
const ts = yield* service2(TypeScriptApi);
|
|
32888
33051
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -32921,6 +33084,8 @@ var effectInFailure = createDiagnostic({
|
|
|
32921
33084
|
code: 49,
|
|
32922
33085
|
description: "Warns when an Effect is used inside an Effect failure channel",
|
|
32923
33086
|
severity: "warning",
|
|
33087
|
+
fixable: false,
|
|
33088
|
+
supportedEffect: ["v3", "v4"],
|
|
32924
33089
|
apply: fn3("effectInFailure.apply")(function* (sourceFile, report) {
|
|
32925
33090
|
const ts = yield* service2(TypeScriptApi);
|
|
32926
33091
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -32985,6 +33150,8 @@ var effectInVoidSuccess = createDiagnostic({
|
|
|
32985
33150
|
code: 14,
|
|
32986
33151
|
description: "Detects nested Effects in void success channels that may cause unexecuted effects",
|
|
32987
33152
|
severity: "warning",
|
|
33153
|
+
fixable: false,
|
|
33154
|
+
supportedEffect: ["v3", "v4"],
|
|
32988
33155
|
apply: fn3("effectInVoidSuccess.apply")(function* (sourceFile, report) {
|
|
32989
33156
|
const ts = yield* service2(TypeScriptApi);
|
|
32990
33157
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -33034,6 +33201,8 @@ var effectMapVoid = createDiagnostic({
|
|
|
33034
33201
|
code: 40,
|
|
33035
33202
|
description: "Suggests using Effect.asVoid instead of Effect.map(() => void 0), Effect.map(() => undefined), or Effect.map(() => {})",
|
|
33036
33203
|
severity: "suggestion",
|
|
33204
|
+
fixable: true,
|
|
33205
|
+
supportedEffect: ["v3", "v4"],
|
|
33037
33206
|
apply: fn3("effectMapVoid.apply")(function* (sourceFile, report) {
|
|
33038
33207
|
const ts = yield* service2(TypeScriptApi);
|
|
33039
33208
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33098,6 +33267,8 @@ var effectSucceedWithVoid = createDiagnostic({
|
|
|
33098
33267
|
code: 47,
|
|
33099
33268
|
description: "Suggests using Effect.void instead of Effect.succeed(undefined) or Effect.succeed(void 0)",
|
|
33100
33269
|
severity: "suggestion",
|
|
33270
|
+
fixable: true,
|
|
33271
|
+
supportedEffect: ["v3", "v4"],
|
|
33101
33272
|
apply: fn3("effectSucceedWithVoid.apply")(function* (sourceFile, report) {
|
|
33102
33273
|
const ts = yield* service2(TypeScriptApi);
|
|
33103
33274
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33143,12 +33314,66 @@ var effectSucceedWithVoid = createDiagnostic({
|
|
|
33143
33314
|
})
|
|
33144
33315
|
});
|
|
33145
33316
|
|
|
33317
|
+
// src/diagnostics/extendsNativeError.ts
|
|
33318
|
+
var extendsNativeError = createDiagnostic({
|
|
33319
|
+
name: "extendsNativeError",
|
|
33320
|
+
code: 50,
|
|
33321
|
+
description: "Warns when a class directly extends the native Error class",
|
|
33322
|
+
severity: "off",
|
|
33323
|
+
fixable: false,
|
|
33324
|
+
supportedEffect: ["v3", "v4"],
|
|
33325
|
+
apply: fn3("extendsNativeError.apply")(function* (sourceFile, report) {
|
|
33326
|
+
const ts = yield* service2(TypeScriptApi);
|
|
33327
|
+
const typeChecker = yield* service2(TypeCheckerApi);
|
|
33328
|
+
const errorSymbol = typeChecker.resolveName("Error", void 0, ts.SymbolFlags.Type, false);
|
|
33329
|
+
if (!errorSymbol) return;
|
|
33330
|
+
const nodeToVisit = [];
|
|
33331
|
+
const appendNodeToVisit = (node) => {
|
|
33332
|
+
nodeToVisit.push(node);
|
|
33333
|
+
return void 0;
|
|
33334
|
+
};
|
|
33335
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
33336
|
+
while (nodeToVisit.length > 0) {
|
|
33337
|
+
const node = nodeToVisit.shift();
|
|
33338
|
+
if (ts.isClassDeclaration(node) && node.heritageClauses) {
|
|
33339
|
+
for (const clause of node.heritageClauses) {
|
|
33340
|
+
if (clause.token === ts.SyntaxKind.ExtendsKeyword && clause.types.length > 0) {
|
|
33341
|
+
const typeExpression = clause.types[0].expression;
|
|
33342
|
+
const exprSymbol = typeChecker.getSymbolAtLocation(typeExpression);
|
|
33343
|
+
const resolvedSymbol = exprSymbol && exprSymbol.flags & ts.SymbolFlags.Alias ? typeChecker.getAliasedSymbol(exprSymbol) : exprSymbol;
|
|
33344
|
+
const isNativeError = resolvedSymbol === errorSymbol || (() => {
|
|
33345
|
+
if (!resolvedSymbol || resolvedSymbol === errorSymbol) return false;
|
|
33346
|
+
const exprType = typeChecker.getTypeAtLocation(typeExpression);
|
|
33347
|
+
const constructSignatures = typeChecker.getSignaturesOfType(exprType, ts.SignatureKind.Construct);
|
|
33348
|
+
if (constructSignatures.length > 0) {
|
|
33349
|
+
const instanceType = typeChecker.getReturnTypeOfSignature(constructSignatures[0]);
|
|
33350
|
+
return instanceType.symbol === errorSymbol;
|
|
33351
|
+
}
|
|
33352
|
+
return false;
|
|
33353
|
+
})();
|
|
33354
|
+
if (isNativeError) {
|
|
33355
|
+
report({
|
|
33356
|
+
location: node.name ?? typeExpression,
|
|
33357
|
+
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.",
|
|
33358
|
+
fixes: []
|
|
33359
|
+
});
|
|
33360
|
+
}
|
|
33361
|
+
}
|
|
33362
|
+
}
|
|
33363
|
+
}
|
|
33364
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
33365
|
+
}
|
|
33366
|
+
})
|
|
33367
|
+
});
|
|
33368
|
+
|
|
33146
33369
|
// src/diagnostics/floatingEffect.ts
|
|
33147
33370
|
var floatingEffect = createDiagnostic({
|
|
33148
33371
|
name: "floatingEffect",
|
|
33149
33372
|
code: 3,
|
|
33150
33373
|
description: "Ensures Effects are yielded or assigned to variables, not left floating",
|
|
33151
33374
|
severity: "error",
|
|
33375
|
+
fixable: false,
|
|
33376
|
+
supportedEffect: ["v3", "v4"],
|
|
33152
33377
|
apply: fn3("floatingEffect.apply")(function* (sourceFile, report) {
|
|
33153
33378
|
const ts = yield* service2(TypeScriptApi);
|
|
33154
33379
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -33200,6 +33425,8 @@ var genericEffectServices = createDiagnostic({
|
|
|
33200
33425
|
code: 10,
|
|
33201
33426
|
description: "Prevents services with type parameters that cannot be discriminated at runtime",
|
|
33202
33427
|
severity: "warning",
|
|
33428
|
+
fixable: false,
|
|
33429
|
+
supportedEffect: ["v3", "v4"],
|
|
33203
33430
|
apply: fn3("genericEffectServices.apply")(function* (sourceFile, report) {
|
|
33204
33431
|
const ts = yield* service2(TypeScriptApi);
|
|
33205
33432
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33247,6 +33474,8 @@ var globalErrorInEffectCatch = createDiagnostic({
|
|
|
33247
33474
|
code: 36,
|
|
33248
33475
|
description: "Warns when catch callbacks return global Error type instead of typed errors",
|
|
33249
33476
|
severity: "warning",
|
|
33477
|
+
fixable: false,
|
|
33478
|
+
supportedEffect: ["v3", "v4"],
|
|
33250
33479
|
apply: fn3("globalErrorInEffectCatch.apply")(function* (sourceFile, report) {
|
|
33251
33480
|
const ts = yield* service2(TypeScriptApi);
|
|
33252
33481
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33307,6 +33536,8 @@ var globalErrorInEffectFailure = createDiagnostic({
|
|
|
33307
33536
|
code: 35,
|
|
33308
33537
|
description: "Warns when the global Error type is used in an Effect failure channel",
|
|
33309
33538
|
severity: "warning",
|
|
33539
|
+
fixable: false,
|
|
33540
|
+
supportedEffect: ["v3", "v4"],
|
|
33310
33541
|
apply: fn3("globalErrorInEffectFailure.apply")(function* (sourceFile, report) {
|
|
33311
33542
|
const ts = yield* service2(TypeScriptApi);
|
|
33312
33543
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33360,6 +33591,8 @@ var importFromBarrel = createDiagnostic({
|
|
|
33360
33591
|
code: 12,
|
|
33361
33592
|
description: "Suggests importing from specific module paths instead of barrel exports",
|
|
33362
33593
|
severity: "off",
|
|
33594
|
+
fixable: true,
|
|
33595
|
+
supportedEffect: ["v3", "v4"],
|
|
33363
33596
|
apply: fn3("importFromBarrel.apply")(function* (sourceFile, report) {
|
|
33364
33597
|
const languageServicePluginOptions = yield* service2(LanguageServicePluginOptions);
|
|
33365
33598
|
if (languageServicePluginOptions.namespaceImportPackages.length === 0) return;
|
|
@@ -33500,6 +33733,8 @@ var instanceOfSchema = createDiagnostic({
|
|
|
33500
33733
|
code: 45,
|
|
33501
33734
|
description: "Suggests using Schema.is instead of instanceof for Effect Schema types",
|
|
33502
33735
|
severity: "off",
|
|
33736
|
+
fixable: true,
|
|
33737
|
+
supportedEffect: ["v3", "v4"],
|
|
33503
33738
|
apply: fn3("instanceOfSchema.apply")(function* (sourceFile, report) {
|
|
33504
33739
|
const ts = yield* service2(TypeScriptApi);
|
|
33505
33740
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -33563,6 +33798,8 @@ var layerMergeAllWithDependencies = createDiagnostic({
|
|
|
33563
33798
|
code: 37,
|
|
33564
33799
|
description: "Detects interdependencies in Layer.mergeAll calls where one layer provides a service that another layer requires",
|
|
33565
33800
|
severity: "warning",
|
|
33801
|
+
fixable: true,
|
|
33802
|
+
supportedEffect: ["v3", "v4"],
|
|
33566
33803
|
apply: fn3("layerMergeAllWithDependencies.apply")(function* (sourceFile, report) {
|
|
33567
33804
|
const ts = yield* service2(TypeScriptApi);
|
|
33568
33805
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -33676,6 +33913,8 @@ var leakingRequirements = createDiagnostic({
|
|
|
33676
33913
|
code: 8,
|
|
33677
33914
|
description: "Detects implementation services leaked in service methods",
|
|
33678
33915
|
severity: "suggestion",
|
|
33916
|
+
fixable: false,
|
|
33917
|
+
supportedEffect: ["v3", "v4"],
|
|
33679
33918
|
apply: fn3("leakingRequirements.apply")(function* (sourceFile, report) {
|
|
33680
33919
|
const ts = yield* service2(TypeScriptApi);
|
|
33681
33920
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -33830,6 +34069,8 @@ var missedPipeableOpportunity = createDiagnostic({
|
|
|
33830
34069
|
code: 26,
|
|
33831
34070
|
description: "Enforces the use of pipeable style for nested function calls",
|
|
33832
34071
|
severity: "off",
|
|
34072
|
+
fixable: true,
|
|
34073
|
+
supportedEffect: ["v3", "v4"],
|
|
33833
34074
|
apply: fn3("missedPipeableOpportunity.apply")(function* (sourceFile, report) {
|
|
33834
34075
|
const ts = yield* service2(TypeScriptApi);
|
|
33835
34076
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -34010,6 +34251,8 @@ var missingEffectContext = createDiagnostic({
|
|
|
34010
34251
|
code: 1,
|
|
34011
34252
|
description: "Reports missing service requirements in Effect context channel",
|
|
34012
34253
|
severity: "error",
|
|
34254
|
+
fixable: false,
|
|
34255
|
+
supportedEffect: ["v3", "v4"],
|
|
34013
34256
|
apply: fn3("missingEffectContext.apply")(function* (sourceFile, report) {
|
|
34014
34257
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
34015
34258
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -34059,6 +34302,8 @@ var missingEffectError = createDiagnostic({
|
|
|
34059
34302
|
code: 1,
|
|
34060
34303
|
description: "Reports missing error types in Effect error channel",
|
|
34061
34304
|
severity: "error",
|
|
34305
|
+
fixable: true,
|
|
34306
|
+
supportedEffect: ["v3", "v4"],
|
|
34062
34307
|
apply: fn3("missingEffectError.apply")(function* (sourceFile, report) {
|
|
34063
34308
|
const ts = yield* service2(TypeScriptApi);
|
|
34064
34309
|
const tsUtils = yield* service2(TypeScriptUtils);
|
|
@@ -34200,6 +34445,8 @@ var missingEffectServiceDependency = createDiagnostic({
|
|
|
34200
34445
|
code: 22,
|
|
34201
34446
|
description: "Checks that Effect.Service dependencies satisfy all required layer inputs",
|
|
34202
34447
|
severity: "off",
|
|
34448
|
+
fixable: false,
|
|
34449
|
+
supportedEffect: ["v3"],
|
|
34203
34450
|
apply: fn3("missingEffectServiceDependency.apply")(function* (sourceFile, report) {
|
|
34204
34451
|
const ts = yield* service2(TypeScriptApi);
|
|
34205
34452
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -34294,6 +34541,8 @@ var missingLayerContext = createDiagnostic({
|
|
|
34294
34541
|
code: 38,
|
|
34295
34542
|
description: "Reports missing service requirements in Layer context channel",
|
|
34296
34543
|
severity: "error",
|
|
34544
|
+
fixable: false,
|
|
34545
|
+
supportedEffect: ["v3", "v4"],
|
|
34297
34546
|
apply: fn3("missingLayerContext.apply")(function* (sourceFile, report) {
|
|
34298
34547
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
34299
34548
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -34343,6 +34592,8 @@ var missingReturnYieldStar = createDiagnostic({
|
|
|
34343
34592
|
code: 7,
|
|
34344
34593
|
description: "Suggests using 'return yield*' for Effects with never success for better type narrowing",
|
|
34345
34594
|
severity: "error",
|
|
34595
|
+
fixable: true,
|
|
34596
|
+
supportedEffect: ["v3", "v4"],
|
|
34346
34597
|
apply: fn3("missingReturnYieldStar.apply")(function* (sourceFile, report) {
|
|
34347
34598
|
const ts = yield* service2(TypeScriptApi);
|
|
34348
34599
|
const typeCheckerUtils = yield* service2(TypeCheckerUtils);
|
|
@@ -34393,6 +34644,8 @@ var missingStarInYieldEffectGen = createDiagnostic({
|
|
|
34393
34644
|
code: 4,
|
|
34394
34645
|
description: "Enforces using 'yield*' instead of 'yield' when yielding Effects in generators",
|
|
34395
34646
|
severity: "error",
|
|
34647
|
+
fixable: true,
|
|
34648
|
+
supportedEffect: ["v3", "v4"],
|
|
34396
34649
|
apply: fn3("missingStarInYieldEffectGen.apply")(function* (sourceFile, report) {
|
|
34397
34650
|
const ts = yield* service2(TypeScriptApi);
|
|
34398
34651
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -34468,6 +34721,8 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
34468
34721
|
code: 18,
|
|
34469
34722
|
description: "Warns against chaining Effect.provide calls which can cause service lifecycle issues",
|
|
34470
34723
|
severity: "warning",
|
|
34724
|
+
fixable: true,
|
|
34725
|
+
supportedEffect: ["v3", "v4"],
|
|
34471
34726
|
apply: fn3("multipleEffectProvide.apply")(function* (sourceFile, report) {
|
|
34472
34727
|
const ts = yield* service2(TypeScriptApi);
|
|
34473
34728
|
const tsUtils = yield* service2(TypeScriptUtils);
|
|
@@ -34554,12 +34809,85 @@ var multipleEffectProvide = createDiagnostic({
|
|
|
34554
34809
|
})
|
|
34555
34810
|
});
|
|
34556
34811
|
|
|
34812
|
+
// src/diagnostics/nodeBuiltinImport.ts
|
|
34813
|
+
var moduleAlternativesV3 = /* @__PURE__ */ new Map([
|
|
34814
|
+
["fs", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
|
|
34815
|
+
["node:fs", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
|
|
34816
|
+
["fs/promises", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
|
|
34817
|
+
["node:fs/promises", { alternative: "FileSystem", module: "fs", package: "@effect/platform" }],
|
|
34818
|
+
["path", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34819
|
+
["node:path", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34820
|
+
["path/posix", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34821
|
+
["node:path/posix", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34822
|
+
["path/win32", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34823
|
+
["node:path/win32", { alternative: "Path", module: "path", package: "@effect/platform" }],
|
|
34824
|
+
["child_process", { alternative: "CommandExecutor", module: "child_process", package: "@effect/platform" }],
|
|
34825
|
+
["node:child_process", { alternative: "CommandExecutor", module: "child_process", package: "@effect/platform" }]
|
|
34826
|
+
]);
|
|
34827
|
+
var moduleAlternativesV4 = /* @__PURE__ */ new Map([
|
|
34828
|
+
["fs", { alternative: "FileSystem", module: "fs", package: "effect" }],
|
|
34829
|
+
["node:fs", { alternative: "FileSystem", module: "fs", package: "effect" }],
|
|
34830
|
+
["fs/promises", { alternative: "FileSystem", module: "fs", package: "effect" }],
|
|
34831
|
+
["node:fs/promises", { alternative: "FileSystem", module: "fs", package: "effect" }],
|
|
34832
|
+
["path", { alternative: "Path", module: "path", package: "effect" }],
|
|
34833
|
+
["node:path", { alternative: "Path", module: "path", package: "effect" }],
|
|
34834
|
+
["path/posix", { alternative: "Path", module: "path", package: "effect" }],
|
|
34835
|
+
["node:path/posix", { alternative: "Path", module: "path", package: "effect" }],
|
|
34836
|
+
["path/win32", { alternative: "Path", module: "path", package: "effect" }],
|
|
34837
|
+
["node:path/win32", { alternative: "Path", module: "path", package: "effect" }],
|
|
34838
|
+
["child_process", { alternative: "ChildProcess", module: "child_process", package: "effect" }],
|
|
34839
|
+
["node:child_process", { alternative: "ChildProcess", module: "child_process", package: "effect" }]
|
|
34840
|
+
]);
|
|
34841
|
+
var nodeBuiltinImport = createDiagnostic({
|
|
34842
|
+
name: "nodeBuiltinImport",
|
|
34843
|
+
code: 52,
|
|
34844
|
+
description: "Warns when importing Node.js built-in modules that have Effect-native counterparts",
|
|
34845
|
+
severity: "off",
|
|
34846
|
+
fixable: false,
|
|
34847
|
+
supportedEffect: ["v3", "v4"],
|
|
34848
|
+
apply: fn3("nodeBuiltinImport.apply")(function* (sourceFile, report) {
|
|
34849
|
+
const ts = yield* service2(TypeScriptApi);
|
|
34850
|
+
const typeParser = yield* service2(TypeParser);
|
|
34851
|
+
const moduleAlternatives = typeParser.supportedEffect() === "v3" ? moduleAlternativesV3 : moduleAlternativesV4;
|
|
34852
|
+
for (const statement of sourceFile.statements) {
|
|
34853
|
+
if (ts.isImportDeclaration(statement) && ts.isStringLiteral(statement.moduleSpecifier)) {
|
|
34854
|
+
const specifier = statement.moduleSpecifier.text;
|
|
34855
|
+
const match9 = moduleAlternatives.get(specifier);
|
|
34856
|
+
if (match9) {
|
|
34857
|
+
report({
|
|
34858
|
+
location: statement.moduleSpecifier,
|
|
34859
|
+
messageText: `Prefer using ${match9.alternative} from ${match9.package} instead of the Node.js '${match9.module}' module.`,
|
|
34860
|
+
fixes: []
|
|
34861
|
+
});
|
|
34862
|
+
}
|
|
34863
|
+
} else if (ts.isVariableStatement(statement)) {
|
|
34864
|
+
for (const decl of statement.declarationList.declarations) {
|
|
34865
|
+
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])) {
|
|
34866
|
+
const arg = decl.initializer.arguments[0];
|
|
34867
|
+
const specifier = arg.text;
|
|
34868
|
+
const match9 = moduleAlternatives.get(specifier);
|
|
34869
|
+
if (match9) {
|
|
34870
|
+
report({
|
|
34871
|
+
location: arg,
|
|
34872
|
+
messageText: `Prefer using ${match9.alternative} from ${match9.package} instead of the Node.js '${match9.module}' module.`,
|
|
34873
|
+
fixes: []
|
|
34874
|
+
});
|
|
34875
|
+
}
|
|
34876
|
+
}
|
|
34877
|
+
}
|
|
34878
|
+
}
|
|
34879
|
+
}
|
|
34880
|
+
})
|
|
34881
|
+
});
|
|
34882
|
+
|
|
34557
34883
|
// src/diagnostics/nonObjectEffectServiceType.ts
|
|
34558
34884
|
var nonObjectEffectServiceType = createDiagnostic({
|
|
34559
34885
|
name: "nonObjectEffectServiceType",
|
|
34560
34886
|
code: 24,
|
|
34561
34887
|
description: "Ensures Effect.Service types are objects, not primitives",
|
|
34562
34888
|
severity: "error",
|
|
34889
|
+
fixable: false,
|
|
34890
|
+
supportedEffect: ["v3"],
|
|
34563
34891
|
apply: fn3("nonObjectEffectServiceType.apply")(function* (sourceFile, report) {
|
|
34564
34892
|
const ts = yield* service2(TypeScriptApi);
|
|
34565
34893
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -35342,6 +35670,8 @@ var outdatedApi = createDiagnostic({
|
|
|
35342
35670
|
code: 48,
|
|
35343
35671
|
description: "Detects usage of APIs that have been removed or renamed in Effect v4",
|
|
35344
35672
|
severity: "warning",
|
|
35673
|
+
fixable: false,
|
|
35674
|
+
supportedEffect: ["v4"],
|
|
35345
35675
|
apply: fn3("outdatedApi.apply")(function* (sourceFile, report) {
|
|
35346
35676
|
const typeParser = yield* service2(TypeParser);
|
|
35347
35677
|
const ts = yield* service2(TypeScriptApi);
|
|
@@ -35409,6 +35739,8 @@ var outdatedEffectCodegen = createDiagnostic({
|
|
|
35409
35739
|
code: 19,
|
|
35410
35740
|
description: "Detects when generated code is outdated and needs to be regenerated",
|
|
35411
35741
|
severity: "warning",
|
|
35742
|
+
fixable: true,
|
|
35743
|
+
supportedEffect: ["v3", "v4"],
|
|
35412
35744
|
apply: fn3("outdatedEffectCodegen.apply")(function* (sourceFile, _report) {
|
|
35413
35745
|
const codegensWithRanges = yield* getCodegensForSourceFile(codegens, sourceFile);
|
|
35414
35746
|
for (const { codegen: codegen2, hash: hash2, range: range2 } of codegensWithRanges) {
|
|
@@ -35455,6 +35787,8 @@ var overriddenSchemaConstructor = createDiagnostic({
|
|
|
35455
35787
|
code: 30,
|
|
35456
35788
|
description: "Prevents overriding constructors in Schema classes which breaks decoding behavior",
|
|
35457
35789
|
severity: "error",
|
|
35790
|
+
fixable: true,
|
|
35791
|
+
supportedEffect: ["v3", "v4"],
|
|
35458
35792
|
apply: fn3("overriddenSchemaConstructor.apply")(function* (sourceFile, report) {
|
|
35459
35793
|
const ts = yield* service2(TypeScriptApi);
|
|
35460
35794
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -35592,6 +35926,8 @@ var preferSchemaOverJson = createDiagnostic({
|
|
|
35592
35926
|
code: 44,
|
|
35593
35927
|
description: "Suggests using Effect Schema for JSON operations instead of JSON.parse/JSON.stringify which may throw",
|
|
35594
35928
|
severity: "suggestion",
|
|
35929
|
+
fixable: false,
|
|
35930
|
+
supportedEffect: ["v3", "v4"],
|
|
35595
35931
|
apply: fn3("preferSchemaOverJson.apply")(function* (sourceFile, report) {
|
|
35596
35932
|
const ts = yield* service2(TypeScriptApi);
|
|
35597
35933
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -35702,6 +36038,8 @@ var redundantSchemaTagIdentifier = createDiagnostic({
|
|
|
35702
36038
|
code: 42,
|
|
35703
36039
|
description: "Suggests removing redundant identifier argument when it equals the tag value in Schema.TaggedClass/TaggedError/TaggedRequest",
|
|
35704
36040
|
severity: "suggestion",
|
|
36041
|
+
fixable: true,
|
|
36042
|
+
supportedEffect: ["v3", "v4"],
|
|
35705
36043
|
apply: fn3("redundantSchemaTagIdentifier.apply")(function* (sourceFile, report) {
|
|
35706
36044
|
const ts = yield* service2(TypeScriptApi);
|
|
35707
36045
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -35752,6 +36090,8 @@ var returnEffectInGen = createDiagnostic({
|
|
|
35752
36090
|
code: 11,
|
|
35753
36091
|
description: "Warns when returning an Effect in a generator causes nested Effect<Effect<...>>",
|
|
35754
36092
|
severity: "suggestion",
|
|
36093
|
+
fixable: true,
|
|
36094
|
+
supportedEffect: ["v3", "v4"],
|
|
35755
36095
|
apply: fn3("returnEffectInGen.apply")(function* (sourceFile, report) {
|
|
35756
36096
|
const ts = yield* service2(TypeScriptApi);
|
|
35757
36097
|
const typeCheckerUtils = yield* service2(TypeCheckerUtils);
|
|
@@ -35821,6 +36161,8 @@ var runEffectInsideEffect = createDiagnostic({
|
|
|
35821
36161
|
code: 32,
|
|
35822
36162
|
description: "Suggests using Runtime methods instead of Effect.run* inside Effect contexts",
|
|
35823
36163
|
severity: "suggestion",
|
|
36164
|
+
fixable: true,
|
|
36165
|
+
supportedEffect: ["v3"],
|
|
35824
36166
|
apply: fn3("runEffectInsideEffect.apply")(function* (sourceFile, report) {
|
|
35825
36167
|
const ts = yield* service2(TypeScriptApi);
|
|
35826
36168
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -35945,6 +36287,8 @@ var schemaStructWithTag = createDiagnostic({
|
|
|
35945
36287
|
code: 34,
|
|
35946
36288
|
description: "Suggests using Schema.TaggedStruct instead of Schema.Struct with _tag field",
|
|
35947
36289
|
severity: "suggestion",
|
|
36290
|
+
fixable: true,
|
|
36291
|
+
supportedEffect: ["v3", "v4"],
|
|
35948
36292
|
apply: fn3("schemaStructWithTag.apply")(function* (sourceFile, report) {
|
|
35949
36293
|
const ts = yield* service2(TypeScriptApi);
|
|
35950
36294
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36037,6 +36381,8 @@ var schemaSyncInEffect = createDiagnostic({
|
|
|
36037
36381
|
code: 43,
|
|
36038
36382
|
description: "Suggests using Effect-based Schema methods instead of sync methods inside Effect generators",
|
|
36039
36383
|
severity: "suggestion",
|
|
36384
|
+
fixable: false,
|
|
36385
|
+
supportedEffect: ["v3", "v4"],
|
|
36040
36386
|
apply: fn3("schemaSyncInEffect.apply")(function* (sourceFile, report) {
|
|
36041
36387
|
const ts = yield* service2(TypeScriptApi);
|
|
36042
36388
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36086,6 +36432,8 @@ var schemaUnionOfLiterals = createDiagnostic({
|
|
|
36086
36432
|
code: 33,
|
|
36087
36433
|
description: "Simplifies Schema.Union of multiple Schema.Literal calls into single Schema.Literal",
|
|
36088
36434
|
severity: "off",
|
|
36435
|
+
fixable: true,
|
|
36436
|
+
supportedEffect: ["v3"],
|
|
36089
36437
|
apply: fn3("schemaUnionOfLiterals.apply")(function* (sourceFile, report) {
|
|
36090
36438
|
const ts = yield* service2(TypeScriptApi);
|
|
36091
36439
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36161,6 +36509,8 @@ var scopeInLayerEffect = createDiagnostic({
|
|
|
36161
36509
|
code: 13,
|
|
36162
36510
|
description: "Suggests using Layer.scoped instead of Layer.effect when Scope is in requirements",
|
|
36163
36511
|
severity: "warning",
|
|
36512
|
+
fixable: true,
|
|
36513
|
+
supportedEffect: ["v3"],
|
|
36164
36514
|
apply: fn3("scopeInLayerEffect.apply")(function* (sourceFile, report) {
|
|
36165
36515
|
const ts = yield* service2(TypeScriptApi);
|
|
36166
36516
|
const tsUtils = yield* service2(TypeScriptUtils);
|
|
@@ -36250,12 +36600,91 @@ Consider using "scoped" instead to get rid of the scope in the requirements.`,
|
|
|
36250
36600
|
})
|
|
36251
36601
|
});
|
|
36252
36602
|
|
|
36603
|
+
// src/diagnostics/serviceNotAsClass.ts
|
|
36604
|
+
var serviceNotAsClass = createDiagnostic({
|
|
36605
|
+
name: "serviceNotAsClass",
|
|
36606
|
+
code: 51,
|
|
36607
|
+
description: "Warns when ServiceMap.Service is used as a variable instead of a class declaration",
|
|
36608
|
+
severity: "off",
|
|
36609
|
+
fixable: true,
|
|
36610
|
+
supportedEffect: ["v4"],
|
|
36611
|
+
apply: fn3("serviceNotAsClass.apply")(function* (sourceFile, report) {
|
|
36612
|
+
const ts = yield* service2(TypeScriptApi);
|
|
36613
|
+
const typeParser = yield* service2(TypeParser);
|
|
36614
|
+
if (typeParser.supportedEffect() === "v3") return;
|
|
36615
|
+
const nodeToVisit = [];
|
|
36616
|
+
const appendNodeToVisit = (node) => {
|
|
36617
|
+
nodeToVisit.push(node);
|
|
36618
|
+
return void 0;
|
|
36619
|
+
};
|
|
36620
|
+
ts.forEachChild(sourceFile, appendNodeToVisit);
|
|
36621
|
+
while (nodeToVisit.length > 0) {
|
|
36622
|
+
const node = nodeToVisit.shift();
|
|
36623
|
+
ts.forEachChild(node, appendNodeToVisit);
|
|
36624
|
+
if (!ts.isVariableDeclaration(node)) continue;
|
|
36625
|
+
if (!node.initializer || !ts.isCallExpression(node.initializer)) continue;
|
|
36626
|
+
const callExpr = node.initializer;
|
|
36627
|
+
if (!callExpr.typeArguments || callExpr.typeArguments.length === 0) continue;
|
|
36628
|
+
const typeArgs = callExpr.typeArguments;
|
|
36629
|
+
const declList = node.parent;
|
|
36630
|
+
if (!ts.isVariableDeclarationList(declList)) continue;
|
|
36631
|
+
if (!(declList.flags & ts.NodeFlags.Const)) continue;
|
|
36632
|
+
const isServiceMapService = yield* pipe(
|
|
36633
|
+
typeParser.isNodeReferenceToServiceMapModuleApi("Service")(callExpr.expression),
|
|
36634
|
+
orUndefined
|
|
36635
|
+
);
|
|
36636
|
+
if (!isServiceMapService) continue;
|
|
36637
|
+
const variableName = ts.isIdentifier(node.name) ? ts.idText(node.name) : sourceFile.text.substring(ts.getTokenPosOfNode(node.name, sourceFile), node.name.end);
|
|
36638
|
+
const variableStatement = declList.parent;
|
|
36639
|
+
const argsText = callExpr.arguments.length > 0 ? callExpr.arguments.map((a) => sourceFile.text.substring(ts.getTokenPosOfNode(a, sourceFile), a.end)).join(", ") : "";
|
|
36640
|
+
const shapeText = typeArgs.length > 0 ? typeArgs.map((t) => sourceFile.text.substring(ts.getTokenPosOfNode(t, sourceFile), t.end)).join(", ") : "Shape";
|
|
36641
|
+
report({
|
|
36642
|
+
location: callExpr,
|
|
36643
|
+
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, "")}") {}`,
|
|
36644
|
+
fixes: [{
|
|
36645
|
+
fixName: "serviceNotAsClass",
|
|
36646
|
+
description: `Convert to class declaration`,
|
|
36647
|
+
apply: gen3(function* () {
|
|
36648
|
+
const changeTracker = yield* service2(ChangeTracker);
|
|
36649
|
+
const targetNode = ts.isVariableStatement(variableStatement) ? variableStatement : declList;
|
|
36650
|
+
const innerCall = ts.factory.createCallExpression(
|
|
36651
|
+
callExpr.expression,
|
|
36652
|
+
[ts.factory.createTypeReferenceNode(variableName), ...typeArgs],
|
|
36653
|
+
[]
|
|
36654
|
+
);
|
|
36655
|
+
const outerCall = ts.factory.createCallExpression(
|
|
36656
|
+
innerCall,
|
|
36657
|
+
void 0,
|
|
36658
|
+
[...callExpr.arguments]
|
|
36659
|
+
);
|
|
36660
|
+
const heritageClause = ts.factory.createHeritageClause(
|
|
36661
|
+
ts.SyntaxKind.ExtendsKeyword,
|
|
36662
|
+
[ts.factory.createExpressionWithTypeArguments(outerCall, void 0)]
|
|
36663
|
+
);
|
|
36664
|
+
const modifiers = ts.isVariableStatement(variableStatement) ? variableStatement.modifiers : void 0;
|
|
36665
|
+
const classDeclaration = ts.factory.createClassDeclaration(
|
|
36666
|
+
modifiers,
|
|
36667
|
+
ts.isIdentifier(node.name) ? node.name : ts.factory.createIdentifier(variableName),
|
|
36668
|
+
void 0,
|
|
36669
|
+
[heritageClause],
|
|
36670
|
+
[]
|
|
36671
|
+
);
|
|
36672
|
+
changeTracker.replaceNode(sourceFile, targetNode, classDeclaration);
|
|
36673
|
+
})
|
|
36674
|
+
}]
|
|
36675
|
+
});
|
|
36676
|
+
}
|
|
36677
|
+
})
|
|
36678
|
+
});
|
|
36679
|
+
|
|
36253
36680
|
// src/diagnostics/strictBooleanExpressions.ts
|
|
36254
36681
|
var strictBooleanExpressions = createDiagnostic({
|
|
36255
36682
|
name: "strictBooleanExpressions",
|
|
36256
36683
|
code: 17,
|
|
36257
36684
|
description: "Enforces boolean types in conditional expressions for type safety",
|
|
36258
36685
|
severity: "off",
|
|
36686
|
+
fixable: false,
|
|
36687
|
+
supportedEffect: ["v3", "v4"],
|
|
36259
36688
|
apply: fn3("strictBooleanExpressions.apply")(function* (sourceFile, report) {
|
|
36260
36689
|
const ts = yield* service2(TypeScriptApi);
|
|
36261
36690
|
const typeChecker = yield* service2(TypeCheckerApi);
|
|
@@ -36327,6 +36756,8 @@ var strictEffectProvide = createDiagnostic({
|
|
|
36327
36756
|
code: 27,
|
|
36328
36757
|
description: "Warns when using Effect.provide with layers outside of application entry points",
|
|
36329
36758
|
severity: "off",
|
|
36759
|
+
fixable: false,
|
|
36760
|
+
supportedEffect: ["v3", "v4"],
|
|
36330
36761
|
apply: fn3("strictEffectProvide.apply")(function* (sourceFile, report) {
|
|
36331
36762
|
const ts = yield* service2(TypeScriptApi);
|
|
36332
36763
|
const typeCheckerUtils = yield* service2(TypeCheckerUtils);
|
|
@@ -36378,6 +36809,8 @@ var tryCatchInEffectGen = createDiagnostic({
|
|
|
36378
36809
|
code: 15,
|
|
36379
36810
|
description: "Discourages try/catch in Effect generators in favor of Effect error handling",
|
|
36380
36811
|
severity: "suggestion",
|
|
36812
|
+
fixable: false,
|
|
36813
|
+
supportedEffect: ["v3", "v4"],
|
|
36381
36814
|
apply: fn3("tryCatchInEffectGen.apply")(function* (sourceFile, report) {
|
|
36382
36815
|
const ts = yield* service2(TypeScriptApi);
|
|
36383
36816
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36435,6 +36868,8 @@ var unknownInEffectCatch = createDiagnostic({
|
|
|
36435
36868
|
code: 31,
|
|
36436
36869
|
description: "Warns when catch callbacks return unknown instead of typed errors",
|
|
36437
36870
|
severity: "warning",
|
|
36871
|
+
fixable: false,
|
|
36872
|
+
supportedEffect: ["v3", "v4"],
|
|
36438
36873
|
apply: fn3("unknownInEffectCatch.apply")(function* (sourceFile, report) {
|
|
36439
36874
|
const ts = yield* service2(TypeScriptApi);
|
|
36440
36875
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36496,6 +36931,8 @@ var unnecessaryEffectGen = createDiagnostic({
|
|
|
36496
36931
|
code: 5,
|
|
36497
36932
|
description: "Suggests removing Effect.gen when it contains only a single return statement",
|
|
36498
36933
|
severity: "suggestion",
|
|
36934
|
+
fixable: true,
|
|
36935
|
+
supportedEffect: ["v3", "v4"],
|
|
36499
36936
|
apply: fn3("unnecessaryEffectGen.apply")(function* (sourceFile, report) {
|
|
36500
36937
|
const ts = yield* service2(TypeScriptApi);
|
|
36501
36938
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36540,6 +36977,8 @@ var unnecessaryFailYieldableError = createDiagnostic({
|
|
|
36540
36977
|
code: 29,
|
|
36541
36978
|
description: "Suggests yielding yieldable errors directly instead of wrapping with Effect.fail",
|
|
36542
36979
|
severity: "suggestion",
|
|
36980
|
+
fixable: true,
|
|
36981
|
+
supportedEffect: ["v3", "v4"],
|
|
36543
36982
|
apply: fn3("unnecessaryFailYieldableError.apply")(function* (sourceFile, report) {
|
|
36544
36983
|
const ts = yield* service2(TypeScriptApi);
|
|
36545
36984
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36599,6 +37038,8 @@ var unnecessaryPipe = createDiagnostic({
|
|
|
36599
37038
|
code: 9,
|
|
36600
37039
|
description: "Removes pipe calls with no arguments",
|
|
36601
37040
|
severity: "suggestion",
|
|
37041
|
+
fixable: true,
|
|
37042
|
+
supportedEffect: ["v3", "v4"],
|
|
36602
37043
|
apply: fn3("unnecessaryPipe.apply")(function* (sourceFile, report) {
|
|
36603
37044
|
const ts = yield* service2(TypeScriptApi);
|
|
36604
37045
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36645,6 +37086,8 @@ var unnecessaryPipeChain = createDiagnostic({
|
|
|
36645
37086
|
code: 16,
|
|
36646
37087
|
description: "Simplifies chained pipe calls into a single pipe call",
|
|
36647
37088
|
severity: "suggestion",
|
|
37089
|
+
fixable: true,
|
|
37090
|
+
supportedEffect: ["v3", "v4"],
|
|
36648
37091
|
apply: fn3("unnecessaryPipeChain.apply")(function* (sourceFile, report) {
|
|
36649
37092
|
const ts = yield* service2(TypeScriptApi);
|
|
36650
37093
|
const typeParser = yield* service2(TypeParser);
|
|
@@ -36720,6 +37163,8 @@ var unsupportedServiceAccessors = createDiagnostic({
|
|
|
36720
37163
|
code: 21,
|
|
36721
37164
|
description: "Warns about service accessors that need codegen due to generic/complex signatures",
|
|
36722
37165
|
severity: "warning",
|
|
37166
|
+
fixable: true,
|
|
37167
|
+
supportedEffect: ["v3", "v4"],
|
|
36723
37168
|
apply: fn3("unsupportedServiceAccessors.apply")(function* (sourceFile, report) {
|
|
36724
37169
|
const ts = yield* service2(TypeScriptApi);
|
|
36725
37170
|
const nodeToVisit = [];
|
|
@@ -36822,7 +37267,10 @@ var diagnostics = [
|
|
|
36822
37267
|
effectFnOpportunity,
|
|
36823
37268
|
redundantSchemaTagIdentifier,
|
|
36824
37269
|
schemaSyncInEffect,
|
|
36825
|
-
preferSchemaOverJson
|
|
37270
|
+
preferSchemaOverJson,
|
|
37271
|
+
extendsNativeError,
|
|
37272
|
+
serviceNotAsClass,
|
|
37273
|
+
nodeBuiltinImport
|
|
36826
37274
|
];
|
|
36827
37275
|
|
|
36828
37276
|
// src/cli/diagnostics.ts
|
|
@@ -36836,6 +37284,11 @@ var DiagnosticsFoundError = class extends TaggedError2("DiagnosticsFoundError")
|
|
|
36836
37284
|
return `Found ${this.errorsCount} errors, ${this.warningsCount} warnings and ${this.messagesCount} messages.`;
|
|
36837
37285
|
}
|
|
36838
37286
|
};
|
|
37287
|
+
var InvalidLspConfigError = class extends TaggedError2("InvalidLspConfigError") {
|
|
37288
|
+
get message() {
|
|
37289
|
+
return `Invalid JSON lsp config: ${this.lspconfig}`;
|
|
37290
|
+
}
|
|
37291
|
+
};
|
|
36839
37292
|
var categoryToSeverity = (category, tsInstance) => {
|
|
36840
37293
|
switch (category) {
|
|
36841
37294
|
case tsInstance.DiagnosticCategory.Error:
|
|
@@ -37031,9 +37484,15 @@ var diagnostics2 = Command_exports.make(
|
|
|
37031
37484
|
progress: Flag_exports.boolean("progress").pipe(
|
|
37032
37485
|
Flag_exports.withDefault(false),
|
|
37033
37486
|
Flag_exports.withDescription("Show progress as files are checked (outputs to stderr)")
|
|
37487
|
+
),
|
|
37488
|
+
lspconfig: Flag_exports.string("lspconfig").pipe(
|
|
37489
|
+
Flag_exports.optional,
|
|
37490
|
+
Flag_exports.withDescription(
|
|
37491
|
+
`An optional inline JSON lsp config that replaces the current project lsp config. e.g. '{ "effectFn": ["untraced"] }'`
|
|
37492
|
+
)
|
|
37034
37493
|
)
|
|
37035
37494
|
},
|
|
37036
|
-
fn2("diagnostics")(function* ({ file: file4, format: format3, progress, project: project2, severity, strict }) {
|
|
37495
|
+
fn2("diagnostics")(function* ({ file: file4, format: format3, lspconfig, progress, project: project2, severity, strict }) {
|
|
37037
37496
|
const path4 = yield* Path;
|
|
37038
37497
|
const severityFilter = parseSeverityFilter(severity);
|
|
37039
37498
|
const state = {
|
|
@@ -37097,7 +37556,14 @@ var diagnostics2 = Command_exports.make(
|
|
|
37097
37556
|
if (!program) continue;
|
|
37098
37557
|
const sourceFile = program.getSourceFile(filePath);
|
|
37099
37558
|
if (!sourceFile) continue;
|
|
37100
|
-
|
|
37559
|
+
let pluginConfig = extractEffectLspOptions(program.getCompilerOptions());
|
|
37560
|
+
if (isSome2(lspconfig)) {
|
|
37561
|
+
try {
|
|
37562
|
+
pluginConfig = { name: "@effect/language-service", ...JSON.parse(lspconfig.value) };
|
|
37563
|
+
} catch {
|
|
37564
|
+
return yield* new InvalidLspConfigError({ lspconfig: lspconfig.value });
|
|
37565
|
+
}
|
|
37566
|
+
}
|
|
37101
37567
|
if (!pluginConfig) continue;
|
|
37102
37568
|
const rawResults = pipe(
|
|
37103
37569
|
getSemanticDiagnosticsWithCodeFixes(diagnostics, sourceFile),
|
|
@@ -37757,7 +38223,10 @@ var import_project_service3 = __toESM(require_dist3());
|
|
|
37757
38223
|
var getLocationFromDeclaration = (declaration, tsInstance) => {
|
|
37758
38224
|
const sourceFile = declaration.getSourceFile();
|
|
37759
38225
|
if (!sourceFile) return void 0;
|
|
37760
|
-
const { character, line } = tsInstance.getLineAndCharacterOfPosition(
|
|
38226
|
+
const { character, line } = tsInstance.getLineAndCharacterOfPosition(
|
|
38227
|
+
sourceFile,
|
|
38228
|
+
tsInstance.getTokenPosOfNode(declaration, sourceFile)
|
|
38229
|
+
);
|
|
37761
38230
|
return {
|
|
37762
38231
|
filePath: sourceFile.fileName,
|
|
37763
38232
|
line: line + 1,
|
|
@@ -38359,7 +38828,8 @@ function getExpressionName(tsApi, expr) {
|
|
|
38359
38828
|
if (tsApi.isCallExpression(expr)) {
|
|
38360
38829
|
return getExpressionName(tsApi, expr.expression);
|
|
38361
38830
|
}
|
|
38362
|
-
const
|
|
38831
|
+
const sourceFile = expr.getSourceFile();
|
|
38832
|
+
const text2 = sourceFile.text.substring(tsApi.getTokenPosOfNode(expr, sourceFile), expr.end).replace(/\s+/g, " ");
|
|
38363
38833
|
return text2.length > 30 ? text2.slice(0, 27) + "..." : text2;
|
|
38364
38834
|
}
|
|
38365
38835
|
var collectLayerInfoByName = (sourceFile, layerName, selectedOutputIndices) => gen3(function* () {
|
|
@@ -39377,6 +39847,7 @@ var assess = (input) => gen2(function* () {
|
|
|
39377
39847
|
});
|
|
39378
39848
|
|
|
39379
39849
|
// src/cli/setup/changes.ts
|
|
39850
|
+
var TSCONFIG_SCHEMA_URL = "https://raw.githubusercontent.com/Effect-TS/language-service/refs/heads/main/schema.json";
|
|
39380
39851
|
function emptyFileChangesResult() {
|
|
39381
39852
|
return {
|
|
39382
39853
|
codeActions: [],
|
|
@@ -39723,8 +40194,17 @@ var computeTsConfigChanges = (current, target, lspVersion) => {
|
|
|
39723
40194
|
const fileChanges = textChanges.ChangeTracker.with(
|
|
39724
40195
|
{ host, formatContext, preferences },
|
|
39725
40196
|
(tracker) => {
|
|
40197
|
+
const schemaProperty = findPropertyInObject(ts, rootObj, "$schema");
|
|
39726
40198
|
const pluginsProperty = findPropertyInObject(ts, compilerOptions, "plugins");
|
|
40199
|
+
const schemaPropertyAssignment = ts.factory.createPropertyAssignment(
|
|
40200
|
+
ts.factory.createStringLiteral("$schema"),
|
|
40201
|
+
ts.factory.createStringLiteral(TSCONFIG_SCHEMA_URL)
|
|
40202
|
+
);
|
|
39727
40203
|
if (isNone2(lspVersion)) {
|
|
40204
|
+
if (schemaProperty) {
|
|
40205
|
+
descriptions.push("Remove $schema from tsconfig");
|
|
40206
|
+
deleteNodeFromList(tracker, current.sourceFile, rootObj.properties, schemaProperty);
|
|
40207
|
+
}
|
|
39728
40208
|
if (pluginsProperty && ts.isArrayLiteralExpression(pluginsProperty.initializer)) {
|
|
39729
40209
|
const pluginsArray = pluginsProperty.initializer;
|
|
39730
40210
|
const lspPluginElement = pluginsArray.elements.find((element) => {
|
|
@@ -39742,6 +40222,13 @@ var computeTsConfigChanges = (current, target, lspVersion) => {
|
|
|
39742
40222
|
}
|
|
39743
40223
|
}
|
|
39744
40224
|
} else {
|
|
40225
|
+
if (!schemaProperty) {
|
|
40226
|
+
descriptions.push("Add $schema to tsconfig");
|
|
40227
|
+
insertNodeAtEndOfList(tracker, current.sourceFile, rootObj.properties, schemaPropertyAssignment);
|
|
40228
|
+
} else if (!ts.isStringLiteral(schemaProperty.initializer) || schemaProperty.initializer.text !== TSCONFIG_SCHEMA_URL) {
|
|
40229
|
+
descriptions.push("Update $schema in tsconfig");
|
|
40230
|
+
tracker.replaceNode(current.sourceFile, schemaProperty.initializer, schemaPropertyAssignment.initializer);
|
|
40231
|
+
}
|
|
39745
40232
|
const buildPluginObject = (severities) => {
|
|
39746
40233
|
const nameProperty = ts.factory.createPropertyAssignment(
|
|
39747
40234
|
ts.factory.createStringLiteral("name"),
|