class RuboCop::Cop::Style::CommandLiteral

This cop enforces using “ or %x around command literals.

@example EnforcedStyle: backticks (default)

# bad
folders = %x(find . -type d).split

# bad
%x(
  ln -s foo.example.yml foo.example
  ln -s bar.example.yml bar.example
)

# good
folders = `find . -type d`.split

# good
`
  ln -s foo.example.yml foo.example
  ln -s bar.example.yml bar.example
`

@example EnforcedStyle: mixed

# bad
folders = %x(find . -type d).split

# bad
`
  ln -s foo.example.yml foo.example
  ln -s bar.example.yml bar.example
`

# good
folders = `find . -type d`.split

# good
%x(
  ln -s foo.example.yml foo.example
  ln -s bar.example.yml bar.example
)

@example EnforcedStyle: percent_x

# bad
folders = `find . -type d`.split

# bad
`
  ln -s foo.example.yml foo.example
  ln -s bar.example.yml bar.example
`

# good
folders = %x(find . -type d).split

# good
%x(
  ln -s foo.example.yml foo.example
  ln -s bar.example.yml bar.example
)

@example AllowInnerBackticks: false (default)

# If `false`, the cop will always recommend using `%x` if one or more
# backticks are found in the command string.

# bad
`echo \`ls\``

# good
%x(echo `ls`)

@example AllowInnerBackticks: true

# good
`echo \`ls\``

Constants

MSG_USE_BACKTICKS
MSG_USE_PERCENT_X

Public Instance Methods

autocorrect(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 94
def autocorrect(node)
  return if contains_backtick?(node)

  replacement = if backtick_literal?(node)
                  ['%x', ''].zip(preferred_delimiter).map(&:join)
                else
                  %w[` `]
                end

  lambda do |corrector|
    corrector.replace(node.loc.begin, replacement.first)
    corrector.replace(node.loc.end, replacement.last)
  end
end
on_xstr(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 84
def on_xstr(node)
  return if node.heredoc?

  if backtick_literal?(node)
    check_backtick_literal(node)
  else
    check_percent_x_literal(node)
  end
end

Private Instance Methods

allow_inner_backticks?() click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 151
def allow_inner_backticks?
  cop_config['AllowInnerBackticks']
end
allowed_backtick_literal?(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 127
def allowed_backtick_literal?(node)
  case style
  when :backticks
    !contains_disallowed_backtick?(node)
  when :mixed
    node.single_line? && !contains_disallowed_backtick?(node)
  end
end
allowed_percent_x_literal?(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 136
def allowed_percent_x_literal?(node)
  case style
  when :backticks
    contains_disallowed_backtick?(node)
  when :mixed
    node.multiline? || contains_disallowed_backtick?(node)
  when :percent_x
    true
  end
end
backtick_literal?(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 164
def backtick_literal?(node)
  node.loc.begin.source == '`'
end
check_backtick_literal(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 111
def check_backtick_literal(node)
  return if allowed_backtick_literal?(node)

  add_offense(node)
end
check_percent_x_literal(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 117
def check_percent_x_literal(node)
  return if allowed_percent_x_literal?(node)

  add_offense(node)
end
command_delimiter() click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 172
def command_delimiter
  preferred_delimiters_config['%x']
end
contains_backtick?(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 155
def contains_backtick?(node)
  node_body(node) =~ /`/
end
contains_disallowed_backtick?(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 147
def contains_disallowed_backtick?(node)
  !allow_inner_backticks? && contains_backtick?(node)
end
default_delimiter() click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 176
def default_delimiter
  preferred_delimiters_config['default']
end
message(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 123
def message(node)
  backtick_literal?(node) ? MSG_USE_PERCENT_X : MSG_USE_BACKTICKS
end
node_body(node) click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 159
def node_body(node)
  loc = node.loc
  loc.expression.source[loc.begin.length...-loc.end.length]
end
preferred_delimiter() click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 168
def preferred_delimiter
  (command_delimiter || default_delimiter).split(//)
end
preferred_delimiters_config() click to toggle source
# File lib/rubocop/cop/style/command_literal.rb, line 180
def preferred_delimiters_config
  config.for_cop('Style/PercentLiteralDelimiters') \
    ['PreferredDelimiters']
end