parser 2.2.2.3 → 2.2.2.5

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: ab4cd18ca1c0a175a8631f5b33b00d1b74a87138
4
- data.tar.gz: 84d9cd1a7216ab854b704080977bfec9dcd86023
3
+ metadata.gz: 710e70cbd335c48e5d33828e22465ed144bb89e1
4
+ data.tar.gz: f7b154226cd171fc3d7290a83636e292631c961a
5
5
  SHA512:
6
- metadata.gz: cdf15aa367699423e2b475cc9e90c90eb52e6fdbd0c8560e63ea9f3e85ed8dd0963052f2413363460dda0b2adfde1738abf059cba398983c2937f3c5860fd4ac
7
- data.tar.gz: 6be794d016744e9d7a0ffab004983bb6af6030c88ba1ccd11c31776d1108d8f45391fa2455d82fc14ca30b89d2c25951648ae3cf186111fc5397f6721978d17c
6
+ metadata.gz: f675cb69ce293a7f6787c6b08ce38d545393a7ca776a999f5c37cb607425a22aee2d2d2f24474792927e8bbc36e86125b8bcbe3c366cebb2c3fc785e2eaa5675
7
+ data.tar.gz: 02fb79c07b4473351667a166383345a235a756cea3ff7b0b718683fe5b6fab13c5f67ffc484e60f72402cf8c0b6e5130305157e1dac96a5d57353efe41d1af3c
data/CHANGELOG.md CHANGED
@@ -1,6 +1,19 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
+ v2.2.2.5 (2015-05-25)
5
+ ---------------------
6
+
7
+ API modifications:
8
+ * Source::Comment::Associator: rework entirely; fixes #194 (Oleg Zubchenko)
9
+
10
+ Features implemented:
11
+ * Source::Map: add last_line, last_column delegation (Oleg Zubchenko)
12
+ * Source::Range: add last_line, last_column methods (Oleg Zubchenko)
13
+
14
+ Bugs fixed:
15
+ * AST::Processor: add missing on_block_pass (fixes #196) (whitequark)
16
+
4
17
  v2.2.2.3 (2015-05-17)
5
18
  ---------------------
6
19
 
@@ -108,6 +108,7 @@ module Parser
108
108
  alias on_arg_expr process_regular_node
109
109
  alias on_restarg_expr process_regular_node
110
110
  alias on_blockarg_expr process_regular_node
111
+ alias on_block_pass process_regular_node
111
112
 
112
113
  alias on_module process_regular_node
113
114
  alias on_class process_regular_node
@@ -54,11 +54,12 @@ module Parser
54
54
  end
55
55
 
56
56
  ##
57
- # Compute a mapping between AST nodes and comments.
57
+ # Compute a mapping between AST nodes and comments. Comment is
58
+ # associated with the node, if it is one of the following types:
58
59
  #
59
- # A comment belongs to a certain node if it begins after end
60
- # of the previous node (if one exists) and ends before beginning of
61
- # the current node.
60
+ # - preceding comment, it ends before the node start
61
+ # - sparse comment, it is located inside the node, after all child nodes
62
+ # - decorating comment, it starts at the same line, where the node ends
62
63
  #
63
64
  # This rule is unambiguous and produces the result
64
65
  # one could reasonably expect; for example, this code
@@ -76,6 +77,9 @@ module Parser
76
77
  # [#<Parser::Source::Comment (string):3:8 "# bar">]
77
78
  # }
78
79
  #
80
+ # Note that comments after the end of the end of a passed tree range are
81
+ # ignored (except root decorating comment).
82
+ #
79
83
  # Note that {associate} produces unexpected result for nodes which are
80
84
  # equal but have distinct locations; comments for these nodes are merged.
81
85
  #
@@ -108,39 +112,35 @@ module Parser
108
112
 
109
113
  advance_through_directives if @skip_directives
110
114
 
111
- @prev_node = nil
112
- visit(@ast)
115
+ visit(@ast) if @ast
113
116
 
114
117
  @mapping
115
118
  end
116
119
 
117
120
  def visit(node)
118
- process_node(node)
119
-
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)
124
- end
125
- process_trailing_comments(node)
126
- @prev_node = node
121
+ process_leading_comments(node)
122
+
123
+ node.children.each do |child|
124
+ next unless child.is_a?(AST::Node) && child.loc && child.loc.expression
125
+ visit(child)
127
126
  end
127
+
128
+ process_trailing_comments(node)
128
129
  end
129
130
 
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)
131
+ def process_leading_comments(node)
132
+ return if node.type == :begin
133
+ while current_comment_before?(node) # preceding comment
134
+ associate_and_advance_comment(node)
134
135
  end
135
- @prev_node = node
136
136
  end
137
137
 
138
- def process_trailing_comments(parent)
139
- while current_comment_decorates?(@prev_node)
140
- associate_and_advance_comment(@prev_node, nil)
138
+ def process_trailing_comments(node)
139
+ while current_comment_before_end?(node)
140
+ associate_and_advance_comment(node) # sparse comment
141
141
  end
