parser 2.4.0.2 → 2.5.0.0

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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/.travis.yml +5 -6
  3. data/CHANGELOG.md +35 -1
  4. data/Gemfile +2 -0
  5. data/README.md +1 -2
  6. data/Rakefile +2 -1
  7. data/bin/ruby-parse +2 -1
  8. data/bin/ruby-rewrite +2 -1
  9. data/lib/gauntlet_parser.rb +2 -0
  10. data/lib/parser.rb +16 -17
  11. data/lib/parser/all.rb +2 -0
  12. data/lib/parser/ast/node.rb +2 -0
  13. data/lib/parser/ast/processor.rb +2 -0
  14. data/lib/parser/base.rb +6 -12
  15. data/lib/parser/builders/default.rb +28 -47
  16. data/lib/parser/clobbering_error.rb +2 -0
  17. data/lib/parser/context.rb +42 -0
  18. data/lib/parser/current.rb +4 -20
  19. data/lib/parser/deprecation.rb +13 -0
  20. data/lib/parser/diagnostic.rb +3 -3
  21. data/lib/parser/diagnostic/engine.rb +2 -0
  22. data/lib/parser/lexer.rl +122 -60
  23. data/lib/parser/lexer/dedenter.rb +2 -0
  24. data/lib/parser/lexer/explanation.rb +2 -0
  25. data/lib/parser/lexer/literal.rb +4 -9
  26. data/lib/parser/lexer/stack_state.rb +4 -1
  27. data/lib/parser/macruby.y +32 -17
  28. data/lib/parser/messages.rb +14 -0
  29. data/lib/parser/meta.rb +2 -0
  30. data/lib/parser/rewriter.rb +30 -44
  31. data/lib/parser/ruby18.y +20 -13
  32. data/lib/parser/ruby19.y +32 -17
  33. data/lib/parser/ruby20.y +33 -18
  34. data/lib/parser/ruby21.y +32 -17
  35. data/lib/parser/ruby22.y +32 -17
  36. data/lib/parser/ruby23.y +32 -17
  37. data/lib/parser/ruby24.y +63 -46
  38. data/lib/parser/ruby25.y +72 -48
  39. data/lib/parser/rubymotion.y +33 -18
  40. data/lib/parser/runner.rb +4 -7
  41. data/lib/parser/runner/ruby_parse.rb +10 -0
  42. data/lib/parser/runner/ruby_rewrite.rb +2 -0
  43. data/lib/parser/source/buffer.rb +19 -24
  44. data/lib/parser/source/comment.rb +2 -0
  45. data/lib/parser/source/comment/associator.rb +2 -0
  46. data/lib/parser/source/map.rb +2 -0
  47. data/lib/parser/source/map/collection.rb +2 -0
  48. data/lib/parser/source/map/condition.rb +2 -0
  49. data/lib/parser/source/map/constant.rb +2 -0
  50. data/lib/parser/source/map/definition.rb +2 -0
  51. data/lib/parser/source/map/for.rb +2 -0
  52. data/lib/parser/source/map/heredoc.rb +2 -0
  53. data/lib/parser/source/map/keyword.rb +2 -0
  54. data/lib/parser/source/map/objc_kwarg.rb +2 -0
  55. data/lib/parser/source/map/operator.rb +2 -0
  56. data/lib/parser/source/map/rescue_body.rb +2 -0
  57. data/lib/parser/source/map/send.rb +2 -0
  58. data/lib/parser/source/map/ternary.rb +2 -0
  59. data/lib/parser/source/map/variable.rb +2 -0
  60. data/lib/parser/source/range.rb +81 -13
  61. data/lib/parser/source/rewriter.rb +48 -10
  62. data/lib/parser/source/rewriter/action.rb +2 -0
  63. data/lib/parser/source/tree_rewriter.rb +301 -0
  64. data/lib/parser/source/tree_rewriter/action.rb +133 -0
  65. data/lib/parser/static_environment.rb +2 -0
  66. data/lib/parser/syntax_error.rb +2 -0
  67. data/lib/parser/tree_rewriter.rb +133 -0
  68. data/lib/parser/version.rb +3 -1
  69. data/parser.gemspec +4 -1
  70. data/test/bug_163/fixtures/input.rb +2 -0
  71. data/test/bug_163/fixtures/output.rb +2 -0
  72. data/test/bug_163/rewriter.rb +2 -0
  73. data/test/helper.rb +7 -7
  74. data/test/parse_helper.rb +57 -10
  75. data/test/racc_coverage_helper.rb +2 -0
  76. data/test/test_base.rb +2 -0
  77. data/test/test_current.rb +2 -4
  78. data/test/test_diagnostic.rb +3 -1
  79. data/test/test_diagnostic_engine.rb +2 -0
  80. data/test/test_encoding.rb +61 -49
  81. data/test/test_lexer.rb +164 -77
  82. data/test/test_lexer_stack_state.rb +2 -0
  83. data/test/test_parse_helper.rb +8 -8
  84. data/test/test_parser.rb +613 -51
  85. data/test/test_runner_rewrite.rb +47 -0
  86. data/test/test_source_buffer.rb +22 -10
  87. data/test/test_source_comment.rb +2 -0
  88. data/test/test_source_comment_associator.rb +2 -0
  89. data/test/test_source_map.rb +2 -0
  90. data/test/test_source_range.rb +92 -45
  91. data/test/test_source_rewriter.rb +3 -1
  92. data/test/test_source_rewriter_action.rb +2 -0
  93. data/test/test_source_tree_rewriter.rb +177 -0
  94. data/test/test_static_environment.rb +2 -0
  95. data/test/using_tree_rewriter/fixtures/input.rb +3 -0
  96. data/test/using_tree_rewriter/fixtures/output.rb +3 -0
  97. data/test/using_tree_rewriter/using_tree_rewriter.rb +9 -0
  98. metadata +21 -10
  99. data/lib/parser/compatibility/ruby1_8.rb +0 -20
  100. data/lib/parser/compatibility/ruby1_9.rb +0 -32
  101. data/test/bug_163/test_runner_rewrite.rb +0 -35
