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..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,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)) * 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 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 2947e09f565..2e7ff1e6bf2 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 x{caret} = 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) + +