From 525184934774978ed6b752feb8020b01acc2d159 Mon Sep 17 00:00:00 2001 From: Matt Mcveigh Date: Sun, 25 Oct 2020 18:38:28 +0000 Subject: [PATCH 1/4] Ensure ignoring a hint from config works --- global.json | 2 +- tests/FSharpLint.Console.Tests/TestApp.fs | 32 +++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/global.json b/global.json index cc4d115ea..c120c8115 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.1.200" + "version": "3.1.301" } } \ No newline at end of file diff --git a/tests/FSharpLint.Console.Tests/TestApp.fs b/tests/FSharpLint.Console.Tests/TestApp.fs index 1402915b8..9fd46062e 100644 --- a/tests/FSharpLint.Console.Tests/TestApp.fs +++ b/tests/FSharpLint.Console.Tests/TestApp.fs @@ -95,3 +95,35 @@ type TestConsoleApplication() = Assert.AreEqual(0, returnCode) Assert.AreEqual(Set.empty, 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 (returnCode, errors) = main [| "lint"; input |] + + // Check default config triggers the hint we're expecting to ignore later. + Assert.AreEqual(-1, returnCode) + Assert.AreEqual(Set.ofList [ + "`List.map f (List.map g x)` might be able to be refactored into `List.map (g >> f) x`."], errors) + + let config = """ + { + "hints": { + "add": [], + "ignore": [ + "List.map f (List.map g x) ===> List.map (g >> f) x" + ] + } + } + """ + use config = new TemporaryFile(config, "json") + + let (returnCode, errors) = main [| "lint"; "--lint-config"; config.FileName; input |] + + Assert.AreEqual(0, returnCode) + Assert.AreEqual(Set.empty, errors) From b49774bcab583a7e79bf5019b690c8acf578dbc4 Mon Sep 17 00:00:00 2001 From: Matt Mcveigh Date: Sun, 25 Oct 2020 20:18:29 +0000 Subject: [PATCH 2/4] Reset sdk version --- global.json | 2 +- src/FSharpLint.Core/Application/Configuration.fs | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/global.json b/global.json index c120c8115..cc4d115ea 100644 --- a/global.json +++ b/global.json @@ -1,5 +1,5 @@ { "sdk": { - "version": "3.1.301" + "version": "3.1.200" } } \ No newline at end of file diff --git a/src/FSharpLint.Core/Application/Configuration.fs b/src/FSharpLint.Core/Application/Configuration.fs index 82808ddd8..6fbd75d95 100644 --- a/src/FSharpLint.Core/Application/Configuration.fs +++ b/src/FSharpLint.Core/Application/Configuration.fs @@ -21,10 +21,10 @@ module FSharpJsonConverter = type OptionConverter() = inherit JsonConverter() - override x.CanConvert(t) = + override __.CanConvert(t) = t.IsGenericType && t.GetGenericTypeDefinition() = typedefof<_ option> - override x.WriteJson(writer, value, serializer) = + override __.WriteJson(writer, value, serializer) = let value = if isNull value then null else @@ -32,7 +32,7 @@ module FSharpJsonConverter = fields.[0] serializer.Serialize(writer, value) - override x.ReadJson(reader, t, _, serializer) = + override __.ReadJson(reader, t, _, serializer) = let innerType = t.GetGenericArguments().[0] let innerType = if innerType.IsValueType then (typedefof>).MakeGenericType([|innerType|]) @@ -42,10 +42,7 @@ module FSharpJsonConverter = if isNull value then FSharpValue.MakeUnion(cases.[0], [||]) else FSharpValue.MakeUnion(cases.[1], [|value|]) - let private converters = - [| - OptionConverter() :> JsonConverter - |] + let private converters = [| OptionConverter() :> JsonConverter |] let serializerSettings = let settings = JsonSerializerSettings() @@ -563,7 +560,8 @@ let flattenConfig (config:Configuration) = config.formatting |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat config.conventions |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat config.typography |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - config.Hints |> Option.map (fun config -> HintMatcher.rule { HintMatcher.Config.HintTrie = parseHints (getOrEmptyList config.add) }) |> Option.toArray + config.Hints |> Option.map (fun config -> HintMatcher.rule { + HintMatcher.Config.HintTrie = parseHints (getOrEmptyList config.add) }) |> Option.toArray |] |> Array.concat let allRules = From 65fcc821e9ba280759c8fdfbc8873ea1b43c555f Mon Sep 17 00:00:00 2001 From: Matt Mcveigh Date: Sun, 25 Oct 2020 20:31:05 +0000 Subject: [PATCH 3/4] Add regression test for deeper issue --- tests/FSharpLint.Console.Tests/TestApp.fs | 27 +++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/tests/FSharpLint.Console.Tests/TestApp.fs b/tests/FSharpLint.Console.Tests/TestApp.fs index 9fd46062e..bab64e22f 100644 --- a/tests/FSharpLint.Console.Tests/TestApp.fs +++ b/tests/FSharpLint.Console.Tests/TestApp.fs @@ -108,8 +108,7 @@ type TestConsoleApplication() = // Check default config triggers the hint we're expecting to ignore later. Assert.AreEqual(-1, returnCode) - Assert.AreEqual(Set.ofList [ - "`List.map f (List.map g x)` might be able to be refactored into `List.map (g >> f) x`."], errors) + Assert.AreEqual(Set.ofList ["`List.map f (List.map g x)` might be able to be refactored into `List.map (g >> f) x`."], errors) let config = """ { @@ -127,3 +126,27 @@ type TestConsoleApplication() = Assert.AreEqual(0, returnCode) Assert.AreEqual(Set.empty, 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 config = new TemporaryFile(config, "json") + + let input = """ + type Signature = + abstract member Encoded : string + abstract member PathName : string + """ + + let (returnCode, errors) = main [| "lint"; "--lint-config"; config.FileName; input |] + + Assert.AreEqual(-1, returnCode) + Assert.AreEqual(Set.ofList ["Consider changing `Signature` to be prefixed with `I`."], errors) From 74915e7676db892600a1d7b02e4c01c8c2342ba3 Mon Sep 17 00:00:00 2001 From: Matt Mcveigh Date: Sun, 25 Oct 2020 20:56:17 +0000 Subject: [PATCH 4/4] Remove deprecated rules --- .../Application/Configuration.fs | 248 +----------------- src/FSharpLint.Core/Application/Lint.fs | 2 +- src/FSharpLint.Core/Framework/Rules.fs | 12 +- .../PatternMatchClauseIndentation.fs | 2 +- .../PatternMatchExpressionIndentation.fs | 2 +- .../Formatting/UnionDefinitionIndentation.fs | 2 +- .../Rules/Typography/Indentation.fs | 2 +- tests/FSharpLint.Console.Tests/TestApp.fs | 3 +- 8 files changed, 19 insertions(+), 254 deletions(-) diff --git a/src/FSharpLint.Core/Application/Configuration.fs b/src/FSharpLint.Core/Application/Configuration.fs index 6fbd75d95..555bd0a6f 100644 --- a/src/FSharpLint.Core/Application/Configuration.fs +++ b/src/FSharpLint.Core/Application/Configuration.fs @@ -117,8 +117,6 @@ module IgnoreFiles = when isCurrentlyIgnored && pathMatchesGlob glob segments isDirectory -> false | _ -> isCurrentlyIgnored) false -// Non-standard record field naming for config serialization. -// fsharplint:disable RecordFieldNames type RuleConfig<'Config> = { Enabled:bool Config:'Config option @@ -134,227 +132,20 @@ let constructRuleWithConfig rule ruleConfig = else None -type TupleFormattingConfig = - { tupleCommaSpacing:EnabledConfig option - tupleIndentation:EnabledConfig option - tupleParentheses:EnabledConfig option } -with - member this.Flatten() = - [| - this.tupleCommaSpacing |> Option.bind (constructRuleIfEnabled TupleCommaSpacing.rule) - this.tupleIndentation |> Option.bind (constructRuleIfEnabled TupleIndentation.rule) - this.tupleParentheses |> Option.bind (constructRuleIfEnabled TupleParentheses.rule) - |] |> Array.choose id - -type PatternMatchFormattingConfig = - { patternMatchClausesOnNewLine:EnabledConfig option - patternMatchOrClausesOnNewLine:EnabledConfig option - patternMatchClauseIndentation:RuleConfig option - patternMatchExpressionIndentation:EnabledConfig option } -with - member this.Flatten() = - [| - this.patternMatchClausesOnNewLine |> Option.bind (constructRuleIfEnabled PatternMatchClausesOnNewLine.rule) - this.patternMatchOrClausesOnNewLine |> Option.bind (constructRuleIfEnabled PatternMatchOrClausesOnNewLine.rule) - this.patternMatchClauseIndentation |> Option.bind (constructRuleWithConfig PatternMatchClauseIndentation.rule) - this.patternMatchExpressionIndentation |> Option.bind (constructRuleIfEnabled PatternMatchExpressionIndentation.rule) - |] |> Array.choose id - -type FormattingConfig = - { typedItemSpacing:RuleConfig option - typePrefixing:EnabledConfig option - unionDefinitionIndentation:EnabledConfig option - moduleDeclSpacing:EnabledConfig option - classMemberSpacing:EnabledConfig option - tupleFormatting:TupleFormattingConfig option - patternMatchFormatting:PatternMatchFormattingConfig option } -with - member this.Flatten() = - [| - this.typedItemSpacing |> Option.bind (constructRuleWithConfig TypedItemSpacing.rule) |> Option.toArray - this.typePrefixing |> Option.bind (constructRuleIfEnabled TypePrefixing.rule) |> Option.toArray - this.unionDefinitionIndentation |> Option.bind (constructRuleIfEnabled UnionDefinitionIndentation.rule) |> Option.toArray - this.moduleDeclSpacing |> Option.bind (constructRuleIfEnabled ModuleDeclSpacing.rule) |> Option.toArray - this.classMemberSpacing |> Option.bind (constructRuleIfEnabled ClassMemberSpacing.rule) |> Option.toArray - this.tupleFormatting |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - this.patternMatchFormatting |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - |] |> Array.concat - -type RaiseWithTooManyArgsConfig = - { raiseWithSingleArgument:EnabledConfig option - nullArgWithSingleArgument:EnabledConfig option - invalidOpWithSingleArgument:EnabledConfig option - invalidArgWithTwoArguments:EnabledConfig option - failwithfWithArgumentsMatchingFormatString:EnabledConfig option } -with - member this.Flatten() = - [| - this.raiseWithSingleArgument |> Option.bind (constructRuleIfEnabled RaiseWithSingleArgument.rule) |> Option.toArray - this.nullArgWithSingleArgument |> Option.bind (constructRuleIfEnabled NullArgWithSingleArgument.rule) |> Option.toArray - this.invalidOpWithSingleArgument |> Option.bind (constructRuleIfEnabled InvalidOpWithSingleArgument.rule) |> Option.toArray - this.invalidArgWithTwoArguments |> Option.bind (constructRuleIfEnabled InvalidArgWithTwoArguments.rule) |> Option.toArray - this.failwithfWithArgumentsMatchingFormatString |> Option.bind (constructRuleIfEnabled FailwithfWithArgumentsMatchingFormatString.rule) |> Option.toArray - |] |> Array.concat - -type SourceLengthConfig = - { maxLinesInLambdaFunction:RuleConfig option - maxLinesInMatchLambdaFunction:RuleConfig option - maxLinesInValue:RuleConfig option - maxLinesInFunction:RuleConfig option - maxLinesInMember:RuleConfig option - maxLinesInConstructor:RuleConfig option - maxLinesInProperty:RuleConfig option - maxLinesInModule:RuleConfig option - maxLinesInRecord:RuleConfig option - maxLinesInEnum:RuleConfig option - maxLinesInUnion:RuleConfig option - maxLinesInClass:RuleConfig option } -with - member this.Flatten() = - [| - this.maxLinesInLambdaFunction |> Option.bind (constructRuleWithConfig MaxLinesInLambdaFunction.rule) |> Option.toArray - this.maxLinesInMatchLambdaFunction |> Option.bind (constructRuleWithConfig MaxLinesInMatchLambdaFunction.rule) |> Option.toArray - this.maxLinesInValue |> Option.bind (constructRuleWithConfig MaxLinesInValue.rule) |> Option.toArray - this.maxLinesInFunction |> Option.bind (constructRuleWithConfig MaxLinesInFunction.rule) |> Option.toArray - this.maxLinesInMember |> Option.bind (constructRuleWithConfig MaxLinesInMember.rule) |> Option.toArray - this.maxLinesInConstructor |> Option.bind (constructRuleWithConfig MaxLinesInConstructor.rule) |> Option.toArray - this.maxLinesInProperty |> Option.bind (constructRuleWithConfig MaxLinesInProperty.rule) |> Option.toArray - this.maxLinesInModule |> Option.bind (constructRuleWithConfig MaxLinesInModule.rule) |> Option.toArray - this.maxLinesInRecord |> Option.bind (constructRuleWithConfig MaxLinesInRecord.rule) |> Option.toArray - this.maxLinesInEnum |> Option.bind (constructRuleWithConfig MaxLinesInEnum.rule) |> Option.toArray - this.maxLinesInUnion |> Option.bind (constructRuleWithConfig MaxLinesInUnion.rule) |> Option.toArray - this.maxLinesInClass |> Option.bind (constructRuleWithConfig MaxLinesInClass.rule) |> Option.toArray - |] |> Array.concat - -type NamesConfig = - { interfaceNames:RuleConfig option - exceptionNames:RuleConfig option - typeNames:RuleConfig option - recordFieldNames:RuleConfig option - enumCasesNames:RuleConfig option - unionCasesNames:RuleConfig option - moduleNames:RuleConfig option - literalNames:RuleConfig option - namespaceNames:RuleConfig option - memberNames:RuleConfig option - parameterNames:RuleConfig option - measureTypeNames:RuleConfig option - activePatternNames:RuleConfig option - publicValuesNames:RuleConfig option - nonPublicValuesNames:RuleConfig option } -with - member this.Flatten() = - [| - this.interfaceNames |> Option.bind (constructRuleWithConfig InterfaceNames.rule) |> Option.toArray - this.exceptionNames |> Option.bind (constructRuleWithConfig ExceptionNames.rule) |> Option.toArray - this.typeNames |> Option.bind (constructRuleWithConfig TypeNames.rule) |> Option.toArray - this.recordFieldNames |> Option.bind (constructRuleWithConfig RecordFieldNames.rule) |> Option.toArray - this.enumCasesNames |> Option.bind (constructRuleWithConfig EnumCasesNames.rule) |> Option.toArray - this.unionCasesNames |> Option.bind (constructRuleWithConfig UnionCasesNames.rule) |> Option.toArray - this.moduleNames |> Option.bind (constructRuleWithConfig ModuleNames.rule) |> Option.toArray - this.literalNames |> Option.bind (constructRuleWithConfig LiteralNames.rule) |> Option.toArray - this.namespaceNames |> Option.bind (constructRuleWithConfig NamespaceNames.rule) |> Option.toArray - this.memberNames |> Option.bind (constructRuleWithConfig MemberNames.rule) |> Option.toArray - this.parameterNames |> Option.bind (constructRuleWithConfig ParameterNames.rule) |> Option.toArray - this.measureTypeNames |> Option.bind (constructRuleWithConfig MeasureTypeNames.rule) |> Option.toArray - this.activePatternNames |> Option.bind (constructRuleWithConfig ActivePatternNames.rule) |> Option.toArray - this.publicValuesNames |> Option.bind (constructRuleWithConfig PublicValuesNames.rule) |> Option.toArray - this.nonPublicValuesNames |> Option.bind (constructRuleWithConfig NonPublicValuesNames.rule) |> Option.toArray - |] |> Array.concat - -type NumberOfItemsConfig = - { maxNumberOfItemsInTuple:RuleConfig option - maxNumberOfFunctionParameters:RuleConfig option - maxNumberOfMembers:RuleConfig option - maxNumberOfBooleanOperatorsInCondition:RuleConfig option } -with - member this.Flatten() = - [| - this.maxNumberOfItemsInTuple |> Option.bind (constructRuleWithConfig MaxNumberOfItemsInTuple.rule) |> Option.toArray - this.maxNumberOfFunctionParameters |> Option.bind (constructRuleWithConfig MaxNumberOfFunctionParameters.rule) |> Option.toArray - this.maxNumberOfMembers |> Option.bind (constructRuleWithConfig MaxNumberOfMembers.rule) |> Option.toArray - this.maxNumberOfBooleanOperatorsInCondition |> Option.bind (constructRuleWithConfig MaxNumberOfBooleanOperatorsInCondition.rule) |> Option.toArray - |] |> Array.concat - -type BindingConfig = - { favourIgnoreOverLetWild:EnabledConfig option - wildcardNamedWithAsPattern:EnabledConfig option - uselessBinding:EnabledConfig option - tupleOfWildcards:EnabledConfig option } -with - member this.Flatten() = - [| - this.favourIgnoreOverLetWild |> Option.bind (constructRuleIfEnabled FavourIgnoreOverLetWild.rule) |> Option.toArray - this.wildcardNamedWithAsPattern |> Option.bind (constructRuleIfEnabled WildcardNamedWithAsPattern.rule) |> Option.toArray - this.uselessBinding |> Option.bind (constructRuleIfEnabled UselessBinding.rule) |> Option.toArray - this.tupleOfWildcards |> Option.bind (constructRuleIfEnabled TupleOfWildcards.rule) |> Option.toArray - |] |> Array.concat - -type ConventionsConfig = - { recursiveAsyncFunction:EnabledConfig option - redundantNewKeyword:EnabledConfig option - nestedStatements:RuleConfig option - reimplementsFunction:EnabledConfig option - canBeReplacedWithComposition:EnabledConfig option - raiseWithTooManyArgs:RaiseWithTooManyArgsConfig option - sourceLength:SourceLengthConfig option - naming:NamesConfig option - numberOfItems:NumberOfItemsConfig option - binding:BindingConfig option } -with - member this.Flatten() = - [| - this.recursiveAsyncFunction |> Option.bind (constructRuleIfEnabled RecursiveAsyncFunction.rule) |> Option.toArray - this.redundantNewKeyword |> Option.bind (constructRuleIfEnabled RedundantNewKeyword.rule) |> Option.toArray - this.nestedStatements |> Option.bind (constructRuleWithConfig NestedStatements.rule) |> Option.toArray - this.reimplementsFunction |> Option.bind (constructRuleIfEnabled ReimplementsFunction.rule) |> Option.toArray - this.canBeReplacedWithComposition |> Option.bind (constructRuleIfEnabled CanBeReplacedWithComposition.rule) |> Option.toArray - this.raiseWithTooManyArgs |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - this.sourceLength |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - this.naming |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - this.numberOfItems |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - this.binding |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - |] |> Array.concat - -type TypographyConfig = - { indentation:EnabledConfig option - maxCharactersOnLine:RuleConfig option - trailingWhitespaceOnLine:RuleConfig option - maxLinesInFile:RuleConfig option - trailingNewLineInFile:EnabledConfig option - noTabCharacters:EnabledConfig option } -with - member this.Flatten() = - [| - this.indentation |> Option.bind (constructRuleIfEnabled Indentation.rule) |> Option.toArray - this.maxCharactersOnLine |> Option.bind (constructRuleWithConfig MaxCharactersOnLine.rule) |> Option.toArray - this.trailingWhitespaceOnLine |> Option.bind (constructRuleWithConfig TrailingWhitespaceOnLine.rule) |> Option.toArray - this.maxLinesInFile |> Option.bind (constructRuleWithConfig MaxLinesInFile.rule) |> Option.toArray - this.trailingNewLineInFile |> Option.bind (constructRuleIfEnabled TrailingNewLineInFile.rule) |> Option.toArray - this.noTabCharacters |> Option.bind (constructRuleIfEnabled NoTabCharacters.rule) |> Option.toArray - |] |> Array.concat - let private getOrEmptyList hints = hints |> Option.defaultValue [||] type HintConfig = { - add:string [] option - ignore:string [] option + Add:string [] option + Ignore:string [] option } type GlobalConfig = { - numIndentationSpaces:int option + NumIndentationSpaces:int option } type Configuration = { Global:GlobalConfig option - // Deprecated grouped configs. TODO: remove in next major release - /// DEPRECATED, provide formatting rules at root level. - formatting:FormattingConfig option - /// DEPRECATED, provide conventions rules at root level. - conventions:ConventionsConfig option - /// DEPRECATED, provide typography rules at root level. - typography:TypographyConfig option - ignoreFiles:string [] option + IgnoreFiles:string [] option Hints:HintConfig option TypedItemSpacing:RuleConfig option TypePrefixing:EnabledConfig option @@ -423,12 +214,8 @@ type Configuration = with static member Zero = { Global = None - ignoreFiles = None + IgnoreFiles = None Hints = None - formatting = None - conventions = None - typography = None - // Configs for rules. TypedItemSpacing = None TypePrefixing = None UnionDefinitionIndentation = None @@ -495,8 +282,6 @@ with NoTabCharacters = None } -// fsharplint:enable RecordFieldNames - /// Tries to parse the provided config text. let parseConfig (configText:string) = try @@ -532,13 +317,12 @@ type LineRules = type LoadedRules = { GlobalConfig:Rules.GlobalRuleConfig AstNodeRules:RuleMetadata [] - LineRules:LineRules - DeprecatedRules:Rule [] } + LineRules:LineRules } let getGlobalConfig (globalConfig:GlobalConfig option) = globalConfig |> Option.map (fun globalConfig -> { - Rules.GlobalRuleConfig.numIndentationSpaces = globalConfig.numIndentationSpaces |> Option.defaultValue Rules.GlobalRuleConfig.Default.numIndentationSpaces + Rules.GlobalRuleConfig.NumIndentationSpaces = globalConfig.NumIndentationSpaces |> Option.defaultValue Rules.GlobalRuleConfig.Default.NumIndentationSpaces }) |> Option.defaultValue Rules.GlobalRuleConfig.Default let private parseHints (hints:string []) = @@ -555,17 +339,11 @@ let private parseHints (hints:string []) = |> MergeSyntaxTrees.mergeHints let flattenConfig (config:Configuration) = - let deprecatedAllRules = + let allRules = [| - config.formatting |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - config.conventions |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat - config.typography |> Option.map (fun config -> config.Flatten()) |> Option.toArray |> Array.concat config.Hints |> Option.map (fun config -> HintMatcher.rule { - HintMatcher.Config.HintTrie = parseHints (getOrEmptyList config.add) }) |> Option.toArray - |] |> Array.concat + HintMatcher.Config.HintTrie = parseHints (getOrEmptyList config.Add) }) - let allRules = - [| config.TypedItemSpacing |> Option.bind (constructRuleWithConfig TypedItemSpacing.rule) config.TypePrefixing |> Option.bind (constructRuleIfEnabled TypePrefixing.rule) config.UnionDefinitionIndentation |> Option.bind (constructRuleIfEnabled UnionDefinitionIndentation.rule) @@ -636,12 +414,7 @@ let flattenConfig (config:Configuration) = let lineRules = ResizeArray() let mutable indentationRule = None let mutable noTabCharactersRule = None - Array.append allRules deprecatedAllRules - |> Array.distinctBy (function // Discard any deprecated rules which were define in a non-deprecated form. - | Rule.AstNodeRule rule -> rule.Identifier - | Rule.LineRule rule -> rule.Identifier - | Rule.IndentationRule rule -> rule.Identifier - | Rule.NoTabCharactersRule rule -> rule.Identifier) + allRules |> Array.iter (function | AstNodeRule rule -> astNodeRules.Add rule | LineRule rule -> lineRules.Add(rule) @@ -649,7 +422,6 @@ let flattenConfig (config:Configuration) = | NoTabCharactersRule rule -> noTabCharactersRule <- Some rule) { LoadedRules.GlobalConfig = getGlobalConfig config.Global - DeprecatedRules = deprecatedAllRules AstNodeRules = astNodeRules.ToArray() LineRules = { GenericLineRules = lineRules.ToArray() diff --git a/src/FSharpLint.Core/Application/Lint.fs b/src/FSharpLint.Core/Application/Lint.fs index aca12b658..02c30777d 100644 --- a/src/FSharpLint.Core/Application/Lint.fs +++ b/src/FSharpLint.Core/Application/Lint.fs @@ -404,7 +404,7 @@ module Lint = ReportLinterProgress = projectProgress } let isIgnoredFile filePath = - config.ignoreFiles + config.IgnoreFiles |> Option.map (fun ignoreFiles -> let parsedIgnoreFiles = ignoreFiles |> Array.map IgnoreFiles.parseIgnorePath |> Array.toList Configuration.IgnoreFiles.shouldFileBeIgnored parsedIgnoreFiles filePath) diff --git a/src/FSharpLint.Core/Framework/Rules.fs b/src/FSharpLint.Core/Framework/Rules.fs index e0f7b6542..1b9e12c5e 100644 --- a/src/FSharpLint.Core/Framework/Rules.fs +++ b/src/FSharpLint.Core/Framework/Rules.fs @@ -3,22 +3,14 @@ open FSharp.Compiler.SyntaxTree open FSharp.Compiler.Range open FSharp.Compiler.SourceCodeServices -open FSharpLint.Framework.AbstractSyntaxArray open FSharpLint.Framework.Ast open FSharpLint.Framework.Suggestion -// Non-standard record field names for serialization -// fsharplint:disable RecordFieldNames type GlobalRuleConfig = - { - numIndentationSpaces:int - } + { NumIndentationSpaces:int } with static member Default = - { - GlobalRuleConfig.numIndentationSpaces = 4 - } -// fsharplint:enable RecordFieldNames + { GlobalRuleConfig.NumIndentationSpaces = 4 } type AstNodeRuleParams = { AstNode:AstNode diff --git a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClauseIndentation.fs b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClauseIndentation.fs index 7734ef037..979863c6b 100644 --- a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClauseIndentation.fs +++ b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClauseIndentation.fs @@ -23,7 +23,7 @@ let check (config:Config) (args:AstNodeRuleParams) matchExprRange (clauses:SynMa |> Option.bind (fun firstClause -> let clauseIndentation = ExpressionUtilities.getLeadingSpaces firstClause.Range args.FileContent if isLambda then - if clauseIndentation <> matchStartIndentation + args.GlobalConfig.numIndentationSpaces then + if clauseIndentation <> matchStartIndentation + args.GlobalConfig.NumIndentationSpaces then { Range = firstClause.Range Message = Resources.GetString("RulesFormattingLambdaPatternMatchClauseIndentationError") SuggestedFix = None diff --git a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchExpressionIndentation.fs b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchExpressionIndentation.fs index 79ec2dc47..e7c1314f6 100644 --- a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchExpressionIndentation.fs +++ b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchExpressionIndentation.fs @@ -19,7 +19,7 @@ let check (args:AstNodeRuleParams) _ (clauses:SynMatchClause list) _ = guard |> Option.map (fun expr -> expr.Range.EndLine) |> Option.defaultValue pat.Range.EndLine - if expr.Range.StartLine <> matchPatternEndLine && exprIndentation <> clauseIndentation + args.GlobalConfig.numIndentationSpaces then + if expr.Range.StartLine <> matchPatternEndLine && exprIndentation <> clauseIndentation + args.GlobalConfig.NumIndentationSpaces then { Range = expr.Range Message = Resources.GetString("RulesFormattingMatchExpressionIndentationError") SuggestedFix = None diff --git a/src/FSharpLint.Core/Rules/Formatting/UnionDefinitionIndentation.fs b/src/FSharpLint.Core/Rules/Formatting/UnionDefinitionIndentation.fs index 8e1a23532..68b8c7617 100644 --- a/src/FSharpLint.Core/Rules/Formatting/UnionDefinitionIndentation.fs +++ b/src/FSharpLint.Core/Rules/Formatting/UnionDefinitionIndentation.fs @@ -23,7 +23,7 @@ let checkUnionDefinitionIndentation (args:AstNodeRuleParams) typeDefnRepr typeDe | [_] -> Array.empty | firstCase :: _ -> let indentationLevelError = - if getUnionCaseStartColumn firstCase - 2 <> typeDefnStartColumn + args.GlobalConfig.numIndentationSpaces then + if getUnionCaseStartColumn firstCase - 2 <> typeDefnStartColumn + args.GlobalConfig.NumIndentationSpaces then { Range = firstCase.Range Message = Resources.GetString("RulesFormattingUnionDefinitionIndentationError") SuggestedFix = None diff --git a/src/FSharpLint.Core/Rules/Typography/Indentation.fs b/src/FSharpLint.Core/Rules/Typography/Indentation.fs index 2102957d9..4ab2f5a9f 100644 --- a/src/FSharpLint.Core/Rules/Typography/Indentation.fs +++ b/src/FSharpLint.Core/Rules/Typography/Indentation.fs @@ -154,7 +154,7 @@ let checkIndentation (expectedSpaces:int) (line:string) (lineNumber:int) (indent None let runner context args = - checkIndentation args.GlobalConfig.numIndentationSpaces args.Line args.LineNumber context + checkIndentation args.GlobalConfig.NumIndentationSpaces args.Line args.LineNumber context |> Option.toArray let rule = diff --git a/tests/FSharpLint.Console.Tests/TestApp.fs b/tests/FSharpLint.Console.Tests/TestApp.fs index bab64e22f..00d784123 100644 --- a/tests/FSharpLint.Console.Tests/TestApp.fs +++ b/tests/FSharpLint.Console.Tests/TestApp.fs @@ -127,7 +127,7 @@ type TestConsoleApplication() = Assert.AreEqual(0, returnCode) Assert.AreEqual(Set.empty, errors) - /// Regression for bug discovered during: https://github.com/fsprojects/FSharpLint/issues/466 + /// Regression test 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).``() = @@ -140,6 +140,7 @@ type TestConsoleApplication() = """ use config = new TemporaryFile(config, "json") + // Should trigger warning for InterfaceNames rule. let input = """ type Signature = abstract member Encoded : string