コード例 #1
0
            private ProjectId GetActiveContextProjectIdAndWatchHierarchies(string moniker, IEnumerable <ProjectId> projectIds, IVsHierarchy hierarchy)
            {
                _foregroundAffinitization.AssertIsForeground();

                // First clear off any existing IVsHierarchies we are watching. Any ones that still matter we will resubscribe to.
                // We could be fancy and diff, but the cost is probably negligible.
                UnsubscribeFromWatchedHierarchies(moniker);

                if (hierarchy == null)
                {
                    // Any item in the RDT should have a hierarchy associated; in this case we don't so there's absolutely nothing
                    // we can do at this point.
                    return(projectIds.First());
                }

                void WatchHierarchy(IVsHierarchy hierarchyToWatch)
                {
                    _watchedHierarchiesForDocumentMoniker.Add(moniker, _hierarchyEventSinkCache.GetOrCreate(hierarchyToWatch, h => new HierarchyEventSink(h, this)));
                }

                // Take a snapshot of the immutable data structure here to avoid mutation underneath us
                var projectToHierarchyMap = _workspace._projectToHierarchyMap;
                var solution = _workspace.CurrentSolution;

                // We now must chase to the actual hierarchy that we know about. First, we'll chase through multiple shared asset projects if
                // we need to do so.
                while (true)
                {
                    var contextHierarchy = hierarchy.GetActiveProjectContext();

                    // The check for if contextHierarchy == hierarchy is working around downstream impacts of https://devdiv.visualstudio.com/DevDiv/_git/CPS/pullrequest/158271
                    // Since that bug means shared projects have themselves as their own owner, it sometimes results in us corrupting state where we end up
                    // having the context of shared project be itself, it seems.
                    if (contextHierarchy == null || contextHierarchy == hierarchy)
                    {
                        break;
                    }

                    WatchHierarchy(hierarchy);
                    hierarchy = contextHierarchy;
                }

                // We may have multiple projects with the same hierarchy, but we can use __VSHPROPID8.VSHPROPID_ActiveIntellisenseProjectContext to distinguish
                if (ErrorHandler.Succeeded(hierarchy.GetProperty(VSConstants.VSITEMID_ROOT, (int)__VSHPROPID8.VSHPROPID_ActiveIntellisenseProjectContext, out var contextProjectNameObject)))
                {
                    WatchHierarchy(hierarchy);

                    if (contextProjectNameObject is string contextProjectName)
                    {
                        var project = _workspace.GetProjectWithHierarchyAndName(hierarchy, contextProjectName);

                        if (project != null && projectIds.Contains(project.Id))
                        {
                            return(project.Id);
                        }
                    }
                }

                // At this point, we should hopefully have only one project that maches by hierarchy. If there's multiple, at this point we can't figure anything
                // out better.
                var matchingProjectId = projectIds.FirstOrDefault(id => projectToHierarchyMap.GetValueOrDefault(id, null) == hierarchy);

                if (matchingProjectId != null)
                {
                    return(matchingProjectId);
                }

                // If we had some trouble finding the project, we'll just pick one arbitrarily
                return(projectIds.First());
            }