parser 2.6.0.0 → 3.1.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 (102) hide show
  1. checksums.yaml +4 -4
  2. data/lib/parser/all.rb +3 -0
  3. data/lib/parser/ast/processor.rb +48 -1
  4. data/lib/parser/base.rb +30 -6
  5. data/lib/parser/builders/default.rb +670 -38
  6. data/lib/parser/context.rb +24 -26
  7. data/lib/parser/current.rb +36 -9
  8. data/lib/parser/current_arg_stack.rb +46 -0
  9. data/lib/parser/diagnostic/engine.rb +1 -2
  10. data/lib/parser/diagnostic.rb +1 -1
  11. data/lib/parser/lexer/dedenter.rb +58 -49
  12. data/lib/parser/lexer/explanation.rb +1 -1
  13. data/lib/parser/lexer.rb +13837 -11893
  14. data/lib/parser/macruby.rb +2544 -2489
  15. data/lib/parser/max_numparam_stack.rb +56 -0
  16. data/lib/parser/messages.rb +78 -44
  17. data/lib/parser/meta.rb +13 -3
  18. data/lib/parser/ruby18.rb +2313 -2259
  19. data/lib/parser/ruby19.rb +2537 -2488
  20. data/lib/parser/ruby20.rb +2724 -2673
  21. data/lib/parser/ruby21.rb +2766 -2727
  22. data/lib/parser/ruby22.rb +2683 -2628
  23. data/lib/parser/ruby23.rb +2796 -2755
  24. data/lib/parser/ruby24.rb +2812 -2771
  25. data/lib/parser/ruby25.rb +2703 -2670
  26. data/lib/parser/ruby26.rb +2794 -2747
  27. data/lib/parser/ruby27.rb +7914 -0
  28. data/lib/parser/ruby28.rb +8047 -0
  29. data/lib/parser/ruby30.rb +8096 -0
  30. data/lib/parser/ruby31.rb +8354 -0
  31. data/lib/parser/rubymotion.rb +2527 -2485
  32. data/lib/parser/runner/ruby_parse.rb +2 -2
  33. data/lib/parser/runner/ruby_rewrite.rb +2 -2
  34. data/lib/parser/runner.rb +36 -2
  35. data/lib/parser/source/buffer.rb +53 -28
  36. data/lib/parser/source/comment/associator.rb +31 -8
  37. data/lib/parser/source/comment.rb +14 -1
  38. data/lib/parser/source/map/method_definition.rb +25 -0
  39. data/lib/parser/source/range.rb +19 -3
  40. data/lib/parser/source/tree_rewriter/action.rb +137 -28
  41. data/lib/parser/source/tree_rewriter.rb +144 -14
  42. data/lib/parser/static_environment.rb +23 -0
  43. data/lib/parser/tree_rewriter.rb +3 -3
  44. data/lib/parser/variables_stack.rb +36 -0
  45. data/lib/parser/version.rb +1 -1
  46. data/lib/parser.rb +4 -0
  47. data/parser.gemspec +12 -19
  48. metadata +34 -99
  49. data/.gitignore +0 -32
  50. data/.travis.yml +0 -45
  51. data/.yardopts +0 -21
  52. data/CHANGELOG.md +0 -943
  53. data/CONTRIBUTING.md +0 -17
  54. data/Gemfile +0 -10
  55. data/README.md +0 -301
  56. data/Rakefile +0 -165
  57. data/ci/run_rubocop_specs +0 -14
  58. data/doc/AST_FORMAT.md +0 -1735
  59. data/doc/CUSTOMIZATION.md +0 -37
  60. data/doc/INTERNALS.md +0 -21
  61. data/doc/css/.gitkeep +0 -0
  62. data/doc/css/common.css +0 -68
  63. data/lib/parser/lexer.rl +0 -2383
  64. data/lib/parser/macruby.y +0 -2198
  65. data/lib/parser/ruby18.y +0 -1934
  66. data/lib/parser/ruby19.y +0 -2175
  67. data/lib/parser/ruby20.y +0 -2353
  68. data/lib/parser/ruby21.y +0 -2357
  69. data/lib/parser/ruby22.y +0 -2364
  70. data/lib/parser/ruby23.y +0 -2370
  71. data/lib/parser/ruby24.y +0 -2408
  72. data/lib/parser/ruby25.y +0 -2405
  73. data/lib/parser/ruby26.y +0 -2413
  74. data/lib/parser/rubymotion.y +0 -2182
  75. data/test/bug_163/fixtures/input.rb +0 -5
  76. data/test/bug_163/fixtures/output.rb +0 -5
  77. data/test/bug_163/rewriter.rb +0 -20
  78. data/test/helper.rb +0 -52
  79. data/test/parse_helper.rb +0 -315
  80. data/test/racc_coverage_helper.rb +0 -133
  81. data/test/test_base.rb +0 -31
  82. data/test/test_current.rb +0 -27
  83. data/test/test_diagnostic.rb +0 -96
  84. data/test/test_diagnostic_engine.rb +0 -62
  85. data/test/test_encoding.rb +0 -99
  86. data/test/test_lexer.rb +0 -3543
  87. data/test/test_lexer_stack_state.rb +0 -78
  88. data/test/test_parse_helper.rb +0 -80
  89. data/test/test_parser.rb +0 -7087
  90. data/test/test_runner_rewrite.rb +0 -47
  91. data/test/test_source_buffer.rb +0 -162
  92. data/test/test_source_comment.rb +0 -36
  93. data/test/test_source_comment_associator.rb +0 -367
  94. data/test/test_source_map.rb +0 -15
  95. data/test/test_source_range.rb +0 -172
  96. data/test/test_source_rewriter.rb +0 -541
  97. data/test/test_source_rewriter_action.rb +0 -46
  98. data/test/test_source_tree_rewriter.rb +0 -173
  99. data/test/test_static_environment.rb +0 -45
  100. data/test/using_tree_rewriter/fixtures/input.rb +0 -3
  101. data/test/using_tree_rewriter/fixtures/output.rb +0 -3
  102. data/test/using_tree_rewriter/using_tree_rewriter.rb +0 -9
