haml_lint 0.40.0 → 0.51.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/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
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module HamlLint::RubyExtraction
|
4
|
+
# Chunk for handling outputting scripts after a tag, such as `%div= spam`
|
5
|
+
class TagScriptChunk < BaseChunk
|
6
|
+
def transfer_correction_logic(coordinator, to_ruby_lines, haml_lines) # rubocop:disable Metrics/AbcSize
|
7
|
+
# TODO: add checks that we have commas at the end of each line except the last one
|
8
|
+
|
9
|
+
from_ruby_line = @ruby_lines.first
|
10
|
+
to_ruby_line = to_ruby_lines.first
|
11
|
+
|
12
|
+
to_line_indent = to_ruby_line.index(/\S/)
|
13
|
+
|
14
|
+
from_ruby_line = from_ruby_line.sub(coordinator.script_output_prefix, '').sub(/^\s+/, '')
|
15
|
+
to_ruby_line = to_ruby_line.sub(coordinator.script_output_prefix, '').sub(/^\s+/, '')
|
16
|
+
|
17
|
+
affected_start_index = haml_lines[@haml_line_index].rindex(from_ruby_line)
|
18
|
+
|
19
|
+
haml_lines[@haml_line_index][affected_start_index..-1] = to_ruby_line
|
20
|
+
|
21
|
+
indent_delta = affected_start_index - coordinator.script_output_prefix.size - to_line_indent
|
22
|
+
|
23
|
+
HamlLint::Utils.map_after_first!(to_ruby_lines) do |line|
|
24
|
+
HamlLint::Utils.indent(line, indent_delta)
|
25
|
+
end
|
26
|
+
|
27
|
+
haml_lines[(@haml_line_index + 1)..haml_end_line_index] = to_ruby_lines[1..]
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -2,7 +2,6 @@
|
|
2
2
|
|
3
3
|
require 'rubocop'
|
4
4
|
require 'rubocop/ast/builder'
|
5
|
-
require 'parser/current'
|
6
5
|
|
7
6
|
module HamlLint
|
8
7
|
# Parser for the Ruby language.
|
@@ -14,10 +13,21 @@ module HamlLint
|
|
14
13
|
class RubyParser
|
15
14
|
# Creates a reusable parser.
|
16
15
|
def initialize
|
16
|
+
require_parser
|
17
17
|
@builder = ::RuboCop::AST::Builder.new
|
18
18
|
@parser = ::Parser::CurrentRuby.new(@builder)
|
19
19
|
end
|
20
20
|
|
21
|
+
# Require the current parser version while suppressing the
|
22
|
+
# compliancy warning for minor version differences.
|
23
|
+
def require_parser
|
24
|
+
prev = $VERBOSE
|
25
|
+
$VERBOSE = nil
|
26
|
+
require 'parser/current'
|
27
|
+
ensure
|
28
|
+
$VERBOSE = prev
|
29
|
+
end
|
30
|
+
|
21
31
|
# Parse the given Ruby source into an abstract syntax tree.
|
22
32
|
#
|
23
33
|
# @param source [String] Ruby source code
|
data/lib/haml_lint/runner.rb
CHANGED
@@ -24,6 +24,8 @@ module HamlLint
|
|
24
24
|
@linter_selector = HamlLint::LinterSelector.new(config, options)
|
25
25
|
@fail_fast = options.fetch(:fail_fast, false)
|
26
26
|
@cache = {}
|
27
|
+
@autocorrect = options[:autocorrect]
|
28
|
+
@autocorrect_only = options[:autocorrect_only]
|
27
29
|
|
28
30
|
report(options)
|
29
31
|
end
|
@@ -88,9 +90,39 @@ module HamlLint
|
|
88
90
|
e.line, e.to_s, :error)]
|
89
91
|
end
|
90
92
|
|
91
|
-
linter_selector.linters_for_file(file)
|
92
|
-
|
93
|
-
|
93
|
+
linters = linter_selector.linters_for_file(file)
|
94
|
+
lint_arrays = []
|
95
|
+
|
96
|
+
if @autocorrect
|
97
|
+
lint_arrays << autocorrect_document(document, linters)
|
98
|
+
end
|
99
|
+
|
100
|
+
unless @autocorrect_only
|
101
|
+
lint_arrays << linters.map do |linter|
|
102
|
+
linter.run(document)
|
103
|
+
end
|
104
|
+
end
|
105
|
+
lint_arrays.flatten
|
106
|
+
end
|
107
|
+
|
108
|
+
# Out of the provided linters, runs those that support autocorrect
|
109
|
+
# against the specified document.
|
110
|
+
# Updates the document and returns the lints that were corrected.
|
111
|
+
#
|
112
|
+
# @param document [HamlLint::Document]
|
113
|
+
# @param linter_selector [HamlLint::LinterSelector]
|
114
|
+
# @return [Array<HamlLint::Lint>]
|
115
|
+
def autocorrect_document(document, linters)
|
116
|
+
lint_arrays = []
|
117
|
+
|
118
|
+
autocorrecting_linters = linters.select(&:supports_autocorrect?)
|
119
|
+
lint_arrays << autocorrecting_linters.map do |linter|
|
120
|
+
linter.run(document, autocorrect: @autocorrect)
|
121
|
+
end
|
122
|
+
|
123
|
+
document.write_to_disk!
|
124
|
+
|
125
|
+
lint_arrays
|
94
126
|
end
|
95
127
|
|
96
128
|
# Returns the list of files that should be linted given the specified
|
@@ -10,9 +10,11 @@ module HamlLint
|
|
10
10
|
expected_line = options[:line]
|
11
11
|
expected_message = options[:message]
|
12
12
|
expected_severity = options[:severity]
|
13
|
+
expected_corrected = options[:corrected]
|
13
14
|
|
14
15
|
match do |linter|
|
15
|
-
has_lints?(linter, expected_line, count, expected_message, expected_severity
|
16
|
+
has_lints?(linter, expected_line, count, expected_message, expected_severity,
|
17
|
+
expected_corrected)
|
16
18
|
end
|
17
19
|
|
18
20
|
failure_message do |linter|
|
@@ -63,13 +65,15 @@ module HamlLint
|
|
63
65
|
(expected_severity ? " with severity '#{expected_severity}'" : '')
|
64
66
|
end
|
65
67
|
|
66
|
-
def has_lints?(linter, expected_line, count, expected_message, expected_severity
|
68
|
+
def has_lints?(linter, expected_line, count, expected_message, expected_severity, # rubocop:disable Metrics/ParameterLists
|
69
|
+
expected_corrected)
|
67
70
|
if expected_line
|
68
71
|
has_expected_line_lints?(linter,
|
69
72
|
expected_line,
|
70
73
|
count,
|
71
74
|
expected_message,
|
72
|
-
expected_severity
|
75
|
+
expected_severity,
|
76
|
+
expected_corrected)
|
73
77
|
elsif count
|
74
78
|
linter.lints.count == count
|
75
79
|
elsif expected_message
|
@@ -79,17 +83,20 @@ module HamlLint
|
|
79
83
|
end
|
80
84
|
end
|
81
85
|
|
82
|
-
def has_expected_line_lints?(linter,
|
86
|
+
def has_expected_line_lints?(linter, # rubocop:disable Metrics/ParameterLists
|
83
87
|
expected_line,
|
84
88
|
count,
|
85
89
|
expected_message,
|
86
|
-
expected_severity
|
90
|
+
expected_severity,
|
91
|
+
expected_corrected)
|
87
92
|
if count
|
88
93
|
multiple_lints_match_line?(linter, expected_line, count)
|
89
94
|
elsif expected_message
|
90
95
|
lint_on_line_matches_message?(linter, expected_line, expected_message)
|
91
96
|
elsif expected_severity
|
92
97
|
lint_on_line_matches_severity?(linter, expected_line, expected_severity)
|
98
|
+
elsif !expected_corrected.nil?
|
99
|
+
lint_on_line_matches_corrected?(linter, expected_line, expected_corrected)
|
93
100
|
else
|
94
101
|
lint_lines(linter).include?(expected_line)
|
95
102
|
end
|
@@ -101,9 +108,10 @@ module HamlLint
|
|
101
108
|
end
|
102
109
|
|
103
110
|
def lint_on_line_matches_message?(linter, expected_line, expected_message)
|
111
|
+
# Using === to support regex to match anywhere in the string
|
104
112
|
linter
|
105
113
|
.lints
|
106
|
-
.any? { |lint| lint.line == expected_line && lint.message
|
114
|
+
.any? { |lint| lint.line == expected_line && expected_message === lint.message } # rubocop:disable Style/CaseEquality
|
107
115
|
end
|
108
116
|
|
109
117
|
def lint_on_line_matches_severity?(linter, expected_line, expected_severity)
|
@@ -112,8 +120,15 @@ module HamlLint
|
|
112
120
|
.any? { |lint| lint.line == expected_line && lint.severity == expected_severity }
|
113
121
|
end
|
114
122
|
|
123
|
+
def lint_on_line_matches_corrected?(linter, expected_line, expected_corrected)
|
124
|
+
linter
|
125
|
+
.lints
|
126
|
+
.any? { |lint| lint.line == expected_line && lint.corrected == expected_corrected }
|
127
|
+
end
|
128
|
+
|
115
129
|
def lint_messages_match?(linter, expected_message)
|
116
|
-
|
130
|
+
# Using === to support regex to match anywhere in the string
|
131
|
+
lint_messages(linter).all? { |message| expected_message === message } # rubocop:disable Style/CaseEquality
|
117
132
|
end
|
118
133
|
|
119
134
|
def lint_lines(linter)
|
@@ -6,8 +6,8 @@ module HamlLint
|
|
6
6
|
# for writing code without having the leading indentation count.
|
7
7
|
module IndentNormalizer
|
8
8
|
def normalize_indent(code)
|
9
|
-
leading_indent = code[
|
10
|
-
code.
|
9
|
+
leading_indent = code[/([ \t]*)/, 1]
|
10
|
+
code.gsub(/^#{leading_indent}/, '')
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
@@ -14,13 +14,21 @@ module HamlLint
|
|
14
14
|
}
|
15
15
|
end
|
16
16
|
|
17
|
+
let(:autocorrect) { nil }
|
18
|
+
|
17
19
|
let(:config) { options[:config].for_linter(described_class) }
|
18
20
|
|
19
21
|
let(:document) { HamlLint::Document.new(normalize_indent(haml), options) }
|
20
22
|
|
23
|
+
# :run_or_raise, :run, or nil to not auto-call something
|
24
|
+
let(:run_method_to_use) { :run_or_raise }
|
25
|
+
|
21
26
|
subject { described_class.new(config) }
|
22
27
|
|
23
|
-
before
|
28
|
+
before do
|
29
|
+
next unless run_method_to_use
|
30
|
+
subject.send(run_method_to_use, document, autocorrect: autocorrect)
|
31
|
+
end
|
24
32
|
end
|
25
33
|
end
|
26
34
|
end
|
@@ -0,0 +1,158 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Makes writing tests for linters a lot DRYer by taking any currently `haml`
|
4
|
+
# variable defined via `let` and normalizing it and running the linter against
|
5
|
+
# it, allowing specs to simply specify whether a lint was reported.
|
6
|
+
|
7
|
+
module HamlLint
|
8
|
+
module Spec
|
9
|
+
module SharedRubocopAutocorrectContext
|
10
|
+
RSpec.shared_context 'rubocop_autocorrect' do
|
11
|
+
# Setting ENV['STUB_RUBOCOP'] to 1 or true makes rubocop tests faster by not involving rubocop.
|
12
|
+
# It is sometimes automatically activated for tests which need a different Rubocop version
|
13
|
+
stub_rubocop_env_result = %w[1 true].include?(ENV['STUB_RUBOCOP'])
|
14
|
+
|
15
|
+
let(:stub_rubocop?) do |example|
|
16
|
+
# Tries to match `{% rubocop_version <= '1.2' %}`, extracting the operator and the "number"
|
17
|
+
rubocop_version_regex = /\{%\s*rubocop_version\s*([^\w\s]+?)\s*['"]?(\d+(\.\d+)*)['"]?\s*%\}/
|
18
|
+
requirements = example.metadata[:full_description].scan(rubocop_version_regex)
|
19
|
+
|
20
|
+
# This can be used by the requirements in eval
|
21
|
+
rubocop_version = HamlLint::VersionComparer.for_rubocop
|
22
|
+
|
23
|
+
accepted = requirements.all? do |(operator, version)|
|
24
|
+
rubocop_version.send(operator, version)
|
25
|
+
end
|
26
|
+
|
27
|
+
next true unless accepted
|
28
|
+
|
29
|
+
# Doing this last so that exceptions in the requirements always fail
|
30
|
+
next true if stub_rubocop_env_result
|
31
|
+
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
let(:supported_haml?) do |example|
|
36
|
+
# Tries to match `{% haml_version >= '5' %}`, extracting the operator and the "number"
|
37
|
+
haml_version_regex = /\{%\s*haml_version\s*([^\w\s]+?)\s*['"]?(\d+(\.\d+)*)['"]?\s*%\}/
|
38
|
+
requirements = example.metadata[:full_description].scan(haml_version_regex)
|
39
|
+
|
40
|
+
# This can be used by the requirements in eval
|
41
|
+
haml_version = HamlLint::VersionComparer.for_haml
|
42
|
+
|
43
|
+
requirements.all? do |(operator, version)|
|
44
|
+
haml_version.send(operator, version)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
before do
|
49
|
+
if stub_rubocop?
|
50
|
+
skip if end_ruby.include?('SKIP')
|
51
|
+
subject.stub(:process_ruby_source).and_return(end_ruby)
|
52
|
+
end
|
53
|
+
subject.stub(:transfer_corrections?).and_return(true)
|
54
|
+
end
|
55
|
+
|
56
|
+
include_context 'linter'
|
57
|
+
# The goal is not to test rubocop the gem, so no need to test the details using both
|
58
|
+
# :safe and :all
|
59
|
+
let(:autocorrect) { :all }
|
60
|
+
|
61
|
+
# We want want to do error handling ourself
|
62
|
+
let(:run_method_to_use) { nil }
|
63
|
+
|
64
|
+
let(:steps_parts) do
|
65
|
+
parts = steps_string.split(/^[ \t]*---[ \t]*\n/, -1)
|
66
|
+
raise "Expected 4 steps, got: #{parts.size}" if parts.size != 4
|
67
|
+
parts
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:start_haml) { steps_parts[0] }
|
71
|
+
|
72
|
+
let(:start_ruby) do
|
73
|
+
lines = steps_parts[1].split("\n", -1)
|
74
|
+
current_matching_line = 1
|
75
|
+
@source_map = {}
|
76
|
+
lines.each.with_index do |line, i|
|
77
|
+
next unless line =~ /\S/
|
78
|
+
mo = line.match(/^(.*?)\$?\s*\$\$(\d+)$/)
|
79
|
+
if mo
|
80
|
+
lines[i] = mo[1]
|
81
|
+
current_matching_line = Integer(mo[2])
|
82
|
+
end
|
83
|
+
@source_map[i + 1] = current_matching_line
|
84
|
+
end
|
85
|
+
lines.join("\n")
|
86
|
+
end
|
87
|
+
|
88
|
+
let(:source_map) do
|
89
|
+
start_ruby
|
90
|
+
@source_map
|
91
|
+
end
|
92
|
+
|
93
|
+
let(:end_ruby) { steps_parts[2] }
|
94
|
+
|
95
|
+
let(:end_haml) { steps_parts[3] }
|
96
|
+
|
97
|
+
# Used by the 'linter' context
|
98
|
+
let(:haml) { start_haml }
|
99
|
+
|
100
|
+
# steps_string is string of multiple lines describing the steps that
|
101
|
+
# the code will take:
|
102
|
+
# 1) input haml
|
103
|
+
# 2) extracted ruby
|
104
|
+
# 3) the corrected ruby
|
105
|
+
# 4) the corrected haml
|
106
|
+
# Each steps is delimited by a line with ---
|
107
|
+
def follows_steps # rubocop:disable Metrics
|
108
|
+
skip unless supported_haml?
|
109
|
+
|
110
|
+
begin
|
111
|
+
subject.run_or_raise(document, autocorrect: autocorrect)
|
112
|
+
rescue StandardError => e
|
113
|
+
exception_while_running = e
|
114
|
+
end
|
115
|
+
|
116
|
+
syntax_lints = subject.lints.select { |lint| lint.message =~ %r{Lint/Syntax} }
|
117
|
+
|
118
|
+
if start_ruby.strip != 'SKIP' && subject.last_extracted_source
|
119
|
+
matcher = eq(start_ruby)
|
120
|
+
subject.last_extracted_source.source.should(
|
121
|
+
matcher,
|
122
|
+
-> { "Extracted Ruby is different from expected. #{matcher.failure_message}\n#{format_lints}" }
|
123
|
+
)
|
124
|
+
end
|
125
|
+
|
126
|
+
syntax_lints.should(be_empty, "Generated Ruby has Syntax Lints:\n#{format_lints(syntax_lints)}")
|
127
|
+
|
128
|
+
if end_ruby.strip != 'SKIP' && subject.last_new_ruby_source
|
129
|
+
matcher = eq(end_ruby)
|
130
|
+
subject.last_new_ruby_source.should(
|
131
|
+
matcher,
|
132
|
+
-> { "Ruby generated by RuboCop is different from expected. #{matcher.failure_message}\n#{format_lints}" }
|
133
|
+
)
|
134
|
+
end
|
135
|
+
|
136
|
+
raise exception_while_running if exception_while_running
|
137
|
+
|
138
|
+
matcher = eq(end_haml)
|
139
|
+
document.source.should(
|
140
|
+
matcher,
|
141
|
+
-> { "Final HAML is different from expected. #{matcher.failure_message}\n#{format_lints}" }
|
142
|
+
)
|
143
|
+
|
144
|
+
if subject.last_extracted_source && start_ruby.strip != 'SKIP'
|
145
|
+
subject.last_extracted_source.source_map.should == source_map
|
146
|
+
end
|
147
|
+
|
148
|
+
haml_different = start_haml != end_haml
|
149
|
+
document.source_was_changed.should == haml_different
|
150
|
+
end
|
151
|
+
|
152
|
+
def format_lints(lints = subject.lints)
|
153
|
+
lints.map { |lint| "#{lint.line}:#{lint.message}" }.join("\n")
|
154
|
+
end
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
data/lib/haml_lint/spec.rb
CHANGED
@@ -7,5 +7,15 @@ module HamlLint::Tree
|
|
7
7
|
def filter_type
|
8
8
|
@value[:name]
|
9
9
|
end
|
10
|
+
|
11
|
+
def text
|
12
|
+
# Seems HAML strips the starting blank lines... without them, line numbers become offset,
|
13
|
+
# breaking the source_map and auto-correct
|
14
|
+
|
15
|
+
nb_blank_lines = 0
|
16
|
+
nb_blank_lines += 1 while @document.source_lines[line + nb_blank_lines]&.empty?
|
17
|
+
|
18
|
+
"#{"\n" * nb_blank_lines}#{super}"
|
19
|
+
end
|
10
20
|
end
|
11
21
|
end
|
data/lib/haml_lint/tree/node.rb
CHANGED
@@ -104,8 +104,13 @@ module HamlLint::Tree
|
|
104
104
|
def line_numbers
|
105
105
|
return (line..line) unless @value && text
|
106
106
|
|
107
|
-
end_line =
|
108
|
-
|
107
|
+
end_line = if !lines.empty?
|
108
|
+
line + lines.count - 1
|
109
|
+
elsif children.empty?
|
110
|
+
nontrivial_end_line
|
111
|
+
else
|
112
|
+
line
|
113
|
+
end
|
109
114
|
|
110
115
|
(line..end_line)
|
111
116
|
end
|
@@ -155,6 +160,10 @@ module HamlLint::Tree
|
|
155
160
|
@value[:text].to_s
|
156
161
|
end
|
157
162
|
|
163
|
+
def keyword
|
164
|
+
@value[:keyword]
|
165
|
+
end
|
166
|
+
|
158
167
|
private
|
159
168
|
|
160
169
|
# Discovers the end line of the node when there are no lines.
|
@@ -164,7 +173,7 @@ module HamlLint::Tree
|
|
164
173
|
if successor
|
165
174
|
successor.line_numbers.begin - 1
|
166
175
|
else
|
167
|
-
@document.
|
176
|
+
@document.last_non_empty_line
|
168
177
|
end
|
169
178
|
end
|
170
179
|
|
@@ -212,7 +221,7 @@ module HamlLint::Tree
|
|
212
221
|
# @param node [HamlLint::Tree::Node]
|
213
222
|
# @return [Array<HamlLint::Tree::Node>]
|
214
223
|
def subsequents(node)
|
215
|
-
siblings[(position(node) + 1)
|
224
|
+
siblings[(position(node) + 1)..]
|
216
225
|
end
|
217
226
|
|
218
227
|
private
|
@@ -9,7 +9,13 @@ module HamlLint::Tree
|
|
9
9
|
#
|
10
10
|
# @return [ParsedRuby] syntax tree in the form returned by Parser gem
|
11
11
|
def parsed_script
|
12
|
-
|
12
|
+
statement =
|
13
|
+
if children.empty?
|
14
|
+
script
|
15
|
+
else
|
16
|
+
"#{script}#{@value[:keyword] == 'case' ? ';when 0;end' : ';end'}"
|
17
|
+
end
|
18
|
+
HamlLint::ParsedRuby.new(HamlLint::RubyParser.new.parse(statement))
|
13
19
|
end
|
14
20
|
|
15
21
|
# Returns the source for the script following the `-` marker.
|
@@ -8,7 +8,22 @@ module HamlLint::Tree
|
|
8
8
|
#
|
9
9
|
# @return [ParsedRuby] syntax tree in the form returned by Parser gem
|
10
10
|
def parsed_script
|
11
|
-
|
11
|
+
statement =
|
12
|
+
case keyword = @value[:keyword]
|
13
|
+
when 'else', 'elsif'
|
14
|
+
'if 0;' + script + ';end'
|
15
|
+
when 'when'
|
16
|
+
'case;' + script + ';end'
|
17
|
+
when 'rescue', 'ensure'
|
18
|
+
'begin;' + script + ';end'
|
19
|
+
else
|
20
|
+
if children.empty?
|
21
|
+
script
|
22
|
+
else
|
23
|
+
"#{script}#{keyword == 'case' ? ';when 0;end' : ';end'}"
|
24
|
+
end
|
25
|
+
end
|
26
|
+
HamlLint::ParsedRuby.new(HamlLint::RubyParser.new.parse(statement))
|
12
27
|
end
|
13
28
|
|
14
29
|
# Returns the source for the script following the `-` marker.
|
@@ -2,7 +2,7 @@
|
|
2
2
|
|
3
3
|
module HamlLint::Tree
|
4
4
|
# Represents a tag node in a HAML document.
|
5
|
-
class TagNode < Node
|
5
|
+
class TagNode < Node
|
6
6
|
# Computed set of attribute hashes code.
|
7
7
|
#
|
8
8
|
# This is a combination of all dynamically calculated attributes from the
|
@@ -49,9 +49,7 @@ module HamlLint::Tree
|
|
49
49
|
# dot removed
|
50
50
|
def static_classes
|
51
51
|
@static_classes ||=
|
52
|
-
|
53
|
-
static_attributes_source.scan(/\.([-:\w]+)/)
|
54
|
-
end
|
52
|
+
static_attributes_source.scan(/\.([-:\w]+)/)
|
55
53
|
end
|
56
54
|
|
57
55
|
# List of ids statically defined for this tag.
|
@@ -63,9 +61,7 @@ module HamlLint::Tree
|
|
63
61
|
# removed
|
64
62
|
def static_ids
|
65
63
|
@static_ids ||=
|
66
|
-
|
67
|
-
static_attributes_source.scan(/#([-:\w]+)/)
|
68
|
-
end
|
64
|
+
static_attributes_source.scan(/#([-:\w]+)/)
|
69
65
|
end
|
70
66
|
|
71
67
|
# Static element attributes defined after the tag name.
|
@@ -101,7 +97,7 @@ module HamlLint::Tree
|
|
101
97
|
@attributes_source ||=
|
102
98
|
begin
|
103
99
|
_explicit_tag, static_attrs, rest =
|
104
|
-
source_code.scan(/\A\s*(%[-:\w]+)?([-:\w
|
100
|
+
source_code.scan(/\A\s*(%[-:\w]+)?([-:\w.\#]*)(.*)/m)[0]
|
105
101
|
|
106
102
|
attr_types = {
|
107
103
|
'{' => [:hash, %w[{ }]],
|
@@ -220,7 +216,7 @@ module HamlLint::Tree
|
|
220
216
|
#
|
221
217
|
# @return [true,false]
|
222
218
|
def remove_outer_whitespace?
|
223
|
-
!!@value[:nuke_outer_whitespace]
|
219
|
+
!!@value[:nuke_outer_whitespace]
|
224
220
|
end
|
225
221
|
|
226
222
|
# Returns the script source that will be evaluated to produce this tag's
|