looksee 3.1.1 → 4.0.0

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