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

Code before:
    {
        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;

        return source;

        void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(ISupportDisposalNotification.IsDisposed) && item.IsDisposed)
            {
                // We are notified when the IVsHierarchyItem is removed from the tree via its INotifyPropertyChanged
                // event for the IsDisposed property. When this fires, we remove the filePath->sourcce mapping we're holding.
                lock (_filePathToCollectionSources)
                {
                    _filePathToCollectionSources.MultiRemove(currentFilePath, source);
                }

Review comment (suggestion):
```suggestion
        // We only support this for real files that we'll then have Roslyn Documents for.  All the other
```

Code after:
    {
        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;

        return source;

        void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
            if (e.PropertyName == nameof(ISupportDisposalNotification.IsDisposed) && item.IsDisposed)
            {
                // We are notified when the IVsHierarchyItem is removed from the tree via its INotifyPropertyChanged
                // event for the IsDisposed property. When this fires, we remove the filePath->sourcce mapping we're holding.
                lock (_filePathToCollectionSources)
                {
                    _filePathToCollectionSources.MultiRemove(currentFilePath, source);
                }