142
- while current_comment_before_end?(parent)
143
- associate_and_advance_comment(@prev_node, nil)
142
+ while current_comment_decorates?(node)
143
+ associate_and_advance_comment(node) # decorating comment
144
144
  end
145
145
  end
146
146
 
@@ -149,40 +149,31 @@ module Parser
149
149
  @current_comment = @comments[@comment_num]
150
150
  end
151
151
 
152
- def current_comment_between?(prev_node, next_node)
152
+ def current_comment_before?(node)
153
153
  return false if !@current_comment
154
154
  comment_loc = @current_comment.location.expression
155
155
 
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
156
+ if node
157
+ node_loc = node.location.expression
158
+ return false if comment_loc.end_pos > node_loc.begin_pos
163
159
  end
164
160
  true
165
161
  end
166
162
 
167
- def current_comment_decorates?(prev_node)
163
+ def current_comment_before_end?(node)
168
164
  return false if !@current_comment
169
- @current_comment.location.line == prev_node.location.line
165
+ comment_loc = @current_comment.location.expression
166
+ node_loc = node.location.expression
167
+ comment_loc.end_pos <= node_loc.end_pos
170
168
  end
171
169
 
172
- def current_comment_before_end?(parent)
170
+ def current_comment_decorates?(node)
173
171
  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
172
+ @current_comment.location.line == node.location.last_line
177
173
  end
178
174
 
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
175
+ def associate_and_advance_comment(node)
176
+ key = @map_using_locations ? node.location : node
186
177
  @mapping[key] << @current_comment
187
178
  advance_comment
188
179
  end
@@ -98,6 +98,8 @@ module Parser
98
98
  @expression.line
99
99
  end
100
100
 
101
+ alias_method :first_line, :line
102
+
101
103
  ##
102
104
  # A shortcut for `self.expression.column`.
103
105
  # @return [Integer]
@@ -106,6 +108,22 @@ module Parser
106
108
  @expression.column
107
109
  end
108
110
 
111
+ ##
112
+ # A shortcut for `self.expression.last_line`.
113
+ # @return [Integer]
114
+ #
115
+ def last_line
116
+ @expression.last_line
117
+ end
118
+
119
+ ##
120
+ # A shortcut for `self.expression.last_column`.
121
+ # @return [Integer]
122
+ #
123
+ def last_column
124
+ @expression.last_column
125
+ end
126
+
109
127
  ##
110
128
  # @api private
111
129
  #
@@ -75,6 +75,8 @@ module Parser
75
75
  line
76
76
  end
77
77
 
78
+ alias_method :first_line, :line
79
+
78
80
  ##
79
81
  # @return [Integer] zero-based column number of the beginning of this range.
80
82
  #
@@ -84,6 +86,24 @@ module Parser
84
86
  column
85
87
  end
86
88
 
89
+ ##
90
+ # @return [Integer] line number of the end of this range.
91
+ #
92
+ def last_line
93
+ line, _ = @source_buffer.decompose_position(@end_pos)
94
+
95
+ line
96
+ end
97
+
98
+ ##
99
+ # @return [Integer] zero-based column number of the end of this range.
100
+ #
101
+ def last_column
102
+ _, column = @source_buffer.decompose_position(@end_pos)
103
+
104
+ column
105
+ end
106
+
87
107
  ##
88
108
  # @return [::Range] a range of columns spanned by this range.
89
109
  # @raise RangeError
@@ -1,3 +1,3 @@
1
1
  module Parser
2
- VERSION = '2.2.2.3'
2
+ VERSION = '2.2.2.5'
3
3
  end
@@ -29,39 +29,56 @@ class TestSourceCommentAssociator < Minitest::Test
29
29
  ast, associations = associate(<<-END)
30
30
  #!/usr/bin/env ruby
31
31
  # coding: utf-8
32
- # Class comment
33
- # another class comment
34
- class Foo
35
- # attr_accessor comment
36
- attr_accessor :foo
37
-
38
- # method comment
32
+ # class preceeding
33
+ # another class preceeding
34
+ class Foo # class keyword line
35
+ # method foo preceeding
36
+ def foo
37
+ puts 'foo'
38
+ end # method foo decorating
39
+ # method bar preceeding
39
40
  def bar
40
- # expr comment
41
- 1 + # intermediate comment
41
+ # expression preceeding
42
+ 1 + # 1 decorating
42
43
  2
43
- # stray comment
44
- end
45
- end
44
+ # method bar sparse
45
+ end # method bar decorating
46
+ # class sparse
47
+ end # class decorating
46
48
  END
47
49
 
