haml_lint 0.28.0 → 0.29.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (85) hide show
  1. checksums.yaml +4 -4
  2. data/bin/haml-lint +1 -0
  3. data/config/default.yml +1 -0
  4. data/lib/haml_lint/adapter/haml_4.rb +2 -0
  5. data/lib/haml_lint/adapter/haml_5.rb +2 -0
  6. data/lib/haml_lint/adapter.rb +2 -0
  7. data/lib/haml_lint/cli.rb +5 -3
  8. data/lib/haml_lint/comment_configuration.rb +2 -0
  9. data/lib/haml_lint/configuration.rb +2 -0
  10. data/lib/haml_lint/configuration_loader.rb +36 -20
  11. data/lib/haml_lint/constants.rb +3 -3
  12. data/lib/haml_lint/directive.rb +4 -2
  13. data/lib/haml_lint/document.rb +3 -3
  14. data/lib/haml_lint/exceptions.rb +2 -0
  15. data/lib/haml_lint/file_finder.rb +2 -0
  16. data/lib/haml_lint/haml_visitor.rb +2 -0
  17. data/lib/haml_lint/lint.rb +2 -0
  18. data/lib/haml_lint/linter/alignment_tabs.rb +4 -2
  19. data/lib/haml_lint/linter/alt_text.rb +2 -0
  20. data/lib/haml_lint/linter/class_attribute_with_static_value.rb +3 -1
  21. data/lib/haml_lint/linter/classes_before_ids.rb +3 -1
  22. data/lib/haml_lint/linter/consecutive_comments.rb +2 -0
  23. data/lib/haml_lint/linter/consecutive_silent_scripts.rb +2 -0
  24. data/lib/haml_lint/linter/empty_object_reference.rb +2 -0
  25. data/lib/haml_lint/linter/empty_script.rb +2 -0
  26. data/lib/haml_lint/linter/final_newline.rb +2 -0
  27. data/lib/haml_lint/linter/html_attributes.rb +2 -0
  28. data/lib/haml_lint/linter/id_names.rb +2 -0
  29. data/lib/haml_lint/linter/implicit_div.rb +2 -0
  30. data/lib/haml_lint/linter/indentation.rb +3 -1
  31. data/lib/haml_lint/linter/inline_styles.rb +3 -1
  32. data/lib/haml_lint/linter/instance_variables.rb +2 -0
  33. data/lib/haml_lint/linter/leading_comment_space.rb +3 -1
  34. data/lib/haml_lint/linter/line_length.rb +1 -1
  35. data/lib/haml_lint/linter/multiline_pipe.rb +2 -2
  36. data/lib/haml_lint/linter/multiline_script.rb +2 -0
  37. data/lib/haml_lint/linter/object_reference_attributes.rb +2 -0
  38. data/lib/haml_lint/linter/repeated_id.rb +3 -1
  39. data/lib/haml_lint/linter/rubocop.rb +2 -0
  40. data/lib/haml_lint/linter/ruby_comments.rb +2 -0
  41. data/lib/haml_lint/linter/space_before_script.rb +1 -1
  42. data/lib/haml_lint/linter/space_inside_hash_attributes.rb +2 -0
  43. data/lib/haml_lint/linter/syntax.rb +2 -0
  44. data/lib/haml_lint/linter/tag_name.rb +2 -0
  45. data/lib/haml_lint/linter/trailing_whitespace.rb +2 -0
  46. data/lib/haml_lint/linter/unnecessary_interpolation.rb +2 -0
  47. data/lib/haml_lint/linter/unnecessary_string_output.rb +1 -1
  48. data/lib/haml_lint/linter/view_length.rb +6 -3
  49. data/lib/haml_lint/linter.rb +5 -3
  50. data/lib/haml_lint/linter_registry.rb +2 -0
  51. data/lib/haml_lint/linter_selector.rb +2 -0
  52. data/lib/haml_lint/logger.rb +2 -0
  53. data/lib/haml_lint/node_transformer.rb +2 -0
  54. data/lib/haml_lint/options.rb +9 -4
  55. data/lib/haml_lint/parsed_ruby.rb +2 -0
  56. data/lib/haml_lint/rake_task.rb +14 -2
  57. data/lib/haml_lint/report.rb +2 -0
  58. data/lib/haml_lint/reporter/checkstyle_reporter.rb +2 -0
  59. data/lib/haml_lint/reporter/default_reporter.rb +2 -0
  60. data/lib/haml_lint/reporter/disabled_config_reporter.rb +11 -3
  61. data/lib/haml_lint/reporter/hash_reporter.rb +2 -0
  62. data/lib/haml_lint/reporter/hooks.rb +2 -0
  63. data/lib/haml_lint/reporter/json_reporter.rb +2 -0
  64. data/lib/haml_lint/reporter/progress_reporter.rb +3 -1
  65. data/lib/haml_lint/reporter/utils.rb +2 -0
  66. data/lib/haml_lint/reporter.rb +2 -0
  67. data/lib/haml_lint/ruby_extractor.rb +3 -1
  68. data/lib/haml_lint/ruby_parser.rb +2 -0
  69. data/lib/haml_lint/runner.rb +11 -6
  70. data/lib/haml_lint/severity.rb +2 -0
  71. data/lib/haml_lint/tree/comment_node.rb +2 -0
  72. data/lib/haml_lint/tree/doctype_node.rb +2 -0
  73. data/lib/haml_lint/tree/filter_node.rb +2 -0
  74. data/lib/haml_lint/tree/haml_comment_node.rb +2 -0
  75. data/lib/haml_lint/tree/node.rb +20 -2
  76. data/lib/haml_lint/tree/null_node.rb +2 -0
  77. data/lib/haml_lint/tree/plain_node.rb +2 -0
  78. data/lib/haml_lint/tree/root_node.rb +2 -0
  79. data/lib/haml_lint/tree/script_node.rb +2 -0
  80. data/lib/haml_lint/tree/silent_script_node.rb +2 -0
  81. data/lib/haml_lint/tree/tag_node.rb +2 -0
  82. data/lib/haml_lint/utils.rb +2 -0
  83. data/lib/haml_lint/version.rb +1 -1
  84. data/lib/haml_lint.rb +2 -0
  85. metadata +5 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: de1778be09762f2f6e9205045f63a6bfbc1966f1bc848e57c5bc22a52a8c0488
