method_extensions 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,211 +5,213 @@ rescue LoadError
5
5
  ripper_available = false
6
6
  end
7
7
 
8
- module MethodSourceWithDoc
9
- # Returns method source by parsing the file returned by `Method#source_location`.
10
- #
11
- # If method definition cannot be found `ArgumentError` exception is raised
12
- # (this includes methods defined `attr_accessor`, `module_eval` etc.).
13
- #
14
- # Sample IRB session:
15
- #
16
- # ruby-1.9.2-head > require 'fileutils'
17
- #
18
- # ruby-1.9.2-head > puts FileUtils.method(:mkdir).source
19
- # def mkdir(list, options = {})
20
- # fu_check_options options, OPT_TABLE['mkdir']
21
- # list = fu_list(list)
22
- # fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" if options[:verbose]
23
- # return if options[:noop]
24
- #
25
- # list.each do |dir|
26
- # fu_mkdir dir, options[:mode]
27
- # end
28
- # end
29
- # => nil
30
- def source
31
- MethodSourceRipper.source_from_source_location(source_location)
32
- end
33
-
34
- # Returns comment preceding the method definition by parsing the file
35
- # returned by `Method#source_location`
36
- #
37
- # Sample IRB session:
38
- #
39
- # ruby-1.9.2-head > require 'fileutils'
40
- #
41
- # ruby-1.9.2-head > puts FileUtils.method(:mkdir).doc
42
- # #
43
- # # Options: mode noop verbose
44
- # #
45
- # # Creates one or more directories.
46
- # #
47
- # # FileUtils.mkdir 'test'
48
- # # FileUtils.mkdir %w( tmp data )
49
- # # FileUtils.mkdir 'notexist', :noop => true # Does not really create.
50
- # # FileUtils.mkdir 'tmp', :mode => 0700
51
- # #
52
- def doc
53
- MethodDocRipper.doc_from_source_location(source_location)
54
- end
8
+ module MethodExtensions
9
+ module MethodSourceWithDoc
10
+ # Returns method source by parsing the file returned by `Method#source_location`.
11
+ #
12
+ # If method definition cannot be found `ArgumentError` exception is raised
13
+ # (this includes methods defined `attr_accessor`, `module_eval` etc.).
14
+ #
15
+ # Sample IRB session:
16
+ #
17
+ # ruby-1.9.2-head > require 'fileutils'
18
+ #
19
+ # ruby-1.9.2-head > puts FileUtils.method(:mkdir).source
20
+ # def mkdir(list, options = {})
21
+ # fu_check_options options, OPT_TABLE['mkdir']
22
+ # list = fu_list(list)
23
+ # fu_output_message "mkdir #{options[:mode] ? ('-m %03o ' % options[:mode]) : ''}#{list.join ' '}" if options[:verbose]
24
+ # return if options[:noop]
25
+ #
26
+ # list.each do |dir|
27
+ # fu_mkdir dir, options[:mode]
28
+ # end
29
+ # end
30
+ # => nil
31
+ def source
32
+ MethodSourceRipper.source_from_source_location(source_location)
33
+ end
55
34
 
