prism 1.5.1 → 1.7.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 (60) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +44 -1
  3. data/Makefile +5 -4
  4. data/README.md +2 -1
  5. data/config.yml +30 -4
  6. data/docs/build_system.md +2 -2
  7. data/docs/cruby_compilation.md +1 -1
  8. data/docs/design.md +2 -2
  9. data/docs/parser_translation.md +1 -1
  10. data/docs/releasing.md +6 -25
  11. data/ext/prism/api_node.c +7 -3
  12. data/ext/prism/extconf.rb +1 -1
  13. data/ext/prism/extension.c +10 -2
  14. data/ext/prism/extension.h +1 -1
  15. data/include/prism/ast.h +85 -21
  16. data/include/prism/diagnostic.h +3 -0
  17. data/include/prism/options.h +8 -2
  18. data/include/prism/parser.h +3 -0
  19. data/include/prism/version.h +3 -3
  20. data/include/prism.h +1 -1
  21. data/lib/prism/dot_visitor.rb +5 -0
  22. data/lib/prism/dsl.rb +2 -2
  23. data/lib/prism/ffi.rb +11 -3
  24. data/lib/prism/inspect_visitor.rb +1 -0
  25. data/lib/prism/node.rb +53 -14
  26. data/lib/prism/parse_result.rb +2 -15
  27. data/lib/prism/polyfill/scan_byte.rb +1 -1
  28. data/lib/prism/polyfill/warn.rb +16 -22
  29. data/lib/prism/reflection.rb +1 -1
  30. data/lib/prism/serialize.rb +8 -5
  31. data/lib/prism/translation/parser/compiler.rb +16 -16
  32. data/lib/prism/translation/parser.rb +12 -3
  33. data/lib/prism/translation/parser35.rb +1 -6
  34. data/lib/prism/translation/parser40.rb +13 -0
  35. data/lib/prism/translation/parser41.rb +13 -0
  36. data/lib/prism/translation/parser_current.rb +4 -2
  37. data/lib/prism/translation/ripper.rb +2 -2
  38. data/lib/prism/translation/ruby_parser.rb +54 -19
  39. data/lib/prism/translation.rb +2 -0
  40. data/lib/prism.rb +20 -0
  41. data/prism.gemspec +5 -1
  42. data/rbi/prism/dsl.rbi +3 -3
  43. data/rbi/prism/node.rbi +21 -8
  44. data/rbi/prism/translation/parser35.rbi +0 -2
  45. data/rbi/prism/translation/parser40.rbi +6 -0
  46. data/rbi/prism/translation/parser41.rbi +6 -0
  47. data/sig/prism/dsl.rbs +2 -2
  48. data/sig/prism/node.rbs +18 -8
  49. data/sig/prism.rbs +4 -0
  50. data/src/diagnostic.c +7 -1
  51. data/src/encoding.c +172 -67
  52. data/src/node.c +9 -0
  53. data/src/options.c +17 -7
  54. data/src/prettyprint.c +16 -0
  55. data/src/prism.c +1287 -1931
  56. data/src/serialize.c +7 -1
  57. data/src/token_type.c +2 -2
  58. data/src/util/pm_constant_pool.c +1 -1
  59. data/src/util/pm_string.c +6 -8
  60. metadata +7 -3
@@ -7,17 +7,14 @@ if (method = Kernel.instance_method(:warn)).respond_to?(:parameters) ? method.pa
7
7
  Kernel.prepend(
8
8
  Module.new {
9
9
  def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
10
- uplevel =
11
- case uplevel
12
- when nil
13
- 1
14
- when Integer
15
- uplevel + 1
16
- else
17
- uplevel.to_int + 1
18
- end
19
-
20
- super(*msgs, uplevel: uplevel)
10
+ case uplevel
11
+ when nil
12
+ super(*msgs)
13
+ when Integer
14
+ super(*msgs, uplevel: uplevel + 1)
15
+ else
16
+ super(*msgs, uplevel: uplevel.to_int + 1)
17
+ end
21
18
  end
22
19
  }
23
20
  )
@@ -25,17 +22,14 @@ if (method = Kernel.instance_method(:warn)).respond_to?(:parameters) ? method.pa
25
22
  Object.prepend(
26
23
  Module.new {
27
24
  def warn(*msgs, uplevel: nil, category: nil) # :nodoc:
28
- uplevel =
29
- case uplevel
30
- when nil
31
- 1
32
- when Integer
33
- uplevel + 1
34
- else
35
- uplevel.to_int + 1
36
- end
37
-
38
- super(*msgs, uplevel: uplevel)
25
+ case uplevel
26
+ when nil
27
+ super(*msgs)
28
+ when Integer
29
+ super(*msgs, uplevel: uplevel + 1)
30
+ else
31
+ super(*msgs, uplevel: uplevel.to_int + 1)
32
+ end
39
33
  end
40
34
  }
41
35
  )
