rubymirrors 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|