Skip to content

Commit 80ee81f

Browse files
committed
+ IsBrowsable/IsCompilerGenerated
1 parent 89c56b6 commit 80ee81f

File tree

4 files changed

+120
-21
lines changed

4 files changed

+120
-21
lines changed

CodeJam.Main.Tests/Reflection/ReflectionExtensionsTest.cs

Lines changed: 27 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections;
33
using System.Collections.Generic;
44
using System.Collections.ObjectModel;
5+
using System.ComponentModel;
56
using System.Runtime.CompilerServices;
67

78
using CodeJam.Targeting;
@@ -274,7 +275,7 @@ public void GetShortAssemblyQualifiedNameTest([NotNull] Type type, [NotNull] str
274275
[TestCase(typeof(string), ExpectedResult = typeof(string))]
275276
public Type ToUnderlying([NotNull] Type type) => type.ToUnderlying();
276277

277-
[CompilerGenerated]
278+
[CompilerGenerated, Browsable(false)]
278279
private class NotAnonymousType<T> : List<T>
279280
{
280281
}
@@ -283,16 +284,39 @@ private class TestAnonymousCaseAttribute : TestCaseAttribute
283284
{
284285
public TestAnonymousCaseAttribute() : base(new { Field = 0 }.GetType())
285286
{
286-
ExpectedResult = true;
287287
}
288288
}
289289

290-
[TestAnonymousCase]
290+
private class TestCompilerGeneratedCaseAttribute : TestCaseAttribute
291+
{
292+
private static Func<int> GetCompilerGeneratedClosure(int arg) => () => arg;
293+
294+
public TestCompilerGeneratedCaseAttribute() : base(GetCompilerGeneratedClosure(0).Target.GetType())
295+
{
296+
}
297+
}
298+
299+
[TestAnonymousCase(ExpectedResult = true)]
300+
[TestCompilerGeneratedCase(ExpectedResult = false)]
291301
[TestCase(typeof(NotAnonymousType<int>), ExpectedResult = false)]
292302
[TestCase(typeof(DateTime?), ExpectedResult = false)]
293303
[TestCase(typeof(DateTime), ExpectedResult = false)]
294304
public bool IsAnonymous([NotNull] Type type) => type.IsAnonymous();
295305

306+
[TestAnonymousCase(ExpectedResult = true)]
307+
[TestCompilerGeneratedCase(ExpectedResult = true)]
308+
[TestCase(typeof(NotAnonymousType<int>), ExpectedResult = true)]
309+
[TestCase(typeof(DateTime?), ExpectedResult = false)]
310+
[TestCase(typeof(DateTime), ExpectedResult = false)]
311+
public bool IsCompilerGenerated([NotNull] Type type) => type.IsCompilerGenerated();
312+
313+
#if TARGETS_NET || NETSTANDARD20_OR_GREATER
314+
[TestCase(typeof(NotAnonymousType<int>), ExpectedResult = false)]
315+
[TestCase(typeof(DateTime?), ExpectedResult = true)]
316+
[TestCase(typeof(DateTime), ExpectedResult = true)]
317+
public bool IsBrowsable([NotNull] Type type) => type.IsBrowsable();
318+
#endif
319+
296320
#region Inner types
297321
private class A
298322
{

CodeJam.Main/Reflection/ReflectionExtensions.cs

Lines changed: 84 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.ComponentModel;
34
using System.Reflection;
45
using System.Runtime.CompilerServices;
56
using System.Text;
@@ -502,24 +503,6 @@ public static Type GetMemberType([NotNull] this MemberInfo memberInfo)
502503
_ => throw new InvalidOperationException()
503504
};
504505
}
505-
506-
/// <summary>
507-
/// Checks if <paramref name="type"/> is an anonymous type.
508-
/// </summary>
509-
/// <param name="type">Type to check.</param>
510-
/// <returns>True, if <paramref name="type"/> is an anonymous type.</returns>
511-
[Pure]
512-
public static bool IsAnonymous([NotNull] this Type type)
513-
{
514-
Code.NotNull(type, nameof(type));
515-
516-
return !type.GetIsPublic()
517-
&& type.GetIsGenericType()
518-
&& (type.Name.StartsWith("<>f__AnonymousType", StringComparison.Ordinal)
519-
|| type.Name.StartsWith("VB$AnonymousType", StringComparison.Ordinal))
520-
&& type.GetIsDefined(typeof(CompilerGeneratedAttribute), false);
521-
}
522-
523506
/// <summary>
524507
/// Returns default constructor.
525508
/// </summary>
@@ -587,5 +570,88 @@ public static Type GetItemType([CanBeNull] this Type type)
587570
type = type.GetBaseType();
588571
}
589572
}
573+
574+
/// <summary>
575+
/// Checks if <paramref name="type"/> is an anonymous type.
576+
/// </summary>
577+
/// <param name="type">Type to check.</param>
578+
/// <returns>True, if <paramref name="type"/> is an anonymous type.</returns>
579+
[Pure]
580+
public static bool IsAnonymous([NotNull] this Type type)
581+
{
582+
Code.NotNull(type, nameof(type));
583+
584+
return !type.GetIsPublic()
585+
&& type.GetIsGenericType()
586+
&& (type.Name.StartsWith("<>f__AnonymousType", StringComparison.Ordinal)
587+
|| type.Name.StartsWith("VB$AnonymousType", StringComparison.Ordinal))
588+
&& type.GetIsDefined(typeof(CompilerGeneratedAttribute), false);
589+
}
590+
591+
/// <summary>
592+
/// Checks if <typeparamref name="TAttribute"/> is defined on <paramref name="type"/>.
593+
/// </summary>
594+
/// <param name="type">Type to check.</param>
595+
/// <returns>True, if <typeparamref name="TAttribute"/> is defined on <paramref name="type"/></returns>
596+
[Pure]
597+
public static bool IsDefined<TAttribute>([NotNull] this Type type) where TAttribute : Attribute
598+
{
599+
Code.NotNull(type, nameof(type));
600+
601+
return type.IsDefined(typeof(TAttribute));
602+
}
603+
604+
/// <summary>
605+
/// Checks if <typeparamref name="TAttribute"/> is defined on <paramref name="member"/>.
606+
/// </summary>
607+
/// <param name="member">Member to check.</param>
608+
/// <returns>True, if <typeparamref name="TAttribute"/> is defined on <paramref name="member"/></returns>
609+
[Pure]
610+
public static bool IsDefined<TAttribute>([NotNull] this MemberInfo member) where TAttribute : Attribute
611+
{
612+
Code.NotNull(member, nameof(member));
613+
614+
return member.IsDefined(typeof(TAttribute));
615+
}
616+
617+
/// <summary>
618+
/// Checks if <paramref name="type"/> is compiler generated type.
619+
/// </summary>
620+
/// <param name="type">Type to check.</param>
621+
/// <returns>True, if <paramref name="type"/> is generated by compiler.</returns>
622+
[Pure]
623+
public static bool IsCompilerGenerated([NotNull] this Type type) => type.IsDefined<CompilerGeneratedAttribute>();
624+
625+
/// <summary>
626+
/// Checks if <paramref name="member"/> is is compiler generated member.
627+
/// </summary>
628+
/// <param name="member">Member to check.</param>
629+
/// <returns>True, if <paramref name="member"/> is generated by compiler.</returns>
630+
[Pure]
631+
public static bool IsCompilerGenerated([NotNull] this MemberInfo member) => member.IsDefined<CompilerGeneratedAttribute>();
632+
633+
#if TARGETS_NET || NETSTANDARD20_OR_GREATER || NETCOREAPP20_OR_GREATER // PUBLIC_API_CHANGES
634+
/// <summary>
635+
/// Checks if <paramref name="type"/> has no <see cref="BrowsableAttribute"/> defined
636+
/// -or-
637+
/// <see cref="BrowsableAttribute.Browsable"/> equals to <c>true</c>.
638+
/// </summary>
639+
/// <param name="type">Type to check.</param>
640+
/// <returns>True, if <paramref name="type"/> is browsable.</returns>
641+
[Pure]
642+
public static bool IsBrowsable([NotNull] this Type type) =>
643+
type.GetCustomAttribute<BrowsableAttribute>()?.Browsable ?? true;
644+
645+
/// <summary>
646+
/// Checks if <paramref name="member"/> has no <see cref="BrowsableAttribute"/> defined
647+
/// -or-
648+
/// <see cref="BrowsableAttribute.Browsable"/> equals to <c>true</c>.
649+
/// </summary>
650+
/// <param name="member">Member to check.</param>
651+
/// <returns>True, if <paramref name="member"/> is browsable.</returns>
652+
[Pure]
653+
public static bool IsBrowsable([NotNull] this MemberInfo member) =>
654+
member.GetCustomAttribute<BrowsableAttribute>()?.Browsable ?? true;
655+
#endif
590656
}
591657
}

CodeJam.Main/Targeting/TypeExtensions.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,14 @@ public static bool GetIsAssignableFrom([NotNull] this Type type, [NotNull] Type
233233
[MethodImpl(AggressiveInlining)]
234234
public static bool GetIsSubclassOf([NotNull] this Type type, [NotNull] Type c) => type.GetTypeInfo().IsSubclassOf(c);
235235

236+
[MethodImpl(AggressiveInlining)]
237+
public static bool IsDefined([NotNull] this Type type, Type attributeType) =>
238+
type.GetTypeInfo().IsDefined(attributeType);
239+
240+
[MethodImpl(AggressiveInlining)]
241+
public static bool IsDefined([NotNull] this Type type, Type attributeType, bool inherit) =>
242+
type.GetTypeInfo().IsDefined(attributeType, inherit);
243+
236244
[MethodImpl(AggressiveInlining)]
237245
public static T GetCustomAttribute<T>([NotNull] this Type type) where T : Attribute =>
238246
type.GetTypeInfo().GetCustomAttribute<T>();

CodeJam.sln.DotSettings

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -390,6 +390,7 @@ Code.NotNull($EXPR$, $NAME$);</s:String>
390390
<s:Boolean x:Key="/Default/UserDictionary/Words/=BADCODE/@EntryIndexedValue">True</s:Boolean>
391391
<s:Boolean x:Key="/Default/UserDictionary/Words/=BASEDON/@EntryIndexedValue">True</s:Boolean>
392392
<s:Boolean x:Key="/Default/UserDictionary/Words/=beforefieldinit/@EntryIndexedValue">True</s:Boolean>
393+
<s:Boolean x:Key="/Default/UserDictionary/Words/=browsable/@EntryIndexedValue">True</s:Boolean>
393394
<s:Boolean x:Key="/Default/UserDictionary/Words/=canbenull/@EntryIndexedValue">True</s:Boolean>
394395
<s:Boolean x:Key="/Default/UserDictionary/Words/=codegen/@EntryIndexedValue">True</s:Boolean>
395396
<s:Boolean x:Key="/Default/UserDictionary/Words/=comparers/@EntryIndexedValue">True</s:Boolean>

0 commit comments

Comments
 (0)