summaryrefslogtreecommitdiffhomepage
path: root/dragon/trace.rb
diff options
context:
space:
mode:
authorAmir Rajan <[email protected]>2020-02-27 20:14:39 -0600
committerAmir Rajan <[email protected]>2020-02-27 20:14:39 -0600
commit5d0c0305854633122b3e800dd9058e93c2950eb6 (patch)
tree0283825a7055cebd59ad1b3aff1b3dec1f2ac03c /dragon/trace.rb
parent07468bf3f309c21ea3f7fcf47195ca275177dc7f (diff)
downloaddragonruby-game-toolkit-contrib-5d0c0305854633122b3e800dd9058e93c2950eb6.tar.gz
dragonruby-game-toolkit-contrib-5d0c0305854633122b3e800dd9058e93c2950eb6.zip
open sourced parts of game toolkit.
Diffstat (limited to 'dragon/trace.rb')
-rw-r--r--dragon/trace.rb150
1 files changed, 150 insertions, 0 deletions
diff --git a/dragon/trace.rb b/dragon/trace.rb
new file mode 100644
index 0000000..c3b4bbd
--- /dev/null
+++ b/dragon/trace.rb
@@ -0,0 +1,150 @@
+# coding: utf-8
+# Copyright 2019 DragonRuby LLC
+# MIT License
+# trace.rb has been released under MIT (*only this file*).
+
+module GTK
+ module Trace
+ IGNORED_METHODS = [
+ :define_singleton_method, :raise_immediately, :instance_of?,
+ :raise_with_caller, :initialize_copy, :class_defined?,
+ :instance_variable_get, :format, :purge_class, :instance_variable_defined?,
+ :metadata_object_id, :instance_variable_set, :__printstr__,
+ :instance_variables, :is_a?, :p, :kind_of?, :==, :log_once,
+ :protected_methods, :log_once_info, :private_methods, :open,
+ :!=, :initialize, :object_id, :Hash, :methods, :tick, :!,
+ :respond_to?, :yield_self, :send, :instance_eval, :then,
+ :__method__, :__send__, :log_print, :dig, :itself, :log_info,
+ :remove_instance_variable, :raise, :public_methods, :instance_exec,
+ :gets, :local_variables, :tap, :__id__, :class, :singleton_class,
+ :block_given?, :_inspect, :puts, :global_variables, :getc, :iterator?,
+ :hash, :to_enum, :printf, :frozen?, :print, :original_puts,
+ :srand, :freeze, :rand, :extend, :eql?, :equal?, :sprintf, :clone,
+ :dup, :to_s, :primitive_determined?, :inspect, :primitive?, :help,
+ :__object_methods__, :proc, :__custom_object_methods__, :Float, :enum_for,
+ :__supports_ivars__?, :nil?, :fast_rand, :or, :and,
+ :__caller_without_noise__, :__gtk_ruby_string_contains_source_file_path__?,
+ :__pretty_print_exception__, :__gtk_ruby_source_files__,
+ :String, :log, :Array, :putsc, :Integer, :===, :here,
+ :raise_error_with_kind_of_okay_message, :better_instance_information,
+ :lambda, :fail, :method_missing, :__case_eqq, :caller,
+ :raise_method_missing_better_error, :require, :singleton_methods,
+ :!~, :loop, :numeric_or_default, :`, :state, :inputs, :outputs, "args=".to_sym,
+ :grid, :gtk, :dragon, :args, :passes, :tick, :grep_source, :grep_source_file,
+ :numeric_or_default, :f_or_default, :s_or_default, :i_or_default,
+ :comment, :primitive_marker, :xrepl, :repl
+ ]
+
+ def self.traced_classes
+ @traced_classes ||= []
+ @traced_classes
+ end
+
+ def self.mark_class_as_traced! klass
+ @traced_classes << klass
+ end
+
+ def self.untrace_classes!
+ traced_classes.each do |klass|
+ klass.class_eval do
+ all_methods = klass.instance_methods false
+ if klass.instance_methods.respond_to?(:__trace_call_depth__)
+ undef_method :__trace_call_depth__
+ end
+
+ GTK::Trace.filter_methods_to_trace(all_methods).each do |m|
+ original_method_name = m
+ trace_method_name = GTK::Trace.trace_method_name_for m
+ if klass.instance_methods.include? trace_method_name
+ alias_method m, trace_method_name
+ end
+ end
+ end
+ end
+ $last_method_traced = nil
+ @traced_classes.clear
+ $trace_enabled = false
+ if !$gtk.production
+ $gtk.write_file 'logs/trace.txt', "Add trace!(SOMEOBJECT) to the top of `tick` and this file will be populated with invocation information.\n"
+ end
+ end
+
+ def self.trace_method_name_for m
+ "__trace_original_#{m}__".to_sym
+ end
+
+ def self.original_method_name_for m
+ return m unless m.to_s.start_with?("__trace_original_") && m.to_s.end_with?("__")
+ m[16..-3]
+ end
+
+ def self.filter_methods_to_trace methods
+ methods.reject { |m| m.start_with? "__trace_" }.reject { |m| IGNORED_METHODS.include? m }
+ end
+
+ def self.flush_trace pad_with_newline = false
+ $trace_puts ||= []
+ if $trace_puts.length > 0
+ text = $trace_puts.join("")
+ if pad_with_newline
+ $gtk.append_file 'logs/trace.txt', "\n" + text.strip
+ else
+ $gtk.append_file 'logs/trace.txt', text.strip
+ end
+ end
+ $trace_puts.clear
+ end
+
+ def self.trace! instance = nil
+ $trace_history ||= []
+ $trace_enabled = true
+ $trace_call_depth ||=0
+ flush_trace
+ instance = $top_level unless instance
+ return if Trace.traced_classes.include? instance.class
+ all_methods = instance.class.instance_methods false
+ instance.class.class_eval do
+ attr_accessor :__trace_call_depth__ unless instance.class.instance_methods.include?(:__trace_call_depth__)
+ GTK::Trace.filter_methods_to_trace(all_methods).each do |m|
+ original_method_name = m
+ trace_method_name = GTK::Trace.trace_method_name_for m
+ alias_method trace_method_name, m
+ $trace_puts << "Tracing #{m} on #{instance.class}.\n"
+ define_method(m) do |*args|
+ instance.__trace_call_depth__ ||= 0
+ tab_width = " " * (instance.__trace_call_depth__ * 8)
+ instance.__trace_call_depth__ += 1
+ $trace_call_depth = instance.__trace_call_depth__
+ parameters = "#{args}"[1..-2]
+ $trace_puts << "\n #{tab_width}#{m}(#{parameters})"
+ execution_time = Time.new.to_i
+ $last_method_traced = trace_method_name
+ $trace_history << [m, parameters]
+ result = send(trace_method_name, *args)
+ completion_time = Time.new.to_i
+ instance.__trace_call_depth__ -= 1
+ instance.__trace_call_depth__ = instance.__trace_call_depth__.greater 0
+ $trace_puts << "\n #{tab_width} success: #{m}"
+ if instance.__trace_call_depth__ == 0
+ $trace_puts << "\n"
+ $trace_history.clear
+ end
+ result
+ rescue Exception => e
+ instance.__trace_call_depth__ -= 1
+ instance.__trace_call_depth__ = instance.__trace_call_depth__.greater 0
+ $trace_puts << "\n #{tab_width} failed: #{m}"
+ if instance.__trace_call_depth__ == 0
+ $trace_puts << "\n #{tab_width} #{e}"
+ $trace_puts << "\n"
+ end
+ $trace_call_depth = 0
+ GTK::Trace.flush_trace true
+ raise e
+ end
+ end
+ end
+ mark_class_as_traced! instance.class
+ end
+ end
+end