56
- # ruby-1.9.2-head > irb_context.inspect_mode = false # turn off inspect mode so that we can view sources
57
- #
58
- # ruby-1.9.2-head > ActiveRecord::Base.method(:find).source_with_doc
59
- # ArgumentError: failed to find method definition around the lines:
60
- # delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped
61
- # delegate :find_each, :find_in_batches, :to => :scoped
62
- #
63
- # ruby-1.9.2-head > ActiveRecord::Base.method(:scoped).source_with_doc
64
- # # Returns an anonymous scope.
65
- # #
66
- # # posts = Post.scoped
67
- # # posts.size # Fires "select count(*) from posts" and returns the count
68
- # # posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
69
- # #
70
- # # fruits = Fruit.scoped
71
- # # fruits = fruits.where(:colour => 'red') if options[:red_only]
72
- # # fruits = fruits.limit(10) if limited?
73
- # #
74
- # # Anonymous \scopes tend to be useful when procedurally generating complex queries, where passing
75
- # # intermediate values (scopes) around as first-class objects is convenient.
76
- # #
77
- # # You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.
78
- # def scoped(options = {}, &block)
79
- # if options.present?
80
- # relation = scoped.apply_finder_options(options)
81
- # block_given? ? relation.extending(Module.new(&block)) : relation
82
- # else
83
- # current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.clone
84
- # end
85
- # end
86
- #
87
- # ruby-1.9.2-head > ActiveRecord::Base.method(:unscoped).source_with_doc
88
- # => def unscoped
89
- # @unscoped ||= Relation.new(self, arel_table)
90
- # finder_needs_type_condition? ? @unscoped.where(type_condition) : @unscoped
91
- # end
92
- #
93
- # ruby-1.9.2-head > ActiveRecord::Relation.instance_method(:find).source_with_doc
94
- # => # Find operates with four different retrieval approaches:
95
- # ...
96
- # def find(*args, &block)
97
- # return to_a.find(&block) if block_given?
98
- #
99
- # options = args.extract_options!
100
- #
101
- # if options.present?
102
- # ...
103
- def source_with_doc
104
- return unless source_location
105
-
106
- [doc.to_s.chomp, source_unindent(source)].compact.reject(&:empty?).join("\n")
107
- end
35
+ # Returns comment preceding the method definition by parsing the file
36
+ # returned by `Method#source_location`
37
+ #
38
+ # Sample IRB session:
39
+ #
40
+ # ruby-1.9.2-head > require 'fileutils'
41
+ #
42
+ # ruby-1.9.2-head > puts FileUtils.method(:mkdir).doc
43
+ # #
44
+ # # Options: mode noop verbose
45
+ # #
46
+ # # Creates one or more directories.
47
+ # #
48
+ # # FileUtils.mkdir 'test'
49
+ # # FileUtils.mkdir %w( tmp data )
50
+ # # FileUtils.mkdir 'notexist', :noop => true # Does not really create.
51
+ # # FileUtils.mkdir 'tmp', :mode => 0700
52
+ # #
53
+ def doc
54
+ MethodDocRipper.doc_from_source_location(source_location)
55
+ end
108
56
 
109
- def full_inspect
110
- "#{ inspect }\n#{ source_location }\n#{ source_with_doc }"
111
- end
57
+ # ruby-1.9.2-head > irb_context.inspect_mode = false # turn off inspect mode so that we can view sources
58
+ #
59
+ # ruby-1.9.2-head > ActiveRecord::Base.method(:find).source_with_doc
60
+ # ArgumentError: failed to find method definition around the lines:
61
+ # delegate :find, :first, :last, :all, :destroy, :destroy_all, :exists?, :delete, :delete_all, :update, :update_all, :to => :scoped
62
+ # delegate :find_each, :find_in_batches, :to => :scoped
63
+ #
64
+ # ruby-1.9.2-head > ActiveRecord::Base.method(:scoped).source_with_doc
65
+ # # Returns an anonymous scope.
66
+ # #
67
+ # # posts = Post.scoped
68
+ # # posts.size # Fires "select count(*) from posts" and returns the count
69
+ # # posts.each {|p| puts p.name } # Fires "select * from posts" and loads post objects
70
+ # #
71
+ # # fruits = Fruit.scoped
72
+ # # fruits = fruits.where(:colour => 'red') if options[:red_only]
73
+ # # fruits = fruits.limit(10) if limited?
74
+ # #
75
+ # # Anonymous \scopes tend to be useful when procedurally generating complex queries, where passing
76
+ # # intermediate values (scopes) around as first-class objects is convenient.
77
+ # #
78
+ # # You can define a scope that applies to all finders using ActiveRecord::Base.default_scope.
79
+ # def scoped(options = {}, &block)
80
+ # if options.present?
81
+ # relation = scoped.apply_finder_options(options)
82
+ # block_given? ? relation.extending(Module.new(&block)) : relation
83
+ # else
84
+ # current_scoped_methods ? unscoped.merge(current_scoped_methods) : unscoped.clone
85
+ # end
86
+ # end
87
+ #
88
+ # ruby-1.9.2-head > ActiveRecord::Base.method(:unscoped).source_with_doc
89
+ # => def unscoped
90
+ # @unscoped ||= Relation.new(self, arel_table)
91
+ # finder_needs_type_condition? ? @unscoped.where(type_condition) : @unscoped
92
+ # end
93
+ #
94
+ # ruby-1.9.2-head > ActiveRecord::Relation.instance_method(:find).source_with_doc
95
+ # => # Find operates with four different retrieval approaches:
96
+ # ...
97
+ # def find(*args, &block)
98
+ # return to_a.find(&block) if block_given?
99
+ #
100
+ # options = args.extract_options!
101
+ #
102
+ # if options.present?
103
+ # ...
104
+ def source_with_doc
105
+ return unless source_location
112
106
 