@@ -274,12 +274,14 @@ rule
274
274
  cmd_brace_block: tLBRACE_ARG
275
275
  {
276
276
  @static_env.extend_dynamic
277
+ @context.push(:block)
277
278
  }
278
279
  opt_block_param compstmt tRCURLY
279
280
  {
280
281
  result = [ val[0], val[2], val[3], val[4] ]
281
282
 
282
283
  @static_env.unextend
284
+ @context.pop
283
285
  }
284
286
 
285
287
  command: operation command_args =tLOWEST
@@ -1122,10 +1124,11 @@ rule
1122
1124
  {
1123
1125
  @static_env.extend_static
1124
1126
  @lexer.push_cmdarg
1127
+ @context.push(:class)
1125
1128
  }
1126
1129
  bodystmt kEND
1127
1130
  {
1128
- if in_def?
1131
+ if @context.indirectly_in_def?
1129
1132
  diagnostic :error, :class_in_def, nil, val[0]
1130
1133
  end
1131
1134
 
@@ -1136,14 +1139,13 @@ rule
1136
1139
 
1137
1140
  @lexer.pop_cmdarg
1138
1141
  @static_env.unextend
1142
+ @context.pop
1139
1143
  }
1140
1144
  | kCLASS tLSHFT expr term
1141
1145
  {
1142
- result = @def_level
1143
- @def_level = 0
1144
-
1145
1146
  @static_env.extend_static
1146
1147
  @lexer.push_cmdarg
1148
+ @context.push(:sclass)
1147
1149
  }
1148
1150
  bodystmt kEND
1149
1151
  {
@@ -1152,8 +1154,7 @@ rule
1152
1154
 
1153
1155
  @lexer.pop_cmdarg
1154
1156
  @static_env.unextend
1155
-
1156
- @def_level = val[4]
1157
+ @context.pop
1157
1158
  }