4
- data.tar.gz: ecb4cc40e34424ba773dec9b252ef7618f60b9a14e63d7afba68164f41d49681
3
+ metadata.gz: a2b6e2913e09e73c44c78189a5766b3b30bb8999c010a61729843f038fdd6b72
4
+ data.tar.gz: 4b59c4427a7bf35b2f90eb03f4fe5c89fb4b6046cdedde5b2bc6137cca1b265d
5
5
  SHA512:
6
- metadata.gz: 7cdf82866d301aa55ba5891d364030f6657dcd492118be4bc06933a3158c88bb45d088fcdc6a0e60e72a983271781f5c1ab515aef5e9eff2b2a82ea23ef16cc1
7
- data.tar.gz: 68ae9a3bd3c9d7c2d3514577aae4513b755479b4c63c7fc08bfd5f45a8cbb1dd5495e4d2dd7f071988e3d8b84bb44959577786860b2f4c2eb5118f2e6257bd8b
6
+ metadata.gz: d1dc05e7ce0d8b5ad2cb268159ad51894f1bf17c883d3f23af222b8754f3d24fdbd73368466b55ceda9d587bf457b7961180818971d482110bbc0ad0cfb7f874
7
+ data.tar.gz: bc1553ea5bd67ee4d19e56ff7ed34fea91f4c286d2a8f09419ccae1ae19da7469c917d2a297e21b5b6e3bf8ad4457b3301c7c7282aca81c1a88102ff0c7fa931
data/bin/haml-lint CHANGED
@@ -1,4 +1,5 @@
1
1
  #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
2
3
 
3
4
  require 'haml_lint'
4
5
  require 'haml_lint/cli'
data/config/default.yml CHANGED
@@ -91,6 +91,7 @@ linters:
91
91
  - Lint/BlockAlignment
92
92
  - Lint/EndAlignment
93
93
  - Lint/Void
94
+ - Layout/AlignHash
94
95
  - Layout/AlignParameters
95
96
  - Layout/ElseAlignment
96
97
  - Layout/EndOfLine
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  class Adapter
3
5
  # Adapts the Haml::Parser from Haml 4 for use in HamlLint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  class Adapter
3
5
  # Adapts the Haml::Parser from Haml 5 for use in HamlLint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/adapter/haml_4'
2
4
  require 'haml_lint/adapter/haml_5'
3
5
  require 'haml_lint/exceptions'
data/lib/haml_lint/cli.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint'
2
4
  require 'haml_lint/options'
3
5
 
@@ -21,8 +23,8 @@ module HamlLint
21
23
  def run(args)
22
24
  options = HamlLint::Options.new.parse(args)
23
25
  act_on_options(options)
24
- rescue StandardError => exception
25
- handle_exception(exception)
26
+ rescue StandardError => e
27
+ handle_exception(e)
26
28
  end
27
29
 
28
30
  private
@@ -92,7 +94,7 @@ module HamlLint
92
94
  # @return [HamlLint::Reporter]
93
95
  def reporter_from_options(options)
94
96
  if options[:auto_gen_config]
95
- HamlLint::Reporter::DisabledConfigReporter.new(log)
97
+ HamlLint::Reporter::DisabledConfigReporter.new(log, limit: options[:auto_gen_exclude_limit] || 15) # rubocop:disable Metrics/LineLength
96
98
  else