113
- private
107
+ [doc.to_s.chomp, source_unindent(source)].compact.reject(&:empty?).join("\n")
108
+ end
114
109
 
115
- def source_unindent(src)
116
- lines = src.split("\n")
117
- indented_lines = lines[1 .. -1] # first line doesn't have proper indentation
118
- indent_level = indented_lines.
119
- reject { |line| line.strip.empty? }. # exclude empty lines from indent level calculation
120
- map { |line| line[/^(\s*)/, 1].size }. # map to indent level of every line
121
- min
122
- [lines[0], *indented_lines.map { |line| line[indent_level .. -1] }].join("\n")
123
- end
124
-
125
- class ::Method
126
- include MethodSourceWithDoc
127
- end
110
+ def full_inspect
111
+ "#{ inspect }\n#{ source_location }\n#{ source_with_doc }"
112
+ end
128
113
 
129
- class ::UnboundMethod
130
- include MethodSourceWithDoc
131
- end
114
+ private
132
115
 
133
- class MethodSourceRipper < Ripper
134
- def self.source_from_source_location(source_location)
135
- return unless source_location
136
- new(*source_location).method_source
116
+ def source_unindent(src)
117
+ lines = src.split("\n")
118
+ indented_lines = lines[1 .. -1] # first line doesn't have proper indentation
119
+ indent_level = indented_lines.
120
+ reject { |line| line.strip.empty? }. # exclude empty lines from indent level calculation
121
+ map { |line| line[/^(\s*)/, 1].size }. # map to indent level of every line
122
+ min
123
+ [lines[0], *indented_lines.map { |line| line[indent_level .. -1] }].join("\n")
137
124
  end
138
125
 
139
- def initialize(filename, method_definition_lineno)
140
- super(IO.read(filename), filename)
141
- @src_lines = IO.read(filename).split("\n")
142
- @method_definition_lineno = method_definition_lineno
126
+ class ::Method
127
+ include MethodSourceWithDoc
143
128
  end
144
129
 
145
- def method_source
146
- parse
147
- if @method_source
148
- @method_source
149
- else
150
- raise ArgumentError.new("failed to find method definition around the lines:\n" <<
151
- definition_lines.join("\n"))
152
- end
130
+ class ::UnboundMethod
131
+ include MethodSourceWithDoc
153
132
  end
154
133
 
155
- def definition_lines
156
- @src_lines[@method_definition_lineno - 1 .. @method_definition_lineno + 1]
157
- end
134
+ class MethodSourceRipper < Ripper
135
+ def self.source_from_source_location(source_location)
136
+ return unless source_location
137
+ new(*source_location).method_source
138
+ end
158
139
 
159
- Ripper::SCANNER_EVENTS.each do |meth|
160
- define_method("on_#{ meth }") do |*args|
161
- [lineno, column]
140
+ def initialize(filename, method_definition_lineno)
141
+ super(IO.read(filename), filename)
142
+ @src_lines = IO.read(filename).split("\n")
143
+ @method_definition_lineno = method_definition_lineno
162
144
  end
163
- end
164
145
 
165
- def on_def(name, params, body)
166
- from_lineno, from_column = name
167
- return unless @method_definition_lineno == from_lineno
146
+ def method_source
147
+ parse
148
+ if @method_source
149
+ @method_source
150
+ else
151
+ raise ArgumentError.new("failed to find method definition around the lines:\n" <<
152
+ definition_lines.join("\n"))
153
+ end
154
+ end
168
155
 
169
- to_lineno, to_column = lineno, column
156
+ def definition_lines
157
+ @src_lines[@method_definition_lineno - 1 .. @method_definition_lineno + 1]
158
+ end
170
159
 
171
- @method_source = @src_lines[from_lineno - 1 .. to_lineno - 1].join("\n").strip
172
- end
160
+ Ripper::SCANNER_EVENTS.each do |meth|
161
+ define_method("on_#{ meth }") do |*args|
162
+ [lineno, column]
163
+ end
164
+ end
173
165
 
174
- def on_defs(target, period, name, params, body)
175
- on_def(target, params, body)
176
- end
177
- end
166
+ def on_def(name, params, body)
167
+ from_lineno, from_column = name
168
+ return unless @method_definition_lineno == from_lineno
178
169
 
179
- class MethodDocRipper < Ripper
180
- def self.doc_from_source_location(source_location)
181
- return unless source_location
182
- new(*source_location).method_doc
183
- end
170
+ to_lineno, to_column = lineno, column
184
171
 