48
- klass_node = ast
49
- attr_accessor_node = ast.children[2].children[0]
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
53
-
54
- assert_equal 5, associations.size
55
- assert_equal ['# Class comment', '# another class comment'],
56
- associations[klass_node].map(&:text)
57
- assert_equal ['# attr_accessor comment'],
58
- associations[attr_accessor_node].map(&:text)
59
- assert_equal ['# method comment'],
60
- associations[method_node].map(&:text)
61
- assert_equal ['# expr comment', "# stray comment"],
62
- associations[expr_node].map(&:text)
63
- assert_equal ['# intermediate comment'],
64
- associations[intermediate_node].map(&:text)
50
+ klass_node = ast
51
+ klass_name_node = klass_node.children[0]
52
+ foo_node = klass_node.children[2].children[0] # def foo
53
+ bar_node = klass_node.children[2].children[1] # def bar
54
+ expr_node = bar_node.children[2] # 1 + 2
55
+ one_node = expr_node.children[0] # 1
56
+
57
+ assert_equal 6, associations.size
58
+ assert_equal [
59
+ '# class preceeding',
60
+ '# another class preceeding',
61
+ '# class sparse',
62
+ '# class decorating'
63
+ ], associations[klass_node].map(&:text)
64
+ assert_equal [
65
+ '# class keyword line'
66
+ ], associations[klass_name_node].map(&:text)
67
+ assert_equal [
68
+ '# method foo preceeding',
69
+ '# method foo decorating'
70
+ ], associations[foo_node].map(&:text)
71
+ assert_equal [
72
+ '# method bar preceeding',
73
+ '# method bar sparse',
74
+ '# method bar decorating'
75
+ ], associations[bar_node].map(&:text)
76
+ assert_equal [
77
+ '# expression preceeding'
78
+ ], associations[expr_node].map(&:text)
79
+ assert_equal [
80
+ '# 1 decorating'
81
+ ], associations[one_node].map(&:text)
65
82
  end
66
83
 
67
84
  # The bug below is fixed by using associate_locations
@@ -93,39 +110,56 @@ end
93
110
  ast, associations = associate_locations(<<-END)
94
111
  #!/usr/bin/env ruby
95
112
  # 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
113
+ # class preceeding
114
+ # another class preceeding
115
+ class Foo # class keyword line
116
+ # method foo preceeding
117
+ def foo
118
+ puts 'foo'
119
+ end # method foo decorating
120
+ # method bar preceeding
103
121
  def bar
104
- # expr comment
105
- 1 + # intermediate comment
122
+ # expression preceeding
123
+ 1 + # 1 decorating
106
124
  2
107
- # stray comment
108
- end
109
- end
125
+ # method bar sparse
126
+ end # method bar decorating
127
+ # class sparse
128
+ end # class decorating
110
129
  END
111
130
 
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)
131
+ klass_node = ast
132
+ klass_name_node = klass_node.children[0]
133
+ foo_node = klass_node.children[2].children[0] # def foo
134
+ bar_node = klass_node.children[2].children[1] # def bar
135
+ expr_node = bar_node.children[2] # 1 + 2
136
+ one_node = expr_node.children[0] # 1
137
+
138
+ assert_equal 6, associations.size
139
+ assert_equal [
140
+ '# class preceeding',
141
+ '# another class preceeding',
142
+ '# class sparse',
143
+ '# class decorating'
144
+ ], associations[klass_node.loc].map(&:text)
145
+ assert_equal [
146
+ '# class keyword line'
147
+ ], associations[klass_name_node.loc].map(&:text)
148
+ assert_equal [
149
+ '# method foo preceeding',
150
+ '# method foo decorating'
151
+ ], associations[foo_node.loc].map(&:text)
152
+ assert_equal [
153
+ '# method bar preceeding',
154
+ '# method bar sparse',
155
+ '# method bar decorating'
156
+ ], associations[bar_node.loc].map(&:text)
157
+ assert_equal [
158
+ '# expression preceeding'
159
+ ], associations[expr_node.loc].map(&:text)
160
+ assert_equal [
161
+ '# 1 decorating'
162
+ ], associations[one_node.loc].map(&:text)
129
163
  end
130
164
 
131
165
  def test_associate_locations_dupe_statement
@@ -164,6 +198,11 @@ end
164
198
  associations[ast].map(&:text)
165
199
  end
166
200
 
201
+ def test_associate_empty_tree
202
+ ast, associations = associate("")
203
+ assert_equal 0, associations.size
204
+ end
205
+
167
206
  def test_associate_shebang_only
168
207
  ast, associations = associate(<<-END)
169
208
  #!ruby
@@ -183,6 +222,17 @@ end
183
222
  assert_equal 0, associations.size
184
223
  end
185
224
 
225
+ def test_associate_comments_after_root_node
226
+ ast, associations = associate(<<-END)
227
+ class Foo
228
+ end
229
+ # not associated
230
+ END
231
+
232
+ assert_equal 0, associations.size
233
+ end
234
+
235
+
186
236
  def test_associate_stray_comment
187
237
  ast, associations = associate(<<-END)
188
238
  def foo
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.2.3
4
+ version: 2.2.2.5
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-05-17 00:00:00.000000000 Z
11
+ date: 2015-05-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast