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 +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/parser/ast/node.rb +2 -0
- data/lib/parser/builders/default.rb +64 -30
- data/lib/parser/current.rb +2 -2
- data/lib/parser/messages.rb +1 -0
- data/lib/parser/source/comment.rb +17 -3
- data/lib/parser/source/comment/associator.rb +81 -34
- data/lib/parser/source/map.rb +19 -1
- data/lib/parser/version.rb +1 -1
- data/test/parse_helper.rb +2 -0
- data/test/test_base.rb +11 -0
- data/test/test_parser.rb +18 -2
- data/test/test_source_comment_associator.rb +108 -7
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8228d5693ac3104ea947dac416025a20f29c32e1
|
4
|
+
data.tar.gz: b078eb868955e08112f252dde8a4957bb91c5e9b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 41b75cd456f815491a2bce7b24e8fc7cd584982895c39ea8167dd46e4ceeead8e287851056099d3405c4eccab687b77934fbb2e5c7fe079f555f22244a5a306f
|
7
|
+
data.tar.gz: 3c7bbc92c7152e2bc3740a9db8524c7f3712330edc493e0d5cefdba614855cefa7a5172406d0e6192d7561f4d6b1c885fa00cb3db6e7f31612e5a967515dbdc0
|
data/CHANGELOG.md
CHANGED
@@ -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
|
|
data/lib/parser/ast/node.rb
CHANGED
@@ -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
|
712
|
-
|
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)
|
data/lib/parser/current.rb
CHANGED
data/lib/parser/messages.rb
CHANGED
@@ -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
|
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
|
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 =
|
106
|
+
@comment_num = -1
|
107
|
+
advance_comment
|
84
108
|
|
85
109
|
advance_through_directives if @skip_directives
|
86
110
|
|
87
|
-
|
111
|
+
@prev_node = nil
|
112
|
+
visit(@ast)
|
88
113
|
|
89
114
|
@mapping
|
90
115
|
end
|
91
116
|
|
92
|
-
|
117
|
+
def visit(node)
|
118
|
+
process_node(node)
|
93
119
|
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
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
|
125
|
+
process_trailing_comments(node)
|
126
|
+
@prev_node = node
|
103
127
|
end
|
128
|
+
end
|
104
129
|
|
105
|
-
|
106
|
-
|
107
|
-
|
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
|
115
|
-
@
|
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
|
153
|
+
return false if !@current_comment
|
154
|
+
comment_loc = @current_comment.location.expression
|
124
155
|
|
125
|
-
|
126
|
-
|
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
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
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
|
-
|
134
|
-
|
135
|
-
|
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
|
-
|
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
|
data/lib/parser/source/map.rb
CHANGED
@@ -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)
|
155
|
+
dup.tap(&block)
|
138
156
|
end
|
139
157
|
|
140
158
|
def update_expression(expression_l)
|
data/lib/parser/version.rb
CHANGED
data/test/parse_helper.rb
CHANGED
@@ -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
|
|
data/test/test_base.rb
CHANGED
@@ -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
|
data/test/test_parser.rb
CHANGED
@@ -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(:
|
3170
|
+
s(:begin, s(:int, 1)),
|
3171
|
+
s(:str, '(?<match>bar)'),
|
3156
3172
|
s(:regopt)),
|
3157
3173
|
:=~,
|
3158
3174
|
s(:str, 'bar')),
|
3159
|
-
%q{/#{
|
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
|
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
|
-
|
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[
|
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
|
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.
|
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-
|
11
|
+
date: 2015-04-15 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: ast
|