parser 2.7.0.2 → 2.7.0.3

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
  SHA256:
3
- metadata.gz: eb64651ef64daa71d4c55d8ab253c90ce470eaf85f3b0ce98dfe5f171a681c80
4
- data.tar.gz: a875a3b5c4a92b7fae3a58c379c300519e7c328641a7cb8d8a65e3f131118eed
3
+ metadata.gz: 2801cd6adbcd161d1a3b643dca79b9a9f7ff13210439bf632fcc22072837dffa
4
+ data.tar.gz: 20a0402b20903555a7cc29507205f7bf7176b26dfe039df79bf17fd503ed951e
5
5
  SHA512:
6
- metadata.gz: 8bd9f983ef31671217011a895e07b466f5327578f1dbc2288e5bcd08e367d038e0ee53c35ee1851323c8b04ab20e3fd27c1347a7615c869a99ebcebc8a949baf
7
- data.tar.gz: cab52019893fb86e6fe66aaa9391d9d6cd721daac62550f7a0d2303bafbcc6deac349c4366315f8bc4ba15f6309b7ead3f30e3ff8fcd0e15a394c63c86071db7
6
+ metadata.gz: b254886d186ac704cb8a6dcc6bfdce7d2f9f079ce83edb456646a0ec04336a2893c140f1b525e8cea89f34c52bf01c1e6849dc8ce80d9f4f3fdb0af072e15ac2
7
+ data.tar.gz: 627b678f07bf6ad130235f3ab1440d563905cf671e0618f2cb3b549e0f34dc341e70f5659580d731259d8caa97fd3d221868b966b5df5188c5c985db836ecc2a
@@ -1,8 +1,8 @@
1
1
  Changelog
2
2
  =========
3
3
 
4
- Not released (2020-01-08)
5
- -------------------------
4
+ v2.7.0.2 (2020-01-08)
5
+ ---------------------
6
6
 
7
7
  Bugs fixed:
8
8
  * lexer.rl: fix paren_nest for curly braces (#646) (Ilya Bylich)
data/README.md CHANGED
@@ -234,7 +234,7 @@ Parser implements the MacRuby 0.12 and RubyMotion mid-2015 parsers precisely. Ho
234
234
 
235
235
  ## Known issues
236
236
 
237
- Adding support for the following Ruby MRI features in Parser would needlessly complicate it, and as they all are very specific and rarely occuring corner cases, this is not done.
237
+ Adding support for the following Ruby MRI features in Parser would needlessly complicate it, and as they all are very specific and rarely occurring corner cases, this is not done.
238
238
 
239
239
  Parser has been extensively tested; in particular, it parses almost entire [Rubygems][rg] corpus. For every issue, a breakdown of affected gems is offered.
240
240
 
@@ -1870,6 +1870,27 @@ Format:
1870
1870
  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression
1871
1871
  ~~~
1872
1872
 
1873
+ #### With empty else
1874
+
1875
+ Empty `else` differs from the missing (or _implicit_) `else` for pattern matching, since
1876
+ the latter one raises a `NoMatchingPattern` exception. Thus, we need a way to distinguish this
1877
+ two cases in the resulting AST.
1878
+
1879
+ Format:
1880
+
1881
+ ~~~
1882
+ (case-match,
1883
+ (str "str")
1884
+ (in-pattern
1885
+ (match-var :foo)
1886
+ (lvar :bar))
1887
+ (empty-else))
1888
+ "case "str"; in foo; bar; else; end"
1889
+ ~~~~ keyword ~~~~ else
1890
+ ~~~ end
1891
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ expression
1892
+ ~~~
1893
+
1873
1894
  ### In clause
1874
1895
 
1875
1896
  Format:
@@ -2140,3 +2161,20 @@ Format:
2140
2161
  ~ name (const-pattern.const)
2141
2162
  ~ expression (const-pattern.const)
2142
2163
  ~~~
2164
+
2165
+ #### With array pattern without elements
2166
+
2167
+ Format:
2168
+
2169
+ ~~~
2170
+ (const-pattern
2171
+ (const nil :X)
2172
+ (array-pattern))
2173
+ "in X[]"
2174
+ ~ begin (const-pattern)
2175
+ ~ end (const-pattern)
2176
+ ~~ expression (const-pattern)
2177
+ ~ name (const-pattern.const)
2178
+ ~ expression (const-pattern.const)
2179
+ ~~ expression (const-pattern.array_pattern)
2180
+ ~~~
@@ -274,6 +274,10 @@ module Parser
274
274
  'Parser::AST::Processor#on_argument instead.'
275
275
  on_argument(node)
276
276
  end
277
+
278
+ def on_empty_else(node)
279
+ node
280
+ end
277
281
  end
278
282
  end
279
283
  end
@@ -1213,6 +1213,7 @@ module Parser
1213
1213
  #
1214
1214
 
1215
1215
  def case_match(case_t, expr, in_bodies, else_t, else_body, end_t)
1216
+ else_body = n(:empty_else, nil, token_map(else_t)) if else_t && !else_body
1216
1217
  n(:case_match, [ expr, *(in_bodies << else_body)],
1217
1218
  condition_map(case_t, expr, nil, nil, else_t, else_body, end_t))
1218
1219
  end
@@ -1313,6 +1314,8 @@ module Parser
1313
1314
  end
1314
1315
 
1315
1316
  def array_pattern(lbrack_t, elements, rbrack_t)
1317
+ return n(:array_pattern, nil, collection_map(lbrack_t, [], rbrack_t)) if elements.nil?
1318
+
1316
1319
  trailing_comma = false
1317
1320
 
1318
1321
  elements = elements.map do |element|
@@ -1369,11 +1372,13 @@ module Parser
1369
1372
  pair_keyword(label, value)
1370
1373
  else
1371
1374
  begin_t, parts, end_t = label
1375
+ label_loc = loc(begin_t).join(loc(end_t))
1372
1376
 
1373
1377
  # quoted label like "label": value
1374
1378
  if (var_name = static_string(parts))
1375
- loc = loc(begin_t).join(loc(end_t))
1376
- check_duplicate_pattern_key(var_name, loc)
1379
+ check_duplicate_pattern_key(var_name, label_loc)
1380
+ else
1381
+ diagnostic :error, :pm_interp_in_var_name, nil, label_loc
1377
1382
  end
1378
1383
 
1379
1384
  pair_quoted(begin_t, parts, end_t, value)
@@ -70,6 +70,7 @@ module Parser
70
70
  :circular_argument_reference => 'circular argument reference %{var_name}',
71
71
  :pm_interp_in_var_name => 'symbol literal with interpolation is not allowed',
72
72
  :lvar_name => "`%{name}' is not allowed as a local variable name",
73
+ :undefined_lvar => "no such local variable: `%{name}'",
73
74
  :duplicate_variable_name => 'duplicate variable name %{name}',
74
75
  :duplicate_pattern_key => 'duplicate hash pattern key %{name}',
75
76
 
@@ -31,6 +31,7 @@ module Parser
31
31
  match_var pin match_alt match_as match_rest
32
32
  array_pattern match_with_trailing_comma array_pattern_with_tail
33
33
  hash_pattern const_pattern if_guard unless_guard match_nil_pattern
34
+ empty_else
34
35
  ).map(&:to_sym).to_set.freeze
