haml_lint 0.23.2 → 0.24.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 5e1e7727e9ee3dadac7fe5fbc6ba6e4a42e482b5
4
- data.tar.gz: 7176808267f479eeb56757133e8c0015c4841b77
3
+ metadata.gz: fe12a287eaf253fd83053061ac62a26b908918e6
4
+ data.tar.gz: cf8bae7a2e75dde6befbe09a9764fb223ea72583
5
5
  SHA512:
6
- metadata.gz: c944db1432ca3b9133769fde9173b0dee6ec253f0ac1d16d5d194fce086bfce9952ae49603a196b3d9fc30dbd93572d067169490483ee01b14c36433cdb49c32
7
- data.tar.gz: e533c56866c2ad9702be3461068cb2aab5fe73c1a39eaf059bfae0850628a1145c67e832eae29f663f6b336d96bff8851d0dcafd8feebb1972767af8c89c6e67
6
+ metadata.gz: 55334bc83c7c8f377c78b290db34ba08a2939bd9179e06541d27f3919118d3942500c85a5028ad2dde31a868ac82c4bd49b7ebf6492ec14400ae0f8b213e72d5
7
+ data.tar.gz: 84e178971e6068b40dd896f49efac863a244a8ed952b4d4d45d93872d6a2030a68134721c2cffbba94cffc5d3b11b88283b487c35a1d3907132eab86df44eb26
data/config/default.yml CHANGED
@@ -47,6 +47,11 @@ linters:
47
47
  ImplicitDiv:
48
48
  enabled: true
49
49
 
50
+ Indentation:
51
+ enabled: true
52
+ character: space # or tab
53
+ width: 2 # ignored if character == tab
54
+
50
55
  InstanceVariables:
51
56
  enabled: true
52
57
  file_types: partials
@@ -108,10 +113,6 @@ linters:
108
113
  enabled: true
109
114
  style: space
110
115
 
111
- Indentation:
112
- enabled: true
113
- character: space # or tab
114
-
115
116
  TagName:
116
117
  enabled: true
117
118
 
data/lib/haml_lint/cli.rb CHANGED
@@ -83,12 +83,26 @@ module HamlLint
83
83
  end
84
84
  end
85
85
 
86
+ # Instantiates a new reporter based on the options.
87
+ #
88
+ # @param options [HamlLint::Configuration]
89
+ # @option options [true, nil] :auto_gen_config whether to use the config
90
+ # generating reporter
91
+ # @option options [Class] :reporter the class of reporter to use
92
+ # @return [HamlLint::Reporter]
93
+ def reporter_from_options(options)
94
+ if options[:auto_gen_config]
95
+ HamlLint::Reporter::DisabledConfigReporter.new(log)
96
+ else
97
+ options.fetch(:reporter, HamlLint::Reporter::DefaultReporter).new(log)
98
+ end
99
+ end
100
+
86
101
  # Scans the files specified by the given options for lints.
87
102
  #
88
103
  # @return [Integer] exit status code
89
104
  def scan_for_lints(options)
90
- reporter = options.fetch(:reporter,
91
- HamlLint::Reporter::DefaultReporter).new(log)
105
+ reporter = reporter_from_options(options)
92
106
  report = Runner.new.run(options.merge(reporter: reporter))
93
107
  report.display
94
108
  report.failed? ? Sysexits::EX_DATAERR : Sysexits::EX_OK
@@ -6,6 +6,7 @@ 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
10
  DEFAULT_CONFIG_PATH = File.join(HamlLint::HOME, 'config', 'default.yml').freeze
10
11
  CONFIG_FILE_NAME = '.haml-lint.yml'.freeze
11
12
 
@@ -31,11 +32,14 @@ module HamlLint
31
32
  # Loads a configuration, ensuring it extends the default configuration.
32
33
  #
33
34
  # @param file [String]
35
+ # @param loaded_files [Array<String>] any previously loaded files in an
36
+ # inheritance chain
34
37
  # @return [HamlLint::Configuration]
35
- def load_file(file)
38
+ def load_file(file, loaded_files = [])
36
39
  config = load_from_file(file)
37
40
 
38
- default_configuration.merge(config)
41
+ [default_configuration, resolve_inheritance(config, loaded_files), config]
42
+ .reduce { |acc, elem| acc.merge(elem) }
39
43
  rescue Psych::SyntaxError, Errno::ENOENT => error
40
44
  raise HamlLint::Exceptions::ConfigurationError,
41
45
  "Unable to load configuration from '#{file}': #{error}",
@@ -67,6 +71,11 @@ module HamlLint
67
71
  {}
68
72
  end
69
73
 
74
+ if hash.key?('inherit_from')
75
+ hash['inherits_from'] ||= []
76
+ hash['inherits_from'].concat(Array(hash.delete('inherit_from')))
77
+ end
78
+
70
79
  HamlLint::Configuration.new(hash)
71
80
  end
72
81
 
