diff --git a/src/Compiler/Checking/CheckDeclarations.fs b/src/Compiler/Checking/CheckDeclarations.fs index f425f49daf..3d80f056de 100644 --- a/src/Compiler/Checking/CheckDeclarations.fs +++ b/src/Compiler/Checking/CheckDeclarations.fs @@ -4418,7 +4418,7 @@ module TcDeclarations = // Only the keep the field-targeted attributes let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> true | _ -> false) let mLetPortion = synExpr.Range - let fldId = ident (CompilerGeneratedName id.idText, mLetPortion) + let fldId = ident (CompilerGeneratedName id.idText, mLetPortion.MakeSynthetic()) let headPat = SynPat.LongIdent (SynLongIdent([fldId], [], [None]), None, Some noInferredTypars, SynArgPats.Pats [], None, mLetPortion) let retInfo = match tyOpt with None -> None | Some ty -> Some (None, SynReturnInfo((ty, SynInfo.unnamedRetVal), ty.Range)) let isMutable = @@ -4446,7 +4446,7 @@ module TcDeclarations = let mMemberPortion = id.idRange // Only the keep the non-field-targeted attributes let attribs = attribs |> List.filter (fun a -> match a.Target with Some t when t.idText = "field" -> false | _ -> true) - let fldId = ident (CompilerGeneratedName id.idText, mMemberPortion) + let fldId = ident (CompilerGeneratedName id.idText, mMemberPortion.MakeSynthetic()) let headPatIds = if isStatic then [id] else [ident ("__", mMemberPortion);id] let headPat = SynPat.LongIdent (SynLongIdent(headPatIds, [], List.replicate headPatIds.Length None), None, Some noInferredTypars, SynArgPats.Pats [], None, mMemberPortion) let memberFlags = { memberFlags with GetterOrSetterIsCompilerGenerated = true } @@ -4475,7 +4475,7 @@ module TcDeclarations = | SynMemberKind.PropertySet | SynMemberKind.PropertyGetSet -> let setter = - let vId = ident("v", mMemberPortion) + let vId = ident("v", mMemberPortion.MakeSynthetic()) let headPat = SynPat.LongIdent (SynLongIdent(headPatIds, [], List.replicate headPatIds.Length None), None, Some noInferredTypars, SynArgPats.Pats [mkSynPatVar None vId], None, mMemberPortion) let rhsExpr = mkSynAssign (SynExpr.Ident fldId) (SynExpr.Ident vId) let binding = mkSynBinding (xmlDoc, headPat) (setterAccess, false, false, mMemberPortion, DebugPointAtBinding.NoneAtInvisible, None, rhsExpr, rhsExpr.Range, [], [], Some memberFlagsForSet, SynBindingTrivia.Zero) diff --git a/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs b/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs index cd494f7e65..551bdf02ea 100644 --- a/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/ProjectAnalysisTests.fs @@ -3512,12 +3512,6 @@ let ``Test Project24 all symbols`` () = ("v", "file1", ((22, 17), (22, 18)), ["defn"], []); ("int", "file1", ((25, 21), (25, 24)), ["type"], ["abbrev"]); ("v", "file1", ((25, 18), (25, 19)), ["defn"], []); - ("``AutoPropGet@``", "file1", ((27, 15), (27, 26)), [], ["compgen"]); - ("``AutoPropGetSet@``", "file1", ((28, 15), (28, 29)), [], ["compgen"; "mutable"]) - ("v", "file1", ((28, 15), (28, 29)), ["defn"], []); - ("``StaticAutoPropGet@``", "file1", ((30, 22), (30, 39)), [], ["compgen"]); - ("``StaticAutoPropGetSet@``", "file1", ((31, 22), (31, 42)), [], - ["compgen"; "mutable"]); ("v", "file1", ((31, 22), (31, 42)), ["defn"], []); ("``.cctor``", "file1", ((4, 5), (4, 23)), ["defn"], ["member"]); ("TypeWithProperties", "file1", ((33, 9), (33, 27)), [], ["member"; "ctor"]); ("NameGetSet", "file1", ((33, 9), (33, 40)), [], ["member"; "prop"]); @@ -3614,12 +3608,6 @@ let ``Test symbol uses of properties with both getters and setters`` () = ("v", "file1", ((22, 17), (22, 18)), []); ("int", "file1", ((25, 21), (25, 24)), ["abbrev"]); ("v", "file1", ((25, 18), (25, 19)), []); - ("``AutoPropGet@``", "file1", ((27, 15), (27, 26)), ["compgen"]); - ("``AutoPropGetSet@``", "file1", ((28, 15), (28, 29)), ["compgen"; "mutable"]); - ("v", "file1", ((28, 15), (28, 29)), []); - ("``StaticAutoPropGet@``", "file1", ((30, 22), (30, 39)), ["compgen"]); - ("``StaticAutoPropGetSet@``", "file1", ((31, 22), (31, 42)), - ["compgen"; "mutable"]); ("v", "file1", ((31, 22), (31, 42)), []); ("``.cctor``", "file1", ((4, 5), (4, 23)), ["member"]); ("TypeWithProperties", "file1", ((33, 9), (33, 27)), ["member"; "ctor"]); ("NameGetSet", "file1", ((33, 9), (33, 40)), ["member"; "prop"]); diff --git a/tests/FSharp.Compiler.Service.Tests/Symbols.fs b/tests/FSharp.Compiler.Service.Tests/Symbols.fs index 3f4d4fcdbd..69bfb70519 100644 --- a/tests/FSharp.Compiler.Service.Tests/Symbols.fs +++ b/tests/FSharp.Compiler.Service.Tests/Symbols.fs @@ -634,18 +634,23 @@ type Foo = Assert.True(setMfv.CompiledName.StartsWith("set_")) | _ -> failwith $"Expected three symbols, got %A{symbols}" - [] - let ``AutoProperty with get, set has property symbol 02`` () = - let symbol = Checker.getSymbolUse """ + // https://github.com/dotnet/fsharp/issues/3939 + [] + let ``AutoProperty with get, set does not expose compiler-generated v symbol`` () = + let _, checkResults = getParseAndCheckResults """ namespace Foo type Foo = - member val AutoPropGetSet{caret} = 0 with get, set + member val AutoPropGetSet = 0 with get, set """ - // The setter should have a symbol for the generated parameter `v`. - let setVMfv = symbol |> chooseMemberOrFunctionOrValue - if Option.isNone setVMfv then - failwith "No generated v symbol for the setter was found" + let allSymbols = checkResults.GetAllUsesOfAllSymbolsInFile() + let allMfvs = allSymbols |> Seq.choose (fun su -> match su.Symbol with :? FSharpMemberOrFunctionOrValue as mfv -> Some mfv | _ -> None) |> Seq.toList + // The compiler-generated `v` setter parameter should NOT appear in symbol uses + let vSymbols = allMfvs |> List.filter (fun mfv -> mfv.DisplayName = "v") + Assert.True(vSymbols.IsEmpty, $"Compiler-generated 'v' symbol should not be exposed via GetAllUsesOfAllSymbolsInFile, but found {vSymbols.Length} occurrences") + // The compiler-generated backing field should also not appear + let backingFieldSymbols = allMfvs |> List.filter (fun mfv -> mfv.DisplayName.Contains("@")) + Assert.True(backingFieldSymbols.IsEmpty, $"Compiler-generated backing field should not appear, but found: {backingFieldSymbols |> List.map (fun m -> m.DisplayName)}") [] let ``Property symbol is resolved for property`` () =