Movatterモバイル変換


[0]ホーム

URL:


Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commitc422581

Browse files
Vasily KirichenkoVasily Kirichenko
Vasily Kirichenko
authored and
Vasily Kirichenko
committed
module scope aware unused opens
1 parent4788e9d commitc422581

File tree

1 file changed

+54
-32
lines changed

1 file changed

+54
-32
lines changed

‎vsintegration/src/FSharp.Editor/Diagnostics/UnusedOpensDiagnosticAnalyzer.fs‎

Lines changed: 54 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -17,28 +17,39 @@ open Microsoft.FSharp.Compiler.Range
1717
openMicrosoft.FSharp.Compiler.SourceCodeServices
1818
openSymbols
1919

20-
2120
moduleprivateUnusedOpens=
22-
23-
24-
let recvisitSynModuleOrNamespaceDecls(parent:Ast.LongIdent)decls:(Set<string>* range)list=
21+
/// Represents single open statement.
22+
typeOpenStatement=
23+
{/// Open namespace or module effective names.
24+
Names:Set<string>
25+
/// Range of open statement itself.
26+
Range:range
27+
/// Enclosing module or namespace range (that is, the scope on in which this open statement is visible).
28+
ModuleRange:range}
29+
30+
let recvisitSynModuleOrNamespaceDecls(parent:Ast.LongIdent)(decls:SynModuleDecls)(moduleRange:range):OpenStatement list=
2531
[for declin declsdo
2632
match declwith
2733
| SynModuleDecl.Open(LongIdentWithDots.LongIdentWithDots(id= longId), range)->
2834
yield
29-
set[yield(longId|> List.map(fun l-> l.idText)|> String.concat".")
30-
// `open N.M` can open N.M module from parent module as well, if it's non empty
31-
ifnot(List.isEmpty parent)then
32-
yield(parent@ longId|> List.map(fun l-> l.idText)|> String.concat".")], range
33-
| SynModuleDecl.NestedModule(SynComponentInfo.ComponentInfo(longId= longId),_, decls,_,_)->
34-
yield! visitSynModuleOrNamespaceDecls longId decls
35+
{ Names=
36+
set[yield(longId|> List.map(fun l-> l.idText)|> String.concat".")
37+
// `open N.M` can open N.M module from parent module as well, if it's non empty
38+
ifnot(List.isEmpty parent)then
39+
yield(parent@ longId|> List.map(fun l-> l.idText)|> String.concat".")]
40+
Range= range
41+
ModuleRange= moduleRange}
42+
43+
| SynModuleDecl.NestedModule(SynComponentInfo.ComponentInfo(longId= longId),_, decls,_,moduleRange)->
44+
yield! visitSynModuleOrNamespaceDecls longId decls moduleRange
3545
|_->()]
3646

37-
letgetOpenStatements=function
47+
letgetOpenStatements(parsedInput:ParsedInput):OpenStatement list=
48+
match parsedInputwith
3849
| ParsedInput.ImplFile(ParsedImplFileInput(modules= modules))->
3950
[for mdin modulesdo
40-
letSynModuleOrNamespace(longId= longId; decls= decls)= md
41-
yield! visitSynModuleOrNamespaceDecls longId decls]
51+
letSynModuleOrNamespace(longId= longId; decls= decls; range= moduleRange)= md
52+
yield! visitSynModuleOrNamespaceDecls longId declsmoduleRange]
4253
|_->[]
4354

4455
letgetAutoOpenAccessPath(ent:FSharpEntity)=
@@ -79,7 +90,11 @@ module private UnusedOpens =
7990
| Some(island,_,_)-> island= fullName
8091
| None->false
8192

82-
letgetUnusedOpens(sourceText:SourceText)(parsedInput:ParsedInput)(symbolUses:FSharpSymbolUse[])=
93+
typeNamespaceUse=
94+
{ Ident:string
95+
Location:range}
96+
97+
letgetUnusedOpens(sourceText:SourceText)(parsedInput:ParsedInput)(symbolUses:FSharpSymbolUse[]):range list=
8398