1158
1159
  | kMODULE cpath
1159
1160
  {
@@ -1162,7 +1163,7 @@ rule
1162
1163
  }
1163
1164
  bodystmt kEND
1164
1165
  {
1165
- if in_def?
1166
+ if @context.indirectly_in_def?
1166
1167
  diagnostic :error, :module_in_def, nil, val[0]
1167
1168
  end
1168
1169
 
@@ -1174,9 +1175,9 @@ rule
1174
1175
  }
1175
1176
  | kDEF fname
1176
1177
  {
1177
- @def_level += 1
1178
1178
  @static_env.extend_static
1179
1179
  @lexer.push_cmdarg
1180
+ @context.push(:def)
1180
1181
  }
1181
1182
  f_arglist bodystmt kEND
1182
1183
  {
@@ -1185,7 +1186,7 @@ rule
1185
1186
 
1186
1187
  @lexer.pop_cmdarg
1187
1188
  @static_env.unextend
1188
- @def_level -= 1
1189
+ @context.pop
1189
1190
  }
1190
1191
  | kDEF singleton dot_or_colon
1191
1192
  {
@@ -1193,9 +1194,9 @@ rule
1193
1194
  }
1194
1195
  fname
1195
1196
  {
1196
- @def_level += 1
1197
1197
  @static_env.extend_static
1198
1198
  @lexer.push_cmdarg
1199
+ @context.push(:defs)
1199
1200
  }
1200
1201
  f_arglist bodystmt kEND
1201
1202
  {
@@ -1204,7 +1205,7 @@ rule
1204
1205
 
1205
1206
  @lexer.pop_cmdarg
1206
1207
  @static_env.unextend
1207
- @def_level -= 1
1208
+ @context.pop
1208
1209
  }
1209
1210
  | kBREAK
1210
1211
  {
@@ -1468,24 +1469,36 @@ rule
1468
1469
  result = @builder.args(nil, val[0], nil)
1469
1470
  }
1470
1471
 
1471
- lambda_body: tLAMBEG compstmt tRCURLY
1472
+ lambda_body: tLAMBEG
1473
+ {
1474
+ @context.push(:lambda)
1475
+ }
1476
+ compstmt tRCURLY
1472
1477
  {
1473
- result = [ val[0], val[1], val[2] ]
1478
+ result = [ val[0], val[2], val[3] ]
1479
+ @context.pop
1474
1480
  }
1475
- | kDO_LAMBDA compstmt kEND
1481
+ | kDO_LAMBDA
1476
1482
  {
1477
- result = [ val[0], val[1], val[2] ]
1483
+ @context.push(:lambda)
1484
+ }
1485
+ compstmt kEND
1486
+ {
1487
+ result = [ val[0], val[2], val[3] ]
1488
+ @context.pop
1478
1489
  }
1479
1490
 
1480
1491
  do_block: kDO_BLOCK
1481
1492
  {
1482
1493
  @static_env.extend_dynamic
1494
+ @context.push(:block)
1483
1495
  }
1484
1496
  opt_block_param compstmt kEND
1485
1497
  {
1486
1498
  result = [ val[0], val[2], val[3], val[4] ]
1487
1499
 
1488
1500
  @static_env.unextend
1501
+ @context.pop
1489
1502
  }
1490
1503
 
1491
1504
  block_call: command do_block
@@ -1559,22 +1572,26 @@ rule
1559
1572
  brace_block: tLCURLY
1560
1573
  {
1561
1574
  @static_env.extend_dynamic
1575
+ @context.push(:block)
1562
1576
  }
1563
1577
  opt_block_param compstmt tRCURLY
1564
1578
  {
1565
1579
  result = [ val[0], val[2], val[3], val[4] ]
1566
1580
 
1567
1581
  @static_env.unextend
1582
+ @context.pop
1568
1583
  }