@@ -143,7 +143,7 @@ module Prism
143
143
  when :call_and_write_node
144
144
  [FlagsField.new(:flags, [:safe_navigation?, :variable_call?, :attribute_write?, :ignore_visibility?]), OptionalNodeField.new(:receiver), OptionalLocationField.new(:call_operator_loc), OptionalLocationField.new(:message_loc), ConstantField.new(:read_name), ConstantField.new(:write_name), LocationField.new(:operator_loc), NodeField.new(:value)]
145
145
  when :call_node
146
- [FlagsField.new(:flags, [:safe_navigation?, :variable_call?, :attribute_write?, :ignore_visibility?]), OptionalNodeField.new(:receiver), OptionalLocationField.new(:call_operator_loc), ConstantField.new(:name), OptionalLocationField.new(:message_loc), OptionalLocationField.new(:opening_loc), OptionalNodeField.new(:arguments), OptionalLocationField.new(:closing_loc), OptionalNodeField.new(:block)]
146
+ [FlagsField.new(:flags, [:safe_navigation?, :variable_call?, :attribute_write?, :ignore_visibility?]), OptionalNodeField.new(:receiver), OptionalLocationField.new(:call_operator_loc), ConstantField.new(:name), OptionalLocationField.new(:message_loc), OptionalLocationField.new(:opening_loc), OptionalNodeField.new(:arguments), OptionalLocationField.new(:closing_loc), OptionalLocationField.new(:equal_loc), OptionalNodeField.new(:block)]
147
147
  when :call_operator_write_node
148
148
  [FlagsField.new(:flags, [:safe_navigation?, :variable_call?, :attribute_write?, :ignore_visibility?]), OptionalNodeField.new(:receiver), OptionalLocationField.new(:call_operator_loc), OptionalLocationField.new(:message_loc), ConstantField.new(:read_name), ConstantField.new(:write_name), ConstantField.new(:binary_operator), LocationField.new(:binary_operator_loc), NodeField.new(:value)]
149
149
  when :call_or_write_node
@@ -21,11 +21,11 @@ module Prism
21
21
 
22
22
  # The minor version of prism that we are expecting to find in the serialized
23
23
  # strings.
24
- MINOR_VERSION = 5
24
+ MINOR_VERSION = 7
25
25
 
26
26
  # The patch version of prism that we are expecting to find in the serialized
27
27
  # strings.
28
- PATCH_VERSION = 1
28
+ PATCH_VERSION = 0
29
29
 
30
30
  # Deserialize the dumped output from a request to parse or parse_file.
31
31
  #
@@ -397,6 +397,7 @@ module Prism
397
397
  :conditional_while_predicate,
398
398
  :constant_path_colon_colon_constant,
399
399
  :def_endless,
400
+ :def_endless_parameters,
400
401
  :def_endless_setter,
401
402
  :def_name,
402
403
  :def_params_term,
@@ -555,6 +556,7 @@ module Prism
555
556
  :parameter_wild_loose_comma,
556
557
  :pattern_array_multiple_rests,
557
558
  :pattern_capture_duplicate,
559
+ :pattern_capture_in_alternative,
558
560
  :pattern_expression_after_bracket,
559
561
  :pattern_expression_after_comma,
560
562
  :pattern_expression_after_hrocket,
@@ -616,6 +618,7 @@ module Prism
616
618
  :unexpected_index_keywords,
617
619
  :unexpected_label,
618
620
  :unexpected_multi_write,
621
+ :unexpected_parameter_default_value,
619
622
  :unexpected_range_operator,
620
623
  :unexpected_safe_navigation,
621
624
  :unexpected_token_close_context,
@@ -878,7 +881,7 @@ module Prism
878
881
  when 18 then
879
882
  CallAndWriteNode.new(source, node_id, location, load_varuint, load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_optional_location(freeze), load_constant(constant_pool, encoding), load_constant(constant_pool, encoding), load_location(freeze), load_node(constant_pool, encoding, freeze))
880
883
  when 19 then