97
99
  options.fetch(:reporter, HamlLint::Reporter::DefaultReporter).new(log)
98
100
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Determines what linters are enabled or disabled via comments.
3
5
  class CommentConfiguration
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Stores runtime configuration for the application.
3
5
  #
@@ -6,24 +6,34 @@ require 'yaml'
6
6
  module HamlLint
7
7
  # Manages configuration file loading.
8
8
  class ConfigurationLoader
9
- AUTO_GENERATED_FILE = '.haml-lint_todo.yml'.freeze
9
+ AUTO_GENERATED_FILE = '.haml-lint_todo.yml'
10
10
  DEFAULT_CONFIG_PATH = File.join(HamlLint::HOME, 'config', 'default.yml').freeze
11
- CONFIG_FILE_NAME = '.haml-lint.yml'.freeze
11
+ CONFIG_FILE_NAME = '.haml-lint.yml'
12
12
 
13
13
  class << self
14
14
  # Load configuration file given the current working directory the
15
15
  # application is running within.
16
- def load_applicable_config
17
- directory = File.expand_path(Dir.pwd)
18
- config_file = possible_config_files(directory).find(&:file?)
19
-
16
+ # @param config_file [String] optional path to the config file to load
17
+ # @param options [Hash]
18
+ # @option options :exclude_files [Array<String>] files that should not
19
+ # be loaded even if they're requested via inherits_from
20
+ # @return [HamlLint::Configuration]
21
+ def load_applicable_config(config_file = nil, options = {})
22
+ config_file ||= default_path_to_config
20
23
  if config_file
21
- load_file(config_file.to_path)
24
+ load_file(config_file, options)
22
25
  else
23
26
  default_configuration
24
27
  end
25
28
  end
26
29
 
30
+ # Path to the default config file, if it exists
31
+ def default_path_to_config
32
+ directory = File.expand_path(Dir.pwd)
33
+ config_file = possible_config_files(directory).find(&:file?)
34
+ config_file ? config_file.to_path : nil
35
+ end
36
+
27
37
  # Loads the built-in default configuration.
28
38
  def default_configuration
29
39
  @default_configuration ||= load_from_file(DEFAULT_CONFIG_PATH)
@@ -32,18 +42,23 @@ module HamlLint
32
42
  # Loads a configuration, ensuring it extends the default configuration.
33
43
  #
34
44
  # @param file [String]
35
- # @param loaded_files [Array<String>] any previously loaded files in an
36
- # inheritance chain
45
+ # @param context [Hash]
46
+ # @option context :loaded_files [Array<String>] any previously loaded
47
+ # files in an inheritance chain
48
+ # @option context :exclude_files [Array<String>] files that should not
49
+ # be loaded even if they're requested via inherits_from
37
50
  # @return [HamlLint::Configuration]
38
- def load_file(file, loaded_files = [])
51
+ def load_file(file, context = {})
52
+ context[:loaded_files] ||= []
53
+ context[:exclude_files] ||= []
39
54
  config = load_from_file(file)
40
55
 
41
- [default_configuration, resolve_inheritance(config, loaded_files), config]
56
+ [default_configuration, resolve_inheritance(config, context), config]
42
57
  .reduce { |acc, elem| acc.merge(elem) }
43
- rescue Psych::SyntaxError, Errno::ENOENT => error
58
+ rescue Psych::SyntaxError, Errno::ENOENT => e
44
59
  raise HamlLint::Exceptions::ConfigurationError,
45
- "Unable to load configuration from '#{file}': #{error}",
46
- error.backtrace
60
+ "Unable to load configuration from '#{file}': #{e}",
61
+ e.backtrace
47
62
  end
48
63
 
49
64
  # Creates a configuration from the specified hash, ensuring it extends the
@@ -97,12 +112,13 @@ module HamlLint
97
112
  # @param loaded_files [Array<String>] previously loaded files in the
98
113
  # inheritance chain
99
114
  # @return [HamlLint::Configuration, nil]
100
- def resolve(file, loaded_files)
115
+ def resolve(file, context)
101
116
  return unless File.exist?(file)
102
- return if loaded_files.include?(file)
117
+ return if context[:loaded_files].include?(file)
118
+ return if context[:exclude_files].include?(file)
103
119
 
104
- loaded_files << file
105
- load_file(file, loaded_files)
120
+ context[:loaded_files] << file
121
+ load_file(file, context)
106
122
  end
107
123
 
108
124
  # Resolves the chain of `inherits_from` directives in a configuration.
@@ -111,9 +127,9 @@ module HamlLint
111
127
  # @param loaded_files [Array<String>] any previously loaded files in an
112
128
  # inheritance chain
113
129
  # @return [HamlLint::Configuration]
