public void HasAttribute_ReturnsTrueForAttributesOnOverridenProperties()
    {
        // Arrange
        var source = @"
using System;
namespace TestApp
{
    public class TestAttribute : Attribute { }

    public class TestControllerBase
    {
        [TestAttribute]
        public virtual string SomeProperty { get; set; }
    }

    public class TestController : TestControllerBase
    {
        public override string SomeProperty { get; set; }
    }
}";

        var compilation = TestCompilation.Create(source);
        var attribute   = compilation.GetTypeByMetadataName("TestApp.TestAttribute");
        var testClass   = compilation.GetTypeByMetadataName("TestApp.TestController");
        var property    = (IPropertySymbol)testClass.GetMembers("SomeProperty").First();

        // Act
        var hasAttributeWithoutInherit = CodeAnalysisExtensions.HasAttribute(property, attribute, inherit: false);
        var hasAttributeWithInherit    = CodeAnalysisExtensions.HasAttribute(property, attribute, inherit: true);

        // Assert
        Assert.False(hasAttributeWithoutInherit);
        Assert.True(hasAttributeWithInherit);
    }
    public void HasAttribute_ReturnsTrueForAttributesOnMethods()
    {
        // Arrange
        var source = @"
using System;
namespace TestApp
{
    public class TestAttribute : Attribute { }

    public class TestController
    {
        [TestAttribute]
        public void SomeMethod() { }
    }
}";

        var compilation = TestCompilation.Create(source);
        var attribute   = compilation.GetTypeByMetadataName("TestApp.TestAttribute");
        var testClass   = compilation.GetTypeByMetadataName("TestApp.TestController");
        var method      = (IMethodSymbol)testClass.GetMembers("SomeMethod").First();

        // Act
        var hasAttribute = CodeAnalysisExtensions.HasAttribute(method, attribute, inherit: false);

        // Assert
        Assert.True(hasAttribute);
    }
    public void HasAttribute_ReturnsTrueIfBaseTypeHasAttribute()
    {
        // Arrange
        var source = @"
using Microsoft.AspNetCore.Mvc;
namespace TestApp
{
    [Controller]
    public class TestControllerBase { }

    public class TestController : TestControllerBase { }
}";

        var compilation = TestCompilation.Create(source);

        var attribute = compilation.GetTypeByMetadataName("Microsoft.AspNetCore.Mvc.ControllerAttribute");
        var testClass = compilation.GetTypeByMetadataName($"TestApp.TestController");

        // Act
        var hasAttributeWithoutInherit = CodeAnalysisExtensions.HasAttribute(testClass, attribute, inherit: false);
        var hasAttributeWithInherit    = CodeAnalysisExtensions.HasAttribute(testClass, attribute, inherit: true);

        // Assert
        Assert.False(hasAttributeWithoutInherit);
        Assert.True(hasAttributeWithInherit);
    }
    public void HasAttribute_ReturnsTrueForInterfaceContractOnAttribute()
    {
        // Arrange
        var source = @"
using System;
namespace TestApp
{
    public interface ITestInterface { }

    public class TestAttribute : Attribute, ITestInterface  { }

    [TestAttribute]
    public class TestController
    {
    }
}";

        var compilation = TestCompilation.Create(source);
        var @interface  = compilation.GetTypeByMetadataName("TestApp.ITestInterface");
        var testClass   = compilation.GetTypeByMetadataName("TestApp.TestController");

        // Act
        var hasAttribute          = CodeAnalysisExtensions.HasAttribute(testClass, @interface, inherit: true);
        var hasAttributeOnDerived = CodeAnalysisExtensions.HasAttribute(testClass, @interface, inherit: true);

        // Assert
        Assert.True(hasAttribute);
        Assert.True(hasAttributeOnDerived);
    }
    public void HasAttribute_ReturnsFalseIfSymbolDoesNotHaveAttribute()
    {
        // Arrange
        var source = @"
using Microsoft.AspNetCore.Mvc;
namespace TestApp
{
    public class HasAttribute_ReturnsFalseIfTypeDoesNotHaveAttribute : Attribute { }

    [Controller]
    public class HasAttribute_ReturnsFalseIfTypeDoesNotHaveAttributeTest
    {
        [NonAction]
        public void SomeMethod() { }

        [BindProperty]
        public string SomeProperty { get; set; }
    }
}";

        var compilation  = TestCompilation.Create(source);
        var attribute    = compilation.GetTypeByMetadataName("TestApp.HasAttribute_ReturnsFalseIfTypeDoesNotHaveAttribute");
        var testClass    = compilation.GetTypeByMetadataName("TestApp.HasAttribute_ReturnsFalseIfTypeDoesNotHaveAttributeTest");
        var testMethod   = (IMethodSymbol)testClass.GetMembers("SomeMethod").First();
        var testProperty = (IPropertySymbol)testClass.GetMembers("SomeProperty").First();

        // Act
        var classHasAttribute    = CodeAnalysisExtensions.HasAttribute(testClass, attribute, inherit: false);
        var methodHasAttribute   = CodeAnalysisExtensions.HasAttribute(testMethod, attribute, inherit: false);
        var propertyHasAttribute = CodeAnalysisExtensions.HasAttribute(testProperty, attribute, inherit: false);

        // AssertControllerAttribute
        Assert.False(classHasAttribute);
        Assert.False(methodHasAttribute);
        Assert.False(propertyHasAttribute);
    }