881
- CallNode.new(source, node_id, location, load_varuint, load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_constant(constant_pool, encoding), load_optional_location(freeze), load_optional_location(freeze), load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_optional_node(constant_pool, encoding, freeze))
884
+ CallNode.new(source, node_id, location, load_varuint, load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_constant(constant_pool, encoding), load_optional_location(freeze), load_optional_location(freeze), load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_optional_location(freeze), load_optional_node(constant_pool, encoding, freeze))
882
885
  when 20 then
883
886
  CallOperatorWriteNode.new(source, node_id, location, load_varuint, load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_optional_location(freeze), load_constant(constant_pool, encoding), load_constant(constant_pool, encoding), load_constant(constant_pool, encoding), load_location(freeze), load_node(constant_pool, encoding, freeze))
884
887
  when 21 then
@@ -1286,7 +1289,7 @@ module Prism
1286
1289
  -> (constant_pool, encoding, freeze) {
1287
1290
  node_id = load_varuint
1288
1291
  location = load_location(freeze)
1289
- value = CallNode.new(source, node_id, location, load_varuint, load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_constant(constant_pool, encoding), load_optional_location(freeze), load_optional_location(freeze), load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_optional_node(constant_pool, encoding, freeze))
1292
+ value = CallNode.new(source, node_id, location, load_varuint, load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_constant(constant_pool, encoding), load_optional_location(freeze), load_optional_location(freeze), load_optional_node(constant_pool, encoding, freeze), load_optional_location(freeze), load_optional_location(freeze), load_optional_node(constant_pool, encoding, freeze))
1290
1293
  value.freeze if freeze
1291
1294
  value
1292
1295
  },
@@ -2238,6 +2241,7 @@ module Prism
2238
2241
  :KEYWORD_WHEN,
2239
2242
  :NEWLINE,
2240
2243
  :PARENTHESIS_RIGHT,
2244
+ :PIPE,
2241
2245
  :SEMICOLON,
2242
2246
  :AMPERSAND,
2243
2247
  :AMPERSAND_AMPERSAND,
@@ -2354,7 +2358,6 @@ module Prism
2354
2358
  :PERCENT_LOWER_X,
2355
2359
  :PERCENT_UPPER_I,
2356
2360
  :PERCENT_UPPER_W,
2357
- :PIPE,
2358
2361
  :PIPE_EQUAL,
2359
2362
  :PIPE_PIPE,
2360
2363
  :PIPE_PIPE_EQUAL,
@@ -217,7 +217,7 @@ module Prism
217
217
  rescue_clause.exceptions.any? ? builder.array(nil, visit_all(rescue_clause.exceptions), nil) : nil,
218
218
  token(rescue_clause.operator_loc),
219
219
  visit(rescue_clause.reference),
220
- srange_find(find_start_offset, find_end_offset, ";"),
220
+ srange_semicolon(find_start_offset, find_end_offset),
221
221
  visit(rescue_clause.statements)
222
222
  )
223
223
  end until (rescue_clause = rescue_clause.subsequent).nil?
@@ -323,7 +323,7 @@ module Prism
323
323
  visit_all(arguments),
324
324
  token(node.closing_loc),
325
325
  ),
326
- srange_find(node.message_loc.end_offset, node.arguments.arguments.last.location.start_offset, "="),
326
+ token(node.equal_loc),
327
327
  visit(node.arguments.arguments.last)
328
328
  ),
329
329
  block
@@ -340,7 +340,7 @@ module Prism
340
340
  if name.end_with?("=") && !message_loc.slice.end_with?("=") && node.arguments && block.nil?
341
341
  builder.assign(
342
342
  builder.attr_asgn(visit(node.receiver), call_operator, token(message_loc)),
343
- srange_find(message_loc.end_offset, node.arguments.location.start_offset, "="),
343
+ token(node.equal_loc),
344
344
  visit(node.arguments.arguments.last)
345
345
  )
346
346
  else
@@ -789,7 +789,7 @@ module Prism
789
789
  if (do_keyword_loc = node.do_keyword_loc)
790
790
  token(do_keyword_loc)
791
791
  else
792
- srange_find(node.collection.location.end_offset, (node.statements&.location || node.end_keyword_loc).start_offset, ";")
792
+ srange_semicolon(node.collection.location.end_offset, (node.statements&.location || node.end_keyword_loc).start_offset)
793
793
  end,
794
794
  visit(node.statements),
795
795
  token(node.end_keyword_loc)
@@ -921,7 +921,7 @@ module Prism
921
921
  if (then_keyword_loc = node.then_keyword_loc)