114
- def resolve_inheritance(config, loaded_files)
130
+ def resolve_inheritance(config, context)
115
131
  Array(config['inherits_from'])
116
- .map { |config_file| resolve(config_file, loaded_files) }
132
+ .map { |config_file| resolve(config_file, context) }
117
133
  .compact
118
134
  .reduce { |acc, elem| acc.merge(elem) } || config
119
135
  end
@@ -3,8 +3,8 @@
3
3
  # Global application constants.
4
4
  module HamlLint
5
5
  HOME = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
6
- APP_NAME = 'haml-lint'.freeze
6
+ APP_NAME = 'haml-lint'
7
7
 
8
- REPO_URL = 'https://github.com/brigade/haml-lint'.freeze
9
- BUG_REPORT_URL = "#{REPO_URL}/issues".freeze
8
+ REPO_URL = 'https://github.com/sds/haml-lint'
9
+ BUG_REPORT_URL = "#{REPO_URL}/issues"
10
10
  end
@@ -1,7 +1,9 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Handles linter configuration transformation via Haml comments.
3
5
  class Directive
4
- LINTER_REGEXP = /(?:[A-Z]\w+)/
6
+ LINTER_REGEXP = /(?:[A-Z]\w+)/.freeze
5
7
 
6
8
  DIRECTIVE_REGEXP = /
7
9
  # "haml-lint:" with optional spacing
@@ -12,7 +14,7 @@ module HamlLint
12
14
 
13
15
  # "all" or a comma-separated list (with optional spaces) of linters
14
16
  (?<linters>all | (?:#{LINTER_REGEXP}\s*,\s*)* #{LINTER_REGEXP})
15
- /x
17
+ /x.freeze
16
18
 
17
19
  # Constructs a directive from source code as a given line.
18
20
  #
@@ -6,7 +6,7 @@ module HamlLint
6
6
  # Represents a parsed Haml document and its associated metadata.
7
7
  class Document
8
8
  # File name given to source code parsed from just a string.
9
- STRING_SOURCE = '(string)'.freeze
9
+ STRING_SOURCE = '(string)'
10
10
 
11
11
  # @return [HamlLint::Configuration] Configuration used to parse template
12
12
  attr_reader :config
@@ -46,8 +46,8 @@ module HamlLint
46
46
  @source_lines = @source.split(/\r\n|\r|\n/)
47
47
 
48
48
  @tree = process_tree(HamlLint::Adapter.detect_class.new(@source).parse)
49
- rescue Haml::Error => ex
50
- error = HamlLint::Exceptions::ParseError.new(ex.message, ex.line)
49
+ rescue Haml::Error => e
50
+ error = HamlLint::Exceptions::ParseError.new(e.message, e.line)
51
51
  raise error
52
52
  end
53
53
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Collection of exceptions that can be raised by the HAML Lint application.
2
4
  module HamlLint::Exceptions
3
5
  # Raised when a {Configuration} could not be loaded from a file.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'find'
2
4
 
3
5
  module HamlLint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Provides an interface which when included allows a class to visit nodes in
3
5
  # the parse tree of a HAML document.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Contains information about a problem or issue with a HAML document.
3
5
  class Lint
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for tabs that are placed for alignment of tag content
3
5
  class Linter::AlignmentTabs < Linter
4
- REGEX = /[^\s*]\t+/
6
+ REGEX = /[^\s*]\t+/.freeze
5
7
 
6
8
  def visit_tag(node)
7
- if REGEX.match(node.source_code)
9
+ if REGEX.match?(node.source_code)
8
10
  record_lint(node, 'Avoid using tabs for alignment')
9
11
  end
10
12
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for missing `alt` attributes on `img` tags.
3
5
  class Linter::AltText < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for class attributes defined in tag attribute hash with static
3
5
  # values.
@@ -18,7 +20,7 @@ module HamlLint
18
20
 
19
21
  STATIC_TYPES = %i[str sym].freeze
20
22
 
21
- VALID_CLASS_REGEX = /^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$/
23
+ VALID_CLASS_REGEX = /^-?[_a-zA-Z]+[_a-zA-Z0-9-]*$/.freeze
22
24
 
23
25
  def visit_tag(node)
24
26
  return unless contains_class_attribute?(node.dynamic_attributes_sources)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks that classes are listed before IDs in tags.
3
5
  class Linter::ClassesBeforeIds < Linter
@@ -9,7 +11,7 @@ module HamlLint
9
11
  '#' => :id,
10
12
  }.freeze
11
13
 
12
- MSG = '%s should be listed before %s (%s should precede %s)'.freeze
14
+ MSG = '%s should be listed before %s (%s should precede %s)'
13
15
 
14
16
  def visit_tag(node)
15
17
  # Convert ".class#id" into [.class, #id] (preserving order)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for multiple lines of code comments that can be condensed.
3
5
  class Linter::ConsecutiveComments < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for multiple consecutive silent script markers that could be
3
5
  # condensed into a :ruby filter block.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for empty object references (e.g. `%div[]`).
3
5
  class Linter::EmptyObjectReference < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for empty scripts.
3
5
  class Linter::EmptyScript < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for final newlines at the end of a file.
3
5
  class Linter::FinalNewline < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for the setting of attributes via HTML shorthand syntax on elements
3
5
  # (e.g. `%tag(lang=en)`).
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for `id` attributes in specific cases on tags.
3
5
  class Linter::IdNames < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for unnecessary uses of the `%div` prefix where a class name or ID
3
5
  # already implies a div.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks the character used for indentation.
3
5
  class Linter::Indentation < Linter
@@ -9,7 +11,7 @@ module HamlLint
9
11
  tab: /^\t*(?![ ])/,
10
12
  }.freeze
