looksee 3.1.1 → 4.0.0
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.
- 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
|