class RuboCop::Cop::Style::PercentLiteralDelimiters

Enforces the consistent usage of `%`-literal delimiters.

Specify the 'default' key to set all preferred delimiters at once. You can continue to specify individual preferred delimiters to override the default.

@example

# Style/PercentLiteralDelimiters:
#   PreferredDelimiters:
#     default: '[]'
#     '%i':    '()'

# good
%w[alpha beta] + %i(gamma delta)

# bad
%W(alpha #{beta})

# bad
%I(alpha beta)

Public Instance Methods

on_array(node) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 30
def on_array(node)
  process(node, '%w', '%W', '%i', '%I')
end
on_dstr(node)
Alias for: on_str
on_regexp(node) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 34
def on_regexp(node)
  process(node, '%r')
end
on_str(node) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 38
def on_str(node)
  process(node, '%', '%Q', '%q')
end
Also aliased as: on_dstr
on_sym(node) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 43
def on_sym(node)
  process(node, '%s')
end
on_xstr(node) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 47
def on_xstr(node)
  process(node, '%x')
end

Private Instance Methods

contains_delimiter?(node, delimiters) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 93
def contains_delimiter?(node, delimiters)
  delimiters_regexp = Regexp.union(delimiters)
  node
    .children.map { |n| string_source(n) }.compact
    .any? { |s| delimiters_regexp.match?(s) }
end
contains_preferred_delimiter?(node, type) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 82
def contains_preferred_delimiter?(node, type)
  contains_delimiter?(node, preferred_delimiters_for(type))
end
include_same_character_as_used_for_delimiter?(node, type) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 86
def include_same_character_as_used_for_delimiter?(node, type)
  return false unless %w[%w %i].include?(type)

  used_delimiters = matchpairs(begin_source(node)[-1])
  contains_delimiter?(node, used_delimiters)
end
matchpairs(begin_delimiter) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 108
def matchpairs(begin_delimiter)
  {
    '(' => %w[( )],
    '[' => %w[[ ]],
    '{' => %w[{ }],
    '<' => %w[< >]
  }.fetch(begin_delimiter, [begin_delimiter])
end
message(type) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 67
def message(type)
  delimiters = preferred_delimiters_for(type)

  "`#{type}`-literals should be delimited by " \
    "`#{delimiters[0]}` and `#{delimiters[1]}`."
end
on_percent_literal(node) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 53
def on_percent_literal(node)
  type = type(node)
  return if uses_preferred_delimiter?(node, type) ||
            contains_preferred_delimiter?(node, type) ||
            include_same_character_as_used_for_delimiter?(node, type)

  add_offense(node, message: message(type)) do |corrector|
    opening_delimiter, closing_delimiter = preferred_delimiters_for(type)

    corrector.replace(node.loc.begin, "#{type}#{opening_delimiter}")
    corrector.replace(node.loc.end, closing_delimiter)
  end
end
preferred_delimiters_for(type) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 74
def preferred_delimiters_for(type)
  PreferredDelimiters.new(type, @config, nil).delimiters
end
string_source(node) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 100
def string_source(node)
  if node.is_a?(String)
    node.scrub
  elsif node.respond_to?(:type) && (node.str_type? || node.sym_type?)
    node.source
  end
end
uses_preferred_delimiter?(node, type) click to toggle source
# File lib/rubocop/cop/style/percent_literal_delimiters.rb, line 78
def uses_preferred_delimiter?(node, type)
  preferred_delimiters_for(type)[0] == begin_source(node)[-1]
end