parser 2.2.0.3 → 2.2.0.4

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