File: RenameTracking\RenameTrackingTaggerProvider.Tagger.cs
Web Access
Project: src\src\EditorFeatures\Core\Microsoft.CodeAnalysis.EditorFeatures.csproj (Microsoft.CodeAnalysis.EditorFeatures)
// 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.Generic;
using Microsoft.VisualStudio.Text;
using Microsoft.VisualStudio.Text.Adornments;
using Microsoft.VisualStudio.Text.Tagging;
 
namespace Microsoft.CodeAnalysis.Editor.Implementation.RenameTracking;
 
internal sealed partial class RenameTrackingTaggerProvider
{
    private class Tagger : ITagger<RenameTrackingTag>, ITagger<IErrorTag>, IDisposable
    {
        private readonly StateMachine _stateMachine;
 
        public event EventHandler<SnapshotSpanEventArgs> TagsChanged = delegate { };
 
        public Tagger(StateMachine stateMachine)
        {
            _stateMachine = stateMachine;
            _stateMachine.Connect();
            _stateMachine.TrackingSessionUpdated += StateMachine_TrackingSessionUpdated;
            _stateMachine.TrackingSessionCleared += StateMachine_TrackingSessionCleared;
        }
 
        private void StateMachine_TrackingSessionCleared(ITrackingSpan trackingSpanToClear)
            => TagsChanged(this, new SnapshotSpanEventArgs(trackingSpanToClear.GetSpan(_stateMachine.Buffer.CurrentSnapshot)));
 
        private void StateMachine_TrackingSessionUpdated()
        {
            if (_stateMachine.TrackingSession != null)
            {
                TagsChanged(this, new SnapshotSpanEventArgs(_stateMachine.TrackingSession.TrackingSpan.GetSpan(_stateMachine.Buffer.CurrentSnapshot)));
            }
        }
 
        public IEnumerable<ITagSpan<RenameTrackingTag>> GetTags(NormalizedSnapshotSpanCollection spans)
            => GetTags(spans, RenameTrackingTag.Instance);
 
        IEnumerable<ITagSpan<IErrorTag>> ITagger<IErrorTag>.GetTags(NormalizedSnapshotSpanCollection spans)
            => GetTags(spans, new ErrorTag(PredefinedErrorTypeNames.Suggestion));
 
        private IEnumerable<TagSpan<T>> GetTags<T>(NormalizedSnapshotSpanCollection spans, T tag) where T : ITag
        {
            if (!_stateMachine.GlobalOptions.GetOption(RenameTrackingOptionsStorage.RenameTracking))
            {
                // Changes aren't being triggered by the buffer, but there may still be taggers
                // out there which we should prevent from doing work.
                yield break;
            }
 
            if (_stateMachine.CanInvokeRename(out var trackingSession, isSmartTagCheck: true))
            {
                foreach (var span in spans)
                {
                    var snapshotSpan = trackingSession.TrackingSpan.GetSpan(span.Snapshot);
                    if (span.IntersectsWith(snapshotSpan))
                    {
                        yield return new TagSpan<T>(snapshotSpan, tag);
                    }
                }
            }
        }
 
        public void Dispose()
        {
            _stateMachine.TrackingSessionUpdated -= StateMachine_TrackingSessionUpdated;
            _stateMachine.TrackingSessionCleared -= StateMachine_TrackingSessionCleared;
            _stateMachine.Disconnect();
        }
    }
}