From ee58b16a92126f96100df3b4e5c59bad60966bc3 Mon Sep 17 00:00:00 2001 From: webwarrior Date: Mon, 18 Dec 2023 14:16:46 +0100 Subject: [PATCH 01/12] Core,Framework,Tests: implemented partial configs Implemented partial configs and added tests for combining configs. --- .../Application/Configuration.fs | 19 ++++++++++++ src/FSharpLint.Core/Application/Lint.fs | 24 +++++++++++--- src/FSharpLint.Core/Application/Lint.fsi | 2 ++ .../Framework/TestConfiguration.fs | 31 ++++++++++++++++++- 4 files changed, 70 insertions(+), 6 deletions(-) diff --git a/src/FSharpLint.Core/Application/Configuration.fs b/src/FSharpLint.Core/Application/Configuration.fs index c5f3ee8f8..a026034ff 100644 --- a/src/FSharpLint.Core/Application/Configuration.fs +++ b/src/FSharpLint.Core/Application/Configuration.fs @@ -697,6 +697,25 @@ let loadConfig (configPath:string) = File.ReadAllText configPath |> parseConfig +/// Combine two configs into one: all values that are Some in second config override +/// corresponding values in first config. +let combineConfigs (baseConfig: Configuration) (overridingConfig: Configuration) : Configuration = + let baseFields = FSharp.Reflection.FSharpValue.GetRecordFields baseConfig + let partialConfigFields = FSharp.Reflection.FSharpValue.GetRecordFields overridingConfig + + let resultingRecordFields = + Array.map2 + (fun baseValue overridingValue -> + if isNull overridingValue then + baseValue + else + overridingValue) + baseFields + partialConfigFields + + FSharp.Reflection.FSharpValue.MakeRecord(typeof, resultingRecordFields) + :?> Configuration + /// A default configuration specifying every analyser and rule is included as a resource file in the framework. /// This function loads and returns this default configuration. let defaultConfiguration = diff --git a/src/FSharpLint.Core/Application/Lint.fs b/src/FSharpLint.Core/Application/Lint.fs index 4e0c7db22..9d0a7404f 100644 --- a/src/FSharpLint.Core/Application/Lint.fs +++ b/src/FSharpLint.Core/Application/Lint.fs @@ -355,6 +355,8 @@ module Lint = type ConfigurationParam = | Configuration of config: Configuration | FromFile of configPath:string + /// Partial config. Contains only differences from default config. + | FromFilePartial of configPath:string /// Tries to load the config from file `fsharplint.json`. /// If this file doesn't exist or is invalid, falls back to the default configuration. | Default @@ -397,6 +399,15 @@ module Lint = /// Gets a FSharpLint Configuration based on the provided ConfigurationParam. let getConfig (configParam:ConfigurationParam) = + let getDefault () = + try + Configuration.loadConfig $"./{Configuration.SettingsFileName}" + |> Ok + with + | :? System.IO.FileNotFoundException -> + Ok Configuration.defaultConfiguration + | ex -> Error (string ex) + match configParam with | Configuration config -> Ok config | FromFile filePath -> @@ -405,14 +416,17 @@ module Lint = |> Ok with | ex -> Error (string ex) - | Default -> + | FromFilePartial filePath -> try - Configuration.loadConfig $"./{Configuration.SettingsFileName}" - |> Ok + match getDefault () with + | Ok defaultConfig -> + let partialConfig = Configuration.loadConfig filePath + Configuration.combineConfigs defaultConfig partialConfig |> Ok + | Error(_) as err -> err with - | :? System.IO.FileNotFoundException -> - Ok Configuration.defaultConfiguration | ex -> Error (string ex) + | Default -> + getDefault () /// Lints an entire F# project by retrieving the files from a given /// path to the `.fsproj` file. diff --git a/src/FSharpLint.Core/Application/Lint.fsi b/src/FSharpLint.Core/Application/Lint.fsi index 7653223d6..2e5b05f1a 100644 --- a/src/FSharpLint.Core/Application/Lint.fsi +++ b/src/FSharpLint.Core/Application/Lint.fsi @@ -40,6 +40,8 @@ module Lint = type ConfigurationParam = | Configuration of config: Configuration | FromFile of configPath:string + /// Partial config. Contains only differences from default config. + | FromFilePartial of configPath:string /// Tries to load the config from file `fsharplint.json`. /// If this file doesn't exist or is invalid, falls back to the default configuration. | Default diff --git a/tests/FSharpLint.Core.Tests/Framework/TestConfiguration.fs b/tests/FSharpLint.Core.Tests/Framework/TestConfiguration.fs index aa7d97ec7..164924782 100644 --- a/tests/FSharpLint.Core.Tests/Framework/TestConfiguration.fs +++ b/tests/FSharpLint.Core.Tests/Framework/TestConfiguration.fs @@ -1,6 +1,7 @@ module FSharpLint.Core.Tests.TestConfiguration open NUnit.Framework +open FSharpLint.Framework open FSharpLint.Framework.Configuration type System.String with @@ -110,4 +111,32 @@ type TestConfiguration() = """ let actualConfig = parseConfig config - Assert.AreEqual(expectedConfig.NoTabCharacters, actualConfig.NoTabCharacters) \ No newline at end of file + Assert.AreEqual(expectedConfig.NoTabCharacters, actualConfig.NoTabCharacters) + + [] + member __.``Combining config with empty one results in unchanged original config`` () = + let defaultConfig = Configuration.defaultConfiguration + + let combinedConfig = Configuration.combineConfigs defaultConfig Configuration.Zero + + Assert.AreEqual(defaultConfig, combinedConfig) + + [] + member __.``When combining one config with another non-empty values are overriden`` () = + let baseConfig = Configuration.Zero + + let partialConfig = { Configuration.Zero with NoTabCharacters = Some { Enabled = true; Config = None } } + + let combinedConfig = Configuration.combineConfigs baseConfig partialConfig + + Assert.AreEqual(combinedConfig.NoTabCharacters, partialConfig.NoTabCharacters) + + [] + member __.``When combining one config with another empty values are not overriden`` () = + let baseConfig = { Configuration.Zero with NoTabCharacters = Some { Enabled = true; Config = None } } + + let partialConfig = Configuration.Zero + + let combinedConfig = Configuration.combineConfigs baseConfig partialConfig + + Assert.AreEqual(combinedConfig.NoTabCharacters, baseConfig.NoTabCharacters) From 17fca43c4a7231635e84256999bdf94c89715816 Mon Sep 17 00:00:00 2001 From: webwarrior Date: Mon, 18 Dec 2023 14:58:48 +0100 Subject: [PATCH 02/12] Console: add option to use partial config Added command line option "--partial-config" that when used, treats config file specified using "--lint-config" as partial config (contains only configs that should be overriden; rules not specified in it use default values). --- src/FSharpLint.Console/Program.fs | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/FSharpLint.Console/Program.fs b/src/FSharpLint.Console/Program.fs index 01419af13..40626d961 100644 --- a/src/FSharpLint.Console/Program.fs +++ b/src/FSharpLint.Console/Program.fs @@ -43,6 +43,7 @@ with and private LintArgs = | [] Target of target:string | [] Lint_Config of lintConfig:string + | Partial_Config | File_Type of FileType // fsharplint:enable UnionDefinitionIndentation with @@ -52,6 +53,7 @@ with | Target _ -> "Input to lint." | File_Type _ -> "Input type the linter will run against. If this is not set, the file type will be inferred from the file extension." | Lint_Config _ -> "Path to the config for the lint." + | Partial_Config -> "Indicates that specified lintConfig is a partial config and is applied as a diff to default config." // fsharplint:enable UnionCasesNames let private validTargetFileExtensions = [ ".fs"; ".fsx"; ".fsproj"; ".sln"; ".slnx" ] @@ -146,8 +148,11 @@ let main argv = let lintConfig = lintArgs.TryGetResult Lint_Config + let isPartialConfig = lintArgs.TryGetResult Partial_Config |> Option.isSome + let configParam = match lintConfig with + | Some configPath when isPartialConfig -> FromFilePartial configPath | Some configPath -> FromFile configPath | None -> Default From 583ebc98de799dcf2fe3df3d7cab0f048fd8f831 Mon Sep 17 00:00:00 2001 From: Matt Mcveigh Date: Sun, 25 Oct 2020 20:31:05 +0000 Subject: [PATCH 03/12] Add regression test for deeper issue Co-authored-by: webwarrior-ws --- tests/FSharpLint.Console.Tests/TestApp.fs | 24 +++++++++++++++++++++++ 1 file changed, 24 insertions(+) diff --git a/tests/FSharpLint.Console.Tests/TestApp.fs b/tests/FSharpLint.Console.Tests/TestApp.fs index 22d4e8bd0..6bb825dcc 100644 --- a/tests/FSharpLint.Console.Tests/TestApp.fs +++ b/tests/FSharpLint.Console.Tests/TestApp.fs @@ -118,6 +118,30 @@ type TestConsoleApplication() = Assert.AreEqual(int ExitCode.Failure, returnCode) Assert.AreEqual(set ["Use prefix syntax for generic type."], errors) + + /// Regression for bug discovered during: https://github.com/fsprojects/FSharpLint/issues/466 + /// Adding a rule to the config was disabling other rules unless they're explicitly specified. + [] + member __.``Adding a rule to a custom config should not have side effects on other rules (from the default config).``() = + let config = """ + { + "exceptionNames": { + "enabled": false + } + } + """ + use configFile = new TemporaryFile(config, "json") + + let input = """ + type Signature = + abstract member Encoded : string + abstract member PathName : string + """ + + let (returnCode, errors) = main [| "lint"; "--lint-config"; configFile.FileName; input |] + + Assert.AreEqual(-1, returnCode) + Assert.AreEqual(set ["Consider changing `Signature` to be prefixed with `I`."], errors) [] type TestFileTypeInference() = From 49d3fdcfcd993b83c64a29961c4ea5199e00dbd0 Mon Sep 17 00:00:00 2001 From: webwarrior-ws Date: Mon, 5 Jan 2026 11:18:25 +0100 Subject: [PATCH 04/12] Core,Console: use --lint-config as --partial-config And remove --partial-config flag. Configs will now be always partial. --- src/FSharpLint.Console/Program.fs | 5 ----- src/FSharpLint.Core/Application/Lint.fs | 8 -------- src/FSharpLint.Core/Application/Lint.fsi | 2 -- 3 files changed, 15 deletions(-) diff --git a/src/FSharpLint.Console/Program.fs b/src/FSharpLint.Console/Program.fs index 40626d961..01419af13 100644 --- a/src/FSharpLint.Console/Program.fs +++ b/src/FSharpLint.Console/Program.fs @@ -43,7 +43,6 @@ with and private LintArgs = | [] Target of target:string | [] Lint_Config of lintConfig:string - | Partial_Config | File_Type of FileType // fsharplint:enable UnionDefinitionIndentation with @@ -53,7 +52,6 @@ with | Target _ -> "Input to lint." | File_Type _ -> "Input type the linter will run against. If this is not set, the file type will be inferred from the file extension." | Lint_Config _ -> "Path to the config for the lint." - | Partial_Config -> "Indicates that specified lintConfig is a partial config and is applied as a diff to default config." // fsharplint:enable UnionCasesNames let private validTargetFileExtensions = [ ".fs"; ".fsx"; ".fsproj"; ".sln"; ".slnx" ] @@ -148,11 +146,8 @@ let main argv = let lintConfig = lintArgs.TryGetResult Lint_Config - let isPartialConfig = lintArgs.TryGetResult Partial_Config |> Option.isSome - let configParam = match lintConfig with - | Some configPath when isPartialConfig -> FromFilePartial configPath | Some configPath -> FromFile configPath | None -> Default diff --git a/src/FSharpLint.Core/Application/Lint.fs b/src/FSharpLint.Core/Application/Lint.fs index 9d0a7404f..4088e832e 100644 --- a/src/FSharpLint.Core/Application/Lint.fs +++ b/src/FSharpLint.Core/Application/Lint.fs @@ -355,8 +355,6 @@ module Lint = type ConfigurationParam = | Configuration of config: Configuration | FromFile of configPath:string - /// Partial config. Contains only differences from default config. - | FromFilePartial of configPath:string /// Tries to load the config from file `fsharplint.json`. /// If this file doesn't exist or is invalid, falls back to the default configuration. | Default @@ -411,12 +409,6 @@ module Lint = match configParam with | Configuration config -> Ok config | FromFile filePath -> - try - Configuration.loadConfig filePath - |> Ok - with - | ex -> Error (string ex) - | FromFilePartial filePath -> try match getDefault () with | Ok defaultConfig -> diff --git a/src/FSharpLint.Core/Application/Lint.fsi b/src/FSharpLint.Core/Application/Lint.fsi index 2e5b05f1a..7653223d6 100644 --- a/src/FSharpLint.Core/Application/Lint.fsi +++ b/src/FSharpLint.Core/Application/Lint.fsi @@ -40,8 +40,6 @@ module Lint = type ConfigurationParam = | Configuration of config: Configuration | FromFile of configPath:string - /// Partial config. Contains only differences from default config. - | FromFilePartial of configPath:string /// Tries to load the config from file `fsharplint.json`. /// If this file doesn't exist or is invalid, falls back to the default configuration. | Default From d9c54e2d63fc8bd6e365462c4867b6ef3f917cae Mon Sep 17 00:00:00 2001 From: webwarrior-ws Date: Mon, 5 Jan 2026 11:42:17 +0100 Subject: [PATCH 05/12] Tests(Console): fix test for disabled rule By using camelCase rule name name in config instead of PascalCase (camelCase is proper rule naming scheme in fsharplint.json). --- tests/FSharpLint.Console.Tests/TestApp.fs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/FSharpLint.Console.Tests/TestApp.fs b/tests/FSharpLint.Console.Tests/TestApp.fs index 6bb825dcc..702c2a41d 100644 --- a/tests/FSharpLint.Console.Tests/TestApp.fs +++ b/tests/FSharpLint.Console.Tests/TestApp.fs @@ -65,7 +65,7 @@ type TestConsoleApplication() = member _.``Lint source with valid config to disable rule, disabled rule is not triggered for given source.``() = let fileContent = """ { - "InterfaceNames": { + "interfaceNames": { "enabled": false } } From 3b9f365a85bf0f55c067d87ac8d9a30aac78eb67 Mon Sep 17 00:00:00 2001 From: webwarrior-ws Date: Mon, 5 Jan 2026 11:50:06 +0100 Subject: [PATCH 06/12] docs: updated documentation about configs To reflect change in how config is applied. --- docs/content/how-tos/rule-configuration.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/content/how-tos/rule-configuration.md b/docs/content/how-tos/rule-configuration.md index 50e819956..cd20adb0e 100644 --- a/docs/content/how-tos/rule-configuration.md +++ b/docs/content/how-tos/rule-configuration.md @@ -10,7 +10,7 @@ menu_order: 3 The linter by default looks for a file named `fsharplint.json` in the current working directory. Typically you would have this file in the root of your project. -At this moment in time the configuration requires every rule to be added to your file, rather than a typical approach where you would override just the rules you want to change from their defaults. This will be addressed in a future version see: [Issue #488](https://github.com/fsprojects/FSharpLint/issues/488). +Entries in configuration file override corresponding entries in default configuration, so you only need to specify rules that you want to change from their defaults. Check out the [default configuration](https://github.com/fsprojects/FSharpLint/blob/master/src/FSharpLint.Core/fsharplint.json) that the tool comes with to see all possible settings and their default values. From 70d314e7150d3496afb0d54c6e0507f14486057e Mon Sep 17 00:00:00 2001 From: Matt Mcveigh Date: Sun, 25 Oct 2020 18:38:28 +0000 Subject: [PATCH 07/12] Ensure ignoring a hint from config works Co-authored-by: webwarrior-ws --- tests/FSharpLint.Console.Tests/TestApp.fs | 34 +++++++++++++++++++++++ 1 file changed, 34 insertions(+) diff --git a/tests/FSharpLint.Console.Tests/TestApp.fs b/tests/FSharpLint.Console.Tests/TestApp.fs index 702c2a41d..61bf8ac0e 100644 --- a/tests/FSharpLint.Console.Tests/TestApp.fs +++ b/tests/FSharpLint.Console.Tests/TestApp.fs @@ -119,6 +119,40 @@ type TestConsoleApplication() = Assert.AreEqual(int ExitCode.Failure, returnCode) Assert.AreEqual(set ["Use prefix syntax for generic type."], errors) + /// Regression test for: https://github.com/fsprojects/FSharpLint/issues/466 + /// Hints listed in the ignore section of the config were not being ignored. + [] + member __.``Ignoring a hint in the configuration should stop it from being output as warning.``() = + let input = """ + let x = [1; 2; 3; 4] |> List.map (fun x -> x + 2) |> List.map (fun x -> x + 2) + let y = not (1 = 1) + """ + + let commonErrorMessage = "`not (a = b)` might be able to be refactored into `a <> b`." + let disabledHintErrorMessage = "`List.map f (List.map g x)` might be able to be refactored into `List.map (g >> f) x`." + + let (returnCode, errors) = main [| "lint"; input |] + + // Check default config triggers the hint we're expecting to ignore later. + Assert.AreEqual(-1, returnCode) + CollectionAssert.AreEquivalent(set [ commonErrorMessage; disabledHintErrorMessage ], errors) + + let config = """ + { + "hints": { + "ignore": [ + "List.map f (List.map g x) ===> List.map (g >> f) x" + ] + } + } + """ + use configFile = new TemporaryFile(config, "json") + + let (returnCode, errors) = main [| "lint"; "--lint-config"; configFile.FileName; input |] + + Assert.AreEqual(-1, returnCode) + CollectionAssert.AreEquivalent(Set.singleton commonErrorMessage, errors) + /// Regression for bug discovered during: https://github.com/fsprojects/FSharpLint/issues/466 /// Adding a rule to the config was disabling other rules unless they're explicitly specified. [] From e28efd5bbfd97e89492df9f8a886d8f7ad0090b0 Mon Sep 17 00:00:00 2001 From: webwarrior-ws Date: Mon, 5 Jan 2026 12:45:56 +0100 Subject: [PATCH 08/12] Core: combine hint configs When combining configs, if both base and overriding configs have Hints config, combine `add` and `ignore` arrays in HintConfig objects instead of totally overriding base hint config by overriding one. Also actually use `ignore` array to filter out available hints when flattening config. Before, `ignore` was not used at all. Fixes https://github.com/fsprojects/FSharpLint/issues/466 --- .../Application/Configuration.fs | 35 +++++++++++++++---- 1 file changed, 29 insertions(+), 6 deletions(-) diff --git a/src/FSharpLint.Core/Application/Configuration.fs b/src/FSharpLint.Core/Application/Configuration.fs index a026034ff..cdf4ea2c5 100644 --- a/src/FSharpLint.Core/Application/Configuration.fs +++ b/src/FSharpLint.Core/Application/Configuration.fs @@ -700,6 +700,17 @@ let loadConfig (configPath:string) = /// Combine two configs into one: all values that are Some in second config override /// corresponding values in first config. let combineConfigs (baseConfig: Configuration) (overridingConfig: Configuration) : Configuration = + let combineHints (baseHints: HintConfig) (overridingHints: HintConfig) = + let mergeLists baseList overridingList = + match (baseList, overridingList) with + | Some baseArray, None -> Some baseArray + | Some baseArray, Some overridingArray -> Array.append baseArray overridingArray |> Array.distinct |> Some + | None, _ -> overridingList + { + add = mergeLists baseHints.add overridingHints.add + ignore = mergeLists baseHints.ignore overridingHints.ignore + } + let baseFields = FSharp.Reflection.FSharpValue.GetRecordFields baseConfig let partialConfigFields = FSharp.Reflection.FSharpValue.GetRecordFields overridingConfig @@ -712,9 +723,16 @@ let combineConfigs (baseConfig: Configuration) (overridingConfig: Configuration) overridingValue) baseFields partialConfigFields - - FSharp.Reflection.FSharpValue.MakeRecord(typeof, resultingRecordFields) - :?> Configuration + + let mergedConfig = + FSharp.Reflection.FSharpValue.MakeRecord(typeof, resultingRecordFields) + :?> Configuration + + match (baseConfig.Hints, overridingConfig.Hints) with + | Some baseHints, Some overridingHints -> + { mergedConfig with Hints = Some(combineHints baseHints overridingHints) } + | _ -> + mergedConfig /// A default configuration specifying every analyser and rule is included as a resource file in the framework. /// This function loads and returns this default configuration. @@ -811,9 +829,14 @@ let flattenConfig (config:Configuration) = |> Array.toList |> MergeSyntaxTrees.mergeHints - let getOrEmptyList hints = Option.defaultValue Array.empty hints - let deprecatedAllRules = + let flattenHints (hintsConfig: HintConfig) = + let ignores = + Option.defaultValue Array.empty hintsConfig.ignore + |> Set.ofArray + Option.defaultValue Array.empty hintsConfig.add + |> Array.filter (fun hint -> not <| ignores.Contains hint) + Array.concat [| // Deprecated grouped configs. TODO: remove in next major release @@ -822,7 +845,7 @@ let flattenConfig (config:Configuration) = config.typography |> Option.map (fun typographyConfig -> typographyConfig.Flatten()) |> Option.toArray |> Array.concat // - config.Hints |> Option.map (fun hintsConfig -> HintMatcher.rule { HintMatcher.Config.HintTrie = parseHints (getOrEmptyList hintsConfig.add) }) |> Option.toArray + config.Hints |> Option.map (fun hintsConfig -> HintMatcher.rule { HintMatcher.Config.HintTrie = parseHints (flattenHints hintsConfig) }) |> Option.toArray |] let allPossibleRules = From 202f9c2ce781a780de5bf996f338f46c390d2bc3 Mon Sep 17 00:00:00 2001 From: webwarrior-ws Date: Mon, 5 Jan 2026 13:34:02 +0100 Subject: [PATCH 09/12] build.fsx,fsharplint.json: enable TypePrefixing rule for SelfCheck With Mode=Always. --- build.fsx | 1 - fsharplint.json | 8 ++++++++ 2 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 fsharplint.json diff --git a/build.fsx b/build.fsx index e5b433124..106261246 100644 --- a/build.fsx +++ b/build.fsx @@ -274,7 +274,6 @@ Target.create "SelfCheck" (fun _ -> "trailingWhitespaceOnLine" // TODO: we should enable at some point - "typePrefixing" "unnestedFunctionNames" "nestedFunctionNames" "nestedStatements" diff --git a/fsharplint.json b/fsharplint.json new file mode 100644 index 000000000..5d29c6a2e --- /dev/null +++ b/fsharplint.json @@ -0,0 +1,8 @@ +{ + "typePrefixing": { + "enabled": true, + "config": { + "mode": "Always" + } + } +} From 15a453d2191807560aa738a4d808ff864dbb80cd Mon Sep 17 00:00:00 2001 From: webwarrior-ws Date: Mon, 22 Jun 2026 13:08:46 +0200 Subject: [PATCH 10/12] Revert "build.fsx,fsharplint.json: enable TypePrefixing rule for SelfCheck" This reverts commit 202f9c2ce781a780de5bf996f338f46c390d2bc3. --- build.fsx | 1 + fsharplint.json | 8 -------- 2 files changed, 1 insertion(+), 8 deletions(-) delete mode 100644 fsharplint.json diff --git a/build.fsx b/build.fsx index 106261246..e5b433124 100644 --- a/build.fsx +++ b/build.fsx @@ -274,6 +274,7 @@ Target.create "SelfCheck" (fun _ -> "trailingWhitespaceOnLine" // TODO: we should enable at some point + "typePrefixing" "unnestedFunctionNames" "nestedFunctionNames" "nestedStatements" diff --git a/fsharplint.json b/fsharplint.json deleted file mode 100644 index 5d29c6a2e..000000000 --- a/fsharplint.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "typePrefixing": { - "enabled": true, - "config": { - "mode": "Always" - } - } -} From cae429b206df43f18e6150248a9ba34ce93a1e9a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9s=20G=2E=20Aragoneses?= Date: Sun, 7 Jun 2026 21:40:07 +0800 Subject: [PATCH 11/12] genericTypesNames rather (36err before this commit) --- fsharplint.json | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 fsharplint.json diff --git a/fsharplint.json b/fsharplint.json new file mode 100644 index 000000000..a35ac0ce5 --- /dev/null +++ b/fsharplint.json @@ -0,0 +1,10 @@ +{ + "genericTypesNames": { + "enabled": true, + "config": { + "naming": "PascalCase", + "underscores": "None", + "prefix": "T" + } + } +} From 9c4ea92a4000b629904d869a497f4976ca485cf5 Mon Sep 17 00:00:00 2001 From: webwarrior-ws Date: Mon, 22 Jun 2026 14:50:16 +0200 Subject: [PATCH 12/12] build.fsx: use fsharplint.json at root for selfCheck Pass fsharplint.json at solution's root to fsharplint in selfCheck using --lint-config parameter. --- build.fsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/build.fsx b/build.fsx index e5b433124..3810b0b82 100644 --- a/build.fsx +++ b/build.fsx @@ -246,8 +246,9 @@ Target.create "SelfCheck" (fun _ -> let consoleProj = Path.Combine(srcDir.FullName, "FSharpLint.Console", "FSharpLint.Console.fsproj") |> FileInfo let sol = Path.Combine(rootDir.FullName, solutionFileName) |> FileInfo + let configFilePath = Path.Combine(sol.DirectoryName, "fsharplint.json") - exec "dotnet" $"run --framework net9.0 lint %s{sol.FullName}" consoleProj.Directory.FullName + exec "dotnet" $"run --framework net9.0 lint --lint-config %s{configFilePath} %s{sol.FullName}" consoleProj.Directory.FullName printfn "Running self-check with default rules..." runLinter ()