Skip to content

Commit cd8ce66

Browse files
webwarrior-wsknocte
authored andcommitted
Core: implement proper underscore AllowInfix injection
In the case the user wants quick fixes to convert {camel,pascal}case to snake_case or MACRO_CASE, we need to inject underscores when case changes. This commit makes the previous added test pass.
1 parent 242e312 commit cd8ce66

File tree

1 file changed

+30
-11
lines changed

1 file changed

+30
-11
lines changed

src/FSharpLint.Core/Rules/Conventions/Naming/NamingHelper.fs

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module FSharpLint.Rules.Helper.Naming
22

33
open System
4+
open System.Text
45
open FSharp.Compiler.Syntax
56
open FSharp.Compiler.Text
67
open FSharpLint.Framework
@@ -67,15 +68,33 @@ module QuickFixes =
6768
let camelCaseIdent = mapFirstChar Char.ToLower ident.idText
6869
Some { FromText = ident.idText; FromRange = ident.idRange; ToText = camelCaseIdent })
6970

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())
7998

8099
[<Literal>]
81100
let private NumberOfExpectedBackticks = 4
@@ -167,10 +186,10 @@ let private checkIdentifierPart (config:NamingConfig) (identifier:Ident) (idText
167186
|> Option.map (formatError >> tryAddFix QuickFixes.toCamelCase)
168187
| Some NamingCase.AllLowercase ->
169188
lowercaseRule idText
170-
|> Option.map (formatError >> tryAddFix QuickFixes.toAllLowercase)
189+
|> Option.map (formatError >> tryAddFix (QuickFixes.toAllLowercase config.Underscores))
171190
| Some NamingCase.AllUppercase ->
172191
uppercaseRule idText
173-
|> Option.map (formatError >> tryAddFix QuickFixes.toAllUppercase)
192+
|> Option.map (formatError >> tryAddFix (QuickFixes.toAllUppercase config.Underscores))
174193
| _ -> None
175194

176195
let underscoresError =

0 commit comments

Comments
 (0)