Skip to content

[release/6.0-rc2] Rename and consolidate "DelegateEndpoint" types #36578

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Sep 20, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -9,9 +9,9 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers;

public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer
public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer
{
internal const string DetectMismatchedParameterOptionalityRuleId = "ASP0006";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,9 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers;

public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer
public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer
{
private static void DetectMisplacedLambdaAttribute(
in OperationAnalysisContext context,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,23 @@

using Microsoft.CodeAnalysis;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers
{
[System.Diagnostics.CodeAnalysis.SuppressMessage("MicrosoftCodeAnalysisReleaseTracking", "RS2008:Enable analyzer release tracking")]
internal static class DiagnosticDescriptors
{
internal static readonly DiagnosticDescriptor DoNotUseModelBindingAttributesOnDelegateEndpointParameters = new(
internal static readonly DiagnosticDescriptor DoNotUseModelBindingAttributesOnRouteHandlerParameters = new(
"ASP0003",
"Do not use model binding attributes with Map handlers",
"Do not use model binding attributes with route handlers",
"{0} should not be specified for a {1} Delegate parameter",
"Usage",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
helpLinkUri: "https://aka.ms/aspnet/analyzers");

internal static readonly DiagnosticDescriptor DoNotReturnActionResultsFromMapActions = new(
internal static readonly DiagnosticDescriptor DoNotReturnActionResultsFromRouteHandlers = new(
"ASP0004",
"Do not use action results with Map actions",
"Do not use action results with route handlers",
"IActionResult instances should not be returned from a {0} Delegate parameter. Consider returning an equivalent result from Microsoft.AspNetCore.Http.Results.",
"Usage",
DiagnosticSeverity.Warning,
Expand All @@ -28,8 +28,8 @@ internal static class DiagnosticDescriptors

internal static readonly DiagnosticDescriptor DetectMisplacedLambdaAttribute = new(
"ASP0005",
"Do not place attribute on route handlers",
"'{0}' should be placed on the endpoint delegate to be effective",
"Do not place attribute on method called by route handler lambda",
"'{0}' should be placed directly on the route handler lambda to be effective",
"Usage",
DiagnosticSeverity.Warning,
isEnabledByDefault: true,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers;

public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer
public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer
{
private static void DisallowMvcBindArgumentsOnParameters(
in OperationAnalysisContext context,
Expand All @@ -33,7 +33,7 @@ private static void DisallowMvcBindArgumentsOnParameters(
var methodName = invocation.TargetMethod.Name;

context.ReportDiagnostic(Diagnostic.Create(
DiagnosticDescriptors.DoNotUseModelBindingAttributesOnDelegateEndpointParameters,
DiagnosticDescriptors.DoNotUseModelBindingAttributesOnRouteHandlerParameters,
location,
modelBindingAttribute.AttributeClass.Name,
methodName));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers;

public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer
public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer
{
private static void DisallowReturningActionResultFromMapMethods(
in OperationAnalysisContext context,
Expand Down Expand Up @@ -40,7 +40,7 @@ private static void DisallowReturningActionResultFromMapMethods(
{
// if we don't have a method body, and the action is IResult or ActionResult<T> returning, produce diagnostics for the entire method.
context.ReportDiagnostic(Diagnostic.Create(
DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions,
DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers,
invocationOperation.Arguments[2].Syntax.GetLocation(),
invocationOperation.TargetMethod.Name));
return;
Expand Down Expand Up @@ -74,7 +74,7 @@ private static void DisallowReturningActionResultFromMapMethods(
if (wellKnownTypes.IActionResult.IsAssignableFrom(type))
{
context.ReportDiagnostic(Diagnostic.Create(
DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions,
DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers,
returnOperation.Syntax.GetLocation(),
invocationOperation.TargetMethod.Name));
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@
using Microsoft.CodeAnalysis.Diagnostics;
using Microsoft.CodeAnalysis.Operations;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public partial class DelegateEndpointAnalyzer : DiagnosticAnalyzer
public partial class RouteHandlerAnalyzer : DiagnosticAnalyzer
{
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics { get; } = ImmutableArray.Create(new[]
{
DiagnosticDescriptors.DoNotUseModelBindingAttributesOnDelegateEndpointParameters,
DiagnosticDescriptors.DoNotReturnActionResultsFromMapActions,
DiagnosticDescriptors.DoNotUseModelBindingAttributesOnRouteHandlerParameters,
DiagnosticDescriptors.DoNotReturnActionResultsFromRouteHandlers,
DiagnosticDescriptors.DetectMisplacedLambdaAttribute,
DiagnosticDescriptors.DetectMismatchedParameterOptionality
});
Expand All @@ -40,7 +40,7 @@ public override void Initialize(AnalysisContext context)
{
var invocation = (IInvocationOperation)operationAnalysisContext.Operation;
var targetMethod = invocation.TargetMethod;
if (IsDelegateHandlerInvocation(wellKnownTypes, invocation, targetMethod))
if (!IsRouteHandlerInvocation(wellKnownTypes, invocation, targetMethod))
{
return;
}
Expand Down Expand Up @@ -109,13 +109,15 @@ public override void Initialize(AnalysisContext context)
});
}

private static bool IsDelegateHandlerInvocation(
private static bool IsRouteHandlerInvocation(
WellKnownTypes wellKnownTypes,
IInvocationOperation invocation,
IMethodSymbol targetMethod)
{
return !targetMethod.Name.StartsWith("Map", StringComparison.Ordinal) ||
!SymbolEqualityComparer.Default.Equals(wellKnownTypes.DelegateEndpointRouteBuilderExtensions, targetMethod.ContainingType) ||
invocation.Arguments.Length != 3;
return targetMethod.Name.StartsWith("Map", StringComparison.Ordinal) &&
SymbolEqualityComparer.Default.Equals(wellKnownTypes.EndpointRouteBuilderExtensions, targetMethod.ContainingType) &&
invocation.Arguments.Length == 3 &&
targetMethod.Parameters.Length == 3 &&
SymbolEqualityComparer.Default.Equals(wellKnownTypes.Delegate, targetMethod.Parameters[2].Type);
}
}
18 changes: 13 additions & 5 deletions src/Framework/AspNetCoreAnalyzers/src/Analyzers/WellKnownTypes.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,21 @@
using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers;

internal sealed class WellKnownTypes
{
public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out WellKnownTypes? wellKnownTypes)
{
wellKnownTypes = default;
const string DelegateEndpointRouteBuilderExtensions = "Microsoft.AspNetCore.Builder.DelegateEndpointRouteBuilderExtensions";
if (compilation.GetTypeByMetadataName(DelegateEndpointRouteBuilderExtensions) is not { } delegateEndpointRouteBuilderExtensions)
const string EndpointRouteBuilderExtensions = "Microsoft.AspNetCore.Builder.EndpointRouteBuilderExtensions";
if (compilation.GetTypeByMetadataName(EndpointRouteBuilderExtensions) is not { } endpointRouteBuilderExtensions)
{
return false;
}

const string Delegate = "System.Delegate";
if (compilation.GetTypeByMetadataName(Delegate) is not { } @delegate)
{
return false;
}
Expand Down Expand Up @@ -51,7 +57,8 @@ public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out We

wellKnownTypes = new WellKnownTypes
{
DelegateEndpointRouteBuilderExtensions = delegateEndpointRouteBuilderExtensions,
EndpointRouteBuilderExtensions = endpointRouteBuilderExtensions,
Delegate = @delegate,
IBinderTypeProviderMetadata = ibinderTypeProviderMetadata,
BindAttribute = bindAttribute,
IResult = iResult,
Expand All @@ -62,7 +69,8 @@ public static bool TryCreate(Compilation compilation, [NotNullWhen(true)] out We
return true;
}

public ITypeSymbol DelegateEndpointRouteBuilderExtensions { get; private init; }
public INamedTypeSymbol EndpointRouteBuilderExtensions { get; private init; }
public INamedTypeSymbol Delegate { get; private init; }
public INamedTypeSymbol IBinderTypeProviderMetadata { get; private init; }
public INamedTypeSymbol BindAttribute { get; private init; }
public INamedTypeSymbol IResult { get; private init; }
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,15 @@
using System.Threading;
using System.Collections.Immutable;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
using Microsoft.AspNetCore.Analyzers.RouteHandlers;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.Editing;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints.Fixers;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers.Fixers;

public class DetectMismatchedParameterOptionalityFixer : CodeFixProvider
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@

using Microsoft.CodeAnalysis.Testing;
using Xunit;
using VerifyCS = Microsoft.AspNetCore.Analyzers.DelegateEndpoints.CSharpDelegateEndpointsCodeFixVerifier<
Microsoft.AspNetCore.Analyzers.DelegateEndpoints.DelegateEndpointAnalyzer,
Microsoft.AspNetCore.Analyzers.DelegateEndpoints.Fixers.DetectMismatchedParameterOptionalityFixer>;
using VerifyCS = Microsoft.AspNetCore.Analyzers.RouteHandlers.CSharpRouteHandlerCodeFixVerifier<
Microsoft.AspNetCore.Analyzers.RouteHandlers.RouteHandlerAnalyzer,
Microsoft.AspNetCore.Analyzers.RouteHandlers.Fixers.DetectMismatchedParameterOptionalityFixer>;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers;

public partial class DetectMismatchedParameterOptionalityTest
{
Expand Down Expand Up @@ -377,7 +377,7 @@ public async Task MatchingRequiredOptionality_WithDisabledNullability()
public void RouteTokenizer_Works_ForSimpleRouteTemplates(string template, string[] expectedNames, string[] expectedQualifiers)
{
// Arrange
var tokenizer = new DelegateEndpointAnalyzer.RouteTokenEnumerator(template);
var tokenizer = new RouteHandlerAnalyzer.RouteTokenEnumerator(template);
var actualNames = new List<string>();
var actualQualifiers = new List<string>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
using Microsoft.AspNetCore.Analyzer.Testing;
using Xunit;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers;

public partial class DetectMisplacedLambdaAttributeTest
{
private TestDiagnosticAnalyzerRunner Runner { get; } = new(new DelegateEndpointAnalyzer());
private TestDiagnosticAnalyzerRunner Runner { get; } = new(new RouteHandlerAnalyzer());

[Fact]
public async Task MinimalAction_WithCorrectlyPlacedAttribute_Works()
Expand Down Expand Up @@ -48,7 +48,7 @@ void Hello() { }
var diagnostic = Assert.Single(diagnostics);
Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
Assert.Equal("'AuthorizeAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
Assert.Equal("'AuthorizeAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
}

[Fact]
Expand All @@ -70,7 +70,7 @@ public async Task MinimalAction_WithMisplacedAttributeAndBlockSyntax_ProducesDia
var diagnostic = Assert.Single(diagnostics);
Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
Assert.Equal("'AuthorizeAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
Assert.Equal("'AuthorizeAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
}

[Fact]
Expand All @@ -95,12 +95,12 @@ void Hello() { }
diagnostic => {
Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
Assert.Equal("'AuthorizeAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
Assert.Equal("'AuthorizeAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
},
diagnostic => {
Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
Assert.Equal("'ProducesAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
Assert.Equal("'ProducesAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
}
);
}
Expand All @@ -126,7 +126,7 @@ void Hello() { }
diagnostic => {
Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
Assert.Equal("'ProducesAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
Assert.Equal("'ProducesAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
}
);
}
Expand Down Expand Up @@ -215,7 +215,7 @@ public static void Hello() { }
var diagnostic = Assert.Single(diagnostics);
Assert.Same(DiagnosticDescriptors.DetectMisplacedLambdaAttribute, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
Assert.Equal("'AuthorizeAttribute' should be placed on the endpoint delegate to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
Assert.Equal("'AuthorizeAttribute' should be placed directly on the route handler lambda to be effective", diagnostic.GetMessage(CultureInfo.InvariantCulture));
}

[Fact]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
using Microsoft.AspNetCore.Analyzer.Testing;
using Xunit;

namespace Microsoft.AspNetCore.Analyzers.DelegateEndpoints;
namespace Microsoft.AspNetCore.Analyzers.RouteHandlers;

public partial class DisallowMvcBindArgumentsOnParametersTest
{
private TestDiagnosticAnalyzerRunner Runner { get; } = new(new DelegateEndpointAnalyzer());
private TestDiagnosticAnalyzerRunner Runner { get; } = new(new RouteHandlerAnalyzer());

[Fact]
public async Task MinimalAction_WithoutBindAttributes_Works()
Expand Down Expand Up @@ -59,7 +59,7 @@ public async Task MinimalAction_Lambda_WithBindAttributes_ProducesDiagnostics()

// Assert
var diagnostic = Assert.Single(diagnostics);
Assert.Same(DiagnosticDescriptors.DoNotUseModelBindingAttributesOnDelegateEndpointParameters, diagnostic.Descriptor);
Assert.Same(DiagnosticDescriptors.DoNotUseModelBindingAttributesOnRouteHandlerParameters, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
Assert.Equal("BindAttribute should not be specified for a MapGet Delegate parameter", diagnostic.GetMessage(CultureInfo.InvariantCulture));
}
Expand All @@ -81,7 +81,7 @@ static void PostWithBind(/*MM*/[ModelBinder] string name) {}

// Assert
var diagnostic = Assert.Single(diagnostics);
Assert.Same(DiagnosticDescriptors.DoNotUseModelBindingAttributesOnDelegateEndpointParameters, diagnostic.Descriptor);
Assert.Same(DiagnosticDescriptors.DoNotUseModelBindingAttributesOnRouteHandlerParameters, diagnostic.Descriptor);
AnalyzerAssert.DiagnosticLocation(source.DefaultMarkerLocation, diagnostic.Location);
Assert.Equal("ModelBinderAttribute should not be specified for a MapPost Delegate parameter", diagnostic.GetMessage(CultureInfo.InvariantCulture));
}
Expand Down
Loading