File: CSharp\CSharpSourceGenerators.cs
Web Access
Project: ..\..\..\src\VisualStudio\IntegrationTest\New.IntegrationTests\Microsoft.VisualStudio.LanguageServices.New.IntegrationTests.csproj (Microsoft.VisualStudio.LanguageServices.New.IntegrationTests)
// 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;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.Host;
using Microsoft.CodeAnalysis.Options;
using Microsoft.CodeAnalysis.Shared.TestHooks;
using Microsoft.CodeAnalysis.Test.Utilities;
using Microsoft.CodeAnalysis.TestSourceGenerator;
using Microsoft.VisualStudio;
using Microsoft.VisualStudio.IntegrationTest.Utilities;
using Microsoft.VisualStudio.LanguageServices;
using Microsoft.VisualStudio.Shell.TableControl;
using Roslyn.VisualStudio.IntegrationTests;
using Roslyn.VisualStudio.IntegrationTests.InProcess;
using WindowsInput.Native;
using Xunit;
using Xunit.Abstractions;
 
namespace Roslyn.VisualStudio.NewIntegrationTests.CSharp
{
    [Trait(Traits.Feature, Traits.Features.SourceGenerators)]
    public class CSharpSourceGenerators : AbstractEditorTest
    {
        private readonly ITestOutputHelper _testOutputHelper;
 
        public CSharpSourceGenerators(ITestOutputHelper testOutputHelper)
            : base(nameof(CSharpSourceGenerators), WellKnownProjectTemplates.ConsoleApplication)
        {
            _testOutputHelper = testOutputHelper;
        }
 
        protected override string LanguageName => LanguageNames.CSharp;
 
        public override async Task InitializeAsync()
        {
            await base.InitializeAsync();
 
            await TestServices.SolutionExplorer.AddAnalyzerReferenceAsync(ProjectName, typeof(HelloWorldGenerator).Assembly.Location, HangMitigatingCancellationToken);
            await TestServices.Workspace.WaitForAllAsyncOperationsAsync(new[] { FeatureAttribute.Workspace, FeatureAttribute.NavigateTo }, HangMitigatingCancellationToken);
        }
 