11
13
 
12
- LEADING_SPACES_REGEX = /^( +)(?! )/
14
+ LEADING_SPACES_REGEX = /^( +)(?! )/.freeze
13
15
 
14
16
  def visit_root(root)
15
17
  character = config['character'].to_sym
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Detects use of inline `style` attributes on any tag
3
5
  class Linter::InlineStyles < Linter
4
6
  include LinterRegistry
5
7
 
6
- MESSAGE = 'Do not use inline style attributes'.freeze
8
+ MESSAGE = 'Do not use inline style attributes'
7
9
 
8
10
  def visit_tag(node)
9
11
  if node.has_hash_attribute?(:style)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for the presence of instance variables
3
5
  class Linter::InstanceVariables < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for comments that don't have a leading space.
3
5
  class Linter::LeadingCommentSpace < Linter
@@ -6,7 +8,7 @@ module HamlLint
6
8
  def visit_haml_comment(node)
7
9
  # Skip if the node spans multiple lines starting on the second line,
8
10
  # or starts with a space
9
- return if node.text =~ /\A(\s*|\s+\S.*)$/
11
+ return if node.text =~ /\A#*(\s*|\s+\S.*)$/
10
12
 
11
13
  record_lint(node, 'Comment should have a space after the `#`')
12
14
  end
@@ -10,7 +10,7 @@ module HamlLint
10
10
  # @api private
11
11
  DummyNode = Struct.new(:line)
12
12
 
13
- MSG = 'Line is too long. [%d/%d]'.freeze
13
+ MSG = 'Line is too long. [%d/%d]'
14
14
 
15
15
  def visit_root(root)
16
16
  max_length = config['max']
@@ -6,7 +6,7 @@ module HamlLint
6
6
  include LinterRegistry
7
7
 
8
8
  MESSAGE = "Don't use the `|` character to split up lines. " \
9
- 'Wrap on commas or extract code into helper.'.freeze
9
+ 'Wrap on commas or extract code into helper.'
10
10
 
11
11
  def visit_tag(node)
12
12
  check(node)
@@ -31,7 +31,7 @@ module HamlLint
31
31
 
32
32
  private
33
33
 
34
- MULTILINE_PIPE_REGEX = /\s+\|\s*$/
34
+ MULTILINE_PIPE_REGEX = /\s+\|\s*$/.freeze
35
35
 
36
36
  def line_text_for_node(node)
37
37
  document.source_lines[node.line - 1]
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks scripts spread over multiple lines.
3
5
  class Linter::MultilineScript < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for uses of the object reference syntax for assigning the class and
3
5
  # ID attributes for an element (e.g. `%div[@user]`).
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Detects repeated instances of an element ID in a file
3
5
  class Linter::RepeatedId < Linter
4
6
  include LinterRegistry
5
7
 
6
- MESSAGE_FORMAT = %{Do not repeat id "#%s" on the page}.freeze
8
+ MESSAGE_FORMAT = %{Do not repeat id "#%s" on the page}
7
9
 
8
10
  def visit_root(_node)
9
11
  @id_map = Hash.new { |hash, key| hash[key] = [] }
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/ruby_extractor'
2
4
  require 'rubocop'
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for Ruby comments that can be written as HAML comments.
3
5
  class Linter::RubyComments < Linter
@@ -5,7 +5,7 @@ module HamlLint
5
5
  class Linter::SpaceBeforeScript < Linter
6
6
  include LinterRegistry
7
7
 
8
- MESSAGE_FORMAT = 'The %s symbol should have one space separating it from code'.freeze
8
+ MESSAGE_FORMAT = 'The %s symbol should have one space separating it from code'
9
9
 
10
10
  ALLOWED_SEPARATORS = [' ', '#'].freeze
11
11
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for spaces inside the braces of hash attributes
3
5
  # (e.g. `%tag{ lang: en }` vs `%tag{lang: en}`).
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # A catch-all linter for syntax violations raised by the Haml parser.
3
5
  class Linter::Syntax < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for tag names with uppercase letters.