1569
1584
  | kDO
1570
1585
  {
1571
1586
  @static_env.extend_dynamic
1587
+ @context.push(:block)
1572
1588
  }
1573
1589
  opt_block_param compstmt kEND
1574
1590
  {
1575
1591
  result = [ val[0], val[2], val[3], val[4] ]
1576
1592
 
1577
1593
  @static_env.unextend
1594
+ @context.pop
1578
1595
  }
1579
1596
 
1580
1597
  case_body: kWHEN args then compstmt cases
@@ -2170,8 +2187,6 @@ end
2170
2187
 
2171
2188
  require 'parser'
2172
2189
 
2173
- Parser.check_for_encoding_support
2174
-
2175
2190
  ---- inner
2176
2191
 
2177
2192
  def version
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  ##
3
5
  # Diagnostic messages (errors, warnings and notices) that can be generated.
@@ -26,6 +28,8 @@ module Parser
26
28
  :bare_backslash => 'bare backslash only allowed before newline',
27
29
  :unexpected => "unexpected `%{character}'",
28
30
  :embedded_document => 'embedded document meets end of file (and they embark on a romantic journey)',
31
+ :heredoc_id_has_newline => 'here document identifier across newlines, never match',
32
+ :heredoc_id_ends_with_nl => 'here document identifier ends with a newline',
29
33
 
30
34
  # Lexer warnings
31
35
  :invalid_escape_use => 'invalid character syntax; use ?%{escape}',
@@ -56,6 +60,7 @@ module Parser
56
60
  :masgn_as_condition => 'multiple assignment in conditional context',
57
61
  :block_given_to_yield => 'block given to yield',
58
62
  :invalid_regexp => '%{message}',
63
+ :invalid_return => 'Invalid return in class/module body',
59
64
 
60
65
  # Parser warnings
61
66
  :useless_else => 'else without rescue is useless',
@@ -66,5 +71,14 @@ module Parser
66
71
  # Rewriter diagnostics
67
72
  :invalid_action => 'cannot %{action}',
68
73
  :clobbered => 'clobbered by: %{action}',
74
+
75
+ # Rewriter diagnostics
76
+ :different_replacements => 'different replacements: %{replacement} vs %{other_replacement}',
77
+ :swallowed_insertions => 'this replacement:',
78
+ :swallowed_insertions_conflict => 'swallows some inner rewriting actions:',
79
+ :crossing_deletions => 'the deletion of:',
80
+ :crossing_deletions_conflict => 'is crossing:',
81
+ :crossing_insertions => 'the rewriting action on:',
82
+ :crossing_insertions_conflict => 'is crossing that on:',
69
83
  }.freeze
70
84
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
  # Parser metadata
3
5
  module Meta
@@ -1,52 +1,15 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module Parser
2
4
 
3
5
  ##
4
- # {Parser::Rewriter} offers a basic API that makes it easy to rewrite
5
- # existing ASTs. It's built on top of {Parser::AST::Processor} and
6
- # {Parser::Source::Rewriter}.
7
- #
8
- # For example, assume you want to remove `do` tokens from a while statement.
9
- # You can do this as following:
10
- #
11
- # require 'parser/current'
12
- #
13
- # class RemoveDo < Parser::Rewriter
14
- # def on_while(node)
15
- # # Check if the statement starts with "do"
16
- # if node.location.begin.is?('do')
17
- # remove(node.location.begin)
18
- # end
19
- # end
20
- # end
21
- #
22
- # code = <<-EOF
23
- # while true do
24
- # puts 'hello'
25
- # end
26
- # EOF
27
- #
28
- # buffer = Parser::Source::Buffer.new('(example)')
29
- # buffer.source = code
30
- # parser = Parser::CurrentRuby.new
31
- # ast = parser.parse(buffer)
32
- # rewriter = RemoveDo.new
33
- #
34
- # # Rewrite the AST, returns a String with the new form.
35
- # puts rewriter.rewrite(buffer, ast)
36
- #
37
- # This would result in the following Ruby code:
38
- #
39
- # while true
40
- # puts 'hello'
41
- # end
42
- #
43
- # Keep in mind that {Parser::Rewriter} does not take care of indentation when
44
- # inserting/replacing code so you'll have to do this yourself.
45
- #
46
- # See also [a blog entry](http://whitequark.org/blog/2013/04/26/lets-play-with-ruby-code/)
47
- # describing rewriters in greater detail.
6
+ # {Parser::Rewriter} is deprecated. Use {Parser::TreeRewriter} instead.
7
+ # It has a backwards compatible API and uses {Parser::Source::TreeRewriter}
8
+ # instead of {Parser::Source::Rewriter}.
9
+ # Please check the documentation for {Parser::Source::Rewriter} for details.
48
10
  #
