GFunk911-rubytypeassert 0.0.1 → 0.0.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/aspect.rb +67 -0
- data/core_ext.rb +156 -0
- data/intel.rb +149 -0
- metadata +4 -2
data/aspect.rb
ADDED
@@ -0,0 +1,67 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'ostruct'
|
3
|
+
|
4
|
+
class MethodRuns
|
5
|
+
attr_accessor :method_name, :method_class
|
6
|
+
def initialize(c,n)
|
7
|
+
@method_name = n.to_s
|
8
|
+
@method_class = c.to_s
|
9
|
+
end
|
10
|
+
#:return: => Object
|
11
|
+
def runs
|
12
|
+
@runs ||= []
|
13
|
+
end
|
14
|
+
def log_run!(r)
|
15
|
+
raise 'wrong' unless method_name == r.method_name.to_s and method_class = r.method_class.to_s
|
16
|
+
runs << r
|
17
|
+
end
|
18
|
+
#:return: => Object
|
19
|
+
def arg_classes
|
20
|
+
runs.map { |r| r.args.map { |x| x.class } }.uniq
|
21
|
+
end
|
22
|
+
def return_classes
|
23
|
+
runs.map { |r| r.return.class }.uniq
|
24
|
+
end
|
25
|
+
#:return: => Object
|
26
|
+
def to_s
|
27
|
+
"#{method_class} / #{method_name}"
|
28
|
+
end
|
29
|
+
#:return: => Object
|
30
|
+
def summary
|
31
|
+
"#{method_class}##{method_name}, returns: #{return_classes.inspect}, args: #{arg_classes.inspect}"
|
32
|
+
end
|
33
|
+
#:return: => Object
|
34
|
+
def self.run_hash
|
35
|
+
@run_hash ||= Hash.new { |h,k| h[k] = new(*k) }
|
36
|
+
end
|
37
|
+
#:return: => Object
|
38
|
+
def self.runs
|
39
|
+
run_hash.values
|
40
|
+
end
|
41
|
+
#:return: => Object
|
42
|
+
def self.log_run!(r)
|
43
|
+
run_hash[[r.method_class.to_s,r.method_name.to_s]].log_run!(r)
|
44
|
+
end
|
45
|
+
#:return: => Object
|
46
|
+
def self.get(c,n)
|
47
|
+
run_hash[[c.to_s,n.to_s]]
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
def add_advice!(*advised_classes)
|
52
|
+
require 'aquarium'
|
53
|
+
advised_classes.flatten.each do |cls|
|
54
|
+
Aquarium::Aspects::Aspect.new :around, :calls_to => cls.uniq_instance_methods, :on_types => cls do |jp, object, *args|
|
55
|
+
#p "Entering: #{join_point.target_type.name}##{join_point.method_name} for object #{object}"
|
56
|
+
result = jp.proceed
|
57
|
+
#p "Leaving: #{join_point.target_type.name}##{join_point.method_name} for object #{object}"
|
58
|
+
MethodRuns.log_run! OpenStruct.new(:method_class => jp.target_type.name, :method_name => jp.method_name, :args => args, :return => result)
|
59
|
+
result # block needs to return the result of the "proceed"!
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
at_exit do
|
65
|
+
File.create("method_runs.txt",MethodRuns.runs.map { |x| x.summary }.join("\n"))
|
66
|
+
end
|
67
|
+
|
data/core_ext.rb
ADDED
@@ -0,0 +1,156 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'facets/file/write'
|
3
|
+
require 'facets/enumerable/collect'
|
4
|
+
class Object
|
5
|
+
def common_methods
|
6
|
+
7.methods + "".methods + 7.class.methods + "".class.methods + ActiveRecord::Base.instance_methods
|
7
|
+
end
|
8
|
+
def uniq_methods
|
9
|
+
(methods - common_methods).sort
|
10
|
+
end
|
11
|
+
def uniq_instance_methods(include_ar=true)
|
12
|
+
(instance_methods - common_methods - superclass.instance_methods - uniq_modules.map { |x| x.instance_methods }.flatten + (include_ar ? ar_methods : [])).sort
|
13
|
+
end
|
14
|
+
def uniq_modules
|
15
|
+
included_modules - superclass.included_modules
|
16
|
+
end
|
17
|
+
def ar_methods
|
18
|
+
return [] unless inherits_from?(ActiveRecord::Base)
|
19
|
+
columns.map { |x| x.name }.map { |x| [x,"#{x}="] }.flatten
|
20
|
+
end
|
21
|
+
def inherits_from?(x)
|
22
|
+
return true if superclass == x
|
23
|
+
return false unless superclass
|
24
|
+
superclass.inherits_from?(x)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
|
29
|
+
class Object
|
30
|
+
def tap
|
31
|
+
yield(self)
|
32
|
+
self
|
33
|
+
end
|
34
|
+
end
|
35
|
+
class Hash
|
36
|
+
def summary
|
37
|
+
keys.sort_by { |x| x.to_s }.map { |k| "#{k}: #{self[k]}" }.join("\n")
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
|
42
|
+
class Class
|
43
|
+
def cond_accessor(*names)
|
44
|
+
names.flatten.each do |name|
|
45
|
+
define_method(name) do |*args|
|
46
|
+
instance_variable_set("@#{name}",args.first) unless args.empty?
|
47
|
+
instance_variable_get("@#{name}")
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
class Object
|
54
|
+
def klass
|
55
|
+
self.class
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def eat_exceptions
|
60
|
+
yield
|
61
|
+
rescue
|
62
|
+
return nil
|
63
|
+
end
|
64
|
+
|
65
|
+
class Object
|
66
|
+
def from_hash(ops)
|
67
|
+
ops.each { |k,v| send("#{k}=",v) unless (v == :UNSET_FIELD) }
|
68
|
+
self
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
class Class
|
73
|
+
def from_hash(ops)
|
74
|
+
new.from_hash(ops)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
class Object
|
79
|
+
def lazy_method(sym,&b)
|
80
|
+
send(:define_method,sym) do
|
81
|
+
instance_variable_set("@#{sym}",instance_eval(&b)) if instance_variable_get("@#{sym}").nil?
|
82
|
+
instance_variable_get("@#{sym}")
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
class Object
|
88
|
+
#attr_accessor :system
|
89
|
+
end
|
90
|
+
|
91
|
+
def log(x)
|
92
|
+
puts x
|
93
|
+
File.append(File.dirname(__FILE__) + "/output.log",x.to_s+"\n")
|
94
|
+
end
|
95
|
+
|
96
|
+
def debug(x)
|
97
|
+
end
|
98
|
+
|
99
|
+
class WIN32OLE
|
100
|
+
include Enumerable
|
101
|
+
def first
|
102
|
+
each { |x| return x }
|
103
|
+
end
|
104
|
+
def size
|
105
|
+
self.Count
|
106
|
+
end
|
107
|
+
def pruned_methods
|
108
|
+
ole_methods.map { |x| x.to_s.gsub(/\d/,"") }.uniq.sort
|
109
|
+
end
|
110
|
+
end
|
111
|
+
|
112
|
+
module ForwardableExtension
|
113
|
+
def delegate_to(object, new_method, *args)
|
114
|
+
options = args.last.is_a?(Hash) ? args.pop : {}
|
115
|
+
args.each do |element|
|
116
|
+
def_delegator object, element, new_method.to_sym
|
117
|
+
if options[:writer]
|
118
|
+
def_delegator object, :"#{element}=", :"#{new_method}="
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
protected
|
124
|
+
def name_with_prefix(element, options)
|
125
|
+
"#{options[:prefix] + "_" unless options[:prefix].nil? }#{element}"
|
126
|
+
end
|
127
|
+
end
|
128
|
+
|
129
|
+
require 'forwardable'
|
130
|
+
Forwardable.send :include, ForwardableExtension
|
131
|
+
|
132
|
+
module Enumerable
|
133
|
+
def propagate_to!(target)
|
134
|
+
each { |x| x.propagate_to!(target) }
|
135
|
+
end
|
136
|
+
end
|
137
|
+
|
138
|
+
def tm(str,num=1)
|
139
|
+
t = Time.now
|
140
|
+
res = nil
|
141
|
+
num.times { res = yield }
|
142
|
+
sec = Time.now - t
|
143
|
+
puts "#{str} took #{sec} seconds (#{res})"
|
144
|
+
end
|
145
|
+
|
146
|
+
class Object
|
147
|
+
def to_is
|
148
|
+
self ? to_i.to_s : nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
class Object
|
153
|
+
def nvl(x)
|
154
|
+
self || x
|
155
|
+
end
|
156
|
+
end
|
data/intel.rb
ADDED
@@ -0,0 +1,149 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
class Object
|
3
|
+
def lazy_method(sym,&b)
|
4
|
+
send(:define_method,sym) do
|
5
|
+
instance_variable_set("@#{sym}",instance_eval(&b)) if instance_variable_get("@#{sym}").nil?
|
6
|
+
instance_variable_get("@#{sym}")
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
class OS
|
12
|
+
def each(&b)
|
13
|
+
ObjectSpace.each_object(&b)
|
14
|
+
end
|
15
|
+
include Enumerable
|
16
|
+
def self.method_missing(sym,*args,&b)
|
17
|
+
new.send(sym,*args,&b)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def current_classes
|
22
|
+
OS.select { |x| x.is_a?(Class) }.uniq
|
23
|
+
end
|
24
|
+
|
25
|
+
def local_class_names
|
26
|
+
$local_class_names ||= Dir["**/*.rb"].map do |filename|
|
27
|
+
File.new(filename).read.scan(/^\s*class (\S+)(?: |$)/).flatten
|
28
|
+
end.flatten.map { |x| x.split(":")[-1] }.sort
|
29
|
+
end
|
30
|
+
|
31
|
+
def init_classes
|
32
|
+
$init_classes ||= current_classes
|
33
|
+
end
|
34
|
+
|
35
|
+
def generate_local_class_defs!(req_file)
|
36
|
+
init_classes
|
37
|
+
load req_file
|
38
|
+
str = local_class_defs.map { |x| x.class_str }.join("\n")
|
39
|
+
File.create("local_class_defs.rb",str)
|
40
|
+
end
|
41
|
+
|
42
|
+
def local_class_defs
|
43
|
+
$local_class_defs ||= (current_classes - init_classes).select { |x| local_class_names.include?(x.to_s.split(":")[-1]) }.map { |x| ClassDef.new(x) }
|
44
|
+
end
|
45
|
+
|
46
|
+
class String
|
47
|
+
def prefix_each_line(pre)
|
48
|
+
pre + self[0..-2].gsub(/\n/,"\n#{pre}") + self[-1..-1]
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
module DefModule
|
53
|
+
def modules
|
54
|
+
cls.to_s.split(":")[0..-2].select { |x| x != '' }
|
55
|
+
end
|
56
|
+
def class_spaces
|
57
|
+
" "*2*modules.size
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
class ClassDef
|
62
|
+
include DefModule
|
63
|
+
attr_accessor :cls
|
64
|
+
def initialize(c)
|
65
|
+
@cls = c
|
66
|
+
end
|
67
|
+
def bare_cls
|
68
|
+
cls.to_s.split(':')[-1]
|
69
|
+
end
|
70
|
+
def class_str
|
71
|
+
str = ''
|
72
|
+
modules.each_with_index { |x,i| str << " "*i*2 + "module #{x}\n" }
|
73
|
+
str << class_spaces + "class #{bare_cls}"
|
74
|
+
str << " < #{cls.superclass}" unless [Object,nil].include?(cls.superclass)
|
75
|
+
str << "\n"
|
76
|
+
cls.uniq_modules.each { |x| str << "#{class_spaces} include #{x}\n" }
|
77
|
+
str << methods_str
|
78
|
+
str << class_spaces + "end\n"
|
79
|
+
modules.each_with_index { |x,i| str << " "*i*2 + "end\n" }
|
80
|
+
str
|
81
|
+
end
|
82
|
+
lazy_method(:methods) do
|
83
|
+
cls.uniq_instance_methods.map { |x| MethodDef.new(cls,x) }
|
84
|
+
end
|
85
|
+
def methods_str
|
86
|
+
methods.map { |x| x.method_str }.join("")
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
class MethodDef
|
91
|
+
include DefModule
|
92
|
+
attr_accessor :cls, :name
|
93
|
+
def initialize(c,n)
|
94
|
+
@cls = c
|
95
|
+
@name = n.to_s.downcase
|
96
|
+
end
|
97
|
+
def method_obj
|
98
|
+
eat_exceptions { cls.instance_method(m) }
|
99
|
+
end
|
100
|
+
def arity
|
101
|
+
method_obj ? method_obj.arity : 0
|
102
|
+
end
|
103
|
+
def arg_str
|
104
|
+
(0...arity).map { |x| ("a"[0]+x).chr }.join(",")
|
105
|
+
end
|
106
|
+
def manual_method_str
|
107
|
+
str = "#{class_spaces} # manual meth def\n"
|
108
|
+
str << "#{class_spaces} def #{name}(#{arg_str})\n"
|
109
|
+
str << "#{class_spaces} end\n"
|
110
|
+
str
|
111
|
+
end
|
112
|
+
def runs
|
113
|
+
MethodRuns.get(cls,name)
|
114
|
+
end
|
115
|
+
def return_type
|
116
|
+
runs.return_classes.flatten.first || Object
|
117
|
+
end
|
118
|
+
def type_comments
|
119
|
+
"#{class_spaces} #:return: => #{return_type}\n"
|
120
|
+
end
|
121
|
+
lazy_method(:method_body) do
|
122
|
+
eat_exceptions { RubyToRuby.translate(cls,name).prefix_each_line(class_spaces+" ") + "\n" } || manual_method_str
|
123
|
+
end
|
124
|
+
def arg_names
|
125
|
+
return [] if method_body.strip =~ /^attr_/
|
126
|
+
arg_str = method_body.scan(/def.*#{name}(.*)$/).flatten.first
|
127
|
+
raise "no arg_str for #{cls} #{name} /def.*#{name}(.*)$/" unless arg_str
|
128
|
+
return [] if arg_str.strip == '' or arg_str.strip == '()'
|
129
|
+
arg_str[1..-2].split(",")
|
130
|
+
end
|
131
|
+
def arg_type(i)
|
132
|
+
(runs.arg_classes[i]||[]).first || Object
|
133
|
+
end
|
134
|
+
def arg_comments
|
135
|
+
arg_names.map_with_index do |arg,i|
|
136
|
+
"#{class_spaces} #:arg: #{arg} => #{arg_type(i)}\n"
|
137
|
+
end.join("")
|
138
|
+
end
|
139
|
+
def method_str
|
140
|
+
type_comments + arg_comments + method_body
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def rta_run!(req_file)
|
145
|
+
require 'ruby2ruby'
|
146
|
+
generate_local_class_defs!(req_file)
|
147
|
+
add_advice!(ActiveRecord::Base)
|
148
|
+
generate_local_class_defs!(req_file)
|
149
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: GFunk911-rubytypeassert
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Mike Harris
|
@@ -22,7 +22,9 @@ extensions: []
|
|
22
22
|
extra_rdoc_files: []
|
23
23
|
|
24
24
|
files:
|
25
|
-
-
|
25
|
+
- aspect.rb
|
26
|
+
- core_ext.rb
|
27
|
+
- intel.rb
|
26
28
|
has_rdoc: false
|
27
29
|
homepage: http://github.com/GFunk911/RubyTypeAssert
|
28
30
|
post_install_message:
|