haml_lint 0.13.0 → 0.14.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 (48) hide show
  1. checksums.yaml +4 -4
  2. data/config/default.yml +1 -0
  3. data/lib/haml_lint/cli.rb +25 -8
  4. data/lib/haml_lint/configuration.rb +56 -34
  5. data/lib/haml_lint/configuration_loader.rb +22 -6
  6. data/lib/haml_lint/constants.rb +1 -1
  7. data/lib/haml_lint/document.rb +102 -0
  8. data/lib/haml_lint/file_finder.rb +14 -5
  9. data/lib/haml_lint/lint.rb +17 -1
  10. data/lib/haml_lint/linter/alt_text.rb +1 -1
  11. data/lib/haml_lint/linter/class_attribute_with_static_value.rb +2 -2
  12. data/lib/haml_lint/linter/classes_before_ids.rb +2 -2
  13. data/lib/haml_lint/linter/consecutive_comments.rb +3 -5
  14. data/lib/haml_lint/linter/consecutive_silent_scripts.rb +5 -5
  15. data/lib/haml_lint/linter/empty_script.rb +1 -1
  16. data/lib/haml_lint/linter/html_attributes.rb +2 -2
  17. data/lib/haml_lint/linter/implicit_div.rb +3 -3
  18. data/lib/haml_lint/linter/leading_comment_space.rb +1 -1
  19. data/lib/haml_lint/linter/line_length.rb +2 -2
  20. data/lib/haml_lint/linter/multiline_pipe.rb +3 -3
  21. data/lib/haml_lint/linter/multiline_script.rb +3 -3
  22. data/lib/haml_lint/linter/object_reference_attributes.rb +1 -1
  23. data/lib/haml_lint/linter/rubocop.rb +60 -34
  24. data/lib/haml_lint/linter/ruby_comments.rb +1 -1
  25. data/lib/haml_lint/linter/space_before_script.rb +4 -4
  26. data/lib/haml_lint/linter/space_inside_hash_attributes.rb +2 -2
  27. data/lib/haml_lint/linter/tag_name.rb +1 -1
  28. data/lib/haml_lint/linter/trailing_whitespace.rb +2 -2
  29. data/lib/haml_lint/linter/unnecessary_interpolation.rb +3 -3
  30. data/lib/haml_lint/linter/unnecessary_string_output.rb +10 -3
  31. data/lib/haml_lint/linter.rb +30 -10
  32. data/lib/haml_lint/linter_registry.rb +13 -2
  33. data/lib/haml_lint/linter_selector.rb +77 -0
  34. data/lib/haml_lint/node_transformer.rb +5 -5
  35. data/lib/haml_lint/options.rb +13 -6
  36. data/lib/haml_lint/rake_task.rb +18 -3
  37. data/lib/haml_lint/report.rb +7 -0
  38. data/lib/haml_lint/reporter/default_reporter.rb +2 -2
  39. data/lib/haml_lint/reporter/json_reporter.rb +15 -10
  40. data/lib/haml_lint/reporter.rb +17 -11
  41. data/lib/haml_lint/{script_extractor.rb → ruby_extractor.rb} +26 -17
  42. data/lib/haml_lint/runner.rb +44 -44
  43. data/lib/haml_lint/tree/node.rb +7 -8
  44. data/lib/haml_lint/utils.rb +88 -21
  45. data/lib/haml_lint/version.rb +1 -1
  46. data/lib/haml_lint.rb +2 -1
  47. metadata +5 -4
  48. data/lib/haml_lint/parser.rb +0 -87
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 343fc1d49926d0ac21d87fbfc26b93c518d690fc
4
- data.tar.gz: 79d58c8fe3e0ded6c8cde5dee115276d84720fc1
3
+ metadata.gz: fdd406c711a12f70bba2b26982550e7f190b2c61
4
+ data.tar.gz: 2cd4a631a543de9987408c30a4367d18bff33d6b
5
5
  SHA512:
