Skip to content
Draft
7 changes: 6 additions & 1 deletion src/Compiler/Checking/NicePrint.fs
Original file line number Diff line number Diff line change
Expand Up @@ -2028,6 +2028,7 @@ module TastDefinitionPrinting =
GetIntrinsicConstructorInfosOfType infoReader m ty
|> List.filter (fun minfo -> IsMethInfoAccessible amap m ad minfo && not minfo.IsClassConstructor && shouldShow minfo.ArbitraryValRef)

// Get base interfaces (either direct or all, depending on settings)
let iimpls =
if suppressInheritanceAndInterfacesForTyInSimplifiedDisplays g amap m ty then
[]
Expand All @@ -2036,7 +2037,11 @@ module TastDefinitionPrinting =
|> List.filter (fun (_, compgen, _) -> not compgen)
|> List.map p13
else
GetImmediateInterfacesOfType SkipUnrefInterfaces.Yes g amap m ty
// Use immediate interfaces when showOnlyDirectBaseTypes=true, otherwise show all interfaces
if denv.showOnlyDirectBaseTypes then
GetImmediateInterfacesOfType SkipUnrefInterfaces.Yes g amap m ty
else
AllInterfacesOfType g amap m AllowMultiIntfInstantiations.Yes ty

let iimplsLs =
iimpls
Expand Down
4 changes: 3 additions & 1 deletion src/Compiler/Service/ServiceDeclarationLists.fs
Original file line number Diff line number Diff line change
Expand Up @@ -384,7 +384,9 @@ module DeclarationListHelpers =
// tooltips are space-constrained, so don't include xml doc comments
// on types/members. The doc comments for the actual member will still
// be shown in the tip.
showDocumentation = false }
showDocumentation = false
// only show direct base types in tooltips
showOnlyDirectBaseTypes = true }
let layout = NicePrint.layoutTyconDefn denv infoReader ad m (* width *) tcref.Deref
let layout = PrintUtilities.squashToWidth width layout
let remarks = OutputFullName displayFullName pubpathOfTyconRef fullDisplayTextOfTyconRefAsLayout tcref
Expand Down
5 changes: 4 additions & 1 deletion src/Compiler/TypedTree/TypedTreeOps.fs
Original file line number Diff line number Diff line change
Expand Up @@ -3173,7 +3173,7 @@
| Suffix

[<NoEquality; NoComparison>]
type DisplayEnv =

Check failure on line 3176 in src/Compiler/TypedTree/TypedTreeOps.fs

View workflow job for this annotation

GitHub Actions / copilot