185
- def initialize(filename, method_definition_lineno)
186
- super(IO.read(filename), filename)
187
- @method_definition_lineno = method_definition_lineno
188
- @last_comment_block = nil
189
- end
172
+ @method_source = @src_lines[from_lineno - 1 .. to_lineno - 1].join("\n").strip
173
+ end
190
174
 
191
- def method_doc
192
- parse
193
- @method_doc
175
+ def on_defs(target, period, name, params, body)
176
+ on_def(target, params, body)
177
+ end
194
178
  end
195
179
 
196
- Ripper::SCANNER_EVENTS.each do |meth|
197
- define_method("on_#{ meth }") do |token|
198
- if @last_comment_block &&
199
- lineno == @method_definition_lineno
200
- @method_doc = @last_comment_block.join.gsub(/^\s*/, "")
201
- end
180
+ class MethodDocRipper < Ripper
181
+ def self.doc_from_source_location(source_location)
182
+ return unless source_location
183
+ new(*source_location).method_doc
184
+ end
202
185
 
186
+ def initialize(filename, method_definition_lineno)
187
+ super(IO.read(filename), filename)
188
+ @method_definition_lineno = method_definition_lineno
203
189
  @last_comment_block = nil
204
190
  end
205
- end
206
191
 
207
- def on_comment(token)
208
- (@last_comment_block ||= []) << token
209
- end
192
+ def method_doc
193
+ parse
194
+ @method_doc
195
+ end
196
+
197
+ Ripper::SCANNER_EVENTS.each do |meth|
198
+ define_method("on_#{ meth }") do |token|
199
+ if @last_comment_block &&
200
+ lineno == @method_definition_lineno
201
+ @method_doc = @last_comment_block.join.gsub(/^\s*/, "")
202
+ end
203
+
204
+ @last_comment_block = nil
205
+ end
206
+ end
210
207
 
211
- def on_sp(token)
212
- @last_comment_block << token if @last_comment_block
208
+ def on_comment(token)
209
+ (@last_comment_block ||= []) << token
210
+ end
211
+
212
+ def on_sp(token)
213
+ @last_comment_block << token if @last_comment_block
214
+ end
213
215
  end
214
216
  end
215
- end if ripper_available
217
+ end if ripper_available
@@ -1,273 +1,274 @@
1
- module MethodSuper
2
- # Returns method which will be called if given Method/UnboundMethod would
3
- # call `super`.
4
- # Implementation is incomplete with regard to modules included in singleton
5
- # class (`class C; extend M; end`), but such modules usually don't use `super`
6
- # anyway.
7
- #
8
- # Examples
9
- #
10
- # class Base
11
- # def meth; end
12
- # end
13
- #
14
- # class Derived < Base
15
- # def meth; end
16
- # end
17
- #
18
- # ruby-1.9.2-head > Derived.instance_method(:meth)
19
- # => #<UnboundMethod: Derived#meth>
20
- #
21
- # ruby-1.9.2-head > Derived.instance_method(:meth).super
22
- # => #<UnboundMethod: Base#meth>
23
- def super
24
- raise ArgumentError, "method doesn't have required @context_for_super instance variable set" unless @context_for_super
25
-
26
- klass, level, name = @context_for_super.values_at(:klass, :level, :name)
27
-
28
- unless @methods_all
29
- @methods_all = MethodSuper.methods_all(klass)
30
-
31
- # on first call ignore first found method
1
+ module MethodExtensions
2
+ module MethodSuper
3
+ # Returns method which will be called if given Method/UnboundMethod would
4
+ # call `super`.
5
+ # Implementation is incomplete with regard to modules included in singleton
6
+ # class (`class C; extend M; end`), but such modules usually don't use `super`
7
+ # anyway.
8
+ #
9
+ # Examples
10
+ #
11
+ # class Base
12
+ # def meth; end
13
+ # end
14
+ #
15
+ # class Derived < Base
16
+ # def meth; end
17
+ # end
18
+ #
19
+ # ruby-1.9.2-head > Derived.instance_method(:meth)
20
+ # => #<UnboundMethod: Derived#meth>
21
+ #
22
+ # ruby-1.9.2-head > Derived.instance_method(:meth).super
23
+ # => #<UnboundMethod: Base#meth>
24
+ def super
25
+ raise ArgumentError, "method doesn't have required @context_for_super instance variable set" unless @context_for_super
26
+
27
+ klass, level, name = @context_for_super.values_at(:klass, :level, :name)
28
+
29
+ unless @methods_all
30
+ @methods_all = MethodSuper.methods_all(klass)
31
+
32
+ # on first call ignore first found method
33
+ superclass_index = MethodSuper.superclass_index(@methods_all,
34
+ level,
35
+ name)
36
+ @methods_all = @methods_all[superclass_index + 1 .. -1]
37
+
38
+ end
39
+
32
40
  superclass_index = MethodSuper.superclass_index(@methods_all,
33
41
  level,
34
42
  name)
