Skip to content
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

Unify API methods to check for attribute (GH-731) #1095

Merged
merged 2 commits into from
Aug 26, 2019
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 1 addition & 1 deletion Src/FluentAssertions/CallerIdentifier.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ public static string DetermineCallerIdentity()

private static bool IsCustomAssertion(StackFrame frame)
{
return frame.GetMethod().HasAttribute<CustomAssertionAttribute>();
return frame.GetMethod().IsDecoratedWithOrInherit<CustomAssertionAttribute>();
}

private static bool IsDynamic(StackFrame frame)
Expand Down
84 changes: 81 additions & 3 deletions Src/FluentAssertions/Common/TypeExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,14 @@ public static class TypeExtensions
/// <returns>
/// <c>true</c> if the specified method has attribute; otherwise, <c>false</c>.
/// </returns>
[Obsolete("This method is deprecated and will be removed on the next major version. Please use <IsDecoratedWithOrInherits> instead.")]
public static bool HasAttribute<TAttribute>(this MemberInfo method)
where TAttribute : Attribute
{
return method.GetCustomAttributes(typeof(TAttribute), true).Any();
}

[Obsolete("This method is deprecated and will be removed on the next major version. Please use <IsDecoratedWith> instead.")]
public static bool HasMatchingAttribute<TAttribute>(this MemberInfo type,
Expression<Func<TAttribute, bool>> isMatchingAttributePredicate)
where TAttribute : Attribute
Expand All @@ -37,6 +39,7 @@ public static bool HasAttribute<TAttribute>(this MemberInfo method)
return GetCustomAttributes<TAttribute>(type).Any(isMatchingAttribute);
}

[Obsolete("This method is deprecated and will be removed on the next major version. Please use <IsDecoratedWithOrInherits> or <IsDecoratedWith> instead.")]
public static bool HasMatchingAttribute<TAttribute>(this Type type,
Expression<Func<TAttribute, bool>> isMatchingAttributePredicate, bool inherit = false)
where TAttribute : Attribute
Expand All @@ -46,22 +49,97 @@ public static bool HasAttribute<TAttribute>(this MemberInfo method)
return GetCustomAttributes<TAttribute>(type, inherit).Any(isMatchingAttribute);
}

public static bool IsDecoratedWith<TAttribute>(this Type type)
where TAttribute : Attribute
{
return GetCustomAttributes<TAttribute>(type).Any();
}

public static bool IsDecoratedWith<TAttribute>(this TypeInfo type)
where TAttribute : Attribute
{
return GetCustomAttributes<TAttribute>(type).Any();
}

public static bool IsDecoratedWith<TAttribute>(this MemberInfo type)
where TAttribute : Attribute
{
return GetCustomAttributes<TAttribute>(type).Any();
}

public static bool IsDecoratedWithOrInherit<TAttribute>(this Type type)
where TAttribute : Attribute
{
return GetCustomAttributes<TAttribute>(type, true).Any();
}

public static bool IsDecoratedWithOrInherit<TAttribute>(this TypeInfo type)
where TAttribute : Attribute
{
return GetCustomAttributes<TAttribute>(type, true).Any();
}

public static bool IsDecoratedWithOrInherit<TAttribute>(this MemberInfo type)
where TAttribute : Attribute
{
return GetCustomAttributes<TAttribute>(type, true).Any();
}

public static bool IsDecoratedWith<TAttribute>(this Type type, Expression<Func<TAttribute, bool>> isMatchingAttributePredicate)
where TAttribute : Attribute
{
Func<TAttribute, bool> isMatchingAttribute = isMatchingAttributePredicate.Compile();
return GetCustomAttributes<TAttribute>(type).Any(isMatchingAttribute);
}

public static bool IsDecoratedWith<TAttribute>(this TypeInfo type, Expression<Func<TAttribute, bool>> isMatchingAttributePredicate)
where TAttribute : Attribute
{
Func<TAttribute, bool> isMatchingAttribute = isMatchingAttributePredicate.Compile();
return GetCustomAttributes<TAttribute>(type).Any(isMatchingAttribute);
}

