diff --git a/src/fsharp/service/ServiceAnalysis.fs b/src/fsharp/service/ServiceAnalysis.fs index f66d372bc28..e4f942b657a 100644 --- a/src/fsharp/service/ServiceAnalysis.fs +++ b/src/fsharp/service/ServiceAnalysis.fs @@ -99,17 +99,27 @@ module UnusedOpens = | :? FSharpMemberOrFunctionOrValue as fv when fv.IsExtensionMember -> // Extension members should be taken into account even though they have a prefix (as they do most of the time) true + | :? FSharpMemberOrFunctionOrValue as fv when not fv.IsModuleValueOrMember -> // Local values can be ignored false + | :? FSharpMemberOrFunctionOrValue when su.IsFromDefinition -> // Value definitions should be ignored false + | :? FSharpGenericParameter -> // Generic parameters can be ignored, they never come into scope via 'open' false + | :? FSharpUnionCase when su.IsFromDefinition -> false + + | :? FSharpField as field when + field.DeclaringEntity.IsSome && field.DeclaringEntity.Value.IsFSharpRecord -> + // Record fields are used in name resolution + true + | _ -> // For the rest of symbols we pick only those which are the first part of a long ident, because it's they which are // contained in opened namespaces / modules. For example, we pick `IO` from long ident `IO.File.OpenWrite` because diff --git a/tests/service/ProjectAnalysisTests.fs b/tests/service/ProjectAnalysisTests.fs index 08f19cbe708..9dca0cd56f6 100644 --- a/tests/service/ProjectAnalysisTests.fs +++ b/tests/service/ProjectAnalysisTests.fs @@ -5523,6 +5523,14 @@ type UseTheThings(i:int) = member x.UseSomeUsedModuleContainingActivePattern(ActivePattern g) = g member x.UseSomeUsedModuleContainingExtensionMember() = (3).Q member x.UseSomeUsedModuleContainingUnion() = A + +module M1 = + type R = { Field: int } + +module M2 = + open M1 + + let foo x = x.Field """ let fileSource1 = FSharp.Compiler.Text.SourceText.ofString fileSource1Text File.WriteAllText(fileName1, fileSource1Text)