parser 2.2.0.3 → 2.2.0.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 32ce09c1a28d2549bf2f979555d9d961091df27b
4
- data.tar.gz: e936c4eb15b204dd1aa89bb107e615f2cf9549dd
3
+ metadata.gz: 8228d5693ac3104ea947dac416025a20f29c32e1
4
+ data.tar.gz: b078eb868955e08112f252dde8a4957bb91c5e9b
5
5
  SHA512:
6
- metadata.gz: 7abb6830a6804ed9b0debdb1ad1c985a33b947d1db7a66dfb36f7c0b3f1acafd74822984985756a67658f1b8a15da97fc7b62a9db2df76230ec4562c8d28bf84
7
- data.tar.gz: ab9d08b75232d9fdd210e50265db49fa7703b5a05d03fdd5d50756f00b40a359f6da0660dc9c7436721fcf0bf958bcc900763b577e077f74bc0cc0e5742dd5b6
6
+ metadata.gz: 41b75cd456f815491a2bce7b24e8fc7cd584982895c39ea8167dd46e4ceeead8e287851056099d3405c4eccab687b77934fbb2e5c7fe079f555f22244a5a306f
7
+ data.tar.gz: 3c7bbc92c7152e2bc3740a9db8524c7f3712330edc493e0d5cefdba614855cefa7a5172406d0e6192d7561f4d6b1c885fa00cb3db6e7f31612e5a967515dbdc0
@@ -1,6 +1,13 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ v2.2.0.4 (2015-04-14)
5
+ ---------------------
6
+
7
+ Features implemented:
8
+ * Add Parser::Source::Map#node. (whitequark)
9
+ * Add Parser::Source::Comment.associate_locations. (kubicle)
10
+
4
11
  v2.2.0.1 (2014-12-27)
5
12
  ---------------------
6
13
 
@@ -27,6 +27,8 @@ module Parser
27
27
  #
28
28
  def assign_properties(properties)
29
29
  if (location = properties[:location])
30
+ location = location.dup if location.frozen?
31
+ location.node = self
30
32
  @location = location
31
33
  end
32
34
  end
@@ -172,6 +172,13 @@ module Parser
172
172
  end
173
173
 
174
174
  def regexp_compose(begin_t, parts, end_t, options)
175
+ begin
176
+ static_regexp(parts, options)
177
+ rescue RegexpError => e
178
+ diagnostic :error, :invalid_regexp, { :message => e.message },
179
+ loc(begin_t).join(loc(end_t))
180
+ end
181
+
175
182
  n(:regexp, (parts << options),
176
183
  regexp_map(begin_t, end_t, options))
177
184
  end
@@ -325,7 +332,7 @@ module Parser
325
332
  when :__FILE__
326
333
  if @emit_file_line_as_literals
327
334
  n(:str, [ node.loc.expression.source_buffer.name ],
328
- node.loc)
335
+ node.loc.dup)
329
336
  else
330
337
  node
331
338
  end
@@ -333,14 +340,14 @@ module Parser
333
340
  when :__LINE__
334
341
  if @emit_file_line_as_literals
335
342
  n(:int, [ node.loc.expression.line ],
336
- node.loc)
343
+ node.loc.dup)
337
344
  else
338
345
  node
339
346
  end
340
347
 
341
348
  when :__ENCODING__
342
349
  n(:const, [ n(:const, [ nil, :Encoding], nil), :UTF_8 ],
343
- node.loc)
350
+ node.loc.dup)
344
351
 
345
352
  when :ident
346
353
  name, = *node
@@ -587,7 +594,7 @@ module Parser
587
594
  expr.updated(:arg)
588
595
  else
589
596
  n(:arg_expr, [ expr ],
590
- expr.loc)
597
+ expr.loc.dup)
591
598
  end
592
599
  end
593
600
 
@@ -598,7 +605,7 @@ module Parser
598
605
  expr.updated(:restarg)
599
606
  else
600
607
  n(:restarg_expr, [ expr ],
601
- expr.loc)
608
+ expr.loc.dup)
602
609
  end
603
610
  end
604
611
 
@@ -607,7 +614,7 @@ module Parser
607
614
  expr.updated(:blockarg)
608
615
  else
609
616
  n(:blockarg_expr, [ expr ],
610
- expr.loc)
617
+ expr.loc.dup)
611
618
  end
612
619
  end
613
620
 