35
- @methods_all = @methods_all[superclass_index + 1 .. -1]
36
-
37
- end
38
43
 
39
- superclass_index = MethodSuper.superclass_index(@methods_all,
40
- level,
41
- name)
44
+ superclass = @methods_all[superclass_index].keys.first
45
+ rest_methods_all = @methods_all[superclass_index + 1 .. -1]
42
46
 
43
- superclass = @methods_all[superclass_index].keys.first
44
- rest_methods_all = @methods_all[superclass_index + 1 .. -1]
47
+ super_method = if level == :class && superclass.class == Class
48
+ superclass.method(name)
49
+ elsif level == :instance ||
50
+ (level == :class && superclass.class == Module)
51
+ superclass.instance_method(name)
52
+ end
45
53
 
46
- super_method = if level == :class && superclass.class == Class
47
- superclass.method(name)
48
- elsif level == :instance ||
49
- (level == :class && superclass.class == Module)
50
- superclass.instance_method(name)
54
+ super_method.instance_variable_set(:@context_for_super, @context_for_super)
55
+ super_method.instance_variable_set(:@methods_all, rest_methods_all)
56
+ super_method
51
57
  end
52
58
 
53
- super_method.instance_variable_set(:@context_for_super, @context_for_super)
54
- super_method.instance_variable_set(:@methods_all, rest_methods_all)
55
- super_method
56
- end
57
-
58
- private
59
+ private
59
60
 
60
- def self.superclass_index(methods_all, level, name)
61
- methods_all.index do |ancestor_with_methods|
62
- ancestor, methods =
63
- ancestor_with_methods.keys.first, ancestor_with_methods.values.first
64
- methods[level] && methods[level].any? do |level, methods|
65
- methods.include?(name)
61
+ def self.superclass_index(methods_all, level, name)
62
+ methods_all.index do |ancestor_with_methods|
63
+ ancestor, methods =
64
+ ancestor_with_methods.keys.first, ancestor_with_methods.values.first
65
+ methods[level] && methods[level].any? do |level, methods|
66
+ methods.include?(name)
67
+ end
66
68
  end
67
69
  end
68
- end
69
70
 
70
- def self.methods_all(klass)
71
- MethodSuper::Methods.new(klass, :ancestor_name_formatter => proc { |ancestor, _| ancestor }).all
72
- end
73
-
74
- class Methods
75
- def initialize(klass_or_module, options = {})
76
- @klass_or_module = klass_or_module
77
- @ancestor_name_formatter = options.fetch(:ancestor_name_formatter,
78
- default_ancestor_name_formatter)
79
- @exclude_trite = options.fetch(:exclude_trite, true)
71
+ def self.methods_all(klass)
72
+ MethodSuper::Methods.new(klass, :ancestor_name_formatter => proc { |ancestor, _| ancestor }).all
80
73
  end
81
74
 
82
- def all
83
- @all ||= find_all
84
- end
75
+ class Methods
76
+ def initialize(klass_or_module, options = {})
77
+ @klass_or_module = klass_or_module
78
+ @ancestor_name_formatter = options.fetch(:ancestor_name_formatter,
79
+ default_ancestor_name_formatter)
80
+ @exclude_trite = options.fetch(:exclude_trite, true)
81
+ end
82
+
83
+ def all
84
+ @all ||= find_all
85
+ end
85
86
 
86
- VISIBILITIES = [ :public, :protected, :private ].freeze
87
+ VISIBILITIES = [ :public, :protected, :private ].freeze
87
88
 
88
- protected
89
+ protected
89
90
 
90
- def default_ancestor_name_formatter
91
- proc do |ancestor, singleton|
92
- ancestor_name(ancestor, singleton)
91
+ def default_ancestor_name_formatter
92
+ proc do |ancestor, singleton|
93
+ ancestor_name(ancestor, singleton)
94
+ end
93
95
  end
94
- end
95
96
 
