|
// 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 file in the project root for more information.
#nullable disable
using System;
using System.Collections.Immutable;
using System.Diagnostics;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.ErrorReporting;
using Microsoft.VisualStudio.LanguageServices.Implementation.F1Help;
using Microsoft.VisualStudio.LanguageServices.Implementation.Library.ObjectBrowser.Lists;
using Microsoft.VisualStudio.LanguageServices.Implementation.Library.VsNavInfo;
using Microsoft.VisualStudio.Shell;
using Microsoft.VisualStudio.Shell.Interop;
using Microsoft.VisualStudio.Utilities;
namespace Microsoft.VisualStudio.LanguageServices.Implementation.Library.ObjectBrowser;
internal class ObjectList : AbstractObjectList<AbstractObjectBrowserLibraryManager>
{
private readonly ObjectList _parentList;
private readonly uint _flags;
private readonly ImmutableArray<ObjectListItem> _items;
public ObjectList(
ObjectListKind kind,
uint flags,
AbstractObjectBrowserLibraryManager manager,
ImmutableArray<ObjectListItem> items)
: this(kind, flags, null, null, manager, items)
{
}
public ObjectList(
ObjectListKind kind,
uint flags,
ObjectList parentList,
ObjectListItem parentListItem,
AbstractObjectBrowserLibraryManager manager,
ImmutableArray<ObjectListItem> items)
: base(manager)
{
Kind = kind;
_flags = flags;
_parentList = parentList;
ParentListItem = parentListItem;
_items = items;
foreach (var item in _items)
{
item.SetParentList(this);
}
}
private bool IsClassView()
=> Helpers.IsClassView(_flags);
private ObjectListItem GetListItem(uint index)
{
var listItem = _items[(int)index];
this.LibraryManager.SetActiveListItem(listItem);
return listItem;
}
private string GetDisplayText(uint index, VSTREETEXTOPTIONS textOptions)
{
var listItem = GetListItem(index);
switch (textOptions)
{
case VSTREETEXTOPTIONS.TTO_SORTTEXT:
case VSTREETEXTOPTIONS.TTO_DISPLAYTEXT:
switch (Kind)
{
case ObjectListKind.BaseTypes:
case ObjectListKind.Hierarchy:
case ObjectListKind.Members:
case ObjectListKind.Namespaces:
case ObjectListKind.Projects:
case ObjectListKind.References:
case ObjectListKind.Types:
return listItem.DisplayText;
}
break;
}
return listItem.DisplayText;
}
protected override bool CanGoToSource(uint index, VSOBJGOTOSRCTYPE srcType)
{
if (srcType == VSOBJGOTOSRCTYPE.GS_DEFINITION)
{
if (GetListItem(index) is SymbolListItem symbolItem)
{
return symbolItem.SupportsGoToDefinition;
}
}
return false;
}
protected override bool TryGetCapabilities(out uint capabilities)
{
capabilities = (uint)_LIB_LISTCAPABILITIES2.LLC_ALLOWELEMENTSEARCH;
return true;
}
private bool TryGetListType(out uint categoryField)
{
switch (Kind)
{
case ObjectListKind.BaseTypes:
categoryField = (uint)_LIB_LISTTYPE.LLT_CLASSES | (uint)_LIB_LISTTYPE.LLT_MEMBERS;
return true;
case ObjectListKind.Hierarchy:
var parentKind = this.ParentKind;
categoryField = parentKind is ObjectListKind.Types or ObjectListKind.BaseTypes
? (uint)_LIB_LISTTYPE.LLT_CLASSES
: (uint)_LIB_LISTTYPE.LLT_PACKAGE;
return true;
case ObjectListKind.Members:
categoryField = 0;
return true;
case ObjectListKind.Namespaces:
categoryField = (uint)_LIB_LISTTYPE.LLT_CLASSES;
return true;
case ObjectListKind.Projects:
categoryField = (uint)_LIB_LISTTYPE.LLT_NAMESPACES | (uint)_LIB_LISTTYPE.LLT_CLASSES;
if (IsClassView() && this.ParentKind == ObjectListKind.None)
{
categoryField |= (uint)_LIB_LISTTYPE.LLT_HIERARCHY;
}
return true;
case ObjectListKind.References:
categoryField = (uint)_LIB_LISTTYPE.LLT_NAMESPACES | (uint)_LIB_LISTTYPE.LLT_CLASSES;
return true;
case ObjectListKind.Types:
categoryField = (uint)_LIB_LISTTYPE.LLT_MEMBERS;
if ((_flags & (Helpers.LLF_SEARCH_EXPAND_MEMBERS | Helpers.LLF_SEARCH_WITH_EXPANSION)) == 0)
{
categoryField |= (uint)_LIB_LISTTYPE.LLT_HIERARCHY;
}
return true;
}
categoryField = 0;
return false;
}
private bool TryGetClassAccess(uint index, out uint categoryField)
{
var typeListItem = (TypeListItem)GetListItem(index);
switch (typeListItem.Accessibility)
{
case Accessibility.Private:
categoryField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PRIVATE;
return true;
case Accessibility.Protected:
categoryField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PROTECTED;
return true;
case Accessibility.Internal:
case Accessibility.ProtectedOrInternal:
case Accessibility.ProtectedAndInternal:
categoryField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PACKAGE;
return true;
default:
categoryField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PUBLIC;
return true;
}
}
private bool TryGetClassType(uint index, out uint categoryField)
{
var typeListItem = (TypeListItem)GetListItem(index);
switch (typeListItem.Kind)
{
case TypeKind.Interface:
categoryField = (uint)_LIBCAT_CLASSTYPE.LCCT_INTERFACE;
return true;
case TypeKind.Struct:
categoryField = (uint)_LIBCAT_CLASSTYPE.LCCT_STRUCT;
return true;
case TypeKind.Enum:
categoryField = (uint)_LIBCAT_CLASSTYPE.LCCT_ENUM;
return true;
case TypeKind.Delegate:
categoryField = (uint)_LIBCAT_CLASSTYPE.LCCT_DELEGATE;
return true;
case TypeKind.Class:
categoryField = (uint)_LIBCAT_CLASSTYPE.LCCT_CLASS;
return true;
case TypeKind.Module:
categoryField = (uint)_LIBCAT_CLASSTYPE.LCCT_MODULE;
return true;
default:
Debug.Fail("Unexpected type kind: " + typeListItem.Kind.ToString());
categoryField = 0;
return false;
}
}
private bool TryGetMemberInheritance(uint index, out uint categoryField)
{
var memberListItem = (MemberListItem)GetListItem(index);
if (memberListItem.IsInherited)
{
categoryField = (uint)_LIBCAT_MEMBERINHERITANCE.LCMI_INHERITED;
}
else
{
categoryField = (uint)_LIBCAT_MEMBERINHERITANCE.LCMI_IMMEDIATE;
}
return true;
}
private bool TryGetMemberAccess(uint index, out uint categoryField)
{
var memberListItem = (MemberListItem)GetListItem(index);
switch (memberListItem.Accessibility)
{
case Accessibility.Private:
categoryField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PRIVATE;
return true;
case Accessibility.Protected:
categoryField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PROTECTED;
return true;
case Accessibility.Internal:
case Accessibility.ProtectedOrInternal:
case Accessibility.ProtectedAndInternal:
categoryField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PACKAGE;
return true;
default:
categoryField = (uint)_LIBCAT_MEMBERACCESS.LCMA_PUBLIC;
return true;
}
}
private bool TryGetMemberType(uint index, out uint categoryField)
{
var memberListItem = (MemberListItem)GetListItem(index);
switch (memberListItem.Kind)
{
case MemberKind.Constant:
categoryField = (uint)_LIBCAT_MEMBERTYPE.LCMT_CONSTANT;
return true;
case MemberKind.EnumMember:
categoryField = (uint)_LIBCAT_MEMBERTYPE.LCMT_ENUMITEM;
return true;
case MemberKind.Event:
categoryField = (uint)_LIBCAT_MEMBERTYPE.LCMT_EVENT;
return true;
case MemberKind.Field:
categoryField = (uint)_LIBCAT_MEMBERTYPE.LCMT_FIELD;
return true;
case MemberKind.Method:
categoryField = (uint)_LIBCAT_MEMBERTYPE.LCMT_METHOD;
return true;
case MemberKind.Operator:
categoryField = (uint)_LIBCAT_MEMBERTYPE.LCMT_OPERATOR;
return true;
case MemberKind.Property:
categoryField = (uint)_LIBCAT_MEMBERTYPE.LCMT_PROPERTY;
return true;
default:
Debug.Fail("Unexpected member kind: " + memberListItem.Kind.ToString());
categoryField = 0;
return false;
}
}
private bool TryGetPhysicalContainerType(uint index, out uint categoryField)
{
var listItem = GetListItem(index);
switch (listItem.ParentListKind)
{
case ObjectListKind.Projects:
categoryField = (uint)_LIBCAT_PHYSICALCONTAINERTYPE.LCPT_PROJECT;
return true;
case ObjectListKind.References:
categoryField = (uint)_LIBCAT_PHYSICALCONTAINERTYPE.LCPT_PROJECTREFERENCE;
return true;
}
categoryField = 0;
return false;
}
private bool TryGetVisibility(uint index, out uint categoryField)
{
var item = GetListItem(index);
categoryField = item.IsHidden
? (uint)_LIBCAT_VISIBILITY.LCV_HIDDEN
: (uint)_LIBCAT_VISIBILITY.LCV_VISIBLE;
return true;
}
protected override bool TryGetCategoryField(uint index, int category, out uint categoryField)
{
switch (category)
{
case (int)LIB_CATEGORY.LC_LISTTYPE:
return TryGetListType(out categoryField);
case (int)_LIB_CATEGORY2.LC_MEMBERINHERITANCE:
return TryGetMemberInheritance(index, out categoryField);
case (int)LIB_CATEGORY.LC_MEMBERACCESS:
return TryGetMemberAccess(index, out categoryField);
case (int)LIB_CATEGORY.LC_MEMBERTYPE:
return TryGetMemberType(index, out categoryField);
case (int)LIB_CATEGORY.LC_CLASSACCESS:
return TryGetClassAccess(index, out categoryField);
case (int)LIB_CATEGORY.LC_CLASSTYPE:
return TryGetClassType(index, out categoryField);
case (int)_LIB_CATEGORY2.LC_HIERARCHYTYPE:
if (Kind == ObjectListKind.Hierarchy)
{
categoryField = this.ParentKind == ObjectListKind.Projects
? (uint)_LIBCAT_HIERARCHYTYPE.LCHT_PROJECTREFERENCES
: (uint)_LIBCAT_HIERARCHYTYPE.LCHT_BASESANDINTERFACES;
}
else
{
categoryField = (uint)_LIBCAT_HIERARCHYTYPE.LCHT_UNKNOWN;
}
return true;
case (int)LIB_CATEGORY.LC_NODETYPE:
categoryField = 0;
return false;
case (int)_LIB_CATEGORY2.LC_PHYSICALCONTAINERTYPE:
return TryGetPhysicalContainerType(index, out categoryField);
case (int)LIB_CATEGORY.LC_VISIBILITY:
return TryGetVisibility(index, out categoryField);
}
throw new NotImplementedException();
}
protected override void GetDisplayData(uint index, ref VSTREEDISPLAYDATA data)
{
var item = GetListItem(index);
data.Image = item.GlyphIndex;
data.SelectedImage = item.GlyphIndex;
if (item.IsHidden)
{
data.State |= (uint)_VSTREEDISPLAYSTATE.TDS_GRAYTEXT;
}
}
protected override bool GetExpandable(uint index, uint listTypeExcluded)
{
switch (Kind)
{
case ObjectListKind.Hierarchy:
case ObjectListKind.Namespaces:
case ObjectListKind.Projects:
case ObjectListKind.References:
return true;
case ObjectListKind.BaseTypes:
case ObjectListKind.Types:
return IsExpandableType(index);
}
return false;
}
private bool IsExpandableType(uint index)
{
if (GetListItem(index) is not TypeListItem typeListItem)
{
return false;
}
var compilation = typeListItem.GetCompilation(this.LibraryManager.Workspace);
if (compilation == null)
{
return false;
}
var typeSymbol = typeListItem.ResolveTypedSymbol(compilation);
// We never show base types for System.Object
if (typeSymbol.SpecialType == SpecialType.System_Object)
{
return false;
}
if (typeSymbol.TypeKind == TypeKind.Module)
{
return false;
}
if (typeSymbol.TypeKind == TypeKind.Interface && typeSymbol.Interfaces.IsEmpty)
{
return false;
}
if (typeSymbol.BaseType == null)
{
return false;
}
return true;
}
protected override uint GetItemCount()
=> (uint)_items.Length;
protected override IVsSimpleObjectList2 GetList(uint index, uint listType, uint flags, VSOBSEARCHCRITERIA2[] pobSrch)
{
var listItem = GetListItem(index);
// We need to do a little massaging of the list type and parent item in a couple of cases.
switch (Kind)
{
case ObjectListKind.Hierarchy:
// LLT_USESCLASSES is for displaying base classes and interfaces
// LLF_PROJREF is for displaying project references
listType = listType == (uint)_LIB_LISTTYPE.LLT_CLASSES
? (uint)_LIB_LISTTYPE.LLT_USESCLASSES
: Helpers.LLT_PROJREF;
// Use the parent of this list as the parent of the new list.
listItem = listItem.ParentList.ParentListItem;
break;
case ObjectListKind.BaseTypes:
if (listType == (uint)_LIB_LISTTYPE.LLT_CLASSES)
{
listType = (uint)_LIB_LISTTYPE.LLT_USESCLASSES;
}
break;
}
var listKind = Helpers.ListTypeToObjectListKind(listType);
if (Helpers.IsFindSymbol(flags))
{
var project = this.LibraryManager.GetProject(listItem.ProjectId);
if (project == null)
{
return null;
}
var lookInReferences = (flags & ((uint)_VSOBSEARCHOPTIONS.VSOBSO_LOOKINREFS | (uint)_VSOBSEARCHOPTIONS2.VSOBSO_LISTREFERENCES)) != 0;
var projectAndAssemblySet = this.LibraryManager.GetAssemblySet(project, lookInReferences, CancellationToken.None);
return this.LibraryManager.GetSearchList(listKind, flags, pobSrch, projectAndAssemblySet);
}
var compilation = listItem.GetCompilation(this.LibraryManager.Workspace);
if (compilation == null)
{
return null;
}
switch (listKind)
{
case ObjectListKind.Types:
return new ObjectList(ObjectListKind.Types, flags, this, listItem, LibraryManager, this.LibraryManager.GetTypeListItems(listItem, compilation));
case ObjectListKind.Hierarchy:
return new ObjectList(ObjectListKind.Hierarchy, flags, this, listItem, LibraryManager, this.LibraryManager.GetFolderListItems(listItem, compilation));
case ObjectListKind.Namespaces:
return new ObjectList(ObjectListKind.Namespaces, flags, this, listItem, LibraryManager, this.LibraryManager.GetNamespaceListItems(listItem, compilation));
case ObjectListKind.Members:
return new ObjectList(ObjectListKind.Members, flags, this, listItem, LibraryManager, this.LibraryManager.GetMemberListItems(listItem, compilation));
case ObjectListKind.References:
return new ObjectList(ObjectListKind.References, flags, this, listItem, LibraryManager, this.LibraryManager.GetReferenceListItems(listItem, compilation));
case ObjectListKind.BaseTypes:
return new ObjectList(ObjectListKind.BaseTypes, flags, this, listItem, LibraryManager, this.LibraryManager.GetBaseTypeListItems(listItem, compilation));
}
throw new NotImplementedException();
}
protected override object GetBrowseObject(uint index)
{
if (GetListItem(index) is SymbolListItem symbolListItem)
{
return this.LibraryManager.Workspace.GetBrowseObject(symbolListItem);
}
return base.GetBrowseObject(index);
}
protected override bool SupportsNavInfo
{
get { return true; }
}
protected override IVsNavInfo GetNavInfo(uint index)
{
var listItem = GetListItem(index);
if (listItem == null)
{
return null;
}
if (listItem is ProjectListItem projectListItem)
{
var project = this.LibraryManager.GetProject(projectListItem.ProjectId);
if (project != null)
{
return this.LibraryManager.LibraryService.NavInfoFactory.CreateForProject(project);
}
}
if (listItem is ReferenceListItem referenceListItem)
{
return this.LibraryManager.LibraryService.NavInfoFactory.CreateForReference(referenceListItem.MetadataReference);
}
if (listItem is SymbolListItem symbolListItem)
{
return this.LibraryManager.GetNavInfo(symbolListItem, useExpandedHierarchy: IsClassView());
}
return null;
}
protected override IVsNavInfoNode GetNavInfoNode(uint index)
{
var listItem = GetListItem(index);
var name = listItem.DisplayText;
var type = Helpers.ObjectListKindToListType(Kind);
if (type == (uint)_LIB_LISTTYPE.LLT_USESCLASSES)
{
type = (uint)_LIB_LISTTYPE.LLT_CLASSES;
}
else if (type == Helpers.LLT_PROJREF)
{
type = (uint)_LIB_LISTTYPE.LLT_PACKAGE;
}
return new NavInfoNode(name, type);
}
protected override bool TryLocateNavInfoNode(IVsNavInfoNode pNavInfoNode, out uint index)
{
var itemCount = GetItemCount();
index = 0xffffffffu;
if (ErrorHandler.Failed(pNavInfoNode.get_Name(out var matchName)))
{
return false;
}
if (ErrorHandler.Failed(pNavInfoNode.get_Type(out _)))
{
return false;
}
var longestMatchedName = string.Empty;
for (uint i = 0; i < itemCount; i++)
{
var name = GetText(i, VSTREETEXTOPTIONS.TTO_DISPLAYTEXT);
if (Kind is ObjectListKind.Types or
ObjectListKind.Namespaces or
ObjectListKind.Members)
{
if (string.Equals(matchName, name, StringComparison.Ordinal))
{
index = i;
break;
}
}
else
{
if (string.Equals(matchName, name, StringComparison.Ordinal))
{
index = i;
break;
}
else if (Kind == ObjectListKind.Projects)
{
if (matchName.IndexOf(name, StringComparison.OrdinalIgnoreCase) >= 0)
{
if (longestMatchedName.Length < name.Length)
{
longestMatchedName = name;
index = i;
}
}
}
}
}
return index != 0xffffffffu;
}
protected override bool SupportsDescription
{
get { return true; }
}
protected override bool TryFillDescription(uint index, _VSOBJDESCOPTIONS options, IVsObjectBrowserDescription3 description)
{
var listItem = GetListItem(index);
return this.LibraryManager.TryFillDescription(listItem, description, options);
}
protected override bool TryGetProperty(uint index, _VSOBJLISTELEMPROPID propertyId, out object pvar)
{
pvar = null;
var listItem = GetListItem(index);
if (listItem == null)
{
return false;
}
switch (propertyId)
{
case _VSOBJLISTELEMPROPID.VSOBJLISTELEMPROPID_FULLNAME:
pvar = listItem.FullNameText;
return true;
case _VSOBJLISTELEMPROPID.VSOBJLISTELEMPROPID_HELPKEYWORD:
if (listItem is SymbolListItem symbolListItem)
{
var project = this.LibraryManager.Workspace.CurrentSolution.GetProject(symbolListItem.ProjectId);
if (project != null)
{
var compilation = project
.GetCompilationAsync(CancellationToken.None)
.WaitAndGetResult_ObjectBrowser(CancellationToken.None);
var symbol = symbolListItem.ResolveSymbol(compilation);
if (symbol != null)
{
var helpContextService = project.Services.GetService<IHelpContextService>();
pvar = helpContextService.FormatSymbol(symbol);
return true;
}
}
}
return false;
}
return false;
}
protected override bool TryCountSourceItems(uint index, out IVsHierarchy hierarchy, out uint itemid, out uint items)
{
hierarchy = null;
itemid = 0;
items = 0;
var listItem = GetListItem(index);
if (listItem == null)
{
return false;
}
hierarchy = this.LibraryManager.Workspace.GetHierarchy(listItem.ProjectId);
if (listItem is ProjectListItem)
{
itemid = (uint)VSConstants.VSITEMID.Root;
items = 1;
return true;
}
else if (listItem is SymbolListItem)
{
// TODO: Get itemid
items = 1;
return true;
}
return false;
}
protected override string GetText(uint index, VSTREETEXTOPTIONS tto)
=> GetDisplayText(index, tto);
protected override string GetTipText(uint index, VSTREETOOLTIPTYPE eTipType)
=> null;
protected override async Task GoToSourceAsync(uint index, VSOBJGOTOSRCTYPE srcType)
{
try
{
var operationExecutor = LibraryManager.ComponentModel.GetService<IUIThreadOperationExecutor>();
using var context = operationExecutor.BeginExecute(ServicesVSResources.IntelliSense, EditorFeaturesResources.Navigating, allowCancellation: true, showProgress: false);
var cancellationToken = context.UserCancellationToken;
if (srcType == VSOBJGOTOSRCTYPE.GS_DEFINITION &&
GetListItem(index) is SymbolListItem symbolItem &&
symbolItem.SupportsGoToDefinition)
{
var project = this.LibraryManager.Workspace.CurrentSolution.GetProject(symbolItem.ProjectId);
var compilation = await project.GetCompilationAsync(cancellationToken).ConfigureAwait(false);
var symbol = symbolItem.ResolveSymbol(compilation);
await this.LibraryManager.Workspace.TryGoToDefinitionAsync(symbol, project, cancellationToken).ConfigureAwait(false);
}
}
catch (OperationCanceledException)
{
}
catch (Exception ex) when (FatalError.ReportAndCatch(ex, ErrorSeverity.Critical))
{
}
}
protected override uint GetUpdateCounter()
{
switch (Kind)
{
case ObjectListKind.Projects:
case ObjectListKind.References:
return LibraryManager.PackageVersion;
case ObjectListKind.BaseTypes:
case ObjectListKind.Namespaces:
case ObjectListKind.Types:
return LibraryManager.ClassVersion;
case ObjectListKind.Members:
return LibraryManager.MembersVersion;
case ObjectListKind.Hierarchy:
return LibraryManager.ClassVersion | LibraryManager.MembersVersion;
default:
Debug.Fail("Unsupported object list kind: " + Kind.ToString());
throw new InvalidOperationException();
}
}
protected override bool TryGetContextMenu(uint index, out Guid menuGuid, out int menuId)
{
if (GetListItem(index) == null)
{
menuGuid = Guid.Empty;
menuId = 0;
return false;
}
menuGuid = VsMenus.guidSHLMainMenu;
// from vsshlids.h
const int IDM_VS_CTXT_CV_PROJECT = 0x0432;
const int IDM_VS_CTXT_CV_ITEM = 0x0433;
const int IDM_VS_CTXT_CV_GROUPINGFOLDER = 0x0435;
const int IDM_VS_CTXT_CV_MEMBER = 0x0438;
switch (Kind)
{
case ObjectListKind.Projects:
menuId = IDM_VS_CTXT_CV_PROJECT;
break;
case ObjectListKind.Members:
menuId = IDM_VS_CTXT_CV_MEMBER;
break;
case ObjectListKind.Hierarchy:
menuId = IDM_VS_CTXT_CV_GROUPINGFOLDER;
break;
default:
menuId = IDM_VS_CTXT_CV_ITEM;
break;
}
return true;
}
protected override bool SupportsBrowseContainers
{
get { return true; }
}
protected override bool TryFindBrowseContainer(VSCOMPONENTSELECTORDATA data, out uint index)
{
index = 0;
var count = GetItemCount();
for (uint i = 0; i < count; i++)
{
var listItem = GetListItem(i);
if (data.type == VSCOMPONENTTYPE.VSCOMPONENTTYPE_ComPlus)
{
if (listItem is not ReferenceListItem referenceListItem)
{
continue;
}
if (referenceListItem.MetadataReference is not PortableExecutableReference metadataReference)
{
continue;
}
if (string.Equals(data.bstrFile, metadataReference.FilePath, StringComparison.OrdinalIgnoreCase))
{
index = i;
return true;
}
}
else
{
Debug.Assert(data.type == VSCOMPONENTTYPE.VSCOMPONENTTYPE_Project);
var hierarchy = this.LibraryManager.Workspace.GetHierarchy(listItem.ProjectId);
if (hierarchy == null)
{
continue;
}
if (this.LibraryManager.ServiceProvider.GetService(typeof(SVsSolution)) is not IVsSolution vsSolution)
{
return false;
}
if (ErrorHandler.Failed(vsSolution.GetProjrefOfProject(hierarchy, out var projectRef)))
{
return false;
}
if (data.bstrProjRef == projectRef)
{
index = i;
return true;
}
}
}
return false;
}
protected override bool TryGetBrowseContainerData(uint index, ref VSCOMPONENTSELECTORDATA data)
{
var listItem = GetListItem(index);
if (listItem is ProjectListItem projectListItem)
{
var hierarchy = this.LibraryManager.Workspace.GetHierarchy(projectListItem.ProjectId);
if (hierarchy == null)
{
return false;
}
if (this.LibraryManager.ServiceProvider.GetService(typeof(SVsSolution)) is not IVsSolution vsSolution)
{
return false;
}
if (ErrorHandler.Failed(vsSolution.GetProjrefOfProject(hierarchy, out var projectRef)))
{
return false;
}
var project = this.LibraryManager.Workspace.CurrentSolution.GetProject(projectListItem.ProjectId);
if (project == null)
{
return false;
}
data.bstrFile = project.FilePath;
data.bstrProjRef = projectRef;
data.bstrTitle = projectListItem.DisplayText;
data.type = VSCOMPONENTTYPE.VSCOMPONENTTYPE_Project;
}
else
{
if (listItem is not ReferenceListItem referenceListItem)
{
return false;
}
if (referenceListItem.MetadataReference is not PortableExecutableReference portableExecutableReference)
{
return false;
}
var assemblyIdentity = AssemblyIdentityUtils.TryGetAssemblyIdentity(portableExecutableReference.FilePath);
if (assemblyIdentity == null)
{
return false;
}
data.bstrFile = portableExecutableReference.FilePath;
data.type = VSCOMPONENTTYPE.VSCOMPONENTTYPE_ComPlus;
data.wFileMajorVersion = (ushort)assemblyIdentity.Version.Major;
data.wFileMinorVersion = (ushort)assemblyIdentity.Version.Minor;
data.wFileBuildNumber = (ushort)assemblyIdentity.Version.Build;
data.wFileRevisionNumber = (ushort)assemblyIdentity.Version.Revision;
}
return true;
}
public ObjectListKind Kind { get; }
public ObjectListKind ParentKind
{
get
{
return _parentList != null
? _parentList.Kind
: ObjectListKind.None;
}
}
public ObjectListItem ParentListItem { get; }
}
|