6
- metadata.gz: 26259ff8ae9e582436736b4830a90c1256259a32d9d36372ec9dc8e823582c1cb4682bf2edb38c5db78b1d325c1d2baadd45f05fa8a1a3e6153aaa610bd38201
7
- data.tar.gz: c30b1bcc9d65705bc944bd90e6743e2f26e35ebcb45df0158ad8db7702a7b03e7f94fe212265d91c88d780bbd112239bf88679f3e1e7614c585447f46d626468
6
+ metadata.gz: 89371444076d421e9589f2b34b3867b6b0387f0f07af00f119a520d20b296b3a77088e425e36cf5b29a1b043cd24e4987b15557a9bc8c0e502985b5c124d0014
7
+ data.tar.gz: 3053c5a7d28d8cc7e242bb0346cc83e8e6a65935dad36042678eedd2d8a21f8784085c67887a528baec7698fae8e2ceb958a76e5ce787e251c41b2ffa6f346ef
data/config/default.yml CHANGED
@@ -61,6 +61,7 @@ linters:
61
61
  - Style/AlignParameters
62
62
  - Style/BlockNesting
63
63
  - Style/FileName
64
+ - Style/FinalNewline
64
65
  - Style/IfUnlessModifier
65
66
  - Style/IndentationWidth
66
67
  - Style/Next
data/lib/haml_lint/cli.rb CHANGED
@@ -1,3 +1,4 @@
1
+ require 'haml_lint'
1
2
  require 'haml_lint/options'
2
3
 
3
4
  require 'sysexits'
@@ -5,8 +6,8 @@ require 'sysexits'
5
6
  module HamlLint
6
7
  # Command line application interface.
7
8
  class CLI
8
- attr_accessor :options
9
-
9
+ # Create a CLI that outputs to the specified logger.
10
+ #
10
11
  # @param logger [HamlLint::Logger]
11
12
  def initialize(logger)
12
13
  @log = logger
@@ -16,7 +17,7 @@ module HamlLint
16
17
  # based on those arguments.
17
18
  #
18
19
  # @param args [Array<String>] command line arguments
19
- # @return [Fixnum] exit status returned by the application
20
+ # @return [Integer] exit status code
20
21
  def run(args)
21
22
  options = HamlLint::Options.new.parse(args)
22
23
  act_on_options(options)
@@ -28,6 +29,9 @@ module HamlLint
28
29
 
29
30
  attr_reader :log
30
31
 
32
+ # Given the provided options, execute the appropriate command.
33
+ #
34
+ # @return [Integer] exit status code
31
35
  def act_on_options(options)
32
36
  log.color_enabled = options.fetch(:color, log.tty?)
33
37
 
@@ -48,6 +52,8 @@ module HamlLint
48
52
  end
49
53
  end
50
54
 
55
+ # Outputs a message and returns an appropriate error code for the specified
56
+ # exception.
51
57
  def handle_exception(ex)
52
58
  case ex
53
59
  when HamlLint::Exceptions::ConfigurationError
@@ -69,21 +75,27 @@ module HamlLint
69
75
  end
70
76
  end
71
77
 
78
+ # Scans the files specified by the given options for lints.
79
+ #
80
+ # @return [Integer] exit status code
72
81
  def scan_for_lints(options)
73
82
  report = Runner.new.run(options)
74
83
  print_report(report, options)
75
84
  report.failed? ? Sysexits::EX_DATAERR : Sysexits::EX_OK
76
85
  end
77
86
 
87
+ # Outputs a report of the linter run using the specified reporter.
78
88
  def print_report(report, options)
79
- reporter = options.fetch(:reporter, Reporter::DefaultReporter).new(log, report)
80
- reporter.report_lints
89
+ reporter = options.fetch(:reporter,
90
+ HamlLint::Reporter::DefaultReporter).new(log)
91
+ reporter.display_report(report)
81
92
  end
82
93
 
94
+ # Outputs a list of all currently available linters.
83
95
  def print_available_linters
84
96
  log.info 'Available linters:'
85
97
 
86
- linter_names = LinterRegistry.linters.map do |linter|
98
+ linter_names = HamlLint::LinterRegistry.linters.map do |linter|
87
99
  linter.name.split('::').last
88
100
  end
89
101
 
@@ -92,10 +104,11 @@ module HamlLint
92
104
  end
93
105
  end
94
106
 
107
+ # Outputs a list of currently available reporters.
95
108
  def print_available_reporters
96
109
  log.info 'Available reporters:'
97
110
 
98
- reporter_names = Reporter.descendants.map do |reporter|
111
+ reporter_names = HamlLint::Reporter.descendants.map do |reporter|
99
112
  reporter.name.split('::').last.sub(/Reporter$/, '').downcase