8499
letgetPartNamespace(symbolUse:FSharpSymbolUse)(fullName:string)=
85100
// given a symbol range such as `Text.ISegment` and a full name of `MonoDevelop.Core.Text.ISegment`, return `MonoDevelop.Core`
@@ -117,25 +132,32 @@ module private UnusedOpens =
117132
yield! entityNamespace declaringEntity]
118133
}|> Option.toList|> List.concat|> List.choose id
119134

120-
letnamespacesInUse=
135+
letnamespacesInUse:NamespaceUse list=
121136
symbolUses
122-
|> Seq.filter(fun(s: FSharpSymbolUse)->not s.IsFromDefinition)
123-
|> Seq.collect getPossibleNamespaces
124-
|> Set.ofSeq
125-
126-
letfilter list:(Set<string>* range)list=
127-
let recfilterInner acc list(seenNamespaces:Set<string>)=
128-
letnotUsed ns=not(namespacesInUse.Contains ns)|| seenNamespaces.Contains ns
137+
|> Array.filter(fun(s: FSharpSymbolUse)->not s.IsFromDefinition)
138+
|> Array.toList
139+
|> List.collect(fun x->
140+
getPossibleNamespaces x
141+
|> List.distinct
142+
|> List.map(fun ns->{ Ident= ns; Location= x.RangeAlternate}))
143+
144+
letfilter list:OpenStatement list=
145+
let recfilterInner acc(list:OpenStatement list)(seenOpenStatements:OpenStatement list)=
146+
147+
letnotUsed(os:OpenStatement)=
148+
not(namespacesInUse|> List.exists(fun nsu-> rangeContainsRange os.ModuleRange nsu.Location&& os.Names|> Set.contains nsu.Ident))
149+
|| seenOpenStatements|> List.contains os
150+
129151
match listwith
130-
|(ns, range):: xswhenns|> Set.forallnotUsed->
131-
filterInner((ns, range):: acc) xs(seenNamespaces|> Set.union ns)
132-
|(ns,_):: xs->
133-
filterInner acc xs(seenNamespaces|> Set.union ns)
152+
|os:: xswhen notUsed os->
153+
filterInner(os:: acc) xs(os:: seenOpenStatements)
154+
|os:: xs->
155+
filterInner acc xs(os:: seenOpenStatements)
134156
|[]-> List.rev acc
135-
filterInner[] list Set.empty
157+
158+
filterInner[] list[]
136159

137-
letopenStatements= getOpenStatements parsedInput
138-
openStatements|> filter|> List.map snd
160+
parsedInput|> getOpenStatements|> filter|> List.map(fun os-> os.Range)
139161

140162
[<DiagnosticAnalyzer(FSharpConstants.FSharpLanguageName)>]
141163
typeinternalUnusedOpensDiagnosticAnalyzer()=
@@ -158,7 +180,7 @@ type internal UnusedOpensDiagnosticAnalyzer() =
158180
override__.SupportedDiagnostics= ImmutableArray.Create Descriptor
159181
overridethis.AnalyzeSyntaxAsync(_,_)= Task.FromResult ImmutableArray<Diagnostic>.Empty
160182

161-
static memberGetUnusedOpenRanges(document:Document,options,checker:FSharpChecker)=
183+
static memberGetUnusedOpenRanges(document:Document,options,checker:FSharpChecker):Async<Option<range list>>=
162184
asyncMaybe{
163185
do! Option.guard Settings.CodeFixes.UnusedOpens
164186
let!sourceText= document.GetTextAsync()
@@ -178,10 +200,10 @@ type internal UnusedOpensDiagnosticAnalyzer() =
178200

179201
return
180202
unusedOpens
181-
|> List.map(funm->
203+
|> List.map(funrange->
182204
Diagnostic.Create(
183205
Descriptor,
184-
RoslynHelpers.RangeToLocation(m, sourceText, document.FilePath)))
206+
RoslynHelpers.RangeToLocation(range, sourceText, document.FilePath)))
185207
|> Seq.toImmutableArray
186208
}
187209
|> Async.map(Option.defaultValue ImmutableArray.Empty)

0 commit comments

Comments
 (0)

[8]ページ先頭

©2009-2025 Movatter.jp