922
922
  token(then_keyword_loc)
923
923
  else
924
- srange_find(node.predicate.location.end_offset, (node.statements&.location || node.subsequent&.location || node.end_keyword_loc).start_offset, ";")
924
+ srange_semicolon(node.predicate.location.end_offset, (node.statements&.location || node.subsequent&.location || node.end_keyword_loc).start_offset)
925
925
  end,
926
926
  visit(node.statements),
927
927
  case node.subsequent
@@ -987,7 +987,7 @@ module Prism
987
987
  if (then_loc = node.then_loc)
988
988
  token(then_loc)
989
989
  else
990
- srange_find(node.pattern.location.end_offset, node.statements&.location&.start_offset, ";")
990
+ srange_semicolon(node.pattern.location.end_offset, node.statements&.location&.start_offset)
991
991
  end,
992
992
  visit(node.statements)
993
993
  )
@@ -1808,7 +1808,7 @@ module Prism
1808
1808
  if (then_keyword_loc = node.then_keyword_loc)
1809
1809
  token(then_keyword_loc)
1810
1810
  else
1811
- srange_find(node.predicate.location.end_offset, (node.statements&.location || node.else_clause&.location || node.end_keyword_loc).start_offset, ";")
1811
+ srange_semicolon(node.predicate.location.end_offset, (node.statements&.location || node.else_clause&.location || node.end_keyword_loc).start_offset)
1812
1812
  end,
1813
1813
  visit(node.else_clause),
1814
1814
  token(node.else_clause&.else_keyword_loc),
@@ -1839,7 +1839,7 @@ module Prism
1839
1839
  if (do_keyword_loc = node.do_keyword_loc)
1840
1840
  token(do_keyword_loc)
1841
1841
  else
1842
- srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, ";")
1842
+ srange_semicolon(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset)
1843
1843
  end,
1844
1844
  visit(node.statements),
1845
1845
  token(node.closing_loc)
@@ -1863,7 +1863,7 @@ module Prism
1863
1863
  if (then_keyword_loc = node.then_keyword_loc)
1864
1864
  token(then_keyword_loc)
1865
1865
  else
1866
- srange_find(node.conditions.last.location.end_offset, node.statements&.location&.start_offset, ";")
1866
+ srange_semicolon(node.conditions.last.location.end_offset, node.statements&.location&.start_offset)
1867
1867
  end,
1868
1868
  visit(node.statements)
1869
1869
  )
@@ -1883,7 +1883,7 @@ module Prism
1883
1883
  if (do_keyword_loc = node.do_keyword_loc)
1884
1884
  token(do_keyword_loc)
1885
1885
  else
1886
- srange_find(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset, ";")
1886
+ srange_semicolon(node.predicate.location.end_offset, (node.statements&.location || node.closing_loc).start_offset)
1887
1887
  end,
1888
1888
  visit(node.statements),
1889
1889
  token(node.closing_loc)
@@ -2012,16 +2012,16 @@ module Prism
2012
2012
  Range.new(source_buffer, offset_cache[start_offset], offset_cache[end_offset])
2013
2013
  end
2014
2014
 
2015
- # Constructs a new source range by finding the given character between
2016
- # the given start offset and end offset. If the needle is not found, it
2017
- # returns nil. Importantly it does not search past newlines or comments.
2015
+ # Constructs a new source range by finding a semicolon between the given
2016
+ # start offset and end offset. If the semicolon is not found, it returns
2017
+ # nil. Importantly it does not search past newlines or comments.
2018
2018
  #
2019
2019
  # Note that end_offset is allowed to be nil, in which case this will
2020
2020
  # search until the end of the string.
