diff --git a/src/FSharpLint.Console/Program.fs b/src/FSharpLint.Console/Program.fs index 0049ff76a..301b11a15 100644 --- a/src/FSharpLint.Console/Program.fs +++ b/src/FSharpLint.Console/Program.fs @@ -4,6 +4,8 @@ open Argu open System open System.IO open System.Reflection +open System.Linq +open System.Text open FSharpLint.Framework open FSharpLint.Application @@ -19,11 +21,20 @@ type internal FileType = | File = 3 | Source = 4 +type ExitCode = + | Error = -1 + | Success = 0 + | NoSuchRuleName = 1 + | NoFix = 2 + +let fileTypeHelp = "Input type the linter will run against. If this is not set, the file type will be inferred from the file extension." + // Allowing underscores in union case names for proper Argu command line option formatting. // fsharplint:disable UnionCasesNames type private ToolArgs = | [] Format of OutputFormat | [] Lint of ParseResults + | [] Fix of ParseResults | Version with interface IArgParserTemplate with @@ -31,6 +42,7 @@ with match this with | Format _ -> "Output format of the linter." | Lint _ -> "Runs FSharpLint against a file or a collection of files." + | Fix _ -> "Apply fixes for specified rule name or names (comma separated)." | Version -> "Prints current version." // TODO: investigate erroneous warning on this type definition @@ -45,10 +57,33 @@ with member this.Usage = match this 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." + | File_Type _ -> fileTypeHelp | Lint_Config _ -> "Path to the config for the lint." + +// TODO: investigate erroneous warning on this type definition +// fsharplint:disable UnionDefinitionIndentation +and private FixArgs = + | [] Fix_Target of ruleName:string * target:string + | Fix_File_Type of FileType +// fsharplint:enable UnionDefinitionIndentation +with + interface IArgParserTemplate with + member this.Usage = + match this with + | Fix_Target _ -> "Rule name to be applied with fix and input to lint." + | Fix_File_Type _ -> fileTypeHelp // fsharplint:enable UnionCasesNames +type private LintingArgs = + { + FileType: FileType + LintParams: OptionalLintParameters + Target: string + ToolsPath: Ionide.ProjInfo.Types.ToolsPath + ShouldFix: bool + MaybeRuleName: string option + } + let private parserProgress (output:Output.IOutput) = function | Starting file -> String.Format(Resources.GetString("ConsoleStartingFile"), file) |> output.WriteInfo @@ -70,8 +105,10 @@ let internal inferFileType (target:string) = else FileType.Source +// can't extract inner functions because they modify exitCode variable +// fsharplint:disable MaxLinesInFunction let private start (arguments:ParseResults) (toolsPath:Ionide.ProjInfo.Types.ToolsPath) = - let mutable exitCode = 0 + let mutable exitCode = ExitCode.Success let output = match arguments.TryGetResult Format with @@ -87,56 +124,156 @@ let private start (arguments:ParseResults) (toolsPath:Ionide.ProjInfo. output.WriteInfo $"Current version: {version}" Environment.Exit 0 - let handleError (str:string) = + let handleError (status:ExitCode) (str:string) = output.WriteError str - exitCode <- -1 + exitCode <- status - match arguments.GetSubCommand() with - | Lint lintArgs -> + let outputWarnings (warnings: List) = + String.Format(Resources.GetString "ConsoleFinished", List.length warnings) + |> output.WriteInfo + + let handleLintResult = function + | LintResult.Success warnings -> + outputWarnings warnings + if List.isEmpty warnings |> not then + exitCode <- ExitCode.Error + | LintResult.Failure failure -> handleError ExitCode.Error failure.Description + + let handleFixResult (target: string) (ruleName: string) = function + | LintResult.Success warnings -> + String.Format(Resources.GetString "ConsoleApplyingFixFile", target) |> output.WriteInfo + let increment = 1 + let noFixIncrement = 0 - let handleLintResult = function - | LintResult.Success(warnings) -> - String.Format(Resources.GetString("ConsoleFinished"), List.length warnings) - |> output.WriteInfo - if not (List.isEmpty warnings) then exitCode <- -1 - | LintResult.Failure(failure) -> - handleError failure.Description + let countFixes (element: Suggestion.LintWarning) = + let sourceCode = File.ReadAllText element.FilePath + if String.Equals(ruleName, element.RuleName, StringComparison.InvariantCultureIgnoreCase) then + match element.Details.Fix with + | Some lazyFix -> + match lazyFix.Force() with + | Some fix -> + let updatedSourceCode = + let builder = StringBuilder(sourceCode.Length + fix.ToText.Length) + let firstPart = + sourceCode.AsSpan( + 0, + (ExpressionUtilities.findPos fix.FromRange.Start sourceCode).Value + ) + let secondPart = + sourceCode.AsSpan + (ExpressionUtilities.findPos fix.FromRange.End sourceCode).Value + builder + .Append(firstPart) + .Append(fix.ToText) + .Append(secondPart) + .ToString() + File.WriteAllText( + element.FilePath, + updatedSourceCode, + Encoding.UTF8) + | _ -> () + increment + | None -> noFixIncrement + else + noFixIncrement - let lintConfig = lintArgs.TryGetResult Lint_Config + let countFix = + warnings |> List.sumBy countFixes + outputWarnings warnings - let configParam = - match lintConfig with + if countFix > 0 then + exitCode <- ExitCode.Success + else + exitCode <- ExitCode.NoFix + + | LintResult.Failure failure -> handleError ExitCode.Error failure.Description + + let linting (args: LintingArgs) = + try + let lintResult = + match args.FileType with + | FileType.File -> Lint.lintFile args.LintParams args.Target + | FileType.Source -> Lint.lintSource args.LintParams args.Target + | FileType.Solution -> Lint.lintSolution args.LintParams args.Target toolsPath + | FileType.Project + | _ -> Lint.lintProject args.LintParams args.Target toolsPath + if args.ShouldFix then + match args.MaybeRuleName with + | Some ruleName -> handleFixResult args.Target ruleName lintResult + | None -> exitCode <- ExitCode.NoSuchRuleName + else + handleLintResult lintResult + with + | exn -> + let target = if args.FileType = FileType.Source then "source" else args.Target + $"Lint failed while analysing %s{target}.{Environment.NewLine}Failed with: %s{exn.Message}{Environment.NewLine}Stack trace: {exn.StackTrace}" + |> handleError ExitCode.Error + + let getParams config = + let paramConfig = + match config with | Some configPath -> FromFile configPath | None -> Default + { CancellationToken = None + ReceivedWarning = Some output.WriteWarning + Configuration = paramConfig + ReportLinterProgress = parserProgress output |> Some } - let lintParams = - { CancellationToken = None - ReceivedWarning = Some output.WriteWarning - Configuration = configParam - ReportLinterProgress = Some (parserProgress output) } + let applyLint (lintArgs: ParseResults) = + let lintConfig = lintArgs.TryGetResult Lint_Config + let lintParams = getParams lintConfig let target = lintArgs.GetResult Target let fileType = lintArgs.TryGetResult File_Type |> Option.defaultValue (inferFileType target) - try - let lintResult = - match fileType with - | FileType.File -> Lint.lintFile lintParams target - | FileType.Source -> Lint.lintSource lintParams target - | FileType.Solution -> Lint.lintSolution lintParams target toolsPath - | FileType.Project - | _ -> Lint.lintProject lintParams target toolsPath - handleLintResult lintResult - with - | exn -> - let target = if fileType = FileType.Source then "source" else target - handleError - $"Lint failed while analysing %s{target}.{Environment.NewLine}Failed with: %s{exn.Message}{Environment.NewLine}Stack trace: {exn.StackTrace}" - | _ -> () + linting + { FileType = fileType + LintParams = lintParams + Target = target + ToolsPath = toolsPath + ShouldFix = false + MaybeRuleName = None } + + let applyFix (fixArgs: ParseResults) = + let fixParams = getParams None + let ruleName, target = fixArgs.GetResult Fix_Target + let fileType = fixArgs.TryGetResult Fix_File_Type |> Option.defaultValue (inferFileType target) + + let allRules = + match getConfig fixParams.Configuration with + | Ok config -> Some (Configuration.flattenConfig config false) + | _ -> None - exitCode + let allRuleNames = + match allRules with + | Some rules -> (fun (loadedRules:Configuration.LoadedRules) -> ([| + loadedRules.LineRules.IndentationRule |> Option.map (fun rule -> rule.Name) |> Option.toArray + loadedRules.LineRules.NoTabCharactersRule |> Option.map (fun rule -> rule.Name) |> Option.toArray + loadedRules.LineRules.GenericLineRules |> Array.map (fun rule -> rule.Name) + loadedRules.AstNodeRules |> Array.map (fun rule -> rule.Name) + |] |> Array.concat |> Set.ofArray)) rules + | _ -> Set.empty + + if allRuleNames.Any(fun aRuleName -> String.Equals(aRuleName, ruleName, StringComparison.InvariantCultureIgnoreCase)) then + linting + { FileType = fileType + LintParams = fixParams + Target = target + ToolsPath = toolsPath + ShouldFix = true + MaybeRuleName = Some ruleName } + else + sprintf "Rule '%s' does not exist." ruleName |> (handleError ExitCode.NoSuchRuleName) + + match arguments.GetSubCommand() with + | Lint lintArgs -> applyLint lintArgs + | Fix fixArgs -> applyFix fixArgs + | _ -> () + int exitCode +// fsharplint:enable MaxLinesInFunction + /// Must be called only once per process. /// We're calling it globally so we can call main multiple times from our tests. let toolsPath = Ionide.ProjInfo.Init.init (DirectoryInfo <| Directory.GetCurrentDirectory()) None diff --git a/src/FSharpLint.Core/Application/Configuration.fs b/src/FSharpLint.Core/Application/Configuration.fs index 9537b8318..5a258cda6 100644 --- a/src/FSharpLint.Core/Application/Configuration.fs +++ b/src/FSharpLint.Core/Application/Configuration.fs @@ -105,13 +105,20 @@ type RuleConfig<'Config> = { type EnabledConfig = RuleConfig -let constructRuleIfEnabled rule ruleConfig = if ruleConfig.Enabled then Some rule else None +let constructRuleIfEnabledBase (onlyEnabled: bool) rule ruleConfig = + if not onlyEnabled || ruleConfig.Enabled then Some rule else None -let constructRuleWithConfig rule ruleConfig = - if ruleConfig.Enabled then - Option.map rule ruleConfig.Config - else - None +let constructRuleIfEnabled rule ruleConfig = + constructRuleIfEnabledBase true rule ruleConfig + +let constructRuleWithConfigBase (onlyEnabled: bool) (rule: 'TRuleConfig -> 'TRule) (ruleConfig: RuleConfig<'TRuleConfig>): Option<'TRule> = + if not onlyEnabled || ruleConfig.Enabled then + ruleConfig.Config |> Option.map rule + else + None + +let constructRuleWithConfig (rule: 'TRuleConfig -> 'TRule) (ruleConfig: RuleConfig<'TRuleConfig>): Option<'TRule> = + constructRuleWithConfigBase true rule ruleConfig let constructTypePrefixingRuleWithConfig rule (ruleConfig: RuleConfig) = if ruleConfig.Enabled then @@ -663,7 +670,7 @@ let findDeprecation config deprecatedAllRules allRules = } // fsharplint:disable MaxLinesInFunction -let flattenConfig (config:Configuration) = +let flattenConfig (config:Configuration) (onlyEnabled:bool) = let deprecatedAllRules = Array.concat [| @@ -673,6 +680,12 @@ let flattenConfig (config:Configuration) = config.Hints |> Option.map (fun config -> HintMatcher.rule { HintMatcher.Config.HintTrie = parseHints (getOrEmptyList config.add) }) |> Option.toArray |] + let constructRuleIfEnabled rule ruleConfig = + constructRuleIfEnabledBase onlyEnabled rule ruleConfig + + let constructRuleWithConfig (rule: 'TRuleConfig -> 'TRule) (ruleConfig: RuleConfig<'TRuleConfig>): Option<'TRule> = + constructRuleWithConfigBase onlyEnabled rule ruleConfig + let allRules = Array.choose id diff --git a/src/FSharpLint.Core/Application/Lint.fs b/src/FSharpLint.Core/Application/Lint.fs index bf9a2a986..2e5708cdd 100644 --- a/src/FSharpLint.Core/Application/Lint.fs +++ b/src/FSharpLint.Core/Application/Lint.fs @@ -237,7 +237,7 @@ module Lint = | Some(value) -> not value.IsCancellationRequested | None -> true - let enabledRules = Configuration.flattenConfig lintInfo.Configuration + let enabledRules = Configuration.flattenConfig lintInfo.Configuration true let lines = String.toLines fileInfo.Text |> Array.map (fun (line, _, _) -> line) let allRuleNames = @@ -423,7 +423,7 @@ module Lint = } /// Gets a FSharpLint Configuration based on the provided ConfigurationParam. - let private getConfig (configParam:ConfigurationParam) = + let getConfig (configParam:ConfigurationParam) = match configParam with | Configuration config -> Ok config | FromFile filePath -> diff --git a/src/FSharpLint.Core/Application/Lint.fsi b/src/FSharpLint.Core/Application/Lint.fsi index 7e697df5a..f1a8e7c7e 100644 --- a/src/FSharpLint.Core/Application/Lint.fsi +++ b/src/FSharpLint.Core/Application/Lint.fsi @@ -165,4 +165,6 @@ module Lint = /// Lints an F# file that has already been parsed using /// `FSharp.Compiler.Services` in the calling application. - val lintParsedFile : optionalParams:OptionalLintParameters -> parsedFileInfo:ParsedFileInformation -> filePath:string -> LintResult \ No newline at end of file + val lintParsedFile : optionalParams:OptionalLintParameters -> parsedFileInfo:ParsedFileInformation -> filePath:string -> LintResult + + val getConfig : ConfigurationParam -> Result diff --git a/src/FSharpLint.Core/Framework/Suggestion.fs b/src/FSharpLint.Core/Framework/Suggestion.fs index afc263a78..e071e98c2 100644 --- a/src/FSharpLint.Core/Framework/Suggestion.fs +++ b/src/FSharpLint.Core/Framework/Suggestion.fs @@ -5,10 +5,7 @@ open FSharp.Compiler.Text /// Information for consuming applications to provide an automated fix for a lint suggestion. [] -type SuggestedFix = { - /// Text to be replaced. - FromText:string - +type Fix = { /// Location of the text to be replaced. FromRange:Range @@ -25,7 +22,7 @@ type WarningDetails = { Message:string /// Information to provide an automated fix. - SuggestedFix:Lazy option + Fix:Lazy option /// Type checks to be performed to confirm this suggestion is valid. /// Suggestion is only considered valid when all type checks resolve to true. diff --git a/src/FSharpLint.Core/Rules/Conventions/AsyncExceptionWithoutReturn.fs b/src/FSharpLint.Core/Rules/Conventions/AsyncExceptionWithoutReturn.fs index 978ed38ef..791170a1c 100644 --- a/src/FSharpLint.Core/Rules/Conventions/AsyncExceptionWithoutReturn.fs +++ b/src/FSharpLint.Core/Rules/Conventions/AsyncExceptionWithoutReturn.fs @@ -50,7 +50,7 @@ let rec checkExpression (expression: SynExpr) (range: range) (continuation: unit { Range = range Message = Resources.GetString "RulesAsyncExceptionWithoutReturn" - SuggestedFix = None + Fix = None TypeChecks = List.Empty } | SynExpr.App (_, _, funcExpr, _, range) -> diff --git a/src/FSharpLint.Core/Rules/Conventions/AvoidSinglePipeOperator.fs b/src/FSharpLint.Core/Rules/Conventions/AvoidSinglePipeOperator.fs index 956722d78..adb03f74c 100644 --- a/src/FSharpLint.Core/Rules/Conventions/AvoidSinglePipeOperator.fs +++ b/src/FSharpLint.Core/Rules/Conventions/AvoidSinglePipeOperator.fs @@ -9,12 +9,12 @@ open FSharpLint.Framework.Ast open FSharpLint.Framework.Rules let runner (args: AstNodeRuleParams) = - let errors range suggestedFix = + let errors range fix = Array.singleton { Range = range Message = String.Format(Resources.GetString ("RulesAvoidSinglePipeOperator")) - SuggestedFix = suggestedFix + Fix = fix TypeChecks = List.Empty } @@ -43,15 +43,15 @@ let runner (args: AstNodeRuleParams) = if isParentPiped then Array.empty else - let suggestedFix = lazy( + let fix = lazy( let maybeFuncText = ExpressionUtilities.tryFindTextOfRange outerArgExpr.Range args.FileContent let maybeArgText = ExpressionUtilities.tryFindTextOfRange argExpr.Range args.FileContent match (maybeFuncText, maybeArgText) with | Some(funcText), Some(argText) -> let replacementText = sprintf "%s %s" funcText argText - Some { FromText=args.FileContent; FromRange=range; ToText=replacementText } + Some { FromRange=range; ToText=replacementText } | _ -> None) - errors ident.idRange (Some suggestedFix) + errors ident.idRange (Some fix) else Array.empty | _ -> diff --git a/src/FSharpLint.Core/Rules/Conventions/AvoidTooShortNames.fs b/src/FSharpLint.Core/Rules/Conventions/AvoidTooShortNames.fs index 5c7f04171..8033de59f 100644 --- a/src/FSharpLint.Core/Rules/Conventions/AvoidTooShortNames.fs +++ b/src/FSharpLint.Core/Rules/Conventions/AvoidTooShortNames.fs @@ -23,7 +23,7 @@ let private checkIdentifier (identifier:Ident) (idText:string) = |> Array.map (fun message -> { Range = identifier.idRange Message = message - SuggestedFix = None + Fix = None TypeChecks = List.Empty }) else Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/Binding/FavourAsKeyword.fs b/src/FSharpLint.Core/Rules/Conventions/Binding/FavourAsKeyword.fs index 81e78db32..accb20c7a 100644 --- a/src/FSharpLint.Core/Rules/Conventions/Binding/FavourAsKeyword.fs +++ b/src/FSharpLint.Core/Rules/Conventions/Binding/FavourAsKeyword.fs @@ -23,21 +23,21 @@ let private checkForNamedPatternEqualsConstant (args:AstNodeRuleParams) pattern let fromRange = Range.mkRange String.Empty range.Start constRange.End - let suggestedFix = + let fix = ExpressionUtilities.tryFindTextOfRange fromRange args.FileContent |> Option.bind (fun text -> ExpressionUtilities.tryFindTextOfRange constRange args.FileContent |> Option.bind (fun constText -> - Some (lazy (Some { FromText = text; FromRange = fromRange; ToText = $"{constText} as {ident.idText}"})) + Some (lazy (Some { FromRange = fromRange; ToText = $"{constText} as {ident.idText}"})) ) ) Array.singleton { Range = fromRange Message = Resources.GetString("RulesFavourAsKeyword") - SuggestedFix = suggestedFix - TypeChecks = List.Empty } + Fix = fix + TypeChecks = List.empty } | _ -> Array.empty | _ -> Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/Binding/FavourIgnoreOverLetWild.fs b/src/FSharpLint.Core/Rules/Conventions/Binding/FavourIgnoreOverLetWild.fs index 4a40f86fa..3047e0a2c 100644 --- a/src/FSharpLint.Core/Rules/Conventions/Binding/FavourIgnoreOverLetWild.fs +++ b/src/FSharpLint.Core/Rules/Conventions/Binding/FavourIgnoreOverLetWild.fs @@ -19,9 +19,8 @@ let private checkForBindingToAWildcard pattern range fileContent (expr: SynExpr) Array.singleton { Range = range Message = Resources.GetString("RulesFavourIgnoreOverLetWildError") - SuggestedFix = Some (lazy (Some({ FromRange = letBindingRange - FromText = fileContent - ToText = sprintf "(%s) |> ignore" exprText }))) + Fix = Some (lazy (Some({ FromRange = letBindingRange + ToText = sprintf "(%s) |> ignore" exprText }))) TypeChecks = List.Empty } else Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/Binding/FavourTypedIgnore.fs b/src/FSharpLint.Core/Rules/Conventions/Binding/FavourTypedIgnore.fs index ce5bec3cf..2488dce3a 100644 --- a/src/FSharpLint.Core/Rules/Conventions/Binding/FavourTypedIgnore.fs +++ b/src/FSharpLint.Core/Rules/Conventions/Binding/FavourTypedIgnore.fs @@ -10,21 +10,18 @@ open FSharpLint.Framework.Rules let private runner (args: AstNodeRuleParams) = let generateError identifier range text = - let suggestedFix = + let fix = lazy (ExpressionUtilities.tryFindTextOfRange range text |> Option.map (fun fromText -> - { FromText = fromText - FromRange = range + { FromRange = range ToText = identifier })) - { - Range = range - Message = String.Format(Resources.GetString "RulesFavourTypedIgnore", identifier) - SuggestedFix = Some suggestedFix - TypeChecks = List.Empty - } + { Range = range + Message = String.Format(Resources.GetString "RulesFavourTypedIgnore", identifier) + Fix = Some fix + TypeChecks = List.Empty } let isTyped expression identifier range text = match expression with diff --git a/src/FSharpLint.Core/Rules/Conventions/Binding/TupleOfWildcards.fs b/src/FSharpLint.Core/Rules/Conventions/Binding/TupleOfWildcards.fs index 87821f70f..1a3b34071 100644 --- a/src/FSharpLint.Core/Rules/Conventions/Binding/TupleOfWildcards.fs +++ b/src/FSharpLint.Core/Rules/Conventions/Binding/TupleOfWildcards.fs @@ -27,15 +27,10 @@ let private checkTupleOfWildcards fileContents pattern identifier identifierRang let refactorFrom = constructorString (List.length patterns) let refactorTo = constructorString 1 let error = String.Format(errorFormat, refactorFrom, refactorTo) - let suggestedFix = lazy( - Some { SuggestedFix.FromRange = identifierRange; FromText = fileContents; ToText = refactorTo }) + let fix = lazy( + Some { Fix.FromRange = identifierRange; ToText = refactorTo }) Array.singleton - { - Range = range - Message = error - SuggestedFix = Some suggestedFix - TypeChecks = List.Empty - } + { Range = range; Message = error; Fix = Some fix; TypeChecks = List.Empty } | _ -> Array.empty let private isTupleMemberArgs breadcrumbs tupleRange = diff --git a/src/FSharpLint.Core/Rules/Conventions/Binding/UselessBinding.fs b/src/FSharpLint.Core/Rules/Conventions/Binding/UselessBinding.fs index 380457eb2..2897908be 100644 --- a/src/FSharpLint.Core/Rules/Conventions/Binding/UselessBinding.fs +++ b/src/FSharpLint.Core/Rules/Conventions/Binding/UselessBinding.fs @@ -9,7 +9,7 @@ open FSharp.Compiler.CodeAnalysis open FSharpLint.Framework.Ast open FSharpLint.Framework.Rules -let private checkForUselessBinding (checkInfo:FSharpCheckFileResults option) pattern expr range maybeSuggestedFix = +let private checkForUselessBinding (checkInfo:FSharpCheckFileResults option) pattern expr range maybeFix = match checkInfo with | Some checkInfo -> let rec findBindingIdentifier = function @@ -42,23 +42,23 @@ let private checkForUselessBinding (checkInfo:FSharpCheckFileResults option) pat |> Option.map (fun ident -> { Range = range Message = Resources.GetString("RulesUselessBindingError") - SuggestedFix = Some (lazy(maybeSuggestedFix)) + Fix = Some (lazy(maybeFix)) TypeChecks = [ checkNotMutable ident ] }) |> Option.toArray | _ -> Array.empty let private runner (args:AstNodeRuleParams) = - let maybeSuggestedFix = + let maybeFix = match args.GetParents(args.NodeIndex) with | AstNode.ModuleDeclaration(SynModuleDecl.Let(_, _, range)) :: _ -> - Some({ FromRange = range; FromText = "let"; ToText = String.Empty }) + Some({ FromRange = range; ToText = String.Empty }) | AstNode.Expression(SynExpr.LetOrUse(_, false, _, _, range, _)) :: _ -> - Some({ FromRange = range; FromText = "use"; ToText = String.Empty }) + Some({ FromRange = range; ToText = String.Empty }) | _ -> None match args.AstNode with | AstNode.Binding(SynBinding(_, _, _, isMutable, _, _, _, pattern, _, expr, range, _, _)) - when maybeSuggestedFix.IsSome && not isMutable -> - checkForUselessBinding args.CheckInfo pattern expr range maybeSuggestedFix + when maybeFix.IsSome && not isMutable -> + checkForUselessBinding args.CheckInfo pattern expr range maybeFix | _ -> Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/Binding/WildcardNamedWithAsPattern.fs b/src/FSharpLint.Core/Rules/Conventions/Binding/WildcardNamedWithAsPattern.fs index db0a4b854..a037246cc 100644 --- a/src/FSharpLint.Core/Rules/Conventions/Binding/WildcardNamedWithAsPattern.fs +++ b/src/FSharpLint.Core/Rules/Conventions/Binding/WildcardNamedWithAsPattern.fs @@ -11,13 +11,12 @@ let private checkForWildcardNamedWithAsPattern fileContents pattern = match pattern with | SynPat.As(SynPat.Wild(wildcardRange), SynPat.Named(SynIdent(identifier, _), _, _, _), range) when wildcardRange <> range -> - let suggestedFix = - lazy( - Some { FromRange = range; FromText = fileContents; ToText = identifier.idText }) + let fix = + lazy(Some { FromRange = range; ToText = identifier.idText }) Array.singleton { Range = range Message = Resources.GetString("RulesWildcardNamedWithAsPattern") - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } | _ -> Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/CyclomaticComplexity.fs b/src/FSharpLint.Core/Rules/Conventions/CyclomaticComplexity.fs index 917797e79..42cfb291e 100644 --- a/src/FSharpLint.Core/Rules/Conventions/CyclomaticComplexity.fs +++ b/src/FSharpLint.Core/Rules/Conventions/CyclomaticComplexity.fs @@ -193,7 +193,7 @@ let runner (config:Config) (args:AstNodeRuleParams) : WarningDetails[] = (pos.Column, pos.Line)) |> Seq.map (fun scope -> // transform into WarningDetails let errMsg = String.Format(Resources.GetString("RulesCyclomaticComplexityError"), scope.Complexity, config.MaxComplexity) - { Range = scope.Binding.RangeOfBindingWithRhs; Message = errMsg; SuggestedFix = None; TypeChecks = List.Empty }) + { Range = scope.Binding.RangeOfBindingWithRhs; Message = errMsg; Fix = None; TypeChecks = List.Empty }) |> Seq.toList let ret = match warningDetails with | Some warning -> warning::fromStack diff --git a/src/FSharpLint.Core/Rules/Conventions/EnsureTailCallDiagnosticsInRecursiveFunctions.fs b/src/FSharpLint.Core/Rules/Conventions/EnsureTailCallDiagnosticsInRecursiveFunctions.fs index e6c25343a..413354359 100644 --- a/src/FSharpLint.Core/Rules/Conventions/EnsureTailCallDiagnosticsInRecursiveFunctions.fs +++ b/src/FSharpLint.Core/Rules/Conventions/EnsureTailCallDiagnosticsInRecursiveFunctions.fs @@ -15,7 +15,7 @@ let private emitWarning (func: UnneededRecKeyword.RecursiveFunctionInfo) = Resources.GetString "RulesEnsureTailCallDiagnosticsInRecursiveFunctions", func.Identifier.idText ) - SuggestedFix = None + Fix = None TypeChecks = list.Empty } let runner (args: AstNodeRuleParams) = diff --git a/src/FSharpLint.Core/Rules/Conventions/FavourConsistentThis.fs b/src/FSharpLint.Core/Rules/Conventions/FavourConsistentThis.fs index 4a4d800a1..b1f5ff9ba 100644 --- a/src/FSharpLint.Core/Rules/Conventions/FavourConsistentThis.fs +++ b/src/FSharpLint.Core/Rules/Conventions/FavourConsistentThis.fs @@ -24,12 +24,12 @@ let runner (config: Config) args = if identifiers.Length = 2 then match identifiers with | head::_ when isNotConsistent head.idText symbol -> - let suggestedFix = lazy(Some({ FromRange = head.idRange; FromText = head.idText; ToText = symbol })) + let fix = lazy(Some({ FromRange = head.idRange; ToText = symbol })) let error = Array.singleton { Range = range Message = String.Format(Resources.GetString "RulesFavourConsistentThis", config.Symbol) - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } error | _ -> Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/FavourNonMutablePropertyInitialization.fs b/src/FSharpLint.Core/Rules/Conventions/FavourNonMutablePropertyInitialization.fs index cf1986321..0e48e70b8 100644 --- a/src/FSharpLint.Core/Rules/Conventions/FavourNonMutablePropertyInitialization.fs +++ b/src/FSharpLint.Core/Rules/Conventions/FavourNonMutablePropertyInitialization.fs @@ -18,7 +18,7 @@ let private getWarningDetails (ident: Ident) = |> Array.map (fun message -> { Range = ident.idRange Message = message - SuggestedFix = None + Fix = None TypeChecks = List.Empty }) let private extraInstanceMethod (app:SynExpr) (instanceMethodCalls: List) = diff --git a/src/FSharpLint.Core/Rules/Conventions/FavourReRaise.fs b/src/FSharpLint.Core/Rules/Conventions/FavourReRaise.fs index b1dfc2d2d..8cdd5fccf 100644 --- a/src/FSharpLint.Core/Rules/Conventions/FavourReRaise.fs +++ b/src/FSharpLint.Core/Rules/Conventions/FavourReRaise.fs @@ -8,24 +8,24 @@ open FSharpLint.Framework.Ast open FSharpLint.Framework.Rules let private runner (args: AstNodeRuleParams) = - let generateError suggestedFix range = + let generateError fix range = Array.singleton { Range = range Message = Resources.GetString "RulesFavourReRaise" - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.empty } let rec checkExpr (expr) maybeIdent = match expr with | SynExpr.App (_, _, SynExpr.Ident raiseId, expression, range) when raiseId.idText = "raise" -> - let suggestedFix = lazy(Some({ FromRange = range; FromText = raiseId.idText; ToText = "reraise()" })) + let fix = lazy(Some({ FromRange = range; ToText = "reraise()" })) match expression with | SynExpr.Ident ident -> match maybeIdent with | Some id when id = ident.idText -> - generateError suggestedFix range + generateError fix range | _ -> Array.empty - | SynExpr.LongIdent (_, SynLongIdent (id, _, _), _, range) -> generateError suggestedFix range + | SynExpr.LongIdent (_, SynLongIdent (id, _, _), _, range) -> generateError fix range | _ -> Array.empty | SynExpr.TryWith (expressions, clauseList, _range, _, _, _) as expr -> clauseList diff --git a/src/FSharpLint.Core/Rules/Conventions/FavourStaticEmptyFields.fs b/src/FSharpLint.Core/Rules/Conventions/FavourStaticEmptyFields.fs index 0ba6790fa..22a01f320 100644 --- a/src/FSharpLint.Core/Rules/Conventions/FavourStaticEmptyFields.fs +++ b/src/FSharpLint.Core/Rules/Conventions/FavourStaticEmptyFields.fs @@ -25,17 +25,17 @@ let private getStaticEmptyErrorMessage (range:FSharp.Compiler.Text.Range) (empt formatError errorMessageKey let private generateError (fileContents: string) (range:FSharp.Compiler.Text.Range) (emptyLiteralType: EmptyLiteralType) = - let suggestedFix = lazy( + let fix = lazy( let replacementText = match emptyLiteralType with | EmptyStringLiteral -> "String.Empty" | EmptyListLiteral -> "List.Empty" | EmptyArrayLiteral -> "Array.empty" - Some({ FromRange = range; FromText = fileContents; ToText = replacementText })) + Some({ FromRange = range; ToText = replacementText })) Array.singleton { Range = range Message = getStaticEmptyErrorMessage range emptyLiteralType - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } let private runner (args: AstNodeRuleParams) = diff --git a/src/FSharpLint.Core/Rules/Conventions/FunctionReimplementation/CanBeReplacedWithComposition.fs b/src/FSharpLint.Core/Rules/Conventions/FunctionReimplementation/CanBeReplacedWithComposition.fs index 3be3ec9bb..cf0c255f5 100644 --- a/src/FSharpLint.Core/Rules/Conventions/FunctionReimplementation/CanBeReplacedWithComposition.fs +++ b/src/FSharpLint.Core/Rules/Conventions/FunctionReimplementation/CanBeReplacedWithComposition.fs @@ -62,13 +62,13 @@ let private validateLambdaCannotBeReplacedWithComposition fileContents _ lambda match tryReplaceWithFunctionComposition lambda.Body with | None -> Array.empty | Some funcStrings -> - let suggestedFix = + let fix = lazy( - Some { FromRange = range; FromText = fileContents; ToText = String.Join(" >> ", funcStrings) }) + Some { FromRange = range; ToText = String.Join(" >> ", funcStrings) }) Array.singleton { Range = range Message = Resources.GetString("RulesCanBeReplacedWithComposition") - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } let runner (args:AstNodeRuleParams) = diff --git a/src/FSharpLint.Core/Rules/Conventions/FunctionReimplementation/ReimplementsFunction.fs b/src/FSharpLint.Core/Rules/Conventions/FunctionReimplementation/ReimplementsFunction.fs index 60bb0c259..a9a3331cb 100644 --- a/src/FSharpLint.Core/Rules/Conventions/FunctionReimplementation/ReimplementsFunction.fs +++ b/src/FSharpLint.Core/Rules/Conventions/FunctionReimplementation/ReimplementsFunction.fs @@ -31,16 +31,14 @@ let private validateLambdaIsNotPointless (text:string) lambda range = ident.idText) |> String.concat "." - let suggestedFix = lazy( + let fix = lazy( ExpressionUtilities.tryFindTextOfRange range text - |> Option.map (fun fromText -> { FromText = fromText; FromRange = range; ToText = identifier })) + |> Option.map (fun fromText -> { FromRange = range; ToText = identifier })) - { - Range = range - Message = String.Format(Resources.GetString("RulesReimplementsFunction"), identifier) - SuggestedFix = Some suggestedFix - TypeChecks = List.Empty - } + { Range = range + Message = String.Format(Resources.GetString("RulesReimplementsFunction"), identifier) + Fix = Some fix + TypeChecks = List.Empty } let argumentsAsIdentifiers = lambda.Arguments diff --git a/src/FSharpLint.Core/Rules/Conventions/Naming/NamingHelper.fs b/src/FSharpLint.Core/Rules/Conventions/Naming/NamingHelper.fs index fe8c2fc06..1b2d274c3 100644 --- a/src/FSharpLint.Core/Rules/Conventions/Naming/NamingHelper.fs +++ b/src/FSharpLint.Core/Rules/Conventions/Naming/NamingHelper.fs @@ -12,23 +12,23 @@ open FSharpLint.Framework.Utilities open FSharp.Compiler.CodeAnalysis open FSharp.Compiler.Symbols -module QuickFixes = +module Fixes = let removeAllUnderscores (ident:Ident) = lazy( let toText = ident.idText.Replace("_", String.Empty) - Some { FromText = ident.idText; FromRange = ident.idRange; ToText = toText }) + Some { FromRange = ident.idRange; ToText = toText }) let removeNonPrefixingUnderscores (ident:Ident) = lazy( let prefixingUnderscores = ident.idText |> Seq.takeWhile (fun char -> char = '_') |> String.Concat let toText = prefixingUnderscores + ident.idText.Replace("_", String.Empty) - Some { FromText = ident.idText; FromRange = ident.idRange; ToText = toText }) + Some { FromRange = ident.idRange; ToText = toText }) let addPrefix prefix (ident:Ident) = lazy( - Some { FromText = ident.idText; FromRange = ident.idRange; ToText = prefix + ident.idText }) + Some { FromRange = ident.idRange; ToText = prefix + ident.idText }) let addSuffix suffix (ident:Ident) = lazy( - Some { FromText = ident.idText; FromRange = ident.idRange; ToText = ident.idText + suffix }) + Some { FromRange = ident.idRange; ToText = ident.idText + suffix }) let private mapFirstChar map (str:string) = let prefix = @@ -42,11 +42,11 @@ module QuickFixes = let toPascalCase (ident:Ident) = lazy( let pascalCaseIdent = mapFirstChar Char.ToUpper ident.idText - Some { FromText = ident.idText; FromRange = ident.idRange; ToText = pascalCaseIdent }) + Some { FromRange = ident.idRange; ToText = pascalCaseIdent }) let toCamelCase (ident:Ident) = lazy( let camelCaseIdent = mapFirstChar Char.ToLower ident.idText - Some { FromText = ident.idText; FromRange = ident.idRange; ToText = camelCaseIdent }) + Some { FromRange = ident.idRange; ToText = camelCaseIdent }) [] let private NumberOfExpectedBackticks = 4 @@ -112,31 +112,31 @@ let private checkIdentifierPart (config:NamingConfig) (identifier:Ident) (idText match config.Naming with | Some NamingCase.PascalCase -> pascalCaseRule idText - |> Option.map (formatError >> tryAddFix QuickFixes.toPascalCase) + |> Option.map (formatError >> tryAddFix Fixes.toPascalCase) | Some NamingCase.CamelCase -> camelCaseRule idText - |> Option.map (formatError >> tryAddFix QuickFixes.toCamelCase) + |> Option.map (formatError >> tryAddFix Fixes.toCamelCase) | _ -> None let underscoresError = match config.Underscores with | Some NamingUnderscores.None -> underscoreRule false idText - |> Option.map (formatError >> tryAddFix QuickFixes.removeAllUnderscores) + |> Option.map (formatError >> tryAddFix Fixes.removeAllUnderscores) | Some NamingUnderscores.AllowPrefix -> underscoreRule true idText - |> Option.map (formatError >> tryAddFix QuickFixes.removeNonPrefixingUnderscores) + |> Option.map (formatError >> tryAddFix Fixes.removeNonPrefixingUnderscores) | _ -> None let prefixError = Option.bind (fun prefix -> prefixRule prefix idText - |> Option.map (formatError2 prefix >> tryAddFix (QuickFixes.addPrefix prefix))) config.Prefix + |> Option.map (formatError2 prefix >> tryAddFix (Fixes.addPrefix prefix))) config.Prefix let suffixError = Option.bind (fun suffix -> suffixRule suffix idText - |> Option.map (formatError2 suffix >> tryAddFix (QuickFixes.addSuffix suffix))) config.Suffix + |> Option.map (formatError2 suffix >> tryAddFix (Fixes.addSuffix suffix))) config.Suffix Array.choose id [| @@ -149,13 +149,11 @@ let private checkIdentifierPart (config:NamingConfig) (identifier:Ident) (idText let private checkIdentifier (namingConfig:NamingConfig) (identifier:Ident) (idText:string) = if notOperator idText && isNotDoubleBackTickedIdent identifier then checkIdentifierPart namingConfig identifier idText - |> Array.map (fun (message, suggestedFix) -> - { - Range = identifier.idRange - Message = message - SuggestedFix = Some suggestedFix - TypeChecks = List.Empty - }) + |> Array.map (fun (message, fix) -> + { Range = identifier.idRange + Message = message + Fix = Some fix + TypeChecks = List.Empty }) else Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/NestedStatements.fs b/src/FSharpLint.Core/Rules/Conventions/NestedStatements.fs index 48a791b7e..eaf8f33f2 100644 --- a/src/FSharpLint.Core/Rules/Conventions/NestedStatements.fs +++ b/src/FSharpLint.Core/Rules/Conventions/NestedStatements.fs @@ -116,12 +116,7 @@ let runner (config:Config) (args:AstNodeRuleParams) = getRange node |> Option.map (fun range -> - { - Range = range - Message = error config.Depth - SuggestedFix = None - TypeChecks = List.Empty - }) + { Range = range; Message = error config.Depth; Fix = None; TypeChecks = List.Empty }) |> Option.toArray else depth <- depth + 1 diff --git a/src/FSharpLint.Core/Rules/Conventions/NoPartialFunctions.fs b/src/FSharpLint.Core/Rules/Conventions/NoPartialFunctions.fs index 999a90340..2823552a0 100644 --- a/src/FSharpLint.Core/Rules/Conventions/NoPartialFunctions.fs +++ b/src/FSharpLint.Core/Rules/Conventions/NoPartialFunctions.fs @@ -92,7 +92,7 @@ let private checkIfPartialIdentifier (config:Config) (identifier:string) (range: Some { Range = range Message = String.Format(Resources.GetString ("RulesConventionsNoPartialFunctionsAdditionalError"), identifier) - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else @@ -103,14 +103,14 @@ let private checkIfPartialIdentifier (config:Config) (identifier:string) (range: { Range = range Message = String.Format(Resources.GetString ("RulesConventionsNoPartialFunctionsPatternMatchError"), identifier) - SuggestedFix = None + Fix = None TypeChecks = List.Empty } | Function replacementFunction -> { Range = range Message = String.Format(Resources.GetString "RulesConventionsNoPartialFunctionsReplacementError", replacementFunction, identifier) - SuggestedFix = Some (lazy ( Some { FromText = identifier; FromRange = range; ToText = replacementFunction })) + Fix = Some (lazy ( Some { FromRange = range; ToText = replacementFunction })) TypeChecks = List.Empty }) @@ -292,41 +292,16 @@ let private isNonStaticInstanceMemberCall (checkFile:FSharpCheckFileResults) nam if typeMatches then match replacementStrategy with - | PatternMatch -> - Some - { - Range = range - Message = - String.Format( - Resources.GetString - "RulesConventionsNoPartialFunctionsPatternMatchError", - fullyQualifiedInstanceMember - ) - SuggestedFix = None - TypeChecks = (fun () -> typeMatches) |> List.singleton - } - | Function replacementFunctionName -> - Some - { - Range = range - Message = - String.Format( - Resources.GetString "RulesConventionsNoPartialFunctionsReplacementError", - replacementFunctionName, - fullyQualifiedInstanceMember - ) - SuggestedFix = - Some( - lazy - (Some - { - FromText = (String.concat "." names) - FromRange = range - ToText = replacementFunctionName - }) - ) - TypeChecks = (fun () -> typeMatches) |> List.singleton - } + | PatternMatch -> + Some { Range = range + Message = String.Format(Resources.GetString "RulesConventionsNoPartialFunctionsPatternMatchError", fullyQualifiedInstanceMember) + Fix = None + TypeChecks = (fun () -> typeMatches) |> List.singleton } + | Function replacementFunctionName -> + Some { Range = range + Message = String.Format(Resources.GetString "RulesConventionsNoPartialFunctionsReplacementError", replacementFunctionName, fullyQualifiedInstanceMember) + Fix = Some (lazy ( Some { FromRange = range; ToText = replacementFunctionName })) + TypeChecks = (fun () -> typeMatches) |> List.singleton } else None | _ -> None @@ -358,41 +333,15 @@ let private checkMemberCallOnExpression if matchesType then match replacementStrategy with | PatternMatch -> - Some - { - Range = originalRange - Message = - String.Format( - Resources.GetString "RulesConventionsNoPartialFunctionsPatternMatchError", - fullyQualifiedInstanceMember - ) - SuggestedFix = None - TypeChecks = (fun () -> true) |> List.singleton - } + Some { Range = originalRange + Message = String.Format(Resources.GetString "RulesConventionsNoPartialFunctionsPatternMatchError", fullyQualifiedInstanceMember) + Fix = None + TypeChecks = (fun () -> true) |> List.singleton } | Function replacementFunctionName -> - Some - { - Range = originalRange - Message = - String.Format( - Resources.GetString "RulesConventionsNoPartialFunctionsReplacementError", - replacementFunctionName, - fullyQualifiedInstanceMember - ) - SuggestedFix = - Some( - lazy - (Some - { - FromText = - (ExpressionUtilities.tryFindTextOfRange originalRange flieContent) - .Value - FromRange = originalRange - ToText = replacementFunctionName - }) - ) - TypeChecks = (fun () -> true) |> List.singleton - } + Some { Range = originalRange + Message = String.Format(Resources.GetString "RulesConventionsNoPartialFunctionsReplacementError", replacementFunctionName, fullyQualifiedInstanceMember) + Fix = Some (lazy ( Some { FromRange = originalRange; ToText = replacementFunctionName })) + TypeChecks = (fun () -> true) |> List.singleton } else None diff --git a/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfBooleanOperatorsInCondition.fs b/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfBooleanOperatorsInCondition.fs index fba0c3c51..ba024a24a 100644 --- a/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfBooleanOperatorsInCondition.fs +++ b/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfBooleanOperatorsInCondition.fs @@ -40,12 +40,7 @@ let private validateCondition (maxBooleanOperators:int) condition = let errorFormatString = Resources.GetString("RulesNumberOfItemsBooleanConditionsError") let error = String.Format(errorFormatString, maxBooleanOperators) Array.singleton - { - Range = condition.Range - Message = error - SuggestedFix = None - TypeChecks = List.Empty - } + { Range = condition.Range; Message = error; Fix = None; TypeChecks = List.Empty } else Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfFunctionParameters.fs b/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfFunctionParameters.fs index 36d792651..9f911e215 100644 --- a/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfFunctionParameters.fs +++ b/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfFunctionParameters.fs @@ -14,12 +14,7 @@ let private validateFunction (maxParameters:int) (constructorArguments:SynArgPat let errorFormatString = Resources.GetString("RulesNumberOfItemsFunctionError") let error = String.Format(errorFormatString, maxParameters) Array.singleton - { - Range = parameters.[maxParameters].Range - Message = error - SuggestedFix = None - TypeChecks = List.Empty - } + { Range = parameters.[maxParameters].Range; Message = error; Fix = None; TypeChecks = List.Empty } | _ -> Array.empty let private runner (config:Helper.NumberOfItems.Config) (args:AstNodeRuleParams) = diff --git a/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfItemsInTuple.fs b/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfItemsInTuple.fs index 39208d1fc..0e32af11e 100644 --- a/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfItemsInTuple.fs +++ b/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfItemsInTuple.fs @@ -25,12 +25,7 @@ let private validateTuple (maxItems:int) (items:SynExpr list) = let errorFormatString = Resources.GetString("RulesNumberOfItemsTupleError") let error = String.Format(errorFormatString, maxItems) Array.singleton - { - Range = items.[maxItems].Range - Message = error - SuggestedFix = None - TypeChecks = List.Empty - } + { Range = items.[maxItems].Range; Message = error; Fix = None; TypeChecks = List.Empty } else Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfMembers.fs b/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfMembers.fs index 8f855e53d..7072eebe4 100644 --- a/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfMembers.fs +++ b/src/FSharpLint.Core/Rules/Conventions/NumberOfItems/MaxNumberOfMembers.fs @@ -31,12 +31,7 @@ let private validateType (maxMembers:int) members typeRepresentation = let errorFormatString = Resources.GetString("RulesNumberOfItemsClassMembersError") let error = String.Format(errorFormatString, maxMembers) Array.singleton - { - Range = members.[maxMembers].Range - Message = error - SuggestedFix = None - TypeChecks = List.Empty - } + { Range = members.[maxMembers].Range; Message = error; Fix = None; TypeChecks = List.Empty } else Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/FailwithBadUsage.fs b/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/FailwithBadUsage.fs index 619a6cd4a..6fd9d4ef1 100644 --- a/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/FailwithBadUsage.fs +++ b/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/FailwithBadUsage.fs @@ -31,14 +31,13 @@ let private runner (args: AstNodeRuleParams) = (badUsageType: BadUsageType) (exceptionParam: Option) = - let suggestedFix = + let fix = match exceptionParam with | Some param -> Some( lazy (Some - { FromText = $"%s{failwithKeyword} %s{failwithErrorMessage}" - FromRange = range + { FromRange = range ToText = $"raise <| Exception(\"%s{failwithErrorMessage}\", %s{param})" }) ) | _ -> None @@ -53,12 +52,10 @@ let private runner (args: AstNodeRuleParams) = let error = Array.singleton - { - Range = range - Message = String.Format(Resources.GetString "RulesFailwithBadUsage", message) - SuggestedFix = suggestedFix - TypeChecks = List.Empty - } + { Range = range + Message = String.Format(Resources.GetString "RulesFailwithBadUsage", message) + Fix = fix + TypeChecks = List.Empty } error diff --git a/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/FailwithfWithArgumentsMatchingFormatString.fs b/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/FailwithfWithArgumentsMatchingFormatString.fs index 33a104cd1..26c591122 100644 --- a/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/FailwithfWithArgumentsMatchingFormatString.fs +++ b/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/FailwithfWithArgumentsMatchingFormatString.fs @@ -20,7 +20,7 @@ let private runner (args:AstNodeRuleParams) = { Range = range Message = Resources.GetString "FailwithfWithArgumentsMatchingFormatString" - SuggestedFix = None + Fix = None TypeChecks = List.Empty } | _ -> Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/RaiseWithTooManyArgumentsHelper.fs b/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/RaiseWithTooManyArgumentsHelper.fs index 668de639e..eb68a30de 100644 --- a/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/RaiseWithTooManyArgumentsHelper.fs +++ b/src/FSharpLint.Core/Rules/Conventions/RaiseWithTooManyArguments/RaiseWithTooManyArgumentsHelper.fs @@ -23,7 +23,7 @@ let checkRaiseWithTooManyArgs (raiseType:string) (count:int) (ruleName:string) ( { Range = range Message = Resources.GetString ruleName - SuggestedFix = None + Fix = None TypeChecks = List.Empty } | _ -> Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/RecursiveAsyncFunction.fs b/src/FSharpLint.Core/Rules/Conventions/RecursiveAsyncFunction.fs index 834ba4ac0..989303835 100644 --- a/src/FSharpLint.Core/Rules/Conventions/RecursiveAsyncFunction.fs +++ b/src/FSharpLint.Core/Rules/Conventions/RecursiveAsyncFunction.fs @@ -33,12 +33,11 @@ let checkRecursiveAsyncFunction (args:AstNodeRuleParams) (range:Range) (doBangEx let doTokenRange = Range.mkRange "do!" (Position.mkPos range.StartLine range.StartColumn) (Position.mkPos range.StartLine (range.StartColumn + 3)) let suggestFix () = - let suggestedFix = + let fix = lazy (ExpressionUtilities.tryFindTextOfRange doTokenRange args.FileContent |> Option.map (fun fromText -> { - FromText = fromText FromRange = doTokenRange ToText = "return!" })) @@ -47,7 +46,7 @@ let checkRecursiveAsyncFunction (args:AstNodeRuleParams) (range:Range) (doBangEx { Range = range Message = Resources.GetString("RulesConventionsRecursiveAsyncFunctionError") - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } diff --git a/src/FSharpLint.Core/Rules/Conventions/RedundantNewKeyword.fs b/src/FSharpLint.Core/Rules/Conventions/RedundantNewKeyword.fs index 4ab45e080..badc46537 100644 --- a/src/FSharpLint.Core/Rules/Conventions/RedundantNewKeyword.fs +++ b/src/FSharpLint.Core/Rules/Conventions/RedundantNewKeyword.fs @@ -40,7 +40,7 @@ let private generateFix (text:string) range = lazy( |> Option.map (fun fromText -> let withoutLeadingWhitespace = fromText.TrimStart() let newKeywordRemoved = withoutLeadingWhitespace.Substring(3).TrimStart() - { FromText = fromText; FromRange = range; ToText = newKeywordRemoved })) + { FromRange = range; ToText = newKeywordRemoved })) let runner args = @@ -48,15 +48,10 @@ let runner args = | AstNode.Expression(SynExpr.New(_, SynType.LongIdent(identifier), _, range)), Some checkInfo | AstNode.Expression(SynExpr.New(_, SynType.App(SynType.LongIdent(identifier), _, _, _, _, _, _), _, range)), Some checkInfo -> Array.singleton - { - Range = range - Message = Resources.GetString("RulesRedundantNewKeyword") - SuggestedFix = Some(generateFix args.FileContent range) - TypeChecks = - [ - fun () -> doesNotImplementIDisposable checkInfo identifier - ] - } + { Range = range + Message = Resources.GetString("RulesRedundantNewKeyword") + Fix = Some (generateFix args.FileContent range) + TypeChecks = [ fun () -> doesNotImplementIDisposable checkInfo identifier ] } | _ -> Array.empty let rule = diff --git a/src/FSharpLint.Core/Rules/Conventions/SourceLength/SourceLengthHelper.fs b/src/FSharpLint.Core/Rules/Conventions/SourceLength/SourceLengthHelper.fs index bfa26d6eb..abf881bdc 100644 --- a/src/FSharpLint.Core/Rules/Conventions/SourceLength/SourceLengthHelper.fs +++ b/src/FSharpLint.Core/Rules/Conventions/SourceLength/SourceLengthHelper.fs @@ -74,12 +74,10 @@ let checkSourceLengthRule (config:Config) range fileContents errorName = let skipResult = sourceCodeLines.Length - commentLinesCount - blankLinesCount if skipResult > config.MaxLines then Array.singleton - { - Range = range - Message = error errorName config.MaxLines skipResult - SuggestedFix = None - TypeChecks = List.Empty - } + { Range = range + Message = error errorName config.MaxLines skipResult + Fix = None + TypeChecks = List.Empty } else Array.empty | None -> Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/SuggestUseAutoProperty.fs b/src/FSharpLint.Core/Rules/Conventions/SuggestUseAutoProperty.fs index f98b6ce5c..3ba57edde 100644 --- a/src/FSharpLint.Core/Rules/Conventions/SuggestUseAutoProperty.fs +++ b/src/FSharpLint.Core/Rules/Conventions/SuggestUseAutoProperty.fs @@ -109,20 +109,19 @@ let private runner (args: AstNodeRuleParams) = | parentNode :: _ when hasStructAttribute parentNode -> Array.empty | _ -> - let suggestedFix = + let fix = lazy (match memberIdentifier.LongIdent with | [ _; memberName ] -> Some - { FromText = args.FileContent - FromRange = memberIdentifier.Range + { FromRange = memberIdentifier.Range ToText = $"val {memberName.idText}" } | _ -> None) Array.singleton { Range = memberRange Message = Resources.GetString "RulesSuggestUseAutoProperty" - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } | _ -> Array.empty | _ -> Array.empty diff --git a/src/FSharpLint.Core/Rules/Conventions/UnneededRecKeyword.fs b/src/FSharpLint.Core/Rules/Conventions/UnneededRecKeyword.fs index 38a65f7f6..87bbf9671 100644 --- a/src/FSharpLint.Core/Rules/Conventions/UnneededRecKeyword.fs +++ b/src/FSharpLint.Core/Rules/Conventions/UnneededRecKeyword.fs @@ -52,7 +52,7 @@ let private emitWarning (func: RecursiveFunctionInfo) = Resources.GetString "RulesUnneededRecKeyword", func.Identifier.idText ) - SuggestedFix = None + Fix = None TypeChecks = list.Empty } let runner (args: AstNodeRuleParams) = diff --git a/src/FSharpLint.Core/Rules/Conventions/UsedUnderscorePrefixedElements.fs b/src/FSharpLint.Core/Rules/Conventions/UsedUnderscorePrefixedElements.fs index 513db8f9a..49b68bf13 100644 --- a/src/FSharpLint.Core/Rules/Conventions/UsedUnderscorePrefixedElements.fs +++ b/src/FSharpLint.Core/Rules/Conventions/UsedUnderscorePrefixedElements.fs @@ -25,7 +25,7 @@ let runner (args: AstNodeRuleParams) = Some { Range = usage.Range Message = String.Format(Resources.GetString ("RulesUsedUnderscorePrefixedElements")) - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClauseIndentation.fs b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClauseIndentation.fs index 1e921c4ce..b9884dc42 100644 --- a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClauseIndentation.fs +++ b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClauseIndentation.fs @@ -24,7 +24,7 @@ let check (config:Config) (args:AstNodeRuleParams) matchExprRange (clauses:SynMa { Range = firstClause.Range Message = Resources.GetString("RulesFormattingLambdaPatternMatchClauseIndentationError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else @@ -34,7 +34,7 @@ let check (config:Config) (args:AstNodeRuleParams) matchExprRange (clauses:SynMa { Range = firstClause.Range Message = Resources.GetString("RulesFormattingPatternMatchClauseIndentationError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else @@ -54,7 +54,7 @@ let check (config:Config) (args:AstNodeRuleParams) matchExprRange (clauses:SynMa { Range = clauseTwo.Range Message = Resources.GetString("RulesFormattingPatternMatchClauseSameIndentationError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClausesOnNewLine.fs b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClausesOnNewLine.fs index 770b55521..3da6af938 100644 --- a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClausesOnNewLine.fs +++ b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchClausesOnNewLine.fs @@ -12,12 +12,10 @@ let check args _ (clauses:SynMatchClause list) _ = let choose (clauseOne: SynMatchClause) (clauseTwo: SynMatchClause) = if clauseOne.Range.EndLine = clauseTwo.Range.StartLine then Some - { - Range = clauseTwo.Range - Message = Resources.GetString("RulesFormattingPatternMatchClausesOnNewLineError") - SuggestedFix = None - TypeChecks = List.Empty - } + { Range = clauseTwo.Range + Message = Resources.GetString("RulesFormattingPatternMatchClausesOnNewLineError") + Fix = None + TypeChecks = List.Empty } else None diff --git a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchExpressionIndentation.fs b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchExpressionIndentation.fs index b398fbd45..d23767eab 100644 --- a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchExpressionIndentation.fs +++ b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchExpressionIndentation.fs @@ -19,12 +19,10 @@ let check (args:AstNodeRuleParams) _ (clauses:SynMatchClause list) _ = |> Option.defaultValue pat.Range.EndLine if expr.Range.StartLine <> matchPatternEndLine && exprIndentation <> clauseIndentation + args.GlobalConfig.numIndentationSpaces then Some - { - Range = expr.Range - Message = Resources.GetString("RulesFormattingMatchExpressionIndentationError") - SuggestedFix = None - TypeChecks = List.Empty - } + { Range = expr.Range + Message = Resources.GetString("RulesFormattingMatchExpressionIndentationError") + Fix = None + TypeChecks = List.Empty } else None diff --git a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchOrClausesOnNewLine.fs b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchOrClausesOnNewLine.fs index d40a08cc9..c5e11ed75 100644 --- a/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchOrClausesOnNewLine.fs +++ b/src/FSharpLint.Core/Rules/Formatting/PatternMatchFormatting/PatternMatchOrClausesOnNewLine.fs @@ -15,7 +15,7 @@ let check args _ (clauses:SynMatchClause list) _ = { Range = clauseTwo.Range Message = Resources.GetString("RulesFormattingPatternMatchOrClausesOnNewLineError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Formatting/Spacing/ClassMemberSpacing.fs b/src/FSharpLint.Core/Rules/Formatting/Spacing/ClassMemberSpacing.fs index 71d7110ca..a572988e7 100644 --- a/src/FSharpLint.Core/Rules/Formatting/Spacing/ClassMemberSpacing.fs +++ b/src/FSharpLint.Core/Rules/Formatting/Spacing/ClassMemberSpacing.fs @@ -27,12 +27,10 @@ let checkClassMemberSpacing (args:AstNodeRuleParams) (members:SynMemberDefns) = (Position.mkPos (memberTwo.Range.StartLine + endOffset) 0) Some - { - Range = intermediateRange - Message = Resources.GetString("RulesFormattingClassMemberSpacingError") - SuggestedFix = None - TypeChecks = List.Empty - } + { Range = intermediateRange + Message = Resources.GetString("RulesFormattingClassMemberSpacingError") + Fix = None + TypeChecks = List.Empty } else None diff --git a/src/FSharpLint.Core/Rules/Formatting/Spacing/ModuleDeclSpacing.fs b/src/FSharpLint.Core/Rules/Formatting/Spacing/ModuleDeclSpacing.fs index 08a140e6a..889396f3e 100644 --- a/src/FSharpLint.Core/Rules/Formatting/Spacing/ModuleDeclSpacing.fs +++ b/src/FSharpLint.Core/Rules/Formatting/Spacing/ModuleDeclSpacing.fs @@ -27,7 +27,7 @@ let checkModuleDeclSpacing (args:AstNodeRuleParams) synModuleOrNamespace = { Range = intermediateRange Message = Resources.GetString("RulesFormattingModuleDeclSpacingError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleCommaSpacing.fs b/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleCommaSpacing.fs index beda74140..a1c2964ba 100644 --- a/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleCommaSpacing.fs +++ b/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleCommaSpacing.fs @@ -19,10 +19,9 @@ let checkTupleCommaSpacing (args:AstNodeRuleParams) (tupleExprs:SynExpr list) tu (Some { FromRange = commaRange - FromText = commaText ToText = ", " }) - let suggestedFix = + let fix = ExpressionUtilities.tryFindTextOfRange commaRange args.FileContent |> Option.map map @@ -30,7 +29,7 @@ let checkTupleCommaSpacing (args:AstNodeRuleParams) (tupleExprs:SynExpr list) tu { Range = commaRange Message = Resources.GetString("RulesFormattingTupleCommaSpacingError") - SuggestedFix = suggestedFix + Fix = fix TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleIndentation.fs b/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleIndentation.fs index d90b024b1..d0b837234 100644 --- a/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleIndentation.fs +++ b/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleIndentation.fs @@ -18,7 +18,7 @@ let checkTupleIndentation _ (tupleExprs:SynExpr list) _ _ = { Range = Range.mkRange "" expr.Range.Start nextExpr.Range.End Message = Resources.GetString("RulesFormattingTupleIndentationError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleParentheses.fs b/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleParentheses.fs index d388940b5..9cd4622ee 100644 --- a/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleParentheses.fs +++ b/src/FSharpLint.Core/Rules/Formatting/TupleFormatting/TupleParentheses.fs @@ -10,19 +10,18 @@ open FSharpLint.Rules.Helper let checkTupleHasParentheses (args:AstNodeRuleParams) _ range parentNode = let processText text = - let suggestedFix = + let fix = lazy (Some { FromRange = range - FromText = text ToText = $"({text})" }) { Range = range Message = Resources.GetString("RulesFormattingTupleParenthesesError") - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } diff --git a/src/FSharpLint.Core/Rules/Formatting/TypePrefixing.fs b/src/FSharpLint.Core/Rules/Formatting/TypePrefixing.fs index 01b51ad1a..9830ff44c 100644 --- a/src/FSharpLint.Core/Rules/Formatting/TypePrefixing.fs +++ b/src/FSharpLint.Core/Rules/Formatting/TypePrefixing.fs @@ -31,14 +31,14 @@ let checkTypePrefixing (typePrefixingConfig: CheckTypePrefixingConfig) = match typePrefixingConfig.TypeName with | SynType.LongIdent lid -> let prefixSuggestion typeName = - let suggestedFix = lazy( + let fix = lazy( (ExpressionUtilities.tryFindTextOfRange typePrefixingConfig.Range typePrefixingConfig.Args.FileContent, typePrefixingConfig.TypeArgs) - ||> Option.map2 (fun fromText typeArgs -> { FromText = fromText; FromRange = typePrefixingConfig.Range; ToText = $"{typeName}<{typeArgs}>" })) + ||> Option.map2 (fun fromText typeArgs -> { FromRange = typePrefixingConfig.Range; ToText = $"{typeName}<{typeArgs}>" })) Some { Range = typePrefixingConfig.Range Message = Resources.GetString("RulesFormattingGenericPrefixError") - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } @@ -53,14 +53,14 @@ let checkTypePrefixing (typePrefixingConfig: CheckTypePrefixingConfig) = // Prefer postfix. if not typePrefixingConfig.IsPostfix && typePrefixingConfig.Config.Mode <> Mode.Always then - let suggestedFix = lazy( + let fix = lazy( (ExpressionUtilities.tryFindTextOfRange typePrefixingConfig.Range typePrefixingConfig.Args.FileContent, typePrefixingConfig.TypeArgs) - ||> Option.map2 (fun fromText typeArgs -> { FromText = fromText; FromRange = typePrefixingConfig.Range; ToText = $"{typeArgs} {typeName}" })) + ||> Option.map2 (fun fromText typeArgs -> { FromRange = typePrefixingConfig.Range; ToText = $"{typeArgs} {typeName}" })) Some { Range = typePrefixingConfig.Range Message = String.Format(recommendPostfixErrMsg.Value, typeName) - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } else @@ -71,14 +71,14 @@ let checkTypePrefixing (typePrefixingConfig: CheckTypePrefixingConfig) = | "array" when typePrefixingConfig.Config.Mode <> Mode.Always -> // Prefer special postfix (e.g. int []). - let suggestedFix = lazy( + let fix = lazy( (ExpressionUtilities.tryFindTextOfRange typePrefixingConfig.Range typePrefixingConfig.Args.FileContent, typePrefixingConfig.TypeArgs) - ||> Option.map2 (fun fromText typeArgs -> { FromText = fromText; FromRange = typePrefixingConfig.Range; ToText = $"{typeArgs} []" })) + ||> Option.map2 (fun fromText typeArgs -> { FromRange = typePrefixingConfig.Range; ToText = $"{typeArgs} []" })) Some { Range = typePrefixingConfig.Range Message = Resources.GetString("RulesFormattingF#ArrayPostfixError") - SuggestedFix = Some suggestedFix + Fix = Some fix TypeChecks = List.Empty } @@ -94,7 +94,7 @@ let checkTypePrefixing (typePrefixingConfig: CheckTypePrefixingConfig) = Range = typePrefixingConfig.Range Message = String.Format(recommendPostfixErrMsg.Value, typeName) // TODO - SuggestedFix = None + Fix = None TypeChecks = List.Empty } | false, _ -> @@ -120,7 +120,7 @@ let runner (config:Config) args = Array.singleton { Range = range Message = Resources.GetString("RulesFormattingF#ArrayPrefixError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } | _ -> Array.empty diff --git a/src/FSharpLint.Core/Rules/Formatting/TypedItemSpacing.fs b/src/FSharpLint.Core/Rules/Formatting/TypedItemSpacing.fs index 683e436a9..6a5f90e46 100644 --- a/src/FSharpLint.Core/Rules/Formatting/TypedItemSpacing.fs +++ b/src/FSharpLint.Core/Rules/Formatting/TypedItemSpacing.fs @@ -54,19 +54,16 @@ let private checkRange (config:Config) (args:AstNodeRuleParams) (range:Range) = let trimmedTypeText = typeText.TrimStart(' ') let spacesBeforeString = " " |> String.replicate expectedSpacesBefore let spacesAfterString = " " |> String.replicate expectedSpacesAfter - let suggestedFix = lazy( + let fix = lazy( Some { FromRange = range; - FromText = text; ToText = $"{trimmedOtherText}{spacesBeforeString}:{spacesAfterString}{trimmedTypeText}" } ) let errorFormatString = Resources.GetString("RulesFormattingTypedItemSpacingError") Some - { - Range = range - Message = String.Format(errorFormatString, expectedSpacesBefore, expectedSpacesAfter) - SuggestedFix = Some suggestedFix - TypeChecks = List.Empty - } + { Range = range + Message = String.Format(errorFormatString, expectedSpacesBefore, expectedSpacesAfter) + Fix = Some fix + TypeChecks = List.Empty } else None | _ -> None diff --git a/src/FSharpLint.Core/Rules/Formatting/UnionDefinitionIndentation.fs b/src/FSharpLint.Core/Rules/Formatting/UnionDefinitionIndentation.fs index 5a4aa75bd..2c470f77d 100644 --- a/src/FSharpLint.Core/Rules/Formatting/UnionDefinitionIndentation.fs +++ b/src/FSharpLint.Core/Rules/Formatting/UnionDefinitionIndentation.fs @@ -28,7 +28,7 @@ let checkUnionDefinitionIndentation (args:AstNodeRuleParams) typeDefnRepr typeDe { Range = firstCase.Range Message = Resources.GetString("RulesFormattingUnionDefinitionIndentationError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else @@ -41,7 +41,7 @@ let checkUnionDefinitionIndentation (args:AstNodeRuleParams) typeDefnRepr typeDe { Range = caseTwo.Range Message = Resources.GetString("RulesFormattingUnionDefinitionSameIndentationError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Hints/HintMatcher.fs b/src/FSharpLint.Core/Rules/Hints/HintMatcher.fs index 24030523b..6395b4de9 100644 --- a/src/FSharpLint.Core/Rules/Hints/HintMatcher.fs +++ b/src/FSharpLint.Core/Rules/Hints/HintMatcher.fs @@ -686,15 +686,15 @@ let private hintError (config: HintErrorConfig) = HintNode = (HintExpr expr) } - let suggestedFix = lazy( + let fix = lazy( ExpressionUtilities.tryFindTextOfRange config.Range config.Args.FileContent - |> Option.map (fun fromText -> { FromText = fromText; FromRange = config.Range; ToText = toText })) + |> Option.map (fun fromText -> { FromRange = config.Range; ToText = toText })) - { Range = config.Range; Message = error; SuggestedFix = Some suggestedFix; TypeChecks = config.TypeChecks } + { Range = config.Range; Message = error; Fix = Some fix; TypeChecks = config.TypeChecks } | Suggestion.Message(message) -> let errorFormatString = Resources.GetString("RulesHintSuggestion") let error = System.String.Format(errorFormatString, matched, message) - { Range = config.Range; Message = error; SuggestedFix = None; TypeChecks = config.TypeChecks } + { Range = config.Range; Message = error; Fix = None; TypeChecks = config.TypeChecks } let private getMethodParameters (checkFile:FSharpCheckFileResults) (methodIdent: SynLongIdent) = let symbol = diff --git a/src/FSharpLint.Core/Rules/Typography/Indentation.fs b/src/FSharpLint.Core/Rules/Typography/Indentation.fs index a9d9372bf..4590bce3d 100644 --- a/src/FSharpLint.Core/Rules/Typography/Indentation.fs +++ b/src/FSharpLint.Core/Rules/Typography/Indentation.fs @@ -150,7 +150,7 @@ let checkIndentation (expectedSpaces:int) (line:string) (lineNumber:int) (indent { Range = range Message = errorString - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else @@ -163,7 +163,7 @@ let checkIndentation (expectedSpaces:int) (line:string) (lineNumber:int) (indent { Range = range Message = String.Format(errorFormatString, expectedSpaces) - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else @@ -174,7 +174,7 @@ let checkIndentation (expectedSpaces:int) (line:string) (lineNumber:int) (indent { Range = range Message = String.Format(errorFormatString, expectedSpaces) - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Typography/MaxCharactersOnLine.fs b/src/FSharpLint.Core/Rules/Typography/MaxCharactersOnLine.fs index 27dc5202d..be3d7ede0 100644 --- a/src/FSharpLint.Core/Rules/Typography/MaxCharactersOnLine.fs +++ b/src/FSharpLint.Core/Rules/Typography/MaxCharactersOnLine.fs @@ -19,7 +19,7 @@ let checkMaxCharactersOnLine (config:Config) (args:LineRuleParams) = { Range = range Message = String.Format(errorFormatString, (maxCharacters + 1)) - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Typography/MaxLinesInFile.fs b/src/FSharpLint.Core/Rules/Typography/MaxLinesInFile.fs index daafcdf0b..cebc7ec7d 100644 --- a/src/FSharpLint.Core/Rules/Typography/MaxLinesInFile.fs +++ b/src/FSharpLint.Core/Rules/Typography/MaxLinesInFile.fs @@ -17,7 +17,7 @@ let private checkNumberOfLinesInFile numberOfLines line maxLines = Range = Range.mkRange "" (Position.mkPos (maxLines + 1) 0) (Position.mkPos numberOfLines (String.length line)) Message = String.Format(errorFormatString, (maxLines + 1)) - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Typography/NoTabCharacters.fs b/src/FSharpLint.Core/Rules/Typography/NoTabCharacters.fs index 4fa34d427..949843a9e 100644 --- a/src/FSharpLint.Core/Rules/Typography/NoTabCharacters.fs +++ b/src/FSharpLint.Core/Rules/Typography/NoTabCharacters.fs @@ -29,12 +29,11 @@ let checkNoTabCharacters literalStrings (args:LineRuleParams) = Array.singleton { Range = range Message = Resources.GetString("RulesTypographyTabCharacterError") - SuggestedFix = + Fix = Some( lazy (Some( { FromRange = range - FromText = "\t" ToText = String.replicate args.GlobalConfig.numIndentationSpaces " " } )) ) diff --git a/src/FSharpLint.Core/Rules/Typography/TrailingNewLineInFile.fs b/src/FSharpLint.Core/Rules/Typography/TrailingNewLineInFile.fs index c66207aeb..650d52531 100644 --- a/src/FSharpLint.Core/Rules/Typography/TrailingNewLineInFile.fs +++ b/src/FSharpLint.Core/Rules/Typography/TrailingNewLineInFile.fs @@ -13,7 +13,7 @@ let checkTrailingNewLineInFile (args:LineRuleParams) = { Range = Range.mkRange "" pos pos Message = Resources.GetString("RulesTypographyTrailingLineError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/Typography/TrailingWhitespaceOnLine.fs b/src/FSharpLint.Core/Rules/Typography/TrailingWhitespaceOnLine.fs index ea01f8224..6ce779866 100644 --- a/src/FSharpLint.Core/Rules/Typography/TrailingWhitespaceOnLine.fs +++ b/src/FSharpLint.Core/Rules/Typography/TrailingWhitespaceOnLine.fs @@ -51,7 +51,7 @@ let checkTrailingWhitespaceOnLine (config:Config) (args:LineRuleParams) = { Range = range Message = Resources.GetString("RulesTypographyTrailingWhitespaceError") - SuggestedFix = None + Fix = None TypeChecks = List.Empty } else diff --git a/src/FSharpLint.Core/Rules/XmlDocumentation.fs b/src/FSharpLint.Core/Rules/XmlDocumentation.fs index 92f54b705..4f62a1beb 100644 --- a/src/FSharpLint.Core/Rules/XmlDocumentation.fs +++ b/src/FSharpLint.Core/Rules/XmlDocumentation.fs @@ -108,7 +108,7 @@ module XmlDocumentation = configExceptionHeader analyserInfo.Config ruleName && isNotSuppressed ruleName i let suggest range message = - args.Info.Suggest { Range = range; Message = message; SuggestedFix = None; TypeChecks = [] } + args.Info.Suggest { Range = range; Message = message; Fix = None; TypeChecks = [] } for i = 0 to syntaxArray.Length - 1 do match syntaxArray.[i].Actual with diff --git a/src/FSharpLint.Core/Text.resx b/src/FSharpLint.Core/Text.resx index 17681b968..2cde0282a 100644 --- a/src/FSharpLint.Core/Text.resx +++ b/src/FSharpLint.Core/Text.resx @@ -138,6 +138,9 @@ ========== Linting {0} ========== + + ========== Applying fixes to {0} ========== + MSBuild could not load the project file {0} because: {1} diff --git a/tests/FSharpLint.Console.Tests/TestApp.fs b/tests/FSharpLint.Console.Tests/TestApp.fs index e200f9c2b..613690e1c 100644 --- a/tests/FSharpLint.Console.Tests/TestApp.fs +++ b/tests/FSharpLint.Console.Tests/TestApp.fs @@ -3,6 +3,7 @@ module FSharpLint.Console.Tests.TestApp open System open System.IO open NUnit.Framework +open FSharpLint.Console.Program let getErrorsFromOutput (output:string) = let splitOutput = output.Split([|Environment.NewLine|], StringSplitOptions.None) @@ -44,7 +45,7 @@ type TestConsoleApplication() = let (returnCode, errors) = main [| "lint"; input.FileName |] - Assert.AreEqual(-1, returnCode) + Assert.AreEqual(int ExitCode.Error, returnCode) Assert.AreEqual(set ["Consider changing `Signature` to be prefixed with `I`."], errors) [] @@ -57,7 +58,7 @@ type TestConsoleApplication() = let (returnCode, errors) = main [| "lint"; input |] - Assert.AreEqual(-1, returnCode) + Assert.AreEqual(int ExitCode.Error, returnCode) Assert.AreEqual(set ["Consider changing `Signature` to be prefixed with `I`."], errors) [] @@ -79,9 +80,9 @@ type TestConsoleApplication() = let (returnCode, errors) = main [| "lint"; "--lint-config"; config.FileName; input |] - Assert.AreEqual(0, returnCode) + Assert.AreEqual(int ExitCode.Success, returnCode) Assert.AreEqual(Set.empty, errors) - + [] member _.``Lint source with error suppressed, no error is given.``() = let input = """ @@ -92,10 +93,72 @@ type TestConsoleApplication() = """ let (returnCode, errors) = main [| "lint"; input |] - - Assert.AreEqual(0, returnCode) + + Assert.AreEqual(int ExitCode.Success, returnCode) Assert.AreEqual(Set.empty, errors) + [] + member __.``Lint source with fix option``() = + let sourceCode = """ +module Fass = + let foo = new System.Collections.Generic.Dictionary() |> ignore + let goo = new Guid() |> ignore + let ntoo = new Int32() |> ignore +module Fall = + let uoo = new Uid() |> ignore + let version = new System.Version() + let xoo = new Uint32() |> ignore + """ + + let expected = """ +module Fass = + let foo = System.Collections.Generic.Dictionary() |> ignore + let goo = Guid() |> ignore + let ntoo = Int32() |> ignore +module Fall = + let uoo = Uid() |> ignore + let version = System.Version() + let xoo = Uint32() |> ignore + """ + let ruleName = "RedundantNewKeyword" + use input = new TemporaryFile(sourceCode, "fs") + let (exitCode, errors) = main [| "fix"; ruleName; input.FileName |] + + Assert.AreEqual(int ExitCode.Success, exitCode) + Assert.AreEqual(set ["Usage of `new` keyword here is redundant."], errors) + Assert.AreEqual(expected, File.ReadAllText input.FileName) + + [] + member __.``Lint source with fix option with wrong rulename``() = + let sourceCode = """ +printfn "Hello" + """ + + let ruleName = "ssrffss" + use input = new TemporaryFile(sourceCode, "fs") + let (exitCode, errors) = main [| "fix"; ruleName; input.FileName |] + + Assert.AreEqual(int ExitCode.NoSuchRuleName, exitCode) + + [] + member __.``Lint source with fix option no need for fix``() = + let sourceCode = """ +module Fass = + let foo = System.Collections.Generic.Dictionary() |> ignore + let goo = Guid() |> ignore + let ntoo = Int32() |> ignore +module Fall = + let uoo = Uid() |> ignore + let version = System.Version() + let xoo = Uint32() |> ignore + """ + let ruleName = "RedundantNewKeyword" + use input = new TemporaryFile(sourceCode, "fs") + let (exitCode, errors) = main [| "fix"; ruleName; input.FileName |] + + Assert.AreEqual(int ExitCode.NoFix, exitCode) + Assert.AreEqual(sourceCode, File.ReadAllText input.FileName) + [] member _.``Regression test: typePrefixing rule with old config format should still work``() = let fileContent = """ diff --git a/tests/FSharpLint.Core.Tests/Rules/Binding/FavourAsKeyword.fs b/tests/FSharpLint.Core.Tests/Rules/Binding/FavourAsKeyword.fs index 090452849..5f9098dd7 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Binding/FavourAsKeyword.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Binding/FavourAsKeyword.fs @@ -9,7 +9,7 @@ type TestBindingFavourAsKeyword() = inherit TestAstNodeRuleBase.TestAstNodeRuleBase(FavourAsKeyword.rule) [] - member this.FavourAsKeywordShouldQuickFix() = + member this.FavourAsKeywordShouldFix() = let source = """ module Program @@ -26,7 +26,7 @@ match "" with | "baz" as bar -> () """ - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] diff --git a/tests/FSharpLint.Core.Tests/Rules/Binding/FavourIgnoreOverLetWild.fs b/tests/FSharpLint.Core.Tests/Rules/Binding/FavourIgnoreOverLetWild.fs index d15f7897a..afd906501 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Binding/FavourIgnoreOverLetWild.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Binding/FavourIgnoreOverLetWild.fs @@ -51,7 +51,7 @@ let a = List.iter (fun x -> ()) [] Assert.IsFalse(this.ErrorsExist) [] - member this.LetWildcardUnitValueSuggestedFix() = + member this.LetWildcardUnitValueFix() = let source = """ module Program @@ -64,12 +64,12 @@ module Program Assert.IsTrue(this.ErrorExistsAt(4, 4)) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) [] - member this.LetWildCardInParanUnitValueSuggestedFix() = + member this.LetWildCardInParanUnitValueFix() = let source = """ module Program @@ -84,6 +84,6 @@ module Program Assert.IsTrue(this.ErrorExistsAt(4, 4)) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) diff --git a/tests/FSharpLint.Core.Tests/Rules/Binding/TupleOfWildcards.fs b/tests/FSharpLint.Core.Tests/Rules/Binding/TupleOfWildcards.fs index 86236d04e..152628593 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Binding/TupleOfWildcards.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Binding/TupleOfWildcards.fs @@ -33,7 +33,7 @@ match cat with this.Parse source - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) @@ -49,7 +49,7 @@ match maybeCat with this.Parse source - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) diff --git a/tests/FSharpLint.Core.Tests/Rules/Binding/UselessBinding.fs b/tests/FSharpLint.Core.Tests/Rules/Binding/UselessBinding.fs index 483b4a467..0ebd7163a 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Binding/UselessBinding.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Binding/UselessBinding.fs @@ -68,7 +68,7 @@ type Cat() = Assert.IsFalse(this.ErrorsExist) [] - member this.UselessBindingSuggestedFix() = + member this.UselessBindingFix() = let source = """ module Program @@ -84,12 +84,12 @@ let a = 10 Assert.IsTrue(this.ErrorExistsAt(5, 4)) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) [] - member this.UselessBindingWithParensSuggestedFix() = + member this.UselessBindingWithParensFix() = let source = """ module Program @@ -106,6 +106,6 @@ let a = 10 Assert.IsTrue(this.ErrorExistsAt(5, 4)) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) diff --git a/tests/FSharpLint.Core.Tests/Rules/Binding/WildcardNamedWithAsPattern.fs b/tests/FSharpLint.Core.Tests/Rules/Binding/WildcardNamedWithAsPattern.fs index 00fb59985..a4723e681 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Binding/WildcardNamedWithAsPattern.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Binding/WildcardNamedWithAsPattern.fs @@ -28,7 +28,7 @@ match [] with Assert.IsTrue(this.ErrorExistsAt(5, 2)) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/AvoidSinglePipeOperator.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/AvoidSinglePipeOperator.fs index e8fa00a3d..20cf71b9b 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/AvoidSinglePipeOperator.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/AvoidSinglePipeOperator.fs @@ -213,7 +213,7 @@ let someFunc someParam = """ this.Parse source - let fixedSource = this.ApplyQuickFix source + let fixedSource = this.ApplyFix source Assert.AreEqual(expected, fixedSource) diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourConsistentThis.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourConsistentThis.fs index aac7aef3a..a6f8cf907 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourConsistentThis.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourConsistentThis.fs @@ -112,7 +112,7 @@ type TorMessageDigest(isSha256: bool) = Assert.IsTrue this.NoErrorsExist [] - member this.InConsistentSelfShouldProduceErrorSuggestedFix() = + member this.InConsistentSelfShouldProduceErrorFix() = let source = """ type Foo = { Bar : Baz } @@ -133,12 +133,12 @@ type Foo = Assert.IsTrue this.ErrorsExist - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) [] - member this.InConsistentSelfShouldProduceErrorSuggestedFix2() = + member this.InConsistentSelfShouldProduceErrorFix2() = let source = """ type Foo = { Bar : Baz } @@ -160,12 +160,12 @@ type Foo = Assert.IsTrue this.ErrorsExist Assert.IsTrue(this.ErrorExistsAt(6, 11)) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) [] - member this.InConsistentSelfShouldProduceErrorSuggestedFix3() = + member this.InConsistentSelfShouldProduceErrorFix3() = let source = """ type CustomerName(firstName, middleInitial, lastName) = member this.FirstName = firstName @@ -182,6 +182,6 @@ type CustomerName(firstName, middleInitial, lastName) = Assert.IsTrue this.ErrorsExist Assert.IsTrue(this.ErrorExistsAt(4, 11)) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourReRaise.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourReRaise.fs index c323f4921..703504fc8 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourReRaise.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourReRaise.fs @@ -120,6 +120,6 @@ with Assert.IsTrue(this.ErrorsExist) Assert.IsTrue(this.ErrorExistsAt(7, 8)) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourStaticEmptyFields.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourStaticEmptyFields.fs index 2369641c0..6d67e59ee 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourStaticEmptyFields.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/FavourStaticEmptyFields.fs @@ -170,7 +170,7 @@ match foo with Assert.IsTrue this.NoErrorsExist [] - member this.FavourStaticEmptyFieldsSuggestedFixForString() = + member this.FavourStaticEmptyFieldsFixForString() = let source = "let foo = \"\"" let expected = "let foo = String.Empty" @@ -179,12 +179,12 @@ match foo with Assert.IsTrue this.ErrorsExist - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) [] - member this.FavourStaticEmptyFieldsSuggestedFixForList() = + member this.FavourStaticEmptyFieldsFixForList() = let source = "let foo = []" let expected = "let foo = List.Empty" @@ -193,12 +193,12 @@ match foo with Assert.IsTrue this.ErrorsExist - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) [] - member this.FavourStaticEmptyFieldsSuggestedFixForArray() = + member this.FavourStaticEmptyFieldsFixForArray() = let source = "let foo = [||]" let expected = "let foo = Array.empty" @@ -207,6 +207,6 @@ match foo with Assert.IsTrue this.ErrorsExist - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/FunctionReimplementation.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/FunctionReimplementation.fs index a799cb223..04d13ba73 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/FunctionReimplementation.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/FunctionReimplementation.fs @@ -40,7 +40,7 @@ let f = List.map (fun (x,_) -> id x) [] this.AssertNoWarnings() [] - member this.``Quickfix for lambda reimplementing operator is to replace the lambda with the operator.``() = + member this.``Fix for lambda reimplementing operator is to replace the lambda with the operator.``() = let source = """ module Program @@ -54,7 +54,7 @@ let f = ( * ) """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Lambda reimplementing long identifier function issues error``() = @@ -67,7 +67,7 @@ let f = fun a b -> List.map a b Assert.IsTrue(this.ErrorsExist) [] - member this.``Quickfix for lambda reimplementing function is to replace the lambda with the func ident.``() = + member this.``Fix for lambda reimplementing function is to replace the lambda with the func ident.``() = let source = """ module Program @@ -81,7 +81,7 @@ let f = List.map """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) /// Regression test for: https://github.com/fsprojects/FSharpLint/issues/113 [] @@ -217,7 +217,7 @@ let f = tan >> cos >> sin this.Parse source - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) @@ -237,7 +237,7 @@ let f = tan >> cos >> sin this.Parse source - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) @@ -257,7 +257,7 @@ let f = min 0.0 >> cos >> tan this.Parse source - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/ExceptionNames.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/ExceptionNames.fs index 289978ec2..cc151233e 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/ExceptionNames.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/ExceptionNames.fs @@ -71,4 +71,4 @@ exception FooException of string """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/InterfaceNames.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/InterfaceNames.fs index 34d5222d4..9d38514ba 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/InterfaceNames.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/InterfaceNames.fs @@ -90,4 +90,4 @@ type IPrintable = """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/ParameterNames.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/ParameterNames.fs index 9e0030781..2716a568f 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/ParameterNames.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/ParameterNames.fs @@ -88,7 +88,7 @@ let baz __foobar = 0 """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Quick fix for camel case takes into account underscore prefixes.``() = @@ -105,7 +105,7 @@ let foo _x = 0 """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``As pattern is processed correctly (GetPatternIdents regression)``() = diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/PrivateValuesNames.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/PrivateValuesNames.fs index 52b15aed5..1c9ccb316 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/PrivateValuesNames.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/PrivateValuesNames.fs @@ -252,7 +252,7 @@ let foo x = 0 """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.ForLoopIdentifierIsCamelCase() = diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/TypeNames.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/TypeNames.fs index 69d3d511b..bbbed5ff4 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/TypeNames.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/TypeNames.fs @@ -215,7 +215,7 @@ type Cat = | Foo """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Quick fix for pascal case converts the first character of the identifier to upper case.``() = @@ -232,7 +232,7 @@ type Cat = | Foo """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.EnumNameIsPascalCase() = diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/NoPartialFunctions.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/NoPartialFunctions.fs index 09f427a27..5c23b7c80 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/NoPartialFunctions.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/NoPartialFunctions.fs @@ -21,12 +21,12 @@ type TestConventionsNoPartialFunctions() = this.AssertErrorWithMessageExists("Consider using 'List.tryFind' instead of partial function/method 'List.find'.") [] - member this.``Quickfix for partial function which should be replaced with another function``() = + member this.``Fix for partial function which should be replaced with another function``() = let source = "let x = List.find 1 [2; 3; 4]" this.Parse(source) let expected = "let x = List.tryFind 1 [2; 3; 4]" - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) this.AssertErrorWithMessageExists( "Consider using 'List.tryFind' instead of partial function/method 'List.find'.") [] diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/RecursiveAsyncFunction.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/RecursiveAsyncFunction.fs index 5e779bb3b..c66b6f32e 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/RecursiveAsyncFunction.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/RecursiveAsyncFunction.fs @@ -52,7 +52,7 @@ module X = Assert.IsTrue(this.NoErrorsExist) [] - member this.``Quickfix for recursive async function ending in recursive do!``() = + member this.``Fix for recursive async function ending in recursive do!``() = let source = """ namespace Program @@ -74,5 +74,5 @@ module X = """ this.Parse(source) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result) \ No newline at end of file diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/RedundantNewKeyword.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/RedundantNewKeyword.fs index ad58dedf9..cd8d8b08c 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/RedundantNewKeyword.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/RedundantNewKeyword.fs @@ -43,7 +43,7 @@ let _ = System.Version() """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``new keyword is not required (1).``() = diff --git a/tests/FSharpLint.Core.Tests/Rules/Conventions/SuggestUseAutoProperty.fs b/tests/FSharpLint.Core.Tests/Rules/Conventions/SuggestUseAutoProperty.fs index 7852bfff6..3cbd10887 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Conventions/SuggestUseAutoProperty.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Conventions/SuggestUseAutoProperty.fs @@ -105,7 +105,7 @@ type Foo(content: int) = """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Should not suggest using auto-property for types with [] attribute`` () = diff --git a/tests/FSharpLint.Core.Tests/Rules/Formatting/TupleFormatting/TupleCommaSpacing.fs b/tests/FSharpLint.Core.Tests/Rules/Formatting/TupleFormatting/TupleCommaSpacing.fs index f552812ee..4f82cd019 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Formatting/TupleFormatting/TupleCommaSpacing.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Formatting/TupleFormatting/TupleCommaSpacing.fs @@ -18,7 +18,7 @@ let x = (1,2)""") Assert.IsTrue(this.ErrorExistsAt(4, 10)) [] - member this.``Quickfix for tuple instantiation without space after comma``() = + member this.``Fix for tuple instantiation without space after comma``() = let source = """ module Program @@ -31,7 +31,7 @@ module Program let x = (1, 2)""" this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Error for tuple instantiation with two spaces after comma``() = @@ -43,7 +43,7 @@ let x = (1, 2)""") Assert.IsTrue(this.ErrorExistsAt(4, 10)) [] - member this.``Quickfix for tuple instantiation with two spaces after comma``() = + member this.``Fix for tuple instantiation with two spaces after comma``() = let source = """ module Program @@ -56,7 +56,7 @@ module Program let x = (1, 2)""" this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``No error for tuple instantiation with single space after comma``() = diff --git a/tests/FSharpLint.Core.Tests/Rules/Formatting/TupleFormatting/TupleParentheses.fs b/tests/FSharpLint.Core.Tests/Rules/Formatting/TupleFormatting/TupleParentheses.fs index 58f5ac8f3..ccb42e12e 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Formatting/TupleFormatting/TupleParentheses.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Formatting/TupleFormatting/TupleParentheses.fs @@ -24,7 +24,7 @@ let x = 1, 2""") Assert.IsTrue(this.NoErrorsExist) [] - member this.``Quickfix for tuple instantiation without parentheses``() = + member this.``Fix for tuple instantiation without parentheses``() = let source = """ module Program @@ -36,7 +36,7 @@ module Program let x = (1, 2)""" this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``No error for tuple instantiation with parentheses``() = diff --git a/tests/FSharpLint.Core.Tests/Rules/Formatting/TypePrefixing.fs b/tests/FSharpLint.Core.Tests/Rules/Formatting/TypePrefixing.fs index bfee8856c..6bc530c0e 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Formatting/TypePrefixing.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Formatting/TypePrefixing.fs @@ -121,7 +121,7 @@ type X = Generic Assert.IsTrue(this.NoErrorsExist) [] - member this.``Quickfix for F# List type``() = + member this.``Fix for F# List type``() = let source = """ module Program @@ -135,10 +135,10 @@ type T = int list """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] - member this.``Quickfix for F# Option type``() = + member this.``Fix for F# Option type``() = let source = """ module Program @@ -152,10 +152,10 @@ type T = int option """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] - member this.``Quickfix for F# Ref type``() = + member this.``Fix for F# Ref type``() = let source = """ module Program @@ -169,10 +169,10 @@ type T = int ref """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] - member this.``Quickfix for F# array type from prefix syntax``() = + member this.``Fix for F# array type from prefix syntax``() = let source = """ module Program @@ -186,10 +186,10 @@ type T = int [] """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] - member this.``Quickfix for F# array type from standard postfix syntax``() = + member this.``Fix for F# array type from standard postfix syntax``() = let source = """ module Program @@ -203,10 +203,10 @@ type T = int [] """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] - member this.``Quickfix for F# array tuple type from standard postfix syntax``() = + member this.``Fix for F# array tuple type from standard postfix syntax``() = let source = """ module Program @@ -220,10 +220,10 @@ type T = (int * int) [] """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] - member this.``Quickfix for generic type``() = + member this.``Fix for generic type``() = let source = """ module Program @@ -237,7 +237,7 @@ type T = Generic """ this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] type TestFormattingAlwaysTypePrefixing() = diff --git a/tests/FSharpLint.Core.Tests/Rules/Formatting/TypedItemSpacing.fs b/tests/FSharpLint.Core.Tests/Rules/Formatting/TypedItemSpacing.fs index 16b4255a0..659c271dc 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Formatting/TypedItemSpacing.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Formatting/TypedItemSpacing.fs @@ -27,11 +27,11 @@ type TestFormattingTypedItemSpaceAfter() = Assert.IsTrue(this.ErrorExistsAt(1, 11)) [] - member this.``Quickfix for typed pattern with no spaces around colon``() = + member this.``Fix for typed pattern with no spaces around colon``() = let source = "let (x:int) = 1" let expected = "let (x: int) = 1" this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Error for typed pattern with spaces around colon``() = @@ -49,11 +49,11 @@ type TestFormattingTypedItemSpaceAfter() = Assert.IsTrue(this.ErrorExistsAt(1, 13)) [] - member this.``Quickfix for typed pattern with spaces around colon``() = + member this.``Fix for typed pattern with spaces around colon``() = let source = "let (x : int) = 1" let expected = "let (x: int) = 1" this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] type TestFormattingTypedItemSpacesAround() = @@ -78,7 +78,7 @@ let (x:int) = 1""") Assert.IsTrue(this.ErrorExistsAt(4, 5)) [] - member this.``Quickfix for typed pattern with spaces around colon``() = + member this.``Fix for typed pattern with spaces around colon``() = let source = """ module Program @@ -91,7 +91,7 @@ module Program let (x : int) = 1""" this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Error for typed pattern with space after colon``() = @@ -103,7 +103,7 @@ let (x: int) = 1""") Assert.IsTrue(this.ErrorExistsAt(4, 5)) [] - member this.``Quickfix for typed pattern with space after colon``() = + member this.``Fix for typed pattern with space after colon``() = let source = """ module Program @@ -116,7 +116,7 @@ module Program let (x : int) = 1""" this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] type TestFormattingTypedItemNoSpaces() = @@ -141,7 +141,7 @@ let (x : int) = 1""") Assert.IsTrue(this.ErrorExistsAt(4, 5)) [] - member this.``Quickfix for typed pattern with spaces around colon``() = + member this.``Fix for typed pattern with spaces around colon``() = let source = """ module Program @@ -154,7 +154,7 @@ module Program let (x:int) = 1""" this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Error for typed pattern with space after colon``() = @@ -166,7 +166,7 @@ let (x: int) = 1""") Assert.IsTrue(this.ErrorExistsAt(4, 5)) [] - member this.``Quickfix for typed pattern with space after colon``() = + member this.``Fix for typed pattern with space after colon``() = let source = """ module Program @@ -179,4 +179,4 @@ module Program let (x:int) = 1""" this.Parse source - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) diff --git a/tests/FSharpLint.Core.Tests/Rules/Hints/HintMatcher.fs b/tests/FSharpLint.Core.Tests/Rules/Hints/HintMatcher.fs index fc4627025..120c99f44 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Hints/HintMatcher.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Hints/HintMatcher.fs @@ -771,7 +771,7 @@ let x = List.collect (fun x -> [x]) [1;2;3] this.SetConfig(["List.concat (List.map f x) ===> List.collect f x"]) this.Parse(source) - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Function application moved in suggestion which does not require parentheses must not be surrounded by them.``() = @@ -789,7 +789,7 @@ let x y = y 0 this.SetConfig(["if x then true else false ===> x"]) this.Parse(source) - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Function application moved in suggestion which requires parens must be surrounded by them.``() = @@ -807,7 +807,7 @@ let x y = y (foo 0) this.SetConfig(["0 ===> foo 0"]) this.Parse(source) - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Function application in suggestion with surrounding parens keeps them.``() = @@ -825,7 +825,7 @@ let x y = y (foo 0 0) this.SetConfig(["foo 0 ===> foo 0 0"]) this.Parse(source) - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Function application as variable in suggestion with surrounding parens keeps them.``() = @@ -843,7 +843,7 @@ let x y = id (foo 0) this.SetConfig(["bar x ===> id x"]) this.Parse(source) - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Function application in suggestion with surrounding parens but no longer needs removes surrounding parens.``() = @@ -861,7 +861,7 @@ let x y = if foo 0 then 0 else 1 this.SetConfig(["bar x ===> if x then 0 else 1"]) this.Parse(source) - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Function application in suggestion with addressof operator keeps parens surrounding application.``() = @@ -879,7 +879,7 @@ let x y = &&(foo 0) this.SetConfig(["&x ===> &&x"]) this.Parse(source) - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Function application in suggestion with prefix operator removed, removes parens surrounding application.``() = @@ -896,7 +896,7 @@ let x y = foo 0 """ this.SetConfig(["- -x ===> x"]) this.Parse(source) - Assert.AreEqual(expected, this.ApplyQuickFix source) + Assert.AreEqual(expected, this.ApplyFix source) [] member this.``Infix operator in hint fix is formatted with space either side of it``() = @@ -918,4 +918,4 @@ let x y = this.SetConfig(["List.map f (List.map g x) ===> List.map (g >> f) x"]) this.Parse(source) - Assert.AreEqual(expected, this.ApplyQuickFix source) \ No newline at end of file + Assert.AreEqual(expected, this.ApplyFix source) \ No newline at end of file diff --git a/tests/FSharpLint.Core.Tests/Rules/TestRuleBase.fs b/tests/FSharpLint.Core.Tests/Rules/TestRuleBase.fs index 2d03f1f77..a9a4fadbd 100644 --- a/tests/FSharpLint.Core.Tests/Rules/TestRuleBase.fs +++ b/tests/FSharpLint.Core.Tests/Rules/TestRuleBase.fs @@ -74,13 +74,13 @@ type TestRuleBase () = member this.AssertNoWarnings() = Assert.IsFalse(this.ErrorsExist, "Expected no errors, but was: " + this.ErrorMsg) - member this.ApplyQuickFix (source:string) = - let firstSuggestedFix = + member this.ApplyFix (source:string) = + let firstFix = suggestions - |> Seq.choose (fun linterSuggestion -> linterSuggestion.Details.SuggestedFix) + |> Seq.choose (fun linterSuggestion -> linterSuggestion.Details.Fix) |> Seq.tryHead - match Option.bind (fun (suggestedFix: Lazy>) -> suggestedFix.Value) firstSuggestedFix with + match Option.bind (fun (fix: Lazy>) -> fix.Value) firstFix with | Some(fix) -> let startIndex = ExpressionUtilities.findPos fix.FromRange.Start source let endIndex = ExpressionUtilities.findPos fix.FromRange.End source diff --git a/tests/FSharpLint.Core.Tests/Rules/Typography/NoTabCharacters.fs b/tests/FSharpLint.Core.Tests/Rules/Typography/NoTabCharacters.fs index fdabe011b..338dcdb3a 100644 --- a/tests/FSharpLint.Core.Tests/Rules/Typography/NoTabCharacters.fs +++ b/tests/FSharpLint.Core.Tests/Rules/Typography/NoTabCharacters.fs @@ -29,14 +29,14 @@ type TestTypographyTabCharacterInFile() = Assert.IsFalse(this.ErrorExistsAt(4, 13)) [] - member this.TabCharacterInFileSuggestedFix() = + member this.TabCharacterInFileFix() = let source = "\t" let expected = String.replicate 4 " " this.Parse source Assert.IsTrue(this.ErrorExistsAt(1, 0)) - let result = this.ApplyQuickFix source + let result = this.ApplyFix source Assert.AreEqual(expected, result)