49
11
  # @api public
12
+ # @deprecated Use {Parser::TreeRewriter}
50
13
  #
51
14
  class Rewriter < Parser::AST::Processor
52
15
  ##
@@ -85,6 +48,16 @@ module Parser
85
48
  @source_rewriter.remove(range)
86
49
  end
87
50
 
51
+ ##
52
+ # Wraps the given source range with the given values.
53
+ #
54
+ # @param [Parser::Source::Range] range
55
+ # @param [String] content
56
+ #
57
+ def wrap(range, before, after)
58
+ @source_rewriter.wrap(range, before, after)
59
+ end
60
+
88
61
  ##
89
62
  # Inserts new code before the given source range.
90
63
  #
@@ -114,6 +87,19 @@ module Parser
114
87
  def replace(range, content)
115
88
  @source_rewriter.replace(range, content)
116
89
  end
90
+
91
+ DEPRECATION_WARNING = [
92
+ 'Parser::Rewriter is deprecated.',
93
+ 'Please update your code to use Parser::TreeRewriter instead'
94
+ ].join("\n").freeze
95
+
96
+ extend Deprecation
97
+
98
+ def initialize(*)
99
+ self.class.warn_of_deprecation
100
+ Source::Rewriter.warned_of_deprecation = true
101
+ super
102
+ end
117
103
  end
118
104
 
119
105
  end
@@ -142,7 +142,7 @@ rule
142
142
  }
143
143
  | klBEGIN tLCURLY compstmt tRCURLY
144
144
  {
145
- if in_def?
145
+ if @context.indirectly_in_def?
146
146
  diagnostic :error, :begin_in_method, nil, val[0]
147
147
  end
148
148
 
@@ -268,12 +268,14 @@ rule
268
268
  cmd_brace_block: tLBRACE_ARG
269
269
  {
270
270
  @static_env.extend_dynamic
271
+ @context.push(:block)
271
272
  }
272
273
  opt_block_var compstmt tRCURLY
273
274
  {
274
275
  result = [ val[0], val[2], val[3], val[4] ]
275
276
 
276
277
  @static_env.unextend
278
+ @context.pop
277
279
  }
278
280
 
279
281
  command: operation command_args =tLOWEST
@@ -1122,10 +1124,11 @@ rule
1122
1124
  | kCLASS cpath superclass
1123
1125
  {
1124
1126
  @static_env.extend_static
1127
+ @context.push(:class)
1125
1128
  }
1126
1129
  bodystmt kEND
1127
1130
  {
1128
- if in_def?
1131
+ if @context.indirectly_in_def?
1129
1132
  diagnostic :error, :class_in_def, nil, val[0]
1130
1133
  end
1131
1134
 
@@ -1135,13 +1138,12 @@ rule
1135
1138
  val[4], val[5])
1136
1139
 
1137
1140
  @static_env.unextend
1141
+ @context.pop
1138
1142
  }
1139
1143
  | kCLASS tLSHFT expr term
1140
1144
  {
1141
- result = @def_level
1142
- @def_level = 0
1143
-
1144
1145
  @static_env.extend_static
1146
+ @context.push(:sclass)
1145
1147
  }
