class SCSSLint::Linter::SpaceAfterComma

Checks for spaces after commas in argument lists.

Constants

EXPECTED_SPACES_AFTER_COMMA

Public Instance Methods

visit_function(node) { || ... } click to toggle source
# File lib/scss_lint/linter/space_after_comma.rb, line 16
def visit_function(node)
  check_definition(node, :function)
  yield
end
visit_mixin(node) { || ... } click to toggle source
# File lib/scss_lint/linter/space_after_comma.rb, line 11
def visit_mixin(node)
  check_invocation(node, :mixin)
  yield
end
visit_mixindef(node) { || ... } click to toggle source
# File lib/scss_lint/linter/space_after_comma.rb, line 6
def visit_mixindef(node)
  check_definition(node, :mixin)
  yield
end
visit_script_funcall(node) { || ... } click to toggle source
# File lib/scss_lint/linter/space_after_comma.rb, line 21
def visit_script_funcall(node)
  check_invocation(node, :function)
  yield
end
visit_script_listliteral(node) { || ... } click to toggle source
# File lib/scss_lint/linter/space_after_comma.rb, line 26
def visit_script_listliteral(node)
  check_commas_after_args(node.elements, 'lists') if node.separator == :comma
  yield
end

Private Instance Methods

check_commas_after_args(args, arg_type) click to toggle source

Check the comma after each argument in a list for a space following it, reporting a lint using the given [arg_type].

# File lib/scss_lint/linter/space_after_comma.rb, line 66
def check_commas_after_args(args, arg_type)
  # For each arg except the last, check the character following the comma
  args[0..-2].each do |arg|
    # Sometimes the line we're looking at doesn't even contain a comma!
    next unless engine.lines[arg.line - 1].include?(',')

    offset = find_comma_offset(arg)

    # Check for space or newline after comma (we allow arguments to be split
    # up over multiple lines).
    spaces = 0
    while (char = character_at(arg.source_range.end_pos, offset + 1)) == ' '
      spaces += 1
      offset += 1
    end
    next if char == "\n" || # Ignore trailing spaces
            spaces == EXPECTED_SPACES_AFTER_COMMA

    add_lint arg, "Commas in #{arg_type} should be followed by a single space"
  end
end
check_definition(node, type) click to toggle source

Check parameters of a function/mixin definition

# File lib/scss_lint/linter/space_after_comma.rb, line 34
def check_definition(node, type)
  # Use the default value's source range if one is defined, since that will
  # be the item with the comma after it
  args = node.args.map { |name, default_value| default_value || name }
  args << node.splat if node.splat

  check_commas_after_args(args, "#{type} parameters")
end
check_invocation(node, type) click to toggle source

Check arguments passed to a function/mixin invocation

# File lib/scss_lint/linter/space_after_comma.rb, line 44
def check_invocation(node, type)
  args = sort_args_by_position(node.args,
                               node.splat,
                               node.keywords.values,
                               node.kwarg_splat)

  check_commas_after_args(args, "#{type} arguments")
end
find_comma_offset(arg) click to toggle source

Find the comma following this argument.

The Sass parser is unpredictable in where it marks the end of the source range. Thus we need to start at the indicated range, and check left and right of that range, gradually moving further outward until we find the comma.

# File lib/scss_lint/linter/space_after_comma.rb, line 94
def find_comma_offset(arg)
  offset = 0

  if character_at(arg.source_range.end_pos, offset) != ','
    loop do
      offset += 1
      break if character_at(arg.source_range.end_pos, offset) == ','
      offset = -offset
      break if character_at(arg.source_range.end_pos, offset) == ','
      offset = -offset
    end
  end

  offset
end
sort_args_by_position(*args) click to toggle source

Since keyword arguments are not guaranteed to be in order, use the source range to order arguments so we check them in the order they were declared.

# File lib/scss_lint/linter/space_after_comma.rb, line 55
def sort_args_by_position(*args)
  args.flatten.compact.sort_by do |arg|
    pos = arg.source_range.end_pos
    [pos.line, pos.offset]
  end
end