ruby_tree_sitter 0.20.6.3-x86_64-linux

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 (41) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +152 -0
  4. data/ext/tree_sitter/encoding.c +29 -0
  5. data/ext/tree_sitter/extconf.rb +172 -0
  6. data/ext/tree_sitter/input.c +126 -0
  7. data/ext/tree_sitter/input_edit.c +42 -0
  8. data/ext/tree_sitter/language.c +134 -0
  9. data/ext/tree_sitter/logger.c +212 -0
  10. data/ext/tree_sitter/macros.h +163 -0
  11. data/ext/tree_sitter/node.c +310 -0
  12. data/ext/tree_sitter/parser.c +203 -0
  13. data/ext/tree_sitter/point.c +26 -0
  14. data/ext/tree_sitter/quantifier.c +43 -0
  15. data/ext/tree_sitter/query.c +157 -0
  16. data/ext/tree_sitter/query_capture.c +28 -0
  17. data/ext/tree_sitter/query_cursor.c +103 -0
  18. data/ext/tree_sitter/query_error.c +41 -0
  19. data/ext/tree_sitter/query_match.c +44 -0
  20. data/ext/tree_sitter/query_predicate_step.c +83 -0
  21. data/ext/tree_sitter/range.c +35 -0
  22. data/ext/tree_sitter/symbol_type.c +46 -0
  23. data/ext/tree_sitter/tree.c +145 -0
  24. data/ext/tree_sitter/tree_cursor.c +97 -0
  25. data/ext/tree_sitter/tree_sitter.c +32 -0
  26. data/ext/tree_sitter/tree_sitter.h +107 -0
  27. data/lib/tree_sitter/node.rb +164 -0
  28. data/lib/tree_sitter/tree_sitter.so +0 -0
  29. data/lib/tree_sitter/version.rb +5 -0
  30. data/lib/tree_sitter.rb +13 -0
  31. data/test/README.md +15 -0
  32. data/test/test_helper.rb +9 -0
  33. data/test/tree_sitter/language_test.rb +68 -0
  34. data/test/tree_sitter/logger_test.rb +69 -0
  35. data/test/tree_sitter/node_test.rb +355 -0
  36. data/test/tree_sitter/parser_test.rb +140 -0
  37. data/test/tree_sitter/query_test.rb +153 -0
  38. data/test/tree_sitter/tree_cursor_test.rb +83 -0
  39. data/test/tree_sitter/tree_test.rb +51 -0
  40. data/tree_sitter.gemspec +32 -0
  41. metadata +192 -0