96
- def find_all
97
- ancestors = [] # flattened ancestors (both normal and singleton)
97
+ def find_all
98
+ ancestors = [] # flattened ancestors (both normal and singleton)
98
99
 
99
- (@klass_or_module.ancestors - trite_ancestors).each do |ancestor|
100
- ancestor_singleton = ancestor.singleton_class
100
+ (@klass_or_module.ancestors - trite_ancestors).each do |ancestor|
101
+ ancestor_singleton = ancestor.singleton_class
101
102
 
102
- # Modules don't inherit class methods from included modules
103
- unless @klass_or_module.instance_of?(Module) && ancestor != @klass_or_module
104
- class_methods = collect_instance_methods(ancestor_singleton)
105
- end
103
+ # Modules don't inherit class methods from included modules
104
+ unless @klass_or_module.instance_of?(Module) && ancestor != @klass_or_module
105
+ class_methods = collect_instance_methods(ancestor_singleton)
106
+ end
106
107
 
107
- instance_methods = collect_instance_methods(ancestor)
108
+ instance_methods = collect_instance_methods(ancestor)
108
109
 
109
- append_ancestor_entry(ancestors, @ancestor_name_formatter[ancestor, false],
110
- class_methods, instance_methods)
110
+ append_ancestor_entry(ancestors, @ancestor_name_formatter[ancestor, false],
111
+ class_methods, instance_methods)
111
112
 
112
- (singleton_ancestors(ancestor) || []).each do |singleton_ancestor|
113
- class_methods = collect_instance_methods(singleton_ancestor)
114
- append_ancestor_entry(ancestors, @ancestor_name_formatter[singleton_ancestor, true],
115
- class_methods)
113
+ (singleton_ancestors(ancestor) || []).each do |singleton_ancestor|
114
+ class_methods = collect_instance_methods(singleton_ancestor)
115
+ append_ancestor_entry(ancestors, @ancestor_name_formatter[singleton_ancestor, true],
116
+ class_methods)
117
+ end
116
118
  end
117
- end
118
119
 
119
- ancestors
120
- end
120
+ ancestors
121
+ end
121
122
 
122
- # singleton ancestors which ancestor introduced
123
- def singleton_ancestors(ancestor)
124
- @singleton_ancestors ||= all_singleton_ancestors
125
- @singleton_ancestors[ancestor]
126
- end
123
+ # singleton ancestors which ancestor introduced
124
+ def singleton_ancestors(ancestor)
125
+ @singleton_ancestors ||= all_singleton_ancestors
126
+ @singleton_ancestors[ancestor]
127
+ end
127
128
 
128
- def all_singleton_ancestors
129
- all = {}
130
- seen = []
131
- (@klass_or_module.ancestors - trite_ancestors).reverse.each do |ancestor|
132
- singleton_ancestors = ancestor.singleton_class.ancestors - trite_singleton_ancestors
133
- introduces = singleton_ancestors - seen
134
- all[ancestor] = introduces unless introduces.empty?
135
- seen.concat singleton_ancestors
129
+ def all_singleton_ancestors
130
+ all = {}
131
+ seen = []
132
+ (@klass_or_module.ancestors - trite_ancestors).reverse.each do |ancestor|
133
+ singleton_ancestors = ancestor.singleton_class.ancestors - trite_singleton_ancestors
134
+ introduces = singleton_ancestors - seen
135
+ all[ancestor] = introduces unless introduces.empty?
136
+ seen.concat singleton_ancestors
137
+ end
138
+ all
136
139
  end
137
- all
138
- end
139
140
 
140
- def ancestor_name(ancestor, singleton)
141
- "#{ singleton ? "S" : ""}[#{ ancestor.is_a?(Class) ? "C" : "M" }] #{ ancestor.name || ancestor.to_s }"
142
- end
141
+ def ancestor_name(ancestor, singleton)
142
+ "#{ singleton ? "S" : ""}[#{ ancestor.is_a?(Class) ? "C" : "M" }] #{ ancestor.name || ancestor.to_s }"
143
+ end
143
144
 
144
- # ancestor is included only when contributes some methods
145
- def append_ancestor_entry(ancestors, ancestor, class_methods, instance_methods = nil)
146
- if class_methods || instance_methods
147
- ancestor_entry = {}
148
- ancestor_entry[:class] = class_methods if class_methods
149
- ancestor_entry[:instance] = instance_methods if instance_methods
150
- ancestors << {ancestor => ancestor_entry}
145
+ # ancestor is included only when contributes some methods
146
+ def append_ancestor_entry(ancestors, ancestor, class_methods, instance_methods = nil)
147
+ if class_methods || instance_methods
148
+ ancestor_entry = {}
149
+ ancestor_entry[:class] = class_methods if class_methods
150
+ ancestor_entry[:instance] = instance_methods if instance_methods
151
+ ancestors << {ancestor => ancestor_entry}
152
+ end
151
153
  end
