parser 2.6.0.0 → 3.1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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}"),