100
113
  end
101
114
 
@@ -104,14 +117,18 @@ module HamlLint
104
117
  end
105
118
  end
106
119
 
120
+ # Outputs help documentation.
107
121
  def print_help(options)
108
122
  log.log options[:help]
109
123
  end
110
124
 
125
+ # Outputs the application name and version.
111
126
  def print_version
112
- log.log "#{APP_NAME} #{HamlLint::VERSION}"
127
+ log.log "#{HamlLint::APP_NAME} #{HamlLint::VERSION}"
113
128
  end
114
129
 
130
+ # Outputs the backtrace of an exception with instructions on how to report
131
+ # the issue.
115
132
  def print_unexpected_exception(ex)
116
133
  log.bold_error ex.message
117
134
  log.error ex.backtrace.join("\n")
@@ -1,6 +1,12 @@
1
1
  module HamlLint
2
- # Stores configuration for haml-lint.
2
+ # Stores runtime configuration for the application.
3
+ #
4
+ # The purpose of this class is to validate and ensure all configurations
5
+ # satisfy some basic pre-conditions so other parts of the application don't
6
+ # have to check the configuration for errors. It should have no knowledge of
7
+ # how these configuration values are ultimately used.
3
8
  class Configuration
9
+ # Internal hash storing the configuration.
4
10
  attr_reader :hash
5
11
 
6
12
  # Creates a configuration from the given options hash.
@@ -11,6 +17,14 @@ module HamlLint
11
17
  validate
12
18
  end
13
19
 
20
+ # Access the configuration as if it were a hash.
21
+ #
22
+ # @param key [String]
23
+ # @return [Array,Hash,Number,String]
24
+ def [](key)
25
+ @hash[key]
26
+ end
27
+
14
28
  # Compares this configuration with another.
15
29
  #
16
30
  # @param other [HamlLint::Configuration]
@@ -30,19 +44,9 @@ module HamlLint
30
44
  linter.name.split('::').last
31
45
  when HamlLint::Linter
32
46
  linter.name
33
- else
34
- linter.to_s
35
47
  end
36
48
 
37
- smart_merge(@hash['linters']['ALL'],
38
- @hash['linters'].fetch(linter_name, {})).freeze
39
- end
40
-
41
- # Returns whether the specified linter is enabled by this configuration.
42
- #
43
- # @param linter [HamlLint::Linter,String]
44
- def linter_enabled?(linter)
45
- for_linter(linter)['enabled'] != false
49
+ @hash['linters'].fetch(linter_name, {}).dup.freeze
46
50
  end
47
51
 
48
52
  # Merges the given configuration with this one, returning a new
@@ -56,18 +60,14 @@ module HamlLint
56
60
 
57
61
  private
58
62
 
59
- # Validates the configuration for any invalid options, normalizing it where
60
- # possible.
61
- def validate
62
- @hash = convert_nils_to_empty_hashes(@hash)
63
- ensure_linter_section_exists(@hash)
64
- end
65
-
63
+ # Merge two hashes such that nested hashes are merged rather than replaced.
64
+ #
65
+ # @param parent [Hash]
66
+ # @param child [Hash]
67
+ # @return [Hash]
66
68
  def smart_merge(parent, child)
67
69
  parent.merge(child) do |_key, old, new|
68
70
  case old
69
- when Array
70
- old + Array(new)
71
71
  when Hash
72
72
  smart_merge(old, new)
73
73
  else
@@ -76,21 +76,43 @@ module HamlLint
76
76
  end
77
77
  end
78
78
 
79
- def ensure_linter_section_exists(hash)
80
- hash['linters'] ||= {}
81
- hash['linters']['ALL'] ||= {}
79
+ # Validates the configuration for any invalid options, normalizing it where
80
+ # possible.
81
+ def validate
82
+ ensure_exclude_option_array_exists
83
+ ensure_linter_section_exists
84
+ ensure_linter_include_exclude_arrays_exist
85
+ ensure_linter_severity_valid
86
+ end
87
+
88
+ # Ensures the `exclude` global option is an array.
89
+ def ensure_exclude_option_array_exists
90
+ @hash['exclude'] = Array(@hash['exclude'])
91
+ end
92
+
93
+ # Ensures the `linters` configuration section exists.
94
+ def ensure_linter_section_exists
95
+ @hash['linters'] ||= {}
96
+ end
97
+
98
+ # Ensure `include` and `exclude` options for linters are arrays
99
+ # (since users can specify a single string glob pattern for convenience)
100
+ def ensure_linter_include_exclude_arrays_exist
101
+ @hash['linters'].keys.each do |linter_name|
102
+ %w[include exclude].each do |option|
103
+ linter_config = @hash['linters'][linter_name]
104
+ linter_config[option] = Array(linter_config[option])
105
+ end
106
+ end
82
107
  end
