rubymirrors 0.0.1
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/Gemfile +7 -0
- data/README.md +30 -0
- data/Rakefile +13 -0
- data/lib/abstract_reflection.rb +112 -0
- data/lib/abstract_reflection/class_mirror.rb +150 -0
- data/lib/abstract_reflection/compiler_mirror.rb +31 -0
- data/lib/abstract_reflection/field_mirror.rb +35 -0
- data/lib/abstract_reflection/gc_mirror.rb +19 -0
- data/lib/abstract_reflection/method_mirror.rb +253 -0
- data/lib/abstract_reflection/mirror.rb +108 -0
- data/lib/abstract_reflection/object_mirror.rb +48 -0
- data/lib/abstract_reflection/stack_frame_mirror.rb +61 -0
- data/lib/abstract_reflection/thread_mirror.rb +64 -0
- data/lib/maglev/reflection.rb +49 -0
- data/lib/maglev/reflection/class_mirror.rb +157 -0
- data/lib/maglev/reflection/core_ext/class_organizer.rb +20 -0
- data/lib/maglev/reflection/core_ext/maglev.rb +5 -0
- data/lib/maglev/reflection/core_ext/method.rb +154 -0
- data/lib/maglev/reflection/core_ext/module.rb +41 -0
- data/lib/maglev/reflection/core_ext/object.rb +4 -0
- data/lib/maglev/reflection/core_ext/thread.rb +226 -0
- data/lib/maglev/reflection/field_mirror.rb +39 -0
- data/lib/maglev/reflection/field_mirror/fixed_instance_variable_mirror.rb +25 -0
- data/lib/maglev/reflection/method_mirror.rb +149 -0
- data/lib/maglev/reflection/mirror.rb +6 -0
- data/lib/maglev/reflection/object_mirror.rb +18 -0
- data/lib/maglev/reflection/stack_frame_mirror.rb +104 -0
- data/lib/maglev/reflection/thread_mirror.rb +116 -0
- data/lib/rubinius/reflection.rb +6 -0
- data/lib/ruby/reflection.rb +74 -0
- data/lib/ruby/reflection/class_mirror.rb +89 -0
- data/lib/ruby/reflection/field_mirror.rb +32 -0
- data/lib/ruby/reflection/field_mirror/class_variable_mirror.rb +25 -0
- data/lib/ruby/reflection/field_mirror/constant_mirror.rb +36 -0
- data/lib/ruby/reflection/field_mirror/instance_variable_mirror.rb +25 -0
- data/lib/ruby/reflection/method_mirror.rb +122 -0
- data/lib/ruby/reflection/mirror.rb +12 -0
- data/lib/ruby/reflection/object_mirror.rb +25 -0
- data/lib/ruby/reflection/stack_frame_mirror.rb +49 -0
- data/lib/ruby/reflection/support/shift_reset.rb +29 -0
- data/lib/ruby/reflection/thread_mirror.rb +47 -0
- data/rubymirrors.gemspec +12 -0
- data/spec/class_spec.rb +92 -0
- data/spec/field_spec.rb +119 -0
- data/spec/fixtures/class_spec.rb +29 -0
- data/spec/fixtures/field_spec.rb +9 -0
- data/spec/fixtures/method_spec.rb +14 -0
- data/spec/fixtures/object_spec.rb +5 -0
- data/spec/fixtures/reflect_spec.rb +14 -0
- data/spec/fixtures/stack_frame_spec.rb +5 -0
- data/spec/fixtures/thread_spec.rb +5 -0
- data/spec/frame_spec.rb +80 -0
- data/spec/method_spec.rb +166 -0
- data/spec/object_spec.rb +18 -0
- data/spec/reflection_spec.rb +74 -0
- data/spec/spec_helper.rb +16 -0
- data/spec/spec_helper/mspec_patch.rb +29 -0
- data/spec/spec_helper/multiple_reflections.rb +14 -0
- data/spec/thread_spec.rb +142 -0
- metadata +173 -0
@@ -0,0 +1,74 @@
|
|
1
|
+
require 'abstract_reflection'
|
2
|
+
require 'ruby/reflection/mirror'
|
3
|
+
require 'ruby/reflection/object_mirror'
|
4
|
+
require 'ruby/reflection/class_mirror'
|
5
|
+
require 'ruby/reflection/field_mirror'
|
6
|
+
require 'ruby/reflection/thread_mirror'
|
7
|
+
require 'ruby/reflection/stack_frame_mirror'
|
8
|
+
require 'ruby/reflection/method_mirror'
|
9
|
+
|
10
|
+
module Ruby
|
11
|
+
class Reflection
|
12
|
+
include AbstractReflection
|
13
|
+
|
14
|
+
def self.codebase
|
15
|
+
nil.class
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialize(ignored = nil)
|
19
|
+
end
|
20
|
+
|
21
|
+
def modules
|
22
|
+
instances_of(Module)
|
23
|
+
end
|
24
|
+
|
25
|
+
def classes
|
26
|
+
instances_of(Class)
|
27
|
+
end
|
28
|
+
|
29
|
+
def instances_of(klass)
|
30
|
+
mirrors ObjectSpace.each_object(klass).select {|obj| obj.class == klass }
|
31
|
+
end
|
32
|
+
|
33
|
+
def object_by_id(id)
|
34
|
+
if obj = ObjectSpace._id2ref(id)
|
35
|
+
reflect obj
|
36
|
+
else
|
37
|
+
nil
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def threads
|
42
|
+
instances_of(Thread)
|
43
|
+
end
|
44
|
+
|
45
|
+
def platform
|
46
|
+
Object::RUBY_PLATFORM
|
47
|
+
end
|
48
|
+
|
49
|
+
def engine
|
50
|
+
Object::RUBY_ENGINE
|
51
|
+
end
|
52
|
+
|
53
|
+
def version
|
54
|
+
Object.const_get("#{engine.upcase}_VERSION")
|
55
|
+
end
|
56
|
+
|
57
|
+
def implementations_of(str)
|
58
|
+
mirrors methods.select {|m| m.name.to_s == str.to_s }
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
def methods
|
63
|
+
ObjectSpace.each_object(Module).collect do |m|
|
64
|
+
ims = m.instance_methods(false).collect {|s| m.instance_method(s) }
|
65
|
+
cms = m.methods(false).collect {|s| m.method(s) }
|
66
|
+
ims + cms
|
67
|
+
end.flatten
|
68
|
+
end
|
69
|
+
|
70
|
+
def mirrors(list)
|
71
|
+
list.collect {|each| reflect each }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
@@ -0,0 +1,89 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Reflection
|
3
|
+
class ClassMirror < ObjectMirror
|
4
|
+
include AbstractReflection::ClassMirror
|
5
|
+
reflect! Module
|
6
|
+
|
7
|
+
def class_variables
|
8
|
+
field_mirrors @subject.class_variables
|
9
|
+
end
|
10
|
+
|
11
|
+
def class_instance_variables
|
12
|
+
field_mirrors @subject.instance_variables
|
13
|
+
end
|
14
|
+
|
15
|
+
def source_files
|
16
|
+
locations = @subject.instance_methods(false).collect do |name|
|
17
|
+
method = @subject.instance_method(name)
|
18
|
+
file = method.source_location if method.respond_to? :source_location
|
19
|
+
file.first if file
|
20
|
+
end
|
21
|
+
locations.compact.uniq
|
22
|
+
end
|
23
|
+
|
24
|
+
def singleton_class
|
25
|
+
reflection.reflect @subject.singleton_class
|
26
|
+
end
|
27
|
+
|
28
|
+
def singleton_class?
|
29
|
+
self.name =~ /^\#<Class:.*>$/
|
30
|
+
end
|
31
|
+
|
32
|
+
def mixins
|
33
|
+
mirrors @subject.ancestors.reject {|m| m.is_a? Class }
|
34
|
+
end
|
35
|
+
|
36
|
+
def superclass
|
37
|
+
reflection.reflect @subject.superclass
|
38
|
+
end
|
39
|
+
|
40
|
+
def subclasses
|
41
|
+
l = ObjectSpace.each_object(Class).select {|a| a.superclass == @subject }
|
42
|
+
mirrors l
|
43
|
+
end
|
44
|
+
|
45
|
+
def ancestors
|
46
|
+
mirrors @subject.ancestors
|
47
|
+
end
|
48
|
+
|
49
|
+
def constants
|
50
|
+
field_mirrors @subject.constants
|
51
|
+
end
|
52
|
+
|
53
|
+
def constant(str)
|
54
|
+
path = str.to_s.split("::")
|
55
|
+
c = path[0..-2].inject(@subject) {|klass,str| klass.const_get(str) }
|
56
|
+
field_mirror (c || @subject), path.last
|
57
|
+
rescue NameError => e
|
58
|
+
p e
|
59
|
+
nil
|
60
|
+
end
|
61
|
+
|
62
|
+
def nesting
|
63
|
+
ary = []
|
64
|
+
@subject.name.split("::").inject(Object) do |klass,str|
|
65
|
+
ary << klass.const_get(str)
|
66
|
+
ary.last
|
67
|
+
end
|
68
|
+
ary.reverse
|
69
|
+
rescue NameError => e
|
70
|
+
[@subject]
|
71
|
+
end
|
72
|
+
|
73
|
+
def nested_classes
|
74
|
+
nc = @subject.constants.collect do |c|
|
75
|
+
@subject.const_get(c) if @subject.const_defined? c
|
76
|
+
end.compact.select {|c| Module === c }
|
77
|
+
mirrors nc
|
78
|
+
end
|
79
|
+
|
80
|
+
def methods
|
81
|
+
@subject.instance_methods(false).collect(&:to_s)
|
82
|
+
end
|
83
|
+
|
84
|
+
def method(name)
|
85
|
+
reflection.reflect @subject.instance_method(name)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Reflection
|
3
|
+
class FieldMirror < Mirror
|
4
|
+
include AbstractReflection::FieldMirror
|
5
|
+
Field = Struct.new(:object, :name)
|
6
|
+
reflect! Field
|
7
|
+
|
8
|
+
def self.mirror_class(field)
|
9
|
+
return unless reflects? field
|
10
|
+
case field.name.to_s
|
11
|
+
when /^@@/ then ClassVariableMirror
|
12
|
+
when /^@/ then InstanceVariableMirror
|
13
|
+
else ConstantMirror
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def initialize(obj)
|
18
|
+
super
|
19
|
+
@object = obj.object
|
20
|
+
@name = obj.name.to_s
|
21
|
+
end
|
22
|
+
|
23
|
+
def name
|
24
|
+
@name
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
require 'ruby/reflection/field_mirror/class_variable_mirror'
|
31
|
+
require 'ruby/reflection/field_mirror/instance_variable_mirror'
|
32
|
+
require 'ruby/reflection/field_mirror/constant_mirror'
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Reflection
|
3
|
+
class ClassVariableMirror < FieldMirror
|
4
|
+
def value
|
5
|
+
reflection.reflect @object.class_variable_get(@name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def value=(o)
|
9
|
+
@object.class_variable_set(@name, o)
|
10
|
+
end
|
11
|
+
|
12
|
+
def public?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def protected?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def private?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Reflection
|
3
|
+
class ConstantMirror < FieldMirror
|
4
|
+
def value
|
5
|
+
if path = @object.autoload?(@name)
|
6
|
+
unless $LOADED_FEATURES.include?(path) ||
|
7
|
+
$LOADED_FEATURES.include?(File.expand_path(path))
|
8
|
+
# Do not trigger autoload
|
9
|
+
return nil
|
10
|
+
end
|
11
|
+
end
|
12
|
+
reflection.reflect @object.const_get(@name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def value=(o)
|
16
|
+
@object.const_set(@name, o)
|
17
|
+
end
|
18
|
+
|
19
|
+
def public?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def protected?
|
24
|
+
false
|
25
|
+
end
|
26
|
+
|
27
|
+
def private?
|
28
|
+
false
|
29
|
+
end
|
30
|
+
|
31
|
+
def delete
|
32
|
+
@object.send(:remove_const, @name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Reflection
|
3
|
+
class InstanceVariableMirror < FieldMirror
|
4
|
+
def value
|
5
|
+
reflection.reflect @object.instance_variable_get(@name)
|
6
|
+
end
|
7
|
+
|
8
|
+
def value=(o)
|
9
|
+
@object.instance_variable_set(@name, o)
|
10
|
+
end
|
11
|
+
|
12
|
+
def public?
|
13
|
+
false
|
14
|
+
end
|
15
|
+
|
16
|
+
def protected?
|
17
|
+
false
|
18
|
+
end
|
19
|
+
|
20
|
+
def private?
|
21
|
+
true
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,122 @@
|
|
1
|
+
begin
|
2
|
+
require 'method_source'
|
3
|
+
rescue LoadError
|
4
|
+
end
|
5
|
+
begin
|
6
|
+
require 'ruby_parser' unless defined? RubyParser
|
7
|
+
rescue LoadError
|
8
|
+
end
|
9
|
+
|
10
|
+
module Ruby
|
11
|
+
class Reflection
|
12
|
+
class MethodMirror < Mirror
|
13
|
+
include AbstractReflection::MethodMirror
|
14
|
+
reflect! Method, UnboundMethod
|
15
|
+
|
16
|
+
def file
|
17
|
+
source_location.first
|
18
|
+
end
|
19
|
+
|
20
|
+
def file=(name)
|
21
|
+
defining_class.reflectee.class_eval(source, name, line)
|
22
|
+
@subject = defining_class.method(selector)
|
23
|
+
end
|
24
|
+
|
25
|
+
def line
|
26
|
+
source_location.last
|
27
|
+
end
|
28
|
+
|
29
|
+
def line=(num)
|
30
|
+
defining_class.reflectee.class_eval(source, file, num)
|
31
|
+
@subject = defining_class.method(selector)
|
32
|
+
end
|
33
|
+
|
34
|
+
def selector
|
35
|
+
@subject.name.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
def defining_class
|
39
|
+
reflection.reflect try_send(:owner)
|
40
|
+
end
|
41
|
+
|
42
|
+
def delete
|
43
|
+
try_send(:owner).send(:remove_method, @subject.name)
|
44
|
+
end
|
45
|
+
|
46
|
+
def block_argument
|
47
|
+
args(:block).first
|
48
|
+
end
|
49
|
+
|
50
|
+
def splat_argument
|
51
|
+
args(:rest).first
|
52
|
+
end
|
53
|
+
|
54
|
+
def optional_arguments
|
55
|
+
args(:opt)
|
56
|
+
end
|
57
|
+
|
58
|
+
def required_arguments
|
59
|
+
args(:req)
|
60
|
+
end
|
61
|
+
|
62
|
+
def arguments
|
63
|
+
try_send(:parameters).map { |t,a| a.to_s }
|
64
|
+
end
|
65
|
+
|
66
|
+
def protected?
|
67
|
+
visibility? :protected
|
68
|
+
end
|
69
|
+
|
70
|
+
def public?
|
71
|
+
visibility? :public
|
72
|
+
end
|
73
|
+
|
74
|
+
def private?
|
75
|
+
visibility? :private
|
76
|
+
end
|
77
|
+
|
78
|
+
def source
|
79
|
+
try_send(:source) or raise(CapabilitiesExceeded)
|
80
|
+
end
|
81
|
+
|
82
|
+
def step_offsets
|
83
|
+
[1, *send_offsets.values]
|
84
|
+
end
|
85
|
+
|
86
|
+
def send_offsets
|
87
|
+
sexp = RubyParser.new.process(source).flatten
|
88
|
+
sends = sexp.each_with_index.map {|e,i| sexp[i-1] if e == :arglist }
|
89
|
+
sends = sends.compact.collect(&:to_s)
|
90
|
+
|
91
|
+
offsets = [0]
|
92
|
+
sends.each do |name|
|
93
|
+
offsets << (source[offsets.last..-1] =~ /#{Regexp.escape(name)}/)
|
94
|
+
end
|
95
|
+
offsets.shift
|
96
|
+
Hash[*sends.zip(offsets).flatten]
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def visibility?(type)
|
102
|
+
list = try_send(:owner).send("#{type}_instance_methods")
|
103
|
+
list.any? { |m| m.to_s == selector }
|
104
|
+
end
|
105
|
+
|
106
|
+
def try_send(method)
|
107
|
+
raise CapabilitiesExceeded unless @subject.respond_to? method
|
108
|
+
@subject.send(method)
|
109
|
+
end
|
110
|
+
|
111
|
+
def args(type)
|
112
|
+
args = []
|
113
|
+
try_send(:parameters).select { |t,n| args << n.to_s if t == type }
|
114
|
+
args
|
115
|
+
end
|
116
|
+
|
117
|
+
def source_location
|
118
|
+
try_send(:source_location) or raise(CapabilitiesExceeded)
|
119
|
+
end
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Ruby
|
2
|
+
class Reflection
|
3
|
+
class ObjectMirror < Mirror
|
4
|
+
include AbstractReflection::ObjectMirror
|
5
|
+
reflect! (defined?(BasicObject) ? BasicObject : Object)
|
6
|
+
|
7
|
+
def variables
|
8
|
+
field_mirrors @subject.instance_variables
|
9
|
+
end
|
10
|
+
|
11
|
+
def target_class
|
12
|
+
reflection.reflect @subject.class
|
13
|
+
end
|
14
|
+
|
15
|
+
private
|
16
|
+
def field_mirrors(list, subject = @subject)
|
17
|
+
list.collect {|name| field_mirror subject, name }
|
18
|
+
end
|
19
|
+
|
20
|
+
def field_mirror(subject, name)
|
21
|
+
reflection.reflect FieldMirror::Field.new(subject, name)
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|