Class: RuboCop::Cop::Homebrew::NoSendInTests Private
- 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 throughpublic_sendso it cannot bypass method visibility.public_sendis 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 writtenreceiver.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'sOPERATOR_METHODSis a private constant and includes`, which no direct call on an explicit receiver can spell. %w( [] []= + - * / % ** == != < <= > >= <=> === =~ !~ & | ^ << >> ~ ! +@ -@ ).freeze
Instance Method Summary collapse
- #on_send(node) ⇒ void (also: #on_csend) private
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.
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) = 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 |