1146
1148
  bodystmt kEND
1147
1149
  {
@@ -1149,8 +1151,7 @@ rule
1149
1151
  val[5], val[6])
1150
1152
 
1151
1153
  @static_env.unextend
1152
-
1153
- @def_level = val[4]
1154
+ @context.pop
1154
1155
  }
1155
1156
  | kMODULE cpath
1156
1157
  {
@@ -1158,7 +1159,7 @@ rule
1158
1159
  }
1159
1160
  bodystmt kEND
1160
1161
  {
1161
- if in_def?
1162
+ if @context.indirectly_in_def?
1162
1163
  diagnostic :error, :module_in_def, nil, val[0]
1163
1164
  end
1164
1165
 
@@ -1169,8 +1170,8 @@ rule
1169
1170
  }
1170
1171
  | kDEF fname
1171
1172
  {
1172
- @def_level += 1
1173
1173
  @static_env.extend_static
1174
+ @context.push(:def)
1174
1175
  }
1175
1176
  f_arglist bodystmt kEND
1176
1177
  {
@@ -1178,7 +1179,7 @@ rule
1178
1179
  val[3], val[4], val[5])
1179
1180
 
1180
1181
  @static_env.unextend
1181
- @def_level -= 1
1182
+ @context.pop
1182
1183
  }
1183
1184
  | kDEF singleton dot_or_colon
1184
1185
  {
@@ -1186,8 +1187,8 @@ rule
1186
1187
  }
1187
1188
  fname
1188
1189
  {
1189
- @def_level += 1
1190
1190
  @static_env.extend_static
1191
+ @context.push(:defs)
1191
1192
  }
1192
1193
  f_arglist bodystmt kEND
1193
1194
  {
@@ -1195,7 +1196,7 @@ rule
1195
1196
  val[4], val[6], val[7], val[8])
1196
1197
 
1197
1198
  @static_env.unextend
1198
- @def_level -= 1
1199
+ @context.pop
1199
1200
  }
1200
1201
  | kBREAK
1201
1202
  {
@@ -1330,12 +1331,14 @@ rule
1330
1331
  do_block: kDO_BLOCK
1331
1332
  {
1332
1333
  @static_env.extend_dynamic
1334
+ @context.push(:block)
1333
1335
  }
1334
1336
  opt_block_var compstmt kEND
1335
1337
  {
1336
1338
  result = [ val[0], val[2], val[3], val[4] ]
1337
1339
 
1338
1340
  @static_env.unextend
1341
+ @context.pop
1339
1342
  }
1340
1343
 
1341
1344
  block_call: command do_block
@@ -1393,22 +1396,26 @@ rule
1393
1396
  brace_block: tLCURLY
1394
1397
  {
1395
1398
  @static_env.extend_dynamic
1399
+ @context.push(:block)
1396
1400
  }
1397
1401
  opt_block_var compstmt tRCURLY
1398
1402
  {
1399
1403
  result = [ val[0], val[2], val[3], val[4] ]
1400
1404
 
1401
1405
  @static_env.unextend
1406
+ @context.pop
1402
1407
  }
1403
1408
  | kDO
1404
1409
  {
1405
1410
  @static_env.extend_dynamic
1411
+ @context.push(:block)
1406
1412
  }
1407
1413
  opt_block_var compstmt kEND
1408
1414
  {
1409
1415
  result = [ val[0], val[2], val[3], val[4] ]
1410
1416
 
1411
1417
  @static_env.unextend
1418
+ @context.pop
1412
1419
  }
1413
1420
 
1414
1421
  case_body: kWHEN when_args then compstmt cases
@@ -1923,5 +1930,5 @@ require 'parser'
1923
1930
  end
1924
1931
 
1925
1932
  def default_encoding
1926
- Encoding::BINARY if defined? Encoding
1933
+ Encoding::BINARY
1927
1934
  end