rubocop-ast 0.0.1 → 0.3.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 (42) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +23 -4
  3. data/lib/rubocop/ast.rb +10 -7
  4. data/lib/rubocop/ast/builder.rb +6 -1
  5. data/lib/rubocop/ast/ext/range.rb +28 -0
  6. data/lib/rubocop/ast/node.rb +41 -8
  7. data/lib/rubocop/ast/node/array_node.rb +2 -8
  8. data/lib/rubocop/ast/node/break_node.rb +1 -6
  9. data/lib/rubocop/ast/node/case_match_node.rb +3 -9
  10. data/lib/rubocop/ast/node/case_node.rb +13 -9
  11. data/lib/rubocop/ast/node/def_node.rb +5 -24
  12. data/lib/rubocop/ast/node/defined_node.rb +2 -0
  13. data/lib/rubocop/ast/node/float_node.rb +1 -0
  14. data/lib/rubocop/ast/node/forward_args_node.rb +15 -0
  15. data/lib/rubocop/ast/node/hash_node.rb +21 -8
  16. data/lib/rubocop/ast/node/if_node.rb +7 -14
  17. data/lib/rubocop/ast/node/index_node.rb +48 -0
  18. data/lib/rubocop/ast/node/indexasgn_node.rb +50 -0
  19. data/lib/rubocop/ast/node/int_node.rb +1 -0
  20. data/lib/rubocop/ast/node/lambda_node.rb +65 -0
  21. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +2 -8
  22. data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +99 -3
  23. data/lib/rubocop/ast/node/mixin/parameterized_node.rb +56 -0
  24. data/lib/rubocop/ast/node/next_node.rb +12 -0
  25. data/lib/rubocop/ast/node/pair_node.rb +2 -2
  26. data/lib/rubocop/ast/node/regexp_node.rb +61 -2
  27. data/lib/rubocop/ast/node/return_node.rb +1 -13
  28. data/lib/rubocop/ast/node/send_node.rb +9 -2
  29. data/lib/rubocop/ast/node/super_node.rb +2 -0
  30. data/lib/rubocop/ast/node/when_node.rb +3 -9
  31. data/lib/rubocop/ast/node/yield_node.rb +2 -0
  32. data/lib/rubocop/ast/node_pattern.rb +952 -0
  33. data/lib/rubocop/ast/processed_source.rb +246 -0
  34. data/lib/rubocop/ast/token.rb +116 -0
  35. data/lib/rubocop/ast/traversal.rb +5 -3
  36. data/lib/rubocop/ast/version.rb +1 -1
  37. metadata +16 -13
  38. data/lib/rubocop/ast/node/retry_node.rb +0 -17
  39. data/lib/rubocop/error.rb +0 -34
  40. data/lib/rubocop/node_pattern.rb +0 -881
  41. data/lib/rubocop/processed_source.rb +0 -211
  42. data/lib/rubocop/token.rb +0 -114
