class RuboCop::Cop::Style::PercentLiteralDelimiters
%I(alpha beta)
# bad
%W(alpha #{beta})
# bad
%w[alpha beta] + %i(gamma delta)
# good
# ‘%i’: ‘()’
# default: ‘[]’
# PreferredDelimiters:
# Style/PercentLiteralDelimiters:
@example
default.
can continue to specify individual preferred delimiters to override the
Specify the ‘default’ key to set all preferred delimiters at once. You
This cop enforces the consistent usage of ‘%`-literal delimiters.
def autocorrect(node)
def autocorrect(node) type = type(node) opening_delimiter, closing_delimiter = preferred_delimiters_for(type) lambda do |corrector| corrector.replace(node.loc.begin, "#{type}#{opening_delimiter}") corrector.replace(node.loc.end, closing_delimiter) end end
def contains_preferred_delimiter?(node, type)
def contains_preferred_delimiter?(node, type) preferred_delimiters = preferred_delimiters_for(type) node .children.map { |n| string_source(n) }.compact .any? { |s| preferred_delimiters.any? { |d| s.include?(d) } } end
def include_same_character_as_used_for_delimiter?(node, type)
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]) escaped_delimiters = used_delimiters.map { |d| "\\#{d}" }.join('|') node .children.map { |n| string_source(n) }.compact .any? { |s| Regexp.new(escaped_delimiters) =~ s } end
def matchpairs(begin_delimiter)
def matchpairs(begin_delimiter) { '(' => %w[( )], '[' => %w[[ ]], '{' => %w[{ }], '<' => %w[< >] }.fetch(begin_delimiter, [begin_delimiter]) end
def message(node)
def message(node) type = type(node) delimiters = preferred_delimiters_for(type) "`#{type}`-literals should be delimited by " \ "`#{delimiters[0]}` and `#{delimiters[1]}`." end
def on_array(node)
def on_array(node) process(node, '%w', '%W', '%i', '%I') end
def on_percent_literal(node)
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) end
def on_regexp(node)
def on_regexp(node) process(node, '%r') end
def on_str(node)
def on_str(node) process(node, '%', '%Q', '%q') end
def on_sym(node)
def on_sym(node) process(node, '%s') end
def on_xstr(node)
def on_xstr(node) process(node, '%x') end
def string_source(node)
def string_source(node) if node.is_a?(String) node elsif node.respond_to?(:type) && node.str_type? node.source end end
def uses_preferred_delimiter?(node, type)
def uses_preferred_delimiter?(node, type) preferred_delimiters_for(type)[0] == begin_source(node)[-1] end