Skip to content

Commit 6ddfbca

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 6ddfbca

File tree

1 file changed

+41
-18
lines changed

1 file changed

+41
-18
lines changed

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

Lines changed: 41 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,44 @@ 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.filter
29+
(fun each -> each.Symbol.DisplayName = nameWithoutUnderscore && each.IsFromDefinition)
30+
|> Array.isEmpty
31+
|> not
32+
33+
if clashesWithOtherDefinitions then
34+
yield {
35+
Range = usage.Range
36+
Message = Resources.GetString ("RulesUsedUnderscorePrefixedElements")
37+
SuggestedFix = None
38+
TypeChecks = List.Empty
39+
}
40+
else
41+
for range in [usage.Range; symbol.DeclarationLocation] do
42+
let warningDetrails =
43+
lazy(
44+
let fromText = symbol.DisplayName
45+
Some { FromRange = range; FromText = fromText; ToText = nameWithoutUnderscore })
46+
yield {
47+
Range = range
48+
Message = Resources.GetString ("RulesUsedUnderscorePrefixedElements")
49+
SuggestedFix = Some warningDetrails
50+
TypeChecks = List.Empty
51+
}
52+
else
53+
()
54+
| _ -> () }
55+
|> Seq.distinctBy (fun wargningDetails -> wargningDetails.Range)
3356
|> Seq.toArray
3457
| None -> Array.empty
3558
else

0 commit comments

Comments
 (0)