@@ -1,211 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'digest/sha1'
4
-
5
- module RuboCop
6
- # ProcessedSource contains objects which are generated by Parser
7
- # and other information such as disabled lines for cops.
8
- # It also provides a convenient way to access source lines.
9
- class ProcessedSource
10
- STRING_SOURCE_NAME = '(string)'
11
-
12
- attr_reader :path, :buffer, :ast, :comments, :tokens, :diagnostics,
13
- :parser_error, :raw_source, :ruby_version
14
-
15
- def self.from_file(path, ruby_version)
16
- file = File.read(path, mode: 'rb')
17
- new(file, ruby_version, path)
18
- rescue Errno::ENOENT
19
- raise RuboCop::Error, "No such file or directory: #{path}"
20
- end
21
-
22
- def initialize(source, ruby_version, path = nil)
23
- # Defaults source encoding to UTF-8, regardless of the encoding it has
24
- # been read with, which could be non-utf8 depending on the default
25
- # external encoding.
26
- source.force_encoding(Encoding::UTF_8) unless source.encoding == Encoding::UTF_8
27
-
28
- @raw_source = source
29
- @path = path
30
- @diagnostics = []
31
- @ruby_version = ruby_version
32
- @parser_error = nil
33
-
34
- parse(source, ruby_version)
35
- end
36
-
37
- def comment_config
38
- @comment_config ||= CommentConfig.new(self)
39
- end
40
-
41
- def disabled_line_ranges
42
- comment_config.cop_disabled_line_ranges
43
- end
44
-
45
- def ast_with_comments
46
- return if !ast || !comments
47
-
48
- @ast_with_comments ||= Parser::Source::Comment.associate(ast, comments)
49
- end
50
-
51
- # Returns the source lines, line break characters removed, excluding a
52
- # possible __END__ and everything that comes after.
53
- def lines
54
- @lines ||= begin
55
- all_lines = @buffer.source_lines
56
- last_token_line = tokens.any? ? tokens.last.line : all_lines.size
57
- result = []
58
- all_lines.each_with_index do |line, ix|
59
- break if ix >= last_token_line && line == '__END__'
60
-
61
- result << line
62
- end
63
- result
64
- end
65
- end
66
-
67
- def [](*args)
68
- lines[*args]
69
- end
70
-
71
- def valid_syntax?
72
- return false if @parser_error
73
-
74
- @diagnostics.none? { |d| %i[error fatal].include?(d.level) }
75
- end
76
-
77
- # Raw source checksum for tracking infinite loops.
78
- def checksum
79
- Digest::SHA1.hexdigest(@raw_source)
80
- end
81
-
82
- def each_comment
83
- comments.each { |comment| yield comment }
84
- end
85
-
86
- def find_comment
87
- comments.find { |comment| yield comment }
88
- end
89
-
90
- def each_token
91
- tokens.each { |token| yield token }
92
- end
93
-
94
- def find_token
95
- tokens.find { |token| yield token }
96
- end
97
-
98
- def file_path
99
- buffer.name
100
- end
101
-
102
- def blank?
103
- ast.nil?
104
- end
105
-
106
- def commented?(source_range)
107
- comment_lines.include?(source_range.line)
108
- end
109
-
110
- def comments_before_line(line)
111
- comments.select { |c| c.location.line <= line }
112
- end
113
-
114
- def start_with?(string)
115
- return false if self[0].nil?
116
-
117
- self[0].start_with?(string)
118
- end
119
-
120
- def preceding_line(token)
121
- lines[token.line - 2]
122
- end
123
-
124
- def current_line(token)
125
- lines[token.line - 1]
126
- end
127
-
128
- def following_line(token)
129
- lines[token.line]
130
- end
131
-
132
- def line_indentation(line_number)
133
- lines[line_number - 1]
134
- .match(/^(\s*)/)[1]
135
- .to_s
136
- .length
137
- end
138
-
139
- private
140
-
141
- def comment_lines
142
- @comment_lines ||= comments.map { |c| c.location.line }
143
- end
144
-
145
- def parse(source, ruby_version)
146
- buffer_name = @path || STRING_SOURCE_NAME
147
- @buffer = Parser::Source::Buffer.new(buffer_name, 1)
148
-
149
- begin
150
- @buffer.source = source
151
- rescue EncodingError => e
152
- @parser_error = e
153
- return
154
- end
155
-
156
- @ast, @comments, @tokens = tokenize(create_parser(ruby_version))
157
- end
158
-
159
- def tokenize(parser)
160
- begin
161
- ast, comments, tokens = parser.tokenize(@buffer)
162
-
163
- ast.respond_to?(:complete!) && ast.complete!
164
- rescue Parser::SyntaxError
165
- # All errors are in diagnostics. No need to handle exception.
166
- end
167
-
168
- tokens = tokens.map { |t| Token.from_parser_token(t) } if tokens
169
-
170
- [ast, comments, tokens]
171
- end
172
-
173
- # rubocop:disable Metrics/MethodLength
174
- def parser_class(ruby_version)
175
- case ruby_version
176
- when 2.4
177
- require 'parser/ruby24'
178
- Parser::Ruby24
179
- when 2.5
180
- require 'parser/ruby25'
181
- Parser::Ruby25
182
- when 2.6
183
- require 'parser/ruby26'
184
- Parser::Ruby26
185
- when 2.7
186
- require 'parser/ruby27'
187
- Parser::Ruby27
188
- else
189
- raise ArgumentError,
190
- "RuboCop found unknown Ruby version: #{ruby_version.inspect}"
191
- end
192
- end
193
- # rubocop:enable Metrics/MethodLength
194
-
195
- def create_parser(ruby_version)
196
- builder = RuboCop::AST::Builder.new
197
-
198
- parser_class(ruby_version).new(builder).tap do |parser|
199
- # On JRuby there's a risk that we hang in tokenize() if we
200
- # don't set the all errors as fatal flag. The problem is caused by a bug
201
- # in Racc that is discussed in issue #93 of the whitequark/parser
202
- # project on GitHub.
203
- parser.diagnostics.all_errors_are_fatal = (RUBY_ENGINE != 'ruby')
204
- parser.diagnostics.ignore_warnings = false
205
- parser.diagnostics.consumer = lambda do |diagnostic|
206
- @diagnostics << diagnostic
207
- end
208
- end
209
- end
210
- end
211
- end
@@ -1,114 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module RuboCop
4
- # A basic wrapper around Parser's tokens.
5
- class Token
6
- attr_reader :pos, :type, :text
7
-
8
- def self.from_parser_token(parser_token)
9
- type, details = parser_token
10
- text, range = details
11
- new(range, type, text)
12
- end
13
-
14
- def initialize(pos, type, text)
15
- @pos = pos
16
- @type = type
17
- # Parser token "text" may be an Integer
18
- @text = text.to_s
19
- end
20
-
21
- def line
22
- @pos.line
23
- end
24
-
25
- def column
26
- @pos.column
27
- end
28
-
29
- def begin_pos
30
- @pos.begin_pos
31
- end
32
-
33
- def end_pos
34
- @pos.end_pos
35
- end
36
-
37
- def to_s
38
- "[[#{line}, #{column}], #{type}, #{text.inspect}]"
39
- end
40
-
41
- # Checks if there is whitespace after token
42
- def space_after?
43
- pos.source_buffer.source.match(/\G\s/, end_pos)
44
- end
45
-
46
- # Checks if there is whitespace before token
47
- def space_before?
48
- position = begin_pos.zero? ? begin_pos : begin_pos - 1
49
- pos.source_buffer.source.match(/\G\s/, position)
50
- end
51
-
52
- ## Type Predicates
53
-
54
- def comment?
55
- type == :tCOMMENT
56
- end
57
-
58
- def semicolon?
59
- type == :tSEMI
60
- end
61
-
62
- def left_array_bracket?
63
- type == :tLBRACK
64
- end
65
-
66
- def left_ref_bracket?
67
- type == :tLBRACK2
68
- end
69
-
70
- def left_bracket?
71
- %i[tLBRACK tLBRACK2].include?(type)
72
- end
73
-
74
- def right_bracket?
75
- type == :tRBRACK
76
- end
77
-
78
- def left_brace?
79
- type == :tLBRACE
80
- end
81
-
82
- def left_curly_brace?
83
- type == :tLCURLY
84
- end
85
-
86
- def right_curly_brace?
87
- type == :tRCURLY
88
- end
89
-
90
- def left_parens?
91
- %i[tLPAREN tLPAREN2].include?(type)
92
- end
93
-
94
- def right_parens?
95
- type == :tRPAREN
96
- end
97
-
98
- def comma?
99
- type == :tCOMMA
100
- end
101
-
102
- def rescue_modifier?
103
- type == :kRESCUE_MOD
104
- end
105
-
106
- def end?
107
- type == :kEND
108
- end
109
-
110
- def equal_sign?
111
- %i[tEQL tOP_ASGN].include?(type)
112
- end
113
- end
114
- end