35
36
 
36
37
  end # Meta
@@ -1841,7 +1841,8 @@ opt_block_args_tail:
1841
1841
  }
1842
1842
  | p_const tLPAREN2 rparen
1843
1843
  {
1844
- result = @builder.const_pattern(val[0], val[1], nil, val[2])
1844
+ pattern = @builder.array_pattern(val[1], nil, val[2])
1845
+ result = @builder.const_pattern(val[0], val[1], pattern, val[2])
1845
1846
  }
1846
1847
  | p_const p_lbracket p_args rbracket
1847
1848
  {
@@ -1857,7 +1858,8 @@ opt_block_args_tail:
1857
1858
  }
1858
1859
  | p_const tLBRACK2 rbracket
1859
1860
  {
1860
- result = @builder.const_pattern(val[0], val[1], nil, val[2])
1861
+ pattern = @builder.array_pattern(val[1], nil, val[2])
1862
+ result = @builder.const_pattern(val[0], val[1], pattern, val[2])
1861
1863
  }
1862
1864
  | tLBRACK
1863
1865
  {
@@ -2096,6 +2098,11 @@ opt_block_args_tail:
2096
2098
 
2097
2099
  p_var_ref: tCARET tIDENTIFIER
2098
2100
  {
2101
+ name = val[1][0]
2102
+ unless static_env.declared?(name)
2103
+ diagnostic :error, :undefined_lvar, { :name => name }, val[1]
2104
+ end
2105
+
2099
2106
  lvar = @builder.accessible(@builder.ident(val[1]))
2100
2107
  result = @builder.pin(val[0], lvar)
2101
2108
  }
@@ -56,11 +56,11 @@ module Parser
56
56
  if action.range == @range
57
57
  merge(action)
58
58
  else
59
- place_in_hierachy(action)
59
+ place_in_hierarchy(action)
60
60
  end
61
61
  end
62
62
 
63
- def place_in_hierachy(action)
63
+ def place_in_hierarchy(action)
64
64
  family = @children.group_by { |child| child.relationship_with(action) }
65
65
 
66
66
  if family[:fusible]
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Parser
4
- VERSION = '2.7.0.2'
4
+ VERSION = '2.7.0.3'
5
5
  end
@@ -13,6 +13,13 @@ Gem::Specification.new do |spec|
13
13
  spec.homepage = 'https://github.com/whitequark/parser'
14
14
  spec.license = 'MIT'
15
15
 
16
+ spec.metadata = {
17
+ 'bug_tracker_uri' => 'https://github.com/whitequark/parser/issues',
18
+ 'changelog_uri' => "https://github.com/whitequark/parser/blob/v#{spec.version}/CHANGELOG.md",
19
+ 'documentation_uri' => "https://www.rubydoc.info/gems/parser/#{spec.version}",
20
+ 'source_code_uri' => "https://github.com/whitequark/parser/tree/v#{spec.version}"
21
+ }
22
+
16
23
  spec.files = `git ls-files`.split + %w(
17
24
  lib/parser/lexer.rb
18
25
  lib/parser/ruby18.rb
@@ -8839,6 +8839,15 @@ class TestParser < Minitest::Test
8839
8839
  )
8840
8840
  end
8841
8841
 
8842
+ def test_pattern_matching_hash_with_string_interpolation_keys
8843
+ assert_diagnoses(
8844
+ [:error, :pm_interp_in_var_name],
8845
+ %q{case a; in "#{a}": 1; end},
8846
+ %q{ ~~~~~~~ location},
8847
+ SINCE_2_7
8848
+ )
8849
+ end
8850
+
8842
8851
  def test_pattern_matching_keyword_variable
8843
8852
  assert_parses_pattern_match(
8844
8853
  s(:in_pattern,
@@ -8997,13 +9006,15 @@ class TestParser < Minitest::Test
8997
9006
  s(:in_pattern,
8998
9007
  s(:const_pattern,
8999
9008
  s(:const, nil, :A),
9000
- nil),
9009
+ s(:array_pattern)),
9001
9010
  nil,
9002
9011
  s(:true)),
9003
9012
  %q{in A() then true},
9004
9013
  %q{ ~~ expression (in_pattern.const_pattern)
9005
9014
  | ~ begin (in_pattern.const_pattern)
9006
- | ~ end (in_pattern.const_pattern)}
9015
+ | ~ end (in_pattern.const_pattern)
9016
+ | ~ expression (in_pattern.const_pattern.const)
9017
+ | ~~ expression (in_pattern.const_pattern.array_pattern)}
9007
9018
  )