@@ -81,6 +90,33 @@ module HamlLint
81
90
  .map { |path| path + CONFIG_FILE_NAME }
82
91
  files << Pathname.new(CONFIG_FILE_NAME)
83
92
  end
93
+
94
+ # Resolves an inherited file and loads it.
95
+ #
96
+ # @param file [String] the path to the file
97
+ # @param loaded_files [Array<String>] previously loaded files in the
98
+ # inheritance chain
99
+ # @return [HamlLint::Configuration, nil]
100
+ def resolve(file, loaded_files)
101
+ return unless File.exist?(file)
102
+ return if loaded_files.include?(file)
103
+
104
+ loaded_files << file
105
+ load_file(file, loaded_files)
106
+ end
107
+
108
+ # Resolves the chain of `inherits_from` directives in a configuration.
109
+ #
110
+ # @param config [HamlLint::Configuration] the pre-existing configuration
111
+ # @param loaded_files [Array<String>] any previously loaded files in an
112
+ # inheritance chain
113
+ # @return [HamlLint::Configuration]
114
+ def resolve_inheritance(config, loaded_files)
115
+ Array(config['inherits_from'])
116
+ .map { |config_file| resolve(config_file, loaded_files) }
117
+ .compact
118
+ .reduce { |acc, elem| acc.merge(elem) } || config
119
+ end
84
120
  end
85
121
  end
86
122
  end
@@ -9,15 +9,51 @@ module HamlLint
9
9
  tab: /^\t*(?![ ])/,
10
10
  }.freeze
11
11
 
12
+ LEADING_SPACES_REGEX = /^( +)(?! )/
13
+
12
14
  def visit_root(root)
13
- regex = INDENT_REGEX[config['character'].to_sym]
15
+ character = config['character'].to_sym
16
+ check_character(character, root)
17
+
18
+ width = config['width'].to_i
19
+ check_width(width, root) if character == :space && width > 0
20
+ end
21
+
22
+ private
23
+
24
+ # validate that indentation matches config characters (either spaces or tabs)
25
+ def check_character(character, root)
26
+ wrong_characters = character == :space ? 'tabs' : 'spaces'
27
+ regex = INDENT_REGEX[character]
14
28
  dummy_node = Struct.new(:line)
15
29
 
16
30
  document.source_lines.each_with_index do |line, index|
17
31
  next if line =~ regex
18
32
 
19
33
  unless root.node_for_line(index).disabled?(self)
20
- record_lint dummy_node.new(index + 1), 'Line contains tabs in indentation'
34
+ record_lint dummy_node.new(index + 1), "Line contains #{wrong_characters} in indentation"
35
+ end
36
+ end
37
+ end
38
+
39
+ # validate that indentation matches config width (only for spaces)
40
+ def check_width(width, root)
41
+ dummy_node = Struct.new(:line)
42
+
43
+ root.children.each do |top_node|
44
+ # once we've found one line with leading space, there's no need to check any more lines
45
+ # `haml` will check indenting_at_start, deeper_indenting, inconsistent_indentation
46
+ break if top_node.children.find do |node|
47
+ line = node.source_code
48
+ leading_space = LEADING_SPACES_REGEX.match(line)
49
+
50
+ break unless leading_space && !node.disabled?(self)
51
+
52
+ if leading_space[1] != ' ' * width
53
+ record_lint dummy_node.new(node.line), "File does not use #{width}-space indentation"
54
+ end
55
+
56
+ break true
21
57
  end
22
58
  end
23
59
  end
@@ -27,6 +27,16 @@ module HamlLint
27
27
  @lints = []
28
28
  visit(document.tree)
29
29
  @lints
30
+ rescue Parser::SyntaxError => ex
31
+ location = ex.diagnostic.location
32
+ @lints <<
33
+ HamlLint::Lint.new(
34
+ HamlLint::Linter::Syntax.new(config),
35
+ document.file,
36
+ location.line,
37
+ ex.to_s,
38
+ :error
39
+ )
30
40
  end
31
41
 
32
42
  # Returns the simple name for this linter.
@@ -21,7 +21,7 @@ module HamlLint
21
21
  end.parse!(args)
22
22
 
23
23
  # Any remaining arguments are assumed to be files
24
- @options[:files] = args
24
+ @options[:files] = args.empty? ? ["."] : args
25
25
 
26
26
  @options
27
27
  rescue OptionParser::InvalidOption => ex
@@ -33,6 +33,10 @@ module HamlLint
33
33
  private
34
34
 
35
35
  def add_linter_options(parser)
36
+ parser.on('--auto-gen-config', 'Generate a configuration file acting as a TODO list') do
37
+ @options[:auto_gen_config] = true
38
+ end
39
+
36
40
  parser.on('-i', '--include-linter linter,...', Array,
37
41
  'Specify which linters you want to run') do |linters|
38
42
  @options[:included_linters] = linters
