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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/bin/haml-lint +1 -1
  3. data/config/default.yml +9 -27
  4. data/config/forced_rubocop_config.yml +180 -0
  5. data/lib/haml_lint/adapter/haml_4.rb +20 -0
  6. data/lib/haml_lint/adapter/haml_5.rb +11 -0
  7. data/lib/haml_lint/adapter/haml_6.rb +59 -0
  8. data/lib/haml_lint/adapter.rb +2 -0
  9. data/lib/haml_lint/cli.rb +8 -3
  10. data/lib/haml_lint/configuration_loader.rb +49 -13
  11. data/lib/haml_lint/document.rb +89 -8
  12. data/lib/haml_lint/exceptions.rb +6 -0
  13. data/lib/haml_lint/extensions/haml_util_unescape_interpolation_tracking.rb +35 -0
  14. data/lib/haml_lint/file_finder.rb +2 -2
  15. data/lib/haml_lint/lint.rb +10 -1
  16. data/lib/haml_lint/linter/final_newline.rb +4 -3
  17. data/lib/haml_lint/linter/implicit_div.rb +1 -1
  18. data/lib/haml_lint/linter/indentation.rb +3 -3
  19. data/lib/haml_lint/linter/no_placeholders.rb +18 -0
  20. data/lib/haml_lint/linter/repeated_id.rb +2 -1
  21. data/lib/haml_lint/linter/rubocop.rb +353 -59
  22. data/lib/haml_lint/linter/space_before_script.rb +8 -10
  23. data/lib/haml_lint/linter/trailing_empty_lines.rb +22 -0
  24. data/lib/haml_lint/linter/unnecessary_string_output.rb +1 -1
  25. data/lib/haml_lint/linter/view_length.rb +1 -1
  26. data/lib/haml_lint/linter.rb +60 -10
  27. data/lib/haml_lint/linter_registry.rb +3 -5
  28. data/lib/haml_lint/logger.rb +2 -2
  29. data/lib/haml_lint/options.rb +26 -2
  30. data/lib/haml_lint/rake_task.rb +2 -2
  31. data/lib/haml_lint/reporter/hash_reporter.rb +1 -3
  32. data/lib/haml_lint/reporter/offense_count_reporter.rb +1 -1
  33. data/lib/haml_lint/reporter/utils.rb +33 -4
  34. data/lib/haml_lint/ruby_extraction/ad_hoc_chunk.rb +24 -0
  35. data/lib/haml_lint/ruby_extraction/base_chunk.rb +114 -0
  36. data/lib/haml_lint/ruby_extraction/chunk_extractor.rb +672 -0
  37. data/lib/haml_lint/ruby_extraction/coordinator.rb +181 -0
  38. data/lib/haml_lint/ruby_extraction/haml_comment_chunk.rb +34 -0
  39. data/lib/haml_lint/ruby_extraction/implicit_end_chunk.rb +17 -0
  40. data/lib/haml_lint/ruby_extraction/interpolation_chunk.rb +26 -0
  41. data/lib/haml_lint/ruby_extraction/non_ruby_filter_chunk.rb +32 -0
  42. data/lib/haml_lint/ruby_extraction/placeholder_marker_chunk.rb +40 -0
  43. data/lib/haml_lint/ruby_extraction/ruby_filter_chunk.rb +33 -0
  44. data/lib/haml_lint/ruby_extraction/ruby_source.rb +5 -0
  45. data/lib/haml_lint/ruby_extraction/script_chunk.rb +251 -0
  46. data/lib/haml_lint/ruby_extraction/tag_attributes_chunk.rb +63 -0
  47. data/lib/haml_lint/ruby_extraction/tag_script_chunk.rb +30 -0
  48. data/lib/haml_lint/ruby_parser.rb +11 -1
  49. data/lib/haml_lint/runner.rb +35 -3
  50. data/lib/haml_lint/spec/matchers/report_lint.rb +22 -7
  51. data/lib/haml_lint/spec/normalize_indent.rb +2 -2
  52. data/lib/haml_lint/spec/shared_linter_context.rb +9 -1
  53. data/lib/haml_lint/spec/shared_rubocop_autocorrect_context.rb +158 -0
  54. data/lib/haml_lint/spec.rb +1 -0
  55. data/lib/haml_lint/tree/filter_node.rb +10 -0
  56. data/lib/haml_lint/tree/node.rb +13 -4
  57. data/lib/haml_lint/tree/script_node.rb +7 -1
  58. data/lib/haml_lint/tree/silent_script_node.rb +16 -1
  59. data/lib/haml_lint/tree/tag_node.rb +5 -9
  60. data/lib/haml_lint/utils.rb +135 -5
  61. data/lib/haml_lint/version.rb +1 -1
  62. data/lib/haml_lint/version_comparer.rb +25 -0
  63. data/lib/haml_lint.rb +12 -0
  64. metadata +29 -15
  65. 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
@@ -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).map do |linter|
92
- linter.run(document)
93
- end.flatten
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 == expected_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
- lint_messages(linter).all? { |message| message == expected_message }
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[/^(\s*)/, 1]
10
- code.lstrip.gsub(/\n#{leading_indent}/, "\n")
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 { subject.run(document) }
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
@@ -2,4 +2,5 @@
2
2
 
3
3
  require 'haml_lint/spec/normalize_indent'
4
4
  require 'haml_lint/spec/shared_linter_context'
5
+ require 'haml_lint/spec/shared_rubocop_autocorrect_context'
5
6
  require 'haml_lint/spec/matchers/report_lint'
@@ -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
@@ -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 = line + lines.count
108
- end_line = nontrivial_end_line if line == end_line && children.empty?
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.source_lines.count
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)..-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
- HamlLint::ParsedRuby.new(HamlLint::RubyParser.new.parse(script))
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
- HamlLint::ParsedRuby.new(HamlLint::RubyParser.new.parse(script))
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 # rubocop:disable Metrics/ClassLength
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
- begin
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
- begin
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\.\#]*)(.*)/m)[0]
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] # rubocop:disable Style/DoubleNegation
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