Skip to content

Commit

Permalink
Merge pull request #9602 from drewnoakes/dep-tree-object-browser
Browse files Browse the repository at this point in the history
Support navigating to Object Browser from the Dependencies tree
  • Loading branch information
drewnoakes authored Dec 5, 2024
2 parents fa5feb1 + d2feb6e commit cd57e22
Show file tree
Hide file tree
Showing 20 changed files with 281 additions and 93 deletions.
1 change: 1 addition & 0 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,7 @@
<!-- 3rd party -->
<PackageVersion Include="Newtonsoft.Json" Version="13.0.3" />
<PackageVersion Include="IsExternalInit" Version="1.0.3" />
<PackageVersion Include="PolySharp" Version="1.15.0" />

<!-- Tests -->
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.5.0-preview-20221003-04" />
Expand Down
2 changes: 1 addition & 1 deletion eng/imports/HostAgnostic.props
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@

<!-- 3rd party -->
<PackageReference Include="Newtonsoft.Json" />
<PackageReference Include="IsExternalInit" PrivateAssets="all" />
<PackageReference Include="PolySharp" PrivateAssets="all" IncludeAssets="runtime; build; native; contentfiles; analyzers" />

<!-- Host-Agnostic Visual Studio -->
<PackageReference Include="Microsoft.VisualStudio.ImageCatalog" />
Expand Down
34 changes: 27 additions & 7 deletions src/Microsoft.VisualStudio.ProjectSystem.Managed.VS/Menus.vsct
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,19 @@
<Group guid="guidManagedProjectSystemCommandSet" id="DebugTargetMenuDebugFrameworkGroup" priority="0x0100">
<Parent guid="guidManagedProjectSystemCommandSet" id="DebugTargetMenuDebugFrameworkMenu"/>
</Group>
<!-- This is the ordering group. Handles ordering files. -->
<!-- Group added to transitive assembly references -->
<Group guid="guidSHLMainMenu" id="IDG_VS_CTXT_ITEM_OBJECTBROWSER" priority="0x0100">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_TRANSITIVE_ASSEMBLY_REFERENCE"/>
</Group>
<!-- Group added to transitive COM references -->
<Group guid="guidSHLMainMenu" id="IDG_VS_CTXT_ITEM_OBJECTBROWSER" priority="0x0100">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_COMREFERENCE"/>
</Group>
<!-- Group added to transitive project references -->
<Group guid="guidSHLMainMenu" id="IDG_VS_CTXT_ITEM_OBJECTBROWSER" priority="0x0100">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_PROJECTREFERENCE"/>
</Group>
<!-- This is the ordering group. Handles ordering files. -->
<Group guid="guidManagedProjectSystemOrderCommandSet" id="OrderingGroup" priority="0x100">
<Parent guid="guidSHLMainMenu" id="IDM_VS_CTXT_ITEMNODE" />
</Group>
Expand Down Expand Up @@ -202,33 +214,38 @@
</Button>
</Buttons>
</Commands>


<CommandPlacements>
<CommandPlacement guid="guidVSStd2K" id="ECMD_VIEWREFINOBJECTBROWSER" priority="0x0200">
<Parent guid="guidSHLMainMenu" id="IDG_VS_CTXT_ITEM_OBJECTBROWSER"/>
</CommandPlacement>
</CommandPlacements>

<KeyBindings>
<KeyBinding guid="guidManagedProjectSystemCommandSet" id="cmdidNavigateToProject" editor="guidSolutionExplorerToolWindow" key1="VK_F12"/>
</KeyBindings>

<Symbols>
<GuidSymbol name="guidSolutionExplorerToolWindow" value="{3AE79031-E1BC-11D0-8F78-00A0C9110057}" />

<!-- This is out managed package guid. -->
<!-- The .NET Project System package GUID. -->
<GuidSymbol name="PackageGuidString" value="{860A27C0-B665-47F3-BC12-637E16A1050A}" />

<!-- IDSymbol values should be spaced out, leaving space to add new values in future. -->

<GuidSymbol name="guidDebugTargetHandlerPackage" value="{6e87cfad-6c05-4adf-9cd7-3b7943875b7c}">
<IDSymbol name="DebugTargetMenuControllerGroup" value="0x1000" />
<IDSymbol name="DebugTargetMenuControllerFooterGroup" value="0x2000" />

</GuidSymbol>