@@ -0,0 +1,105 @@
1
+ require 'haml_lint/reporter/progress_reporter'
2
+
3
+ module HamlLint
4
+ # Outputs a YAML configuration file based on existing violations.
5
+ class Reporter::DisabledConfigReporter < Reporter::ProgressReporter
6
+ HEADING =
7
+ ['# This configuration was generated by',
8
+ '# `haml-lint --auto-gen-config`',
9
+ "# on #{Time.now} using Haml-Lint version #{HamlLint::VERSION}.",
10
+ '# The point is for the user to remove these configuration records',
11
+ '# one by one as the lints are removed from the code base.',
12
+ '# Note that changes in the inspected code, or installation of new',
13
+ '# versions of Haml-Lint, may require this file to be generated again.']
14
+ .join("\n")
15
+
16
+ # Disables this reporter on the CLI since it doesn't output anything.
17
+ #
18
+ # @return [false]
19
+ def self.available?
20
+ false
21
+ end
22
+
23
+ # Create the reporter that will display the report and write the config.
24
+ #
25
+ # @param _log [HamlLint::Logger]
26
+ def initialize(_log)
27
+ super
28
+ @linters_with_lints = Hash.new { |hash, key| hash[key] = [] }
29
+ @linters_lint_count = Hash.new(0)
30
+ end
31
+
32
+ # A hash of linters with the files that have that type of lint.
33
+ #
34
+ # @return [Hash<String, Integer] a Hash with linter name keys and lint
35
+ # count values
36
+ attr_reader :linters_lint_count
37
+
38
+ # A hash of linters with the files that have that type of lint.
39
+ #
40
+ # @return [Hash<String, Array<String>>] a Hash with linter name keys and file
41
+ # name list values
42
+ attr_reader :linters_with_lints
43
+
44
+ # Prints the standard progress reporter output and writes the new config file.
45
+ #
46
+ # @param report [HamlLint::Report]
47
+ # @return [void]
48
+ def display_report(report)
49
+ super
50
+
51
+ File.write(ConfigurationLoader::AUTO_GENERATED_FILE, config_file_contents)
52
+ log.log "Created #{ConfigurationLoader::AUTO_GENERATED_FILE}."
53
+ log.log "Run `haml-lint --config #{ConfigurationLoader::AUTO_GENERATED_FILE}`" \
54
+ ", or add `inherits_from: #{ConfigurationLoader::AUTO_GENERATED_FILE}` in a " \
55
+ '.haml-lint.yml file.'
56
+ end
57
+
58
+ # Prints the standard progress report marks and tracks files with lint.
59
+ #
60
+ # @param file [String]
61
+ # @param lints [Array<HamlLint::Lint>]
62
+ # @return [void]
63
+ def finished_file(file, lints)
64
+ super
65
+
66
+ if lints.any?
67
+ lints.each do |lint|
68
+ linters_with_lints[lint.linter.name] |= [lint.filename]
69
+ linters_lint_count[lint.linter.name] += 1
70
+ end
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ # The contents of the generated configuration file based on captured lint.
77
+ #
78
+ # @return [String] a Yaml-formatted configuration file's contents
79
+ def config_file_contents
80
+ output = []
81
+ output << HEADING
82
+ output << 'linters:' if linters_with_lints.any?
83
+ linters_with_lints.each do |linter, files|
84
+ output << generate_config_for_linter(linter, files)
85
+ end
86
+ output.join("\n\n")
87
+ end
88
+
89
+ # Constructs the configuration for excluding a linter in some files.
90
+ #
91
+ # @param linter [String] the name of the linter to exclude
92
+ # @param files [Array<String>] the files in which the linter is excluded
93
+ # @return [String] a Yaml-formatted configuration
94
+ def generate_config_for_linter(linter, files)
95
+ [].tap do |output|
96
+ output << " # Offense count: #{linters_lint_count[linter]}"
97
+ output << " #{linter}:"
98
+ output << ' exclude:'
99
+ files.each do |filename|
100
+ output << %{ - "#{filename}"}
101
+ end
102
+ end.join("\n")
103
+ end
104
+ end
105
+ end
@@ -2,5 +2,5 @@
2
2
 
3
3
  # Defines the gem version.
4
4
  module HamlLint
5
- VERSION = '0.23.2'.freeze
5
+ VERSION = '0.24.0'.freeze
6
6
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haml_lint
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.23.2
4
+ version: 0.24.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Brigade Engineering
@@ -9,7 +9,7 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2017-03-15 00:00:00.000000000 Z
12
+ date: 2017-03-28 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: haml
@@ -160,6 +160,7 @@ files:
160
160
  - lib/haml_lint/reporter.rb
161
161
  - lib/haml_lint/reporter/checkstyle_reporter.rb
162
162
  - lib/haml_lint/reporter/default_reporter.rb
163
+ - lib/haml_lint/reporter/disabled_config_reporter.rb
163
164
  - lib/haml_lint/reporter/hash_reporter.rb
164
165
  - lib/haml_lint/reporter/hooks.rb
165
166
  - lib/haml_lint/reporter/json_reporter.rb