Class: RuboCop::Cop::Homebrew::NoSendInTests Private

Inherits:
Base
  • Object
show all
Defined in:
rubocops/no_send_in_tests.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.

Flags send-family dispatch in tests. Tests should exercise methods the way real callers do: a private method poked via send should be made public and called directly instead.

  • send/__send__ are always flagged: with a static method name the call can be written directly (after making the method public if needed); with a dynamic one it must go through public_send so it cannot bypass method visibility.
  • public_send is flagged only when the method name is a literal that could have been written as a direct call: an identifier, setter or operator name such as :[] or :<<. A dynamic name (public_send(method_name), public_send(:"#{artifact_dsl_key}_phase")) is the one legitimate use: parameterised dispatch to public API. A literal name with no direct call syntax (e.g. :"gcc-9") is also allowed, as no direct call can spell it.

Example

# bad
formula.send(:active_spec)

# good (with `active_spec` made public)
formula.active_spec

# good (dynamic dispatch to public API in a parameterised example)
subject.public_send(:"#{artifact_dsl_key}_phase")

Constant Summary collapse

MSG_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.

"Make the method public and call it directly instead of using `%<method>s` in tests."
MSG_SEND_DYNAMIC =

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.

"Use `public_send` instead of `%<method>s` in tests; " \
"`%<method>s` bypasses method visibility."
MSG_PUBLIC_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.

"Call the method directly instead of using `public_send` with a static method name."
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.

[:send, :__send__, :public_send].freeze
DIRECTLY_CALLABLE_NAME =

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.

A literal method name that direct call syntax can spell, including setters (public_send(:foo=, value) can be written receiver.foo = value).

/\A[a-zA-Z_][a-zA-Z0-9_]*[?!=]?\z/
DIRECTLY_CALLABLE_OPERATORS =

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.

Operator method names that direct call syntax can also spell, e.g. receiver[key], receiver[key] = value, receiver << value, !receiver. rubocop-ast's OPERATOR_METHODS is a private constant and includes `, which no direct call on an explicit receiver can spell.

%w(
  [] []= + - * / % ** == != < <= > >= <=> === =~ !~ & | ^ << >> ~ ! +@ -@
).freeze

Instance Method Summary collapse

Instance Method Details

#on_send(node) ⇒ void Also known as: on_csend

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.

This method returns an undefined value.

Parameters:

  • node (RuboCop::AST::SendNode)


52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
# File 'rubocops/no_send_in_tests.rb', line 52

def on_send(node)
  directly_callable = directly_callable_name?(node.first_argument)

  message = if node.method_name == :public_send
    return unless directly_callable

    MSG_PUBLIC_SEND
  elsif directly_callable
    format(MSG_SEND, method: node.method_name)
  else
    format(MSG_SEND_DYNAMIC, method: node.method_name)
  end

  add_offense(node.loc.selector, message:)
end