aspnetcore/src/Microsoft.AspNetCore.Mvc.An.../MvcFacts.cs

138 lines
4.0 KiB
C#

// Copyright (c) .NET Foundation. All rights reserved.
// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
using System;
using System.Diagnostics;
using Microsoft.CodeAnalysis;
namespace Microsoft.AspNetCore.Mvc.Analyzers
{
internal static class MvcFacts
{
public static bool IsController(INamedTypeSymbol type, INamedTypeSymbol controllerAttribute, INamedTypeSymbol nonControllerAttribute)
{
Debug.Assert(type != null);
Debug.Assert(controllerAttribute != null);
Debug.Assert(nonControllerAttribute != null);
if (type.TypeKind != TypeKind.Class)
{
return false;
}
if (type.IsAbstract)
{
return false;
}
// We only consider public top-level classes as controllers.
if (type.DeclaredAccessibility != Accessibility.Public)
{
return false;
}
if (type.ContainingType != null)
{
return false;
}
if (type.IsGenericType || type.IsUnboundGenericType)
{
return false;
}
if (type.HasAttribute(nonControllerAttribute, inherit: true))
{
return false;
}
if (!type.Name.EndsWith("Controller", StringComparison.OrdinalIgnoreCase) &&
!type.HasAttribute(controllerAttribute, inherit: true))
{
return false;
}
return true;
}
public static bool IsControllerAction(IMethodSymbol method, INamedTypeSymbol nonActionAttribute, IMethodSymbol disposableDispose)
{
Debug.Assert(method != null);
Debug.Assert(nonActionAttribute != null);
if (method.MethodKind != MethodKind.Ordinary)
{
return false;
}
if (method.HasAttribute(nonActionAttribute, inherit: true))
{
return false;
}
// Overridden methods from Object class, e.g. Equals(Object), GetHashCode(), etc., are not valid.
if (GetDeclaringType(method).SpecialType == SpecialType.System_Object)
{
return false;
}
if (IsIDisposableDispose(method, disposableDispose))
{
return false;
}
if (method.IsStatic)
{
return false;
}
if (method.IsAbstract)
{
return false;
}
if (method.IsGenericMethod)
{
return false;
}
return method.DeclaredAccessibility == Accessibility.Public;
}
private static INamedTypeSymbol GetDeclaringType(IMethodSymbol method)
{
while (method.IsOverride)
{
method = method.OverriddenMethod;
}
return method.ContainingType;
}
private static bool IsIDisposableDispose(IMethodSymbol method, IMethodSymbol disposableDispose)
{
if (method.Name != disposableDispose.Name)
{
return false;
}
if (method.Parameters.Length != disposableDispose.Parameters.Length)
{
return false;
}
// Explicit implementation
for (var i = 0; i < method.ExplicitInterfaceImplementations.Length; i++)
{
if (method.ExplicitInterfaceImplementations[i].ContainingType.SpecialType == SpecialType.System_IDisposable)
{
return true;
}
}
var implementedMethod = method.ContainingType.FindImplementationForInterfaceMember(disposableDispose);
return implementedMethod == method;
}
}
}