83
108
 
84
- def convert_nils_to_empty_hashes(hash)
85
- hash.each_with_object({}) do |(key, value), h|
86
- h[key] =
87
- case value
88
- when nil then {}
89
- when Hash then convert_nils_to_empty_hashes(value)
90
- else
91
- value
92
- end
93
- h
109
+ def ensure_linter_severity_valid
110
+ @hash['linters'].each do |linter_name, linter_config|
111
+ severity = linter_config['severity']
112
+ unless [nil, 'warning', 'error'].include?(severity)
113
+ raise HamlLint::Exceptions::ConfigurationError,
114
+ "Invalid severity '#{severity}' specified for #{linter_name}"
115
+ end
94
116
  end
95
117
  end
96
118
  end
@@ -4,10 +4,12 @@ require 'yaml'
4
4
  module HamlLint
5
5
  # Manages configuration file loading.
6
6
  class ConfigurationLoader
7
- DEFAULT_CONFIG_PATH = File.join(HAML_LINT_HOME, 'config', 'default.yml')
7
+ DEFAULT_CONFIG_PATH = File.join(HamlLint::HOME, 'config', 'default.yml')
8
8
  CONFIG_FILE_NAME = '.haml-lint.yml'
9
9
 
10
10
  class << self
11
+ # Load configuration file given the current working directory the
12
+ # application is running within.
11
13
  def load_applicable_config
12
14
  directory = File.expand_path(Dir.pwd)
13
15
  config_file = possible_config_files(directory).find(&:file?)
@@ -19,33 +21,42 @@ module HamlLint
19
21
  end
20
22
  end
21
23
 
24
+ # Loads the built-in default configuration.
22
25
  def default_configuration
23
26
  @default_config ||= load_from_file(DEFAULT_CONFIG_PATH)
24
27
  end
25
28
 
26
29
  # Loads a configuration, ensuring it extends the default configuration.
30
+ #
31
+ # @param file [String]
32
+ # @return [HamlLint::Configuration]
27
33
  def load_file(file)
28
34
  config = load_from_file(file)
29
35
 
30
36
  default_configuration.merge(config)
31
- rescue => error
37
+ rescue Psych::SyntaxError, Errno::ENOENT => error
32
38
  raise HamlLint::Exceptions::ConfigurationError,
33
39
  "Unable to load configuration from '#{file}': #{error}",
34
40
  error.backtrace
35
41
  end
36
42
 
43
+ # Creates a configuration from the specified hash, ensuring it extends the
44
+ # default configuration.
45
+ #
46
+ # @param hash [Hash]
47
+ # @return [HamlLint::Configuration]
37
48
  def load_hash(hash)
38
49
  config = HamlLint::Configuration.new(hash)
39
50
 
40
51
  default_configuration.merge(config)
41
- rescue => error
42
- raise HamlLint::Exceptions::ConfigurationError,
43
- "Unable to load configuration from '#{file}': #{error}",
44
- error.backtrace
45
52
  end
46
53
 
47
54
  private
48
55
 
56
+ # Parses and loads a configuration from the given file.
57
+ #
58
+ # @param file [String]
59
+ # @return [HamlLint::Configuration]
49
60
  def load_from_file(file)
50
61
  hash =
51
62
  if yaml = YAML.load_file(file)
@@ -57,6 +68,11 @@ module HamlLint
57
68
  HamlLint::Configuration.new(hash)
58
69
  end
59
70
 
71
+ # Returns a list of possible configuration files given the context of the
72
+ # specified directory.
73
+ #
74
+ # @param directory [String]
75
+ # @return [Array<Pathname>]
60
76
  def possible_config_files(directory)
61
77
  files = Pathname.new(directory)
62
78
  .enum_for(:ascend)
@@ -1,6 +1,6 @@
1
1
  # Global application constants.
2
2
  module HamlLint
3
- HAML_LINT_HOME = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
3
+ HOME = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
4
4
  APP_NAME = 'haml-lint'
5
5
 
6
6
  REPO_URL = 'https://github.com/brigade/haml-lint'
@@ -0,0 +1,102 @@
1
+ module HamlLint
2
+ # Represents a parsed Haml document and its associated metadata.
3
+ class Document
4
+ # File name given to source code parsed from just a string.
5
+ STRING_SOURCE = '(string)'
6
+
7
+ # @return [HamlLint::Configuration] Configuration used to parse template
8
+ attr_reader :config
9
+
10
+ # @return [String] Haml template file path
11
+ attr_reader :file
12
+
13
+ # @return [HamlLint::Tree::Node] Root of the parse tree
14
+ attr_reader :tree
15
+
16
+ # @return [String] original source code
17
+ attr_reader :source
18
+
19
+ # @return [Array<String>] original source code as an array of lines
20
+ attr_reader :source_lines
21
+
22
+ # Parses the specified Haml code into a {Document}.
23
+ #
24
+ # @param source [String] Haml code to parse
25
+ # @param options [Hash]
26
+ # @option options :file [String] file name of document that was parsed
27
+ # @raise [Haml::Parser::Error] if there was a problem parsing the document
28
+ def initialize(source, options)
29
+ @config = options[:config]
30
+ @file = options.fetch(:file, STRING_SOURCE)
31
+
32
+ process_source(source)
33
+ end
34
+
35
+ private
36
+
37
+ # @param source [String] Haml code to parse
38
+ # @raise [Haml::Parser::Error] if there was a problem parsing the document
39
+ def process_source(source)
40
+ @source = strip_frontmatter(source)
41
+ @source_lines = @source.split("\n")
42
+
43
+ @tree = process_tree(Haml::Parser.new(@source, Haml::Options.new).parse)
44
+ end
45
+
46
+ # Processes the {Haml::Parser::ParseNode} tree and returns a tree composed
47
+ # of friendlier {HamlLint::Tree::Node}s.
48
+ #
49
+ # @param original_tree [Haml::Parser::ParseNode]
50
+ # @return [Haml::Tree::Node]
51
+ def process_tree(original_tree)
52
+ # Remove the trailing empty HAML comment that the parser creates to signal
53
+ # the end of the HAML document
54
+ if Gem::Requirement.new('~> 4.0.0').satisfied_by?(Gem.loaded_specs['haml'].version)
55
+ original_tree.children.pop
56
+ end
57
+
58
+ @node_transformer = HamlLint::NodeTransformer.new(self)
59
+ convert_tree(original_tree)
60
+ end
61
+
62
+ # Converts a HAML parse tree to a tree of {HamlLint::Tree::Node} objects.
63
+ #
64
+ # This provides a cleaner interface with which the linters can interact with
65
+ # the parse tree.
66
+ #
67
+ # @param haml_node [Haml::Parser::ParseNode]
68
+ # @param parent [Haml::Tree::Node]
69
+ # @return [Haml::Tree::Node]
70
+ def convert_tree(haml_node, parent = nil)
71
+ new_node = @node_transformer.transform(haml_node)
72
+ new_node.parent = parent
73
+
74
+ new_node.children = haml_node.children.map do |child|
75
+ convert_tree(child, new_node)
76
+ end
77
+
78
+ new_node
79
+ end
80
+
81
+ # Removes YAML frontmatter
82
+ def strip_frontmatter(source)
83
+ if config['skip_frontmatter'] &&
84
+ source =~ /
85
+ # From the start of the string
86
+ \A
87
+ # First-capture match --- followed by optional whitespace up
88
+ # to a newline then 0 or more chars followed by an optional newline.
89
+ # This matches the --- and the contents of the frontmatter
90
+ (---\s*\n.*?\n?)
91
+ # From the start of the line
92
+ ^
93
+ # Second capture match --- or ... followed by optional whitespace
94
+ # and newline. This matches the closing --- for the frontmatter.
95
+ (---|\.\.\.)\s*$\n?/mx
96
+ source = $POSTMATCH
97
+ end
98
+
99
+ source
100
+ end
101
+ end
102
+ end
@@ -1,13 +1,15 @@
1
1
  require 'find'
2
2
 
3
3
  module HamlLint
4
- # Finds HAML files that should be linted given a specified list of paths, glob
4
+ # Finds Haml files that should be linted given a specified list of paths, glob
5
5
  # patterns, and configuration.
6
6
  class FileFinder
7
7
  # List of extensions of files to include under a directory when a directory
8
8
  # is specified instead of a file.
9
9
  VALID_EXTENSIONS = %w[.haml]
10
10
 
11
+ # Create a file finder using the specified configuration.
12
+ #
11
13
  # @param config [HamlLint::Configuration]
12
14
  def initialize(config)
13
15
  @config = config
@@ -22,15 +24,18 @@ module HamlLint
22
24
  def find(patterns, excluded_patterns)
23
25
  extract_files_from(patterns).reject do |file|
24
26
  excluded_patterns.any? do |exclusion_glob|
25
- ::File.fnmatch?(exclusion_glob, file,
26
- ::File::FNM_PATHNAME | # Wildcards don't match path separators
27
- ::File::FNM_DOTMATCH) # `*` wildcard matches dotfiles
27
+ HamlLint::Utils.any_glob_matches?(exclusion_glob, file)
28
28
  end
29
29
  end
30
30
  end
31
31
 
32
32
  private
33
33
 
34
+ # Extract the list of matching files given the list of glob patterns, file
35
+ # paths, and directories.
36
+ #
37
+ # @param patterns [Array<String>]
38
+ # @return [Array<String>]
34
39
  def extract_files_from(patterns) # rubocop:disable MethodLength
35
40
  files = []
36
41
 
@@ -57,9 +62,13 @@ module HamlLint
57
62
  end
58
63
  end
59
64
 
60
- files.uniq
65
+ files.uniq.sort
61
66
  end
62
67
 
68
+ # Whether the given file should be treated as a Haml file.
69
+ #
70
+ # @param file [String]
71
+ # @return [Boolean]
63
72
  def haml_file?(file)
64
73
  return false unless ::FileTest.file?(file)
65
74
 
@@ -1,7 +1,20 @@
1
1
  module HamlLint
2
2
  # Contains information about a problem or issue with a HAML document.
3
3
  class Lint
4
- attr_reader :filename, :line, :linter, :message, :severity
4
+ # @return [String] file path to which the lint applies
5
+ attr_reader :filename
6
+
7
+ # @return [String] line number of the file the lint corresponds to
8
+ attr_reader :line
9
+
10
+ # @return [SlimLint::Linter] linter that reported the lint
11
+ attr_reader :linter
12
+
13
+ # @return [String] error/warning message to display to user
14
+ attr_reader :message
15
+
16
+ # @return [Symbol] whether this lint is a warning or an error
17
+ attr_reader :severity
5
18
 
6
19
  # Creates a new lint.
7
20
  #
@@ -18,6 +31,9 @@ module HamlLint
18
31
  @severity = severity
19
32
  end
20
33
 
34
+ # Return whether this lint has a severity of error.
35
+ #
36
+ # @return [Boolean]
21
37
  def error?
22
38
  @severity == :error
23
39
  end
@@ -5,7 +5,7 @@ module HamlLint
5
5
 
6
6
  def visit_tag(node)
7
7
  if node.tag_name == 'img' && !node.has_hash_attribute?(:alt)
8
- add_lint(node, '`img` tags must include alt text')
8
+ record_lint(node, '`img` tags must include alt text')
9
9
  end
10
10
  end
11
11
  end
@@ -18,8 +18,8 @@ module HamlLint
18
18
  def visit_tag(node)
19
19
  return unless contains_class_attribute?(node.dynamic_attributes_sources)
20
20
 
21
- add_lint(node, 'Avoid defining `class` in attributes hash ' \
22
- 'for static class names')
21
+ record_lint(node, 'Avoid defining `class` in attributes hash ' \
22
+ 'for static class names')
23
23
  end
24
24
 
25
25
  private
@@ -17,8 +17,8 @@ module HamlLint
17
17
  next unless components[index].start_with?('.') &&
18
18
  components[index - 1].start_with?('#')
19
19
 
20
- add_lint(node, 'Classes should be listed before IDs '\
21
- "(#{components[index]} should precede #{components[index - 1]})")
20
+ record_lint(node, 'Classes should be listed before IDs '\
21
+ "(#{components[index]} should precede #{components[index - 1]})")
22
22
  break
23
23
  end
24
24
  end
@@ -3,17 +3,15 @@ module HamlLint
3
3
  class Linter::ConsecutiveComments < Linter
4
4
  include LinterRegistry
5
5
 
6
- MIN_CONSECUTIVE = 2
7
6
  COMMENT_DETECTOR = ->(child) { child.type == :haml_comment }
8
7
 
9
8
  def visit_root(node)
10
- HamlLint::Utils.find_consecutive(
9
+ HamlLint::Utils.for_consecutive_items(
11
10
  node.children,
12
- MIN_CONSECUTIVE,
13
11
  COMMENT_DETECTOR,
14
12
  ) do |group|
15
- add_lint(group.first,
16
- "#{group.count} consecutive comments can be merged into one")
13
+ record_lint(group.first,
14
+ "#{group.count} consecutive comments can be merged into one")
17
15
  end
18
16
  end
19
17
  end
@@ -9,14 +9,14 @@ module HamlLint
9
9
  end
10
10
 
11
11
  def visit_root(node)
12
- HamlLint::Utils.find_consecutive(
12
+ HamlLint::Utils.for_consecutive_items(
13
13
  node.children,
14
- config['max_consecutive'] + 1,
15
14
  SILENT_SCRIPT_DETECTOR,
15
+ config['max_consecutive'] + 1,
16
16
  ) do |group|
17
- add_lint(group.first,
18
- "#{group.count} consecutive Ruby scripts can be merged into " \
19
- 'a single `:ruby` filter')
17
+ record_lint(group.first,
18
+ "#{group.count} consecutive Ruby scripts can be merged " \
19
+ 'into a single `:ruby` filter')
20
20
  end
21
21
  end
22
22
  end
@@ -6,7 +6,7 @@ module HamlLint
6
6
  def visit_silent_script(node)
7
7
  return unless node.script =~ /\A\s*\Z/
8
8
 
9
- add_lint(node, 'Empty script should be removed')
9
+ record_lint(node, 'Empty script should be removed')
10
10
  end
11
11
  end
12
12
  end
@@ -7,8 +7,8 @@ module HamlLint
7
7
  def visit_tag(node)
8
8
  return unless node.html_attributes?
9
9
 
10
- add_lint(node, "Prefer the hash attributes syntax (%tag{ lang: 'en' }) over " \
11
- 'HTML attributes syntax (%tag(lang=en))')
10
+ record_lint(node, "Prefer the hash attributes syntax (%tag{ lang: 'en' }) " \
11
+ 'over HTML attributes syntax (%tag(lang=en))')
12
12
  end
13
13
  end
14
14
  end
@@ -12,9 +12,9 @@ module HamlLint
12
12
  tag = node.source_code[/\s*([^\s={\(\[]+)/, 1]
13
13
  return unless tag.start_with?('%div')
14
14
 
15
- add_lint(node,
16
- "`#{tag}` can be written as `#{node.static_attributes_source}` " \
17
- 'since `%div` is implicit')
15
+ record_lint(node,
16
+ "`#{tag}` can be written as `#{node.static_attributes_source}` " \
17
+ 'since `%div` is implicit')
18
18
  end
19
19
  end
20
20
  end
@@ -8,7 +8,7 @@ module HamlLint
8
8
  # or starts with a space
9
9
  return if node.text.match(/\A(\s*|\s+\S.*)$/)
10
10
 
11
- add_lint(node, 'Comment should have a space after the `#`')
11
+ record_lint(node, 'Comment should have a space after the `#`')
12
12
  end
13
13
  end
14
14
  end
@@ -9,10 +9,10 @@ module HamlLint
9
9
  max_length = config['max']
10
10
  dummy_node = Struct.new(:line)
11
11
 
12
- parser.lines.each_with_index do |line, index|
12
+ document.source_lines.each_with_index do |line, index|
13
13
  next if line.length <= max_length
14
14
 
15
- add_lint(dummy_node.new(index + 1), format(MSG, line.length, max_length))
15
+ record_lint(dummy_node.new(index + 1), format(MSG, line.length, max_length))
16
16
  end
17
17
  end
18
18
  end