152
- end
153
154
 
154
- # Returns hash { :public => [...public methods...],
155
- # :protected => [...private methods...],
156
- # :private => [...private methods...] }
157
- # keys with empty values are excluded,
158
- # when no methods are found - returns nil
159
- def collect_instance_methods(klass)
160
- methods_with_visibility = VISIBILITIES.map do |visibility|
161
- methods = klass.send("#{ visibility }_instance_methods", false)
162
- [visibility, methods] unless methods.empty?
163
- end.compact
164
- Hash[methods_with_visibility] unless methods_with_visibility.empty?
165
- end
155
+ # Returns hash { :public => [...public methods...],
156
+ # :protected => [...private methods...],
157
+ # :private => [...private methods...] }
158
+ # keys with empty values are excluded,
159
+ # when no methods are found - returns nil
160
+ def collect_instance_methods(klass)
161
+ methods_with_visibility = VISIBILITIES.map do |visibility|
162
+ methods = klass.send("#{ visibility }_instance_methods", false)
163
+ [visibility, methods] unless methods.empty?
164
+ end.compact
165
+ Hash[methods_with_visibility] unless methods_with_visibility.empty?
166
+ end
166
167
 
167
- def trite_singleton_ancestors
168
- return [] unless @exclude_trite
169
- @trite_singleton_ancestors ||= Class.new.singleton_class.ancestors
170
- end
168
+ def trite_singleton_ancestors
169
+ return [] unless @exclude_trite
170
+ @trite_singleton_ancestors ||= Class.new.singleton_class.ancestors
171
+ end
171
172
 
172
- def trite_ancestors
173
- return [] unless @exclude_trite
174
- @trite_ancestors ||= Class.new.ancestors
173
+ def trite_ancestors
174
+ return [] unless @exclude_trite
175
+ @trite_ancestors ||= Class.new.ancestors
176
+ end
175
177
  end
176
178
  end
177
- end
178
-
179
- class Method
180
- include MethodSuper
181
- end
182
179
 
183
- class UnboundMethod
184
- include MethodSuper
185
- end
186
-
187
- class Module
188
- def instance_method_with_ancestors_for_super(name)
189
- method = instance_method_without_ancestors_for_super(name)
190
- method.instance_variable_set(:@context_for_super,
191
- :klass => self,
192
- :level => :instance,
193
- :name => name)
194
-
195
- method
180
+ class ::Method
181
+ include MethodSuper
196
182
  end
197
183
 
198
- unless method_defined?(:instance_method_without_ancestors_for_super) ||
199
- private_method_defined?(:instance_method_without_ancestors_for_super)
200
- alias_method :instance_method_without_ancestors_for_super, :instance_method
201
- alias_method :instance_method, :instance_method_with_ancestors_for_super
184
+ class ::UnboundMethod
185
+ include MethodSuper
202
186
  end
203
- end
204
-
205
- module Kernel
206
- def method_with_ancestors_for_super(name)
207
- method = method_without_ancestors_for_super(name)
208
187
 
209
- if respond_to?(:ancestors)
188
+ class ::Module
189
+ def instance_method_with_ancestors_for_super(name)
190
+ method = instance_method_without_ancestors_for_super(name)
210
191
  method.instance_variable_set(:@context_for_super,
211
192
  :klass => self,
212
- :level => :class,
213
- :name => name)
214
- else
215
- method.instance_variable_set(:@context_for_super,
216
- :klass => self.class,
217
193
  :level => :instance,
218
194
  :name => name)
195
+
196
+ method
219
197
  end
220
-
221
- method
222
- end
223
198
 
224
- unless method_defined?(:method_without_ancestors_for_super) ||
225
- private_method_defined?(:method_without_ancestors_for_super)
226
- alias_method :method_without_ancestors_for_super, :method
227
- alias_method :method, :method_with_ancestors_for_super
199
+ unless method_defined?(:instance_method_without_ancestors_for_super) ||
200
+ private_method_defined?(:instance_method_without_ancestors_for_super)
201
+ alias_method :instance_method_without_ancestors_for_super, :instance_method
202
+ alias_method :instance_method, :instance_method_with_ancestors_for_super
203
+ end
228
204
  end
