Repository: dotnet/roslyn
File: src/VisualStudio/Core/Impl/SolutionExplorer/SymbolTree/RootSymbolTreeItemSourceProvider.cs (C#)

Code before:
        // Update all the affected documents in parallel.
        await Parallel.ForEachAsync(
            sources,
            cancellationToken,
            async (source, cancellationToken) =>
            {
                await source.UpdateIfEverBeenAskedToComputeAsync(cancellationToken)
                    .ReportNonFatalErrorUnlessCancelledAsync(cancellationToken)
                    .ConfigureAwait(false);
            }).ConfigureAwait(false);
    }

    protected override IAttachedCollectionSource? CreateCollectionSource(IVsHierarchyItem item, string relationshipName)
    {
        if (item == null ||
            item.IsDisposed ||
            item.HierarchyIdentity == null ||
            item.HierarchyIdentity.NestedHierarchy == null ||
            relationshipName != KnownRelationships.Contains)
        {
            return null;
        }

        // Important: currentFilePath is mutable state captured *AND UPDATED* in the local function  
        // OnItemPropertyChanged below.  It allows us to know the file path of the item *prior* to
        // it being changed *when* we hear the update about it having changed (since hte event doesn't
        // contain the old value).  
        if (item.CanonicalName is not string currentFilePath)
            return null;

        if (item.HierarchyIdentity.NestedHierarchy.GetGuidProperty(
                item.HierarchyIdentity.ItemID,
                (int)__VSHPROPID.VSHPROPID_TypeGuid,
                out var guid) != VSConstants.S_OK)
        {
            return null;
        }

        // We only support this for real files that we'll then have roslyn Documents for.  All the other
        // things in a project (like folders, nested projects, etc) are not supported.
        if (guid != VSConstants.ItemTypeGuid.PhysicalFile_guid)
            return null;

        var source = new RootSymbolTreeItemCollectionSource(this, item);
        lock (_filePathToCollectionSources)
        {
            _filePathToCollectionSources.MultiAdd(currentFilePath, source);
        }

        // Register to hear about if this hierarchy is disposed. We'll stop watching it if so.
        item.PropertyChanged += OnItemPropertyChanged;

Review comment (performance):
This comment concerns me a bit in two ways:

1. Not sure there's a better way to do this than the local function; feels like if we're having to comment a bit warning here then maybe we can restructure it. For example, should the provider just hold the subscription/unsubscription logic and just fires an event when it's path changes, so the code here isn't quite so complicated.
2. I'm also surprised we're not having each provider cache it's canonical name generally. I am seeing DetermineDocumentId in the CollectionSource requerying it on a background thread, which is going to be doing all sorts of RPC and is a huge no-no for VS threading rules.

Code after:
        // Update all the affected documents in parallel.
        await Parallel.ForEachAsync(
            sources,
            cancellationToken,
            async (source, cancellationToken) =>
            {
                await source.UpdateIfEverBeenAskedToComputeAsync(cancellationToken)
                    .ReportNonFatalErrorUnlessCancelledAsync(cancellationToken)
                    .ConfigureAwait(false);
            }).ConfigureAwait(false);
    }

    protected override IAttachedCollectionSource? CreateCollectionSource(IVsHierarchyItem item, string relationshipName)
    {
        if (item == null ||
            item.IsDisposed ||
            item.HierarchyIdentity == null ||
            item.HierarchyIdentity.NestedHierarchy == null ||
            relationshipName != KnownRelationships.Contains)
        {
            return null;
        }

        // Important: currentFilePath is mutable state captured *AND UPDATED* in the local function  
        // OnItemPropertyChanged below.  It allows us to know the file path of the item *prior* to
        // it being changed *when* we hear the update about it having changed (since the event doesn't
        // contain the old value).  
        if (item.CanonicalName is not string currentFilePath)
            return null;

        if (item.HierarchyIdentity.NestedHierarchy.GetGuidProperty(
                item.HierarchyIdentity.ItemID,
                (int)__VSHPROPID.VSHPROPID_TypeGuid,
                out var guid) != VSConstants.S_OK)
        {
            return null;
        }

        // We only support this for real files that we'll then have Roslyn Documents for.  All the other
        // things in a project (like folders, nested projects, etc) are not supported.
        if (guid != VSConstants.ItemTypeGuid.PhysicalFile_guid)
            return null;

        var source = new RootSymbolTreeItemCollectionSource(this, item);
        lock (_filePathToCollectionSources)
        {
            _filePathToCollectionSources.MultiAdd(currentFilePath, source);
        }

        // Register to hear about if this hierarchy is disposed. We'll stop watching it if so.
        item.PropertyChanged += OnItemPropertyChanged;