haml_lint 0.40.0 → 0.51.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/bin/haml-lint +1 -1
- data/config/default.yml +9 -27
- data/config/forced_rubocop_config.yml +180 -0
- data/lib/haml_lint/adapter/haml_4.rb +20 -0
- data/lib/haml_lint/adapter/haml_5.rb +11 -0
- data/lib/haml_lint/adapter/haml_6.rb +59 -0
- data/lib/haml_lint/adapter.rb +2 -0
- data/lib/haml_lint/cli.rb +8 -3
- data/lib/haml_lint/configuration_loader.rb +49 -13
- data/lib/haml_lint/document.rb +89 -8
- data/lib/haml_lint/exceptions.rb +6 -0
- data/lib/haml_lint/extensions/haml_util_unescape_interpolation_tracking.rb +35 -0
- data/lib/haml_lint/file_finder.rb +2 -2
- data/lib/haml_lint/lint.rb +10 -1
- data/lib/haml_lint/linter/final_newline.rb +4 -3
- data/lib/haml_lint/linter/implicit_div.rb +1 -1
- data/lib/haml_lint/linter/indentation.rb +3 -3
- data/lib/haml_lint/linter/no_placeholders.rb +18 -0
- data/lib/haml_lint/linter/repeated_id.rb +2 -1
- data/lib/haml_lint/linter/rubocop.rb +353 -59
- data/lib/haml_lint/linter/space_before_script.rb +8 -10
- data/lib/haml_lint/linter/trailing_empty_lines.rb +22 -0
- data/lib/haml_lint/linter/unnecessary_string_output.rb +1 -1
- data/lib/haml_lint/linter/view_length.rb +1 -1
- data/lib/haml_lint/linter.rb +60 -10
- data/lib/haml_lint/linter_registry.rb +3 -5
- data/lib/haml_lint/logger.rb +2 -2
- data/lib/haml_lint/options.rb +26 -2
- data/lib/haml_lint/rake_task.rb +2 -2
- data/lib/haml_lint/reporter/hash_reporter.rb +1 -3
- data/lib/haml_lint/reporter/offense_count_reporter.rb +1 -1
- data/lib/haml_lint/reporter/utils.rb +33 -4
- data/lib/haml_lint/ruby_extraction/ad_hoc_chunk.rb +24 -0
- data/lib/haml_lint/ruby_extraction/base_chunk.rb +114 -0
- data/lib/haml_lint/ruby_extraction/chunk_extractor.rb +672 -0
- data/lib/haml_lint/ruby_extraction/coordinator.rb +181 -0
- data/lib/haml_lint/ruby_extraction/haml_comment_chunk.rb +34 -0
- data/lib/haml_lint/ruby_extraction/implicit_end_chunk.rb +17 -0
- data/lib/haml_lint/ruby_extraction/interpolation_chunk.rb +26 -0
- data/lib/haml_lint/ruby_extraction/non_ruby_filter_chunk.rb +32 -0
- data/lib/haml_lint/ruby_extraction/placeholder_marker_chunk.rb +40 -0
- data/lib/haml_lint/ruby_extraction/ruby_filter_chunk.rb +33 -0
- data/lib/haml_lint/ruby_extraction/ruby_source.rb +5 -0
- data/lib/haml_lint/ruby_extraction/script_chunk.rb +251 -0
- data/lib/haml_lint/ruby_extraction/tag_attributes_chunk.rb +63 -0
- data/lib/haml_lint/ruby_extraction/tag_script_chunk.rb +30 -0
- data/lib/haml_lint/ruby_parser.rb +11 -1
- data/lib/haml_lint/runner.rb +35 -3
- data/lib/haml_lint/spec/matchers/report_lint.rb +22 -7
- data/lib/haml_lint/spec/normalize_indent.rb +2 -2
- data/lib/haml_lint/spec/shared_linter_context.rb +9 -1
- data/lib/haml_lint/spec/shared_rubocop_autocorrect_context.rb +158 -0
- data/lib/haml_lint/spec.rb +1 -0
- data/lib/haml_lint/tree/filter_node.rb +10 -0
- data/lib/haml_lint/tree/node.rb +13 -4
- data/lib/haml_lint/tree/script_node.rb +7 -1
- data/lib/haml_lint/tree/silent_script_node.rb +16 -1
- data/lib/haml_lint/tree/tag_node.rb +5 -9
- data/lib/haml_lint/utils.rb +135 -5
- data/lib/haml_lint/version.rb +1 -1
- data/lib/haml_lint/version_comparer.rb +25 -0
- data/lib/haml_lint.rb +12 -0
- metadata +29 -15
- data/lib/haml_lint/ruby_extractor.rb +0 -222
@@ -9,7 +9,7 @@ module HamlLint
|
|
9
9
|
|
10
10
|
ALLOWED_SEPARATORS = [' ', '#'].freeze
|
11
11
|
|
12
|
-
def visit_tag(node) # rubocop:disable Metrics/CyclomaticComplexity
|
12
|
+
def visit_tag(node) # rubocop:disable Metrics/CyclomaticComplexity
|
13
13
|
# If this tag has inline script
|
14
14
|
return unless node.contains_script?
|
15
15
|
|
@@ -18,15 +18,13 @@ module HamlLint
|
|
18
18
|
|
19
19
|
tag_with_text = tag_with_inline_text(node)
|
20
20
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
return
|
29
|
-
end
|
21
|
+
# For tags with inline text that contain interpolation, the parser
|
22
|
+
# converts them to inline script by surrounding them in string quotes,
|
23
|
+
# e.g. `%p Hello #{name}` becomes `%p= "Hello #{name}"`, causing the
|
24
|
+
# above search to fail. Check for this case by removing added quotes.
|
25
|
+
if !(index = tag_with_text.rindex(text)) && !((text_without_quotes = strip_surrounding_quotes(text)) &&
|
26
|
+
(index = tag_with_text.rindex(text_without_quotes)))
|
27
|
+
return
|
30
28
|
end
|
31
29
|
|
32
30
|
return if tag_with_text[index] == '#' # Ignore code comments
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HamlLint
|
4
|
+
# Checks for trailing empty lines.
|
5
|
+
class Linter::TrailingEmptyLines < Linter
|
6
|
+
include LinterRegistry
|
7
|
+
|
8
|
+
DummyNode = Struct.new(:line)
|
9
|
+
|
10
|
+
def visit_root(root)
|
11
|
+
return if document.source.empty?
|
12
|
+
line_number = document.last_non_empty_line
|
13
|
+
|
14
|
+
node = root.node_for_line(line_number)
|
15
|
+
return if node.disabled?(self)
|
16
|
+
|
17
|
+
return unless document.source.end_with?("\n\n")
|
18
|
+
|
19
|
+
record_lint(line_number, 'Files should not end with trailing empty lines')
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -35,7 +35,7 @@ module HamlLint
|
|
35
35
|
return unless tree = parse_ruby(script_node.script)
|
36
36
|
%i[str dstr].include?(tree.type) &&
|
37
37
|
!starts_with_reserved_character?(tree.children.first)
|
38
|
-
rescue ::Parser::SyntaxError
|
38
|
+
rescue ::Parser::SyntaxError
|
39
39
|
# Gracefully ignore syntax errors, as that's managed by a different linter
|
40
40
|
end
|
41
41
|
|
data/lib/haml_lint/linter.rb
CHANGED
@@ -24,11 +24,8 @@ module HamlLint
|
|
24
24
|
# Runs the linter against the given Haml document.
|
25
25
|
#
|
26
26
|
# @param document [HamlLint::Document]
|
27
|
-
def run(document)
|
28
|
-
|
29
|
-
@lints = []
|
30
|
-
visit(document.tree)
|
31
|
-
@lints
|
27
|
+
def run(document, autocorrect: nil) # rubocop:disable Metrics
|
28
|
+
run_or_raise(document, autocorrect: autocorrect)
|
32
29
|
rescue Parser::SyntaxError => e
|
33
30
|
location = e.diagnostic.location
|
34
31
|
@lints <<
|
@@ -39,6 +36,35 @@ module HamlLint
|
|
39
36
|
e.to_s,
|
40
37
|
:error
|
41
38
|
)
|
39
|
+
rescue StandardError => e
|
40
|
+
msg = "Couldn't process the file".dup
|
41
|
+
if @autocorrect
|
42
|
+
# Those lints related to auto-correction were not saved, so don't display them
|
43
|
+
@lints = []
|
44
|
+
msg << " for autocorrect '#{@autocorrect}'. "
|
45
|
+
else
|
46
|
+
msg << ' for linting. '
|
47
|
+
end
|
48
|
+
|
49
|
+
msg << "#{e.class.name}: #{e.message}"
|
50
|
+
if ENV['HAML_LINT_DEBUG'] == 'true'
|
51
|
+
msg << "(DEBUG: Backtrace follows)\n#{e.backtrace.join("\n")}\n------"
|
52
|
+
end
|
53
|
+
|
54
|
+
@lints << HamlLint::Lint.new(self, document.file, nil, msg, :error)
|
55
|
+
@lints
|
56
|
+
end
|
57
|
+
|
58
|
+
# Runs the linter against the given Haml document, raises if the file cannot be processed due to
|
59
|
+
# Syntax or HAML-Lint internal errors. (For testing purposes)
|
60
|
+
#
|
61
|
+
# @param document [HamlLint::Document]
|
62
|
+
def run_or_raise(document, autocorrect: nil)
|
63
|
+
@document = document
|
64
|
+
@lints = []
|
65
|
+
@autocorrect = autocorrect
|
66
|
+
visit(document.tree)
|
67
|
+
@lints
|
42
68
|
end
|
43
69
|
|
44
70
|
# Returns the simple name for this linter.
|
@@ -48,25 +74,49 @@ module HamlLint
|
|
48
74
|
self.class.name.to_s.split('::').last
|
49
75
|
end
|
50
76
|
|
77
|
+
# Returns true if this linter supports autocorrect, false otherwise
|
78
|
+
#
|
79
|
+
# @return [Boolean]
|
80
|
+
def self.supports_autocorrect?
|
81
|
+
@supports_autocorrect || false
|
82
|
+
end
|
83
|
+
|
84
|
+
def supports_autocorrect?
|
85
|
+
self.class.supports_autocorrect?
|
86
|
+
end
|
87
|
+
|
51
88
|
private
|
52
89
|
|
53
90
|
attr_reader :config, :document
|
54
91
|
|
92
|
+
# Linters can call supports_autocorrect(true) in their top-level scope to indicate that
|
93
|
+
# they supports autocorrect.
|
94
|
+
#
|
95
|
+
# @params value [Boolean] The new value for supports_autocorrect
|
96
|
+
private_class_method def self.supports_autocorrect(value)
|
97
|
+
@supports_autocorrect = value
|
98
|
+
end
|
99
|
+
|
55
100
|
# Record a lint for reporting back to the user.
|
56
101
|
#
|
57
|
-
# @param
|
102
|
+
# @param node_or_line [#line] line number or node to extract the line number from
|
58
103
|
# @param message [String] error/warning to display to the user
|
59
|
-
def record_lint(
|
60
|
-
|
61
|
-
|
104
|
+
def record_lint(node_or_line, message, corrected: false)
|
105
|
+
line = node_or_line.is_a?(Integer) ? node_or_line : node_or_line.line
|
106
|
+
@lints << HamlLint::Lint.new(self, @document.file, line, message,
|
107
|
+
config.fetch('severity', :warning).to_sym,
|
108
|
+
corrected: corrected)
|
62
109
|
end
|
63
110
|
|
64
111
|
# Parse Ruby code into an abstract syntax tree.
|
65
112
|
#
|
66
113
|
# @return [AST::Node]
|
67
114
|
def parse_ruby(source)
|
115
|
+
self.class.ruby_parser.parse(source)
|
116
|
+
end
|
117
|
+
|
118
|
+
def self.ruby_parser # rubocop:disable Lint/IneffectiveAccessModifier
|
68
119
|
@ruby_parser ||= HamlLint::RubyParser.new
|
69
|
-
@ruby_parser.parse(source)
|
70
120
|
end
|
71
121
|
|
72
122
|
# Remove the surrounding double quotes from a string, ignoring any
|
@@ -27,11 +27,9 @@ module HamlLint
|
|
27
27
|
# @return [Array<Class>]
|
28
28
|
def extract_linters_from(linter_names)
|
29
29
|
linter_names.map do |linter_name|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
raise NoSuchLinter, "Linter #{linter_name} does not exist"
|
34
|
-
end
|
30
|
+
HamlLint::Linter.const_get(linter_name)
|
31
|
+
rescue NameError
|
32
|
+
raise NoSuchLinter, "Linter #{linter_name} does not exist"
|
35
33
|
end
|
36
34
|
end
|
37
35
|
end
|
data/lib/haml_lint/logger.rb
CHANGED
@@ -30,7 +30,7 @@ module HamlLint
|
|
30
30
|
#
|
31
31
|
# @param output [String] the output to send
|
32
32
|
# @param newline [true,false] whether to append a newline
|
33
|
-
def log(output, newline = true)
|
33
|
+
def log(output, newline = true) # rubocop:disable Style/OptionalBooleanParameter
|
34
34
|
@out.print(output)
|
35
35
|
@out.print("\n") if newline
|
36
36
|
end
|
@@ -97,7 +97,7 @@ module HamlLint
|
|
97
97
|
|
98
98
|
private
|
99
99
|
|
100
|
-
def color(code, output, newline = true)
|
100
|
+
def color(code, output, newline = true) # rubocop:disable Style/OptionalBooleanParameter
|
101
101
|
log(color_enabled ? "\033[#{code}m#{output}\033[0m" : output, newline)
|
102
102
|
end
|
103
103
|
end
|
data/lib/haml_lint/options.rb
CHANGED
@@ -32,7 +32,7 @@ module HamlLint
|
|
32
32
|
|
33
33
|
private
|
34
34
|
|
35
|
-
def add_linter_options(parser)
|
35
|
+
def add_linter_options(parser) # rubocop:disable Metrics/MethodLength
|
36
36
|
parser.on('--auto-gen-config', 'Generate a configuration file acting as a TODO list') do
|
37
37
|
@options[:auto_gen_config] = true
|
38
38
|
end
|
@@ -55,6 +55,20 @@ module HamlLint
|
|
55
55
|
parser.on('-p', '--parallel', 'Run linters in parallel using available CPUs') do
|
56
56
|
@options[:parallel] = true
|
57
57
|
end
|
58
|
+
|
59
|
+
parser.on('-a', '--auto-correct', 'Auto-correct offenses (only when it’s safe)') do
|
60
|
+
@options[:autocorrect] = :safe
|
61
|
+
end
|
62
|
+
|
63
|
+
parser.on('-A', '--auto-correct-all', 'Auto-correct offenses (safe and unsafe)') do
|
64
|
+
@options[:autocorrect] = :all
|
65
|
+
end
|
66
|
+
|
67
|
+
parser.on('--auto-correct-only', "Only do auto-correct, don't lint. " \
|
68
|
+
'Also activates safe auto-correct if no auto-correct is selected') do
|
69
|
+
@options[:autocorrect_only] = true
|
70
|
+
@options[:autocorrect] ||= :safe
|
71
|
+
end
|
58
72
|
end
|
59
73
|
|
60
74
|
def add_report_options(parser)
|
@@ -99,7 +113,7 @@ module HamlLint
|
|
99
113
|
end
|
100
114
|
end
|
101
115
|
|
102
|
-
def add_info_options(parser)
|
116
|
+
def add_info_options(parser) # rubocop:disable Metrics/MethodLength
|
103
117
|
parser.on('--show-linters', 'Display available linters') do
|
104
118
|
@options[:show_linters] = true
|
105
119
|
end
|
@@ -108,6 +122,16 @@ module HamlLint
|
|
108
122
|
@options[:show_reporters] = true
|
109
123
|
end
|
110
124
|
|
125
|
+
parser.on('-d', '--debug', 'Add some debug information to messages') do
|
126
|
+
@options[:debug] = true
|
127
|
+
end
|
128
|
+
|
129
|
+
parser.on('--internal-debug', 'Add lots of (internal) debug information.' \
|
130
|
+
" Also affects some lint's line numbers to skip sourcemap") do
|
131
|
+
@options[:debug] = true
|
132
|
+
@options[:internal_debug] = true
|
133
|
+
end
|
134
|
+
|
111
135
|
parser.on_tail('-h', '--help', 'Display help documentation') do
|
112
136
|
@options[:help] = parser.help
|
113
137
|
end
|
data/lib/haml_lint/rake_task.rb
CHANGED
@@ -104,7 +104,7 @@ module HamlLint
|
|
104
104
|
# @param task_args [Rake::TaskArguments]
|
105
105
|
def run_cli(task_args)
|
106
106
|
cli_args = parse_args
|
107
|
-
logger = quiet ? HamlLint::Logger.silent : HamlLint::Logger.new(
|
107
|
+
logger = quiet ? HamlLint::Logger.silent : HamlLint::Logger.new($stdout)
|
108
108
|
result = HamlLint::CLI.new(logger).run(Array(cli_args) + files_to_lint(task_args))
|
109
109
|
|
110
110
|
fail "#{HamlLint::APP_NAME} failed with exit code #{result}" unless result == 0
|
@@ -115,7 +115,7 @@ module HamlLint
|
|
115
115
|
#
|
116
116
|
# @param task_args [Rake::TaskArguments]
|
117
117
|
def files_to_lint(task_args)
|
118
|
-
#
|
118
|
+
# NOTE: we're abusing Rake's argument handling a bit here. We call the
|
119
119
|
# first argument `files` but it's actually only the first file--we pull
|
120
120
|
# the rest out of the `extras` from the task arguments. This is so we
|
121
121
|
# can specify an arbitrary list of files separated by commas on the
|
@@ -14,7 +14,7 @@ module HamlLint
|
|
14
14
|
lints = report.lints
|
15
15
|
grouped = lints.group_by(&:filename)
|
16
16
|
|
17
|
-
|
17
|
+
{
|
18
18
|
metadata: metadata,
|
19
19
|
files: grouped.map { |l| map_file(l) },
|
20
20
|
summary: {
|
@@ -23,8 +23,6 @@ module HamlLint
|
|
23
23
|
inspected_file_count: report.files.length,
|
24
24
|
},
|
25
25
|
}
|
26
|
-
|
27
|
-
report_hash
|
28
26
|
end
|
29
27
|
|
30
28
|
private
|
@@ -10,7 +10,7 @@ module HamlLint
|
|
10
10
|
return if total_count.zero?
|
11
11
|
|
12
12
|
lints.group_by { |l| lint_type_group(l) }
|
13
|
-
.
|
13
|
+
.transform_values(&:size)
|
14
14
|
.sort_by { |_linter, lint_count| -lint_count }
|
15
15
|
.each do |linter, lint_count|
|
16
16
|
log.log "#{lint_count.to_s.ljust(total_count.to_s.length + 2)} #{linter}"
|
@@ -56,6 +56,10 @@ module HamlLint
|
|
56
56
|
# @param lint [HamlLint::Lint] the lint to print
|
57
57
|
# @return [void]
|
58
58
|
def print_message(lint)
|
59
|
+
if lint.corrected
|
60
|
+
log.success('[Corrected] ', false)
|
61
|
+
end
|
62
|
+
|
59
63
|
if lint.linter
|
60
64
|
log.success("#{lint.linter.name}: ", false)
|
61
65
|
end
|
@@ -70,10 +74,15 @@ module HamlLint
|
|
70
74
|
def print_summary(report)
|
71
75
|
return unless log.summary_enabled
|
72
76
|
|
77
|
+
log.log('')
|
73
78
|
print_summary_files(report)
|
74
|
-
print_summary_lints(report)
|
75
79
|
|
76
|
-
|
80
|
+
print_summary_lints(report, is_append: true)
|
81
|
+
|
82
|
+
log.log ' detected', false
|
83
|
+
|
84
|
+
print_summary_corrected_lints(report, is_append: true)
|
85
|
+
log.log ''
|
77
86
|
end
|
78
87
|
|
79
88
|
# Prints a summary of the number of files linted in a report.
|
@@ -81,14 +90,17 @@ module HamlLint
|
|
81
90
|
# @param report [HamlLint::Report] the report to print
|
82
91
|
# @return [void]
|
83
92
|
def print_summary_files(report)
|
84
|
-
log.log "
|
93
|
+
log.log "#{pluralize('file', count: report.files.count)} inspected", false
|
85
94
|
end
|
86
95
|
|
87
96
|
# Prints a summary of the number of lints found in a report.
|
88
97
|
#
|
89
98
|
# @param report [HamlLint::Report] the report to print
|
99
|
+
# @param is_append [Boolean] if this is appending to a line. Will preffix with ", ".
|
90
100
|
# @return [void]
|
91
|
-
def print_summary_lints(report)
|
101
|
+
def print_summary_lints(report, is_append:)
|
102
|
+
log.log ', ', false if is_append
|
103
|
+
|
92
104
|
lint_count = report.lints.size
|
93
105
|
lint_message = pluralize('lint', count: lint_count)
|
94
106
|
|
@@ -98,6 +110,23 @@ module HamlLint
|
|
98
110
|
log.error lint_message, false
|
99
111
|
end
|
100
112
|
end
|
113
|
+
|
114
|
+
# Prints a summary of the number of lints corrected in a report.
|
115
|
+
#
|
116
|
+
# @param report [HamlLint::Report] the report to print
|
117
|
+
# @param is_append [Boolean] if this is appending to a line. Will preffix with ", ".
|
118
|
+
# @return [void]
|
119
|
+
def print_summary_corrected_lints(report, is_append:)
|
120
|
+
lint_count = report.lints.count(&:corrected)
|
121
|
+
return if lint_count == 0
|
122
|
+
|
123
|
+
log.log ', ', false if is_append
|
124
|
+
|
125
|
+
lint_message = pluralize('lint', count: lint_count)
|
126
|
+
|
127
|
+
log.info lint_message, false
|
128
|
+
log.log ' corrected', false
|
129
|
+
end
|
101
130
|
end
|
102
131
|
end
|
103
132
|
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HamlLint::RubyExtraction
|
4
|
+
# This chunk just adds its code to the ruby, but does not attempt to transfer their correction
|
5
|
+
# in any way.
|
6
|
+
#
|
7
|
+
# Used for piece of code that just need to be in the generated ruby for reasons specific to
|
8
|
+
# the use cases, such as needing a `begin` to do add indentation.
|
9
|
+
class AdHocChunk < BaseChunk
|
10
|
+
def initialize(*args, **kwargs)
|
11
|
+
super(*args, **kwargs.merge(end_marker_indent: nil))
|
12
|
+
end
|
13
|
+
|
14
|
+
def wrap_in_markers
|
15
|
+
false
|
16
|
+
end
|
17
|
+
|
18
|
+
def transfer_correction(coordinator, all_corrected_ruby_lines, haml_lines); end
|
19
|
+
|
20
|
+
def skip_line_indexes_in_source_map
|
21
|
+
(0...@ruby_lines.size).to_a
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HamlLint::RubyExtraction
|
4
|
+
# This is the base class for all of the Chunks of HamlLint::RubyExtraction.
|
5
|
+
# A Chunk represents a part of the HAML file that HamlLint::Linter::RuboCop
|
6
|
+
# is processing and will insert some Ruby code in a file passed to RuboCop.
|
7
|
+
#
|
8
|
+
# There are chunks for most HAML concepts, even if they don't represent Ruby
|
9
|
+
# code. For example, there is a chunk that represents a `%div` tag, which
|
10
|
+
# uses a `begin` in the generated Ruby to add indentation for the children
|
11
|
+
# of the %div in the Ruby file just like there is in the HAML file.
|
12
|
+
class BaseChunk
|
13
|
+
COMMA_CHANGES_LINES = true
|
14
|
+
|
15
|
+
# @return [HamlLint::Tree::Node] Haml node that this comes from
|
16
|
+
attr_reader :node
|
17
|
+
|
18
|
+
# @return [Integer] First line index of the auto-correctable code in the Haml source
|
19
|
+
# Usually same as node.line - 1, but some cases, such as interpolation in a filter will
|
20
|
+
# will be different.
|
21
|
+
attr_reader :haml_line_index
|
22
|
+
|
23
|
+
# @return [Integer] Line number of the line marker in the ruby source placed before
|
24
|
+
# this auto-correctable code
|
25
|
+
attr_reader :start_marker_line_number
|
26
|
+
|
27
|
+
# @return [Integer] The indentation (number of spaces) to use to index the marker
|
28
|
+
# that follows this chunk. Unlike the marker before, this one can vary.
|
29
|
+
attr_reader :end_marker_indent
|
30
|
+
|
31
|
+
# @return [Array<String>] The ruby lines that this chunk will insert
|
32
|
+
attr_reader :ruby_lines
|
33
|
+
|
34
|
+
def initialize(node,
|
35
|
+
ruby_lines,
|
36
|
+
end_marker_indent:, haml_line_index: node.line - 1)
|
37
|
+
ruby_lines = [ruby_lines] if ruby_lines.is_a?(String)
|
38
|
+
@node = node
|
39
|
+
@ruby_lines = ruby_lines
|
40
|
+
@haml_line_index = haml_line_index
|
41
|
+
@end_marker_indent = end_marker_indent
|
42
|
+
end
|
43
|
+
|
44
|
+
# To be overridden in subclasses.
|
45
|
+
# Return a new chunk which is the result of fusing self with the given following chunk.
|
46
|
+
# If no fusion is possible, returns nil
|
47
|
+
def fuse(_following_chunk)
|
48
|
+
nil
|
49
|
+
end
|
50
|
+
|
51
|
+
# Overwrites haml_lines to match the Ruby code that was corrected by RuboCop which is in
|
52
|
+
# all_corrected_ruby_lines. This can change non-ruby parts to, especially for
|
53
|
+
# indentation.
|
54
|
+
#
|
55
|
+
# This will be called on ruby chunks in the reverse order they were created. Two benefits
|
56
|
+
# of this approach:
|
57
|
+
# * No need to track when lines in haml_lines are moved to apply changes later in the file
|
58
|
+
# * When fixing indentation of lines that follow a corrected line, those following lines will
|
59
|
+
# already have been corrected and so require nothing.
|
60
|
+
# Can be overridden by subclasses to make it do nothing
|
61
|
+
def transfer_correction(coordinator, _all_corrected_ruby_lines, haml_lines)
|
62
|
+
to_ruby_lines = coordinator.extract_from_corrected_lines(@start_marker_line_number, @ruby_lines.size)
|
63
|
+
transfer_correction_logic(coordinator, to_ruby_lines, haml_lines)
|
64
|
+
end
|
65
|
+
|
66
|
+
# To be overriden by subclasses.
|
67
|
+
#
|
68
|
+
# Logic to transfer the corrections that turned from_ruby_lines into to_ruby_lines.
|
69
|
+
#
|
70
|
+
# This method only received the ruby code that belongs to this chunk. (It was
|
71
|
+
# extracted using #extract_from by #transfer_correction)
|
72
|
+
def transfer_correction_logic(_coordinator, _to_ruby_lines, _haml_lines)
|
73
|
+
raise "Implement #transfer_correction_logic in #{self.class.name}"
|
74
|
+
end
|
75
|
+
|
76
|
+
def start_marker_indent
|
77
|
+
ruby_lines.first[/ */].size
|
78
|
+
end
|
79
|
+
|
80
|
+
def haml_end_line_index
|
81
|
+
# the .max is needed to handle cases with 0 nb_haml_lines
|
82
|
+
[@haml_line_index + nb_haml_lines - 1, @haml_line_index].max
|
83
|
+
end
|
84
|
+
|
85
|
+
def nb_haml_lines
|
86
|
+
@ruby_lines.size - skip_line_indexes_in_source_map.size
|
87
|
+
end
|
88
|
+
|
89
|
+
def full_assemble(coordinator)
|
90
|
+
if wrap_in_markers
|
91
|
+
@start_marker_line_number = coordinator.add_marker(start_marker_indent,
|
92
|
+
haml_line_index: haml_line_index)
|
93
|
+
assemble_in(coordinator)
|
94
|
+
coordinator.add_marker(@end_marker_indent, haml_line_index: haml_end_line_index)
|
95
|
+
else
|
96
|
+
assemble_in(coordinator)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def assemble_in(coordinator)
|
101
|
+
coordinator.add_lines(@ruby_lines,
|
102
|
+
haml_line_index: haml_line_index,
|
103
|
+
skip_indexes_in_source_map: skip_line_indexes_in_source_map)
|
104
|
+
end
|
105
|
+
|
106
|
+
def skip_line_indexes_in_source_map
|
107
|
+
[]
|
108
|
+
end
|
109
|
+
|
110
|
+
def wrap_in_markers
|
111
|
+
true
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|