1+ using System . Diagnostics ;
12using System . Reflection ;
23using HarmonyLib ;
34using NeoModLoader . constants ;
45
56namespace NeoModLoader . services ;
67
8+ [ AttributeUsage ( AttributeTargets . Method | AttributeTargets . Class ) ]
9+ public class DebugAttribute : Attribute { }
710public static class DebugService
811{
9- static void Debugger ( MethodBase __originalMethod )
12+ static bool IsDebuggable ( MethodBase method )
1013 {
11- LogService . LogInfo ( __originalMethod . ToString ( ) ) ;
14+ if ( method . IsAbstract || method . ContainsGenericParameters || method . IsSpecialName || method . Name . Contains ( "<" ) )
15+ {
16+ return false ;
17+ }
18+ return true ;
1219 }
13- static readonly Harmony Patcher = new Harmony ( Others . harmony_id ) ;
14- private static readonly HarmonyMethod Hook = new ( AccessTools . Method ( typeof ( DebugService ) , nameof ( Debugger ) ) ) ;
15- public static void AttachDebugger ( Assembly assembly )
20+ public abstract class Debugger
1621 {
17- foreach ( var Type in assembly . GetTypes ( ) )
22+ protected HarmonyMethod Prefix ;
23+ protected HarmonyMethod Postfix ;
24+ protected HarmonyMethod Finalizer ;
25+ public void Attach ( Assembly assembly , Func < MethodBase , bool > predicate = null )
1826 {
27+ foreach ( var Type in assembly . GetTypes ( ) )
28+ {
29+ Attach ( Type , predicate ) ;
30+ }
31+ }
32+ public void Attach ( Type Type , Func < MethodBase , bool > predicate = null )
33+ {
34+ predicate ??= Default ;
1935 foreach ( var method in Type . GetMethods (
2036 BindingFlags . Public |
2137 BindingFlags . NonPublic |
2238 BindingFlags . Instance |
2339 BindingFlags . Static |
24- BindingFlags . DeclaredOnly ) )
40+ BindingFlags . DeclaredOnly ) . Where ( m => IsDebuggable ( m ) && predicate ( m ) ) )
2541 {
26- Patcher . Patch ( method , Hook ) ;
42+ Attach ( method ) ;
2743 }
28- }
29- }
30- public static void RemoveDebugger ( Assembly assembly )
31- {
32- foreach ( var Type in assembly . GetTypes ( ) )
33- {
34- foreach ( var method in Type . GetMethods (
44+ foreach ( var method in Type . GetConstructors (
3545 BindingFlags . Public |
3646 BindingFlags . NonPublic |
3747 BindingFlags . Instance |
3848 BindingFlags . Static |
39- BindingFlags . DeclaredOnly ) )
49+ BindingFlags . DeclaredOnly ) . Where ( m => IsDebuggable ( m ) && predicate ( m ) ) )
50+ {
51+ Attach ( method ) ;
52+ }
53+ }
54+ public void Attach ( MethodBase method )
55+ {
56+ try
4057 {
41- Patcher . Unpatch ( method , HarmonyPatchType . Prefix ) ;
58+ Patcher . Patch ( method , Prefix , Postfix , null , Finalizer , null ) ;
59+ }
60+ catch ( Exception e )
61+ {
62+ LogService . LogError ( $ "Failed to attach debugger to { method . FullDescription ( ) } due to { e } ") ;
4263 }
4364 }
4465 }
66+ public class LogDebugger : Debugger
67+ {
68+ static void prefix ( MethodBase __originalMethod )
69+ {
70+ LogService . Log ( __originalMethod . ToString ( ) ) ;
71+ }
72+ public LogDebugger ( )
73+ {
74+ Prefix = new HarmonyMethod ( AccessTools . Method ( typeof ( LogDebugger ) , nameof ( prefix ) ) ) ;
75+ }
76+ }
77+ public class ProfilerDebugger : Debugger
78+ {
79+ static Stopwatch stopwatch = new ( ) ;
80+ public static void prefix ( out long __state )
81+ {
82+ __state = Stopwatch . GetTimestamp ( ) ;
83+ }
84+ public static void postfix (
85+ MethodBase __originalMethod ,
86+ long __state )
87+ {
88+ LogService . Log (
89+ $ "{ __originalMethod . Name } took { Stopwatch . GetTimestamp ( ) - __state } ") ;
90+ }
91+ public ProfilerDebugger ( )
92+ {
93+ Prefix = new HarmonyMethod ( AccessTools . Method ( typeof ( ProfilerDebugger ) , nameof ( prefix ) ) ) ;
94+ Postfix = new HarmonyMethod ( AccessTools . Method ( typeof ( ProfilerDebugger ) , nameof ( postfix ) ) ) ;
95+ }
96+ }
97+ public class ExceptionDebugger : Debugger
98+ {
99+ static void finalizer ( Exception __exception , MethodBase __original )
100+ {
101+ if ( __exception is not null )
102+ handler ? . Invoke ( __exception , __original ) ;
103+ }
104+ public ExceptionDebugger ( )
105+ {
106+ Finalizer = new HarmonyMethod ( AccessTools . Method ( typeof ( ExceptionDebugger ) , nameof ( finalizer ) ) ) ;
107+ }
108+ public static void AddHandler ( ExceptionHandler Handler )
109+ {
110+ handler += Handler ;
111+ }
112+ public delegate void ExceptionHandler ( Exception Exception , MethodBase Method ) ;
113+ public static event ExceptionHandler handler ;
114+ }
115+ static readonly Harmony Patcher = new Harmony ( Others . harmony_id ) ;
116+ public static readonly LogDebugger Logger = new ( ) ;
117+ public static readonly ProfilerDebugger Profiler = new ( ) ;
118+ public static readonly ExceptionDebugger ExceptionHandler = new ( ) ;
119+ static readonly Func < MethodBase , bool > Default = _ => true ;
120+ static readonly Func < MethodBase , bool > Attribute = method => method . IsDefined ( typeof ( DebugAttribute ) , true ) || method . DeclaringType ? . IsDefined ( typeof ( DebugAttribute ) , true ) == true ;
45121}
0 commit comments