From 132a3e687790a996c58c2966e0aa7d33b2cc69ee Mon Sep 17 00:00:00 2001 From: Copilot Date: Fri, 29 May 2026 18:21:28 +0200 Subject: [PATCH 1/4] RED: failing tooltip tests for #17335 companion module demangling Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../TooltipTests.fs | 67 +++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs b/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs index 2947e09f565..e26b8f162ee 100644 --- a/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs @@ -852,3 +852,70 @@ let inline fo{caret}o< ^T> (x: ^T) = x |> fun text -> // Type param appears in tooltip Assert.Contains("'T", text) + +let private getFullNameRemarks (source: string) = + let _mainDesc, _xml, remarks = + Checker.getTooltip source + |> assertAndExtractTooltip + match remarks with + | Some r -> r + | None -> failwith "Expected tooltip remarks containing 'Full name:'" + +[] +let ``Companion module tooltip shows demangled name`` () = + let remarks = + getFullNameRemarks """ +module TestNs +type MyType = { F: int } +module MyType = + let func1{caret}23 x = x +""" + Assert.Contains("MyType.func123", remarks) + Assert.DoesNotContain("MyTypeModule", remarks) + +[] +let ``Non-companion module keeps literal name`` () = + let remarks = + getFullNameRemarks """ +module TestNs +module HelperModule = + let doSt{caret}uff () = () +""" + Assert.Contains("HelperModule.doStuff", remarks) + +[] +let ``ModuleSuffix attribute without companion type demangles`` () = + let remarks = + getFullNameRemarks """ +module TestNs +[] +module Foo = + let {caret}x = 1 +""" + Assert.Contains("Foo.x", remarks) + Assert.DoesNotContain("FooModule", remarks) + +[] +let ``Nested companion module demangled`` () = + let remarks = + getFullNameRemarks """ +module TestNs +module Outer = + type Inner = { v: int } + module Inner = + let hel{caret}per x = x +""" + Assert.Contains("Outer.Inner.helper", remarks) + Assert.DoesNotContain("InnerModule", remarks) + +[] +let ``List dot map tooltip shows List not ListModule`` () = + let remarks = + getFullNameRemarks """ +module TestNs +let _ = List.m{caret}ap id [1] +""" + Assert.Contains("List.map", remarks) + Assert.DoesNotContain("ListModule", remarks) + + From 4a9cac7a369f2dd49c294714f4feeb80cab33dae Mon Sep 17 00:00:00 2001 From: Copilot Date: Fri, 29 May 2026 18:48:54 +0200 Subject: [PATCH 2/4] GREEN: demangle VRefLocal parent path in tooltip Full name Routes the VRefLocal branch of fullNameOfParentOfValRef[AsLayout] through fullNameOfEntityRef[AsLayout] using TryDeclaringEntity. This reuses the existing entity-walking helper that calls DemangledModuleOrNamespaceName, so companion modules (FSharpModuleWithSuffix) lose their 'Module' suffix in the 'Full name:' tooltip, matching the VRefNonLocal branch behavior. Fixes #17335. Also corrects the caret placement in the 'ModuleSuffix attribute without companion type demangles' test (added in Sprint 01) so that the resolve position lands on the identifier 'x' rather than the preceding space. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../TypedTree/TypedTreeOps.FreeVars.fs | 18 ++++++++++++------ .../TooltipTests.fs | 2 +- 2 files changed, 13 insertions(+), 7 deletions(-) diff --git a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs index 054df3371fd..6ca9f965344 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs @@ -1395,17 +1395,23 @@ module internal MemberRepresentation = let fullNameOfParentOfValRef vref = match vref with | VRefLocal x -> - match x.PublicPath with - | None -> ValueNone - | Some(ValPubPath(pp, _)) -> ValueSome(fullNameOfPubPath pp) + match x.PublicPath, x.TryDeclaringEntity with + | None, _ -> ValueNone + | Some _, Parent eref -> + ValueSome(fullNameOfEntityRef (fun (e: EntityRef) -> e.DemangledModuleOrNamespaceName) eref) + | Some(ValPubPath(pp, _)), ParentNone -> + ValueSome(fullNameOfPubPath pp) | VRefNonLocal nlr -> ValueSome(fullNameOfEntityRef (fun (x: EntityRef) -> x.DemangledModuleOrNamespaceName) nlr.EnclosingEntity) let fullNameOfParentOfValRefAsLayout vref = match vref with | VRefLocal x -> - match x.PublicPath with - | None -> ValueNone - | Some(ValPubPath(pp, _)) -> ValueSome(fullNameOfPubPathAsLayout pp) + match x.PublicPath, x.TryDeclaringEntity with + | None, _ -> ValueNone + | Some _, Parent eref -> + ValueSome(fullNameOfEntityRefAsLayout (fun (e: EntityRef) -> e.DemangledModuleOrNamespaceName) eref) + | Some(ValPubPath(pp, _)), ParentNone -> + ValueSome(fullNameOfPubPathAsLayout pp) | VRefNonLocal nlr -> ValueSome(fullNameOfEntityRefAsLayout (fun (x: EntityRef) -> x.DemangledModuleOrNamespaceName) nlr.EnclosingEntity) diff --git a/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs b/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs index e26b8f162ee..2e7ff1e6bf2 100644 --- a/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs +++ b/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs @@ -890,7 +890,7 @@ let ``ModuleSuffix attribute without companion type demangles`` () = module TestNs [] module Foo = - let {caret}x = 1 + let x{caret} = 1 """ Assert.Contains("Foo.x", remarks) Assert.DoesNotContain("FooModule", remarks) From 6a1d9753b22fe09b0823772d5c9afa093f1e85d9 Mon Sep 17 00:00:00 2001 From: Copilot Date: Fri, 29 May 2026 19:20:04 +0200 Subject: [PATCH 3/4] REFACTOR: format + release note for tooltip demangling fix (#17335) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- .../.FSharp.Compiler.Service/11.0.100.md | 1 + src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs | 12 ++++-------- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 43601b6e34c..2644021257b 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -1,5 +1,6 @@ ### Fixed +* Tooltip "Full name" now shows demangled companion module names (e.g. `MyType.func` instead of `MyTypeModule.func`). ([Issue #17335](https://github.com/dotnet/fsharp/issues/17335)) * Reject non-function bindings for single-case and partial active pattern names with FS1209, matching the existing multi-case behavior. ([PR #19763](https://github.com/dotnet/fsharp/pull/19763)) * Fix FS0421 "The address of the variable cannot be used at this point" incorrectly raised for the discard pattern `let _ = &expr` when `let x = &expr` compiles. ([Issue #18841](https://github.com/dotnet/fsharp/issues/18841), [PR #19811](https://github.com/dotnet/fsharp/pull/19811)) * Honor `--nowarn` and `--warnaserror` for warnings emitted during command-line option parsing ([Issue #19576](https://github.com/dotnet/fsharp/issues/19576), [PR #19776](https://github.com/dotnet/fsharp/pull/19776)) diff --git a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs index 6ca9f965344..1b1590c19fb 100644 --- a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs +++ b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs @@ -1397,10 +1397,8 @@ module internal MemberRepresentation = | VRefLocal x -> match x.PublicPath, x.TryDeclaringEntity with | None, _ -> ValueNone - | Some _, Parent eref -> - ValueSome(fullNameOfEntityRef (fun (e: EntityRef) -> e.DemangledModuleOrNamespaceName) eref) - | Some(ValPubPath(pp, _)), ParentNone -> - ValueSome(fullNameOfPubPath pp) + | Some _, Parent eref -> ValueSome(fullNameOfEntityRef (fun (e: EntityRef) -> e.DemangledModuleOrNamespaceName) eref) + | Some(ValPubPath(pp, _)), ParentNone -> ValueSome(fullNameOfPubPath pp) | VRefNonLocal nlr -> ValueSome(fullNameOfEntityRef (fun (x: EntityRef) -> x.DemangledModuleOrNamespaceName) nlr.EnclosingEntity) let fullNameOfParentOfValRefAsLayout vref = @@ -1408,10 +1406,8 @@ module internal MemberRepresentation = | VRefLocal x -> match x.PublicPath, x.TryDeclaringEntity with | None, _ -> ValueNone - | Some _, Parent eref -> - ValueSome(fullNameOfEntityRefAsLayout (fun (e: EntityRef) -> e.DemangledModuleOrNamespaceName) eref) - | Some(ValPubPath(pp, _)), ParentNone -> - ValueSome(fullNameOfPubPathAsLayout pp) + | Some _, Parent eref -> ValueSome(fullNameOfEntityRefAsLayout (fun (e: EntityRef) -> e.DemangledModuleOrNamespaceName) eref) + | Some(ValPubPath(pp, _)), ParentNone -> ValueSome(fullNameOfPubPathAsLayout pp) | VRefNonLocal nlr -> ValueSome(fullNameOfEntityRefAsLayout (fun (x: EntityRef) -> x.DemangledModuleOrNamespaceName) nlr.EnclosingEntity) From 723889334611ebaecf70c4bdeea84983c3830cbc Mon Sep 17 00:00:00 2001 From: Copilot Date: Fri, 29 May 2026 22:04:43 +0200 Subject: [PATCH 4/4] Update release notes with PR link (#19867) Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- docs/release-notes/.FSharp.Compiler.Service/11.0.100.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md index 2644021257b..877d4213347 100644 --- a/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md +++ b/docs/release-notes/.FSharp.Compiler.Service/11.0.100.md @@ -1,6 +1,6 @@ ### Fixed -* Tooltip "Full name" now shows demangled companion module names (e.g. `MyType.func` instead of `MyTypeModule.func`). ([Issue #17335](https://github.com/dotnet/fsharp/issues/17335)) +* Tooltip "Full name" now shows demangled companion module names (e.g. `MyType.func` instead of `MyTypeModule.func`). ([Issue #17335](https://github.com/dotnet/fsharp/issues/17335), [PR #19867](https://github.com/dotnet/fsharp/pull/19867)) * Reject non-function bindings for single-case and partial active pattern names with FS1209, matching the existing multi-case behavior. ([PR #19763](https://github.com/dotnet/fsharp/pull/19763)) * Fix FS0421 "The address of the variable cannot be used at this point" incorrectly raised for the discard pattern `let _ = &expr` when `let x = &expr` compiles. ([Issue #18841](https://github.com/dotnet/fsharp/issues/18841), [PR #19811](https://github.com/dotnet/fsharp/pull/19811)) * Honor `--nowarn` and `--warnaserror` for warnings emitted during command-line option parsing ([Issue #19576](https://github.com/dotnet/fsharp/issues/19576), [PR #19776](https://github.com/dotnet/fsharp/pull/19776))