@@ -5,47 +5,45 @@ module Parser
5
5
  #
6
6
  # Supported states:
7
7
  # + :class - in the class body (class A; end)
8
+ # + :module - in the module body (module M; end)
8
9
  # + :sclass - in the singleton class body (class << obj; end)
9
10
  # + :def - in the method body (def m; end)
10
11
  # + :defs - in the singleton method body (def self.m; end)
12
+ # + :def_open_args - in the arglist of the method definition
13
+ # keep in mind that it's set **only** after reducing the first argument,
14
+ # if you need to handle the first argument check `lex_state == expr_fname`
11
15
  # + :block - in the block body (tap {})
12
16
  # + :lambda - in the lambda body (-> {})
13
17
  #
14
18
  class Context
15
- attr_reader :stack
19
+ FLAGS = %i[
20
+ in_defined
21
+ in_kwarg
22
+ in_argdef
23
+ in_def
24
+ in_class
25
+ in_block
26
+ in_lambda
27
+ ]
16
28
 
17
29
  def initialize
18
- @stack = []
19
- freeze
20
- end
21
-
22
- def push(state)
23
- @stack << state
24
- end
25
-
26
- def pop
27
- @stack.pop
30
+ reset
28
31
  end
29
32
 
30
33
  def reset
31
- @stack.clear
32
- end
33
-
34
- def in_class?
35
- @stack.last == :class
36
- end
37
-
38
- def indirectly_in_def?
39
- @stack.include?(:def) || @stack.include?(:defs)
34
+ @in_defined = false
35
+ @in_kwarg = false
36
+ @in_argdef = false
37
+ @in_def = false
38
+ @in_class = false
39
+ @in_block = false
40
+ @in_lambda = false
40
41
  end
41
42
 
42
- def class_definition_allowed?
43
- def_index = stack.rindex { |item| [:def, :defs].include?(item) }
44
- sclass_index = stack.rindex(:sclass)
43
+ attr_accessor(*FLAGS)
45
44
 
46
- def_index.nil? || (!sclass_index.nil? && sclass_index > def_index)
45
+ def in_dynamic_block?
46
+ in_block || in_lambda
47
47
  end
48
- alias module_definition_allowed? class_definition_allowed?
49
- alias dynamic_const_definition_allowed? class_definition_allowed?
50
48
  end
51
49
  end
@@ -3,9 +3,9 @@
3
3
  module Parser
4
4
  class << self
5
5
  def warn_syntax_deviation(feature, version)
6
- warn "warning: parser/current is loading #{feature}, which recognizes"
7
- warn "warning: #{version}-compliant syntax, but you are running #{RUBY_VERSION}."
8
- warn "warning: please see https://github.com/whitequark/parser#compatibility-with-ruby-mri."
6
+ warn "warning: parser/current is loading #{feature}, which recognizes" \
7
+ "#{version}-compliant syntax, but you are running #{RUBY_VERSION}.\n" \
8
+ "Please see https://github.com/whitequark/parser#compatibility-with-ruby-mri."
9
9
  end
10
10
  private :warn_syntax_deviation
11
11
  end
@@ -48,7 +48,7 @@ module Parser
48
48
  CurrentRuby = Ruby23
