dotnet / dotnet/roslyn

Object Browser / Class View: no way for a non-Roslyn language (F#) to draw its own project glyph

Open
#85,102 1 comment 0 reactions 0 assignees View on GitHub
Area-IDE
Dominant language
C#
Stars
20.7k
Forks
4.3k
PR merge metrics
PR metrics pending

Description

## Summary

I am adding Object Browser and Class View support to F# ([dotnet/fsharp#3512](https://github.com/dotnet/fsharp/issues/3512)), implementing `IVsSimpleLibrary2` / `IVsSimpleObjectList2` directly and modelling it on Roslyn's `src/VisualStudio/Core/Def/Library/**`.

Everything transfers except the project node's icon: there is no F# glyph reachable from that surface, so an F# project can only be drawn with another language's icon.

Filing here rather than on Developer Community because Roslyn owns the only managed implementation of this surface and the `Glyph` → image mapping around it; if the right fix lives in the VS SDK instead, I would appreciate a redirect.

## Why the icon cannot be supplied

`IVsSimpleObjectList2.GetDisplayData` communicates the icon as `VSTREEDISPLAYDATA.Image`, a `ushort` index into an image list. Roslyn deliberately passes `hImageList = 0` so the shell uses its default list ([`AbstractObjectList.GetDisplayData`](https://github.com/dotnet/roslyn/blob/main/src/VisualStudio/Core/Def/Library/AbstractObjectList.cs), *"allows the object browser to use the default image list with no DPI issues"*), and `ObjectListItem.GlyphIndex` is computed from `StandardGlyphGroup` + `StandardGlyphItem`.

That table has project glyphs for C#, VB, C++ and J#:

```
GlyphVBProject = 0xC2
GlyphCoolProject = 0xC4
GlyphCppProject = 0xC7
GlyphJSharpProject = 0xD3
```

but none for F# — `StandardGlyphGroup` lives in `Microsoft.VisualStudio.Language.Intellisense` and predates the language. I also checked `KnownMonikers` in `Microsoft.VisualStudio.ImageCatalog`: it has no `FSharp*` entry either, and there is no moniker → `HIMAGELIST` bridge in the SDK (`IVsUIShell5/6.CreateThemedImageList` only themes a list that already exists).

So `ProjectListItem`'s equivalent for F# has to choose between the C# icon and a generic one. Roslyn hits the same wall from the other side — `GlyphExtensions.GetStandardGlyphGroup` can map `Glyph.CSharpProject`/`Glyph.BasicProject`, and there is nothing it could map an F# project to.

## What I did instead

For project nodes I read the icon the project's own hierarchy already publishes to Solution Explorer, and hand the shell that image list rather than the default one:

```fsharp
hierarchy.GetProperty(VSITEMID_ROOT, __VSHPROPID.VSHPROPID_IconImgList, &imageList)
hierarchy.GetProperty(VSITEMID_ROOT, __VSHPROPID.VSHPROPID_IconIndex, &index)
// -> VSTREEDISPLAYDATA.hImageList / .Image
```

This works and is themed and DPI-correct, because the icon comes from the project system. It is a workaround though: it only covers nodes that map to an `IVsHierarchy`, and it opts out of the default-image-list guarantee the comment in `AbstractObjectList` is protecting.

## What would help

Either of these, in preference order:

1. **Expose the Object Browser / Class View library infrastructure through `Microsoft.CodeAnalysis.ExternalAccess.FSharp`.** `AbstractObjectBrowserLibraryManager`, `AbstractObjectList`, `ObjectListItem`, `NavInfoFactory` and friends are all `internal`, so a non-Roslyn language reimplements the entire COM surface — roughly 1.5k lines of `IVsSimpleObjectList2` plumbing that is not language-specific in any way. Sharing it would carry the glyph handling along with everything else, and is the same shape as the seam proposed in #85089.

2. **Add F# entries to the glyph path** — an `FSharpProject` moniker in the image catalog and a corresponding `Glyph`/`StandardGlyphGroup` value — so the default image list can represent an F# project at all.

Happy to do the work on either side; mainly looking for a decision on which direction is acceptable before writing PRs.

cc @tmat @davidwengier @vzarytovskii @T-Gro

Contributor guide

Open the contributing guide

Research direction

Start by reading Roslyn's src/VisualStudio/Core/Def/Library/AbstractObjectList.cs, ObjectListItem, GlyphExtensions.GetStandardGlyphGroup, and the Microsoft.CodeAnalysis.ExternalAccess.FSharp seam proposed in #85089. Compare the two requested directions—shared library infrastructure or F# glyph entries—and seek a maintainer decision before implementation; done means one accepted path is specified well enough for a PR.

Written by the indexing model from the issue text.

Assessment

Tech stack
csharp
Domain
developer-experience, tooling
Issue type
Feature
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.