From d48da25976ae5406eca754cb74ade7eb8f921759 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 24 May 2019 17:16:46 +0300 Subject: [PATCH 1/2] Fix unused opens false positive for record fields --- src/fsharp/service/ServiceAnalysis.fs | 9 +++++++++ tests/service/ProjectAnalysisTests.fs | 8 ++++++++ 2 files changed, 17 insertions(+) diff --git a/src/fsharp/service/ServiceAnalysis.fs b/src/fsharp/service/ServiceAnalysis.fs index f66d372bc28..831dcc7d828 100644 --- a/src/fsharp/service/ServiceAnalysis.fs +++ b/src/fsharp/service/ServiceAnalysis.fs @@ -99,17 +99,26 @@ 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 -> + // 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) From 237e587380716e5ab7dd092d0c3b88a5116cb126 Mon Sep 17 00:00:00 2001 From: Eugene Auduchinok Date: Fri, 24 May 2019 17:27:39 +0300 Subject: [PATCH 2/2] Add record check --- src/fsharp/service/ServiceAnalysis.fs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/fsharp/service/ServiceAnalysis.fs b/src/fsharp/service/ServiceAnalysis.fs index 831dcc7d828..e4f942b657a 100644 --- a/src/fsharp/service/ServiceAnalysis.fs +++ b/src/fsharp/service/ServiceAnalysis.fs @@ -115,7 +115,8 @@ module UnusedOpens = | :? FSharpUnionCase when su.IsFromDefinition -> false - | :? FSharpField -> + | :? FSharpField as field when + field.DeclaringEntity.IsSome && field.DeclaringEntity.Value.IsFSharpRecord -> // Record fields are used in name resolution true