49
49
 
50
50
  when /^2\.4\./
51
- current_version = '2.4.5'
51
+ current_version = '2.4.10'
52
52
  if RUBY_VERSION != current_version
53
53
  warn_syntax_deviation 'parser/ruby24', current_version
54
54
  end
@@ -57,7 +57,7 @@ module Parser
57
57
  CurrentRuby = Ruby24
58
58
 
59
59
  when /^2\.5\./
60
- current_version = '2.5.3'
60
+ current_version = '2.5.9'
61
61
  if RUBY_VERSION != current_version
62
62
  warn_syntax_deviation 'parser/ruby25', current_version
63
63
  end
@@ -66,7 +66,7 @@ module Parser
66
66
  CurrentRuby = Ruby25
67
67
 
68
68
  when /^2\.6\./
69
- current_version = '2.6.0'
69
+ current_version = '2.6.9'
70
70
  if RUBY_VERSION != current_version
71
71
  warn_syntax_deviation 'parser/ruby26', current_version
72
72
  end
@@ -74,10 +74,37 @@ module Parser
74
74
  require 'parser/ruby26'
75
75
  CurrentRuby = Ruby26
76
76
 
77
+ when /^2\.7\./
78
+ current_version = '2.7.5'
79
+ if RUBY_VERSION != current_version
80
+ warn_syntax_deviation 'parser/ruby27', current_version
81
+ end
82
+
83
+ require 'parser/ruby27'
84
+ CurrentRuby = Ruby27
85
+
86
+ when /^3\.0\./
87
+ current_version = '3.0.3'
88
+ if RUBY_VERSION != current_version
89
+ warn_syntax_deviation 'parser/ruby30', current_version
90
+ end
91
+
92
+ require 'parser/ruby30'
93
+ CurrentRuby = Ruby30
94
+
95
+ when /^3\.1\./
96
+ current_version = '3.1.0'
97
+ if RUBY_VERSION != current_version
98
+ warn_syntax_deviation 'parser/ruby31', current_version
99
+ end
100
+
101
+ require 'parser/ruby31'
102
+ CurrentRuby = Ruby31
103
+
77
104
  else # :nocov:
78
105
  # Keep this in sync with released Ruby.
79
- warn_syntax_deviation 'parser/ruby25', '2.5.x'
80
- require 'parser/ruby25'
81
- CurrentRuby = Ruby25
106
+ warn_syntax_deviation 'parser/ruby31', '3.1.x'
107
+ require 'parser/ruby31'
108
+ CurrentRuby = Ruby31
82
109
  end
83
110
  end
@@ -0,0 +1,46 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Parser
4
+ # Stack that holds names of current arguments,
5
+ # i.e. while parsing
6
+ # def m1(a = (def m2(b = def m3(c = 1); end); end)); end
7
+ # ^
8
+ # stack is [:a, :b, :c]
9
+ #
10
+ # Emulates `p->cur_arg` in MRI's parse.y
11
+ #
12
+ # @api private
13
+ #
14
+ class CurrentArgStack
15
+ attr_reader :stack
16
+
17
+ def initialize
18
+ @stack = []
19
+ freeze
20
+ end
21
+
22
+ def empty?
23
+ @stack.size == 0
24
+ end
25
+
26
+ def push(value)
27
+ @stack << value
28
+ end
29
+
30
+ def set(value)
31
+ @stack[@stack.length - 1] = value
32
+ end
33
+
34
+ def pop
35
+ @stack.pop
36
+ end
37
+
38
+ def reset
39
+ @stack.clear
40
+ end
41
+
42
+ def top
43
+ @stack.last
44
+ end
45
+ end
46
+ end
@@ -7,8 +7,7 @@ module Parser
7
7
  # diagnostics by delegating them to registered consumers.
8
8
  #
9
9
  # @example
10
- # buffer = Parser::Source::Buffer.new(__FILE__)
11
- # buffer.code = 'foobar'
10
+ # buffer = Parser::Source::Buffer.new(__FILE__, source: 'foobar')
12
11
  #
13
12
  # consumer = lambda do |diagnostic|
14
13
  # puts diagnostic.message
@@ -67,7 +67,7 @@ module Parser
67
67
  # @return [String] the rendered message.
68
68
  #
69
69
  def message
70
- MESSAGES[@reason] % @arguments
70
+ Messages.compile(@reason, @arguments)
71
71
  end
72
72
 
73
73
  ##
@@ -3,72 +3,81 @@
3
3
  module Parser
4
4
 
5
5
  class Lexer::Dedenter
6
+ # Tab (\t) counts as 8 spaces
7
+ TAB_WIDTH = 8
8
+
6
9
  def initialize(dedent_level)
7
10
  @dedent_level = dedent_level
8
11
  @at_line_begin = true
9
12
  @indent_level = 0
10
13
  end
11
14
 
15
+ # For a heredoc like
16
+ # <<-HERE
17
+ # a
18
+ # b
19
+ # HERE
20
+ # this method gets called with " a\n" and " b\n"
21
+ #
22
+ # However, the following heredoc:
23
+ #
24
+ # <<-HERE
25
+ # a\
26
+ # b
27
+ # HERE
28
+ # calls this method only once with a string " a\\\n b\n"
29
+ #
30
+ # This is important because technically it's a single line,
31
+ # but it has to be concatenated __after__ dedenting.
32
+ #
33
+ # It has no effect for non-squiggly heredocs, i.e. it simply removes "\\\n"
34
+ # Of course, lexer could do it but once again: it's all because of dedenting.
35
+ #
12
36
  def dedent(string)
13
- space_begin = space_end = offset = 0
14
- last_index = string.length - 1
15
- escape = false
16
- _at_line_begin = nil
37
+ original_encoding = string.encoding
38
+ # Prevent the following error when processing binary encoded source.
39
+ # "\xC0".split # => ArgumentError (invalid byte sequence in UTF-8)
40
+ lines = string.force_encoding(Encoding::BINARY).split("\\\n")
41
+ if lines.length == 1
42
+ # If the line continuation sequence was found but there is no second
43
+ # line, it was not really a line continuation and must be ignored.
44
+ lines = [string.force_encoding(original_encoding)]
45
+ else
46
+ lines.map! {|s| s.force_encoding(original_encoding) }
47
+ end
17
48
 
18
- string.chars.each_with_index do |char, index|
19
- if char == '\\'
20
- # entering escape mode
21
- escape = true
22
- string.slice!(index - offset)
23
- offset += 1
24
- _at_line_begin = @at_line_begin
25
- @at_line_begin = false
26
- elsif escape
27
- if char == ?\n
28
- # trimming \n, starting a new line
29
- string.slice!(index - offset)
30
- offset += 1
31
- @at_line_begin = true
32
- space_begin = space_end = index - offset
33
- @indent_level = 0
34
- elsif char == ?n
35
- # replacing \\n to \n
36
- string.slice!(index - offset)
37
- string.insert(index - offset, ?\n)
38
- else
39
- # exiting escape mode as it's not an escape sequence
40
- @at_line_begin = _at_line_begin
41
- escape = false
42
- redo
43
- end
44
- escape = false
45
- elsif @at_line_begin
46
- if char == ?\n || @indent_level >= @dedent_level
47
- string.slice!(space_begin...space_end)
48
- offset += space_end - space_begin
49
- @at_line_begin = false
50
- end
49
+ if @at_line_begin
50
+ lines_to_dedent = lines
51
+ else
52
+ _first, *lines_to_dedent = lines
53
+ end
54
+
55
+ lines_to_dedent.each do |line|
56
+ left_to_remove = @dedent_level
57
+ remove = 0
51
58
 
59
+ line.each_char do |char|
60
+ break if left_to_remove <= 0
52
61
  case char
53
62
  when ?\s
54
- @indent_level += 1
55
- space_end += 1
63
+ remove += 1
64
+ left_to_remove -= 1
56
65
  when ?\t
57
- @indent_level += 8 - @indent_level % 8
58
- space_end += 1
66
+ break if TAB_WIDTH * (remove / TAB_WIDTH + 1) > @dedent_level
67
+ remove += 1
68
+ left_to_remove -= TAB_WIDTH
69
+ else
70
+ # no more spaces or tabs
71
+ break
59
72
  end
60
- elsif char == ?\n && index == last_index
61
- @at_line_begin = true
62
- @indent_level = 0
63
- space_begin = space_end = index - offset + 1
64
73
  end
65
- end
66
74
 
67
- if @at_line_begin
68
- string.slice!(space_begin..space_end)
75
+ line.slice!(0, remove)
69
76
  end
70
77
 
71
- nil
78
+ string.replace(lines.join)
79
+
80
+ @at_line_begin = string.end_with?("\n")
72
81
  end
73
82
 
74
83
  def interrupt
@@ -18,7 +18,7 @@ module Parser
18
18
  def advance
19
19
  type, (val, range) = advance_before_explanation
20
20
 
21
- more = "(in-kwarg)" if @in_kwarg
21
+ more = "(in-kwarg)" if @context.in_kwarg
22
22
 
23
23
  puts decorate(range,
24
24
  Color.green("#{type} #{val.inspect}"),