|
1 | 1 | module FSharpLint.Rules.Helper.Naming |
2 | 2 |
|
3 | 3 | open System |
| 4 | +open System.Text |
4 | 5 | open FSharp.Compiler.Syntax |
5 | 6 | open FSharp.Compiler.Text |
6 | 7 | open FSharpLint.Framework |
@@ -67,15 +68,33 @@ module QuickFixes = |
67 | 68 | let camelCaseIdent = mapFirstChar Char.ToLower ident.idText |
68 | 69 | Some { FromText = ident.idText; FromRange = ident.idRange; ToText = camelCaseIdent }) |
69 | 70 |
|
70 | | - let toAllLowercase (ident:Ident) = lazy( |
71 | | - let newIdent = ident.idText.ToLower() |
72 | | - //TODO: in case Underscores=AllowAny or AllowInfix, and ident is PascalCase or CamelCase, try to inject them when case changes |
73 | | - Some { FromText = ident.idText; FromRange = ident.idRange; ToText = newIdent }) |
74 | | - |
75 | | - let toAllUppercase (ident:Ident) = lazy( |
76 | | - let newIdent = ident.idText.ToUpper() |
77 | | - //TODO: in case Underscores=AllowAny or AllowInfix, and ident is PascalCase or CamelCase, try to inject them when case changes |
78 | | - Some { FromText = ident.idText; FromRange = ident.idRange; ToText = newIdent }) |
| 71 | + let splitByCaseChange (name: string) : seq<string> = |
| 72 | + let builder = System.Text.StringBuilder() |
| 73 | + seq { |
| 74 | + let isUppercase = Char.IsUpper name.[0] |
| 75 | + for char in name do |
| 76 | + if isUppercase <> Char.IsUpper char then |
| 77 | + yield builder.ToString() |
| 78 | + builder.Clear() |> ignore<StringBuilder> |
| 79 | + builder.Append char |> ignore<StringBuilder> |
| 80 | + if builder.Length > 0 then |
| 81 | + yield builder.ToString() |
| 82 | + } |
| 83 | + |
| 84 | + let private convertAllToCase (caseMapping: string -> string) (underscoresConfig: Option<NamingUnderscores>) (ident:Ident) = |
| 85 | + lazy( |
| 86 | + let newIdent = |
| 87 | + match underscoresConfig with |
| 88 | + | Some NamingUnderscores.AllowAny | Some NamingUnderscores.AllowInfix -> |
| 89 | + let parts = splitByCaseChange ident.idText |> Seq.map caseMapping |
| 90 | + String.Join('_', parts) |
| 91 | + | _ -> caseMapping ident.idText |
| 92 | + Some { FromText = ident.idText; FromRange = ident.idRange; ToText = newIdent } |
| 93 | + ) |
| 94 | + |
| 95 | + let toAllLowercase = convertAllToCase (fun part -> part.ToLower()) |
| 96 | + |
| 97 | + let toAllUppercase = convertAllToCase (fun part -> part.ToUpper()) |
79 | 98 |
|
80 | 99 | [<Literal>] |
81 | 100 | let private NumberOfExpectedBackticks = 4 |
@@ -167,10 +186,10 @@ let private checkIdentifierPart (config:NamingConfig) (identifier:Ident) (idText |
167 | 186 | |> Option.map (formatError >> tryAddFix QuickFixes.toCamelCase) |
168 | 187 | | Some NamingCase.AllLowercase -> |
169 | 188 | lowercaseRule idText |
170 | | - |> Option.map (formatError >> tryAddFix QuickFixes.toAllLowercase) |
| 189 | + |> Option.map (formatError >> tryAddFix (QuickFixes.toAllLowercase config.Underscores)) |
171 | 190 | | Some NamingCase.AllUppercase -> |
172 | 191 | uppercaseRule idText |
173 | | - |> Option.map (formatError >> tryAddFix QuickFixes.toAllUppercase) |
| 192 | + |> Option.map (formatError >> tryAddFix (QuickFixes.toAllUppercase config.Underscores)) |
174 | 193 | | _ -> None |
175 | 194 |
|
176 | 195 | let underscoresError = |
|
0 commit comments