haml_lint 0.62.0 → 0.64.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/lib/haml_lint/document.rb +5 -0
- data/lib/haml_lint/linter/rubocop.rb +87 -66
- data/lib/haml_lint/runner.rb +1 -0
- data/lib/haml_lint/source.rb +5 -0
- data/lib/haml_lint/utils.rb +0 -28
- data/lib/haml_lint/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 73a515adb6ca4915d07c747133e7a657e04bd8d6a5c41cf5cd63a0adf3e03316
|
4
|
+
data.tar.gz: efb5d688d181d7906a28bef3f25b1080e1e38e2461d9343db554ed5a98037296
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7a6c42a2be6709314fb8bff476e8a0ff80f0054895eeaa795b8fd741039a580bfb6ced6b0a45b293cdbe0641676a412909363b99f3638a5f8f4f5dd910de736a
|
7
|
+
data.tar.gz: 7165be1ef28719e4a08ad60a26aa6d0a8f8e1ca0507c5376cbfa776e813320fbb3fbd4357c7d74809393cd9c676ca009bab3d8d36b48770de7ffda4c680ed3a2
|
data/lib/haml_lint/document.rb
CHANGED
@@ -14,6 +14,9 @@ module HamlLint
|
|
14
14
|
# @return [String] Haml template file path
|
15
15
|
attr_reader :file
|
16
16
|
|
17
|
+
# @return [Boolean] true if source was read directly from `file` on-disk (rather than from stdin)
|
18
|
+
attr_reader :file_on_disk
|
19
|
+
|
17
20
|
# @return [Boolean] true if source changes (from autocorrect) should be written to stdout instead of disk
|
18
21
|
attr_reader :write_to_stdout
|
19
22
|
|
@@ -39,12 +42,14 @@ module HamlLint
|
|
39
42
|
# @param source [String] Haml code to parse
|
40
43
|
# @param options [Hash]
|
41
44
|
# @option options :file [String] file name of document that was parsed
|
45
|
+
# @option options :file_on_disk [Boolean] true if source was read straight from `file` on disk
|
42
46
|
# @option options :write_to_stdout [Boolean] true if source changes should be written to stdout
|
43
47
|
# @raise [Haml::Parser::Error] if there was a problem parsing the document
|
44
48
|
def initialize(source, options)
|
45
49
|
@config = options[:config]
|
46
50
|
@file = options.fetch(:file, STRING_SOURCE)
|
47
51
|
@write_to_stdout = options[:write_to_stdout]
|
52
|
+
@file_on_disk = options[:file_on_disk] && @file != STRING_SOURCE
|
48
53
|
@source_was_changed = false
|
49
54
|
process_source(source)
|
50
55
|
end
|
@@ -16,6 +16,46 @@ module HamlLint
|
|
16
16
|
#
|
17
17
|
# The work is spread across the classes in the HamlLint::RubyExtraction module.
|
18
18
|
class Linter::RuboCop < Linter
|
19
|
+
# Processes a ruby file and reports RuboCop offenses
|
20
|
+
class Runner < ::RuboCop::Runner
|
21
|
+
attr_reader :offenses
|
22
|
+
|
23
|
+
def run(haml_path, ruby_code, config:, allow_cache: false)
|
24
|
+
@allow_cache = allow_cache
|
25
|
+
@offenses = []
|
26
|
+
@config_store.instance_variable_set(:@options_config, config)
|
27
|
+
@options[:stdin] = ruby_code
|
28
|
+
super([haml_path])
|
29
|
+
end
|
30
|
+
|
31
|
+
def corrected_code
|
32
|
+
@options[:stdin]
|
33
|
+
end
|
34
|
+
|
35
|
+
# Executed when a file has been scanned by RuboCop, adding the reported
|
36
|
+
# offenses to our collection.
|
37
|
+
#
|
38
|
+
# @param _file [String]
|
39
|
+
# @param offenses [Array<RuboCop::Cop::Offense>]
|
40
|
+
def file_finished(_file, offenses)
|
41
|
+
@offenses = offenses
|
42
|
+
end
|
43
|
+
|
44
|
+
# RuboCop caches results by taking a hash of the file contents & path, among other things.
|
45
|
+
# It disables its cache when working on file-content from stdin.
|
46
|
+
# Unfortunately we always use RuboCop's stdin, even when we're linting a file on-disk.
|
47
|
+
# So, override RuboCop::Runner#cached_run? so that it'll allow caching results, so long
|
48
|
+
# as haml-lint itself isn't being invoked with files on stdin.
|
49
|
+
def cached_run?
|
50
|
+
return false unless @allow_cache
|
51
|
+
|
52
|
+
@cached_run ||=
|
53
|
+
(@options[:cache] == 'true' ||
|
54
|
+
(@options[:cache] != 'false' && @config_store.for_pwd.for_all_cops['UseCache'])) &&
|
55
|
+
!@options[:auto_gen_config]
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
19
59
|
include LinterRegistry
|
20
60
|
|
21
61
|
supports_autocorrect(true)
|
@@ -98,9 +138,9 @@ module HamlLint
|
|
98
138
|
|
99
139
|
def rubocop_config_for(path)
|
100
140
|
user_config_path = ENV['HAML_LINT_RUBOCOP_CONF'] || config['config_file']
|
101
|
-
user_config_path ||=
|
141
|
+
user_config_path ||= rubocop_config_store.user_rubocop_config_path_for(path)
|
102
142
|
user_config_path = File.absolute_path(user_config_path)
|
103
|
-
|
143
|
+
rubocop_config_store.config_object_pointing_to(user_config_path)
|
104
144
|
end
|
105
145
|
|
106
146
|
# Extracted here so that tests can stub this to always return true
|
@@ -168,15 +208,13 @@ module HamlLint
|
|
168
208
|
false
|
169
209
|
end
|
170
210
|
|
171
|
-
# A single
|
211
|
+
# A single RuboCop runner is shared between files to avoid RuboCop
|
172
212
|
# having to repeatedly reload .rubocop.yml.
|
173
|
-
def
|
174
|
-
|
175
|
-
# because it can't be Marshal.dump'd (as used by Parallel.map)
|
176
|
-
@rubocop_cli ||= ::RuboCop::CLI.new
|
213
|
+
def rubocop_runner
|
214
|
+
@rubocop_runner ||= Runner.new(rubocop_options, ::RuboCop::ConfigStore.new)
|
177
215
|
end
|
178
216
|
|
179
|
-
def
|
217
|
+
def rubocop_config_store
|
180
218
|
@rubocop_config_store ||= RubocopConfigStore.new
|
181
219
|
end
|
182
220
|
|
@@ -190,7 +228,7 @@ module HamlLint
|
|
190
228
|
def process_ruby_source(ruby_code, source_map)
|
191
229
|
filename = document.file || 'ruby_script.rb'
|
192
230
|
|
193
|
-
offenses, corrected_ruby = run_rubocop(
|
231
|
+
offenses, corrected_ruby = run_rubocop(rubocop_runner, ruby_code, filename)
|
194
232
|
|
195
233
|
extract_lints_from_offenses(offenses, source_map)
|
196
234
|
corrected_ruby
|
@@ -199,55 +237,35 @@ module HamlLint
|
|
199
237
|
# Runs RuboCop, returning the offenses and corrected code. Raises when RuboCop
|
200
238
|
# fails to run correctly.
|
201
239
|
#
|
202
|
-
# @param
|
240
|
+
# @param rubocop_runner [HamlLint::Linter::RuboCop::Runner] There to simplify tests by using a stub
|
203
241
|
# @param ruby_code [String] The ruby code to run through RuboCop
|
204
242
|
# @param path [String] the path to tell RuboCop we are running
|
205
243
|
# @return [Array<RuboCop::Cop::Offense>, String]
|
206
|
-
def run_rubocop(
|
207
|
-
|
208
|
-
stdout_str, stderr_str = HamlLint::Utils.with_captured_streams(ruby_code) do
|
209
|
-
rubocop_cli.config_store.instance_variable_set(:@options_config, rubocop_config_for(path))
|
210
|
-
rubocop_status = rubocop_cli.run(rubocop_flags + ['--stdin', path])
|
211
|
-
end
|
244
|
+
def run_rubocop(rubocop_runner, ruby_code, path) # rubocop:disable Metrics
|
245
|
+
rubocop_runner.run(path, ruby_code, config: rubocop_config_for(path), allow_cache: @document&.file_on_disk)
|
212
246
|
|
213
247
|
if ENV['HAML_LINT_INTERNAL_DEBUG'] == 'true'
|
214
|
-
if
|
248
|
+
if rubocop_runner.offenses.empty?
|
215
249
|
puts "------ No lints found by RuboCop in #{@document.file}"
|
216
250
|
else
|
217
251
|
puts "------ Raw lints found by RuboCop in #{@document.file}"
|
218
|
-
|
252
|
+
rubocop_runner.offenses.each do |offense|
|
219
253
|
puts offense
|
220
254
|
end
|
221
255
|
puts '------'
|
222
256
|
end
|
223
257
|
end
|
224
258
|
|
225
|
-
unless [::RuboCop::CLI::STATUS_SUCCESS, ::RuboCop::CLI::STATUS_OFFENSES].include?(rubocop_status)
|
226
|
-
if stderr_str.start_with?('Infinite loop')
|
227
|
-
msg = "RuboCop exited unsuccessfully with status #{rubocop_status}." \
|
228
|
-
' This appears to be due to an autocorrection infinite loop.'
|
229
|
-
if ENV['HAML_LINT_DEBUG'] == 'true'
|
230
|
-
msg += " DEBUG: RuboCop's output:\n"
|
231
|
-
msg += stderr_str.strip
|
232
|
-
else
|
233
|
-
msg += " First line of RuboCop's output (Use --debug mode to see more):\n"
|
234
|
-
msg += stderr_str.each_line.first.strip
|
235
|
-
end
|
236
|
-
|
237
|
-
raise HamlLint::Exceptions::InfiniteLoopError, msg
|
238
|
-
end
|
239
|
-
|
240
|
-
raise HamlLint::Exceptions::ConfigurationError,
|
241
|
-
"RuboCop exited unsuccessfully with status #{rubocop_status}." \
|
242
|
-
' Here is its output to check the stack trace or see if there was' \
|
243
|
-
" a misconfiguration:\n#{stderr_str}"
|
244
|
-
end
|
245
|
-
|
246
259
|
if @autocorrect
|
247
|
-
corrected_ruby =
|
260
|
+
corrected_ruby = rubocop_runner.corrected_code
|
248
261
|
end
|
249
262
|
|
250
|
-
[
|
263
|
+
[rubocop_runner.offenses, corrected_ruby]
|
264
|
+
rescue ::RuboCop::Error => e
|
265
|
+
raise HamlLint::Exceptions::ConfigurationError,
|
266
|
+
"RuboCop raised #{e}." \
|
267
|
+
' Here is its output to check the stack trace or see if there was' \
|
268
|
+
" a misconfiguration:\n#{e.message}\n#{e.backtrace}"
|
251
269
|
end
|
252
270
|
|
253
271
|
# Aggregates RuboCop offenses and converts them to {HamlLint::Lint}s
|
@@ -294,14 +312,27 @@ module HamlLint
|
|
294
312
|
corrected: corrected)
|
295
313
|
end
|
296
314
|
|
297
|
-
#
|
315
|
+
# rubocop:disable Style/MutableConstant
|
316
|
+
# Using BaseFormatter suppresses any default output
|
317
|
+
DEFAULT_FLAGS = %w[--format RuboCop::Formatter::BaseFormatter]
|
318
|
+
begin
|
319
|
+
::RuboCop::Options.new.parse(['--raise-cop-error'])
|
320
|
+
DEFAULT_FLAGS << '--raise-cop-error'
|
321
|
+
rescue OptionParser::InvalidOption
|
322
|
+
# older versions of RuboCop don't support this flag
|
323
|
+
end
|
324
|
+
DEFAULT_FLAGS.freeze
|
325
|
+
# rubocop:enable Style/MutableConstant
|
326
|
+
|
327
|
+
# Returns options that will be passed to the RuboCop runner.
|
298
328
|
#
|
299
|
-
# @return [
|
300
|
-
def
|
301
|
-
flags =
|
329
|
+
# @return [Hash]
|
330
|
+
def rubocop_options
|
331
|
+
flags = DEFAULT_FLAGS
|
302
332
|
flags += ignored_cops_flags
|
303
333
|
flags += rubocop_autocorrect_flags
|
304
|
-
flags
|
334
|
+
options, _args = ::RuboCop::Options.new.parse(flags)
|
335
|
+
options
|
305
336
|
end
|
306
337
|
|
307
338
|
def rubocop_autocorrect_flags
|
@@ -342,29 +373,19 @@ module HamlLint
|
|
342
373
|
return [] if ignored_cops.empty?
|
343
374
|
['--except', ignored_cops.uniq.join(',')]
|
344
375
|
end
|
345
|
-
end
|
346
376
|
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
353
|
-
|
354
|
-
# Executed when RuboCop begins linting.
|
355
|
-
#
|
356
|
-
# @param _target_files [Array<String>]
|
357
|
-
def started(_target_files)
|
358
|
-
self.class.offenses = []
|
377
|
+
# Exclude ivars that don't marshal properly
|
378
|
+
def marshal_dump
|
379
|
+
excluded_ivars = %i[@rubocop_runner @rubocop_config_store @user_config_path_to_config_object]
|
380
|
+
(instance_variables - excluded_ivars).to_h do |ivar|
|
381
|
+
[ivar, instance_variable_get(ivar)]
|
382
|
+
end
|
359
383
|
end
|
360
384
|
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
# @param offenses [Array<RuboCop::Cop::Offense>]
|
366
|
-
def file_finished(_file, offenses)
|
367
|
-
self.class.offenses += offenses
|
385
|
+
def marshal_load(ivars)
|
386
|
+
ivars.each do |k, v|
|
387
|
+
instance_variable_set(k, v)
|
388
|
+
end
|
368
389
|
end
|
369
390
|
end
|
370
391
|
|
data/lib/haml_lint/runner.rb
CHANGED
@@ -89,6 +89,7 @@ module HamlLint
|
|
89
89
|
begin
|
90
90
|
document = HamlLint::Document.new source.contents, file: source.path,
|
91
91
|
config: config,
|
92
|
+
file_on_disk: !source.stdin?,
|
92
93
|
write_to_stdout: @autocorrect_stdout
|
93
94
|
rescue HamlLint::Exceptions::ParseError => e
|
94
95
|
return [HamlLint::Lint.new(HamlLint::Linter::Syntax.new(config), source.path,
|
data/lib/haml_lint/source.rb
CHANGED
data/lib/haml_lint/utils.rb
CHANGED
@@ -249,34 +249,6 @@ module HamlLint
|
|
249
249
|
$!
|
250
250
|
end
|
251
251
|
|
252
|
-
# Overrides the global stdin, stdout and stderr while within the block, to
|
253
|
-
# push a string in stdin, and capture both stdout and stderr which are returned.
|
254
|
-
#
|
255
|
-
# @param stdin_str [String] the string to push in as stdin
|
256
|
-
# @param _block [Block] the block to perform with the overridden std streams
|
257
|
-
# @return [String, String]
|
258
|
-
def with_captured_streams(stdin_str, &_block)
|
259
|
-
original_stdin = $stdin
|
260
|
-
# The dup is needed so that stdin_data isn't altered (encoding-wise at least)
|
261
|
-
$stdin = StringIO.new(stdin_str.dup)
|
262
|
-
begin
|
263
|
-
original_stdout = $stdout
|
264
|
-
$stdout = StringIO.new
|
265
|
-
begin
|
266
|
-
original_stderr = $stderr
|
267
|
-
$stderr = StringIO.new
|
268
|
-
yield
|
269
|
-
[$stdout.string, $stderr.string]
|
270
|
-
ensure
|
271
|
-
$stderr = original_stderr
|
272
|
-
end
|
273
|
-
ensure
|
274
|
-
$stdout = original_stdout
|
275
|
-
end
|
276
|
-
ensure
|
277
|
-
$stdin = original_stdin
|
278
|
-
end
|
279
|
-
|
280
252
|
def regexp_for_parts(parts, join_regexp, prefix: nil, suffix: nil)
|
281
253
|
regexp_code = parts.map { |c| Regexp.quote(c) }.join(join_regexp)
|
282
254
|
regexp_code = "#{prefix}#{regexp_code}#{suffix}"
|
data/lib/haml_lint/version.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: haml_lint
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.64.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Shane da Silva
|
8
8
|
bindir: bin
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-06-29 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: haml
|