Skip to content

Commit be6dcb6

Browse files
webwarrior-wsMersho
andcommitted
UsedUnderscorePrefixedElements: implement quick fix
Implement quick fix for UsedUnderscorePrefixedElements. Quick fix is only applied if no other identifiers with suggested name (without underscore) exist. There are cases when such identifiers exist, but not in the same scope, and stil no quick fix is applied. Co-authored-by: Mehrshad <[email protected]>
1 parent 3b7fc5d commit be6dcb6

File tree

1 file changed

+39
-18
lines changed

1 file changed

+39
-18
lines changed

src/FSharpLint.Core/Rules/Conventions/UsedUnderscorePrefixedElements.fs

Lines changed: 39 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,11 @@ module FSharpLint.Rules.UsedUnderscorePrefixedElements
22

33
open System
44

5+
open FSharp.Compiler.Symbols
6+
open FSharp.Compiler.CodeAnalysis
7+
58
open FSharpLint.Framework
69
open FSharpLint.Framework.Suggestion
7-
open FSharp.Compiler.Syntax
8-
open FSharp.Compiler.Text
9-
open FSharp.Compiler.CodeAnalysis
1010
open FSharpLint.Framework.Ast
1111
open FSharpLint.Framework.Rules
1212

@@ -15,21 +15,42 @@ let runner (args: AstNodeRuleParams) =
1515
if args.NodeIndex = 0 then
1616
match args.CheckInfo with
1717
| Some checkResults ->
18-
checkResults.GetAllUsesOfAllSymbolsInFile()
19-
|> Seq.choose (fun usage ->
20-
match usage.Symbol with
21-
| :? FSharp.Compiler.Symbols.FSharpMemberOrFunctionOrValue as symbol ->
22-
if not usage.IsFromDefinition && symbol.FullName.StartsWith "_"
23-
&& symbol.FullName <> "_" && not symbol.IsCompilerGenerated then
24-
Some {
25-
Range = usage.Range
26-
Message = String.Format(Resources.GetString ("RulesUsedUnderscorePrefixedElements"))
27-
SuggestedFix = None
28-
TypeChecks = List.Empty
29-
}
30-
else
31-
None
32-
| _ -> None )
18+
let allUsages = checkResults.GetAllUsesOfAllSymbolsInFile() |> Seq.toArray
19+
seq {
20+
for usage in allUsages do
21+
match usage.Symbol with
22+
| :? FSharpMemberOrFunctionOrValue as symbol ->
23+
if not usage.IsFromDefinition && symbol.DisplayName.StartsWith "_"
24+
&& symbol.DisplayName <> "_" && not symbol.IsCompilerGenerated && not symbol.IsMember then
25+
let nameWithoutUnderscore = symbol.DisplayName.[1..]
26+
let clashesWithOtherDefinitions =
27+
allUsages
28+
|> Array.exists
29+
(fun each -> each.Symbol.DisplayName = nameWithoutUnderscore && each.IsFromDefinition)
30+
31+
if clashesWithOtherDefinitions then
32+
yield {
33+
Range = usage.Range
34+
Message = Resources.GetString ("RulesUsedUnderscorePrefixedElements")
35+
SuggestedFix = None
36+
TypeChecks = List.Empty
37+
}
38+
else
39+
for range in [usage.Range; symbol.DeclarationLocation] do
40+
let warningDetrails =
41+
lazy(
42+
let fromText = symbol.DisplayName
43+
Some { FromRange = range; FromText = fromText; ToText = nameWithoutUnderscore })
44+
yield {
45+
Range = range
46+
Message = Resources.GetString ("RulesUsedUnderscorePrefixedElements")
47+
SuggestedFix = Some warningDetrails
48+
TypeChecks = List.Empty
49+
}
50+
else
51+
()
52+
| _ -> () }
53+
|> Seq.distinctBy (fun wargningDetails -> wargningDetails.Range)
3354
|> Seq.toArray
3455
| None -> Array.empty
3556
else

0 commit comments

Comments
 (0)