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 +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
|