slim_lint 0.2.0 → 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/bin/slim-lint +0 -1
- data/lib/slim_lint/atom.rb +91 -0
- data/lib/slim_lint/capture_map.rb +17 -0
- data/lib/slim_lint/cli.rb +25 -8
- data/lib/slim_lint/configuration.rb +38 -31
- data/lib/slim_lint/configuration_loader.rb +21 -5
- data/lib/slim_lint/document.rb +20 -4
- data/lib/slim_lint/engine.rb +6 -0
- data/lib/slim_lint/file_finder.rb +13 -4
- data/lib/slim_lint/filters/inject_line_numbers.rb +7 -2
- data/lib/slim_lint/filters/sexp_converter.rb +4 -0
- data/lib/slim_lint/lint.rb +17 -1
- data/lib/slim_lint/linter/comment_control_statement.rb +2 -2
- data/lib/slim_lint/linter/consecutive_control_statements.rb +1 -16
- data/lib/slim_lint/linter/empty_control_statement.rb +1 -1
- data/lib/slim_lint/linter/redundant_div.rb +8 -5
- data/lib/slim_lint/linter/rubocop.rb +40 -18
- data/lib/slim_lint/linter/tag_case.rb +1 -1
- data/lib/slim_lint/linter.rb +19 -6
- data/lib/slim_lint/linter_registry.rb +13 -2
- data/lib/slim_lint/linter_selector.rb +74 -0
- data/lib/slim_lint/logger.rb +5 -9
- data/lib/slim_lint/matcher/anything.rb +9 -0
- data/lib/slim_lint/matcher/base.rb +19 -0
- data/lib/slim_lint/matcher/capture.rb +30 -0
- data/lib/slim_lint/matcher/nothing.rb +11 -0
- data/lib/slim_lint/options.rb +16 -6
- data/lib/slim_lint/rake_task.rb +15 -0
- data/lib/slim_lint/report.rb +7 -0
- data/lib/slim_lint/reporter/default_reporter.rb +2 -2
- data/lib/slim_lint/reporter/json_reporter.rb +15 -10
- data/lib/slim_lint/reporter.rb +17 -11
- data/lib/slim_lint/ruby_extractor.rb +2 -0
- data/lib/slim_lint/runner.rb +43 -39
- data/lib/slim_lint/sexp.rb +43 -30
- data/lib/slim_lint/sexp_visitor.rb +66 -28
- data/lib/slim_lint/utils.rb +17 -0
- data/lib/slim_lint/version.rb +1 -1
- data/lib/slim_lint.rb +10 -1
- metadata +10 -3
@@ -14,12 +14,18 @@ module SlimLint
|
|
14
14
|
extractor = SlimLint::RubyExtractor.new
|
15
15
|
extracted_ruby = extractor.extract(processed_sexp)
|
16
16
|
|
17
|
-
find_lints(
|
17
|
+
find_lints(extracted_ruby, extractor.source_map) unless extracted_ruby.empty?
|
18
18
|
end
|
19
19
|
|
20
20
|
private
|
21
21
|
|
22
|
-
|
22
|
+
# Executes RuboCop against the given Ruby code and records the offenses as
|
23
|
+
# lints.
|
24
|
+
#
|
25
|
+
# @param ruby [String] Ruby code
|
26
|
+
# @param source_map [Hash] map of Ruby code line numbers to original line
|
27
|
+
# numbers in the template
|
28
|
+
def find_lints(ruby, source_map)
|
23
29
|
rubocop = ::RuboCop::CLI.new
|
24
30
|
|
25
31
|
original_filename = document.file || 'ruby_script'
|
@@ -30,7 +36,7 @@ module SlimLint
|
|
30
36
|
begin
|
31
37
|
f.write(ruby)
|
32
38
|
f.close
|
33
|
-
|
39
|
+
extract_lints_from_offenses(lint_file(rubocop, f.path), source_map)
|
34
40
|
ensure
|
35
41
|
f.unlink
|
36
42
|
end
|
@@ -38,36 +44,52 @@ module SlimLint
|
|
38
44
|
end
|
39
45
|
|
40
46
|
# Defined so we can stub the results in tests
|
47
|
+
#
|
48
|
+
# @param rubocop [RuboCop::CLI]
|
49
|
+
# @param file [String]
|
50
|
+
# @return [Array<RuboCop::Cop::Offense>]
|
41
51
|
def lint_file(rubocop, file)
|
42
|
-
rubocop.run(%w[--format SlimLint::
|
43
|
-
|
52
|
+
rubocop.run(%w[--format SlimLint::OffenseCollector] << file)
|
53
|
+
OffenseCollector.offenses
|
44
54
|
end
|
45
55
|
|
46
|
-
|
47
|
-
|
48
|
-
|
56
|
+
# Aggregates RuboCop offenses and converts them to {SlimLint::Lint}s
|
57
|
+
# suitable for reporting.
|
58
|
+
#
|
59
|
+
# @param offenses [Array<RuboCop::Cop::Offense>]
|
60
|
+
# @param source_map [Hash]
|
61
|
+
def extract_lints_from_offenses(offenses, source_map)
|
62
|
+
offenses.select { |offense| !config['ignored_cops'].include?(offense.cop_name) }
|
63
|
+
.each do |offense|
|
49
64
|
@lints << Lint.new(self,
|
50
65
|
document.file,
|
51
|
-
|
52
|
-
"#{
|
66
|
+
source_map[offense.line],
|
67
|
+
"#{offense.cop_name}: #{offense.message}")
|
53
68
|
end
|
54
69
|
end
|
55
70
|
end
|
56
71
|
|
57
|
-
# Collects
|
58
|
-
class
|
59
|
-
attr_accessor :offences
|
60
|
-
|
72
|
+
# Collects offenses detected by RuboCop.
|
73
|
+
class OffenseCollector < ::RuboCop::Formatter::BaseFormatter
|
61
74
|
class << self
|
62
|
-
|
75
|
+
# List of offenses reported by RuboCop.
|
76
|
+
attr_accessor :offenses
|
63
77
|
end
|
64
78
|
|
79
|
+
# Executed when RuboCop begins linting.
|
80
|
+
#
|
81
|
+
# @param _target_files [Array<String>]
|
65
82
|
def started(_target_files)
|
66
|
-
self.class.
|
83
|
+
self.class.offenses = []
|
67
84
|
end
|
68
85
|
|
69
|
-
|
70
|
-
|
86
|
+
# Executed when a file has been scanned by RuboCop, adding the reported
|
87
|
+
# offenses to our collection.
|
88
|
+
#
|
89
|
+
# @param _file [String]
|
90
|
+
# @param offenses [Array<RuboCop::Cop::Offense>]
|
91
|
+
def file_finished(_file, offenses)
|
92
|
+
self.class.offenses += offenses
|
71
93
|
end
|
72
94
|
end
|
73
95
|
end
|
data/lib/slim_lint/linter.rb
CHANGED
@@ -1,22 +1,29 @@
|
|
1
1
|
module SlimLint
|
2
2
|
# Base implementation for all lint checks.
|
3
|
+
#
|
4
|
+
# @abstract
|
3
5
|
class Linter
|
4
6
|
# Include definitions for Sexp pattern-matching helpers.
|
5
7
|
include SexpVisitor
|
6
8
|
extend SexpVisitor::DSL
|
7
9
|
|
8
|
-
#
|
9
|
-
#
|
10
|
+
# List of lints reported by this linter.
|
11
|
+
#
|
12
|
+
# @todo Remove once spec/support/shared_linter_context returns an array of
|
13
|
+
# lints for the subject instead of the linter itself.
|
10
14
|
attr_reader :lints
|
11
15
|
|
16
|
+
# Initializes a linter with the specified configuration.
|
17
|
+
#
|
12
18
|
# @param config [Hash] configuration for this linter
|
13
19
|
def initialize(config)
|
14
20
|
@config = config
|
15
21
|
@lints = []
|
16
|
-
@ruby_parser = nil
|
17
22
|
end
|
18
23
|
|
19
|
-
# Runs the linter against the
|
24
|
+
# Runs the linter against the given Slim document.
|
25
|
+
#
|
26
|
+
# @param document [SlimLint::Document]
|
20
27
|
def run(document)
|
21
28
|
@document = document
|
22
29
|
@lints = []
|
@@ -25,6 +32,8 @@ module SlimLint
|
|
25
32
|
end
|
26
33
|
|
27
34
|
# Returns the simple name for this linter.
|
35
|
+
#
|
36
|
+
# @return [String]
|
28
37
|
def name
|
29
38
|
self.class.name.split('::').last
|
30
39
|
end
|
@@ -34,12 +43,16 @@ module SlimLint
|
|
34
43
|
attr_reader :config, :document
|
35
44
|
|
36
45
|
# Record a lint for reporting back to the user.
|
37
|
-
|
38
|
-
|
46
|
+
#
|
47
|
+
# @param node [#line] node to extract the line number from
|
48
|
+
# @param message [String] error/warning to display to the user
|
49
|
+
def report_lint(node, message)
|
50
|
+
@lints << SlimLint::Lint.new(self, @document.file, node.line, message)
|
39
51
|
end
|
40
52
|
|
41
53
|
# Parse Ruby code into an abstract syntax tree.
|
42
54
|
#
|
55
|
+
# @param source [String] Ruby code to parse
|
43
56
|
# @return [AST::Node]
|
44
57
|
def parse_ruby(source)
|
45
58
|
@ruby_parser ||= SlimLint::RubyParser.new
|
@@ -6,12 +6,23 @@ module SlimLint
|
|
6
6
|
@linters = []
|
7
7
|
|
8
8
|
class << self
|
9
|
+
# List of all registered linters.
|
9
10
|
attr_reader :linters
|
10
11
|
|
11
|
-
|
12
|
-
|
12
|
+
# Executed when a linter includes the {LinterRegistry} module.
|
13
|
+
#
|
14
|
+
# This results in the linter being registered with the registry.
|
15
|
+
#
|
16
|
+
# @param subclass [Class]
|
17
|
+
def included(subclass)
|
18
|
+
@linters << subclass
|
13
19
|
end
|
14
20
|
|
21
|
+
# Return a list of {SlimLint::Linter} {Class}es corresponding to the
|
22
|
+
# specified list of names.
|
23
|
+
#
|
24
|
+
# @param linter_names [Array<String>]
|
25
|
+
# @return [Array<Class>]
|
15
26
|
def extract_linters_from(linter_names)
|
16
27
|
linter_names.map do |linter_name|
|
17
28
|
begin
|
@@ -0,0 +1,74 @@
|
|
1
|
+
module SlimLint
|
2
|
+
# Chooses the appropriate linters to run given the specified configuration.
|
3
|
+
class LinterSelector
|
4
|
+
# Creates a selector using the given configuration and additional options.
|
5
|
+
def initialize(config, options)
|
6
|
+
@config = config
|
7
|
+
@options = options
|
8
|
+
end
|
9
|
+
|
10
|
+
# Returns the set of linters to run against the given file.
|
11
|
+
#
|
12
|
+
# @param file [String]
|
13
|
+
# @raise [SlimLint::Exceptions::NoLintersError] when no linters are enabled
|
14
|
+
# @return [Array<SlimLint::Linter>]
|
15
|
+
def linters_for_file(file)
|
16
|
+
@linters ||= extract_enabled_linters(@config, @options)
|
17
|
+
@linters.select { |linter| run_linter_on_file?(@config, linter, file) }
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
# Returns a list of linters that are enabled given the specified
|
23
|
+
# configuration and additional options.
|
24
|
+
#
|
25
|
+
# @param config [SlimLint::Configuration]
|
26
|
+
# @param options [Hash]
|
27
|
+
# @return [Array<SlimLint::Linter>]
|
28
|
+
def extract_enabled_linters(config, options)
|
29
|
+
included_linters = LinterRegistry
|
30
|
+
.extract_linters_from(options.fetch(:included_linters, []))
|
31
|
+
|
32
|
+
included_linters = LinterRegistry.linters if included_linters.empty?
|
33
|
+
|
34
|
+
excluded_linters = LinterRegistry
|
35
|
+
.extract_linters_from(options.fetch(:excluded_linters, []))
|
36
|
+
|
37
|
+
# After filtering out explicitly included/excluded linters, only include
|
38
|
+
# linters which are enabled in the configuration
|
39
|
+
linters = (included_linters - excluded_linters).map do |linter_class|
|
40
|
+
linter_config = config.for_linter(linter_class)
|
41
|
+
linter_class.new(linter_config) if linter_config['enabled']
|
42
|
+
end.compact
|
43
|
+
|
44
|
+
# Highlight condition where all linters were filtered out, as this was
|
45
|
+
# likely a mistake on the user's part
|
46
|
+
if linters.empty?
|
47
|
+
raise SlimLint::Exceptions::NoLintersError, 'No linters specified'
|
48
|
+
end
|
49
|
+
|
50
|
+
linters
|
51
|
+
end
|
52
|
+
|
53
|
+
# Whether to run the given linter against the specified file.
|
54
|
+
#
|
55
|
+
# @param config [SlimLint::Configuration]
|
56
|
+
# @param linter [SlimLint::Linter]
|
57
|
+
# @param file [String]
|
58
|
+
# @return [Boolean]
|
59
|
+
def run_linter_on_file?(config, linter, file)
|
60
|
+
linter_config = config.for_linter(linter)
|
61
|
+
|
62
|
+
if linter_config['include'].any? &&
|
63
|
+
!SlimLint::Utils.any_glob_matches?(linter_config['include'], file)
|
64
|
+
return false
|
65
|
+
end
|
66
|
+
|
67
|
+
if SlimLint::Utils.any_glob_matches?(linter_config['exclude'], file)
|
68
|
+
return false
|
69
|
+
end
|
70
|
+
|
71
|
+
true
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
data/lib/slim_lint/logger.rb
CHANGED
@@ -73,15 +73,6 @@ module SlimLint
|
|
73
73
|
color(33, *args)
|
74
74
|
end
|
75
75
|
|
76
|
-
# Print specified output in bold face in a color indicative of a warning.
|
77
|
-
# If output destination is not a TTY, behaves the same as {#log}.
|
78
|
-
#
|
79
|
-
# @param args [Array<String>]
|
80
|
-
# @return [nil]
|
81
|
-
def bold_warning(*args)
|
82
|
-
color('1;33', *args)
|
83
|
-
end
|
84
|
-
|
85
76
|
# Print the specified output in a color indicating information.
|
86
77
|
# If output destination is not a TTY, behaves the same as {#log}.
|
87
78
|
#
|
@@ -100,6 +91,11 @@ module SlimLint
|
|
100
91
|
|
101
92
|
private
|
102
93
|
|
94
|
+
# Print output in the specified color.
|
95
|
+
#
|
96
|
+
# @param code [Integer,String] ANSI color code
|
97
|
+
# @param output [String] output to print
|
98
|
+
# @param newline [Boolean] whether to append a newline
|
103
99
|
def color(code, output, newline = true)
|
104
100
|
log(color_enabled ? "\033[#{code}m#{output}\033[0m" : output, newline)
|
105
101
|
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module SlimLint::Matcher
|
2
|
+
# Represents a Sexp pattern implementing complex matching logic.
|
3
|
+
#
|
4
|
+
# Subclasses can implement custom logic to create complex matches that can be
|
5
|
+
# reused across linters, DRYing up matching code.
|
6
|
+
#
|
7
|
+
# @abstract
|
8
|
+
class Base
|
9
|
+
# Whether this matcher matches the specified object.
|
10
|
+
#
|
11
|
+
# This must be implemented by subclasses.
|
12
|
+
#
|
13
|
+
# @param other [Object]
|
14
|
+
# @return [Boolean]
|
15
|
+
def match?(*)
|
16
|
+
raise NotImplementedError, 'Matcher must implement `match?`'
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module SlimLint::Matcher
|
2
|
+
# Wraps a matcher, taking on the behavior of the wrapped matcher but storing
|
3
|
+
# the value that matched so it can be referred to later.
|
4
|
+
class Capture < Base
|
5
|
+
# @return [SlimLint::Matcher::Base] matcher that this capture wraps
|
6
|
+
attr_accessor :matcher
|
7
|
+
|
8
|
+
# @return [Object] value that was captured
|
9
|
+
attr_accessor :value
|
10
|
+
|
11
|
+
# Creates a capture that wraps that given matcher.
|
12
|
+
#
|
13
|
+
# @param matcher [SlimLint::Matcher::Base]
|
14
|
+
# @return [SlimLint::Matcher::Capture]
|
15
|
+
def self.from_matcher(matcher)
|
16
|
+
new.tap do |cap_matcher|
|
17
|
+
cap_matcher.matcher = matcher
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
# @see {SlimLint::Matcher::Base#match?}
|
22
|
+
def match?(object)
|
23
|
+
if result = @matcher.match?(object)
|
24
|
+
@value = object
|
25
|
+
end
|
26
|
+
|
27
|
+
result
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
data/lib/slim_lint/options.rb
CHANGED
@@ -30,12 +30,8 @@ module SlimLint
|
|
30
30
|
|
31
31
|
private
|
32
32
|
|
33
|
+
# Register linter-related flags.
|
33
34
|
def add_linter_options(parser)
|
34
|
-
parser.on('-e', '--exclude file,...', Array,
|
35
|
-
'List of file names to exclude') do |files|
|
36
|
-
@options[:excluded_files] = files
|
37
|
-
end
|
38
|
-
|
39
35
|
parser.on('-i', '--include-linter linter,...', Array,
|
40
36
|
'Specify which linters you want to run') do |linters|
|
41
37
|
@options[:included_linters] = linters
|
@@ -48,10 +44,23 @@ module SlimLint
|
|
48
44
|
|
49
45
|
parser.on('-r', '--reporter reporter', String,
|
50
46
|
'Specify which reporter you want to use to generate the output') do |reporter|
|
51
|
-
@options[:reporter] =
|
47
|
+
@options[:reporter] = load_reporter_class(reporter.capitalize)
|
52
48
|
end
|
53
49
|
end
|
54
50
|
|
51
|
+
# Returns the class of the specified Reporter.
|
52
|
+
#
|
53
|
+
# @param reporter_name [String]
|
54
|
+
# @raise [SlimLint::Exceptions::InvalidCLIOption] if reporter doesn't exist
|
55
|
+
# @return [Class]
|
56
|
+
def load_reporter_class(reporter_name)
|
57
|
+
SlimLint::Reporter.const_get("#{reporter_name}Reporter")
|
58
|
+
rescue NameError
|
59
|
+
raise SlimLint::Exceptions::InvalidCLIOption,
|
60
|
+
"#{reporter_name}Reporter does not exist"
|
61
|
+
end
|
62
|
+
|
63
|
+
# Register file-related flags.
|
55
64
|
def add_file_options(parser)
|
56
65
|
parser.on('-c', '--config config-file', String,
|
57
66
|
'Specify which configuration file you want to use') do |conf_file|
|
@@ -64,6 +73,7 @@ module SlimLint
|
|
64
73
|
end
|
65
74
|
end
|
66
75
|
|
76
|
+
# Register informational flags.
|
67
77
|
def add_info_options(parser)
|
68
78
|
parser.on('--show-linters', 'Display available linters') do
|
69
79
|
@options[:show_linters] = true
|
data/lib/slim_lint/rake_task.rb
CHANGED
@@ -51,6 +51,8 @@ module SlimLint
|
|
51
51
|
attr_accessor :quiet
|
52
52
|
|
53
53
|
# Create the task so it exists in the current namespace.
|
54
|
+
#
|
55
|
+
# @param name [Symbol] task name
|
54
56
|
def initialize(name = :slim_lint)
|
55
57
|
@name = name
|
56
58
|
@files = ['.'] # Search for everything under current directory by default
|
@@ -63,6 +65,7 @@ module SlimLint
|
|
63
65
|
|
64
66
|
private
|
65
67
|
|
68
|
+
# Defines the Rake task.
|
66
69
|
def define
|
67
70
|
desc default_description unless ::Rake.application.last_description
|
68
71
|
|
@@ -75,6 +78,9 @@ module SlimLint
|
|
75
78
|
end
|
76
79
|
end
|
77
80
|
|
81
|
+
# Executes the CLI given the specified task arguments.
|
82
|
+
#
|
83
|
+
# @param task_args [Rake::TaskArguments]
|
78
84
|
def run_cli(task_args)
|
79
85
|
cli_args = ['--config', config] if config
|
80
86
|
|
@@ -84,6 +90,10 @@ module SlimLint
|
|
84
90
|
fail "#{SlimLint::APP_NAME} failed with exit code #{result}" unless result == 0
|
85
91
|
end
|
86
92
|
|
93
|
+
# Returns the list of files that should be linted given the specified task
|
94
|
+
# arguments.
|
95
|
+
#
|
96
|
+
# @param task_args [Rake::TaskArguments]
|
87
97
|
def files_to_lint(task_args)
|
88
98
|
# Note: we're abusing Rake's argument handling a bit here. We call the
|
89
99
|
# first argument `files` but it's actually only the first file--we pull
|
@@ -96,6 +106,11 @@ module SlimLint
|
|
96
106
|
end
|
97
107
|
|
98
108
|
# Friendly description that shows the full command that will be executed.
|
109
|
+
#
|
110
|
+
# This allows us to change the information displayed by `rake --tasks` based
|
111
|
+
# on the options passed to the constructor which defined the task.
|
112
|
+
#
|
113
|
+
# @return [String]
|
99
114
|
def default_description
|
100
115
|
description = "Run `#{SlimLint::APP_NAME}"
|
101
116
|
description += " --config #{config}" if config
|
data/lib/slim_lint/report.rb
CHANGED
@@ -1,9 +1,16 @@
|
|
1
1
|
module SlimLint
|
2
2
|
# Contains information about all lints detected during a scan.
|
3
3
|
class Report
|
4
|
+
# List of lints that were found.
|
4
5
|
attr_accessor :lints
|
6
|
+
|
7
|
+
# List of files that were linted.
|
5
8
|
attr_reader :files
|
6
9
|
|
10
|
+
# Creates a report.
|
11
|
+
#
|
12
|
+
# @param lints [Array<SlimLint::Lint>] lints that were found
|
13
|
+
# @param files [Array<String>] files that were linted
|
7
14
|
def initialize(lints, files)
|
8
15
|
@lints = lints.sort_by { |l| [l.filename, l.line] }
|
9
16
|
@files = files
|
@@ -2,8 +2,8 @@ module SlimLint
|
|
2
2
|
# Outputs lints in a simple format with the filename, line number, and lint
|
3
3
|
# message.
|
4
4
|
class Reporter::DefaultReporter < Reporter
|
5
|
-
def
|
6
|
-
sorted_lints = lints.sort_by { |l| [l.filename, l.line] }
|
5
|
+
def display_report(report)
|
6
|
+
sorted_lints = report.lints.sort_by { |l| [l.filename, l.line] }
|
7
7
|
|
8
8
|
sorted_lints.each do |lint|
|
9
9
|
print_location(lint)
|
@@ -1,29 +1,34 @@
|
|
1
1
|
module SlimLint
|
2
2
|
# Outputs report as a JSON document.
|
3
3
|
class Reporter::JsonReporter < Reporter
|
4
|
-
def
|
4
|
+
def display_report(report)
|
5
|
+
lints = report.lints
|
5
6
|
grouped = lints.group_by(&:filename)
|
6
7
|
|
7
|
-
|
8
|
-
metadata:
|
9
|
-
slim_lint_version: SlimLint::VERSION,
|
10
|
-
ruby_engine: RUBY_ENGINE,
|
11
|
-
ruby_patchlevel: RUBY_PATCHLEVEL.to_s,
|
12
|
-
ruby_platform: RUBY_PLATFORM,
|
13
|
-
},
|
8
|
+
report_hash = {
|
9
|
+
metadata: metadata,
|
14
10
|
files: grouped.map { |l| map_file(l) },
|
15
11
|
summary: {
|
16
12
|
offense_count: lints.length,
|
17
13
|
target_file_count: grouped.length,
|
18
|
-
inspected_file_count: files.length,
|
14
|
+
inspected_file_count: report.files.length,
|
19
15
|
},
|
20
16
|
}
|
21
17
|
|
22
|
-
log.log
|
18
|
+
log.log report_hash.to_json
|
23
19
|
end
|
24
20
|
|
25
21
|
private
|
26
22
|
|
23
|
+
def metadata
|
24
|
+
{
|
25
|
+
slim_lint_version: SlimLint::VERSION,
|
26
|
+
ruby_engine: RUBY_ENGINE,
|
27
|
+
ruby_patchlevel: RUBY_PATCHLEVEL.to_s,
|
28
|
+
ruby_platform: RUBY_PLATFORM,
|
29
|
+
}
|
30
|
+
end
|
31
|
+
|
27
32
|
def map_file(file)
|
28
33
|
{
|
29
34
|
path: file.first,
|
data/lib/slim_lint/reporter.rb
CHANGED
@@ -1,36 +1,42 @@
|
|
1
1
|
module SlimLint
|
2
|
-
# Abstract lint reporter. Subclass and override {#
|
2
|
+
# Abstract lint reporter. Subclass and override {#display_report} to
|
3
3
|
# implement a custom lint reporter.
|
4
4
|
#
|
5
5
|
# @abstract
|
6
6
|
class Reporter
|
7
|
-
|
8
|
-
|
9
|
-
|
7
|
+
# Creates the reporter that will display the given report.
|
8
|
+
#
|
10
9
|
# @param logger [SlimLint::Logger]
|
11
|
-
|
12
|
-
def initialize(logger, report)
|
10
|
+
def initialize(logger)
|
13
11
|
@log = logger
|
14
|
-
@lints = report.lints
|
15
|
-
@files = report.files
|
16
12
|
end
|
17
13
|
|
18
14
|
# Implemented by subclasses to display lints from a {SlimLint::Report}.
|
19
|
-
|
20
|
-
|
15
|
+
#
|
16
|
+
# @param report [SlimLint::Report]
|
17
|
+
def display_report(report)
|
18
|
+
raise NotImplementedError,
|
19
|
+
"Implement `display_report` to display #{report}"
|
21
20
|
end
|
22
21
|
|
23
|
-
# Keep tracking all the descendants of this class for the list of available
|
22
|
+
# Keep tracking all the descendants of this class for the list of available
|
23
|
+
# reporters.
|
24
|
+
#
|
25
|
+
# @return [Array<Class>]
|
24
26
|
def self.descendants
|
25
27
|
@descendants ||= []
|
26
28
|
end
|
27
29
|
|
30
|
+
# Executed when this class is subclassed.
|
31
|
+
#
|
32
|
+
# @param descendant [Class]
|
28
33
|
def self.inherited(descendant)
|
29
34
|
descendants << descendant
|
30
35
|
end
|
31
36
|
|
32
37
|
private
|
33
38
|
|
39
|
+
# @return [SlimLint::Logger] logger to send output to
|
34
40
|
attr_reader :log
|
35
41
|
end
|
36
42
|
end
|
@@ -30,6 +30,8 @@ module SlimLint
|
|
30
30
|
include SexpVisitor
|
31
31
|
extend SexpVisitor::DSL
|
32
32
|
|
33
|
+
# Map of generated Ruby source code lines and their corresponding lines in
|
34
|
+
# the original document.
|
33
35
|
attr_reader :source_map
|
34
36
|
|
35
37
|
# Extracts Ruby code from Sexp representing a Slim document.
|