haml_lint 0.15.2 → 0.16.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: 80e71cdb5e58b93dd53b7e4fe3eef1bba2002af5
4
- data.tar.gz: a724e0a1cb1748cce64d430cd4ba34e82fc904ec
3
+ metadata.gz: 4dc951907854f1ef5fe256a2868825b5ce382501
4
+ data.tar.gz: 1ee304256e171748b98bab3fb375fca6549f2b16
5
5
  SHA512:
6
- metadata.gz: 202ce87309496ebb5372e607f734348e9532a1c83cde72ada2b88fe2e6a5b5d4d26459b181de83e838bd35685dd12b36bf0b7b25405351811f734a809f78d6c8
7
- data.tar.gz: f82080cf1c10090eee512efd10ef85eac22e751d49d488e9f94d889eed191c1203b85bd00411c1cb3b77a1076a93908ce18078213f9906427e1a2f51d8212ac2
6
+ metadata.gz: 08fa8027ec5658c01c88b999202da378051c6fc421be0e5dd5226d7a6cbb23ad27cd0f0db334dfe329ccb2a20261abb1141e34f4b03935f48ebc3a436791e694
7
+ data.tar.gz: 094fcc02c2900bbacb8c740b5862c103e1e32c68d9dbf5e304500af5d9cbce5c9cdf32bd69f2373208ea6fdbe4185f497883760913120549d0cfbef124d596b5
@@ -32,7 +32,6 @@ module HamlLint
32
32
  def ==(other)
33
33
  super || @hash == other.hash
34
34
  end
35
- alias_method :eql?, :==
36
35
 
37
36
  # Returns a non-modifiable configuration for the specified linter.
38
37
  #
@@ -1,11 +1,13 @@
1
+ # frozen_string_literal: true
2
+
1
3
  require 'pathname'
2
4
  require 'yaml'
3
5
 
4
6
  module HamlLint
5
7
  # Manages configuration file loading.
6
8
  class ConfigurationLoader
7
- DEFAULT_CONFIG_PATH = File.join(HamlLint::HOME, 'config', 'default.yml')
8
- CONFIG_FILE_NAME = '.haml-lint.yml'
9
+ DEFAULT_CONFIG_PATH = File.join(HamlLint::HOME, 'config', 'default.yml').freeze
10
+ CONFIG_FILE_NAME = '.haml-lint.yml'.freeze
9
11
 
10
12
  class << self
11
13
  # Load configuration file given the current working directory the
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Global application constants.
2
4
  module HamlLint
3
- HOME = File.expand_path(File.join(File.dirname(__FILE__), '..', '..'))
4
- APP_NAME = 'haml-lint'
5
+ HOME = File.expand_path(File.join(File.dirname(__FILE__), '..', '..')).freeze
6
+ APP_NAME = 'haml-lint'.freeze
5
7
 
6
- REPO_URL = 'https://github.com/brigade/haml-lint'
7
- BUG_REPORT_URL = "#{REPO_URL}/issues"
8
+ REPO_URL = 'https://github.com/brigade/haml-lint'.freeze
9
+ BUG_REPORT_URL = "#{REPO_URL}/issues".freeze
8
10
  end
@@ -1,8 +1,10 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Represents a parsed Haml document and its associated metadata.
3
5
  class Document
4
6
  # File name given to source code parsed from just a string.
5
- STRING_SOURCE = '(string)'
7
+ STRING_SOURCE = '(string)'.freeze
6
8
 
7
9
  # @return [HamlLint::Configuration] Configuration used to parse template
8
10
  attr_reader :config
@@ -6,7 +6,7 @@ module HamlLint
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
- VALID_EXTENSIONS = %w[.haml]
9
+ VALID_EXTENSIONS = %w[.haml].freeze
10
10
 
11
11
  # Create a file finder using the specified configuration.
12
12
  #
@@ -12,8 +12,7 @@ module HamlLint
12
12
  class Linter::ClassAttributeWithStaticValue < Linter
13
13
  include LinterRegistry
14
14
 
15
- STATIC_TYPES = [:str, :sym]
16
- STATIC_CLASSES = [String, Symbol]
15
+ STATIC_TYPES = [:str, :sym].freeze
17
16
 
18
17
  def visit_tag(node)
19
18
  return unless contains_class_attribute?(node.dynamic_attributes_sources)
@@ -26,11 +25,8 @@ module HamlLint
26
25
 
27
26
  def contains_class_attribute?(attributes_sources)
28
27
  attributes_sources.each do |code|
29
- begin
30
- ast_root = parse_ruby(code.start_with?('{') ? code : "{#{code}}")
31
- rescue ::Parser::SyntaxError
32
- next # RuboCop linter will report syntax errors
33
- end
28
+ ast_root = parse_ruby(code.start_with?('{') ? code : "{#{code}}")
29
+ next unless ast_root # RuboCop linter will report syntax errors
34
30
 
35
31
  ast_root.children.each do |pair|
36
32
  return true if static_class_attribute_value?(pair)
@@ -45,7 +41,7 @@ module HamlLint
45
41
 
46
42
  STATIC_TYPES.include?(key.type) &&
47
43
  key.children.first.to_sym == :class &&
48
- STATIC_CLASSES.include?(value.children.first.class)
44
+ STATIC_TYPES.include?(value.type)
49
45
  end
50
46
  end
51
47
  end
@@ -7,7 +7,7 @@ module HamlLint
7
7
  TYPES_BY_PREFIX = {
8
8
  '.' => :class,
9
9
  '#' => :id,
10
- }
10
+ }.freeze
11
11
 
12
12
  def visit_tag(node)
13
13
  # Convert ".class#id" into [.class, #id] (preserving order)
@@ -12,9 +12,9 @@ module HamlLint
12
12
  if config['present']
13
13
  record_lint(dummy_node,
14
14
  'Files should end with a trailing newline') unless ends_with_newline
15
- else
15
+ elsif ends_with_newline
16
16
  record_lint(dummy_node,
17
- 'Files should not end with a trailing newline') if ends_with_newline
17
+ 'Files should not end with a trailing newline')
18
18
  end
19
19
  end
20
20
  end
@@ -7,7 +7,7 @@ module HamlLint
7
7
  INDENT_REGEX = {
8
8
  space: /^[ ]*(?!\t)/,
9
9
  tab: /^\t*(?![ ])/,
10
- }
10
+ }.freeze
11
11
 
12
12
  def visit_root(_node)
13
13
  regex = INDENT_REGEX[config['character'].to_sym]
@@ -6,7 +6,7 @@ module HamlLint
6
6
  def visit_haml_comment(node)
7
7
  # Skip if the node spans multiple lines starting on the second line,
8
8
  # or starts with a space
9
- return if node.text.match(/\A(\s*|\s+\S.*)$/)
9
+ return if node.text =~ /\A(\s*|\s+\S.*)$/
10
10
 
11
11
  record_lint(node, 'Comment should have a space after the `#`')
12
12
  end
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for lines longer than a maximum number of columns.
3
5
  class Linter::LineLength < Linter
4
6
  include LinterRegistry
5
7
 
6
- MSG = 'Line is too long. [%d/%d]'
8
+ MSG = 'Line is too long. [%d/%d]'.freeze
7
9
 
8
10
  def visit_root(_node)
9
11
  max_length = config['max']
@@ -1,10 +1,12 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for uses of the multiline pipe character.
3
5
  class Linter::MultilinePipe < Linter
4
6
  include LinterRegistry
5
7
 
6
8
  MESSAGE = "Don't use the `|` character to split up lines. " \
7
- 'Wrap on commas or extract code into helper.'
9
+ 'Wrap on commas or extract code into helper.'.freeze
8
10
 
9
11
  def visit_tag(node)
10
12
  check(node)
@@ -32,6 +32,19 @@ module HamlLint
32
32
  private
33
33
 
34
34
  def check(node)
35
+ # Condition occurs when scripts do not contain nested content, e.g.
36
+ #
37
+ # - if condition || <-- no children; its sibling is a continuation
38
+ # - other_condition
39
+ #
40
+ # ...whereas when it contains nested content it's not a multiline script:
41
+ #
42
+ # - begin <-- has children
43
+ # some_helper
44
+ # - rescue
45
+ # An error occurred
46
+ return unless node.children.empty?
47
+
35
48
  operator = node.script[/\s+(\S+)\z/, 1]
36
49
  if SPLIT_OPERATORS.include?(operator)
37
50
  record_lint(node,
@@ -1,9 +1,11 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for Ruby script in HAML templates with no space after the `=`/`-`.
3
5
  class Linter::SpaceBeforeScript < Linter
4
6
  include LinterRegistry
5
7
 
6
- MESSAGE_FORMAT = 'The %s symbol should have one space separating it from code'
8
+ MESSAGE_FORMAT = 'The %s symbol should have one space separating it from code'.freeze
7
9
 
8
10
  def visit_tag(node) # rubocop:disable Metrics/CyclomaticComplexity
9
11
  # If this tag has inline script
@@ -17,7 +17,7 @@ module HamlLint
17
17
  start_message: 'Hash attribute should start with one space after the opening brace',
18
18
  end_message: 'Hash attribute should end with one space before the closing brace'
19
19
  }
20
- }
20
+ }.freeze
21
21
 
22
22
  def visit_tag(node)
23
23
  return unless node.hash_attributes?
@@ -5,7 +5,7 @@ module HamlLint
5
5
 
6
6
  def visit_tag(node)
7
7
  tag = node.tag_name
8
- return unless tag.match(/[A-Z]/)
8
+ return unless tag =~ /[A-Z]/
9
9
 
10
10
  record_lint(node, "`#{tag}` should be written in lowercase as `#{tag.downcase}`")
11
11
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  module HamlLint
2
4
  # Checks for unnecessary outputting of strings in Ruby script tags.
3
5
  #
@@ -9,7 +11,7 @@ module HamlLint
9
11
  class Linter::UnnecessaryStringOutput < Linter
10
12
  include LinterRegistry
11
13
 
12
- MESSAGE = '`= "..."` should be rewritten as `...`'
14
+ MESSAGE = '`= "..."` should be rewritten as `...`'.freeze
13
15
 
14
16
  def visit_tag(node)
15
17
  if tag_has_inline_script?(node) && inline_content_is_string?(node)
@@ -29,13 +29,13 @@ module HamlLint
29
29
  # @param options [Hash]
30
30
  # @return [Array<HamlLint::Linter>]
31
31
  def extract_enabled_linters(config, options)
32
- included_linters = LinterRegistry
33
- .extract_linters_from(options.fetch(:included_linters, []))
32
+ included_linters =
33
+ LinterRegistry.extract_linters_from(options.fetch(:included_linters, []))
34
34
 
35
35
  included_linters = LinterRegistry.linters if included_linters.empty?
36
36
 
37
- excluded_linters = LinterRegistry
38
- .extract_linters_from(options.fetch(:excluded_linters, []))
37
+ excluded_linters =
38
+ LinterRegistry.extract_linters_from(options.fetch(:excluded_linters, []))
39
39
 
40
40
  # After filtering out explicitly included/excluded linters, only include
41
41
  # linters which are enabled in the configuration
@@ -22,7 +22,7 @@ module HamlLint
22
22
  # The translation won't be perfect, and won't make any real sense, but the
23
23
  # relationship between variable declarations/uses and the flow control graph
24
24
  # will remain intact.
25
- class RubyExtractor
25
+ class RubyExtractor # rubocop:disable Metrics/ClassLength
26
26
  include HamlVisitor
27
27
 
28
28
  # Stores the extracted source and a map of lines of generated source to the
@@ -47,6 +47,7 @@ module HamlLint
47
47
  @source_map = {}
48
48
  @line_count = 0
49
49
  @indent_level = 0
50
+ @output_count = 0
50
51
 
51
52
  yield # Collect lines of code from children
52
53
  end
@@ -55,7 +56,7 @@ module HamlLint
55
56
  # Don't output the text, as we don't want to have to deal with any RuboCop
56
57
  # cops regarding StringQuotes or AsciiComments, and it's not important to
57
58
  # overall document anyway.
58
- add_line('puts', node)
59
+ add_dummy_puts(node)
59
60
  end
60
61
 
61
62
  def visit_tag(node)
@@ -78,7 +79,7 @@ module HamlLint
78
79
 
79
80
  # We add a dummy puts statement to represent the tag name being output.
80
81
  # This prevents some erroneous RuboCop warnings.
81
- add_line("puts # #{node.tag_name}", node)
82
+ add_dummy_puts(node, node.tag_name)
82
83
 
83
84
  code = node.script.strip
84
85
  add_line(code, node) unless code.empty?
@@ -86,7 +87,7 @@ module HamlLint
86
87
 
87
88
  def after_visit_tag(node)
88
89
  # We add a dummy puts statement for closing tag.
89
- add_line("puts # #{node.tag_name}/", node)
90
+ add_dummy_puts(node, "#{node.tag_name}/")
90
91
  end
91
92
 
92
93
  def visit_script(node)
@@ -111,13 +112,13 @@ module HamlLint
111
112
  visit_script(node, &block)
112
113
  end
113
114
 
114
- def visit_filter(node)
115
+ def visit_filter(node) # rubocop:disable Metrics/AbcSize
115
116
  if node.filter_type == 'ruby'
116
117
  node.text.split("\n").each_with_index do |line, index|
117
118
  add_line(line, node.line + index + 1)
118
119
  end
119
120
  else
120
- add_line('puts', node)
121
+ add_dummy_puts(node, ":#{node.filter_type}")
121
122
  HamlLint::Utils.extract_interpolated_values(node.text) do |interpolated_code, line|
122
123
  add_line(interpolated_code, node.line + line)
123
124
  end
@@ -139,6 +140,14 @@ module HamlLint
139
140
  end
140
141
  end
141
142
 
143
+ # Adds a dummy method call with a unique name so we don't get
144
+ # Style/IdenticalConditionalBranches RuboCop warnings
145
+ def add_dummy_puts(node, annotation = nil)
146
+ annotation = " # #{annotation}" if annotation
147
+ add_line("_haml_lint_puts_#{@output_count}#{annotation}", node)
148
+ @output_count += 1
149
+ end
150
+
142
151
  def add_line(code, node_or_line)
143
152
  return if code.empty?
144
153
 
@@ -172,20 +181,21 @@ module HamlLint
172
181
  text =~ /\bdo\s*(\|\s*[^\|]*\s*\|)?(\s*#.*)?\z/
173
182
  end
174
183
 
175
- START_BLOCK_KEYWORDS = %w[if unless case begin for until while]
184
+ START_BLOCK_KEYWORDS = %w[if unless case begin for until while].freeze
176
185
  def start_block_keyword?(text)
177
186
  START_BLOCK_KEYWORDS.include?(block_keyword(text))
178
187
  end
179
188
 
180
- MID_BLOCK_KEYWORDS = %w[else elsif when rescue ensure]
189
+ MID_BLOCK_KEYWORDS = %w[else elsif when rescue ensure].freeze
181
190
  def mid_block_keyword?(text)
182
191
  MID_BLOCK_KEYWORDS.include?(block_keyword(text))
183
192
  end
184
193
 
194
+ LOOP_KEYWORDS = %w[for until while].freeze
185
195
  def block_keyword(text)
186
196
  # Need to handle 'for'/'while' since regex stolen from HAML parser doesn't
187
197
  if keyword = text[/\A\s*([^\s]+)\s+/, 1]
188
- return keyword if %w[for until while].include?(keyword)
198
+ return keyword if LOOP_KEYWORDS.include?(keyword)
189
199
  end
190
200
 
191
201
  return unless keyword = text.scan(Haml::Parser::BLOCK_KEYWORD_REGEX)[0]
@@ -1,16 +1,18 @@
1
- require 'astrolabe/builder'
1
+ require 'rubocop'
2
+ require 'rubocop/ast_node/builder'
2
3
  require 'parser/current'
3
4
 
4
5
  module HamlLint
5
6
  # Parser for the Ruby language.
6
7
  #
7
8
  # This provides a convenient wrapper around the `parser` gem and the
8
- # `astrolabe` integration to go with it. It is intended to be used for linter
9
+ # Astrolabe integration (now built-in to RuboCop, so no longer called
10
+ # Astrolabe) to go with it. It is intended to be used for linter
9
11
  # checks that require deep inspection of Ruby code.
10
12
  class RubyParser
11
13
  # Creates a reusable parser.
12
14
  def initialize
13
- @builder = ::Astrolabe::Builder.new
15
+ @builder = ::RuboCop::Node::Builder.new
14
16
  @parser = ::Parser::CurrentRuby.new(@builder)
15
17
  end
16
18
 
@@ -28,9 +28,11 @@ module HamlLint::Tree
28
28
  #
29
29
  # Returns nil if no node matching the given block was found.
30
30
  #
31
+ # @yieldparam [HamlLint::Tree::Node] node
32
+ # @yieldreturn [Boolean] whether the node matches
31
33
  # @return [HamlLint::Tree::Node,nil]
32
34
  def find(&block)
33
- return self if block.call(self)
35
+ return self if yield(self)
34
36
 
35
37
  children.each do |child|
36
38
  if result = child.find(&block)
@@ -53,8 +55,8 @@ module HamlLint::Tree
53
55
  end
54
56
 
55
57
  @document.source_lines[@line - 1...next_node_line]
56
- .join("\n")
57
- .gsub(/^\s*\z/m, '') # Remove blank lines at the end
58
+ .join("\n")
59
+ .gsub(/^\s*\z/m, '') # Remove blank lines at the end
58
60
  end
59
61
 
60
62
  def inspect
@@ -87,8 +87,8 @@ module HamlLint::Tree
87
87
  def attributes_source
88
88
  @attr_source ||=
89
89
  begin
90
- _explicit_tag, static_attrs, rest = source_code
91
- .scan(/\A\s*(%[-:\w]+)?([-:\w\.\#]*)(.*)/m)[0]
90
+ _explicit_tag, static_attrs, rest =
91
+ source_code.scan(/\A\s*(%[-:\w]+)?([-:\w\.\#]*)(.*)/m)[0]
92
92
 
93
93
  attr_types = {
94
94
  '{' => [:hash, %w[{ }]],
@@ -105,9 +105,9 @@ module HamlLint
105
105
  # inclusion
106
106
  # @yieldreturn [Boolean] whether to include the item
107
107
  # @return [Integer]
108
- def count_consecutive(items, offset = 0, &block)
108
+ def count_consecutive(items, offset = 0)
109
109
  count = 1
110
- count += 1 while (offset + count < items.count) && block.call(items[offset + count])
110
+ count += 1 while (offset + count < items.count) && yield(items[offset + count])
111
111
  count
112
112
  end
113
113
 
@@ -1,4 +1,6 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Defines the gem version.
2
4
  module HamlLint
3
- VERSION = '0.15.2'
5
+ VERSION = '0.16.0'.freeze
4
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.15.2
4
+ version: 0.16.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: 2015-09-08 00:00:00.000000000 Z
12
+ date: 2016-01-21 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: haml
@@ -25,20 +25,34 @@ dependencies:
25
25
  - - "~>"
26
26
  - !ruby/object:Gem::Version
27
27
  version: '4.0'
28
+ - !ruby/object:Gem::Dependency
29
+ name: rake
30
+ requirement: !ruby/object:Gem::Requirement
31
+ requirements:
32
+ - - "~>"
33
+ - !ruby/object:Gem::Version
34
+ version: '10.0'
35
+ type: :runtime
36
+ prerelease: false
37
+ version_requirements: !ruby/object:Gem::Requirement
38
+ requirements:
39
+ - - "~>"
40
+ - !ruby/object:Gem::Version
41
+ version: '10.0'
28
42
  - !ruby/object:Gem::Dependency
29
43
  name: rubocop
30
44
  requirement: !ruby/object:Gem::Requirement
31
45
  requirements:
32
46
  - - ">="
33
47
  - !ruby/object:Gem::Version
34
- version: 0.25.0
48
+ version: 0.36.0
35
49
  type: :runtime
36
50
  prerelease: false
37
51
  version_requirements: !ruby/object:Gem::Requirement
38
52
  requirements:
39
53
  - - ">="
40
54
  - !ruby/object:Gem::Version
41
- version: 0.25.0
55
+ version: 0.36.0
42
56
  - !ruby/object:Gem::Dependency
43
57
  name: sysexits
44
58
  requirement: !ruby/object:Gem::Requirement
@@ -171,7 +185,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
171
185
  version: '0'
172
186
  requirements: []
173
187
  rubyforge_project:
174
- rubygems_version: 2.4.8
188
+ rubygems_version: 2.5.1
175
189
  signing_key:
176
190
  specification_version: 4
177
191
  summary: HAML lint tool