@@ -708,30 +715,8 @@ module Parser
708
715
  def match_op(receiver, match_t, arg)
709
716
  source_map = send_binary_op_map(receiver, match_t, arg)
710
717
 
711
- if receiver.type == :regexp &&
712
- receiver.children.count == 2 &&
713
- receiver.children.first.type == :str
714
-
715
- str_node, opt_node = *receiver
716
- regexp_body, = *str_node
717
- *regexp_opt = *opt_node
718
-
719
- if defined?(Encoding)
720
- regexp_body = case
721
- when regexp_opt.include?(:u)
722
- regexp_body.encode(Encoding::UTF_8)
723
- when regexp_opt.include?(:e)
724
- regexp_body.encode(Encoding::EUC_JP)
725
- when regexp_opt.include?(:s)
726
- regexp_body.encode(Encoding::WINDOWS_31J)
727
- when regexp_opt.include?(:n)
728
- regexp_body.encode(Encoding::BINARY)
729
- else
730
- regexp_body
731
- end
732
- end
733
-
734
- Regexp.new(regexp_body).names.each do |name|
718
+ if (regexp = static_regexp_node(receiver))
719
+ regexp.names.each do |name|
735
720
  @parser.static_env.declare(name)
736
721
  end
737
722
 
@@ -1382,6 +1367,55 @@ module Parser
1382
1367
  # HELPERS
1383
1368
  #
1384
1369
 
1370
+ # Extract a static string from e.g. a regular expression,
1371
+ # honoring the fact that MRI expands interpolations like #{""}
1372
+ # at parse time.
1373
+ def static_string(nodes)
1374
+ nodes.map do |node|
1375
+ case node.type
1376
+ when :str
1377
+ node.children[0]
1378
+ when :begin
1379
+ if (string = static_string(node.children))
1380
+ string
1381
+ else
1382
+ return nil
1383
+ end
1384
+ else
1385
+ return nil
1386
+ end
1387
+ end.join
1388
+ end
1389
+
1390
+ def static_regexp(parts, options)
1391
+ source = static_string(parts)
1392
+ return nil if source.nil?
1393
+
1394
+ if defined?(Encoding)
1395
+ source = case
1396
+ when options.children.include?(:u)
1397
+ source.encode(Encoding::UTF_8)
1398
+ when options.children.include?(:e)
1399
+ source.encode(Encoding::EUC_JP)
1400
+ when options.children.include?(:s)
1401
+ source.encode(Encoding::WINDOWS_31J)
1402
+ when options.children.include?(:n)
1403
+ source.encode(Encoding::BINARY)
1404
+ else
1405
+ source
1406
+ end
1407
+ end
1408
+
1409
+ Regexp.new(source)
1410
+ end
1411
+
1412
+ def static_regexp_node(node)
1413
+ if node.type == :regexp
1414
+ parts, options = node.children[0..-2], node.children[-1]
1415
+ static_regexp(parts, options)
1416
+ end
1417
+ end
1418
+
1385
1419
  def collapse_string_parts?(parts)
1386
1420
  parts.one? &&
1387
1421
  [:str, :dstr].include?(parts.first.type)
@@ -29,8 +29,8 @@ module Parser
29
29
  CurrentRuby = Ruby20
30
30
 
31
31
  when /^2\.1\./
32
- if RUBY_VERSION != '2.1.5'
33
- warn_syntax_deviation 'parser/ruby21', '2.1.5'
32
+ if RUBY_VERSION != '2.1.6'
33
+ warn_syntax_deviation 'parser/ruby21', '2.1.6'
34
34
  end
35
35
 
36
36
  require 'parser/ruby21'
@@ -54,6 +54,7 @@ module Parser
54
54
  :block_and_blockarg => 'both block argument and literal block are passed',
55
55
  :masgn_as_condition => 'multiple assignment in conditional context',
56
56
  :block_given_to_yield => 'block given to yield',
57
+ :invalid_regexp => '%{message}',
57
58
 
58
59
  # Parser warnings
59
60
  :useless_else => 'else without rescue is useless',
@@ -19,19 +19,33 @@ module Parser
19
19
  alias_method :loc, :location
20
20
 
21
21
  ##
22
- # Associate `comments` with `ast` nodes by their location in the
23
- # source.
22
+ # Associate `comments` with `ast` nodes by their corresponding node.
24
23
  #
25
24
  # @param [Parser::AST::Node] ast
