brew vendor-gems: commit updates.
This commit is contained in:
parent
898f3f1fcb
commit
c25fb4eb35
@ -88,7 +88,7 @@ $:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-progressbar-1.11
|
||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/unicode-display_width-2.1.0/lib"
|
||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-1.24.1/lib"
|
||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-performance-1.13.1/lib"
|
||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rails-2.13.0/lib"
|
||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rails-2.13.1/lib"
|
||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-rspec-2.7.0/lib"
|
||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/rubocop-sorbet-0.6.5/lib"
|
||||
$:.unshift "#{path}/../#{ruby_engine}/#{ruby_version}/gems/ruby-macho-2.5.1/lib"
|
||||
|
@ -23,22 +23,22 @@ module RuboCop
|
||||
|
||||
def_node_matcher :on_bad_each_with_object, <<~PATTERN
|
||||
(block
|
||||
({send csend} _ :each_with_object (hash))
|
||||
(call _ :each_with_object (hash))
|
||||
(args (arg $_el) (arg _memo))
|
||||
({send csend} (lvar _memo) :[]= $!`_memo (lvar _el)))
|
||||
(call (lvar _memo) :[]= $!`_memo (lvar _el)))
|
||||
PATTERN
|
||||
|
||||
def_node_matcher :on_bad_to_h, <<~PATTERN
|
||||
(block
|
||||
({send csend} _ :to_h)
|
||||
(call _ :to_h)
|
||||
(args (arg $_el))
|
||||
(array $_ (lvar _el)))
|
||||
PATTERN
|
||||
|
||||
def_node_matcher :on_bad_map_to_h, <<~PATTERN
|
||||
({send csend}
|
||||
(call
|
||||
(block
|
||||
({send csend} _ {:map :collect})
|
||||
(call _ {:map :collect})
|
||||
(args (arg $_el))
|
||||
(array $_ (lvar _el)))
|
||||
:to_h)
|
||||
@ -49,7 +49,7 @@ module RuboCop
|
||||
(const _ :Hash)
|
||||
:[]
|
||||
(block
|
||||
({send csend} _ {:map :collect})
|
||||
(call _ {:map :collect})
|
||||
(args (arg $_el))
|
||||
(array $_ (lvar _el))))
|
||||
PATTERN
|
@ -26,22 +26,22 @@ module RuboCop
|
||||
|
||||
def_node_matcher :on_bad_each_with_object, <<~PATTERN
|
||||
(block
|
||||
({send csend} _ :each_with_object (hash))
|
||||
(call _ :each_with_object (hash))
|
||||
(args (arg $_el) (arg _memo))
|
||||
({send csend} (lvar _memo) :[]= (lvar _el) $!`_memo))
|
||||
(call (lvar _memo) :[]= (lvar _el) $!`_memo))
|
||||
PATTERN
|
||||
|
||||
def_node_matcher :on_bad_to_h, <<~PATTERN
|
||||
(block
|
||||
({send csend} _ :to_h)
|
||||
(call _ :to_h)
|
||||
(args (arg $_el))
|
||||
(array (lvar _el) $_))
|
||||
PATTERN
|
||||
|
||||
def_node_matcher :on_bad_map_to_h, <<~PATTERN
|
||||
({send csend}
|
||||
(call
|
||||
(block
|
||||
({send csend} _ {:map :collect})
|
||||
(call _ {:map :collect})
|
||||
(args (arg $_el))
|
||||
(array (lvar _el) $_))
|
||||
:to_h)
|
||||
@ -52,7 +52,7 @@ module RuboCop
|
||||
(const _ :Hash)
|
||||
:[]
|
||||
(block
|
||||
({send csend} _ {:map :collect})
|
||||
(call _ {:map :collect})
|
||||
(args (arg $_el))
|
||||
(array (lvar _el) $_)))
|
||||
PATTERN
|
@ -23,6 +23,17 @@ module RuboCop
|
||||
# # good
|
||||
# x = self[:attr]
|
||||
# self[:attr] = val
|
||||
#
|
||||
# When called from within a method with the same name as the attribute,
|
||||
# `read_attribute` and `write_attribute` must be used to prevent an
|
||||
# infinite loop:
|
||||
#
|
||||
# @example
|
||||
#
|
||||
# # good
|
||||
# def foo
|
||||
# bar || read_attribute(:foo)
|
||||
# end
|
||||
class ReadWriteAttribute < Base
|
||||
extend AutoCorrector
|
||||
|
||||
@ -38,6 +49,7 @@ module RuboCop
|
||||
|
||||
def on_send(node)
|
||||
return unless read_write_attribute?(node)
|
||||
return if within_shadowing_method?(node)
|
||||
|
||||
add_offense(node.loc.selector, message: message(node)) do |corrector|
|
||||
case node.method_name
|
||||
@ -53,6 +65,15 @@ module RuboCop
|
||||
|
||||
private
|
||||
|
||||
def within_shadowing_method?(node)
|
||||
node.each_ancestor(:def).any? do |enclosing_method|
|
||||
shadowing_method_name = node.first_argument.value.to_s
|
||||
shadowing_method_name << '=' if node.method?(:write_attribute)
|
||||
|
||||
enclosing_method.method_name.to_s == shadowing_method_name
|
||||
end
|
||||
end
|
||||
|
||||
def message(node)
|
||||
if node.method?(:read_attribute)
|
||||
format(MSG, prefer: 'self[:attr]', current: 'read_attribute(:attr)')
|
@ -32,7 +32,7 @@ module RuboCop
|
||||
extend AutoCorrector
|
||||
extend TargetRailsVersion
|
||||
|
||||
MSG = 'Remove explicit presence validation for `%<association>s`.'
|
||||
MSG = 'Remove explicit presence validation for %<association>s.'
|
||||
RESTRICT_ON_SEND = %i[validates].freeze
|
||||
|
||||
minimum_target_rails_version 5.0
|
||||
@ -43,28 +43,39 @@ module RuboCop
|
||||
# @example source that matches - by association
|
||||
# validates :user, presence: true
|
||||
#
|
||||
# @example source that matches - by association
|
||||
# validates :name, :user, presence: true
|
||||
#
|
||||
# @example source that matches - with presence options
|
||||
# validates :user, presence: { message: 'duplicate' }
|
||||
#
|
||||
# @example source that matches - by a foreign key
|
||||
# validates :user_id, presence: true
|
||||
#
|
||||
# @example source that DOES NOT match - strict validation
|
||||
# validates :user_id, presence: true, strict: true
|
||||
#
|
||||
# @example source that DOES NOT match - custom strict validation
|
||||
# validates :user_id, presence: true, strict: MissingUserError
|
||||
def_node_matcher :presence_validation?, <<~PATTERN
|
||||
$(
|
||||
(
|
||||
send nil? :validates
|
||||
(sym $_)
|
||||
...
|
||||
$(hash <$(pair (sym :presence) {true hash}) ...>)
|
||||
(sym $_)+
|
||||
$[
|
||||
(hash <$(pair (sym :presence) {true hash}) ...>) # presence: true
|
||||
!(hash <$(pair (sym :strict) {true const}) ...>) # strict: true
|
||||
]
|
||||
)
|
||||
PATTERN
|
||||
|
||||
# @!method optional_option?(node)
|
||||
# Match a `belongs_to` association with an optional option in a hash
|
||||
# @!method optional?(node)
|
||||
# Match a `belongs_to` association with an optional option in a hash
|
||||
def_node_matcher :optional?, <<~PATTERN
|
||||
(send nil? :belongs_to _ ... #optional_option?)
|
||||
PATTERN
|
||||
|
||||
# @!method optional_option?(node)
|
||||
# Match an optional option in a hash
|
||||
# Match an optional option in a hash
|
||||
def_node_matcher :optional_option?, <<~PATTERN
|
||||
{
|
||||
(hash <(pair (sym :optional) true) ...>) # optional: true
|
||||
@ -122,7 +133,7 @@ module RuboCop
|
||||
)
|
||||
PATTERN
|
||||
|
||||
# @!method belongs_to_without_fk?(node, fk)
|
||||
# @!method belongs_to_without_fk?(node, key)
|
||||
# Match a matching `belongs_to` association, without an explicit `foreign_key` option
|
||||
#
|
||||
# @param node [RuboCop::AST::Node]
|
||||
@ -150,22 +161,44 @@ module RuboCop
|
||||
PATTERN
|
||||
|
||||
def on_send(node)
|
||||
validation, key, options, presence = presence_validation?(node)
|
||||
return unless validation
|
||||
presence_validation?(node) do |all_keys, options, presence|
|
||||
keys = non_optional_belongs_to(node.parent, all_keys)
|
||||
return if keys.none?
|
||||
|
||||
belongs_to = belongs_to_for(node.parent, key)
|
||||
return unless belongs_to
|
||||
return if optional?(belongs_to)
|
||||
|
||||
message = format(MSG, association: key.to_s)
|
||||
|
||||
add_offense(presence, message: message) do |corrector|
|
||||
remove_presence_validation(corrector, node, options, presence)
|
||||
add_offense_and_correct(node, all_keys, keys, options, presence)
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def add_offense_and_correct(node, all_keys, keys, options, presence)
|
||||
add_offense(presence, message: message_for(keys)) do |corrector|
|
||||
if options.children.one? # `presence: true` is the only option
|
||||
if keys == all_keys
|
||||
remove_validation(corrector, node)
|
||||
else
|
||||
remove_keys_from_validation(corrector, node, keys)
|
||||
end
|
||||
elsif keys == all_keys
|
||||
remove_presence_option(corrector, presence)
|
||||
else
|
||||
extract_validation_for_keys(corrector, node, keys, options)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def message_for(keys)
|
||||
display_keys = keys.map { |key| "`#{key}`" }.join('/')
|
||||
format(MSG, association: display_keys)
|
||||
end
|
||||
|
||||
def non_optional_belongs_to(node, keys)
|
||||
keys.select do |key|
|
||||
belongs_to = belongs_to_for(node, key)
|
||||
belongs_to && !optional?(belongs_to)
|
||||
end
|
||||
end
|
||||
|
||||
def belongs_to_for(model_class_node, key)
|
||||
if key.to_s.end_with?('_id')
|
||||
normalized_key = key.to_s.delete_suffix('_id').to_sym
|
||||
@ -175,17 +208,48 @@ module RuboCop
|
||||
end
|
||||
end
|
||||
|
||||
def remove_presence_validation(corrector, node, options, presence)
|
||||
if options.children.one?
|
||||
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
|
||||
else
|
||||
range = range_with_surrounding_comma(
|
||||
range_with_surrounding_space(range: presence.source_range, side: :left),
|
||||
:left
|
||||
def remove_validation(corrector, node)
|
||||
corrector.remove(validation_range(node))
|
||||
end
|
||||
|
||||
def remove_keys_from_validation(corrector, node, keys)
|
||||
keys.each do |key|
|
||||
key_node = node.arguments.find { |arg| arg.value == key }
|
||||
key_range = range_with_surrounding_space(
|
||||
range: range_with_surrounding_comma(key_node.source_range, :right),
|
||||
side: :right
|
||||
)
|
||||
corrector.remove(range)
|
||||
corrector.remove(key_range)
|
||||
end
|
||||
end
|
||||
|
||||
def remove_presence_option(corrector, presence)
|
||||
range = range_with_surrounding_comma(
|
||||
range_with_surrounding_space(range: presence.source_range, side: :left),
|
||||
:left
|
||||
)
|
||||
corrector.remove(range)
|
||||
end
|
||||
|
||||
def extract_validation_for_keys(corrector, node, keys, options)
|
||||
indentation = ' ' * node.source_range.column
|
||||
options_without_presence = options.children.reject { |pair| pair.key.value == :presence }
|
||||
source = [
|
||||
indentation,
|
||||
'validates ',
|
||||
keys.map(&:inspect).join(', '),
|
||||
', ',
|
||||
options_without_presence.map(&:source).join(', '),
|
||||
"\n"
|
||||
].join
|
||||
|
||||
remove_keys_from_validation(corrector, node, keys)
|
||||
corrector.insert_after(validation_range(node), source)
|
||||
end
|
||||
|
||||
def validation_range(node)
|
||||
range_by_whole_lines(node.source_range, include_final_newline: true)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
@ -179,7 +179,7 @@ module RuboCop
|
||||
MSG = '%<action>s is not reversible.'
|
||||
|
||||
def_node_matcher :irreversible_schema_statement_call, <<~PATTERN
|
||||
(send nil? ${:change_column :execute :remove_belongs_to :remove_reference} ...)
|
||||
(send nil? ${:change_column :execute} ...)
|
||||
PATTERN
|
||||
|
||||
def_node_matcher :drop_table_call, <<~PATTERN
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user