The type definitions for type 'DisplayEnv' in the signature and implementation are not compatible because the order of the fields is different in the signature and implementation
{ includeStaticParametersInTypeNames: bool
openTopPathsSorted: InterruptibleLazy<string list list>
openTopPathsRaw: string list list
Expand All @@ -3193,13 +3193,14 @@
showCsharpCodeAnalysisAttributes: bool
showOverrides: bool
showStaticallyResolvedTyparAnnotations: bool
showNullnessAnnotations: bool option

Check failure on line 3196 in src/Compiler/TypedTree/TypedTreeOps.fs

View workflow job for this annotation

GitHub Actions / copilot

The module contains the field� showNullnessAnnotations: bool option �but its signature specifies� showOnlyDirectBaseTypes: bool �The names differ
abbreviateAdditionalConstraints: bool
showTyparDefaultConstraints: bool
showDocumentation: bool
shrinkOverloads: bool
printVerboseSignatures: bool
escapeKeywordNames: bool
showOnlyDirectBaseTypes: bool
g: TcGlobals
contextAccessibility: Accessibility
generatedValueLayout : Val -> Layout option
Expand Down Expand Up @@ -3238,6 +3239,7 @@
shrinkOverloads = true
printVerboseSignatures = false
escapeKeywordNames = false
showOnlyDirectBaseTypes = false
g = tcGlobals
contextAccessibility = taccessPublic
generatedValueLayout = (fun _ -> None)
Expand Down Expand Up @@ -3267,7 +3269,8 @@
showDocumentation = true
shrinkOverloads = false
escapeKeywordNames = true
includeStaticParametersInTypeNames = true }
includeStaticParametersInTypeNames = true
showOnlyDirectBaseTypes = false }
denv.SetOpenPaths
[ FSharpLib.RootPath
FSharpLib.CorePath
Expand Down
1 change: 1 addition & 0 deletions src/Compiler/TypedTree/TypedTreeOps.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -1084,6 +1084,7 @@ type DisplayEnv =
showCsharpCodeAnalysisAttributes: bool
showOverrides: bool
showStaticallyResolvedTyparAnnotations: bool
showOnlyDirectBaseTypes: bool
showNullnessAnnotations: bool option
abbreviateAdditionalConstraints: bool
showTyparDefaultConstraints: bool
Expand Down
104 changes: 103 additions & 1 deletion tests/FSharp.Compiler.Service.Tests/TooltipTests.fs
Original file line number Diff line number Diff line change
Expand Up @@ -522,4 +522,106 @@ open System
let doIt(myAction : Action<int>) = myAc{caret}tion.Invoke(42)
"""
|> assertAndGetSingleToolTipText
|> Assert.shouldBeEquivalentTo ("""val myAction: Action<int>""" |> normalize)
|> Assert.shouldBeEquivalentTo ("""val myAction: Action<int>""" |> normalize)

// Tests for direct interfaces in tooltips
[<Fact>]
let ``Tooltip for class with multiple direct interfaces shows all direct interfaces`` () =
let source = """
module DirectInterfaces

// Define multiple interfaces
type IA =
abstract DoA: unit -> unit

type IB =
abstract DoB: unit -> unit

// Class implementing multiple interfaces
type ClassWithMultipleInterfaces() =
interface IA with
member _.DoA() = ()
interface IB with
member _.DoB() = ()

// Create an instance
let obj = ClassWithMultipleInterfaces()
"""
let checkResults = getCheckResults source Array.empty
let tooltip = checkResults.GetToolTip(12, 30, "type ClassWithMultipleInterfaces() =", [ "ClassWithMultipleInterfaces" ], FSharpTokenTag.Identifier)
let tooltipText = tooltip |> assertAndGetSingleToolTipText

// Verify both direct interfaces are shown
Assert.contains "inherit IA" tooltipText
Assert.contains "inherit IB" tooltipText

[<Fact>]
let ``Tooltip for class implementing interface chain shows only direct interface`` () =
let source = """
module InterfaceChain

// Define chained interfaces
type IX =
abstract DoX: unit -> unit

type IY =
inherit IX
abstract DoY: unit -> unit

// Class implementing the most derived interface
type ClassWithChainedInterface() =
interface IY with
member _.DoY() = ()
member _.DoX() = ()

// Create an instance
let obj = ClassWithChainedInterface()
"""
let checkResults = getCheckResults source Array.empty
let tooltip = checkResults.GetToolTip(12, 31, "type ClassWithChainedInterface() =", [ "ClassWithChainedInterface" ], FSharpTokenTag.Identifier)
let tooltipText = tooltip |> assertAndGetSingleToolTipText

// Verify only direct interface is shown
Assert.contains "inherit IY" tooltipText
Assert.doesNotContain "inherit IX" tooltipText

[<Fact>]
let ``Tooltip for class with combined interface hierarchy shows only direct interfaces`` () =
let source = """
module CombinedHierarchy

// Base interfaces
type IBase1 =
abstract DoBase1: unit -> unit

type IBase2 =
abstract DoBase2: unit -> unit

// Derived interfaces
type IDerived1 =
inherit IBase1
abstract DoDerived1: unit -> unit

type IDerived2 =
inherit IBase2
abstract DoDerived2: unit -> unit

// Class implementing multiple interfaces, some in a chain
type ComplexClass() =
interface IDerived1 with
member _.DoDerived1() = ()
member _.DoBase1() = ()
interface IBase2 with
member _.DoBase2() = ()

// Create an instance
let obj = ComplexClass()
"""
let checkResults = getCheckResults source Array.empty
let tooltip = checkResults.GetToolTip(21, 19, "type ComplexClass() =", [ "ComplexClass" ], FSharpTokenTag.Identifier)
let tooltipText = tooltip |> assertAndGetSingleToolTipText

// Verify only direct interfaces are shown
Assert.contains "inherit IDerived1" tooltipText
Assert.contains "inherit IBase2" tooltipText
Assert.doesNotContain "inherit IBase1" tooltipText
Loading