3
5
  class Linter::TagName < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for trailing whitespace.
3
5
  class Linter::TrailingWhitespace < Linter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for unnecessary uses of string interpolation.
3
5
  #
@@ -11,7 +11,7 @@ module HamlLint
11
11
  class Linter::UnnecessaryStringOutput < Linter
12
12
  include LinterRegistry
13
13
 
14
- MESSAGE = '`= "..."` should be rewritten as `...`'.freeze
14
+ MESSAGE = '`= "..."` should be rewritten as `...`'
15
15
 
16
16
  def visit_tag(node)
17
17
  if tag_has_inline_script?(node) && inline_content_is_string?(node)
@@ -1,17 +1,20 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Detects overly long views.
3
5
  class Linter::ViewLength < Linter
4
6
  include LinterRegistry
5
7
 
6
- MSG = 'View template is too long [%d/%d]'.freeze
8
+ MSG = 'View template is too long [%d/%d]'
7
9
 
8
10
  DummyNode = Struct.new(:line)
9
11
 
10
- def visit_root(_root)
12
+ def visit_root(root)
11
13
  max = config['max']
12
14
  line_count = document.source_lines.count
15
+ node = root.children.first
13
16
 
14
- if line_count > max
17
+ if line_count > max && !node.disabled?(self)
15
18
  record_lint(DummyNode.new(0), format(MSG, line_count, max))
16
19
  end
17
20
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Base implementation for all lint checks.
3
5
  #
@@ -27,14 +29,14 @@ module HamlLint
27
29
  @lints = []
28
30
  visit(document.tree)
29
31
  @lints
30
- rescue Parser::SyntaxError => ex
31
- location = ex.diagnostic.location
32
+ rescue Parser::SyntaxError => e
33
+ location = e.diagnostic.location
32
34
  @lints <<
33
35
  HamlLint::Lint.new(
34
36
  HamlLint::Linter::Syntax.new(config),
35
37
  document.file,
36
38
  location.line,
37
- ex.to_s,
39
+ e.to_s,
38
40
  :error
39
41
  )
40
42
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  class NoSuchLinter < StandardError; end
3
5
 
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Chooses the appropriate linters to run given the specified configuration.
3
5
  class LinterSelector
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Encapsulates all communication to an output source.
3
5
  class Logger
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Responsible for transforming {Haml::Parser::ParseNode} objects into
3
5
  # corresponding {HamlLint::Tree::Node} objects.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'optparse'
2
4
 
3
5
  module HamlLint
@@ -24,10 +26,8 @@ module HamlLint
24
26
  @options[:files] = args.empty? ? ['.'] : args
25
27
 
26
28
  @options
27
- rescue OptionParser::InvalidOption => ex
28
- raise Exceptions::InvalidCLIOption,
29
- ex.message,
30
- ex.backtrace
29
+ rescue OptionParser::InvalidOption => e
30
+ raise Exceptions::InvalidCLIOption, e.message, e.backtrace
31
31
  end
32
32
 
33
33
  private
@@ -37,6 +37,11 @@ module HamlLint
37
37
  @options[:auto_gen_config] = true
38
38
  end
39
39
 
40
+ parser.on('--auto-gen-exclude-limit limit', Integer,
41
+ 'Number of failures to allow in the TODO list before the entire rule is excluded') do |limit| # rubocop:disable Metrics/LineLength
42
+ @options[:auto_gen_exclude_limit] = limit
43
+ end
44
+
40
45
  parser.on('-i', '--include-linter linter,...', Array,
41
46
  'Specify which linters you want to run') do |linters|
42
47
  @options[:included_linters] = linters
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'delegate'
2
4
 
3
5
  module HamlLint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rake'
2
4
  require 'rake/tasklib'
3
5
  require 'haml_lint/constants'
@@ -35,9 +37,18 @@ module HamlLint
35
37
  # @return [String]
36
38
  attr_accessor :name
37
39
 
38
- # Configuration file to use.
40
+ # Set the configuration file or path.
41
+ #
42
+ # @param config [String,File]
43
+ def config=(config)
44
+ @config = config.is_a?(String) ? File.open(config, 'r') : config
45
+ end
46
+
47
+ # Return the configuration file path.
39
48
  # @return [String]
40
- attr_accessor :config
49
+ def config
50
+ @config.path
51
+ end
41
52
 
42
53
  # List of files to lint (can contain shell globs).
43
54
  #
@@ -131,6 +142,7 @@ module HamlLint
131
142
  def parse_args
132
143
  cli_args = config ? ['--config', config] : []
133
144
  cli_args.concat(['--fail-level', fail_level]) if fail_level
145
+ cli_args
134
146
  end
135
147
  end
136
148
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Contains information about all lints detected during a scan.
3
5
  class Report
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: false
2
+
1
3
  module HamlLint