26
25
  # @param [Array(Comment)] comments
27
26
  # @return [Hash(Parser::AST::Node, Array(Comment))]
28
- # @see Parser::Source::Comment::Associator
27
+ # @see Parser::Source::Comment::Associator#associate
28
+ # @deprecated Use {associate_locations}.
29
29
  #
30
30
  def self.associate(ast, comments)
31
31
  associator = Associator.new(ast, comments)
32
32
  associator.associate
33
33
  end
34
34
 
35
+ ##
36
+ # Associate `comments` with `ast` nodes by their location in the
37
+ # source.
38
+ #
39
+ # @param [Parser::AST::Node] ast
40
+ # @param [Array(Comment)] comments
41
+ # @return [Hash(Parser::Source::Map, Array(Comment))]
42
+ # @see Parser::Source::Comment::Associator#associate_locations
43
+ #
44
+ def self.associate_locations(ast, comments)
45
+ associator = Associator.new(ast, comments)
46
+ associator.associate_locations
47
+ end
48
+
35
49
  ##
36
50
  # @param [Parser::Source::Range] range
37
51
  #
@@ -27,7 +27,7 @@ module Parser
27
27
  # # #<Parser::Source::Comment (string):4:3 "# @see bar">]
28
28
  # # }
29
29
  #
30
- # @see #associate
30
+ # @see {associate}
31
31
  #
32
32
  # @!attribute skip_directives
33
33
  # Skip file processing directives disguised as comments.
@@ -76,78 +76,125 @@ module Parser
76
76
  # [#<Parser::Source::Comment (string):3:8 "# bar">]
77
77
  # }
78
78
  #
79
+ # Note that {associate} produces unexpected result for nodes which are
80
+ # equal but have distinct locations; comments for these nodes are merged.
81
+ #
79
82
  # @return [Hash(Parser::AST::Node, Array(Parser::Source::Comment))]
83
+ # @deprecated Use {associate_locations}.
80
84
  #
81
85
  def associate
86
+ @map_using_locations = false
87
+ do_associate
88
+ end
89
+
90
+ ##
91
+ # Same as {associate}, but uses `node.loc` instead of `node` as
92
+ # the hash key, thus producing an unambiguous result even in presence
93
+ # of equal nodes.
94
+ #
95
+ # @return [Hash(Parser::Source::Map, Array(Parser::Source::Comment))]
96
+ #
97
+ def associate_locations
98
+ @map_using_locations = true
99
+ do_associate
100
+ end
101
+
102
+ private
103
+
104
+ def do_associate
82
105
  @mapping = Hash.new { |h, k| h[k] = [] }
83
- @comment_num = 0
106
+ @comment_num = -1
107
+ advance_comment
84
108
 
85
109
  advance_through_directives if @skip_directives
86
110
 
87
- process(nil, @ast)
111
+ @prev_node = nil
112
+ visit(@ast)
88
113
 
89
114
  @mapping
90
115
  end
91
116
 
92
- private
117
+ def visit(node)
118
+ process_node(node)
93
119
 
94
- def process(upper_node, node)
95
- if node.type == :begin
96
- prev_node, next_node = nil, upper_node
97
- else
98
- while current_comment_between?(prev_node, node)
99
- associate_and_advance_comment(node)
120
+ if node.children.length > 0
121
+ node.children.each do |child|
122
+ next unless child.is_a?(AST::Node) && child.loc && child.loc.expression
123
+ visit(child)
100
124
  end
101
-
102
- prev_node, next_node = nil, upper_node
125
+ process_trailing_comments(node)
126
+ @prev_node = node
103
127
  end
128
+ end
104
129
 
105
- node.children.each do |child|
106
- if child.is_a?(AST::Node) && child.loc && child.loc.expression
107
- prev_node, next_node = next_node, child
108
-
109
- process(prev_node, child)
110
- end
130
+ def process_node(node)
131
+ return unless node.type != :begin
132
+ while current_comment_between?(@prev_node, node)
133
+ associate_and_advance_comment(@prev_node, node)
111
134
  end
135
+ @prev_node = node
112
136
  end
113
137
 
114
- def current_comment
115
- @comments[@comment_num]
138
+ def process_trailing_comments(parent)
139
+ while current_comment_decorates?(@prev_node)
140
+ associate_and_advance_comment(@prev_node, nil)
141
+ end
142
+ while current_comment_before_end?(parent)
143
+ associate_and_advance_comment(@prev_node, nil)
144
+ end
116
145
  end
