|
// 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.
// Copy of https://devdiv.visualstudio.com/DevDiv/_git/VS.CloudCache?path=%2Ftest%2FMicrosoft.VisualStudio.Cache.Tests%2FMocks&_a=contents&version=GBmain
// Try to keep in sync and avoid unnecessary changes here.
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Threading.Tasks.Dataflow;
using Microsoft.VisualStudio.RpcContracts.Solution;
using Microsoft.VisualStudio.Threading;
#pragma warning disable CS0067 // events that are never used
namespace Microsoft.CodeAnalysis.UnitTests.WorkspaceServices.Mocks
{
internal class SolutionServiceMock : ISolutionService
{
private readonly BroadcastObservable<OpenCodeContainersState> openContainerObservable = new BroadcastObservable<OpenCodeContainersState>(new OpenCodeContainersState());
public event EventHandler<ProjectsLoadedEventArgs>? ProjectsLoaded;
public event EventHandler<ProjectsUnloadedEventArgs>? ProjectsUnloaded;
public event EventHandler<ProjectsLoadProgressEventArgs>? ProjectLoadProgressChanged;
internal Uri? SolutionFilePath
{
get => this.openContainerObservable.Value.SolutionFilePath;
set => this.openContainerObservable.Value = this.openContainerObservable.Value with { SolutionFilePath = value };
}
public ValueTask<bool[]> AreProjectsLoadedAsync(Guid[] projectIds, CancellationToken cancellationToken) => throw new NotImplementedException();
public Task<IDisposable> SubscribeToOpenCodeContainersStateAsync(IObserver<OpenCodeContainersState> observer, CancellationToken cancellationToken)
{
cancellationToken.ThrowIfCancellationRequested();
return Task.FromResult(this.openContainerObservable.Subscribe(observer));
}
public Task<OpenCodeContainersState> GetOpenCodeContainersStateAsync(CancellationToken cancellationToken) => Task.FromResult(this.openContainerObservable.Value);
public Task CloseSolutionAndFolderAsync(CancellationToken cancellationToken) => throw new NotImplementedException();
public ValueTask<IReadOnlyList<string?>> GetPropertyValuesAsync(IReadOnlyList<int> propertyIds, CancellationToken cancellationToken) => throw new NotImplementedException();
public ValueTask<IReadOnlyList<string?>> GetSolutionTelemetryContextPropertyValuesAsync(IReadOnlyList<string> propertyNames, CancellationToken cancellationToken) => throw new NotImplementedException();
public ValueTask<bool> LoadProjectsAsync(Guid[] projectIds, CancellationToken cancellationToken) => throw new NotImplementedException();
public ValueTask<ProjectLoadResult> LoadProjectsWithResultAsync(Guid[] projectIds, CancellationToken cancellationToken) => throw new NotImplementedException();
public ValueTask<bool> RemoveProjectsAsync(IReadOnlyList<Guid> projectIds, CancellationToken cancellationToken) => throw new NotImplementedException();
public Task RequestProjectEventsAsync(CancellationToken cancellationToken) => throw new NotImplementedException();
public Task SaveSolutionFilterFileAsync(string filterFileDirectory, string filterFileName, CancellationToken cancellationToken) => throw new NotImplementedException();
public ValueTask<bool> UnloadProjectsAsync(Guid[] projectIds, ProjectUnloadReason unloadReason, CancellationToken cancellationToken) => throw new NotImplementedException();
internal void SimulateFolderChange(IReadOnlyList<Uri> folderPaths) => this.openContainerObservable.Value = this.openContainerObservable.Value with { OpenFolderPaths = folderPaths };
private class BroadcastObservable<T> : IObservable<T>
{
private readonly BroadcastBlock<T> sourceBlock = new(v => v);
private T value;
internal BroadcastObservable(T initialValue)
{
this.sourceBlock.Post(this.value = initialValue);
}
internal T Value
{
get => this.value;
set => this.sourceBlock.Post(this.value = value);
}
public IDisposable Subscribe(IObserver<T> observer)
{
var actionBlock = new ActionBlock<T>(observer.OnNext);
actionBlock.Completion.ContinueWith(
static (t, s) =>
{
var observer = (IObserver<T>)s!;
if (t.Exception is object)
{
observer.OnError(t.Exception);
}
else
{
observer.OnCompleted();
}
},
observer,
TaskScheduler.Default).Forget();
return this.sourceBlock.LinkTo(actionBlock, new DataflowLinkOptions { PropagateCompletion = true });
}
}
}
}
|