229
- end
230
205
 
231
- module BaseIncludedModule
232
- def module_meth
233
- end
234
- end
206
+ module ::Kernel
207
+ def method_with_ancestors_for_super(name)
208
+ method = method_without_ancestors_for_super(name)
209
+
210
+ if respond_to?(:ancestors)
211
+ method.instance_variable_set(:@context_for_super,
212
+ :klass => self,
213
+ :level => :class,
214
+ :name => name)
215
+ else
216
+ method.instance_variable_set(:@context_for_super,
217
+ :klass => self.class,
218
+ :level => :instance,
219
+ :name => name)
220
+ end
221
+
222
+ method
223
+ end
235
224
 
236
- module BaseExtendedModule
237
- def module_meth
225
+ unless method_defined?(:method_without_ancestors_for_super) ||
226
+ private_method_defined?(:method_without_ancestors_for_super)
227
+ alias_method :method_without_ancestors_for_super, :method
228
+ alias_method :method, :method_with_ancestors_for_super
229
+ end
238
230
  end
239
231
  end
240
232
 
241
- class BaseClass
242
- include BaseIncludedModule
243
- extend BaseExtendedModule
233
+ if $PROGRAM_NAME == __FILE__
234
+ require "rspec/core"
235
+ require "rspec/expectations"
236
+ require "rspec/matchers"
244
237
 
245
- def self.singleton_meth
238
+ module BaseIncludedModule
239
+ def module_meth
240
+ end
246
241
  end
247
242
 
248
- def meth
243
+ module BaseExtendedModule
244
+ def module_meth
245
+ end
249
246
  end
250
- end
251
247
 
252
- class DerivedClass < BaseClass
253
- def self.singleton_meth
254
- end
248
+ class BaseClass
249
+ include BaseIncludedModule
250
+ extend BaseExtendedModule
255
251
 
256
- def self.module_meth
257
- end
252
+ def self.singleton_meth
253
+ end
258
254
 
259
- def meth
255
+ def meth
256
+ end
260
257
  end
261
258
 
262
- def module_meth
263
- end
264
- end
259
+ class DerivedClass < BaseClass
260
+ def self.singleton_meth
261
+ end
265
262
 
266
- if $PROGRAM_NAME == __FILE__
267
- require "rspec/core"
268
- require "rspec/expectations"
269
- require "rspec/matchers"
263
+ def self.module_meth
264
+ end
265
+
266
+ def meth
267
+ end
270
268
 
269
+ def module_meth
270
+ end
271
+ end
271
272
 
272
273
  describe Method do
273
274
  describe "#super" do
@@ -1,2 +1,3 @@
1
1
  require "method_extensions/method/source_with_doc"
2
- require "method_extensions/method/super"
2
+ # We don't require `super` by default since it patches core methods
3
+ # require "method_extensions/method/super"
@@ -3,7 +3,7 @@ $:.unshift lib unless $:.include?(lib)
3
3
 
4
4
  Gem::Specification.new do |s|
5
5
  s.name = "method_extensions"
6
- s.version = "0.0.1"
6
+ s.version = "0.0.2"
7
7
  s.authors = ["Evgeniy Dolzhenko"]
8
8
  s.email = ["dolzenko@gmail.com"]
9
9
  s.homepage = "http://github.com/dolzenko/method_extensions"
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 0
8
- - 1
9
- version: 0.0.1
8
+ - 2
9
+ version: 0.0.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Evgeniy Dolzhenko
@@ -42,7 +42,6 @@ rdoc_options: []
42
42
  require_paths:
43
43
  - lib
44
44
  required_ruby_version: !ruby/object:Gem::Requirement
45
- none: false
46
45
  requirements:
47
46
  - - ">="
48
47
  - !ruby/object:Gem::Version
@@ -50,7 +49,6 @@ required_ruby_version: !ruby/object:Gem::Requirement
50
49
  - 0
51
50
  version: "0"
52
51
  required_rubygems_version: !ruby/object:Gem::Requirement
53
- none: false
54
52
  requirements:
55
53
  - - ">="
56
54
  - !ruby/object:Gem::Version
@@ -60,7 +58,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
60
58
  requirements: []
61
59
 
62
60
  rubyforge_project:
63
- rubygems_version: 1.3.7
61
+ rubygems_version: 1.3.6
64
62
  signing_key:
65
63
  specification_version: 3
66
64
  summary: Method object extensions for better code navigation