117
146
 
118
147
  def advance_comment
119
148
  @comment_num += 1
149
+ @current_comment = @comments[@comment_num]
120
150
  end
121
151
 
122
152
  def current_comment_between?(prev_node, next_node)
123
- return false if current_comment.nil?
153
+ return false if !@current_comment
154
+ comment_loc = @current_comment.location.expression
124
155
 
125
- comment_loc = current_comment.location.expression
126
- next_loc = next_node.location.expression
156
+ if next_node
157
+ next_loc = next_node.location.expression
158
+ return false if comment_loc.end_pos > next_loc.begin_pos
159
+ end
160
+ if prev_node
161
+ prev_loc = prev_node.location.expression
162
+ return false if comment_loc.begin_pos < prev_loc.begin_pos
163
+ end
164
+ true
165
+ end
127
166
 
128
- if prev_node.nil?
129
- comment_loc.end_pos <= next_loc.begin_pos
130
- else
131
- prev_loc = prev_node.location.expression
167
+ def current_comment_decorates?(prev_node)
168
+ return false if !@current_comment
169
+ @current_comment.location.line == prev_node.location.line
170
+ end
132
171
 
133
- comment_loc.begin_pos >= prev_loc.end_pos &&
134
- comment_loc.end_pos <= next_loc.begin_pos
135
- end
172
+ def current_comment_before_end?(parent)
173
+ return false if !@current_comment
174
+ comment_loc = @current_comment.location.expression
175
+ parent_loc = parent.location.expression
176
+ comment_loc.end_pos <= parent_loc.end_pos
136
177
  end
137
178
 
138
- def associate_and_advance_comment(node)
139
- @mapping[node] << current_comment
179
+ def associate_and_advance_comment(prev_node, node)
180
+ if prev_node && node
181
+ owner_node = (@current_comment.location.line == prev_node.location.line) ? prev_node : node
182
+ else
183
+ owner_node = prev_node ? prev_node : node
184
+ end
185
+ key = @map_using_locations ? owner_node.location : owner_node
186
+ @mapping[key] << @current_comment
140
187
  advance_comment
141
188
  end
142
189
 
143
190
  def advance_through_directives
144
191
  # Skip shebang.
145
- if current_comment && current_comment.text =~ /^#!/
192
+ if @current_comment && @current_comment.text =~ /^#!/
146
193
  advance_comment
147
194
  end
148
195
 
149
196
  # Skip encoding line.
150
- if current_comment && current_comment.text =~ Buffer::ENCODING_RE
197
+ if @current_comment && @current_comment.text =~ Buffer::ENCODING_RE
151
198
  advance_comment
152
199
  end
153
200
  end
@@ -56,20 +56,38 @@ module Parser
56
56
  # # @begin=#<Source::Range (string) 0...1>,
57
57
  # # @expression=#<Source::Range (string) 0...6>>
58
58
  #
59
+ # @!attribute [r] node
60
+ # The node that is described by this map. Nodes and maps have 1:1 correspondence.
61
+ # @return [Parser::AST::Node]
62
+ #
59
63
  # @!attribute [r] expression
60
64
  # @return [Range]
61
65
  #
62
66
  # @api public
63
67
  #
64
68
  class Map
69
+ attr_reader :node
65
70
  attr_reader :expression
66
71
 
67
72
  ##
68
73
  # @param [Range] expression
69
74
  def initialize(expression)
70
75
  @expression = expression
76
+ end
77
+
78
+ ##
79
+ # @api private
80
+ def initialize_copy(other)
81
+ super
82
+ @node = nil
83
+ end
71
84
 
85
+ ##
86
+ # @api private
87
+ def node=(node)
88
+ @node = node
72
89
  freeze
90
+ @node
73
91
  end
74
92
 
75
93
  ##
@@ -134,7 +152,7 @@ module Parser
134
152
  protected
135
153
 
136
154
  def with(&block)
137
- dup.tap(&block).freeze
155
+ dup.tap(&block)
138
156
  end
139
157
 
140
158
  def update_expression(expression_l)
@@ -1,3 +1,3 @@
1
1
  module Parser
2
- VERSION = '2.2.0.3'
2
+ VERSION = '2.2.0.4'
3
3
  end
@@ -95,6 +95,8 @@ module ParseHelper
95
95
  raise "No entity with AST path #{ast_path} in #{parsed_ast.inspect}"
