diff --git a/src/FSharpLint.Core/Application/Configuration.fs b/src/FSharpLint.Core/Application/Configuration.fs index f2745b966..ec8befc99 100644 --- a/src/FSharpLint.Core/Application/Configuration.fs +++ b/src/FSharpLint.Core/Application/Configuration.fs @@ -136,8 +136,11 @@ let constructRuleWithConfig rule ruleConfig = let constructTypePrefixingRuleWithConfig rule (ruleConfig: RuleConfig) = if ruleConfig.Enabled then - let config = ruleConfig.Config |> Option.defaultValue { Mode = TypePrefixing.Mode.Hybrid } - Some(rule config) + match ruleConfig.Config with + | Some { Mode = TypePrefixing.Mode.Hybrid } | None -> + Some(rule { TypePrefixing.Config.Mode = TypePrefixing.Mode.HybridWeak }) + | Some config -> + Some(rule config) else None diff --git a/src/FSharpLint.Core/Rules/Formatting/TypePrefixing.fs b/src/FSharpLint.Core/Rules/Formatting/TypePrefixing.fs index f9b15e5f2..1fa8b68f0 100644 --- a/src/FSharpLint.Core/Rules/Formatting/TypePrefixing.fs +++ b/src/FSharpLint.Core/Rules/Formatting/TypePrefixing.fs @@ -9,9 +9,13 @@ open FSharpLint.Framework.Rules open FSharpLint.Framework.ExpressionUtilities type Mode = - | Hybrid = 0 + | HybridWeak = 0 | Always = 1 | Never = 2 + | HybridStrict = 3 + + /// obsolete: use HybridStrict or HybridWeak instead (default: HybridWeak) + | Hybrid = 128 [] type Config = { Mode: Mode } @@ -38,7 +42,7 @@ let checkTypePrefixing (config:Config) (args:AstNodeRuleParams) range typeName t | "Ref" as typeName -> // Prefer postfix. - if not isPostfix && config.Mode <> Mode.Always + if not isPostfix && (config.Mode = Mode.HybridStrict || config.Mode = Mode.Never) then let suggestedFix = lazy( (ExpressionUtilities.tryFindTextOfRange range args.FileContent, typeArgs) @@ -53,7 +57,7 @@ let checkTypePrefixing (config:Config) (args:AstNodeRuleParams) range typeName t else None - | "array" when config.Mode <> Mode.Always -> + | "array" when config.Mode = Mode.HybridStrict || config.Mode = Mode.Never -> // Prefer special postfix (e.g. int []). let suggestedFix = lazy( (ExpressionUtilities.tryFindTextOfRange range args.FileContent, typeArgs) @@ -63,6 +67,9 @@ let checkTypePrefixing (config:Config) (args:AstNodeRuleParams) range typeName t SuggestedFix = Some suggestedFix TypeChecks = [] } |> Some + | "array" when config.Mode = Mode.HybridWeak -> + None + | typeName -> match (isPostfix, config.Mode) with | true, Mode.Never -> diff --git a/src/FSharpLint.Core/fsharplint.json b/src/FSharpLint.Core/fsharplint.json index 25a8be5d4..5f8cce7df 100644 --- a/src/FSharpLint.Core/fsharplint.json +++ b/src/FSharpLint.Core/fsharplint.json @@ -14,7 +14,7 @@ "typePrefixing": { "enabled": false, "config": { - "mode": "Hybrid" + "mode": "HybridWeak" } }, "unionDefinitionIndentation": { "enabled": false }, diff --git a/tests/FSharpLint.Console.Tests/TestApp.fs b/tests/FSharpLint.Console.Tests/TestApp.fs index 68b69ab64..1d10f6d7b 100644 --- a/tests/FSharpLint.Console.Tests/TestApp.fs +++ b/tests/FSharpLint.Console.Tests/TestApp.fs @@ -117,3 +117,108 @@ type TestConsoleApplication() = Assert.AreEqual(-1, returnCode) Assert.AreEqual(set ["Use prefix syntax for generic type."], errors) + + [] + member __.``TypePrefixing rule Hybrid mode should still work (after it gets renamed to HybridWeak)``() = + let fileContent = """ + { + "typePrefixing": { + "enabled": true, + "config": { + "mode": "Hybrid" + } + } + } + """ + use config = new TemporaryFile(fileContent, "json") + + let input = """ + module Program + + type X = int Generic + """ + + let (returnCode, errors) = main [| "lint"; "--lint-config"; config.FileName; input |] + + Assert.AreEqual(-1, returnCode) + Assert.AreEqual(set ["Use prefix syntax for generic type."], errors) + + [] + member __.``TypePrefixing rule HybridStrict mode should complain about List``() = + let fileContent = """ + { + "typePrefixing": { + "enabled": true, + "config": { + "mode": "HybridStrict" + } + } + } + """ + use config = new TemporaryFile(fileContent, "json") + + let input = """ + module Program + + type X = List + """ + + let (returnCode, errors) = main [| "lint"; "--lint-config"; config.FileName; input |] + + Assert.AreEqual(-1, returnCode, "Return code of HybridStrict against List should not be zero") + Assert.AreNotEqual(0, errors.Count, "Number of errors for HybridStrict mode against List should not be zero") + Assert.AreEqual("Use postfix syntax for F# type List.", errors.MaximumElement) + + [] + member __.``TypePrefixing rule HybridStrict mode should complain about array``() = + let fileContent = """ + { + "typePrefixing": { + "enabled": true, + "config": { + "mode": "HybridStrict" + } + } + } + """ + use config = new TemporaryFile(fileContent, "json") + + let input = """ + module Program + + type X = array + """ + + let (returnCode, errors) = main [| "lint"; "--lint-config"; config.FileName; input |] + + Assert.AreEqual(-1, returnCode, "Return code of HybridStrict against array should not be zero") + Assert.AreNotEqual(0, errors.Count, "Number of errors for HybridStrict mode against array should not be zero") + Assert.AreEqual("Use special postfix syntax for F# type array.", errors.MaximumElement) + + [] + member __.``TypePrefixing rule HybridWeak mode should not complain about List``() = + let fileContent = """ + { + "typePrefixing": { + "enabled": true, + "config": { + "mode": "HybridWeak" + } + } + } + """ + use config = new TemporaryFile(fileContent, "json") + + let input = """ + module Program + + type X = List + """ + + let (returnCode, errors) = main [| "lint"; "--lint-config"; config.FileName; input |] + + Assert.AreEqual(0, returnCode) + if errors.Count = 0 then + Assert.AreEqual(0, errors.Count, "Return code of HybridWeak against List should not be zero (=success; no suggestions)") + else + Assert.AreEqual(0, errors.Count, "No errors should happen, but we got at least one: " + errors.MaximumElement) diff --git a/tests/FSharpLint.Core.Tests/Rules/Formatting/TypePrefixing.fs b/tests/FSharpLint.Core.Tests/Rules/Formatting/TypePrefixing.fs index 7cf4faf7c..22c8abc10 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Formatting/TypePrefixing.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Formatting/TypePrefixing.fs @@ -5,8 +5,8 @@ open FSharpLint.Rules open FSharpLint.Rules.TypePrefixing [] -type TestFormattingHybridTypePrefixing() = - inherit TestAstNodeRuleBase.TestAstNodeRuleBase(TypePrefixing.rule { Config.Mode = Mode.Hybrid }) +type TestFormattingHybridStrictTypePrefixing() = + inherit TestAstNodeRuleBase.TestAstNodeRuleBase(TypePrefixing.rule { Config.Mode = Mode.HybridStrict }) [] member this.``Error for F# List type prefix syntax``() = @@ -238,6 +238,120 @@ type T = Generic this.Parse source Assert.AreEqual(expected, this.ApplyQuickFix source) +[] +type TestFormattingHybridWeakTypePrefixing() = + inherit TestAstNodeRuleBase.TestAstNodeRuleBase(TypePrefixing.rule { Config.Mode = Mode.HybridWeak }) + + [] + member this.``Ignore F# List type prefix syntax``() = + this.Parse """ +module Program + +type T = list +""" + + Assert.IsTrue this.NoErrorsExist + + [] + member this.``Ignore for F# List type postfix syntax``() = + this.Parse """ +module Program + +type T = int list +""" + + Assert.IsTrue this.NoErrorsExist + + [] + member this.``Ignore F# Option type prefix syntax``() = + this.Parse """ +module Program + +type T = Option +""" + + Assert.IsTrue this.NoErrorsExist + + [] + member this.``Ignore F# Option type postfix syntax``() = + this.Parse """ +module Program + +type T = int option +""" + + Assert.IsTrue this.NoErrorsExist + + [] + member this.``Ignore F# ref type prefix syntax``() = + this.Parse """ +module Program + +type T = ref +""" + + Assert.IsTrue this.NoErrorsExist + + [] + member this.``Ignore F# ref type postfix syntax``() = + this.Parse """ +module Program + +type T = int ref +""" + + Assert.IsTrue this.NoErrorsExist + + [] + member this.``Ignore F# array type prefix syntax``() = + this.Parse """ +module Program + +type T = array +""" + + Assert.IsTrue this.NoErrorsExist + + [] + member this.``Ignore F# array type standard postfix syntax``() = + this.Parse """ +module Program + +type T = int array +""" + + Assert.IsTrue this.NoErrorsExist + + [] + member this.``Ignore F# array type special postfix syntax``() = + this.Parse """ +module Program + +type T = int [] +""" + + Assert.IsTrue this.NoErrorsExist + + [] + member this.``Error for generic type postfix syntax``() = + this.Parse """ +module Program + +type X = int Generic +""" + + Assert.IsTrue(this.ErrorExistsAt(4, 9)) + + [] + member this.``No error for generic type prefix syntax``() = + this.Parse """ +module Program + +type X = Generic +""" + + Assert.IsTrue this.NoErrorsExist + [] type TestFormattingAlwaysTypePrefixing() = inherit TestAstNodeRuleBase.TestAstNodeRuleBase(TypePrefixing.rule { Config.Mode = Mode.Always })