Skip to content

Commit

Permalink
Code fix suggestion for correct registration in ASP.NET core integrat…
Browse files Browse the repository at this point in the history
…ion (#1992)
  • Loading branch information
surgupta-msft authored Oct 26, 2023
1 parent 54dbe73 commit 8238eda
Show file tree
Hide file tree
Showing 3 changed files with 154 additions and 2 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the MIT License. See License.txt in the project root for license information.

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeFixes;
using System.Collections.Immutable;
using System.Threading.Tasks;
using System.Composition;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using System.Threading;
using System.Linq;

namespace Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(CodeFixForRegistrationInASPNetCoreIntegration)), Shared]
public sealed class CodeFixForRegistrationInASPNetCoreIntegration : CodeFixProvider
{
public override ImmutableArray<string> FixableDiagnosticIds =>
ImmutableArray.Create(DiagnosticDescriptors.CorrectRegistrationExpectedInAspNetIntegration.Id);

public override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;

private const string ExpectedRegistrationMethod = "ConfigureFunctionsWebApplication";

public override Task RegisterCodeFixesAsync(CodeFixContext context)
{
Diagnostic diagnostic = context.Diagnostics.First();
context.RegisterCodeFix(new ChangeConfigurationForASPNetIntegration(context.Document, diagnostic), diagnostic);

return Task.CompletedTask;
}

/// <summary>
/// CodeAction implementation which fixes the method configuration for ASP.NET Core Integration.
/// </summary>
private sealed class ChangeConfigurationForASPNetIntegration : CodeAction
{
private readonly Document _document;
private readonly Diagnostic _diagnostic;

internal ChangeConfigurationForASPNetIntegration(Document document, Diagnostic diagnostic)
{
this._document = document;
this._diagnostic = diagnostic;
}

public override string Title => "Change configuration for ASP.Net Core Integration";

public override string EquivalenceKey => null;

/// <summary>
/// Returns an updated Document with correct method configuration for ASP.NET Core Integration.
/// </summary>
protected override async Task<Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
{
SyntaxNode root = await _document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

var currentNode = root.FindNode(this._diagnostic.Location.SourceSpan).FirstAncestorOrSelf<IdentifierNameSyntax>();

var newNode = currentNode.ReplaceNode(currentNode, SyntaxFactory.IdentifierName(ExpectedRegistrationMethod));

SyntaxNode newSyntaxRoot = root.ReplaceNode(currentNode, newNode);

return _document.WithSyntaxRoot(newSyntaxRoot);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -10,4 +10,5 @@

### Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.Analyzers

- Analyzer to detect missing ASP.NET Core Integration registration (#1917)
- Analyzer to detect missing ASP.NET Core Integration registration (#1917)
- Code fix suggestion for correct registration in ASP.NET core integration (#1992)
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
using AnalyzerTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpAnalyzerTest<Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.RegistrationExpectedInASPNetIntegration, Microsoft.CodeAnalysis.Testing.Verifiers.XUnitVerifier>;
using Verifier = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier<Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.RegistrationExpectedInASPNetIntegration>;
using CodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest<Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.RegistrationExpectedInASPNetIntegration, Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.CodeFixForRegistrationInASPNetCoreIntegration, Microsoft.CodeAnalysis.Testing.Verifiers.XUnitVerifier>;
using CodeFixVerifier = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixVerifier<Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.RegistrationExpectedInASPNetIntegration, Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore.CodeFixForRegistrationInASPNetCoreIntegration, Microsoft.CodeAnalysis.Testing.Verifiers.XUnitVerifier>;
using Microsoft.CodeAnalysis.Testing;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
Expand Down Expand Up @@ -323,11 +325,90 @@ private static void Method2()
await test.RunAsync();
}

[Fact]
public async Task AspNetIntegration_WithIncorrectRegistration_Diagnostics_Expected_CodeFixWorks()
{
string inputCode = @"
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace AspNetIntegration
{
class Program
{
static void Main(string[] args)
{
//<docsnippet_aspnet_registration>
var host = new HostBuilder()
.ConfigureFunctionsWorkerDefaults()
.Build();
host.Run();
//</docsnippet_aspnet_registration>
}
public static void Method1()
{
}
private static void Method2()
{
}
}
}";

string expectedCode = @"
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Azure.Functions.Worker;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
namespace AspNetIntegration
{
class Program
{
static void Main(string[] args)
{
//<docsnippet_aspnet_registration>
var host = new HostBuilder()
.ConfigureFunctionsWebApplication()
.Build();
host.Run();
//</docsnippet_aspnet_registration>
}
public static void Method1()
{
}
private static void Method2()
{
}
}
}";


var expectedDiagnosticResult = CodeFixVerifier
.Diagnostic("AZFW0014")
.WithSeverity(DiagnosticSeverity.Error)
.WithSpan(16, 34, 16, 66)
.WithArguments(ExpectedRegistrationMethod);

var test = new CodeFixTest
{
ReferenceAssemblies = LoadRequiredDependencyAssemblies(),
TestCode = inputCode,
FixedCode = expectedCode
};

test.ExpectedDiagnostics.AddRange(new[] { expectedDiagnosticResult });
await test.RunAsync();
}

private static ReferenceAssemblies LoadRequiredDependencyAssemblies()
{
var referenceAssemblies = ReferenceAssemblies.Net.Net60.WithPackages(ImmutableArray.Create(
new PackageIdentity("Microsoft.Azure.Functions.Worker", "1.19.0"),
new PackageIdentity("Microsoft.Azure.Functions.Worker.Sdk", "1.14.1"),
new PackageIdentity("Microsoft.Azure.Functions.Worker.Sdk", "1.15.1"),
new PackageIdentity("Microsoft.Azure.Functions.Worker.Extensions.Storage.Blobs", "6.0.0"),
new PackageIdentity("Microsoft.Azure.Functions.Worker.Extensions.Http.AspNetCore", "1.0.0"),
new PackageIdentity("Microsoft.Azure.Functions.Worker.Extensions.Abstractions", "5.0.0"),
Expand Down

0 comments on commit 8238eda

Please sign in to comment.