File: VirtualDocumentBase.cs
Web Access
Project: src\src\Razor\src\Razor\src\Microsoft.VisualStudio.LanguageServer.ContainedLanguage\Microsoft.VisualStudio.LanguageServer.ContainedLanguage.csproj (Microsoft.VisualStudio.LanguageServer.ContainedLanguage)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using Microsoft.VisualStudio.LanguageServer.ContainedLanguage.Extensions;
using Microsoft.VisualStudio.Text;
 
namespace Microsoft.VisualStudio.LanguageServer.ContainedLanguage;
 
public abstract class VirtualDocumentBase<T> : VirtualDocument where T : VirtualDocumentSnapshot
{
    private T _currentSnapshot;
    private int _hostDocumentSyncVersion;
 
    protected VirtualDocumentBase(Uri uri, ITextBuffer textBuffer)
    {
        if (uri is null)
        {
            throw new ArgumentNullException(nameof(uri));
        }
 
        if (textBuffer is null)
        {
            throw new ArgumentNullException(nameof(textBuffer));
        }
 
        Uri = uri;
        TextBuffer = textBuffer;
        _currentSnapshot = GetUpdatedSnapshot(state: null);
    }
 
    public override Uri Uri { get; }
 
    public override ITextBuffer TextBuffer { get; }
 
    public override int HostDocumentVersion => _hostDocumentSyncVersion;
 
    public override VirtualDocumentSnapshot CurrentSnapshot => _currentSnapshot;
 
    public override VirtualDocumentSnapshot Update(IReadOnlyList<ITextChange> changes, int hostDocumentVersion, object? state)
    {
        if (changes is null)
        {
            throw new ArgumentNullException(nameof(changes));
        }
 
        _hostDocumentSyncVersion = hostDocumentVersion;
        TextBuffer.SetHostDocumentSyncVersion(_hostDocumentSyncVersion);
 
        using var edit = TextBuffer.CreateEdit(EditOptions.None, reiteratedVersionNumber: null, InviolableEditTag.Instance);
        for (var i = 0; i < changes.Count; i++)
        {
            var change = changes[i];
            edit.Replace(change.OldSpan.Start, change.OldSpan.Length, change.NewText);
        }
 
        edit.Apply();
        _currentSnapshot = GetUpdatedSnapshot(state);
 
        return _currentSnapshot;
    }
 
    protected abstract T GetUpdatedSnapshot(object? state);
 
    [SuppressMessage("Usage", "CA1816:Dispose methods should call SuppressFinalize", Justification = "https://github.com/dotnet/roslyn-analyzers/issues/4801")]
    public override void Dispose()
    {
        TextBuffer.ChangeContentType(InertContentType.Instance, null);
 
        if (TextBuffer.Properties != null && TextBuffer.Properties.TryGetProperty(typeof(ITextDocument), out ITextDocument textDocument))
        {
            TextBuffer.Properties.RemoveProperty(typeof(ITextDocument));
 
            try
            {
                textDocument.Dispose();
            }
            catch
            {
                // Eat the exception for now while we are investigating an issue.
                // There is System.OperationCanceledException: 'Project unload has already occurred or begun.'
                // that gets thrown if Razor file is open when you are shutting down VS at
                // Microsoft.VisualStudio.ProjectSystem.ProjectAsynchronousTasksServiceBase.RegisterAsyncTask(Microsoft.VisualStudio.Threading.JoinableTask, Microsoft.VisualStudio.ProjectSystem.ProjectCriticalOperation, bool)
                // Microsoft.VisualStudio.ProjectSystem.VS.Implementation.CodeGenerators.GeneratorScheduler.ScheduleFileGeneration(Microsoft.VisualStudio.ProjectSystem.VS.Implementation.CodeGenerators.IGeneratorSchedulerRequest)
                // Microsoft.VisualStudio.ProjectSystem.VS.Implementation.CodeGenerators.SingleFileGeneratorsService.ScheduleRefreshGeneratedFile(string)
                // Microsoft.VisualStudio.ProjectSystem.VS.Implementation.CodeGenerators.SingleFileGeneratorsService.TextDocumentFactoryService_TextDocumentDisposed(object, Microsoft.VisualStudio.Text.TextDocumentEventArgs)
                // Microsoft.VisualStudio.Text.Implementation.TextDocumentFactoryService.RaiseTextDocumentDisposed(Microsoft.VisualStudio.Text.ITextDocument)
                // Microsoft.VisualStudio.Text.Implementation.TextDocument.Dispose()
                // Microsoft.VisualStudio.LanguageServer.ContainedLanguage.VirtualDocumentBase<T>.Dispose() in VirtualDocumentBase
            }
        }
    }
}