Class: RuboCop::Cop::Homebrew::ShellCommands Private

Inherits:
Base
  • Object
show all
Extended by:
AutoCorrector
Includes:
RuboCop::Cop::HelperFunctions
Defined in:
rubocops/shell_commands.rb

Overview

This class is part of a private API. This class may only be used in the Homebrew/brew repository. Third parties should avoid using this class if possible, as it may be removed or changed without warning.

This cop makes sure that shell command arguments are separated.

Constant Summary collapse

MSG =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

"Separate `%<method>s` commands into `%<good_args>s`"
RESTRICT_ON_SEND =

This constant is part of a private API. This constant may only be used in the Homebrew/brew repository. Third parties should avoid using this constant if possible, as it may be removed or changed without warning.

TARGET_METHODS.map(&:second).uniq.freeze

Instance Method Summary collapse

Methods included from RuboCop::Cop::HelperFunctions

#block_method_called_in_block?, #block_size, #check_precedence, #class_name, #component_precedes?, #end_column, #expression_negated?, #find_all_blocks, #find_block, #find_blocks, #find_const, #find_every_func_call_by_name, #find_every_method_call_by_name, #find_instance_call, #find_instance_method_call, #find_method_calls_by_name, #find_method_def, #find_method_with_args, #find_node_method_by_name, #find_strings, #format_component, #line_number, #line_start_column, #method_called?, #method_called_ever?, #method_name, #node_equals?, #offending_node, #parameters, #parameters_passed?, #problem, #regex_match_group, #size, #source_buffer, #start_column, #string_content

Methods included from Kernel

#disk_usage_readable, #ensure_executable!, #ensure_formula_installed!, #exec_browser, #exec_editor, #ignore_interrupts, #interactive_shell, #number_readable, #odebug, #odeprecated, #odie, #odisabled, #ofail, #oh1, #oh1_title, #ohai, #ohai_title, #onoe, #opoo, #paths, #pretty_duration, #pretty_installed, #pretty_outdated, #pretty_uninstalled, #quiet_system, #redact_secrets, #redirect_stdout, #require?, #safe_system, #tap_and_name_comparison, #truncate_text_to_approximate_size, #which, #which_all, #which_editor, #with_custom_locale, #with_env, #with_homebrew_path

Instance Method Details

#on_send(node) ⇒ Object

This method is part of a private API. This method may only be used in the Homebrew/brew repository. Third parties should avoid using this method if possible, as it may be removed or changed without warning.



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
# File 'rubocops/shell_commands.rb', line 69

def on_send(node)
  TARGET_METHODS.each do |target_class, target_method|
    next if node.method_name != target_method

    target_receivers = if target_class.nil?
      [nil, s(:const, nil, :Kernel), s(:const, nil, :Homebrew)]
    else
      [s(:const, nil, target_class)]
    end
    next unless target_receivers.include?(node.receiver)

    first_arg = node.arguments.first
    arg_count = node.arguments.count
    if first_arg&.hash_type? # popen methods allow env hash
      first_arg = node.arguments.second
      arg_count -= 1
    end
    next if first_arg.nil? || arg_count >= 2

    first_arg_str = string_content(first_arg)
    stripped_first_arg_str = string_content(first_arg, strip_dynamic: true)

    split_args = first_arg_str.shellsplit
    next if split_args.count <= 1

    # Only separate when no shell metacharacters are present
    command = split_args.first
    next if SHELL_BUILTINS.any?(command)
    next if command&.include?("=")
    next if SHELL_METACHARACTERS.any? { |meta| stripped_first_arg_str.include?(meta) }

    good_args = split_args.map { |arg| "\"#{arg}\"" }.join(", ")
    method_string = if target_class
      "#{target_class}.#{target_method}"
    else
      target_method.to_s
    end
    add_offense(first_arg, message: format(MSG, method: method_string, good_args:)) do |corrector|
      corrector.replace(first_arg.source_range, good_args)
    end
  end
end