2
4
  # Outputs report as an XML checkstyle document.
3
5
  class Reporter::CheckstyleReporter < Reporter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/reporter/utils'
2
4
 
3
5
  module HamlLint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/reporter/progress_reporter'
2
4
 
3
5
  module HamlLint
@@ -23,10 +25,11 @@ module HamlLint
23
25
  # Create the reporter that will display the report and write the config.
24
26
  #
25
27
  # @param _log [HamlLint::Logger]
26
- def initialize(_log)
27
- super
28
+ def initialize(log, limit: 15)
29
+ super(log)
28
30
  @linters_with_lints = Hash.new { |hash, key| hash[key] = [] }
29
31
  @linters_lint_count = Hash.new(0)
32
+ @exclude_limit = limit
30
33
  end
31
34
 
32
35
  # A hash of linters with the files that have that type of lint.
@@ -41,6 +44,11 @@ module HamlLint
41
44
  # name list values
42
45
  attr_reader :linters_with_lints
43
46
 
47
+ # Number of offenses to allow before simply disabling the linter
48
+ #
49
+ # @return [Integer] file exclude limit
50
+ attr_reader :exclude_limit
51
+
44
52
  # Prints the standard progress reporter output and writes the new config file.
45
53
  #
46
54
  # @param report [HamlLint::Report]
@@ -97,7 +105,7 @@ module HamlLint
97
105
  output << " #{linter}:"
98
106
  # disable the linter when there are many files with offenses.
99
107
  # exclude the affected files otherwise.
100
- if files.count > 15
108
+ if files.count > exclude_limit
101
109
  output << ' enabled: false'
102
110
  else
103
111
  output << ' exclude:'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Outputs report as a Ruby Hash for easy use by other tools.
3
5
  class Reporter::HashReporter < Reporter
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  class Reporter
3
5
  # A collection of hook methods for incremental processing.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/reporter/hash_reporter'
2
4
 
3
5
  module HamlLint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rainbow'
2
4
  require 'haml_lint/reporter/utils'
3
5
 
@@ -7,7 +9,7 @@ module HamlLint
7
9
  class Reporter::ProgressReporter < Reporter
8
10
  include Reporter::Utils
9
11
 
10
- DOT = '.'.freeze
12
+ DOT = '.'
11
13
 
12
14
  def display_report(report)
13
15
  lints = report.lints
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  class Reporter
3
5
  # Formatting helpers for printing the default report format.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/reporter/hooks'
2
4
 
3
5
  module HamlLint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Utility class for extracting Ruby script from a HAML file that can then be
3
5
  # linted with a Ruby linter (i.e. is "legal" Ruby). The goal is to turn this:
@@ -122,7 +124,7 @@ module HamlLint
122
124
  visit_script(node, &block)
123
125
  end
124
126
 
125
- def visit_filter(node) # rubocop:disable Metrics/AbcSize
127
+ def visit_filter(node)
126
128
  if node.filter_type == 'ruby'
127
129
  node.text.split("\n").each_with_index do |line, index|
128
130
  add_line(line, node.line + index + 1, false)
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'rubocop'
2
4
  require 'rubocop/ast/builder'
3
5
  require 'parser/current'
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Responsible for running the applicable linters against the desired files.
3
5
  class Runner
@@ -57,12 +59,15 @@ module HamlLint
57
59
  # @param options [Hash]
58
60
  # @return [HamlLint::Configuration]
59
61
  def load_applicable_config(options)
60
- if options[:config_file]
61
- HamlLint::ConfigurationLoader.load_file(options[:config_file])
62
- elsif options[:config]
62
+ if options[:config]
63
63
  options[:config]
64
+ elsif options[:auto_gen_config]
65
+ HamlLint::ConfigurationLoader.load_applicable_config(
66
+ options[:config_file],
67
+ exclude_files: [HamlLint::ConfigurationLoader::AUTO_GENERATED_FILE]
68
+ )
64
69
  else
65
- HamlLint::ConfigurationLoader.load_applicable_config
70
+ HamlLint::ConfigurationLoader.load_applicable_config(options[:config_file])
66
71
  end
67
72
  end
68
73
 
@@ -75,9 +80,9 @@ module HamlLint
75
80
  def collect_lints(file, linter_selector, config)
76
81
  begin
77
82
  document = HamlLint::Document.new(File.read(file), file: file, config: config)
78
- rescue HamlLint::Exceptions::ParseError => ex
83
+ rescue HamlLint::Exceptions::ParseError => e
79
84
  return [HamlLint::Lint.new(HamlLint::Linter::Syntax.new(config), file,
80
- ex.line, ex.to_s, :error)]
85
+ e.line, e.to_s, :error)]
81
86
  end
82
87
 
83
88
  linter_selector.linters_for_file(file).map do |linter|
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'delegate'
2
4
 