@@ -0,0 +1,164 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ class Node
5
+ def fields
6
+ return @fields if @fields
7
+
8
+ @fields = Set.new
9
+ child_count.times do |i|
10
+ name = field_name_for_child(i)
11
+ @fields << name.to_sym if name
12
+ end
13
+
14
+ @fields
15
+ end
16
+
17
+ def field?(field)
18
+ fields.include?(field)
19
+ end
20
+
21
+ # Access node's named children.
22
+ #
23
+ # It's similar to {#fetch}, but differes in input type, return values, and
24
+ # the internal implementation.
25
+ #
26
+ # Both of these methods exist for separate use cases, but also because
27
+ # sometime tree-sitter does some monkey business and having both separate
28
+ # implementations can help.
29
+ #
30
+ # Comparison with {#fetch}:
31
+ #
32
+ # [] | fetch
33
+ # ------------------------------+----------------------
34
+ # input types Integer, String, Symbol | Array<String, Symbol>
35
+ # Array<Integer, String, Symbol>|
36
+ # ------------------------------+----------------------
37
+ # returns 1-to-1 correspondance with | unique nodes
38
+ # input |
39
+ # ------------------------------+----------------------
40
+ # uses named_child | field_name_for_child
41
+ # child_by_field_name | via each_node
42
+ # ------------------------------+----------------------
43
+ #
44
+ # @param keys [Integer | String | Symbol | Array<Integer, String, Symbol>, #read]
45
+ #
46
+ # @return [Node | Array<Node>]
47
+ def [](*keys)
48
+ case keys.length
49
+ when 0 then raise "#{self.class.name}##{__method__} requires a key."
50
+ when 1
51
+ case k = keys.first
52
+ when Numeric then named_child(k)
53
+ when String, Symbol
54
+ if fields.include?(k.to_sym)
55
+ child_by_field_name(k.to_s)
56
+ else
57
+ raise "Cannot find field #{k}"
58
+ end
59
+ else raise <<~ERR
60
+ #{self.class.name}##{__method__} accepts Integer and returns named child at given index,
61
+ or a (String | Symbol) and returns the child by given field name.
62
+ ERR
63
+ end
64
+ else
65
+ keys.map { |key| self[key] }
66
+ end
67
+ end
68
+
69
+ # Allows access to child_by_field_name without using [].
70
+ def method_missing(method_name, *_args, &_block)
71
+ if fields.include?(method_name)
72
+ child_by_field_name(method_name.to_s)
73
+ else
74
+ super
75
+ end
76
+ end
77
+
78
+ def respond_to_missing?(*args)
79
+ init_fields
80
+ args.length == 1 && fields.include?(args[0])
81
+ end
82
+
83
+ # Iterate over a node's children.
84
+ #
85
+ # @yieldparam child [Node] the child
86
+ def each
87
+ return enum_for __method__ if !block_given?
88
+
89
+ (0...(child_count)).each do |i|
90
+ yield child(i)
91
+ end
92
+ end
93
+
94
+ # Iterate over a node's children assigned to a field.
95
+ #
96
+ # @yieldparam name [NilClass | String] field name.
97
+ # @yieldparam child [Node] the child.
98
+ def each_field
99
+ return enum_for __method__ if !block_given?
100
+
101
+ each.with_index do |c, i|
102
+ f = field_name_for_child(i)
103
+ next if f.nil? || f.empty?
104
+
105
+ yield f, c
106
+ end
107
+ end
108
+
109
+ # Iterate over a node's named children
110
+ #
111
+ # @yieldparam child [Node] the child
112
+ def each_named
113
+ return enum_for __method__ if !block_given?
114
+
115
+ (0...(named_child_count)).each do |i|
116
+ yield named_child(i)
117
+ end
118
+ end
119
+
120
+ def to_a
121
+ each.to_a
122
+ end
123
+
124
+ # Access node's named children.
125
+ #
126
+ # It's similar to {#fetch}, but differes in input type, return values, and
127
+ # the internal implementation.
128
+ #
129
+ # Both of these methods exist for separate use cases, but also because
130
+ # sometime tree-sitter does some monkey business and having both separate
131
+ # implementations can help.
132
+ #
133
+ # Comparison with {#fetch}:
134
+ #
135
+ # [] | fetch
136
+ # ------------------------------+----------------------
137
+ # input types Integer, String, Symbol | String, Symbol
138
+ # Array<Integer, String, Symbol>| Array<String, Symbol>
139
+ # ------------------------------+----------------------
140
+ # returns 1-to-1 correspondance with | unique nodes
141
+ # input |
142
+ # ------------------------------+----------------------
143
+ # uses named_child | field_name_for_child
144
+ # child_by_field_name | via each_node
145
+ # ------------------------------+----------------------
146
+ def fetch(*keys)
147
+ dict = {}
148
+ keys.each.with_index do |k, i|
149
+ dict[k.to_s] = i
150
+ end
151
+
152
+ res = {}
153
+ each_field do |f, c|
154
+ if dict.key?(f)
155
+ res[dict[f]] = c
156
+ dict.delete(f)
157
+ end
158
+ break if dict.empty?
159
+ end
160
+
161
+ res.sort.map { |_, v| v }
162
+ end
163
+ end
164
+ end
Binary file
@@ -0,0 +1,5 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ VERSION = '0.20.6.3'
5
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module TreeSitter
4
+ end
5
+
6
+ require 'set'
7
+
8
+ require 'tree_sitter/version'
9
+
10
+ require 'tree_sitter/tree_sitter'
11
+ require 'tree_sitter/node'
12
+
13
+ ObjectSpace.define_finalizer(TreeSitter::Tree.class, proc { TreeSitter::Tree.finalizer })
data/test/README.md ADDED
@@ -0,0 +1,15 @@
1
+ # Unit testing
2
+
3
+ Since we don't have languages bundled in ruby gems, we have to load the dynamic
4
+ libraries from disk.
5
+
6
+ We're using the `bin/get` scripts to do so.
7
+
8
+ Since not all languages have a Makefile in their root dir, and we don't want to
9
+ mess with copying Makefiles, we're going to rely on languages that do have a
10
+ Makefile in their root.
11
+
12
+ So for the time being we're sticking with `ruby`.
13
+
14
+ We might need to change this strategy in the future if we're to test some
15
+ multilang parsing.
@@ -0,0 +1,9 @@
1
+ # frozen_string_literal: true
2
+
3
+ at_exit { GC.start }
4
+
5
+ require 'minitest/autorun'
6
+ require 'minitest/color'
7
+ require 'tree_sitter'
8
+
9
+ require_relative '../examples/helpers'
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+
5
+ ruby = TreeSitter.lang('ruby')
6
+ parser = TreeSitter::Parser.new
7
+ parser.language = ruby
8
+
9
+ program = <<~RUBY
10
+ def mul(a, b)
11
+ res = a * b
12
+ puts res.inspect
13
+ return res
14
+ end
15
+ RUBY
16
+
17
+ tree = parser.parse_string(nil, program)
18
+ root = tree.root_node
19
+
20
+ # NOTE: one should be weary of testing with data structures that are owned by
21
+ # parsers. They are not reliable and we should expect them to break when these
22
+ # parsers evolve.
23
+
24
+ describe 'language' do
25
+ it 'must be able to load a library from `Pathname` (or any object that has `to_s`)' do
26
+ path =
27
+ if p = ENV.fetch('TREE_SITTER_PARSERS', nil)
28
+ Pathname(p) / "libtree-sitter-ruby.#{TreeSitter.ext}"
29
+ else
30
+ Pathname('tree-sitter-parsers') / 'ruby' / "libtree-sitter-ruby.#{TreeSitter.ext}"
31
+ end
32
+ ll = TreeSitter::Language.load('ruby', path)
33
+ assert ll.field_count.positive?
34
+ end
35
+
36
+ it 'must return symbol count' do
37
+ assert ruby.symbol_count.positive?
38
+ end
39
+
40
+ it 'must return symbol name' do
41
+ assert_equal 'end', ruby.symbol_name(0)
42
+ end
43
+
44
+ it 'must return symbol id for string name' do
45
+ assert ruby.symbol_for_name(root.type, root.named?).positive?
46
+ end
47
+
48
+ it 'must return field count' do
49
+ assert ruby.field_count.positive?
50
+ end
51
+
52
+ it 'must return field name for id' do
53
+ assert_equal 'alias', ruby.field_name_for_id(1)
54
+ end
55
+
56
+ it 'must return field name for id' do
57
+ assert_equal 1, ruby.field_id_for_name('alias')
58
+ end
59
+
60
+ it 'must return field symbol type' do
61
+ assert_equal TreeSitter::SymbolType::AUXILIARY, ruby.symbol_type(0)
62
+ end
63
+
64
+ it 'must be of correct version' do
65
+ assert ruby.version <= TreeSitter::LANGUAGE_VERSION \
66
+ && ruby.version >= TreeSitter::MIN_COMPATIBLE_LANGUAGE_VERSION
67
+ end
68
+ end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+ require 'stringio'
5
+
6
+ ruby = TreeSitter.lang('ruby')
7
+ parser = TreeSitter::Parser.new
8
+ parser.language = ruby
9
+
10
+ program = <<~RUBY
11
+ def mul(a, b)
12
+ res = a * b
13
+ puts res.inspect
14
+ return res
15
+ end
16
+ RUBY
17
+
18
+ # Use with fork.
19
+ #
20
+ # Minitest on ruby 2.7 was failing sometimes for no particular reason,
21
+ # complaining about some random number not having a `write` method.
22
+ #
23
+ # My assumption is that the global var $stderr is not playing nice when
24
+ # we try to replace it and other minitest stuff are going alongside.
25
+ #
26
+ # If this theory holds, then forking should solve any race conditions that
27
+ # minitest could introduce. Let's wait and see.
28
+ def capture_stderr
29
+ # The output stream must be an IO-like object. In this case we capture it in
30
+ # an in-memory IO object so we can return the string value. You can assign any
31
+ # IO object here.
32
+ previous_stderr = $stderr
33
+ $stderr = StringIO.new
34
+ yield
35
+ $stderr.string
36
+ ensure
37
+ # Restore the previous value of stderr (typically equal to STDERR).
38
+ $stderr = previous_stderr
39
+ end
40
+
41
+ describe 'logging' do
42
+ it 'should log to stderr by default' do
43
+ fork do
44
+ captured_output = capture_stderr do
45
+ # Does not output anything directly.
46
+ parser.logger = TreeSitter::Logger.new
47
+ parser.parse_string(nil, program)
48
+ end
49
+ refute_equal 0, captured_output.length
50
+ end
51
+ end
52
+
53
+ it 'should log to IO objects' do
54
+ backend = StringIO.new
55
+ parser.logger = TreeSitter::Logger.new(backend)
56
+ parser.parse_string(nil, program)
57
+ refute_equal 0, backend.length
58
+ end
59
+
60
+ it 'should format output when a format string is passed' do
61
+ delim = '~~~~~'
62
+ backend = StringIO.new
63
+ parser.logger = TreeSitter::Logger.new(backend, "%s#{delim}%s")
64
+ parser.parse_string(nil, program)
65
+ backend.each_line do |l|
66
+ assert (/#{delim}/ =~ l), 'delimiter must be in every single line'
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,355 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative '../test_helper'
4
+
5
+ ruby = TreeSitter.lang('ruby')
6
+ parser = TreeSitter::Parser.new
7
+ parser.language = ruby
8
+
9
+ program = <<~RUBY
10
+ def mul(a, b)
11
+ res = a * b
12
+ puts res.inspect
13
+ return res
14
+ end
15
+ RUBY
16
+
17
+ tree = parser.parse_string(nil, program)
18
+ root = tree.root_node
19
+
20
+ describe 'type' do
21
+ it 'must be a Symbol' do
22
+ assert_instance_of Symbol, root.type
23
+ end
24
+
25
+ it 'must be "program" on root' do
26
+ assert_equal :program, root.type
27
+ end
28
+ end
29
+
30
+ describe 'symbol' do
31
+ it 'must be an Integer' do
32
+ assert_instance_of Integer, root.symbol
33
+ end
34
+ end
35
+
36
+ describe 'start_byte' do
37
+ it 'must be an Integer' do
38
+ assert_instance_of Integer, root.start_byte
39
+ end
40
+
41
+ it 'must be an 0' do
42
+ assert_equal 0, root.start_byte
43
+ end
44
+ end
45
+
46
+ describe 'end_byte' do
47
+ it 'must be an Integer' do
48
+ assert_instance_of Integer, root.end_byte
49
+ end
50
+
51
+ it 'must not be 0' do
52
+ refute_equal 0, root.end_byte
53
+ end
54
+ end
55
+
56
+ describe 'start_point' do
57
+ it 'must be an instance of point' do
58
+ assert_instance_of TreeSitter::Point, root.start_point
59
+ end
60
+
61
+ it 'must be at row 0' do
62
+ assert_equal 0, root.start_point.row
63
+ end
64
+
65
+ it 'must be at column 0' do
66
+ assert_equal 0, root.start_point.row
67
+ end
68
+ end
69
+
70
+ describe 'end_point' do
71
+ it 'must be an instance of point' do
72
+ assert_instance_of TreeSitter::Point, root.end_point
73
+ end
74
+
75
+ it 'must not be at row 0' do
76
+ refute_equal 0, root.end_point.row
77
+ end
78
+
79
+ it 'must not be at column 0' do
80
+ refute_equal 0, root.end_point.row
81
+ end
82
+ end
83
+
84
+ describe 'string' do
85
+ it 'must be an instance of string' do
86
+ assert_instance_of String, root.to_s
87
+ end
88
+
89
+ it 'must be non-empty' do
90
+ refute root.to_s.empty?
91
+ end
92
+ end
93
+
94
+ describe 'predicates' do
95
+ it 'must not be null' do
96
+ refute_nil root.null?
97
+ end
98
+
99
+ it 'must be named' do
100
+ assert root.named?
101
+ end
102
+
103
+ it 'must not be missing' do
104
+ refute root.missing?
105
+ end
106
+
107
+ it 'must not be extra' do
108
+ refute root.extra?
109
+ end
110
+
111
+ it 'must not have any changes' do
112
+ # TODO: needs a more elaborate test to check for true changes?
113
+ refute root.changed?
114
+ end
115
+
116
+ it 'must not have no errors' do
117
+ refute root.error?
118
+ end
119
+ end
120
+
121
+ describe 'parent' do
122
+ # NOTE: never call parent on root. It will segfault.
123
+ #
124
+ # tree-sitter does not provide a way to check if a node has a parent.
125
+
126
+ it 'must never be nil' do
127
+ refute_nil root.child(0).parent
128
+ end
129
+
130
+ it 'must be root for its children' do
131
+ assert_equal root, root.child(0).parent
132
+ end
133
+ end
134
+
135
+ describe 'child' do
136
+ before do
137
+ @child = root.child(0)
138
+ end
139
+
140
+ it 'must return proper children count' do
141
+ assert_equal 1, root.child_count
142
+ end
143
+
144
+ it 'must return proper name child count' do
145
+ assert_equal 5, @child.named_child_count
146
+ end
147
+
148
+ it 'must return proper name child' do
149
+ assert_equal @child.child(1), @child.named_child(0)
150
+ end
151
+
152
+ it 'must return proper child by field name' do
153
+ assert_equal @child.child(1), @child.child_by_field_name('name')
154
+ end
155
+
156
+ it 'must return proper child by field id' do
157
+ assert_equal @child.child(1), @child.child_by_field_id(ruby.field_id_for_name('name'))
158
+ end
159
+
160
+ it 'must return proper child for byte' do
161
+ child = @child.child(0)
162
+ assert_equal child, @child.first_child_for_byte(child.start_byte)
163
+ end
164
+
165
+ it 'must return proper named child for byte' do
166
+ child = @child.child(1)
167
+ assert_equal child, @child.first_named_child_for_byte(child.start_byte)
168
+ end
169
+
170
+ it 'must return proper descendant for byte range' do
171
+ child = @child.child(1)
172
+ assert_equal child, @child.descendant_for_byte_range(child.start_byte, child.end_byte)
173
+ end
174
+
175
+ it 'must return proper descendant for point range' do
176
+ child = @child.child(1)
177
+ assert_equal child, @child.descendant_for_point_range(child.start_point, child.end_point)
178
+ end
179
+
180
+ it 'must return proper named descendant for byte range' do
181
+ child = @child.child(1)
182
+ assert_equal child, @child.named_descendant_for_byte_range(child.start_byte, child.end_byte)
183
+ end
184
+
185
+ it 'must return proper named descendant for point range' do
186
+ child = @child.child(1)
187
+ assert_equal child, @child.named_descendant_for_point_range(child.start_point, child.end_point)
188
+ end
189
+
190
+ it 'must raise an exception for wrong ranges' do
191
+ child = @child.child(0)
192
+ assert_raises IndexError do
193
+ @child.descendant_for_byte_range(child.end_byte, child.start_byte)
194
+ end
195
+ assert_raises IndexError do
196
+ @child.named_descendant_for_byte_range(child.end_byte, child.start_byte)
197
+ end
198
+ assert_raises IndexError do
199
+ p1 = TreeSitter::Point.new
200
+ p1.row = @child.end_point.row
201
+ p1.column = @child.end_point.column + 1
202
+ @child.named_descendant_for_point_range(@child.start_point, p1)
203
+ end
204
+ assert_raises IndexError do
205
+ p1 = TreeSitter::Point.new
206
+ p1.row = @child.end_point.row
207
+ p1.column = @child.end_point.column + 1
208
+ @child.named_descendant_for_point_range(@child.start_point, p1)
209
+ end
210
+ end
211
+ end
212
+
213
+ describe 'field_name' do
214
+ before do
215
+ @child = root.child(0)
216
+ end
217
+
218
+ it 'must return proper field name' do
219
+ assert_equal 'name', @child.field_name_for_child(1)
220
+ end
221
+ end
222
+
223
+ describe 'siblings' do
224
+ before do
225
+ @child = root.child(0).child(0)
226
+ end
227
+
228
+ it 'must return proper next/previous siblings' do
229
+ assert_equal @child, @child.next_sibling.prev_sibling
230
+ end
231
+
232
+ it 'must return proper next/previous named siblings' do
233
+ assert_equal @child.parent.child(1), @child.next_named_sibling
234
+ end
235
+ end
236
+
237
+ # TODO: edit
238
+
239
+ # Tese are High-Level Ruby APIs that we designed.
240
+ # They rely on the bindings.
241
+
242
+ describe '[]' do
243
+ before do
244
+ @child = root.child(0)
245
+ end
246
+
247
+ it 'must return a named child by index when index is an Integer' do
248
+ assert_equal @child.named_child(0), @child[0]
249
+ end
250
+
251
+ it 'must return a child by field name when index is a (String | Symbol)' do
252
+ assert_equal @child.named_child(0), @child[:name]
253
+ assert_equal @child.named_child(0), @child['name']
254
+ end
255
+
256
+ it 'must return an array of nodes when index is an Array' do
257
+ arr = [@child.named_child(0)] * 3
258
+ assert_equal arr, @child[0, :name, 'name']
259
+ end
260
+
261
+ it 'must throw an exception when out of index' do
262
+ assert_raises { @child[255] }
263
+ end
264
+
265
+ it 'must throw an exception when field is not found (NO SIGSEGV ANYMORE!)' do
266
+ assert_raises { @child[:randomzes] }
267
+ end
268
+ end
269
+
270
+ describe 'each' do
271
+ before do
272
+ @child = root.child(0)
273
+ end
274
+
275
+ it 'must iterate over all children' do
276
+ i = 0
277
+ @child.each do |_|
278
+ i += 1
279
+ end
280
+ assert @child.child_count, i
281
+ end
282
+
283
+ it 'must iterate ove named children attached to fields only' do
284
+ @child.each_field do |f, c|
285
+ refute f.nil?
286
+ refute f.empty?
287
+ assert_equal @child[f], c
288
+ end
289
+ end
290
+
291
+ it 'must iterate over named children when `each_named_child`' do
292
+ i = 0
293
+ @child.each_named do |c|
294
+ assert c.named?
295
+ i += 1
296
+ end
297
+ assert @child.named_child_count, i
298
+ end
299
+ end
300
+
301
+ describe 'method_missing' do
302
+ before do
303
+ @child = root.child(0)
304
+ end
305
+
306
+ it 'should act like the [] method when we pass (String | Symbol)' do
307
+ assert_equal @child[:name], @child.name
308
+ end
309
+ end
310
+
311
+ describe 'to_a' do
312
+ before do
313
+ @child = root.child(0)
314
+ end
315
+
316
+ it 'should return the list from each' do
317
+ ll = @child.to_a
318
+
319
+ refute ll.empty?
320
+
321
+ @child.each.with_index do |c, i|
322
+ assert_equal @child.child(i), c
323
+ end
324
+ end
325
+ end
326
+
327
+ describe 'fetch' do
328
+ before do
329
+ @child = root.child(0).child(4)
330
+ end
331
+
332
+ it 'should return all requested keys by order' do
333
+ method = @child.child(0)
334
+ arguments = @child.child(1)
335
+
336
+ m, a = @child.fetch(:method, :arguments)
337
+
338
+ assert_equal method, m
339
+ assert_equal arguments, a
340
+
341
+ a, m = @child.fetch(:arguments, :method)
342
+
343
+ assert_equal method, m
344
+ assert_equal arguments, a
345
+ end
346
+
347
+ it 'should return unique keys' do
348
+ method = @child.child(0)
349
+
350
+ m = @child.fetch(:method, :method)
351
+
352
+ assert_equal 1, m.length
353
+ assert_equal method, m.first
354
+ end
355
+ end