rubocop-ast 0.0.2 → 0.0.3

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