/
githubmirror
/
roslyn
Обзор
Документация
Войти
/
githubmirror
/
roslyn
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
main
src/Analyzers/CSharp/Tests/ImplementInterface/ImplementInterfaceCodeFixTests_Razor.cs
281 строка
11 KB
David Wengier
Fix analyzer warnings in Razor implement interface tests
11 май 2026, 06:17
11 май 2026, 06:17
6f4e664
Код
Авторство
О чём код?
// 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.Collections.Immutable; using System.Linq; using System.Threading; using System.Threading.Tasks; using Microsoft.CodeAnalysis; using Microsoft.CodeAnalysis.CodeActions; using Microsoft.CodeAnalysis.CodeFixes; using Microsoft.CodeAnalysis.CSharp.ImplementInterface; using Microsoft.CodeAnalysis.Diagnostics; using Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.Diagnostics; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; using Xunit.Abstractions; namespace Microsoft.CodeAnalysis.Editor.CSharp.UnitTests.ImplementInterface; [Trait(Traits.Feature, Traits.Features.CodeActionsImplementInterface)] public sealed class ImplementInterfaceCodeFixTests_Razor(ITestOutputHelper logger) : AbstractCSharpDiagnosticProviderBasedUserDiagnosticTest_NoEditor(logger) { private const string CS0535 = nameof(CS0535); private const string RazorSourceGeneratorTypeName = "Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator"; private sealed record GeneratedDocumentData(string HintName, string GeneratedCode, bool IsRazor); internal override (DiagnosticAnalyzer?, CodeFixProvider) CreateDiagnosticProviderAndFixer(Workspace workspace) => (null, new CSharpImplementInterfaceCodeFixProvider()); protected override void InitializeWorkspace(TestWorkspace workspace, TestParameters parameters) { if (parameters.fixProviderData is not GeneratedDocumentData generatedDocument) { return; } var analyzerReference = generatedDocument.IsRazor ? new TestGeneratorReference( new Microsoft.NET.Sdk.Razor.SourceGenerators.RazorSourceGenerator( context => context.AddSource(generatedDocument.HintName, generatedDocument.GeneratedCode))) : new TestGeneratorReference(new TestSourceGenerator(generatedDocument.HintName, generatedDocument.GeneratedCode)); var project = workspace.CurrentSolution.Projects.Single(); var updatedProject = project.AddAnalyzerReference(analyzerReference); Assert.True(workspace.TryApplyChanges(updatedProject.Solution)); } private static TestParameters WithRazorGeneratedDocument(string generatedCode, string hintName = "Component.razor.g.cs") => new(fixProviderData: new GeneratedDocumentData(hintName, generatedCode, IsRazor: true)); private static TestParameters WithGeneratedDocument(string generatedCode, string hintName = "Component.g.cs") => new(fixProviderData: new GeneratedDocumentData(hintName, generatedCode, IsRazor: false)); [Fact] public Task TestImplementInterfaceInRazorSourceGeneratedDocument() => TestImplementingInterfaceInGeneratedDocumentAsync( workspaceMarkup: """ <Workspace> <Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true"> <Document> interface IMyInterface { void Method1(); } </Document> </Project> </Workspace> """, generatedCode: """ // <auto-generated /> public partial class Component : IMyInterface { } """, expectedGeneratedCode: """ // <auto-generated /> public partial class Component : IMyInterface { public void Method1() { throw new System.NotImplementedException(); } } """, actionTitle: CodeFixesResources.Implement_interface, isRazorSourceGeneratedDocument: true); [Fact] public Task TestImplementInterfaceInHiddenRazorSourceGeneratedDocument() => TestImplementingInterfaceInGeneratedDocumentAsync( workspaceMarkup: """ <Workspace> <Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true"> <Document> interface IMyInterface { void Method1(); } </Document> </Project> </Workspace> """, generatedCode: """ // <auto-generated /> #line hidden public partial class Component : IMyInterface { } #line default """, expectedGeneratedCode: """ // <auto-generated /> #line hidden public partial class Component : IMyInterface { public void Method1() { throw new System.NotImplementedException(); } } #line default """, actionTitle: CodeFixesResources.Implement_interface, isRazorSourceGeneratedDocument: true); [Fact] public Task TestImplementInterfaceExplicitlyInRazorSourceGeneratedDocument() => TestImplementingInterfaceInGeneratedDocumentAsync( workspaceMarkup: """ <Workspace> <Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true"> <Document> interface IMyInterface { void Method1(); } </Document> </Project> </Workspace> """, generatedCode: """ // <auto-generated /> public partial class Component : IMyInterface { } """, expectedGeneratedCode: """ // <auto-generated /> public partial class Component : IMyInterface { void IMyInterface.Method1() { throw new System.NotImplementedException(); } } """, actionTitle: CodeFixesResources.Implement_all_members_explicitly, isRazorSourceGeneratedDocument: true); [Fact] public async Task TestDoesNotImplementInterfaceInNonRazorSourceGeneratedDocument() { using var workspace = CreateWorkspaceFromOptions( """ <Workspace> <Project Language="C#" AssemblyName="ClassLibrary1" CommonReferences="true"> <Document> interface IMyInterface { void Method1(); } </Document> </Project> </Workspace> """, WithGeneratedDocument( """ // <auto-generated /> public partial class Component : IMyInterface { } """)); var project = workspace.CurrentSolution.Projects.Single(); var sourceGeneratedDocument = Assert.Single(await project.GetSourceGeneratedDocumentsAsync(CancellationToken.None)); Assert.DoesNotContain(RazorSourceGeneratorTypeName, sourceGeneratedDocument.FilePath); var codeActions = await GetCodeActionsAsync(project, sourceGeneratedDocument, CancellationToken.None); Assert.Empty(codeActions); } private async Task TestImplementingInterfaceInGeneratedDocumentAsync( string workspaceMarkup, string generatedCode, string expectedGeneratedCode, string actionTitle, bool isRazorSourceGeneratedDocument) { using var workspace = CreateWorkspaceFromOptions( workspaceMarkup, isRazorSourceGeneratedDocument ? WithRazorGeneratedDocument(generatedCode) : WithGeneratedDocument(generatedCode)); var project = workspace.CurrentSolution.Projects.Single(); var sourceGeneratedDocument = Assert.Single(await project.GetSourceGeneratedDocumentsAsync(CancellationToken.None)); if (isRazorSourceGeneratedDocument) { Assert.Contains(RazorSourceGeneratorTypeName, sourceGeneratedDocument.FilePath); } else { Assert.DoesNotContain(RazorSourceGeneratorTypeName, sourceGeneratedDocument.FilePath); } Assert.StartsWith( "// <auto-generated />", (await sourceGeneratedDocument.GetTextAsync(CancellationToken.None)).ToString()); var codeActions = await GetCodeActionsAsync(project, sourceGeneratedDocument, CancellationToken.None); var codeAction = Assert.Single(codeActions.Where(action => action.Title == actionTitle)); var operations = await codeAction.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()); } private static async Task<ImmutableArray<CodeAction>> GetCodeActionsAsync(Project project, Document requestDocument, CancellationToken cancellationToken) { var requestTree = await requestDocument.GetSyntaxTreeAsync(cancellationToken); var compilation = await project.GetCompilationAsync(cancellationToken); Assert.NotNull(requestTree); Assert.NotNull(compilation); var diagnostic = Assert.Single( compilation!.GetDiagnostics(cancellationToken).Where( diagnostic => diagnostic.Id == CS0535 && 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); var provider = new CSharpImplementInterfaceCodeFixProvider(); await provider.RegisterCodeFixesAsync(context); return FlattenActions([.. codeActions]); } #pragma warning disable RS1042 // Do not implement private sealed class TestSourceGenerator(string hintName, string generatedCode) : ISourceGenerator #pragma warning restore RS1042 // Do not implement { public void Initialize(GeneratorInitializationContext context) { } public void Execute(GeneratorExecutionContext context) => context.AddSource(hintName, generatedCode); } }