Sha256: f685cdc5bac61821d645f3ce6f8bba883f777fda18f280b7cf7f2106a6561f36

Contents?: true

Size: 1.98 KB

Versions: 19

Compression:

Stored size: 1.98 KB

Contents

module SCSSLint
  # Checks for selectors with large depths of applicability.
  class Linter::SelectorDepth < Linter
    include LinterRegistry

    def visit_root(_node)
      @max_depth = config['max_depth']
      @depth = 0
      yield # Continue
    end

    def visit_rule(node)
      old_depth = @depth
      @depth = max_sequence_depth(node.parsed_rules, @depth)

      if @depth > @max_depth
        add_lint(node.parsed_rules || node,
                 'Selector should have depth of applicability no greater ' \
                 "than #{@max_depth}, but was #{@depth}")
      end

      yield # Continue linting children
      @depth = old_depth
    end

  private

    # Find the maximum depth of all sequences in a comma sequence.
    def max_sequence_depth(comma_sequence, current_depth)
      # Sequence contains interpolation; assume a depth of 1
      return current_depth + 1 unless comma_sequence

      comma_sequence.members.map { |sequence| sequence_depth(sequence, current_depth) }.max
    end

    def sequence_depth(sequence, current_depth)
      separators, simple_sequences = sequence.members.partition do |item|
        item.is_a?(String)
      end

      parent_selectors = simple_sequences.count do |item|
        next if item.is_a?(Array) # @keyframe percentages end up as Arrays
        item.rest.any? { |i| i.is_a?(Sass::Selector::Parent) }
      end

      # Take the number of simple sequences and subtract one for each sibling
      # combinator, as these "combine" simple sequences such that they do not
      # increase depth.
      depth = simple_sequences.size -
        separators.count { |item| item == '~' || item == '+' }

      depth +=
        if parent_selectors > 0
          # If parent selectors are present, add the current depth for each
          # additional parent selector.
          parent_selectors * (current_depth - 1)
        else
          # Otherwise this just descends from the containing selector
          current_depth
        end

      depth
    end
  end
end

Version data entries

19 entries across 19 versions & 1 rubygems

Version Path
scss_lint-0.57.1 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.57.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.56.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.55.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.54.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.53.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.52.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.51.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.50.3 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.50.2 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.50.1 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.50.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.49.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.48.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.47.1 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.47.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.46.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.45.0 lib/scss_lint/linter/selector_depth.rb
scss_lint-0.44.0 lib/scss_lint/linter/selector_depth.rb