haml_lint 0.13.0 → 0.14.0

Sign up to get free protection for your applications and to get access to all the features.
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