@@ -9,10 +9,14 @@ open Microsoft.FSharp.Compiler.Range
99module UnusedOpens =
1010open Microsoft.FSharp .Compiler .PrettyNaming
1111
12+ type Module =
13+ { Entity: FSharpEntity
14+ IsNestedAutoOpen: bool }
15+
1216/// Represents single open statement.
1317type OpenStatement =
1418{ /// All modules which this open declaration effectively opens, including all auto open ones, recursively.
15- Modules: FSharpEntity list
19+ Modules: Module list
1620/// Range of open statement itself.
1721 Range: range
1822/// Scope on which this open declaration is applied.
@@ -21,7 +25,7 @@ module UnusedOpens =
2125 IsGlobal: bool }
2226
2327member this.AllChildSymbols =
24- seq { for modulin this.Modulesdo
28+ seq { for modulin this.Modules|> List.map ( fun x -> x.Entity ) do
2529for entin modul.NestedEntitiesdo
2630yield ent:> FSharpSymbol
2731
@@ -40,19 +44,19 @@ module UnusedOpens =
4044yield upcast apCase
4145} |> Seq.cache
4246
43- let rec getModuleAndItsAutoOpens ( modul : FSharpEntity ) =
44- [ yield modul
47+ let rec getModuleAndItsAutoOpens ( isNestedAutoOpen : bool ) ( modul : FSharpEntity ) =
48+ [ yield { Entity = modul; IsNestedAutoOpen = isNestedAutoOpen }
4549for entin modul.NestedEntitiesdo
4650if ent.IsFSharpModule&& Symbol.hasAttribute< AutoOpenAttribute> ent.Attributesthen
47- yield ! getModuleAndItsAutoOpens ent]
51+ yield ! getModuleAndItsAutoOpenstrue ent]
4852
4953let getOpenStatements ( openDeclarations : FSharpOpenDeclaration list ) : OpenStatement list =
5054 openDeclarations
5155|> List.filter( fun x -> not x.IsOwnNamespace)
5256|> List.choose( fun openDecl ->
5357match openDecl.LongId, openDecl.Rangewith
5458| firstId:: _, Some range->
55- Some{ Modules= openDecl.Modules|> List.collect getModuleAndItsAutoOpens
59+ Some{ Modules= openDecl.Modules|> List.collect( getModuleAndItsAutoOpensfalse )
5660 Range= range
5761 AppliedScope= openDecl.AppliedScope
5862 IsGlobal= firstId.idText= MangledGlobalName}
@@ -97,7 +101,12 @@ module UnusedOpens =
97101// if such open statement has already been marked as used in this or outer module, we skip it
98102// (that is, do not mark as used so far)
99103 rangeContainsRange seenNs.AppliedScope openStatement.AppliedScope&&
100- openStatement.Modules|> List.exists( fun x -> seenNs.Modules|> List.exists( fun s -> s.IsEffectivelySameAs x)))
104+ openStatement.Modules
105+ |> List.exists( fun x ->
106+ // do not check if any of auto open nested modules has already been seen,
107+ // current open statement should be seen itself or as an auto open module of its outer module.
108+ not x.IsNestedAutoOpen&&
109+ seenNs.Modules|> List.exists( fun s -> s.Entity.IsEffectivelySameAs x.Entity)))
101110not alreadySeen
102111
103112match openStatementswith