public static bool IsDecoratedWith<TAttribute>(this MemberInfo type, Expression<Func<TAttribute, bool>> isMatchingAttributePredicate)
where TAttribute : Attribute
{
Func<TAttribute, bool> isMatchingAttribute = isMatchingAttributePredicate.Compile();
return GetCustomAttributes<TAttribute>(type).Any(isMatchingAttribute);
}

public static bool IsDecoratedWithOrInherit<TAttribute>(this Type type, Expression<Func<TAttribute, bool>> isMatchingAttributePredicate)
where TAttribute : Attribute
{
Func<TAttribute, bool> isMatchingAttribute = isMatchingAttributePredicate.Compile();
return GetCustomAttributes<TAttribute>(type, true).Any(isMatchingAttribute);
}

public static bool IsDecoratedWithOrInherit<TAttribute>(this TypeInfo type, Expression<Func<TAttribute, bool>> isMatchingAttributePredicate)
where TAttribute : Attribute
{
Func<TAttribute, bool> isMatchingAttribute = isMatchingAttributePredicate.Compile();
return GetCustomAttributes<TAttribute>(type, true).Any(isMatchingAttribute);
}

public static bool IsDecoratedWithOrInherit<TAttribute>(this MemberInfo type, Expression<Func<TAttribute, bool>> isMatchingAttributePredicate)
where TAttribute : Attribute
{
Func<TAttribute, bool> isMatchingAttribute = isMatchingAttributePredicate.Compile();
return GetCustomAttributes<TAttribute>(type, true).Any(isMatchingAttribute);
}

[Obsolete("This overload is deprecated and will be removed on the next major version. Please use <IsDecoratedWithOrInherits> or <IsDecoratedWith> instead.")]
public static bool IsDecoratedWith<TAttribute>(this Type type, bool inherit = false)
where TAttribute : Attribute
{
return GetCustomAttributes<TAttribute>(type, inherit).Any();
}

private static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(MemberInfo type)
private static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(MemberInfo type, bool inherit = false)
where TAttribute : Attribute
{
return type.GetCustomAttributes(false).OfType<TAttribute>();
// Do not use as extension method here, there is an issue with PropertyInfo and EventInfo
// preventing the inherit option to work.
return CustomAttributeExtensions.GetCustomAttributes(type, inherit).OfType<TAttribute>();
}

private static IEnumerable<TAttribute> GetCustomAttributes<TAttribute>(Type type, bool inherit = false)
Expand Down Expand Up @@ -433,7 +511,7 @@ private static bool IsAnonymousType(this Type type)
}

bool hasCompilerGeneratedAttribute =
type.GetTypeInfo().GetCustomAttributes(typeof(CompilerGeneratedAttribute), false).Any();
type.GetTypeInfo().IsDecoratedWith<CompilerGeneratedAttribute>();

return hasCompilerGeneratedAttribute;
}
Expand Down
2 changes: 1 addition & 1 deletion Src/FluentAssertions/Formatting/AttributeBasedFormatter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ private static MethodInfo[] FindCustomFormatters()
where type != null
from method in type.GetMethods(BindingFlags.Static | BindingFlags.Public)
where method.IsStatic
where method.HasAttribute<ValueFormatterAttribute>()
where method.IsDecoratedWithOrInherit<ValueFormatterAttribute>()
where method.GetParameters().Length == 1
select method;

Expand Down
2 changes: 1 addition & 1 deletion Src/FluentAssertions/Specialized/DelegateAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@ private Exception InvokeSubjectWithInterception()

private void FailIfSubjectIsAsyncVoid()
{
if (!CanHandleAsync && Subject.GetMethodInfo().HasAttribute<AsyncStateMachineAttribute>())
if (!CanHandleAsync && Subject.GetMethodInfo().IsDecoratedWithOrInherit<AsyncStateMachineAttribute>())
{
throw new InvalidOperationException("Cannot use action assertions on an async void method. Assign the async method to a variable of type Func<Task> instead of Action so that it can be awaited.");
}
Expand Down
9 changes: 5 additions & 4 deletions Src/FluentAssertions/Types/MethodInfoSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using FluentAssertions.Common;

namespace FluentAssertions.Types
{
Expand Down Expand Up @@ -93,7 +94,7 @@ public MethodInfoSelector ThatDoNotReturn<TReturn>()
public MethodInfoSelector ThatAreDecoratedWith<TAttribute>()
where TAttribute : Attribute
{
selectedMethods = selectedMethods.Where(method => method.GetCustomAttributes(false).OfType<TAttribute>().Any());
selectedMethods = selectedMethods.Where(method => method.IsDecoratedWith<TAttribute>());
return this;
}

Expand All @@ -103,7 +104,7 @@ public MethodInfoSelector ThatAreDecoratedWith<TAttribute>()
public MethodInfoSelector ThatAreDecoratedWithOrInherit<TAttribute>()
where TAttribute : Attribute
{
selectedMethods = selectedMethods.Where(method => method.GetCustomAttributes(true).OfType<TAttribute>().Any());
selectedMethods = selectedMethods.Where(method => method.IsDecoratedWithOrInherit<TAttribute>());
return this;
}

Expand All @@ -113,7 +114,7 @@ public MethodInfoSelector ThatAreDecoratedWithOrInherit<TAttribute>()
public MethodInfoSelector ThatAreNotDecoratedWith<TAttribute>()
where TAttribute : Attribute
{
selectedMethods = selectedMethods.Where(method => !method.GetCustomAttributes(false).OfType<TAttribute>().Any());
selectedMethods = selectedMethods.Where(method => !method.IsDecoratedWith<TAttribute>());
return this;
}

Expand All @@ -123,7 +124,7 @@ public MethodInfoSelector ThatAreNotDecoratedWith<TAttribute>()
public MethodInfoSelector ThatAreNotDecoratedWithOrInherit<TAttribute>()
where TAttribute : Attribute
{
selectedMethods = selectedMethods.Where(method => !method.GetCustomAttributes(true).OfType<TAttribute>().Any());
selectedMethods = selectedMethods.Where(method => !method.IsDecoratedWithOrInherit<TAttribute>());
return this;
}

Expand Down
4 changes: 2 additions & 2 deletions Src/FluentAssertions/Types/MethodInfoSelectorAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -208,13 +208,13 @@ public AndConstraint<MethodInfoSelectorAssertions> NotBeDecoratedWith<TAttribute
private MethodInfo[] GetMethodsWithout<TAttribute>(Expression<Func<TAttribute, bool>> isMatchingPredicate)
where TAttribute : Attribute
{
return SubjectMethods.Where(method => !method.HasMatchingAttribute(isMatchingPredicate)).ToArray();
return SubjectMethods.Where(method => !method.IsDecoratedWith(isMatchingPredicate)).ToArray();
}

private MethodInfo[] GetMethodsWith<TAttribute>(Expression<Func<TAttribute, bool>> isMatchingPredicate)
where TAttribute : Attribute
{
return SubjectMethods.Where(method => method.HasMatchingAttribute(isMatchingPredicate)).ToArray();
return SubjectMethods.Where(method => method.IsDecoratedWith(isMatchingPredicate)).ToArray();
}

private static string GetDescriptionsFor(IEnumerable<MethodInfo> methods)
Expand Down
9 changes: 5 additions & 4 deletions Src/FluentAssertions/Types/PropertyInfoSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using FluentAssertions.Common;

namespace FluentAssertions.Types
{
Expand Down Expand Up @@ -55,7 +56,7 @@ public PropertyInfoSelector ThatArePublicOrInternal
public PropertyInfoSelector ThatAreDecoratedWith<TAttribute>()
where TAttribute : Attribute
{
selectedProperties = selectedProperties.Where(property => CustomAttributeExtensions.GetCustomAttributes(property, false).OfType<TAttribute>().Any());
selectedProperties = selectedProperties.Where(property => property.IsDecoratedWith<TAttribute>());
return this;
}

Expand All @@ -65,7 +66,7 @@ public PropertyInfoSelector ThatAreDecoratedWith<TAttribute>()
public PropertyInfoSelector ThatAreDecoratedWithOrInherit<TAttribute>()
where TAttribute : Attribute
{
selectedProperties = selectedProperties.Where(property => CustomAttributeExtensions.GetCustomAttributes(property, true).OfType<TAttribute>().Any());
selectedProperties = selectedProperties.Where(property => property.IsDecoratedWithOrInherit<TAttribute>());
return this;
}

Expand All @@ -75,7 +76,7 @@ public PropertyInfoSelector ThatAreDecoratedWithOrInherit<TAttribute>()
public PropertyInfoSelector ThatAreNotDecoratedWith<TAttribute>()
where TAttribute : Attribute
{
selectedProperties = selectedProperties.Where(property => !property.GetCustomAttributes(false).OfType<TAttribute>().Any());
selectedProperties = selectedProperties.Where(property => !property.IsDecoratedWith<TAttribute>());
return this;
}

Expand All @@ -85,7 +86,7 @@ public PropertyInfoSelector ThatAreNotDecoratedWith<TAttribute>()
public PropertyInfoSelector ThatAreNotDecoratedWithOrInherit<TAttribute>()
where TAttribute : Attribute
{
selectedProperties = selectedProperties.Where(property => !CustomAttributeExtensions.GetCustomAttributes(property, true).OfType<TAttribute>().Any());
selectedProperties = selectedProperties.Where(property => !property.IsDecoratedWithOrInherit<TAttribute>());
return this;
}

Expand Down
12 changes: 6 additions & 6 deletions Src/FluentAssertions/Types/TypeAssertions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,7 @@ public AndConstraint<TypeAssertions> BeDecoratedWith<TAttribute>(string because
BeDecoratedWith<TAttribute>(because, becauseArgs);

Execute.Assertion
.ForCondition(Subject.HasMatchingAttribute(isMatchingAttributePredicate))
.ForCondition(Subject.IsDecoratedWith(isMatchingAttributePredicate))
.BecauseOf(because, becauseArgs)
.FailWith("Expected type {0} to be decorated with {1} that matches {2}{reason}, but no matching attribute was found.",
Subject, typeof(TAttribute), isMatchingAttributePredicate.Body);
Expand All @@ -276,7 +276,7 @@ public AndConstraint<TypeAssertions> BeDecoratedWithOrInherit<TAttribute>(string
where TAttribute : Attribute
{
Execute.Assertion
.ForCondition(Subject.IsDecoratedWith<TAttribute>(true))
.ForCondition(Subject.IsDecoratedWithOrInherit<TAttribute>())
.BecauseOf(because, becauseArgs)
.FailWith("Expected type {0} to be decorated with or inherit {1}{reason}, but the attribute was not found.",
Subject, typeof(TAttribute));
Expand Down Expand Up @@ -307,7 +307,7 @@ public AndConstraint<TypeAssertions> BeDecoratedWithOrInherit<TAttribute>(string
BeDecoratedWithOrInherit<TAttribute>(because, becauseArgs);

Execute.Assertion
.ForCondition(Subject.HasMatchingAttribute(isMatchingAttributePredicate, true))
.ForCondition(Subject.IsDecoratedWithOrInherit(isMatchingAttributePredicate))
.BecauseOf(because, becauseArgs)
.FailWith("Expected type {0} to be decorated with or inherit {1} that matches {2}{reason}, but no matching attribute was found.",
Subject, typeof(TAttribute), isMatchingAttributePredicate.Body);
Expand Down Expand Up @@ -358,7 +358,7 @@ public AndConstraint<TypeAssertions> NotBeDecoratedWith<TAttribute>(string becau
Guard.ThrowIfArgumentIsNull(isMatchingAttributePredicate, nameof(isMatchingAttributePredicate));

Execute.Assertion
.ForCondition(!Subject.HasMatchingAttribute(isMatchingAttributePredicate))
.ForCondition(!Subject.IsDecoratedWith(isMatchingAttributePredicate))
.BecauseOf(because, becauseArgs)
.FailWith("Expected type {0} to not be decorated with {1} that matches {2}{reason}, but a matching attribute was found.",
Subject, typeof(TAttribute), isMatchingAttributePredicate.Body);
Expand All @@ -380,7 +380,7 @@ public AndConstraint<TypeAssertions> NotBeDecoratedWithOrInherit<TAttribute>(str
where TAttribute : Attribute
{
Execute.Assertion
.ForCondition(!Subject.IsDecoratedWith<TAttribute>(true))
.ForCondition(!Subject.IsDecoratedWithOrInherit<TAttribute>())
.BecauseOf(because, becauseArgs)
.FailWith("Expected type {0} to not be decorated with or inherit {1}{reason}, but the attribute was found.",
Subject, typeof(TAttribute));
Expand Down Expand Up @@ -409,7 +409,7 @@ public AndConstraint<TypeAssertions> NotBeDecoratedWithOrInherit<TAttribute>(str
Guard.ThrowIfArgumentIsNull(isMatchingAttributePredicate, nameof(isMatchingAttributePredicate));

Execute.Assertion
.ForCondition(!Subject.HasMatchingAttribute(isMatchingAttributePredicate, true))
.ForCondition(!Subject.IsDecoratedWithOrInherit(isMatchingAttributePredicate))
.BecauseOf(because, becauseArgs)
.FailWith("Expected type {0} to not be decorated with or inherit {1} that matches {2}{reason}, but a matching attribute was found.",
Subject, typeof(TAttribute), isMatchingAttributePredicate.Body);
Expand Down
9 changes: 5 additions & 4 deletions Src/FluentAssertions/Types/TypeSelector.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using FluentAssertions.Common;

namespace FluentAssertions.Types
{
Expand Down Expand Up @@ -81,7 +82,7 @@ public TypeSelector ThatAreDecoratedWith<TAttribute>()
{
types = types

.Where(t => t.GetTypeInfo().GetCustomAttributes(typeof(TAttribute), false).Any())
.Where(t => t.GetTypeInfo().IsDecoratedWith<TAttribute>())
.ToList();

return this;
Expand All @@ -95,7 +96,7 @@ public TypeSelector ThatAreDecoratedWithOrInherit<TAttribute>()
{
types = types

.Where(t => t.GetTypeInfo().GetCustomAttributes(typeof(TAttribute), true).Any())
.Where(t => t.GetTypeInfo().IsDecoratedWithOrInherit<TAttribute>())
.ToList();

return this;
Expand All @@ -109,7 +110,7 @@ public TypeSelector ThatAreNotDecoratedWith<TAttribute>()
{
types = types

.Where(t => !t.GetTypeInfo().GetCustomAttributes(typeof(TAttribute), false).Any())
.Where(t => !t.GetTypeInfo().IsDecoratedWith<TAttribute>())
.ToList();

return this;
Expand All @@ -123,7 +124,7 @@ public TypeSelector ThatAreNotDecoratedWithOrInherit<TAttribute>()
{
types = types

.Where(t => !t.GetTypeInfo().GetCustomAttributes(typeof(TAttribute), true).Any())
.Where(t => !t.GetTypeInfo().IsDecoratedWithOrInherit<TAttribute>())
.ToList();

return this;
Expand Down