9008
9019
 
9009
9020
  assert_parses_pattern_match(
@@ -9043,13 +9054,14 @@ class TestParser < Minitest::Test
9043
9054
  s(:in_pattern,
9044
9055
  s(:const_pattern,
9045
9056
  s(:const, nil, :A),
9046
- nil),
9057
+ s(:array_pattern)),
9047
9058
  nil,
9048
9059
  s(:true)),
9049
9060
  %q{in A[] then true},
9050
9061
  %q{ ~~ expression (in_pattern.const_pattern)
9051
9062
  | ~ begin (in_pattern.const_pattern)
9052
- | ~ end (in_pattern.const_pattern)}
9063
+ | ~ end (in_pattern.const_pattern)
9064
+ | ~~ expression (in_pattern.const_pattern.array_pattern)}
9053
9065
  )
9054
9066
  end
9055
9067
 
@@ -9093,6 +9105,20 @@ class TestParser < Minitest::Test
9093
9105
  )
9094
9106
  end
9095
9107
 
9108
+ def test_pattern_matching_blank_else
9109
+ assert_parses(
9110
+ s(:case_match,
9111
+ s(:int, 1),
9112
+ s(:in_pattern,
9113
+ s(:int, 2), nil,
9114
+ s(:int, 3)),
9115
+ s(:empty_else)),
9116
+ %q{case 1; in 2; 3; else; end},
9117
+ %q{ ~~~~ else},
9118
+ SINCE_2_7
9119
+ )
9120
+ end
9121
+
9096
9122
  def assert_pattern_matching_defines_local_variables(match_code, lvar_names, versions = SINCE_2_7)
9097
9123
  code = "case 1; #{match_code}; then [#{lvar_names.join(', ')}]; end"
9098
9124
 
@@ -9295,6 +9321,14 @@ class TestParser < Minitest::Test
9295
9321
  SINCE_2_7)
9296
9322
  end
9297
9323
 
9324
+ def test_pattern_matching_required_bound_variable_before_pin
9325
+ assert_diagnoses(
9326
+ [:error, :undefined_lvar, { :name => 'a' }],
9327
+ %{case 0; in ^a; true; end},
9328
+ %{ ^ location},
9329
+ SINCE_2_7)
9330
+ end
9331
+
9298
9332
  def test_parser_bug_645
9299
9333
  assert_parses(
9300
9334
  s(:block,
@@ -31,16 +31,16 @@ class TestSourceCommentAssociator < Minitest::Test
31
31
  ast, associations = associate(<<-END)
32
32
  #!/usr/bin/env ruby
33
33
  # coding: utf-8
34
- # class preceeding
35
- # another class preceeding
34
+ # class preceding
35
+ # another class preceding
36
36
  class Foo # class keyword line
37
- # method foo preceeding
37
+ # method foo preceding
38
38
  def foo
39
39
  puts 'foo'
40
40
  end # method foo decorating
41
- # method bar preceeding
41
+ # method bar preceding
42
42
  def bar
43
- # expression preceeding
43
+ # expression preceding
44
44
  1 + # 1 decorating
45
45
  2
46
46
  # method bar sparse
@@ -58,8 +58,8 @@ end # class decorating
58
58
 
59
59
  assert_equal 6, associations.size
60
60
  assert_equal [
61
- '# class preceeding',
62
- '# another class preceeding',
61
+ '# class preceding',
62
+ '# another class preceding',
63
63
  '# class sparse',
64
64
  '# class decorating'
65
65
  ], associations[klass_node].map(&:text)
@@ -67,16 +67,16 @@ end # class decorating
67
67
  '# class keyword line'
68
68
  ], associations[klass_name_node].map(&:text)
69
69
  assert_equal [
70
- '# method foo preceeding',
70
+ '# method foo preceding',
71
71
  '# method foo decorating'
72
72
  ], associations[foo_node].map(&:text)
73
73
  assert_equal [
74
- '# method bar preceeding',
74
+ '# method bar preceding',
75
75
  '# method bar sparse',
76
76
  '# method bar decorating'
77
77
  ], associations[bar_node].map(&:text)
78
78
  assert_equal [
79
- '# expression preceeding'
79
+ '# expression preceding'
80
80
  ], associations[expr_node].map(&:text)
81
81
  assert_equal [
82
82
  '# 1 decorating'
@@ -112,16 +112,16 @@ end
112
112
  ast, associations = associate_locations(<<-END)
113
113
  #!/usr/bin/env ruby
114
114
  # coding: utf-8
115
- # class preceeding
116
- # another class preceeding
115
+ # class preceding
116
+ # another class preceding
117
117
  class Foo # class keyword line
118
- # method foo preceeding
118
+ # method foo preceding
119
119
  def foo
120
120
  puts 'foo'
121
121
  end # method foo decorating
122
- # method bar preceeding
122
+ # method bar preceding
123
123
  def bar
124
- # expression preceeding
124
+ # expression preceding
125
125
  1 + # 1 decorating
126
126
  2
127
127
  # method bar sparse
@@ -139,8 +139,8 @@ end # class decorating
139
139
 
140
140
  assert_equal 6, associations.size
141
141
  assert_equal [
142
- '# class preceeding',
143
- '# another class preceeding',
142
+ '# class preceding',
143
+ '# another class preceding',
144
144
  '# class sparse',
145
145
  '# class decorating'
146
146
  ], associations[klass_node.loc].map(&:text)
@@ -148,16 +148,16 @@ end # class decorating
148
148
  '# class keyword line'
149
149
  ], associations[klass_name_node.loc].map(&:text)
150
150
  assert_equal [
151
- '# method foo preceeding',
151
+ '# method foo preceding',
152
152
  '# method foo decorating'
153
153
  ], associations[foo_node.loc].map(&:text)
154
154
  assert_equal [
155
- '# method bar preceeding',
155
+ '# method bar preceding',
156
156
  '# method bar sparse',
157
157
  '# method bar decorating'
158
158
  ], associations[bar_node.loc].map(&:text)
159
159
  assert_equal [
160
- '# expression preceeding'
160
+ '# expression preceding'
161
161
  ], associations[expr_node.loc].map(&:text)
162
162
  assert_equal [
163
163
  '# 1 decorating'
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.7.0.2
4
+ version: 2.7.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - whitequark
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-01-08 00:00:00.000000000 Z
11
+ date: 2020-02-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: ast
@@ -295,7 +295,11 @@ files:
295
295
  homepage: https://github.com/whitequark/parser
296
296
  licenses:
297
297
  - MIT
298
- metadata: {}
298
+ metadata:
299
+ bug_tracker_uri: https://github.com/whitequark/parser/issues
300
+ changelog_uri: https://github.com/whitequark/parser/blob/v2.7.0.3/CHANGELOG.md
301
+ documentation_uri: https://www.rubydoc.info/gems/parser/2.7.0.3
302
+ source_code_uri: https://github.com/whitequark/parser/tree/v2.7.0.3
299
303
  post_install_message:
300
304
  rdoc_options: []
301
305
  require_paths: