A game framework written with osu! in mind.
1// Copyright (c) ppy Pty Ltd <contact@ppy.sh>. Licensed under the MIT Licence.
2// See the LICENCE file in the repository root for full licence text.
3
4using System;
5using System.Linq;
6using System.Reflection;
7using osu.Framework.Extensions.TypeExtensions;
8
9namespace osu.Framework.Development
10{
11 internal static class ReflectionUtils
12 {
13 // taken from https://github.com/nunit/nunit/blob/73dbcce0896a6897a2add4281cc48734eca546a2/src/NUnitFramework/framework/Internal/Reflect.cs
14 // as it was removed/refactored in nunit 3.13.1
15
16 // ***********************************************************************
17 // Copyright (c) 2007-2018 Charlie Poole, Rob Prouse
18 //
19 // Permission is hereby granted, free of charge, to any person obtaining
20 // a copy of this software and associated documentation files (the
21 // "Software"), to deal in the Software without restriction, including
22 // without limitation the rights to use, copy, modify, merge, publish,
23 // distribute, sublicense, and/or sell copies of the Software, and to
24 // permit persons to whom the Software is furnished to do so, subject to
25 // the following conditions:
26 //
27 // The above copyright notice and this permission notice shall be
28 // included in all copies or substantial portions of the Software.
29 //
30 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
31 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
32 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
33 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
34 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
35 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
36 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
37 // ***********************************************************************
38
39 private const BindingFlags all_members = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
40
41 /// <summary>
42 /// Returns all methods declared by the specified fixture type that have the specified attribute, optionally
43 /// including base classes. Methods from a base class are always returned before methods from a class that
44 /// inherits from it.
45 /// </summary>
46 /// <param name="fixtureType">The type to examine.</param>
47 /// <param name="attributeType">Only methods to which this attribute is applied will be returned.</param>
48 /// <param name="inherit">Specifies whether to search the fixture type inheritance chain.</param>
49 internal static MethodInfo[] GetMethodsWithAttribute(Type fixtureType, Type attributeType, bool inherit)
50 {
51 if (!inherit)
52 {
53 return fixtureType
54 .GetMethods(all_members | BindingFlags.DeclaredOnly)
55 .Where(method => method.IsDefined(attributeType, inherit: false))
56 .ToArray();
57 }
58
59 var methodsByDeclaringType = fixtureType
60 .GetMethods(all_members | BindingFlags.FlattenHierarchy) // FlattenHierarchy is complex to replicate by looping over base types with DeclaredOnly.
61 .Where(method => method.IsDefined(attributeType, inherit: true))
62 .ToLookup(method => method.DeclaringType);
63
64 return fixtureType
65 .EnumerateBaseTypes()
66 .Reverse()
67 .SelectMany(declaringType => methodsByDeclaringType[declaringType])
68 .ToArray();
69 }
70 }
71}