        [IdeFact]
        public async Task GoToDefinitionOpensGeneratedFile()
        {
            await TestServices.Editor.SetTextAsync(@"using System;
internal static class Program
{
    public static void Main()
    {
        Console.WriteLine(" + HelloWorldGenerator.GeneratedEnglishClassName + @".GetMessage());
    }
}", HangMitigatingCancellationToken);
 
            await TestServices.Editor.PlaceCaretAsync(HelloWorldGenerator.GeneratedEnglishClassName, charsOffset: 0, HangMitigatingCancellationToken);
            await TestServices.Editor.GoToDefinitionAsync(HangMitigatingCancellationToken);
            Assert.Equal($"{HelloWorldGenerator.GeneratedEnglishClassName}.cs {ServicesVSResources.generated_suffix}", await TestServices.Shell.GetActiveWindowCaptionAsync(HangMitigatingCancellationToken));
            Assert.Equal(HelloWorldGenerator.GeneratedEnglishClassName, await TestServices.Editor.GetSelectedTextAsync(HangMitigatingCancellationToken));
        }
 
        [IdeTheory(Skip = "https://github.com/dotnet/roslyn/issues/64721")]
        [CombinatorialData]
        public async Task FindReferencesForFileWithDefinitionInSourceGeneratedFile(bool invokeFromSourceGeneratedFile)
        {
            await TestServices.Editor.SetTextAsync(@"using System;
internal static class Program
{
    public static void Main()
    {
        Console.WriteLine(" + HelloWorldGenerator.GeneratedEnglishClassName + @".GetMessage());
    }
}", HangMitigatingCancellationToken);
 
            await TestServices.Editor.PlaceCaretAsync(HelloWorldGenerator.GeneratedEnglishClassName, charsOffset: 0, HangMitigatingCancellationToken);
 
            if (invokeFromSourceGeneratedFile)
            {
                var workspace = await TestServices.Shell.GetComponentModelServiceAsync<VisualStudioWorkspace>(HangMitigatingCancellationToken);
 
                // clear configuration options already read by initialization above, so that the global option update below is effective:
                var configurationService = (WorkspaceConfigurationService)workspace.Services.GetRequiredService<IWorkspaceConfigurationService>();
                configurationService.Clear();
 
                var globalOptions = await TestServices.Shell.GetComponentModelServiceAsync<IGlobalOptionService>(HangMitigatingCancellationToken);
                globalOptions.SetGlobalOption(WorkspaceConfigurationOptionsStorage.EnableOpeningSourceGeneratedFilesInWorkspace, true);
 
                await TestServices.Editor.GoToDefinitionAsync(HangMitigatingCancellationToken);
                Assert.Equal($"{HelloWorldGenerator.GeneratedEnglishClassName}.cs {ServicesVSResources.generated_suffix}", await TestServices.Shell.GetActiveWindowCaptionAsync(HangMitigatingCancellationToken));
            }
 
            await TestServices.Input.SendAsync((VirtualKeyCode.F12, VirtualKeyCode.SHIFT), HangMitigatingCancellationToken);
 
            var results = (await TestServices.FindReferencesWindow.GetContentsAsync(HangMitigatingCancellationToken)).OrderBy(r => r.GetLine()).ToArray();
 
            Assert.Collection(
                results,
                new Action<ITableEntryHandle2>[]
                {
                    reference =>
                    {
                        Assert.Equal(expected: "/// <summary><see cref=\"HelloWorld\" /> is a simple class to fetch the classic message.</summary>", actual: reference.GetText());
                        Assert.Equal(expected: 1, actual: reference.GetLine());
                        Assert.Equal(expected: 24, actual: reference.GetColumn());
                    },
                    reference =>
                    {
                        Assert.Equal(expected: "internal class HelloWorld", actual: reference.GetText());
                        Assert.Equal(expected: 2, actual: reference.GetLine());
                        Assert.Equal(expected: 15, actual: reference.GetColumn());
                    },
                    reference =>
                    {
                        Assert.Equal(expected: "Console.WriteLine(" + HelloWorldGenerator.GeneratedEnglishClassName + ".GetMessage());", actual: reference.GetText());
                        Assert.Equal(expected: 5, actual: reference.GetLine());
                        Assert.Equal(expected: 26, actual: reference.GetColumn());
                    },
                });
        }
 
        [IdeTheory, CombinatorialData]
        public async Task FindReferencesAndNavigateToReferenceInGeneratedFile(bool isPreview)
        {
            await TestServices.Editor.SetTextAsync(@"using System;
internal static class Program
{
    public static void Main()
    {
        Console.WriteLine(" + HelloWorldGenerator.GeneratedEnglishClassName + @".GetMessage());
    }
}", HangMitigatingCancellationToken);
 
            await TestServices.Editor.PlaceCaretAsync(HelloWorldGenerator.GeneratedEnglishClassName, charsOffset: 0, HangMitigatingCancellationToken);
            await TestServices.Input.SendAsync((VirtualKeyCode.F12, VirtualKeyCode.SHIFT), HangMitigatingCancellationToken);
 
            var results = await TestServices.FindReferencesWindow.GetContentsAsync(HangMitigatingCancellationToken);
            var referenceInGeneratedFile = results.Single(r => r.GetText()?.Contains("<summary>") ?? false);
            await TestServices.FindReferencesWindow.NavigateToAsync(referenceInGeneratedFile, isPreview: isPreview, shouldActivate: true, HangMitigatingCancellationToken);
 
            // Assert we are in the right file now
            Assert.Equal($"{HelloWorldGenerator.GeneratedEnglishClassName}.cs {ServicesVSResources.generated_suffix}", await TestServices.Shell.GetActiveWindowCaptionAsync(HangMitigatingCancellationToken));
            Assert.Equal(isPreview, await TestServices.Shell.IsActiveTabProvisionalAsync(HangMitigatingCancellationToken));
        }
 
        [IdeFact]
        public async Task InvokeNavigateToForGeneratedFile()
        {
            await TestServices.Shell.ShowNavigateToDialogAsync(HangMitigatingCancellationToken);
 
            await TestServices.Input.SendToNavigateToAsync(new InputKey[] { HelloWorldGenerator.GeneratedEnglishClassName, VirtualKeyCode.RETURN }, HangMitigatingCancellationToken);
            await TestServices.Workarounds.WaitForNavigationAsync(HangMitigatingCancellationToken);
 
            Assert.Equal($"{HelloWorldGenerator.GeneratedEnglishClassName}.cs [generated]", await TestServices.Shell.GetActiveWindowCaptionAsync(HangMitigatingCancellationToken));
            Assert.Equal("HelloWorld", await TestServices.Editor.GetSelectedTextAsync(HangMitigatingCancellationToken));
        }
    }
}