3
5
  module HamlLint
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint::Tree
2
4
  # Represents a visible XHTML comment in a HAML document.
3
5
  class CommentNode < Node
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint::Tree
2
4
  # Represents a doctype definition for a HAML document.
3
5
  class DoctypeNode < Node
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint::Tree
2
4
  # Represents a filter node which contains arbitrary code.
3
5
  class FilterNode < Node
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/directive'
2
4
 
3
5
  module HamlLint::Tree
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/comment_configuration'
2
4
 
3
5
  module HamlLint::Tree
@@ -102,7 +104,10 @@ module HamlLint::Tree
102
104
  def line_numbers
103
105
  return (line..line) unless @value && text
104
106
 
105
- (line..line + lines.count)
107
+ end_line = line + lines.count
108
+ end_line = nontrivial_end_line if line == end_line
109
+
110
+ (line..end_line)
106
111
  end
107
112
 
108
113
  # The previous node to be traversed in the tree.
@@ -124,7 +129,7 @@ module HamlLint::Tree
124
129
  next_sibling = siblings.next(self)
125
130
  return next_sibling if next_sibling
126
131
 
127
- parent.successor if parent
132
+ parent&.successor
128
133
  end
129
134
 
130
135
  # Returns the next node that appears after this node in the document.
@@ -152,6 +157,19 @@ module HamlLint::Tree
152
157
 
153
158
  private
154
159
 
160
+ # Discovers the end line of the node when there are no lines.
161
+ #
162
+ # @return [Integer] the end line of the node
163
+ def nontrivial_end_line
164
+ if (last_child = children.last)
165
+ last_child.line_numbers.end - 1
166
+ elsif successor
167
+ successor.line_numbers.begin - 1
168
+ else
169
+ @document.source_lines.count
170
+ end
171
+ end
172
+
155
173
  # The siblings of this node within the tree.
156
174
  #
157
175
  # @api private
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint::Tree
2
4
  # A null object version of a node that can be used as a safe default.
3
5
  class NullNode < Node
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint::Tree
2
4
  # Represents a node that contains plain text.
3
5
  class PlainNode < Node
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/tree/null_node'
2
4
 
3
5
  module HamlLint::Tree
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'haml_lint/parsed_ruby'
2
4
 
3
5
  module HamlLint::Tree
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint::Tree
2
4
  # Represents a HAML silent script node (`- some_expression`) which executes
3
5
  # code without producing output.
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint::Tree
2
4
  # Represents a tag node in a HAML document.
3
5
  class TagNode < Node # rubocop:disable ClassLength
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
 
3
5
  module HamlLint
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the gem version.
4
4
  module HamlLint
5
- VERSION = '0.28.0'.freeze
5
+ VERSION = '0.29.0'
6
6
  end
data/lib/haml_lint.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Need to load haml before we can reference some Haml modules in our code
2
4
  require 'haml'
3
5
 
metadata CHANGED
@@ -1,15 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml_lint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.28.0
4
+ version: 0.29.0
5
5
  platform: ruby
6
6
  authors:
7
- - Brigade Engineering
8
7
  - Shane da Silva
9
8
  autorequire:
10
9
  bindir: bin
11
10
  cert_chain: []
12
- date: 2018-06-07 00:00:00.000000000 Z
11
+ date: 2019-05-03 00:00:00.000000000 Z
13
12
  dependencies:
14
13
  - !ruby/object:Gem::Dependency
15
14
  name: haml
@@ -95,7 +94,6 @@ dependencies:
95
94
  version: '1.1'
96
95
  description: Configurable tool for writing clean and consistent HAML
97
96
  email:
98
- - eng@brigade.com
99
97
  - shane@dasilva.io
100
98
  executables:
101
99
  - haml-lint
@@ -185,7 +183,7 @@ files:
185
183
  - lib/haml_lint/tree/tag_node.rb
186
184
  - lib/haml_lint/utils.rb
187
185
  - lib/haml_lint/version.rb
188
- homepage: https://github.com/brigade/haml-lint
186
+ homepage: https://github.com/sds/haml-lint
189
187
  licenses:
190
188
  - MIT
191
189
  metadata: {}
@@ -197,15 +195,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
197
195
  requirements:
198
196
  - - ">="
199
197
  - !ruby/object:Gem::Version
200
- version: 2.2.0
198
+ version: 2.4.0
201
199
  required_rubygems_version: !ruby/object:Gem::Requirement
202
200
  requirements:
203
201
  - - ">="
204
202
  - !ruby/object:Gem::Version
205
203
  version: '0'
206
204
  requirements: []
207
- rubyforge_project:
208
- rubygems_version: 2.7.6
205
+ rubygems_version: 3.0.3
209
206
  signing_key:
210
207
  specification_version: 4
211
208
  summary: HAML lint tool