<GuidSymbol name="guidManagedProjectSystemCommandSet" value="{568ABDF7-D522-474D-9EED-34B5E5095BA5}">
<!-- Note that these need room to grow hence they need to be spaced out-->
<IDSymbol name="cmdidProjectDebugger" value="0x0100" />
<IDSymbol name="cmdidGenerateNuGetPackageProjectContextMenu" value="0x2000" />
<IDSymbol name="cmdidGenerateNuGetPackageTopLevelBuild" value="0x2001" />
<IDSymbol name="cmdidNavigateToProject" value="0x2002" />
<IDSymbol name="DebugTargetMenuDebugFrameworkMenu" value="0x3000" />
<IDSymbol name="DebugTargetMenuDebugFrameworkGroup" value="0x3001" />
<IDSymbol name="cmdidDebugFrameworks" value="0x3050" /> <!--needs space to grow-->

<IDSymbol name="cmdidDebugFrameworks" value="0x3050" />
<IDSymbol name="NavigateGroup" value="0x4000" />
</GuidSymbol>

Expand All @@ -247,8 +264,11 @@
</GuidSymbol>

<GuidSymbol name="guidSHLMainMenu" value="{ 0xd309f791, 0x903f, 0x11d0, { 0x9e, 0xfc, 0x00, 0xa0, 0xc9, 0x11, 0x00, 0x4f } }">
<IDSymbol name="IDM_VS_CTXT_COMREFERENCE" value="0x04A5" />
<IDSymbol name="IDG_VS_CTXT_ITEM_OBJECTBROWSER" value="0x02F6" />
<IDSymbol name="IDM_VS_CTXT_PROJECTREFERENCE" value="0x04A7"/>
<IDSymbol name="IDM_VS_CTXT_SHAREDPROJECTREFERENCE" value="0x04A8" />
<IDSymbol name="IDM_VS_CTXT_TRANSITIVE_ASSEMBLY_REFERENCE" value="0x04B1" />
</GuidSymbol>

<GuidSymbol name="SlnExplorerGuid" value="{3AE79031-E1BC-11D0-8F78-00A0C9110057}" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@
<CreateVsixContainer>false</CreateVsixContainer>
<UseCodebase>false</UseCodebase>

<!-- Nuget -->
<!-- NuGet -->
<IsPackable>true</IsPackable>
<Description>Microsoft VisualStudio ProjectSystem for Managed Languages Project hosts that interact with VisualStudio interfaces.</Description>
<Summary>Microsoft VisualStudio Managed Project System VS Components</Summary>
Expand All @@ -29,6 +29,7 @@
<PackageReference Include="Microsoft.VisualStudio.HotReload.Components" />
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.Query" />
<PackageReference Include="Microsoft.VisualStudio.ProjectSystem.VS" />
<PackageReference Include="IsExternalInit" PrivateAssets="all" />
</ItemGroup>

<ItemGroup>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
// Licensed to the .NET Foundation under one or more agreements. The .NET Foundation licenses this file to you under the MIT license. See the LICENSE.md file in the project root for more information.

namespace Microsoft.VisualStudio.ProjectSystem.VS.Tree.Dependencies.AttachedCollections;

