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.
- checksums.yaml +4 -4
- data/README.md +23 -4
- data/lib/rubocop/ast.rb +10 -7
- data/lib/rubocop/ast/builder.rb +6 -1
- data/lib/rubocop/ast/ext/range.rb +28 -0
- data/lib/rubocop/ast/node.rb +41 -8
- data/lib/rubocop/ast/node/array_node.rb +2 -8
- data/lib/rubocop/ast/node/break_node.rb +1 -6
- data/lib/rubocop/ast/node/case_match_node.rb +3 -9
- data/lib/rubocop/ast/node/case_node.rb +13 -9
- data/lib/rubocop/ast/node/def_node.rb +5 -24
- data/lib/rubocop/ast/node/defined_node.rb +2 -0
- data/lib/rubocop/ast/node/float_node.rb +1 -0
- data/lib/rubocop/ast/node/forward_args_node.rb +15 -0
- data/lib/rubocop/ast/node/hash_node.rb +21 -8
- data/lib/rubocop/ast/node/if_node.rb +7 -14
- data/lib/rubocop/ast/node/index_node.rb +48 -0
- data/lib/rubocop/ast/node/indexasgn_node.rb +50 -0
- data/lib/rubocop/ast/node/int_node.rb +1 -0
- data/lib/rubocop/ast/node/lambda_node.rb +65 -0
- data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +2 -8
- data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +99 -3
- data/lib/rubocop/ast/node/mixin/parameterized_node.rb +56 -0
- data/lib/rubocop/ast/node/next_node.rb +12 -0
- data/lib/rubocop/ast/node/pair_node.rb +2 -2
- data/lib/rubocop/ast/node/regexp_node.rb +61 -2
- data/lib/rubocop/ast/node/return_node.rb +1 -13
- data/lib/rubocop/ast/node/send_node.rb +9 -2
- data/lib/rubocop/ast/node/super_node.rb +2 -0
- data/lib/rubocop/ast/node/when_node.rb +3 -9
- data/lib/rubocop/ast/node/yield_node.rb +2 -0
- data/lib/rubocop/ast/node_pattern.rb +952 -0
- data/lib/rubocop/ast/processed_source.rb +246 -0
- data/lib/rubocop/ast/token.rb +116 -0
- data/lib/rubocop/ast/traversal.rb +5 -3
- data/lib/rubocop/ast/version.rb +1 -1
- metadata +16 -13
- data/lib/rubocop/ast/node/retry_node.rb +0 -17
- data/lib/rubocop/error.rb +0 -34
- data/lib/rubocop/node_pattern.rb +0 -881
- data/lib/rubocop/processed_source.rb +0 -211
- 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
|
data/lib/rubocop/token.rb
DELETED
@@ -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
|