2021
- def srange_find(start_offset, end_offset, character)
2022
- if (match = source_buffer.source.byteslice(start_offset...end_offset)[/\A\s*#{character}/])
2021
+ def srange_semicolon(start_offset, end_offset)
2022
+ if (match = source_buffer.source.byteslice(start_offset...end_offset)[/\A\s*;/])
2023
2023
  final_offset = start_offset + match.bytesize
2024
- [character, Range.new(source_buffer, offset_cache[final_offset - character.bytesize], offset_cache[final_offset])]
2024
+ [";", Range.new(source_buffer, offset_cache[final_offset - 1], offset_cache[final_offset])]
2025
2025
  end
2026
2026
  end
2027
2027
 
@@ -19,6 +19,13 @@ module Prism
19
19
  # whitequark/parser gem's syntax tree. It inherits from the base parser for
20
20
  # the parser gem, and overrides the parse* methods to parse with prism and
21
21
  # then translate.
22
+ #
23
+ # Note that this version of the parser always parses using the latest
24
+ # version of Ruby syntax supported by Prism. If you want specific version
25
+ # support, use one of the version-specific subclasses, such as
26
+ # `Prism::Translation::Parser34`. If you want to parse using the same
27
+ # version of Ruby syntax as the currently running version of Ruby, use
28
+ # `Prism::Translation::ParserCurrent`.
22
29
  class Parser < ::Parser::Base
23
30
  Diagnostic = ::Parser::Diagnostic # :nodoc:
24
31
  private_constant :Diagnostic
@@ -77,7 +84,7 @@ module Prism
77
84
  end
78
85
 
79
86
  def version # :nodoc:
80
- 34
87
+ 41
81
88
  end
82
89
 
83
90
  # The default encoding for Ruby files is UTF-8.
@@ -349,8 +356,10 @@ module Prism
349
356
  "3.3.1"
350
357
  when 34
351
358
  "3.4.0"
352
- when 35
353
- "3.5.0"
359
+ when 35, 40
360
+ "4.0.0"
361
+ when 41
362
+ "4.1.0"
354
363
  else
355
364
  "latest"
356
365
  end
@@ -3,11 +3,6 @@
3
3
 
4
4
  module Prism
5
5
  module Translation
6
- # This class is the entry-point for Ruby 3.5 of `Prism::Translation::Parser`.
7
- class Parser35 < Parser
8
- def version # :nodoc:
9
- 35
10
- end
11
- end
6
+ Parser35 = Parser40 # :nodoc:
12
7
  end
13
8
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ # :markup: markdown
3
+
4
+ module Prism
5
+ module Translation
6
+ # This class is the entry-point for Ruby 4.0 of `Prism::Translation::Parser`.
7
+ class Parser40 < Parser
8
+ def version # :nodoc:
9
+ 40
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+ # :markup: markdown
3
+
4
+ module Prism
5
+ module Translation
6
+ # This class is the entry-point for Ruby 4.1 of `Prism::Translation::Parser`.
7
+ class Parser41 < Parser
8
+ def version # :nodoc:
9
+ 41
10
+ end
11
+ end
12
+ end
13
+ end
@@ -10,8 +10,10 @@ module Prism
10
10
  ParserCurrent = Parser33
11
11
  when /^3\.4\./
12
12
  ParserCurrent = Parser34
13
- when /^3\.5\./
14
- ParserCurrent = Parser35
13
+ when /^3\.5\./, /^4\.0\./
14
+ ParserCurrent = Parser40
15
+ when /^4\.1\./
16
+ ParserCurrent = Parser41
15
17
  else
16
18
  # Keep this in sync with released Ruby.
17
19
  parser = Parser34
@@ -71,7 +71,7 @@ module Prism
71
71
  # [[1, 13], :on_kw, "end", END ]]
72
72
  #
73
73
  def self.lex(src, filename = "-", lineno = 1, raise_errors: false)
74
- result = Prism.lex_compat(src, filepath: filename, line: lineno)
74
+ result = Prism.lex_compat(src, filepath: filename, line: lineno, version: "current")
75
75
 
76
76
  if result.failure? && raise_errors
77
77
  raise SyntaxError, result.errors.first.message
@@ -3295,7 +3295,7 @@ module Prism
3295
3295
 
3296
3296
  # Lazily initialize the parse result.
3297
3297
  def result
3298
- @result ||= Prism.parse(source, partial_script: true)
3298
+ @result ||= Prism.parse(source, partial_script: true, version: "current")
3299
3299
  end
3300
3300
 
3301
3301
  ##########################################################################
@@ -2,12 +2,17 @@
2
2
  # :markup: markdown
3
3
 
4
4
  begin
5
- require "ruby_parser"
5
+ require "sexp"
6
6
  rescue LoadError
7
- warn(%q{Error: Unable to load ruby_parser. Add `gem "ruby_parser"` to your Gemfile.})
7
+ warn(%q{Error: Unable to load sexp. Add `gem "sexp_processor"` to your Gemfile.})
8
8
  exit(1)
9
9
  end
10
10
 
11
+ class RubyParser # :nodoc:
12
+ class SyntaxError < RuntimeError # :nodoc:
13
+ end
14
+ end
15
+
11
16
  module Prism
12
17
  module Translation
13
18
  # This module is the entry-point for converting a prism syntax tree into the
@@ -152,7 +157,7 @@ module Prism
152
157
  # ^^
153
158
  # ```
154
159
  def visit_back_reference_read_node(node)
155
- s(node, :back_ref, node.name.name.delete_prefix("$").to_sym)
160
+ s(node, :back_ref, node.name.to_s.delete_prefix("$").to_sym)
156
161
  end
157
162
 
158
163
  # ```
@@ -415,14 +420,18 @@ module Prism
415
420
  visit(node.constant_path)
416
421
  end
417
422
 
418
- if node.body.nil?
419
- s(node, :class, name, visit(node.superclass))
420
- elsif node.body.is_a?(StatementsNode)
421
- compiler = copy_compiler(in_def: false)
422
- s(node, :class, name, visit(node.superclass)).concat(node.body.body.map { |child| child.accept(compiler) })
423
- else
424
- s(node, :class, name, visit(node.superclass), node.body.accept(copy_compiler(in_def: false)))
425
- end
423
+ result =
424
+ if node.body.nil?
425
+ s(node, :class, name, visit(node.superclass))
426
+ elsif node.body.is_a?(StatementsNode)
427
+ compiler = copy_compiler(in_def: false)
428
+ s(node, :class, name, visit(node.superclass)).concat(node.body.body.map { |child| child.accept(compiler) })
429
+ else
430
+ s(node, :class, name, visit(node.superclass), node.body.accept(copy_compiler(in_def: false)))
431
+ end
432
+
433
+ attach_comments(result, node)
434
+ result
426
435
  end
427
436
 
428
437
  # ```
@@ -611,7 +620,9 @@ module Prism
611
620
  s(node, :defs, visit(node.receiver), name)
612
621
  end
613
622
 
623
+ attach_comments(result, node)
614
624
  result.line(node.name_loc.start_line)
625
+
615
626
  if node.parameters.nil?
616
627
  result << s(node, :args).line(node.name_loc.start_line)
617
628
  else
@@ -1270,14 +1281,18 @@ module Prism
1270
1281
  visit(node.constant_path)
1271
1282
  end
1272
1283
 
1273
- if node.body.nil?
1274
- s(node, :module, name)
1275
- elsif node.body.is_a?(StatementsNode)
1276
- compiler = copy_compiler(in_def: false)
1277
- s(node, :module, name).concat(node.body.body.map { |child| child.accept(compiler) })
1278
- else
1279
- s(node, :module, name, node.body.accept(copy_compiler(in_def: false)))
1280
- end
1284
+ result =
1285
+ if node.body.nil?
1286
+ s(node, :module, name)
1287
+ elsif node.body.is_a?(StatementsNode)
1288
+ compiler = copy_compiler(in_def: false)
1289
+ s(node, :module, name).concat(node.body.body.map { |child| child.accept(compiler) })
1290
+ else
1291
+ s(node, :module, name, node.body.accept(copy_compiler(in_def: false)))
1292
+ end
1293
+
1294
+ attach_comments(result, node)
1295
+ result
1281
1296
  end
1282
1297
 
1283
1298
  # ```
@@ -1820,6 +1835,17 @@ module Prism
1820
1835
 
1821
1836
  private
1822
1837
 
1838
+ # Attach prism comments to the given sexp.
1839
+ def attach_comments(sexp, node)
1840
+ return unless node.comments
1841
+ return if node.comments.empty?
1842
+
1843
+ extra = node.location.start_line - node.comments.last.location.start_line
1844
+ comments = node.comments.map(&:slice)
1845
+ comments.concat([nil] * [0, extra].max)
1846
+ sexp.comments = comments.join("\n")
1847
+ end
1848
+
1823
1849
  # Create a new compiler with the given options.
1824
1850
  def copy_compiler(in_def: self.in_def, in_pattern: self.in_pattern)
1825
1851
  Compiler.new(file, in_def: in_def, in_pattern: in_pattern)
@@ -1898,6 +1924,14 @@ module Prism
1898
1924
  translate(Prism.parse_file(filepath, partial_script: true), filepath)
1899
1925
  end
1900
1926
 
1927
+ # Parse the give file and translate it into the
1928
+ # seattlerb/ruby_parser gem's Sexp format. This method is
1929
+ # provided for API compatibility to RubyParser and takes an
1930
+ # optional +timeout+ argument.
1931
+ def process(ruby, file = "(string)", timeout = nil)
1932
+ Timeout.timeout(timeout) { parse(ruby, file) }
1933
+ end
1934
+
1901
1935
  class << self
1902
1936
  # Parse the given source and translate it into the seattlerb/ruby_parser
1903
1937
  # gem's Sexp format.
@@ -1922,6 +1956,7 @@ module Prism
1922
1956
  raise ::RubyParser::SyntaxError, "#{filepath}:#{error.location.start_line} :: #{error.message}"
1923
1957
  end
1924
1958
 
1959
+ result.attach_comments!
1925
1960
  result.value.accept(Compiler.new(filepath))
1926
1961
  end
1927
1962
  end
@@ -10,6 +10,8 @@ module Prism
10
10
  autoload :Parser33, "prism/translation/parser33"
11
11
  autoload :Parser34, "prism/translation/parser34"
12
12
  autoload :Parser35, "prism/translation/parser35"
13
+ autoload :Parser40, "prism/translation/parser40"
14
+ autoload :Parser41, "prism/translation/parser41"
13
15
  autoload :Ripper, "prism/translation/ripper"
14
16
  autoload :RubyParser, "prism/translation/ruby_parser"
15
17
  end
data/lib/prism.rb CHANGED
@@ -37,6 +37,26 @@ module Prism
37
37
  private_constant :LexCompat
38
38
  private_constant :LexRipper
39
39
 
40
+ # Raised when requested to parse as the currently running Ruby version but Prism has no support for it.
41
+ class CurrentVersionError < ArgumentError
42
+ # Initialize a new exception for the given ruby version string.
43
+ def initialize(version)
44
+ message = +"invalid version: Requested to parse as `version: 'current'`; "
45
+ segments =
46
+ if version.match?(/\A\d+\.\d+.\d+\z/)
47
+ version.split(".").map(&:to_i)
48
+ end
49
+
50
+ if segments && ((segments[0] < 3) || (segments[0] == 3 && segments[1] < 3))
51
+ message << " #{version} is below the minimum supported syntax."
52
+ else
53
+ message << " #{version} is unknown. Please update the `prism` gem."
54
+ end
55
+
56
+ super(message)
57
+ end
58
+ end
59
+
40
60
  # :call-seq:
41
61
  # Prism::lex_compat(source, **options) -> LexCompat::Result
42
62
  #
data/prism.gemspec CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = "prism"
5
- spec.version = "1.5.1"
5
+ spec.version = "1.7.0"
6
6
  spec.authors = ["Shopify"]
7
7
  spec.email = ["ruby@shopify.com"]
8
8
 
@@ -101,6 +101,8 @@ Gem::Specification.new do |spec|
101
101
  "lib/prism/translation/parser33.rb",
102
102
  "lib/prism/translation/parser34.rb",
103
103
  "lib/prism/translation/parser35.rb",
104
+ "lib/prism/translation/parser40.rb",
105
+ "lib/prism/translation/parser41.rb",
104
106
  "lib/prism/translation/parser/builder.rb",
105
107
  "lib/prism/translation/parser/compiler.rb",
106
108
  "lib/prism/translation/parser/lexer.rb",
@@ -123,6 +125,8 @@ Gem::Specification.new do |spec|
123
125
  "rbi/prism/translation/parser33.rbi",
124
126
  "rbi/prism/translation/parser34.rbi",
125
127
  "rbi/prism/translation/parser35.rbi",
128
+ "rbi/prism/translation/parser40.rbi",
129
+ "rbi/prism/translation/parser41.rbi",
126
130
  "rbi/prism/translation/ripper.rbi",
127
131
  "rbi/prism/visitor.rbi",
128
132
  "sig/prism.rbs",
data/rbi/prism/dsl.rbi CHANGED
@@ -67,8 +67,8 @@ module Prism::DSL
67
67
  sig { params(source: Prism::Source, node_id: Integer, location: Prism::Location, flags: Integer, receiver: T.nilable(Prism::Node), call_operator_loc: T.nilable(Prism::Location), message_loc: T.nilable(Prism::Location), read_name: Symbol, write_name: Symbol, operator_loc: Prism::Location, value: Prism::Node).returns(Prism::CallAndWriteNode) }
68
68
  def call_and_write_node(source: default_source, node_id: 0, location: default_location, flags: 0, receiver: nil, call_operator_loc: nil, message_loc: nil, read_name: :"", write_name: :"", operator_loc: location, value: default_node(source, location)); end
69
69
 
70
- sig { params(source: Prism::Source, node_id: Integer, location: Prism::Location, flags: Integer, receiver: T.nilable(Prism::Node), call_operator_loc: T.nilable(Prism::Location), name: Symbol, message_loc: T.nilable(Prism::Location), opening_loc: T.nilable(Prism::Location), arguments: T.nilable(Prism::ArgumentsNode), closing_loc: T.nilable(Prism::Location), block: T.nilable(T.any(Prism::BlockNode, Prism::BlockArgumentNode))).returns(Prism::CallNode) }
71
- def call_node(source: default_source, node_id: 0, location: default_location, flags: 0, receiver: nil, call_operator_loc: nil, name: :"", message_loc: nil, opening_loc: nil, arguments: nil, closing_loc: nil, block: nil); end
70
+ sig { params(source: Prism::Source, node_id: Integer, location: Prism::Location, flags: Integer, receiver: T.nilable(Prism::Node), call_operator_loc: T.nilable(Prism::Location), name: Symbol, message_loc: T.nilable(Prism::Location), opening_loc: T.nilable(Prism::Location), arguments: T.nilable(Prism::ArgumentsNode), closing_loc: T.nilable(Prism::Location), equal_loc: T.nilable(Prism::Location), block: T.nilable(T.any(Prism::BlockNode, Prism::BlockArgumentNode))).returns(Prism::CallNode) }
71
+ def call_node(source: default_source, node_id: 0, location: default_location, flags: 0, receiver: nil, call_operator_loc: nil, name: :"", message_loc: nil, opening_loc: nil, arguments: nil, closing_loc: nil, equal_loc: nil, block: nil); end
72
72
 
73
73
  sig { params(source: Prism::Source, node_id: Integer, location: Prism::Location, flags: Integer, receiver: T.nilable(Prism::Node), call_operator_loc: T.nilable(Prism::Location), message_loc: T.nilable(Prism::Location), read_name: Symbol, write_name: Symbol, binary_operator: Symbol, binary_operator_loc: Prism::Location, value: Prism::Node).returns(Prism::CallOperatorWriteNode) }
74
74
  def call_operator_write_node(source: default_source, node_id: 0, location: default_location, flags: 0, receiver: nil, call_operator_loc: nil, message_loc: nil, read_name: :"", write_name: :"", binary_operator: :"", binary_operator_loc: location, value: default_node(source, location)); end
@@ -265,7 +265,7 @@ module Prism::DSL
265
265
  sig { params(source: Prism::Source, node_id: Integer, location: Prism::Location, flags: Integer, opening_loc: Prism::Location, parts: T::Array[T.any(Prism::StringNode, Prism::EmbeddedStatementsNode, Prism::EmbeddedVariableNode)], closing_loc: Prism::Location).returns(Prism::InterpolatedRegularExpressionNode) }
266
266
  def interpolated_regular_expression_node(source: default_source, node_id: 0, location: default_location, flags: 0, opening_loc: location, parts: [], closing_loc: location); end
267
267
 
268
- sig { params(source: Prism::Source, node_id: Integer, location: Prism::Location, flags: Integer, opening_loc: T.nilable(Prism::Location), parts: T::Array[T.any(Prism::StringNode, Prism::EmbeddedStatementsNode, Prism::EmbeddedVariableNode, Prism::InterpolatedStringNode, Prism::XStringNode)], closing_loc: T.nilable(Prism::Location)).returns(Prism::InterpolatedStringNode) }
268
+ sig { params(source: Prism::Source, node_id: Integer, location: Prism::Location, flags: Integer, opening_loc: T.nilable(Prism::Location), parts: T::Array[T.any(Prism::StringNode, Prism::EmbeddedStatementsNode, Prism::EmbeddedVariableNode, Prism::InterpolatedStringNode, Prism::XStringNode, Prism::InterpolatedXStringNode, Prism::SymbolNode, Prism::InterpolatedSymbolNode)], closing_loc: T.nilable(Prism::Location)).returns(Prism::InterpolatedStringNode) }
269
269
  def interpolated_string_node(source: default_source, node_id: 0, location: default_location, flags: 0, opening_loc: nil, parts: [], closing_loc: nil); end
270
270
 
271
271
  sig { params(source: Prism::Source, node_id: Integer, location: Prism::Location, flags: Integer, opening_loc: T.nilable(Prism::Location), parts: T::Array[T.any(Prism::StringNode, Prism::EmbeddedStatementsNode, Prism::EmbeddedVariableNode)], closing_loc: T.nilable(Prism::Location)).returns(Prism::InterpolatedSymbolNode) }