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.
Files changed (47) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG +9 -0
  3. data/README.markdown +61 -81
  4. data/ext/extconf.rb +3 -7
  5. data/ext/mri/2.3.0/internal.h +1404 -0
  6. data/ext/mri/2.3.0/method.h +213 -0
  7. data/ext/mri/mri.c +21 -264
  8. data/ext/rbx/rbx.c +0 -9
  9. data/lib/looksee/JRuby.jar +0 -0
  10. data/lib/looksee/adapter/base.rb +19 -54
  11. data/lib/looksee/adapter/rubinius.rb +3 -62
  12. data/lib/looksee/clean.rb +5 -1
  13. data/lib/looksee/editor.rb +1 -1
  14. data/lib/looksee/help.rb +3 -2
  15. data/lib/looksee/lookup_path.rb +7 -3
  16. data/lib/looksee/version.rb +1 -1
  17. data/spec/looksee/adapter_spec.rb +72 -365
  18. data/spec/looksee/editor_spec.rb +1 -1
  19. data/spec/looksee/inspector_spec.rb +21 -21
  20. data/spec/looksee/lookup_path_spec.rb +34 -21
  21. data/spec/spec_helper.rb +2 -0
  22. data/spec/support/temporary_classes.rb +10 -14
  23. data/spec/support/test_adapter.rb +2 -53
  24. metadata +6 -29
  25. data/ext/mri/1.9.2/debug.h +0 -36
  26. data/ext/mri/1.9.2/id.h +0 -170
  27. data/ext/mri/1.9.2/method.h +0 -103
  28. data/ext/mri/1.9.2/node.h +0 -483
  29. data/ext/mri/1.9.2/thread_pthread.h +0 -27
  30. data/ext/mri/1.9.2/vm_core.h +0 -707
  31. data/ext/mri/1.9.2/vm_opts.h +0 -51
  32. data/ext/mri/1.9.3/atomic.h +0 -56
  33. data/ext/mri/1.9.3/debug.h +0 -41
  34. data/ext/mri/1.9.3/id.h +0 -175
  35. data/ext/mri/1.9.3/internal.h +0 -227
  36. data/ext/mri/1.9.3/internal_falcon.h +0 -248
  37. data/ext/mri/1.9.3/method.h +0 -105
  38. data/ext/mri/1.9.3/node.h +0 -503
  39. data/ext/mri/1.9.3/thread_pthread.h +0 -51
  40. data/ext/mri/1.9.3/vm_core.h +0 -755
  41. data/ext/mri/1.9.3/vm_opts.h +0 -51
  42. data/ext/mri/2.0.0/internal.h +0 -378
  43. data/ext/mri/2.0.0/method.h +0 -138
  44. data/ext/mri/env-1.8.h +0 -27
  45. data/ext/mri/eval_c-1.8.h +0 -27
  46. data/ext/mri/node-1.9.h +0 -35
  47. data/lib/looksee/mri.bundle +0 -0
@@ -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
@@ -6,13 +6,14 @@ module Looksee
6
6
  # object's method lookup path.
7
7
  #
8
8
  def lookup_modules(object)
9
- modules = []
10
- klass = internal_class(object)
11
- while klass
12
- modules << klass
13
- klass = internal_superclass(klass)
14
- end
15
- modules
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 singleton_class?(object)
29
+ while (instance = singleton_instance(object))
27
30
  num_brackets += 1
28
- object = singleton_instance(object)
31
+ object = instance
29
32
  end
30
33
 
31
- if included_class?(mod) || object.is_a?(Module)
34
+ if object.is_a?(Module)
32
35
  description = module_name(object)
33
36
  if description.empty?
34
- is_class = real_module(object).is_a?(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 singleton_class?(object)
81
- raise NotImplementedError, "abstract"
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
- raise NotImplementedError, "abstract"
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?(singleton_class) or
45
- raise TypeError, "expected singleton class, got #{singleton_class.class}"
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
- mod.__name__
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
@@ -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]
@@ -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 = Looksee.adapter.source_location(method)
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)
@@ -4,7 +4,8 @@ module Looksee
4
4
  <<-EOS.gsub(/^ *\|/, '')
5
5
  |== Looksee Quick Reference
6
6
  |
7
- | object.ls(*specifiers) or Looksee[object, *specifiers]
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
- | object.ls.edit(method)
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
@@ -28,7 +28,7 @@ module Looksee
28
28
  if visibility == :undefined
29
29
  return nil
30
30
  else
31
- return Looksee.adapter.real_module(entry.module).instance_method(name)
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, :undefined].each do |visibility|
87
- Looksee.adapter.send("internal_#{visibility}_instance_methods", @module).each do |method|
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
@@ -1,5 +1,5 @@
1
1
  module Looksee
2
- VERSION = [3, 1, 1]
2
+ VERSION = [4, 0, 0]
3
3
 
4
4
  class << VERSION
5
5
  include Comparable
@@ -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
- # only in ruby 1.9
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 exists" do
56
+ it "should contain an entry for the object's singleton class if it has methods" do
61
57
  object = Object.new
62
- object.singleton_class
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
- def self.it_should_list_methods_with_visibility(visibility)
85
- it "should return the list of #{visibility} instance methods defined directly on a class" do
86
- temporary_class :C
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, visibility => :one
121
- temporary_module :M
122
- add_methods M, visibility => :one
123
- C.send(:prepend, M)
124
- @adapter.send(target_method, C).should be_empty
125
-
126
- origin = @adapter.lookup_modules(C.new).
127
- find { |mod| @adapter.describe_module(mod) == 'C (origin)' }
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
- it "should not return defined methods" do
190
- temporary_class :C
191
- C.send(:define_method, :f){}
192
- @adapter.internal_undefined_instance_methods(C).should == []
193
- end
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
- it "should not return removed methods" do
196
- temporary_class :C
197
- C.send(:define_method, :f){}
198
- C.send(:remove_method, :f)
199
- @adapter.internal_undefined_instance_methods(C).should == []
200
- end
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
- it "should handle the MRI allocator being undefined (e.g. Struct)" do
203
- struct_singleton_class = (class << Struct; self; end)
204
- @adapter.internal_undefined_instance_methods(struct_singleton_class).should == []
205
- end
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
- if RUBY_VERSION >= '2'
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.send(:undef_method, :f)
212
- temporary_module :M
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
- @adapter.internal_undefined_instance_methods(C).should be_empty
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
- origin = @adapter.lookup_modules(C.new).
220
- find { |mod| @adapter.describe_module(mod) == 'C (origin)' }
221
- @adapter.internal_undefined_instance_methods(origin).should_not be_empty
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 raise a TypeError if the given object is just a class" do
288
- lambda do
289
- @adapter.singleton_instance(Class.new)
290
- end.should raise_error(TypeError)
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 raise a TypeError if the given object is just a module" do
294
- lambda do
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 raise a TypeError if the given object is just a object" do
300
- lambda do
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
- describe "#module_name" do
307
- it "should return the fully-qualified name of the given module" do
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 fully-qualified name of the given class" do
318
- ::M = Module.new
319
- M::C = Class.new
320
- begin
321
- @adapter.module_name(M::C).should == 'M::C'
322
- ensure
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
- it "should not be affected by overridding the module's #to_s or #name" do
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::C = Class.new do
331
- def name
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 an empty string for unnamed modules" do
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 = Module.new
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 argument is not an UnboundMethod" do
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.source_location(nil)
291
+ @adapter.describe_module(Object.new)
585
292
  end.should raise_error(TypeError)
586
293
  end
587
294
  end