File: Workspace\Solution\LoadableTextAndVersionSource.cs
Web Access
Project: ..\..\..\src\Workspaces\Core\Portable\Microsoft.CodeAnalysis.Workspaces.csproj (Microsoft.CodeAnalysis.Workspaces)
// 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.
 
using System.Diagnostics.CodeAnalysis;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
 
namespace Microsoft.CodeAnalysis;
 
internal sealed class LoadableTextAndVersionSource : ITextAndVersionSource
{
    private sealed class LazyValueWithOptions
    {
        public readonly LoadableTextAndVersionSource Source;
        public readonly AsyncLazy<TextAndVersion> LazyValue;
        public readonly LoadTextOptions Options;
 
        public LazyValueWithOptions(LoadableTextAndVersionSource source, LoadTextOptions options)
        {
            LazyValue = new AsyncLazy<TextAndVersion>(LoadAsync, LoadSynchronously, source.CacheResult);
            Source = source;
            Options = options;
        }
 
        private Task<TextAndVersion> LoadAsync(CancellationToken cancellationToken)
            => Source.Loader.LoadTextAsync(Options, cancellationToken);
 
        private TextAndVersion LoadSynchronously(CancellationToken cancellationToken)
            => Source.Loader.LoadTextSynchronously(Options, cancellationToken);
    }
 
    public readonly TextLoader Loader;
    public readonly bool CacheResult;
 
    private LazyValueWithOptions? _lazyValue;
 
    public LoadableTextAndVersionSource(TextLoader loader, bool cacheResult)
    {
        Loader = loader;
        CacheResult = cacheResult;
    }
 
    public bool CanReloadText
        => Loader.CanReloadText;
 
    private AsyncLazy<TextAndVersion> GetLazyValue(LoadTextOptions options)
    {
        var lazy = _lazyValue;
 
        if (lazy == null || lazy.Options != options)
        {
            // drop previous value and replace it with the one that has current options:
            _lazyValue = lazy = new LazyValueWithOptions(this, options);
        }
 
        return lazy.LazyValue;
    }
 
    public TextAndVersion GetValue(LoadTextOptions options, CancellationToken cancellationToken)
        => GetLazyValue(options).GetValue(cancellationToken);
 
    public bool TryGetValue(LoadTextOptions options, [MaybeNullWhen(false)] out TextAndVersion value)
        => GetLazyValue(options).TryGetValue(out value);
 
    public Task<TextAndVersion> GetValueAsync(LoadTextOptions options, CancellationToken cancellationToken)
        => GetLazyValue(options).GetValueAsync(cancellationToken);
}