96
96
  end
97
97
 
98
+ assert astlet.frozen?
99
+
98
100
  assert astlet.location.respond_to?(map_field),
99
101
  "(#{version}) #{astlet.location.inspect}.respond_to?(#{map_field.inspect}) for:\n#{parsed_ast.inspect}"
100
102
 
@@ -15,4 +15,15 @@ class TestBase < Minitest::Test
15
15
  assert_equal 1, comments.size
16
16
  assert_equal '# foo', comments.first.text
17
17
  end
18
+
19
+ def test_loc_to_node
20
+ ast = Parser::CurrentRuby.parse('1')
21
+ assert_equal ast.loc.node, ast
22
+ end
23
+
24
+ def test_loc_dup
25
+ ast = Parser::CurrentRuby.parse('1')
26
+ assert_equal nil, ast.loc.dup.node
27
+ Parser::AST::Node.new(:root, [], :location => ast.loc)
28
+ end
18
29
  end
@@ -360,6 +360,21 @@ class TestParser < Minitest::Test
360
360
  |~~~~~~~~~~~~~~ expression})
361
361
  end
362
362
 
363
+ def test_regex_error
364
+ # The tests work on 1.8, but with a different message.
365
+ assert_diagnoses(
366
+ [:error, :invalid_regexp, {:message => 'target of repeat operator is not specified: /?/'}],
367
+ %q[/?/],
368
+ %q(~~~ location),
369
+ ALL_VERSIONS - %w(1.8))
370
+
371
+ assert_diagnoses(
372
+ [:error, :invalid_regexp, {:message => 'target of repeat operator is not specified: /?/'}],
373
+ %q[/#{""}?/],
374
+ %q(~~~~~~~~ location),
375
+ ALL_VERSIONS - %w(1.8))
376
+ end
377
+
363
378
  # Arrays
364
379
 
365
380
  def test_array_plain
@@ -3152,11 +3167,12 @@ class TestParser < Minitest::Test
3152
3167
  assert_parses(
3153
3168
  s(:send,
3154
3169
  s(:regexp,
3155
- s(:begin, s(:str, '(?<match>bar)')),
3170
+ s(:begin, s(:int, 1)),
3171
+ s(:str, '(?<match>bar)'),
3156
3172
  s(:regopt)),
3157
3173
  :=~,
3158
3174
  s(:str, 'bar')),
3159
- %q{/#{'(?<match>bar)'}/ =~ 'bar'})
3175
+ %q{/#{1}(?<match>bar)/ =~ 'bar'})
3160
3176
  end
3161
3177
 
3162
3178
  # To superclass
@@ -2,18 +2,29 @@ require 'helper'
2
2
  require 'parser/ruby18'
3
3
 
4
4
  class TestSourceCommentAssociator < Minitest::Test
5
- def associate(code)
5
+ def parse_with_comments(code)
6
6
  parser = Parser::Ruby18.new
7
7
 
8
8
  buffer = Parser::Source::Buffer.new('(comments)')
9
9
  buffer.source = code
10
10
 
11
- ast, comments = parser.parse_with_comments(buffer)
11
+ parser.parse_with_comments(buffer)
12
+ end
13
+
14
+ def associate(code)
15
+ ast, comments = parse_with_comments(code)
12
16
  associations = Parser::Source::Comment.associate(ast, comments)
13
17
 
14
18
  [ ast, associations ]
15
19
  end
16
20
 
21
+ def associate_locations(code)
22
+ ast, comments = parse_with_comments(code)
23
+ associations = Parser::Source::Comment.associate_locations(ast, comments)
24
+
25
+ [ ast, associations ]
26
+ end
27
+
17
28
  def test_associate
18
29
  ast, associations = associate(<<-END)
19
30
  #!/usr/bin/env ruby
@@ -36,9 +47,9 @@ end
36
47
 
37
48
  klass_node = ast
38
49
  attr_accessor_node = ast.children[2].children[0]
39
- method_node = ast.children[2].children[1]
40
- expr_node = method_node.children[2]
41
- intermediate_node = expr_node.children[2]
50
+ method_node = ast.children[2].children[1] # def bar
51
+ expr_node = method_node.children[2] # 1 + 2
52
+ intermediate_node = expr_node.children[0] # 1
42
53
 
43
54
  assert_equal 5, associations.size
44
55
  assert_equal ['# Class comment', '# another class comment'],
@@ -47,12 +58,100 @@ end
47
58
  associations[attr_accessor_node].map(&:text)
48
59
  assert_equal ['# method comment'],
49
60
  associations[method_node].map(&:text)
50
- assert_equal ['# expr comment'],
61
+ assert_equal ['# expr comment', "# stray comment"],
51
62
  associations[expr_node].map(&:text)
52
63
  assert_equal ['# intermediate comment'],
53
64
  associations[intermediate_node].map(&:text)
54
65
  end
55
66
 
67
+ # The bug below is fixed by using associate_locations
68
+ def test_associate_dupe_statement
69
+ ast, associations = associate(<<-END)
70
+ class Foo
71
+ def bar
72
+ f1 # comment on 1st call to f1
73
+ f2
74
+ f1 # comment on 2nd call to f1
75
+ end
76
+ end
77
+ END
78
+
79
+ klass_node = ast
80
+ method_node = ast.children[2]
81
+ body = method_node.children[2]
82
+ f1_1_node = body.children[0]
83
+ f1_2_node = body.children[2]
84
+
85
+ assert_equal 1, associations.size
86
+ assert_equal ['# comment on 1st call to f1', '# comment on 2nd call to f1'],
87
+ associations[f1_1_node].map(&:text)
88
+ assert_equal ['# comment on 1st call to f1', '# comment on 2nd call to f1'],
89
+ associations[f1_2_node].map(&:text)
90
+ end
91
+
92
+ def test_associate_locations
93
+ ast, associations = associate_locations(<<-END)
94
+ #!/usr/bin/env ruby
95
+ # coding: utf-8
96
+ # Class comment
97
+ # another class comment
98
+ class Foo
99
+ # attr_accessor comment
100
+ attr_accessor :foo
101
+
102
+ # method comment
103
+ def bar
104
+ # expr comment
105
+ 1 + # intermediate comment
106
+ 2
107
+ # stray comment
108
+ end
109
+ end
110
+ END
111
+
112
+ klass_node = ast
113
+ attr_accessor_node = ast.children[2].children[0]
114
+ method_node = ast.children[2].children[1]
115
+ expr_node = method_node.children[2]
116
+ intermediate_node = expr_node.children[0]
117
+
118
+ assert_equal 5, associations.size
119
+ assert_equal ['# Class comment', '# another class comment'],
120
+ associations[klass_node.loc].map(&:text)
121
+ assert_equal ['# attr_accessor comment'],
122
+ associations[attr_accessor_node.loc].map(&:text)
123
+ assert_equal ['# method comment'],
124
+ associations[method_node.loc].map(&:text)
125
+ assert_equal ['# expr comment', '# stray comment'],
126
+ associations[expr_node.loc].map(&:text)
127
+ assert_equal ['# intermediate comment'],
128
+ associations[intermediate_node.loc].map(&:text)
129
+ end
130
+
131
+ def test_associate_locations_dupe_statement
132
+ ast, associations = associate_locations(<<-END)
133
+ class Foo
134
+ def bar
135
+ f1 # comment on 1st call to f1
136
+ f2
137
+ f1 # comment on 2nd call to f1
138
+ end
139
+ end
140
+ END
141
+
142
+ klass_node = ast
143
+ method_node = ast.children[2]
144
+ body = method_node.children[2]
145
+ f1_1_node = body.children[0]
146
+ f1_2_node = body.children[2]
147
+
148
+ assert_equal 2, associations.size
149
+ assert_equal ['# comment on 1st call to f1'],
150
+ associations[f1_1_node.loc].map(&:text)
151
+ assert_equal ['# comment on 2nd call to f1'],
152
+ associations[f1_2_node.loc].map(&:text)
153
+ end
154
+
56
155
  def test_associate_no_body
57
156
  ast, associations = associate(<<-END)
58
157
  # foo
@@ -91,7 +190,9 @@ def foo
91
190
  end
92
191
  END
93
192
 
94
- assert_equal 0, associations.size
193
+ assert_equal 1, associations.size
194
+ assert_equal ['# foo'],
195
+ associations[ast].map(&:text)
95
196
  end
96
197
 
97
198
  def test_associate___ENCODING__
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: parser
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.2.0.3
4
+ version: 2.2.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Peter Zotov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-02-13 00:00:00.000000000 Z
11
+ date: 2015-04-15 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast