haml_lint 0.15.2 → 0.16.0

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