looksee 3.1.1 → 4.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG +9 -0
- data/README.markdown +61 -81
- data/ext/extconf.rb +3 -7
- data/ext/mri/2.3.0/internal.h +1404 -0
- data/ext/mri/2.3.0/method.h +213 -0
- data/ext/mri/mri.c +21 -264
- data/ext/rbx/rbx.c +0 -9
- data/lib/looksee/JRuby.jar +0 -0
- data/lib/looksee/adapter/base.rb +19 -54
- data/lib/looksee/adapter/rubinius.rb +3 -62
- data/lib/looksee/clean.rb +5 -1
- data/lib/looksee/editor.rb +1 -1
- data/lib/looksee/help.rb +3 -2
- data/lib/looksee/lookup_path.rb +7 -3
- data/lib/looksee/version.rb +1 -1
- data/spec/looksee/adapter_spec.rb +72 -365
- data/spec/looksee/editor_spec.rb +1 -1
- data/spec/looksee/inspector_spec.rb +21 -21
- data/spec/looksee/lookup_path_spec.rb +34 -21
- data/spec/spec_helper.rb +2 -0
- data/spec/support/temporary_classes.rb +10 -14
- data/spec/support/test_adapter.rb +2 -53
- metadata +6 -29
- data/ext/mri/1.9.2/debug.h +0 -36
- data/ext/mri/1.9.2/id.h +0 -170
- data/ext/mri/1.9.2/method.h +0 -103
- data/ext/mri/1.9.2/node.h +0 -483
- data/ext/mri/1.9.2/thread_pthread.h +0 -27
- data/ext/mri/1.9.2/vm_core.h +0 -707
- data/ext/mri/1.9.2/vm_opts.h +0 -51
- data/ext/mri/1.9.3/atomic.h +0 -56
- data/ext/mri/1.9.3/debug.h +0 -41
- data/ext/mri/1.9.3/id.h +0 -175
- data/ext/mri/1.9.3/internal.h +0 -227
- data/ext/mri/1.9.3/internal_falcon.h +0 -248
- data/ext/mri/1.9.3/method.h +0 -105
- data/ext/mri/1.9.3/node.h +0 -503
- data/ext/mri/1.9.3/thread_pthread.h +0 -51
- data/ext/mri/1.9.3/vm_core.h +0 -755
- data/ext/mri/1.9.3/vm_opts.h +0 -51
- data/ext/mri/2.0.0/internal.h +0 -378
- data/ext/mri/2.0.0/method.h +0 -138
- data/ext/mri/env-1.8.h +0 -27
- data/ext/mri/eval_c-1.8.h +0 -27
- data/ext/mri/node-1.9.h +0 -35
- data/lib/looksee/mri.bundle +0 -0
data/ext/rbx/rbx.c
CHANGED
@@ -1,13 +1,4 @@
|
|
1
1
|
#include "ruby.h"
|
2
2
|
|
3
|
-
VALUE Looksee_internal_class(VALUE self, VALUE object) {
|
4
|
-
return CLASS_OF(object);
|
5
|
-
}
|
6
|
-
|
7
3
|
void Init_rbx(void) {
|
8
|
-
VALUE mLooksee = rb_const_get(rb_cObject, rb_intern("Looksee"));
|
9
|
-
VALUE mAdapter = rb_const_get(mLooksee, rb_intern("Adapter"));
|
10
|
-
VALUE mBase = rb_const_get(mAdapter, rb_intern("Base"));
|
11
|
-
VALUE mRubinius = rb_define_class_under(mAdapter, "Rubinius", mBase);
|
12
|
-
rb_define_method(mRubinius, "internal_class", Looksee_internal_class, 1);
|
13
4
|
}
|
Binary file
|
data/lib/looksee/adapter/base.rb
CHANGED
@@ -6,13 +6,14 @@ module Looksee
|
|
6
6
|
# object's method lookup path.
|
7
7
|
#
|
8
8
|
def lookup_modules(object)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
9
|
+
start =
|
10
|
+
begin
|
11
|
+
singleton_class = (class << object; self; end)
|
12
|
+
singleton_class unless has_no_methods?(singleton_class) && !(Class === object)
|
13
|
+
rescue TypeError # immediate object
|
14
|
+
end
|
15
|
+
start ||= Looksee.safe_call(Object, :class, object)
|
16
|
+
start.ancestors
|
16
17
|
end
|
17
18
|
|
18
19
|
#
|
@@ -21,17 +22,19 @@ module Looksee
|
|
21
22
|
# This is used for the module labels in the Inspector output.
|
22
23
|
#
|
23
24
|
def describe_module(mod)
|
25
|
+
Module === mod or
|
26
|
+
raise TypeError, "expected Module, got: #{mod.inspect}"
|
24
27
|
num_brackets = 0
|
25
28
|
object = mod
|
26
|
-
while
|
29
|
+
while (instance = singleton_instance(object))
|
27
30
|
num_brackets += 1
|
28
|
-
object =
|
31
|
+
object = instance
|
29
32
|
end
|
30
33
|
|
31
|
-
if
|
34
|
+
if object.is_a?(Module)
|
32
35
|
description = module_name(object)
|
33
36
|
if description.empty?
|
34
|
-
is_class =
|
37
|
+
is_class = Class === object
|
35
38
|
description = "unnamed #{is_class ? 'Class' : 'Module'}"
|
36
39
|
end
|
37
40
|
else
|
@@ -45,40 +48,14 @@ module Looksee
|
|
45
48
|
end
|
46
49
|
end
|
47
50
|
|
48
|
-
def real_module(module_or_included_class)
|
49
|
-
module_or_included_class
|
50
|
-
end
|
51
|
-
|
52
|
-
def internal_superclass(klass)
|
53
|
-
raise NotImplementedError, "abstract"
|
54
|
-
end
|
55
|
-
|
56
|
-
def internal_class(object)
|
57
|
-
raise NotImplementedError, "abstract"
|
58
|
-
end
|
59
|
-
|
60
|
-
def included_class?(object)
|
61
|
-
raise NotImplementedError, "abstract"
|
62
|
-
end
|
63
|
-
|
64
|
-
def internal_public_instance_methods(mod)
|
65
|
-
raise NotImplementedError, "abstract"
|
66
|
-
end
|
67
|
-
|
68
|
-
def internal_protected_instance_methods(mod)
|
69
|
-
raise NotImplementedError, "abstract"
|
70
|
-
end
|
71
|
-
|
72
|
-
def internal_private_instance_methods(mod)
|
73
|
-
raise NotImplementedError, "abstract"
|
74
|
-
end
|
75
|
-
|
76
51
|
def internal_undefined_instance_methods(mod)
|
77
52
|
raise NotImplementedError, "abstract"
|
78
53
|
end
|
79
54
|
|
80
|
-
def
|
81
|
-
|
55
|
+
def has_no_methods?(mod)
|
56
|
+
[:public, :protected, :private].all? do |visibility|
|
57
|
+
Looksee.safe_call(Module, "#{visibility}_instance_methods", mod, false).empty?
|
58
|
+
end && internal_undefined_instance_methods(mod).empty?
|
82
59
|
end
|
83
60
|
|
84
61
|
def singleton_instance(singleton_class)
|
@@ -86,19 +63,7 @@ module Looksee
|
|
86
63
|
end
|
87
64
|
|
88
65
|
def module_name(mod)
|
89
|
-
|
90
|
-
end
|
91
|
-
|
92
|
-
if RUBY_VERSION >= '1.9.0' || Looksee.ruby_engine == 'rbx'
|
93
|
-
def source_location(method)
|
94
|
-
method.is_a?(UnboundMethod) or
|
95
|
-
raise TypeError, "expected UnboundMethod, got #{method.class}"
|
96
|
-
method.source_location
|
97
|
-
end
|
98
|
-
else
|
99
|
-
def source_location(method)
|
100
|
-
raise NotImplementedError, 'abstract'
|
101
|
-
end
|
66
|
+
Looksee.safe_call(Module, :name, mod) || ''
|
102
67
|
end
|
103
68
|
end
|
104
69
|
end
|
@@ -4,25 +4,6 @@ require 'looksee/rbx'
|
|
4
4
|
module Looksee
|
5
5
|
module Adapter
|
6
6
|
class Rubinius < Base
|
7
|
-
def internal_superclass(klass)
|
8
|
-
klass.direct_superclass
|
9
|
-
end
|
10
|
-
|
11
|
-
def internal_public_instance_methods(mod)
|
12
|
-
return [] if !mod.origin.equal?(mod)
|
13
|
-
mod.method_table.public_names
|
14
|
-
end
|
15
|
-
|
16
|
-
def internal_protected_instance_methods(mod)
|
17
|
-
return [] if !mod.origin.equal?(mod)
|
18
|
-
mod.method_table.protected_names
|
19
|
-
end
|
20
|
-
|
21
|
-
def internal_private_instance_methods(mod)
|
22
|
-
return [] if !mod.origin.equal?(mod)
|
23
|
-
mod.method_table.private_names
|
24
|
-
end
|
25
|
-
|
26
7
|
def internal_undefined_instance_methods(mod)
|
27
8
|
return [] if !mod.origin.equal?(mod)
|
28
9
|
names = []
|
@@ -32,51 +13,11 @@ module Looksee
|
|
32
13
|
names
|
33
14
|
end
|
34
15
|
|
35
|
-
def included_class?(object)
|
36
|
-
object.is_a?(::Rubinius::IncludedModule)
|
37
|
-
end
|
38
|
-
|
39
|
-
def singleton_class?(object)
|
40
|
-
object.is_a?(Class) && !!::Rubinius::Type.singleton_class_object(object)
|
41
|
-
end
|
42
|
-
|
43
16
|
def singleton_instance(singleton_class)
|
44
|
-
singleton_class
|
45
|
-
|
46
|
-
::Rubinius::Type.singleton_class_object(singleton_class)
|
47
|
-
end
|
48
|
-
|
49
|
-
def module_name(mod)
|
50
|
-
mod.is_a?(Module) or
|
51
|
-
raise TypeError, "expected module, got #{mod.class}"
|
52
|
-
|
53
|
-
if ::Rubinius::IncludedModule === mod
|
54
|
-
if Class === mod.module
|
55
|
-
"#{module_name(mod.module)} (origin)"
|
56
|
-
else
|
57
|
-
module_name(mod.module)
|
58
|
-
end
|
59
|
-
elsif ::Rubinius::Type.respond_to?(:module_name)
|
60
|
-
::Rubinius::Type.module_name(mod) || ''
|
17
|
+
if Class === singleton_class && (instance = ::Rubinius::Type.singleton_class_object(singleton_class))
|
18
|
+
instance
|
61
19
|
else
|
62
|
-
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
def source_location(method)
|
67
|
-
method.is_a?(UnboundMethod) or
|
68
|
-
raise TypeError, "expected UnboundMethod, got #{method.class}"
|
69
|
-
source_location = method.source_location and
|
70
|
-
return source_location
|
71
|
-
|
72
|
-
# #source_location doesn't always work. If it returns nil, try
|
73
|
-
# a little harder.
|
74
|
-
case (executable = method.executable)
|
75
|
-
when ::Rubinius::BlockEnvironment::AsMethod
|
76
|
-
method = executable.instance_variable_get(:@block_env).method
|
77
|
-
[method.file.to_s, method.lines[1]]
|
78
|
-
when ::Rubinius::DelegatedMethod
|
79
|
-
executable.instance_variable_get(:@receiver).source_location
|
20
|
+
nil
|
80
21
|
end
|
81
22
|
end
|
82
23
|
end
|
data/lib/looksee/clean.rb
CHANGED
@@ -15,7 +15,6 @@ module Looksee
|
|
15
15
|
autoload :Help, 'looksee/help'
|
16
16
|
autoload :Inspector, 'looksee/inspector'
|
17
17
|
autoload :LookupPath, 'looksee/lookup_path'
|
18
|
-
autoload :WirbleCompatibility, 'looksee/wirble_compatibility'
|
19
18
|
|
20
19
|
class << self
|
21
20
|
#
|
@@ -138,6 +137,11 @@ module Looksee
|
|
138
137
|
def help
|
139
138
|
Help.new
|
140
139
|
end
|
140
|
+
|
141
|
+
# Call mod#method on receiver, ignoring any overrides in receiver's class.
|
142
|
+
def safe_call(mod, name, receiver, *args) # :nodoc:
|
143
|
+
mod.instance_method(name).bind(receiver).call(*args)
|
144
|
+
end
|
141
145
|
end
|
142
146
|
|
143
147
|
self.default_specifiers = [:public, :protected, :private, :undefined, :overridden]
|
data/lib/looksee/editor.rb
CHANGED
@@ -15,7 +15,7 @@ module Looksee
|
|
15
15
|
def edit(object, method_name)
|
16
16
|
method = LookupPath.new(object).find(method_name.to_s) or
|
17
17
|
raise NoMethodError, "no method `#{method_name}' in lookup path of #{object.class} instance"
|
18
|
-
file, line =
|
18
|
+
file, line = method.source_location
|
19
19
|
if !file
|
20
20
|
raise NoSourceLocationError, "no source location for #{method.owner}##{method.name}"
|
21
21
|
elsif !File.exist?(file)
|
data/lib/looksee/help.rb
CHANGED
@@ -4,7 +4,8 @@ module Looksee
|
|
4
4
|
<<-EOS.gsub(/^ *\|/, '')
|
5
5
|
|== Looksee Quick Reference
|
6
6
|
|
|
7
|
-
|
|
7
|
+
| \e[1mobject.ls(*specifiers)\e[0m or \e[1mLooksee[object, *specifiers]\e[0m
|
8
|
+
|
|
8
9
|
| Print the methods of \`object\'.
|
9
10
|
|
|
10
11
|
| Available specifiers:
|
@@ -40,7 +41,7 @@ module Looksee
|
|
40
41
|
| ...
|
41
42
|
| }
|
42
43
|
|
|
43
|
-
|
|
44
|
+
| \e[1mobject.ls.edit(method)\e[0m
|
44
45
|
|
|
45
46
|
| Jump to the source of the given method. Set your editor
|
46
47
|
| with Looksee.editor or the LOOKSEE_EDITOR environment
|
data/lib/looksee/lookup_path.rb
CHANGED
@@ -28,7 +28,7 @@ module Looksee
|
|
28
28
|
if visibility == :undefined
|
29
29
|
return nil
|
30
30
|
else
|
31
|
-
return Looksee.
|
31
|
+
return Looksee.safe_call(Module, :instance_method, entry.module, name)
|
32
32
|
end
|
33
33
|
end
|
34
34
|
nil
|
@@ -83,11 +83,15 @@ module Looksee
|
|
83
83
|
|
84
84
|
def find_methods
|
85
85
|
methods = {}
|
86
|
-
[:public, :protected, :private
|
87
|
-
Looksee.
|
86
|
+
[:public, :protected, :private].each do |visibility|
|
87
|
+
meths = Looksee.safe_call(Module, "#{visibility}_instance_methods", @module, false)
|
88
|
+
meths.each do |method|
|
88
89
|
methods[method.to_s] = visibility
|
89
90
|
end
|
90
91
|
end
|
92
|
+
Looksee.adapter.send("internal_undefined_instance_methods", @module).each do |method|
|
93
|
+
methods[method.to_s] = :undefined
|
94
|
+
end
|
91
95
|
methods
|
92
96
|
end
|
93
97
|
end
|
data/lib/looksee/version.rb
CHANGED
@@ -30,15 +30,11 @@ describe "Looksee.adapter" do
|
|
30
30
|
junk_patterns = [
|
31
31
|
# pollution from testing libraries
|
32
32
|
'Mocha', 'Spec',
|
33
|
-
# RSpec adds this under ruby 1.8.6
|
34
|
-
'InstanceExecHelper',
|
35
33
|
# RSpec 2
|
36
34
|
'RSpec::',
|
37
|
-
#
|
38
|
-
'BasicObject',
|
39
|
-
# something pulls this in under ruby 1.9
|
35
|
+
# not sure what pulls this in
|
40
36
|
'PP',
|
41
|
-
# our own pollution
|
37
|
+
# our own pollution
|
42
38
|
'Looksee::ObjectMixin',
|
43
39
|
]
|
44
40
|
pattern = /\b(#{junk_patterns.join('|')})\b/
|
@@ -53,22 +49,22 @@ describe "Looksee.adapter" do
|
|
53
49
|
include Mod1
|
54
50
|
include Mod2
|
55
51
|
end
|
56
|
-
filtered_lookup_modules(Derived.new) ==
|
57
|
-
['Derived', 'Mod2', 'Mod1', 'Base', 'Object', 'Kernel']
|
52
|
+
filtered_lookup_modules(Derived.new).should ==
|
53
|
+
['Derived', 'Mod2', 'Mod1', 'Base', 'Object', 'Kernel', 'BasicObject']
|
58
54
|
end
|
59
55
|
|
60
|
-
it "should contain an entry for the object's singleton class if it
|
56
|
+
it "should contain an entry for the object's singleton class if it has methods" do
|
61
57
|
object = Object.new
|
62
|
-
object.
|
58
|
+
def object.f; end
|
63
59
|
|
64
60
|
filtered_lookup_modules(object).should ==
|
65
|
-
['[Object instance]', 'Object', 'Kernel']
|
61
|
+
['[Object instance]', 'Object', 'Kernel', 'BasicObject']
|
66
62
|
end
|
67
63
|
|
68
64
|
it "should contain entries for singleton classes of all ancestors for class objects" do
|
69
65
|
temporary_class :C
|
70
66
|
filtered_lookup_modules(C).should ==
|
71
|
-
['[C]', '[Object]', 'Class', 'Module', 'Object', 'Kernel']
|
67
|
+
['[C]', '[Object]', '[BasicObject]', 'Class', 'Module', 'Object', 'Kernel', 'BasicObject']
|
72
68
|
end
|
73
69
|
|
74
70
|
it "should work for immediate objects" do
|
@@ -81,193 +77,60 @@ describe "Looksee.adapter" do
|
|
81
77
|
define_method(:target_method){name}
|
82
78
|
end
|
83
79
|
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
add_methods C, visibility => [:one, :two]
|
88
|
-
@adapter.send(target_method, C).to_set.should == Set[:one, :two]
|
89
|
-
end
|
90
|
-
|
91
|
-
it "should return the list of #{visibility} instance methods defined directly on a module" do
|
92
|
-
temporary_module :M
|
93
|
-
add_methods M, visibility => [:one, :two]
|
94
|
-
@adapter.send(target_method, M).to_set.should == Set[:one, :two]
|
95
|
-
end
|
96
|
-
|
97
|
-
it "should return the list of #{visibility} instance methods defined directly on a singleton class" do
|
98
|
-
temporary_class :C
|
99
|
-
c = C.new
|
100
|
-
add_methods c.singleton_class, visibility => [:one, :two]
|
101
|
-
@adapter.send(target_method, c.singleton_class).to_set.should == Set[:one, :two]
|
102
|
-
end
|
103
|
-
|
104
|
-
it "should return the list of #{visibility} instance methods defined directly on a class' singleton class" do
|
105
|
-
temporary_class :C
|
106
|
-
add_methods C.singleton_class, visibility => [:one, :two], :class_singleton => true
|
107
|
-
@adapter.send(target_method, C.singleton_class).to_set.should == Set[:one, :two]
|
108
|
-
end
|
109
|
-
|
110
|
-
it "should not return undefined methods" do
|
111
|
-
temporary_class :C
|
112
|
-
add_methods C, visibility => [:removed]
|
113
|
-
C.send(:undef_method, :removed)
|
114
|
-
@adapter.send(target_method, C).to_set.should == Set[]
|
115
|
-
end
|
116
|
-
|
117
|
-
if RUBY_VERSION >= '2'
|
118
|
-
it "should return methods only for origin classes" do
|
80
|
+
describe ".internal_undefined_instance_methods" do
|
81
|
+
if Looksee.ruby_engine == 'ruby' && RUBY_VERSION >= '2.3'
|
82
|
+
it "just returns an empty array" do
|
119
83
|
temporary_class :C
|
120
|
-
add_methods C,
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
@adapter.send(target_method, origin).should_not be_empty
|
84
|
+
add_methods C, undefined: [:f]
|
85
|
+
@adapter.internal_undefined_instance_methods(C).should == []
|
86
|
+
end
|
87
|
+
else
|
88
|
+
it "should return the list of undefined instance methods directly on a class" do
|
89
|
+
temporary_class :C
|
90
|
+
add_methods(C, undefined: [:f])
|
91
|
+
@adapter.internal_undefined_instance_methods(C).should == [:f]
|
129
92
|
end
|
130
|
-
end
|
131
|
-
end
|
132
|
-
|
133
|
-
def self.it_should_not_list_methods_with_visibility(visibility1, visibility2)
|
134
|
-
it "should not return any #{visibility1} or #{visibility2} instance methods" do
|
135
|
-
temporary_class :C
|
136
|
-
add_methods C, {visibility1 => [:a], visibility2 => [:b]}
|
137
|
-
@adapter.send(target_method, C).to_set.should == Set[]
|
138
|
-
end
|
139
|
-
end
|
140
|
-
|
141
|
-
describe ".internal_public_instance_methods" do
|
142
|
-
target_method :internal_public_instance_methods
|
143
|
-
it_should_list_methods_with_visibility :public
|
144
|
-
it_should_not_list_methods_with_visibility :private, :protected
|
145
|
-
end
|
146
|
-
|
147
|
-
describe ".internal_protected_instance_methods" do
|
148
|
-
target_method :internal_protected_instance_methods
|
149
|
-
it_should_list_methods_with_visibility :protected
|
150
|
-
it_should_not_list_methods_with_visibility :public, :private
|
151
|
-
end
|
152
|
-
|
153
|
-
describe ".internal_private_instance_methods" do
|
154
|
-
target_method :internal_private_instance_methods
|
155
|
-
it_should_list_methods_with_visibility :private
|
156
|
-
it_should_not_list_methods_with_visibility :public, :protected
|
157
|
-
end
|
158
|
-
|
159
|
-
describe ".internal_undefined_instance_methods" do
|
160
|
-
it "should return the list of undefined instance methods directly on a class" do
|
161
|
-
temporary_class :C
|
162
|
-
C.send(:define_method, :f){}
|
163
|
-
C.send(:undef_method, :f)
|
164
|
-
@adapter.internal_undefined_instance_methods(C).should == [:f]
|
165
|
-
end
|
166
|
-
|
167
|
-
it "should return the list of undefined instance methods directly on a module" do
|
168
|
-
temporary_module :M
|
169
|
-
M.send(:define_method, :f){}
|
170
|
-
M.send(:undef_method, :f)
|
171
|
-
@adapter.internal_undefined_instance_methods(M).should == [:f]
|
172
|
-
end
|
173
|
-
|
174
|
-
it "should return the list of undefined instance methods directly on a singleton class" do
|
175
|
-
temporary_class :C
|
176
|
-
c = C.new
|
177
|
-
c.singleton_class.send(:define_method, :f){}
|
178
|
-
c.singleton_class.send(:undef_method, :f)
|
179
|
-
@adapter.internal_undefined_instance_methods(c.singleton_class).should == [:f]
|
180
|
-
end
|
181
|
-
|
182
|
-
it "should return the list of undefined instance methods directly on a class' singleton class" do
|
183
|
-
temporary_class :C
|
184
|
-
C.singleton_class.send(:define_method, :f){}
|
185
|
-
C.singleton_class.send(:undef_method, :f)
|
186
|
-
@adapter.internal_undefined_instance_methods(C.singleton_class).should == [:f]
|
187
|
-
end
|
188
93
|
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
94
|
+
it "should return the list of undefined instance methods directly on a module" do
|
95
|
+
temporary_module :M
|
96
|
+
add_methods(M, undefined: [:f])
|
97
|
+
@adapter.internal_undefined_instance_methods(M).should == [:f]
|
98
|
+
end
|
194
99
|
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
100
|
+
it "should return the list of undefined instance methods directly on a singleton class" do
|
101
|
+
temporary_class :C
|
102
|
+
c = C.new
|
103
|
+
add_methods(c.singleton_class, undefined: [:f])
|
104
|
+
@adapter.internal_undefined_instance_methods(c.singleton_class).should == [:f]
|
105
|
+
end
|
201
106
|
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
107
|
+
it "should return the list of undefined instance methods directly on a class' singleton class" do
|
108
|
+
temporary_class :C
|
109
|
+
add_methods(C.singleton_class, undefined: [:f])
|
110
|
+
@adapter.internal_undefined_instance_methods(C.singleton_class).should == [:f]
|
111
|
+
end
|
206
112
|
|
207
|
-
|
208
|
-
it "should return an empty list for non-origin classes" do
|
113
|
+
it "should not return defined methods" do
|
209
114
|
temporary_class :C
|
210
115
|
C.send(:define_method, :f){}
|
211
|
-
C.
|
212
|
-
|
213
|
-
M.send(:define_method, :f){}
|
214
|
-
M.send(:undef_method, :f)
|
215
|
-
C.send(:prepend, M)
|
116
|
+
@adapter.internal_undefined_instance_methods(C).should == []
|
117
|
+
end
|
216
118
|
|
217
|
-
|
119
|
+
it "should not return removed methods" do
|
120
|
+
temporary_class :C
|
121
|
+
C.send(:define_method, :f){}
|
122
|
+
C.send(:remove_method, :f)
|
123
|
+
@adapter.internal_undefined_instance_methods(C).should == []
|
124
|
+
end
|
218
125
|
|
219
|
-
|
220
|
-
|
221
|
-
@adapter.internal_undefined_instance_methods(
|
126
|
+
it "should handle the MRI allocator being undefined (e.g. Struct)" do
|
127
|
+
struct_singleton_class = (class << Struct; self; end)
|
128
|
+
@adapter.internal_undefined_instance_methods(struct_singleton_class).should == []
|
222
129
|
end
|
223
130
|
end
|
224
131
|
end
|
225
132
|
end
|
226
133
|
|
227
|
-
describe "#singleton_class?" do
|
228
|
-
it "should return true if the object is a singleton class of an object" do
|
229
|
-
object = (class << Object.new; self; end)
|
230
|
-
@adapter.singleton_class?(object).should == true
|
231
|
-
end
|
232
|
-
|
233
|
-
it "should return true if the object is a singleton class of a class" do
|
234
|
-
object = (class << Class.new; self; end)
|
235
|
-
@adapter.singleton_class?(object).should == true
|
236
|
-
end
|
237
|
-
|
238
|
-
it "should return true if the object is a singleton class of a singleton class" do
|
239
|
-
object = (class << (class << Class.new; self; end); self; end)
|
240
|
-
@adapter.singleton_class?(object).should == true
|
241
|
-
end
|
242
|
-
|
243
|
-
it "should return false if the object is just a class" do
|
244
|
-
object = Class.new
|
245
|
-
@adapter.singleton_class?(object).should == false
|
246
|
-
end
|
247
|
-
|
248
|
-
it "should return false if the object is just a module" do
|
249
|
-
object = Module.new
|
250
|
-
@adapter.singleton_class?(object).should == false
|
251
|
-
end
|
252
|
-
|
253
|
-
it "should return false if the object is just an object" do
|
254
|
-
object = Object.new
|
255
|
-
@adapter.singleton_class?(object).should == false
|
256
|
-
end
|
257
|
-
|
258
|
-
it "should return false if the object is TrueClass" do
|
259
|
-
@adapter.singleton_class?(TrueClass).should == false
|
260
|
-
end
|
261
|
-
|
262
|
-
it "should return false if the object is FalseClass" do
|
263
|
-
@adapter.singleton_class?(FalseClass).should == false
|
264
|
-
end
|
265
|
-
|
266
|
-
it "should return false if the object is NilClass" do
|
267
|
-
@adapter.singleton_class?(NilClass).should == false
|
268
|
-
end
|
269
|
-
end
|
270
|
-
|
271
134
|
describe "singleton_instance" do
|
272
135
|
it "should return the instance of the given singleton class" do
|
273
136
|
object = Object.new
|
@@ -284,88 +147,48 @@ describe "Looksee.adapter" do
|
|
284
147
|
@adapter.singleton_instance((class << mod; self; end)).should equal(mod)
|
285
148
|
end
|
286
149
|
|
287
|
-
it "should
|
288
|
-
|
289
|
-
|
290
|
-
|
150
|
+
it "should return the instance of the given singleton class singleton class" do
|
151
|
+
singleton_class = (class << Class.new; self; end)
|
152
|
+
super_singleton_class = (class << singleton_class; self; end)
|
153
|
+
@adapter.singleton_instance(super_singleton_class).should equal(singleton_class)
|
291
154
|
end
|
292
155
|
|
293
|
-
it "should
|
294
|
-
|
295
|
-
@adapter.singleton_instance(Module.new)
|
296
|
-
end.should raise_error(TypeError)
|
156
|
+
it "should return nil if the given object is just a class" do
|
157
|
+
@adapter.singleton_instance(Class.new).should be_nil
|
297
158
|
end
|
298
159
|
|
299
|
-
it "should
|
300
|
-
|
301
|
-
@adapter.singleton_instance(Object.new)
|
302
|
-
end.should raise_error(TypeError)
|
160
|
+
it "should return nil if the given object is just a module" do
|
161
|
+
@adapter.singleton_instance(Module.new).should be_nil
|
303
162
|
end
|
304
|
-
end
|
305
163
|
|
306
|
-
|
307
|
-
|
308
|
-
::M = Module.new
|
309
|
-
M::N = Module.new
|
310
|
-
begin
|
311
|
-
@adapter.module_name(M::N).should == 'M::N'
|
312
|
-
ensure
|
313
|
-
Object.send :remove_const, :M
|
314
|
-
end
|
164
|
+
it "should return nil if the given object is just a object" do
|
165
|
+
@adapter.singleton_instance(Object.new).should be_nil
|
315
166
|
end
|
316
167
|
|
317
|
-
it "should return the
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
Object.send :remove_const, :M
|
324
|
-
end
|
168
|
+
it "should return nil if the given object is an immediate object" do
|
169
|
+
@adapter.singleton_instance(nil).should be_nil
|
170
|
+
@adapter.singleton_instance(true).should be_nil
|
171
|
+
@adapter.singleton_instance(false).should be_nil
|
172
|
+
@adapter.singleton_instance(1).should be_nil
|
173
|
+
@adapter.singleton_instance(:hi).should be_nil
|
325
174
|
end
|
175
|
+
end
|
326
176
|
|
327
|
-
|
177
|
+
describe "#describe_module" do
|
178
|
+
it "should return the fully-qualified name of a module" do
|
328
179
|
begin
|
329
180
|
::M = Module.new
|
330
|
-
::M::
|
331
|
-
|
332
|
-
'overridden'
|
333
|
-
end
|
334
|
-
def to_s
|
335
|
-
'overridden'
|
336
|
-
end
|
337
|
-
end
|
338
|
-
@adapter.describe_module(M::C).should == 'M::C'
|
181
|
+
::M::N = Module.new
|
182
|
+
@adapter.describe_module(::M::N).should == 'M::N'
|
339
183
|
ensure
|
340
184
|
Object.send :remove_const, :M
|
341
185
|
end
|
342
186
|
end
|
343
187
|
|
344
|
-
it "should return
|
345
|
-
@adapter.module_name(Module.new).should == ''
|
346
|
-
end
|
347
|
-
|
348
|
-
it "should return an empty string for unnamed classes" do
|
349
|
-
@adapter.module_name(Class.new).should == ''
|
350
|
-
end
|
351
|
-
|
352
|
-
it "should return an empty string for singleton classes" do
|
353
|
-
object = Object.new
|
354
|
-
@adapter.module_name((class << object; self; end)).should == ''
|
355
|
-
end
|
356
|
-
|
357
|
-
it "should raise a TypeError if the argumeent is not a module" do
|
358
|
-
lambda do
|
359
|
-
@adapter.module_name(Object.new)
|
360
|
-
end.should raise_error(TypeError)
|
361
|
-
end
|
362
|
-
end
|
363
|
-
|
364
|
-
describe "#describe_module" do
|
365
|
-
it "should return the fully-qualified name of a module" do
|
188
|
+
it "should return the fully-qualified name of a class" do
|
366
189
|
begin
|
367
190
|
::M = Module.new
|
368
|
-
::M::N =
|
191
|
+
::M::N = Class.new
|
369
192
|
@adapter.describe_module(::M::N).should == 'M::N'
|
370
193
|
ensure
|
371
194
|
Object.send :remove_const, :M
|
@@ -462,126 +285,10 @@ describe "Looksee.adapter" do
|
|
462
285
|
end
|
463
286
|
end
|
464
287
|
end
|
465
|
-
end
|
466
|
-
|
467
|
-
describe "#source_location" do
|
468
|
-
def load_source(source)
|
469
|
-
@tmp = "#{ROOT}/spec/tmp"
|
470
|
-
# rbx 1.2.3 caches the file content by file name - ensure file names are different.
|
471
|
-
@source_path = "#@tmp/c#{__id__}.rb"
|
472
|
-
FileUtils.mkdir_p @tmp
|
473
|
-
open(@source_path, 'w') { |f| f.print source }
|
474
|
-
load @source_path
|
475
|
-
@source_path
|
476
|
-
end
|
477
|
-
|
478
|
-
after do
|
479
|
-
FileUtils.rm_rf @tmp if @tmp
|
480
|
-
Object.send(:remove_const, :C) if Object.const_defined?(:C)
|
481
|
-
end
|
482
|
-
|
483
|
-
it "should return the file and line number the given method was defined on" do
|
484
|
-
path = load_source <<-EOS.demargin
|
485
|
-
|class C
|
486
|
-
| def f
|
487
|
-
| end
|
488
|
-
|end
|
489
|
-
EOS
|
490
|
-
method = C.instance_method(:f)
|
491
|
-
@adapter.source_location(method).should == [path, 2]
|
492
|
-
end
|
493
|
-
|
494
|
-
it "should work for methods defined via a block (MRI BMETHOD)" do
|
495
|
-
path = load_source <<-EOS.demargin
|
496
|
-
|class C
|
497
|
-
| define_method :f do
|
498
|
-
| end
|
499
|
-
|end
|
500
|
-
EOS
|
501
|
-
method = C.instance_method(:f)
|
502
|
-
@adapter.source_location(method).should == [path, 2]
|
503
|
-
end
|
504
|
-
|
505
|
-
it "should work for methods defined via a proc (MRI BMETHOD)" do
|
506
|
-
path = load_source <<-EOS.demargin
|
507
|
-
|class C
|
508
|
-
| f = lambda do
|
509
|
-
| end
|
510
|
-
| define_method :f, f
|
511
|
-
|end
|
512
|
-
EOS
|
513
|
-
method = C.instance_method(:f)
|
514
|
-
@adapter.source_location(method).should == [path, 2]
|
515
|
-
end
|
516
|
-
|
517
|
-
it "should work for methods defined via a UnboundMethod (MRI DMETHOD)" do
|
518
|
-
path = load_source <<-EOS.demargin
|
519
|
-
|class C
|
520
|
-
| def f
|
521
|
-
| end
|
522
|
-
| define_method :g, instance_method(:f)
|
523
|
-
|end
|
524
|
-
EOS
|
525
|
-
method = C.instance_method(:g)
|
526
|
-
@adapter.source_location(method).should == [path, 2]
|
527
|
-
end
|
528
|
-
|
529
|
-
it "should work for methods defined via a BoundMethod (MRI DMETHOD)" do
|
530
|
-
path = load_source <<-EOS.demargin
|
531
|
-
|class C
|
532
|
-
| def f
|
533
|
-
| end
|
534
|
-
| define_method :g, new.method(:f)
|
535
|
-
|end
|
536
|
-
EOS
|
537
|
-
method = C.instance_method(:g)
|
538
|
-
@adapter.source_location(method).should == [path, 2]
|
539
|
-
end
|
540
|
-
|
541
|
-
it "should work for methods whose visibility is overridden in a subclass (MRI ZSUPER)" do
|
542
|
-
path = load_source <<-EOS.demargin
|
543
|
-
|class C
|
544
|
-
| def f
|
545
|
-
| end
|
546
|
-
|end
|
547
|
-
|class D < C
|
548
|
-
| private :f
|
549
|
-
|end
|
550
|
-
EOS
|
551
|
-
begin
|
552
|
-
method = D.instance_method(:f)
|
553
|
-
@adapter.source_location(method).should == [path, 2]
|
554
|
-
ensure
|
555
|
-
Object.send(:remove_const, :D)
|
556
|
-
end
|
557
|
-
end
|
558
|
-
|
559
|
-
it "should work for aliases (MRI FBODY)" do
|
560
|
-
path = load_source <<-EOS.demargin
|
561
|
-
|class C
|
562
|
-
| def f
|
563
|
-
| end
|
564
|
-
| alias g f
|
565
|
-
|end
|
566
|
-
EOS
|
567
|
-
method = C.instance_method(:g)
|
568
|
-
@adapter.source_location(method).should == [path, 2]
|
569
|
-
end
|
570
|
-
|
571
|
-
it "should return nil for primitive methods (MRI CBODY)" do
|
572
|
-
method = String.instance_method(:bytesize)
|
573
|
-
@adapter.source_location(method).should == nil
|
574
|
-
end
|
575
288
|
|
576
|
-
it "should raise a TypeError if the
|
577
|
-
path = load_source <<-EOS.demargin
|
578
|
-
|class C
|
579
|
-
| def f
|
580
|
-
| end
|
581
|
-
|end
|
582
|
-
EOS
|
289
|
+
it "should raise a TypeError if the argumeent is not a module" do
|
583
290
|
lambda do
|
584
|
-
@adapter.
|
291
|
+
@adapter.describe_module(Object.new)
|
585
292
|
end.should raise_error(TypeError)
|
586
293
|
end
|
587
294
|
end
|