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 a41b15a78ac..b89cf11dc7e 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), [PR #19867](https://github.com/dotnet/fsharp/pull/19867))
 * Fix internal error (FS0193) when calling an indexed property setter with a named argument that matches an indexer parameter. ([Issue #16034](https://github.com/dotnet/fsharp/issues/16034), [PR #19851](https://github.com/dotnet/fsharp/pull/19851))
 * Fix missing FS1182 ("unused binding") warning for unused `let` function bindings inside class types. ([Issue #13849](https://github.com/dotnet/fsharp/issues/13849), [PR #19805](https://github.com/dotnet/fsharp/pull/19805))
 * Fix inner mutually-recursive `let rec ... and ...` functions under `--realsig+` not being lifted to top-level static methods (TLR), causing `FSharpFunc` closure allocations and loss of `tail.` opcodes — the large struct-mutual-recursion perf regression reported in [Issue #17607](https://github.com/dotnet/fsharp/issues/17607). ([PR #19882](https://github.com/dotnet/fsharp/pull/19882))
diff --git a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs
index 054df3371fd..1b1590c19fb 100644
--- a/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs
+++ b/src/Compiler/TypedTree/TypedTreeOps.FreeVars.fs
@@ -1395,17 +1395,19 @@ 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 9742daf0bf3..8dae1b5f572 100644
--- a/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs
+++ b/tests/FSharp.Compiler.Service.Tests/TooltipTests.fs
@@ -892,3 +892,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:'"
+
+[<Fact>]
+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)
+
+[<Fact>]
+let ``Non-companion module keeps literal name`` () =
+    let remarks =
+        getFullNameRemarks """
+module TestNs
+module HelperModule =
+    let doSt{caret}uff () = ()
+"""
+    Assert.Contains("HelperModule.doStuff", remarks)
+
+[<Fact>]
+let ``ModuleSuffix attribute without companion type demangles`` () =
+    let remarks =
+        getFullNameRemarks """
+module TestNs
+[<CompilationRepresentation(CompilationRepresentationFlags.ModuleSuffix)>]
+module Foo =
+    let x{caret} = 1
+"""
+    Assert.Contains("Foo.x", remarks)
+    Assert.DoesNotContain("FooModule", remarks)
+
+[<Fact>]
+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)
+
+[<Fact>]
+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)
+
+
