|
// 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.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp.CodeFixes.GenerateMethod;
using Microsoft.CodeAnalysis.Test.Utilities;
using Roslyn.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics.GenerateMethod;
public sealed partial class GenerateMethodTests
{
private sealed record RazorGeneratedDocumentData(string HintName, string GeneratedCode);
protected override void InitializeWorkspace(TestWorkspace workspace, TestParameters parameters)
{
if (parameters.fixProviderData is not RazorGeneratedDocumentData generatedDocument)
{
return;
}
var project = workspace.CurrentSolution.Projects.Single();
var updatedProject = project.AddAnalyzerReference(
new TestGeneratorReference(
new Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator(
context => context.AddSource(generatedDocument.HintName, generatedDocument.GeneratedCode))));
Assert.True(workspace.TryApplyChanges(updatedProject.Solution));
}
private static TestParameters WithRazorGeneratedDocument(string generatedCode, string hintName = "Component.razor.g.cs")
=> new(fixProviderData: new RazorGeneratedDocumentData(hintName, generatedCode));
private async Task TestGeneratingInRazorSourceGeneratedDocumentAsync(
string workspaceMarkup,
string generatedCode,
string expectedGeneratedCode,
bool requestFromSourceGeneratedDocument)
{
using var workspace = CreateWorkspaceFromOptions(workspaceMarkup, WithRazorGeneratedDocument(generatedCode));
var project = workspace.CurrentSolution.Projects.Single();
var sourceGeneratedDocument = Assert.Single(await project.GetSourceGeneratedDocumentsAsync(CancellationToken.None));
Assert.Contains("Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator", sourceGeneratedDocument.FilePath);
Assert.StartsWith(
"// <auto-generated />",
(await sourceGeneratedDocument.GetTextAsync(CancellationToken.None)).ToString());
var requestDocument = requestFromSourceGeneratedDocument
? sourceGeneratedDocument
: project.Documents.Single();
var requestTree = await requestDocument.GetSyntaxTreeAsync(CancellationToken.None);
var compilation = await project.GetCompilationAsync(CancellationToken.None);
Assert.NotNull(requestTree);
Assert.NotNull(compilation);
var diagnostic = Assert.Single(
compilation!.GetDiagnostics(CancellationToken.None).Where(
diagnostic => diagnostic.Severity == DiagnosticSeverity.Error && diagnostic.Location.SourceTree == requestTree));
var codeActions = new List<CodeAction>();
var context = new CodeFixContext(
requestDocument,
diagnostic.Location.SourceSpan,
[diagnostic],
(action, _) => codeActions.Add(action),
CancellationToken.None);
var provider = new GenerateMethodCodeFixProvider();
await provider.RegisterCodeFixesAsync(context);
var operations = await Assert.Single(codeActions).GetOperationsAsync(CancellationToken.None);
var changedSolutions = await ApplyOperationsAndGetSolutionAsync(workspace, operations);
var newSourceGeneratedDocument = await changedSolutions.Item2.GetSourceGeneratedDocumentAsync(sourceGeneratedDocument.Id, CancellationToken.None);
Assert.NotNull(newSourceGeneratedDocument);
AssertEx.EqualOrDiff(
expectedGeneratedCode,
(await newSourceGeneratedDocument!.GetTextAsync(CancellationToken.None)).ToString());
}
[Fact]
public Task TestGeneratingIntoRazorSourceGeneratedDocumentFromRegularDocument()
=> TestGeneratingInRazorSourceGeneratedDocumentAsync(
"""
<Workspace>
<Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true">
<Document>
public class C
{
public void M()
{
Component.Me$$thod();
}
}
</Document>
</Project>
</Workspace>
""",
"""
// <auto-generated />
using System;
public partial class Component
{
}
""",
"""
// <auto-generated />
using System;
public partial class Component
{
internal static void Method()
{
throw new NotImplementedException();
}
}
""",
requestFromSourceGeneratedDocument: false);
[Fact]
public Task TestGeneratingInRazorSourceGeneratedDocument()
=> TestGeneratingInRazorSourceGeneratedDocumentAsync(
"""
<Workspace>
<Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true">
<Document>
public class Placeholder
{
}
</Document>
</Project>
</Workspace>
""",
"""
// <auto-generated />
using System;
public partial class Component
{
public void M()
{
MissingMethod();
}
}
""",
"""
// <auto-generated />
using System;
public partial class Component
{
public void M()
{
MissingMethod();
}
private void MissingMethod()
{
throw new NotImplementedException();
}
}
""",
requestFromSourceGeneratedDocument: true);
[Fact]
public Task TestGeneratingIntoHiddenRazorSourceGeneratedDocumentFromRegularDocument()
=> TestGeneratingInRazorSourceGeneratedDocumentAsync(
"""
<Workspace>
<Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true">
<Document>
public class C
{
public void M()
{
Component.Me$$thod();
}
}
</Document>
</Project>
</Workspace>
""",
"""
// <auto-generated />
using System;
#line hidden
public partial class Component
{
}
#line default
""",
"""
// <auto-generated />
using System;
#line hidden
public partial class Component
{
internal static void Method()
{
throw new NotImplementedException();
}
}
#line default
""",
requestFromSourceGeneratedDocument: false);
[Fact]
public Task TestGeneratingInHiddenRazorSourceGeneratedDocument()
=> TestGeneratingInRazorSourceGeneratedDocumentAsync(
"""
<Workspace>
<Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true">
<Document>
public class Placeholder
{
}
</Document>
</Project>
</Workspace>
""",
"""
// <auto-generated />
using System;
#line hidden
public partial class Component
{
public void M()
{
MissingMethod();
}
}
#line default
""",
"""
// <auto-generated />
using System;
#line hidden
public partial class Component
{
public void M()
{
MissingMethod();
}
private void MissingMethod()
{
throw new NotImplementedException();
}
}
#line default
""",
requestFromSourceGeneratedDocument: true);
}
|