Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions docs/release-notes/.FSharp.Compiler.Service/11.0.100.md
Original file line number Diff line number Diff line change
Expand Up @@ -180,6 +180,7 @@
* IL: hold custom attributes in fields rather than a union case ([PR #20287](https://github.com/dotnet/fsharp/pull/20287))
* IL: reuse the cached ILTypeRef in ILTypeInfo.FromType ([PR #20255](https://github.com/dotnet/fsharp/pull/20255))
* Name resolution: group C#-style extension members per `open` and extended type ([PR #20298](https://github.com/dotnet/fsharp/pull/20298))
* `NavigableContainer` publishes its `File` and `Container` cases, so a consumer of `NavigateTo.GetNavigableItems` can take a container apart and rebuild one — needed to cache navigable items outside the process that produced them. `Container` now carries a `[<Struct>]` record, `NavigableContainerInfo`, in place of its three-element tuple: the fields gain names at no cost, since a struct record is laid out inside the case exactly as the tuple was. ([PR #20529](https://github.com/dotnet/fsharp/pull/20529))

### Improved

Expand Down
53 changes: 43 additions & 10 deletions src/Compiler/Service/ServiceNavigation.fs
Original file line number Diff line number Diff line change
Expand Up @@ -731,28 +731,36 @@ type NavigableContainerType =
| Type
| Exception

type NavigableContainer =
[<Struct>]
type NavigableContainerInfo =
{
ContainerType: NavigableContainerType
NameParts: string list
Parent: NavigableContainer
}

and NavigableContainer =
| File of fileName: string
| Container of containerType: NavigableContainerType * nameParts: string list * parent: NavigableContainer
| Container of info: NavigableContainerInfo

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🤖 🕵️ [P2] Ordered-container comparisons now box each NavigableContainerInfo — 120 bytes per comparison at depth three, versus 0 with the previous representation.

open System
open System.Collections.Generic
open FSharp.Compiler.EditorServices

let chain file =
    [1..3] |> List.fold (fun parent _ ->
        NavigableContainer.Container {
            ContainerType = NavigableContainerType.Module
            NameParts = ["M"]
            Parent = parent
        }) (NavigableContainer.File file)

let a, b = chain "a.fs", chain "b.fs"
let comparer = Comparer<NavigableContainer>.Default
for _ in 1..10000 do comparer.Compare(a, b) |> ignore

let allocated =
    let before = GC.GetAllocatedBytesForCurrentThread()
    for _ in 1..100000 do comparer.Compare(a, b) |> ignore
    GC.GetAllocatedBytesForCurrentThread() - before
printfn "%d bytes" allocated // 12000000 bytes


member x.FullName =
let rec loop acc =
function
| File _ -> acc
| Container(_, nameParts, parent) -> loop (nameParts @ acc) parent
| Container info -> loop (info.NameParts @ acc) info.Parent

loop [] x |> textOfPath

member x.Type =
match x with
| File _ -> NavigableContainerType.File
| Container(t, _, _) -> t
| Container info -> info.ContainerType

member x.Name =
match x with
| File name -> name
| Container(nameParts = []) -> ""
| Container(nameParts = ns) -> ns |> List.last
| Container { NameParts = [] } -> ""
| Container { NameParts = ns } -> ns |> List.last

type NavigableItem =
{
Expand Down Expand Up @@ -813,13 +821,24 @@ module NavigateTo =
let addExceptionRepr exnRepr isSig container =
let (SynExceptionDefnRepr(_, SynUnionCase(ident = SynIdent(id, _)), _, _, _, _)) = exnRepr
addIdent NavigableItemKind.Exception id isSig container
NavigableContainer.Container(NavigableContainerType.Exception, [ id.idText ], container)

NavigableContainer.Container
{
ContainerType = NavigableContainerType.Exception
NameParts = [ id.idText ]
Parent = container
}

let addComponentInfo containerType kind (info: SynComponentInfo) isSig container =
let lid = info.LongIdent
addLongIdent kind lid isSig container

NavigableContainer.Container(containerType, pathOfLid lid, container)
NavigableContainer.Container
{
ContainerType = containerType
NameParts = pathOfLid lid
Parent = container
}

let addValSig kind synValSig isSig container =
let (SynValSig(ident = SynIdent(id, _))) = synValSig
Expand Down Expand Up @@ -897,7 +916,14 @@ module NavigateTo =
NavigableContainerType.Namespace

for decl in decls do
walkSynModuleSigDecl decl (NavigableContainer.Container(ctype, pathOfLid lid, container))
walkSynModuleSigDecl
decl
(NavigableContainer.Container
{
ContainerType = ctype
NameParts = pathOfLid lid
Parent = container
})

and walkSynModuleSigDecl (decl: SynModuleSigDecl) container =
match decl with
Expand Down Expand Up @@ -956,7 +982,14 @@ module NavigateTo =
NavigableContainerType.Namespace

for decl in decls do
walkSynModuleDecl decl (NavigableContainer.Container(ctype, pathOfLid lid, container))
walkSynModuleDecl
decl
(NavigableContainer.Container
{
ContainerType = ctype
NameParts = pathOfLid lid
Parent = container
})

and walkSynModuleDecl (decl: SynModuleDecl) container =
match decl with
Expand Down
20 changes: 18 additions & 2 deletions src/Compiler/Service/ServiceNavigation.fsi
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,24 @@ type NavigableContainerType =
| Type
| Exception

[<Sealed>]
type NavigableContainer =
/// What a container declared inside a file is, and what encloses it.
[<Struct>]
type NavigableContainerInfo =
{
/// The kind of container.
ContainerType: NavigableContainerType

/// The name of the container, one element per dotted part.
NameParts: string list

/// The container this one is declared in, ending at the file.
Parent: NavigableContainer
}

and NavigableContainer =
| File of fileName: string
| Container of info: NavigableContainerInfo

/// The kind of container.
member Type: NavigableContainerType

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3877,21 +3877,56 @@ FSharp.Compiler.EditorServices.ModuleKind: Int32 GetHashCode()
FSharp.Compiler.EditorServices.ModuleKind: Int32 GetHashCode(System.Collections.IEqualityComparer)
FSharp.Compiler.EditorServices.ModuleKind: System.String ToString()
FSharp.Compiler.EditorServices.ModuleKind: Void .ctor(Boolean, Boolean)
FSharp.Compiler.EditorServices.NavigableContainer+Container: FSharp.Compiler.EditorServices.NavigableContainerInfo get_info()
FSharp.Compiler.EditorServices.NavigableContainer+Container: FSharp.Compiler.EditorServices.NavigableContainerInfo info
FSharp.Compiler.EditorServices.NavigableContainer+File: System.String fileName
FSharp.Compiler.EditorServices.NavigableContainer+File: System.String get_fileName()
FSharp.Compiler.EditorServices.NavigableContainer+Tags: Int32 Container
FSharp.Compiler.EditorServices.NavigableContainer+Tags: Int32 File
FSharp.Compiler.EditorServices.NavigableContainer: Boolean Equals(FSharp.Compiler.EditorServices.NavigableContainer)
FSharp.Compiler.EditorServices.NavigableContainer: Boolean Equals(FSharp.Compiler.EditorServices.NavigableContainer, System.Collections.IEqualityComparer)
FSharp.Compiler.EditorServices.NavigableContainer: Boolean Equals(System.Object)
FSharp.Compiler.EditorServices.NavigableContainer: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
FSharp.Compiler.EditorServices.NavigableContainer: Boolean IsContainer
FSharp.Compiler.EditorServices.NavigableContainer: Boolean IsFile
FSharp.Compiler.EditorServices.NavigableContainer: Boolean get_IsContainer()
FSharp.Compiler.EditorServices.NavigableContainer: Boolean get_IsFile()
FSharp.Compiler.EditorServices.NavigableContainer: FSharp.Compiler.EditorServices.NavigableContainer NewContainer(FSharp.Compiler.EditorServices.NavigableContainerInfo)
FSharp.Compiler.EditorServices.NavigableContainer: FSharp.Compiler.EditorServices.NavigableContainer NewFile(System.String)
FSharp.Compiler.EditorServices.NavigableContainer: FSharp.Compiler.EditorServices.NavigableContainer+Container
FSharp.Compiler.EditorServices.NavigableContainer: FSharp.Compiler.EditorServices.NavigableContainer+File
FSharp.Compiler.EditorServices.NavigableContainer: FSharp.Compiler.EditorServices.NavigableContainer+Tags
FSharp.Compiler.EditorServices.NavigableContainer: FSharp.Compiler.EditorServices.NavigableContainerType Type
FSharp.Compiler.EditorServices.NavigableContainer: FSharp.Compiler.EditorServices.NavigableContainerType get_Type()
FSharp.Compiler.EditorServices.NavigableContainer: Int32 CompareTo(FSharp.Compiler.EditorServices.NavigableContainer)
FSharp.Compiler.EditorServices.NavigableContainer: Int32 CompareTo(System.Object)
FSharp.Compiler.EditorServices.NavigableContainer: Int32 CompareTo(System.Object, System.Collections.IComparer)
FSharp.Compiler.EditorServices.NavigableContainer: Int32 GetHashCode()
FSharp.Compiler.EditorServices.NavigableContainer: Int32 GetHashCode(System.Collections.IEqualityComparer)
FSharp.Compiler.EditorServices.NavigableContainer: Int32 Tag
FSharp.Compiler.EditorServices.NavigableContainer: Int32 get_Tag()
FSharp.Compiler.EditorServices.NavigableContainer: System.String FullName
FSharp.Compiler.EditorServices.NavigableContainer: System.String Name
FSharp.Compiler.EditorServices.NavigableContainer: System.String ToString()
FSharp.Compiler.EditorServices.NavigableContainer: System.String get_FullName()
FSharp.Compiler.EditorServices.NavigableContainer: System.String get_Name()
FSharp.Compiler.EditorServices.NavigableContainerInfo: Boolean Equals(FSharp.Compiler.EditorServices.NavigableContainerInfo)
FSharp.Compiler.EditorServices.NavigableContainerInfo: Boolean Equals(FSharp.Compiler.EditorServices.NavigableContainerInfo, System.Collections.IEqualityComparer)
FSharp.Compiler.EditorServices.NavigableContainerInfo: Boolean Equals(System.Object)
FSharp.Compiler.EditorServices.NavigableContainerInfo: Boolean Equals(System.Object, System.Collections.IEqualityComparer)
FSharp.Compiler.EditorServices.NavigableContainerInfo: FSharp.Compiler.EditorServices.NavigableContainer Parent
FSharp.Compiler.EditorServices.NavigableContainerInfo: FSharp.Compiler.EditorServices.NavigableContainer get_Parent()
FSharp.Compiler.EditorServices.NavigableContainerInfo: FSharp.Compiler.EditorServices.NavigableContainerType ContainerType
FSharp.Compiler.EditorServices.NavigableContainerInfo: FSharp.Compiler.EditorServices.NavigableContainerType get_ContainerType()
FSharp.Compiler.EditorServices.NavigableContainerInfo: Int32 CompareTo(FSharp.Compiler.EditorServices.NavigableContainerInfo)
FSharp.Compiler.EditorServices.NavigableContainerInfo: Int32 CompareTo(System.Object)
FSharp.Compiler.EditorServices.NavigableContainerInfo: Int32 CompareTo(System.Object, System.Collections.IComparer)
FSharp.Compiler.EditorServices.NavigableContainerInfo: Int32 GetHashCode()
FSharp.Compiler.EditorServices.NavigableContainerInfo: Int32 GetHashCode(System.Collections.IEqualityComparer)
FSharp.Compiler.EditorServices.NavigableContainerInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] NameParts
FSharp.Compiler.EditorServices.NavigableContainerInfo: Microsoft.FSharp.Collections.FSharpList`1[System.String] get_NameParts()
FSharp.Compiler.EditorServices.NavigableContainerInfo: System.String ToString()
FSharp.Compiler.EditorServices.NavigableContainerInfo: Void .ctor(FSharp.Compiler.EditorServices.NavigableContainerType, Microsoft.FSharp.Collections.FSharpList`1[System.String], FSharp.Compiler.EditorServices.NavigableContainer)
FSharp.Compiler.EditorServices.NavigableContainerType+Tags: Int32 Exception
FSharp.Compiler.EditorServices.NavigableContainerType+Tags: Int32 File
FSharp.Compiler.EditorServices.NavigableContainerType+Tags: Int32 Module
Expand Down
Loading