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
@@ -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
|