Skip to content

Commit af06e2f

Browse files
committed
Core: new "AllowInfix" enum for underscores
This paves the way for allowing people to use MACRO_CASE or snake_case in their configurations.
1 parent 1920f80 commit af06e2f

File tree

4 files changed

+96
-10
lines changed

4 files changed

+96
-10
lines changed

src/FSharpLint.Core/Framework/Rules.fs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ type NamingUnderscores =
5858
| None = 0
5959
| AllowPrefix = 1
6060
| AllowAny = 2
61+
| AllowInfix = 3
6162

6263
type NamingConfig =
6364
{ Naming:NamingCase option

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

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,25 @@ module QuickFixes =
2424
let toText = prefixingUnderscores + ident.idText.Replace("_", String.Empty)
2525
Some { FromText = ident.idText; FromRange = ident.idRange; ToText = toText })
2626

27+
let removePrefixingAndSuffixingUnderscores (ident:Ident) = lazy(
28+
let rec removePrefixingUnderscores (str: string) =
29+
if str.StartsWith "_" then
30+
removePrefixingUnderscores(str.Substring 1)
31+
else
32+
str
33+
34+
let rec removeSuffixingUnderscores (str: string) =
35+
if str.EndsWith "_" then
36+
removeSuffixingUnderscores(str.Substring(0, str.Length - 1))
37+
else
38+
str
39+
40+
let toText =
41+
ident.idText
42+
|> removePrefixingUnderscores
43+
|> removeSuffixingUnderscores
44+
Some { FromText = ident.idText; FromRange = ident.idRange; ToText = toText })
45+
2746
let addPrefix prefix (ident:Ident) = lazy(
2847
Some { FromText = ident.idText; FromRange = ident.idRange; ToText = prefix + ident.idText })
2948

@@ -83,12 +102,17 @@ let private camelCaseRule (identifier:string) =
83102
if not (isCamelCase identifier) then Some "RulesNamingConventionsCamelCaseError"
84103
else None
85104

86-
let private underscoreRule allowPrefix (identifier:string) =
87-
if allowPrefix && identifier.TrimStart('_').Contains("_") then
88-
Some "RulesNamingConventionsUnderscoreError"
89-
else if not allowPrefix && identifier.Contains("_") then
90-
Some "RulesNamingConventionsUnderscoreError"
91-
else
105+
let private underscoreRule (underscoreMode: NamingUnderscores) (identifier:string) =
106+
let errorKeyToRemoveUnderscores = "RulesNamingConventionsUnderscoreError"
107+
let errorKeyToRemoveLeadingOrTrailingUnderscores = "RulesNamingConventionsNoInfixUnderscoreError"
108+
match underscoreMode with
109+
| NamingUnderscores.AllowPrefix when identifier.TrimStart('_').Contains '_' ->
110+
Some errorKeyToRemoveUnderscores
111+
| NamingUnderscores.None when identifier.Contains '_' ->
112+
Some errorKeyToRemoveUnderscores
113+
| NamingUnderscores.AllowInfix when (identifier.StartsWith '_' || identifier.EndsWith '_') ->
114+
Some errorKeyToRemoveLeadingOrTrailingUnderscores
115+
| _ ->
92116
None
93117

94118
let private prefixRule (prefix:string) (identifier:string) =
@@ -120,12 +144,15 @@ let private checkIdentifierPart (config:NamingConfig) (identifier:Ident) (idText
120144

121145
let underscoresError =
122146
match config.Underscores with
123-
| Some NamingUnderscores.None ->
124-
underscoreRule false idText
147+
| Some (NamingUnderscores.None as nuCfg) ->
148+
underscoreRule nuCfg idText
125149
|> Option.map (formatError >> tryAddFix QuickFixes.removeAllUnderscores)
126-
| Some NamingUnderscores.AllowPrefix ->
127-
underscoreRule true idText
150+
| Some (NamingUnderscores.AllowPrefix as nuCfg) ->
151+
underscoreRule nuCfg idText
128152
|> Option.map (formatError >> tryAddFix QuickFixes.removeNonPrefixingUnderscores)
153+
| Some (NamingUnderscores.AllowInfix as nuCfg) ->
154+
underscoreRule nuCfg idText
155+
|> Option.map (formatError >> tryAddFix QuickFixes.removePrefixingAndSuffixingUnderscores)
129156
| _ -> None
130157

131158
let prefixError =

src/FSharpLint.Core/Text.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -174,6 +174,9 @@
174174
<data name="RulesNamingConventionsUnderscoreError" xml:space="preserve">
175175
<value>Consider changing `{0}` to remove any underscores.</value>
176176
</data>
177+
<data name="RulesNamingConventionsNoInfixUnderscoreError" xml:space="preserve">
178+
<value>Consider removing any leading or trailing underscore from `{0}`.</value>
179+
</data>
177180
<data name="RulesAvoidTooShortNamesError" xml:space="preserve">
178181
<value>Consider using a longer name, as it is currently too short.</value>
179182
</data>

tests/FSharpLint.Core.Tests/Rules/Conventions/Naming/LiteralNames.fs

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ let config =
1010
Underscores = Some NamingUnderscores.None
1111
Prefix = None
1212
Suffix = None }
13+
1314
[<TestFixture>]
1415
type TestConventionsLiteralNames() =
1516
inherit TestAstNodeRuleBase.TestAstNodeRuleBase(LiteralNames.rule config)
@@ -69,3 +70,57 @@ let cat = 5
6970

7071
Assert.IsTrue(this.ErrorExistsAt(5, 4))
7172

73+
let infixConfig =
74+
{ NamingConfig.Naming = Some NamingCase.PascalCase
75+
Underscores = Some NamingUnderscores.AllowInfix
76+
Prefix = None
77+
Suffix = None }
78+
79+
[<TestFixture>]
80+
type TestConventionsLiteralNamesInfix() =
81+
inherit TestAstNodeRuleBase.TestAstNodeRuleBase(LiteralNames.rule infixConfig)
82+
83+
[<Test>]
84+
member this.LiteralIsInfixUnderscore() =
85+
this.Parse """
86+
module Program
87+
88+
[<Literal>]
89+
let Super_Cat = 5
90+
"""
91+
92+
this.AssertNoWarnings()
93+
94+
[<Test>]
95+
member this.LiteralIsUnderscorePrefix() =
96+
this.Parse """
97+
module Program
98+
99+
[<Literal>]
100+
let _Cat = 5
101+
"""
102+
103+
Assert.IsTrue(this.ErrorExistsOnLine 5)
104+
105+
[<Test>]
106+
member this.LiteralIsUnderscoreSuffix() =
107+
this.Parse """
108+
module Program
109+
110+
[<Literal>]
111+
let Cat_ = 5
112+
"""
113+
114+
Assert.IsTrue(this.ErrorExistsOnLine 5)
115+
116+
[<Test>]
117+
member this.LiteralIsNoUnderscore() =
118+
this.Parse """
119+
module Program
120+
121+
[<Literal>]
122+
let SuperCat = 5
123+
"""
124+
125+
this.AssertNoWarnings()
126+

0 commit comments

Comments
 (0)