/// <summary>
/// Used by implementations of <see cref="IRelatableItem"/> that support opening in Visual Studio's Object Browser via their context menu.
/// </summary>
public interface IObjectBrowserItem : IRelatableItem
{
/// <summary>
/// Gets the absolute path to an assembly that should be opened in the Object Browser.
/// </summary>
string? AssemblyPath { get; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@

namespace Microsoft.VisualStudio.ProjectSystem.VS.Tree.Dependencies.AttachedCollections.Implementation
{
internal sealed class FrameworkReferenceAssemblyItem : RelatableItemBase
internal sealed class FrameworkReferenceAssemblyItem : RelatableItemBase, IObjectBrowserItem
{
private const int IDM_VS_CTXT_TRANSITIVE_ASSEMBLY_REFERENCE = 0x04B1;

private static readonly IContextMenuController s_defaultMenuController = new MenuController(VsMenus.guidSHLMainMenu, IDM_VS_CTXT_TRANSITIVE_ASSEMBLY_REFERENCE);
private static readonly IContextMenuController s_defaultMenuController = CreateContextMenuController(VsMenus.guidSHLMainMenu, IDM_VS_CTXT_TRANSITIVE_ASSEMBLY_REFERENCE);

public string AssemblyName { get; }
public string? Path { get; }
Expand All @@ -38,33 +38,33 @@ public FrameworkReferenceAssemblyItem(string assemblyName, string? path, string?

public override object? GetBrowseObject() => new BrowseObject(this);

private sealed class BrowseObject : LocalizableProperties
{
private readonly FrameworkReferenceAssemblyItem _item;
string? IObjectBrowserItem.AssemblyPath => GetAssemblyPath();

public BrowseObject(FrameworkReferenceAssemblyItem log) => _item = log;
private string? GetAssemblyPath() => Path is not null
? System.IO.Path.GetFullPath(System.IO.Path.Combine(Framework.Path, Path))
: null;

public override string GetComponentName() => _item.AssemblyName;
private sealed class BrowseObject(FrameworkReferenceAssemblyItem item) : LocalizableProperties
{
public override string GetComponentName() => item.AssemblyName;

public override string GetClassName() => VSResources.FrameworkAssemblyBrowseObjectClassName;

[BrowseObjectDisplayName(nameof(VSResources.FrameworkAssemblyAssemblyNameDisplayName))]
[BrowseObjectDescription(nameof(VSResources.FrameworkAssemblyAssemblyNameDescription))]
public string AssemblyName => _item.Text;
public string AssemblyName => item.Text;

[BrowseObjectDisplayName(nameof(VSResources.FrameworkAssemblyPathDisplayName))]
[BrowseObjectDescription(nameof(VSResources.FrameworkAssemblyPathDescription))]
public string Path => _item.Path is not null
? System.IO.Path.GetFullPath(System.IO.Path.Combine(_item.Framework.Path, _item.Path))
: "";
public string Path => item.GetAssemblyPath() ?? "";

[BrowseObjectDisplayName(nameof(VSResources.FrameworkAssemblyAssemblyVersionDisplayName))]
[BrowseObjectDescription(nameof(VSResources.FrameworkAssemblyAssemblyVersionDescription))]
public string AssemblyVersion => _item.AssemblyVersion ?? "";
public string AssemblyVersion => item.AssemblyVersion ?? "";

[BrowseObjectDisplayName(nameof(VSResources.FrameworkAssemblyFileVersionDisplayName))]
[BrowseObjectDescription(nameof(VSResources.FrameworkAssemblyFileVersionDescription))]
public string FileVersion => _item.FileVersion ?? "";
public string FileVersion => item.FileVersion ?? "";
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,39 +9,78 @@ namespace Microsoft.VisualStudio.ProjectSystem.VS.Tree.Dependencies.AttachedColl
{
public abstract partial class RelatableItemBase
{
internal sealed class MenuController : IContextMenuController
{
private readonly Guid _menuGuid;
private readonly int _menuId;
/// <summary>
/// Creates a <see cref="IContextMenuController"/> for use in overrides of <see cref="ContextMenuController"/>.
/// </summary>
public static IContextMenuController CreateContextMenuController(Guid menuGuid, int menuId) => new MenuController(menuGuid, menuId);

public MenuController(Guid menuGuid, int menuId)
{
_menuGuid = menuGuid;
_menuId = menuId;
}
internal sealed class MenuController(Guid menuGuid, int menuId) : IContextMenuController
{
public static ImmutableArray<IRelatableItem> CurrentItems { get; private set; } = [];

public bool ShowContextMenu(IEnumerable<object> items, Point location)
{
bool shouldShowMenu = items.All(item => item is IRelatableItem);
ImmutableArray<IRelatableItem>? relatableItems = GetItems();

if (relatableItems is null)
{
return false;
}

CurrentItems = relatableItems.Value;

try
{
return ShowContextMenu();
}
finally
{
CurrentItems = [];
}

if (shouldShowMenu)
ImmutableArray<IRelatableItem>? GetItems()
{
ImmutableArray<IRelatableItem>.Builder? builder = null;

foreach (object item in items)
{
if (item is IRelatableItem relatableItem)
{
builder ??= ImmutableArray.CreateBuilder<IRelatableItem>();
builder.Add(relatableItem);
}
else
{
return null;
}
}

if (builder is null)
{
return null;
}

return builder.ToImmutable();
}

bool ShowContextMenu()
{
if (Package.GetGlobalService(typeof(SVsUIShell)) is IVsUIShell shell)
{
Guid guidContextMenu = _menuGuid;
Guid guidContextMenu = menuGuid;

int result = shell.ShowContextMenu(
dwCompRole: 0,
rclsidActive: ref guidContextMenu,
nMenuId: _menuId,
pos: new[] { new POINTS { x = (short)location.X, y = (short)location.Y } },
nMenuId: menuId,
pos: [new POINTS { x = (short)location.X, y = (short)location.Y }],
pCmdTrgtActive: null);

return ErrorHandler.Succeeded(result);
}
}

return false;
return false;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ public abstract partial class RelatableItemBase : AttachedCollectionItemBase, IR
{
private const int IDM_VS_CTXT_DEPENDENCY_TRANSITIVE_ITEM = 0x04B0;

private static readonly IContextMenuController s_defaultMenuController = new MenuController(VsMenus.guidSHLMainMenu, IDM_VS_CTXT_DEPENDENCY_TRANSITIVE_ITEM);
private static readonly IContextMenuController s_defaultMenuController = CreateContextMenuController(VsMenus.guidSHLMainMenu, IDM_VS_CTXT_DEPENDENCY_TRANSITIVE_ITEM);

private AggregateContainsRelationCollection? _containsCollection;

Expand Down
Loading

0 comments on commit cd57e22

Please sign in to comment.