File: CodeActions\PreviewTests.cs
Web Access
Project: src\src\EditorFeatures\CSharpTest\Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests.csproj (Microsoft.CodeAnalysis.CSharp.EditorFeatures.UnitTests)
// 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 System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeRefactorings;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Editor.Implementation.Preview;
using Microsoft.CodeAnalysis.Editor.UnitTests;
using Microsoft.CodeAnalysis.Editor.UnitTests.Preview;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Test.Utilities;
using Xunit;
 
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.CodeRefactorings;
 
public partial class PreviewTests : AbstractCSharpCodeActionTest
{
    private static readonly TestComposition s_composition = EditorTestCompositions.EditorFeaturesWpf
        .AddParts(
            typeof(MockPreviewPaneService));
 
    private const string AddedDocumentName = "AddedDocument";
    private const string AddedDocumentText = "class C1 {}";
    private static string s_removedMetadataReferenceDisplayName = "";
    private const string AddedProjectName = "AddedProject";
    private static readonly ProjectId s_addedProjectId = ProjectId.CreateNewId();
    private const string ChangedDocumentText = "class C {}";
 
    protected override TestComposition GetComposition() => s_composition;
 
    protected override CodeRefactoringProvider CreateCodeRefactoringProvider(EditorTestWorkspace workspace, TestParameters parameters)
        => new MyCodeRefactoringProvider();
 
    private sealed class MyCodeRefactoringProvider : CodeRefactoringProvider
    {
        public sealed override Task ComputeRefactoringsAsync(CodeRefactoringContext context)
        {
            var codeAction = new TestCodeAction(context.Document);
            context.RegisterRefactoring(codeAction, context.Span);
            return Task.CompletedTask;
        }
 
        private class TestCodeAction : CodeAction
        {
            private readonly Document _oldDocument;
 
            public TestCodeAction(Document document)
                => _oldDocument = document;
 
            public override string Title
            {
                get
                {
                    return "Title";
                }
            }
 
            protected override Task<Solution> GetChangedSolutionAsync(
                IProgress<CodeAnalysisProgress> progress, CancellationToken cancellationToken)
            {
                var solution = _oldDocument.Project.Solution;
 
                // Add a document - This will result in IWpfTextView previews.
                solution = solution.AddDocument(DocumentId.CreateNewId(_oldDocument.Project.Id, AddedDocumentName), AddedDocumentName, AddedDocumentText);
 
                // Remove a reference - This will result in a string preview.
                var removedReference = _oldDocument.Project.MetadataReferences[_oldDocument.Project.MetadataReferences.Count - 1];
                s_removedMetadataReferenceDisplayName = removedReference.Display;
                solution = solution.RemoveMetadataReference(_oldDocument.Project.Id, removedReference);
 
                // Add a project - This will result in a string preview.
                solution = solution.AddProject(ProjectInfo.Create(s_addedProjectId, VersionStamp.Create(), AddedProjectName, AddedProjectName, LanguageNames.CSharp));
 
                // Change a document - This will result in IWpfTextView previews.
                solution = solution.WithDocumentSyntaxRoot(_oldDocument.Id, CSharpSyntaxTree.ParseText(ChangedDocumentText, cancellationToken: cancellationToken).GetRoot(cancellationToken));
 
                return Task.FromResult(solution);
            }
        }
    }
 
    private async Task<(Document document, SolutionPreviewResult previews)> GetMainDocumentAndPreviewsAsync(TestParameters parameters, EditorTestWorkspace workspace)
    {
        var document = GetDocument(workspace);
        var provider = CreateCodeRefactoringProvider(workspace, parameters);
        var span = document.GetSyntaxRootAsync().Result.Span;
        var refactorings = new List<CodeAction>();
        var context = new CodeRefactoringContext(document, span, refactorings.Add, CancellationToken.None);
        provider.ComputeRefactoringsAsync(context).Wait();
        var action = refactorings.Single();
        var editHandler = workspace.ExportProvider.GetExportedValue<ICodeActionEditHandlerService>();
        var previews = await editHandler.GetPreviewsAsync(workspace, action.GetPreviewOperationsAsync(CancellationToken.None).Result, CancellationToken.None);
 
        return (document, previews);
    }
 
    [WpfFact]
    public async Task TestPickTheRightPreview_NoPreference()
    {
        var parameters = new TestParameters();
        using var workspace = CreateWorkspaceFromOptions("class D {}", parameters);
 
        var (document, previews) = await GetMainDocumentAndPreviewsAsync(parameters, workspace);
 
        // The changed document comes first.
        var previewObjects = await previews.GetPreviewsAsync();
        var preview = previewObjects[0];
        Assert.NotNull(preview);
        Assert.True(preview is DifferenceViewerPreview);
        var diffView = preview as DifferenceViewerPreview;
        var text = diffView.Viewer.RightView.TextBuffer.AsTextContainer().CurrentText.ToString();
        Assert.Equal(ChangedDocumentText, text);
        diffView.Dispose();
 
        // Then comes the removed metadata reference.
        preview = previewObjects[1];
        Assert.NotNull(preview);
        Assert.True(preview is string);
        text = preview as string;
        Assert.Contains(s_removedMetadataReferenceDisplayName, text, StringComparison.Ordinal);
 
        // And finally the added project.
        preview = previewObjects[2];
        Assert.NotNull(preview);
        Assert.True(preview is string);
        text = preview as string;
        Assert.Contains(AddedProjectName, text, StringComparison.Ordinal);
    }
}