rubocop 0.42.0 → 0.43.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/assets/output.html.erb +21 -10
- data/config/default.yml +32 -2
- data/config/disabled.yml +8 -1
- data/config/enabled.yml +40 -12
- data/lib/rubocop.rb +14 -2
- data/lib/rubocop/ast_node.rb +2 -0
- data/lib/rubocop/cached_data.rb +13 -11
- data/lib/rubocop/cli.rb +5 -5
- data/lib/rubocop/config.rb +68 -24
- data/lib/rubocop/config_loader.rb +13 -11
- data/lib/rubocop/config_loader_resolver.rb +4 -2
- data/lib/rubocop/cop/cop.rb +16 -5
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +21 -20
- data/lib/rubocop/cop/lint/block_alignment.rb +3 -4
- data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -3
- data/lib/rubocop/cop/lint/duplicate_methods.rb +16 -6
- data/lib/rubocop/cop/lint/else_layout.rb +1 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/end_alignment.rb +4 -6
- data/lib/rubocop/cop/lint/eval.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -1
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +8 -8
- data/lib/rubocop/cop/lint/inherit_exception.rb +22 -7
- data/lib/rubocop/cop/lint/literal_in_condition.rb +5 -5
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +3 -5
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +9 -8
- data/lib/rubocop/cop/lint/percent_string_array.rb +17 -6
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +4 -4
- data/lib/rubocop/cop/lint/rand_one.rb +3 -3
- data/lib/rubocop/cop/lint/require_parentheses.rb +1 -3
- data/lib/rubocop/cop/lint/shadowed_exception.rb +39 -44
- data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +2 -2
- data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +1 -2
- data/lib/rubocop/cop/lint/unified_integer.rb +38 -0
- data/lib/rubocop/cop/lint/unneeded_disable.rb +51 -38
- data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +114 -0
- data/lib/rubocop/cop/lint/useless_assignment.rb +25 -12
- data/lib/rubocop/cop/lint/useless_setter_call.rb +27 -28
- data/lib/rubocop/cop/lint/void.rb +2 -4
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +5 -5
- data/lib/rubocop/cop/mixin/array_hash_indentation.rb +19 -17
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +3 -5
- data/lib/rubocop/cop/mixin/configurable_naming.rb +4 -5
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +52 -0
- data/lib/rubocop/cop/mixin/def_node.rb +28 -0
- data/lib/rubocop/cop/mixin/documentation_comment.rb +41 -0
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +18 -13
- data/lib/rubocop/cop/mixin/if_node.rb +6 -0
- data/lib/rubocop/cop/mixin/match_range.rb +2 -5
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +40 -28
- data/lib/rubocop/cop/mixin/negative_conditional.rb +6 -6
- data/lib/rubocop/cop/mixin/percent_literal.rb +1 -5
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +14 -4
- data/lib/rubocop/cop/mixin/safe_mode.rb +23 -0
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +2 -4
- data/lib/rubocop/cop/mixin/space_inside.rb +1 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +30 -20
- data/lib/rubocop/cop/mixin/trailing_comma.rb +19 -17
- data/lib/rubocop/cop/performance/case_when_splat.rb +16 -41
- data/lib/rubocop/cop/performance/casecmp.rb +28 -16
- data/lib/rubocop/cop/performance/count.rb +58 -34
- data/lib/rubocop/cop/performance/detect.rb +3 -7
- data/lib/rubocop/cop/performance/double_start_end_with.rb +17 -13
- data/lib/rubocop/cop/performance/fixed_size.rb +19 -14
- data/lib/rubocop/cop/performance/flat_map.rb +16 -9
- data/lib/rubocop/cop/performance/hash_each.rb +2 -3
- data/lib/rubocop/cop/performance/lstrip_rstrip.rb +4 -6
- data/lib/rubocop/cop/performance/redundant_match.rb +4 -1
- data/lib/rubocop/cop/performance/redundant_merge.rb +63 -32
- data/lib/rubocop/cop/performance/redundant_sort_by.rb +8 -7
- data/lib/rubocop/cop/performance/reverse_each.rb +1 -4
- data/lib/rubocop/cop/performance/size.rb +21 -8
- data/lib/rubocop/cop/performance/sort_with_block.rb +54 -0
- data/lib/rubocop/cop/performance/string_replacement.rb +3 -7
- data/lib/rubocop/cop/rails/delegate.rb +2 -3
- data/lib/rubocop/cop/rails/find_by.rb +4 -8
- data/lib/rubocop/cop/rails/not_null_column.rb +45 -0
- data/lib/rubocop/cop/rails/request_referer.rb +3 -3
- data/lib/rubocop/cop/rails/safe_navigation.rb +89 -0
- data/lib/rubocop/cop/rails/save_bang.rb +78 -9
- data/lib/rubocop/cop/rails/scope_args.rb +3 -1
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +2 -3
- data/lib/rubocop/cop/rails/validation.rb +1 -1
- data/lib/rubocop/cop/security/json_load.rb +36 -0
- data/lib/rubocop/cop/style/alias.rb +1 -1
- data/lib/rubocop/cop/style/align_hash.rb +25 -14
- data/lib/rubocop/cop/style/and_or.rb +13 -3
- data/lib/rubocop/cop/style/array_join.rb +3 -3
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -2
- data/lib/rubocop/cop/style/ascii_identifiers.rb +1 -2
- data/lib/rubocop/cop/style/attr.rb +1 -3
- data/lib/rubocop/cop/style/block_comments.rb +2 -6
- data/lib/rubocop/cop/style/block_delimiters.rb +35 -21
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +4 -4
- data/lib/rubocop/cop/style/case_indentation.rb +1 -3
- data/lib/rubocop/cop/style/class_methods.rb +3 -4
- data/lib/rubocop/cop/style/collection_methods.rb +1 -1
- data/lib/rubocop/cop/style/command_literal.rb +15 -8
- data/lib/rubocop/cop/style/comment_annotation.rb +1 -2
- data/lib/rubocop/cop/style/conditional_assignment.rb +68 -36
- data/lib/rubocop/cop/style/copyright.rb +1 -5
- data/lib/rubocop/cop/style/def_with_parentheses.rb +3 -5
- data/lib/rubocop/cop/style/documentation.rb +28 -56
- data/lib/rubocop/cop/style/documentation_method.rb +80 -0
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +6 -5
- data/lib/rubocop/cop/style/each_with_object.rb +2 -2
- data/lib/rubocop/cop/style/else_alignment.rb +10 -9
- data/lib/rubocop/cop/style/empty_case_condition.rb +2 -4
- data/lib/rubocop/cop/style/empty_else.rb +1 -4
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +1 -3
- data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +2 -5
- data/lib/rubocop/cop/style/encoding.rb +28 -14
- data/lib/rubocop/cop/style/even_odd.rb +28 -17
- data/lib/rubocop/cop/style/extra_spacing.rb +36 -25
- data/lib/rubocop/cop/style/file_name.rb +19 -10
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +2 -3
- data/lib/rubocop/cop/style/for.rb +12 -8
- data/lib/rubocop/cop/style/format_string.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +22 -56
- data/lib/rubocop/cop/style/hash_syntax.rb +72 -7
- data/lib/rubocop/cop/style/if_unless_modifier.rb +23 -19
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -3
- data/lib/rubocop/cop/style/indentation_width.rb +30 -16
- data/lib/rubocop/cop/style/infinite_loop.rb +16 -13
- data/lib/rubocop/cop/style/initial_indentation.rb +23 -18
- data/lib/rubocop/cop/style/inline_comment.rb +16 -3
- data/lib/rubocop/cop/style/lambda.rb +22 -10
- data/lib/rubocop/cop/style/leading_comment_space.rb +12 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +24 -6
- data/lib/rubocop/cop/style/method_call_parentheses.rb +18 -9
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -4
- data/lib/rubocop/cop/style/method_def_parentheses.rb +3 -4
- data/lib/rubocop/cop/style/method_missing.rb +10 -2
- data/lib/rubocop/cop/style/module_function.rb +14 -6
- data/lib/rubocop/cop/style/multiline_assignment_layout.rb +2 -5
- data/lib/rubocop/cop/style/multiline_block_chain.rb +3 -5
- data/lib/rubocop/cop/style/multiline_block_layout.rb +22 -15
- data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +9 -0
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +41 -20
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +6 -6
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +3 -5
- data/lib/rubocop/cop/style/mutable_constant.rb +21 -13
- data/lib/rubocop/cop/style/negated_if.rb +1 -1
- data/lib/rubocop/cop/style/negated_while.rb +3 -3
- data/lib/rubocop/cop/style/nested_modifier.rb +2 -4
- data/lib/rubocop/cop/style/next.rb +4 -4
- data/lib/rubocop/cop/style/non_nil_check.rb +18 -10
- data/lib/rubocop/cop/style/numeric_literal_prefix.rb +8 -0
- data/lib/rubocop/cop/style/numeric_predicate.rb +9 -9
- data/lib/rubocop/cop/style/one_line_conditional.rb +11 -1
- data/lib/rubocop/cop/style/op_method.rb +1 -1
- data/lib/rubocop/cop/style/option_hash.rb +8 -8
- data/lib/rubocop/cop/style/optional_arguments.rb +21 -8
- data/lib/rubocop/cop/style/parallel_assignment.rb +51 -35
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +2 -2
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/raise_args.rb +2 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +1 -1
- data/lib/rubocop/cop/style/redundant_parentheses.rb +26 -15
- data/lib/rubocop/cop/style/redundant_return.rb +5 -5
- data/lib/rubocop/cop/style/redundant_self.rb +20 -11
- data/lib/rubocop/cop/style/regexp_literal.rb +16 -10
- data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +8 -6
- data/lib/rubocop/cop/style/safe_navigation.rb +125 -0
- data/lib/rubocop/cop/style/self_assignment.rb +2 -2
- data/lib/rubocop/cop/style/semicolon.rb +9 -10
- data/lib/rubocop/cop/style/signal_exception.rb +2 -4
- data/lib/rubocop/cop/style/single_line_block_params.rb +1 -1
- data/lib/rubocop/cop/style/single_line_methods.rb +18 -11
- data/lib/rubocop/cop/style/space_after_method_name.rb +2 -3
- data/lib/rubocop/cop/style/space_after_not.rb +4 -6
- data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -2
- data/lib/rubocop/cop/style/space_around_equals_in_parameter_default.rb +1 -3
- data/lib/rubocop/cop/style/space_around_operators.rb +21 -16
- data/lib/rubocop/cop/style/space_before_block_braces.rb +2 -12
- data/lib/rubocop/cop/style/space_before_first_arg.rb +1 -3
- data/lib/rubocop/cop/style/space_inside_array_percent_literal.rb +1 -1
- data/lib/rubocop/cop/style/space_inside_block_braces.rb +33 -40
- data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +38 -23
- data/lib/rubocop/cop/style/space_inside_percent_literal_delimiters.rb +1 -1
- data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +26 -12
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -4
- data/lib/rubocop/cop/style/symbol_array.rb +10 -10
- data/lib/rubocop/cop/style/symbol_proc.rb +28 -13
- data/lib/rubocop/cop/style/ternary_parentheses.rb +35 -5
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +2 -4
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +29 -17
- data/lib/rubocop/cop/style/trivial_accessors.rb +6 -6
- data/lib/rubocop/cop/style/unless_else.rb +2 -6
- data/lib/rubocop/cop/style/unneeded_capital_w.rb +8 -4
- data/lib/rubocop/cop/style/unneeded_interpolation.rb +4 -5
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +13 -7
- data/lib/rubocop/cop/style/variable_number.rb +79 -0
- data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +25 -15
- data/lib/rubocop/cop/style/zero_length_predicate.rb +2 -0
- data/lib/rubocop/cop/util.rb +23 -4
- data/lib/rubocop/cop/variable_force.rb +59 -25
- data/lib/rubocop/cop/variable_force/locatable.rb +8 -6
- data/lib/rubocop/cop/variable_force/variable.rb +2 -2
- data/lib/rubocop/cop/variable_force/variable_table.rb +3 -3
- data/lib/rubocop/formatter/disabled_config_formatter.rb +16 -11
- data/lib/rubocop/formatter/formatter_set.rb +12 -10
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +4 -4
- data/lib/rubocop/node_pattern.rb +79 -35
- data/lib/rubocop/options.rb +4 -4
- data/lib/rubocop/processed_source.rb +9 -5
- data/lib/rubocop/remote_config.rb +14 -10
- data/lib/rubocop/result_cache.rb +14 -6
- data/lib/rubocop/runner.rb +55 -34
- data/lib/rubocop/string_util.rb +9 -5
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/token.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- metadata +15 -4
- data/lib/rubocop/cop/lint/useless_array_splat.rb +0 -56
- data/lib/rubocop/cop/performance/push_splat.rb +0 -47
@@ -0,0 +1,54 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Performance
|
7
|
+
# This cop identifies places where `sort { |a, b| a.foo <=> b.foo }`
|
8
|
+
# can be replaced by `sort_by(&:foo)`.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# @bad
|
12
|
+
# array.sort { |a, b| a.foo <=> b.foo }
|
13
|
+
#
|
14
|
+
# @good
|
15
|
+
# array.sort_by(&:foo)
|
16
|
+
# array.sort_by { |v| v.foo }
|
17
|
+
# array.sort_by do |var|
|
18
|
+
# var.foo
|
19
|
+
# end
|
20
|
+
class SortWithBlock < Cop
|
21
|
+
MSG = 'Use `sort_by(&:%s)` instead of ' \
|
22
|
+
'`sort { |%s, %s| %s.%s <=> %s.%s }`.'.freeze
|
23
|
+
|
24
|
+
def_node_matcher :sort, <<-END
|
25
|
+
(block $(send _ :sort) (args (arg $_a) (arg $_b)) (send (send (lvar _a) $_m) :<=> (send (lvar _b) $_m)))
|
26
|
+
END
|
27
|
+
|
28
|
+
def on_block(node)
|
29
|
+
sort(node) do |send, var_a, var_b, method|
|
30
|
+
range = sort_range(send, node)
|
31
|
+
add_offense(node, range,
|
32
|
+
format(MSG, method, var_a, var_b,
|
33
|
+
var_a, method, var_b, method))
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def autocorrect(node)
|
38
|
+
send, = *node
|
39
|
+
|
40
|
+
lambda do |corrector|
|
41
|
+
method = node.children.last.children.last.children.last
|
42
|
+
corrector.replace(sort_range(send, node), "sort_by(&:#{method})")
|
43
|
+
end
|
44
|
+
end
|
45
|
+
|
46
|
+
private
|
47
|
+
|
48
|
+
def sort_range(send, node)
|
49
|
+
range_between(send.loc.selector.begin_pos, node.loc.end.end_pos)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -160,9 +160,7 @@ module RuboCop
|
|
160
160
|
end
|
161
161
|
|
162
162
|
def range(node)
|
163
|
-
|
164
|
-
node.loc.selector.begin_pos,
|
165
|
-
node.source_range.end_pos)
|
163
|
+
range_between(node.loc.selector.begin_pos, node.source_range.end_pos)
|
166
164
|
end
|
167
165
|
|
168
166
|
def replacement_method(method, first_source, second_source)
|
@@ -192,10 +190,8 @@ module RuboCop
|
|
192
190
|
end
|
193
191
|
|
194
192
|
def remove_second_param(corrector, node, first_param)
|
195
|
-
end_range =
|
196
|
-
|
197
|
-
first_param.source_range.end_pos,
|
198
|
-
node.source_range.end_pos)
|
193
|
+
end_range = range_between(first_param.source_range.end_pos,
|
194
|
+
node.source_range.end_pos)
|
199
195
|
|
200
196
|
corrector.replace(end_range, method_suffix(node))
|
201
197
|
end
|
@@ -61,9 +61,8 @@ module RuboCop
|
|
61
61
|
end
|
62
62
|
|
63
63
|
def delegate?(body)
|
64
|
-
receiver,
|
65
|
-
return false unless receiver.is_a?
|
66
|
-
return false unless receiver.type == :send
|
64
|
+
receiver, = *body
|
65
|
+
return false unless receiver.is_a?(Node) && receiver.send_type?
|
67
66
|
receiver.child_nodes.empty?
|
68
67
|
end
|
69
68
|
|
@@ -26,9 +26,8 @@ module RuboCop
|
|
26
26
|
return unless (recv_and_method = where_first(node))
|
27
27
|
receiver, second_method = *recv_and_method
|
28
28
|
|
29
|
-
range =
|
30
|
-
|
31
|
-
node.loc.selector.end_pos)
|
29
|
+
range = range_between(receiver.loc.selector.begin_pos,
|
30
|
+
node.loc.selector.end_pos)
|
32
31
|
|
33
32
|
add_offense(node, range, format(MSG, second_method))
|
34
33
|
end
|
@@ -41,11 +40,8 @@ module RuboCop
|
|
41
40
|
return if second_method == :first
|
42
41
|
|
43
42
|
where_loc = receiver.loc.selector
|
44
|
-
first_loc =
|
45
|
-
|
46
|
-
node.loc.dot.begin_pos,
|
47
|
-
node.loc.selector.end_pos
|
48
|
-
)
|
43
|
+
first_loc = range_between(node.loc.dot.begin_pos,
|
44
|
+
node.loc.selector.end_pos)
|
49
45
|
|
50
46
|
lambda do |corrector|
|
51
47
|
corrector.replace(where_loc, 'find_by')
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Rails
|
7
|
+
# This cop checks for add_column call with NOT NULL constraint
|
8
|
+
# in migration file.
|
9
|
+
#
|
10
|
+
# @example
|
11
|
+
# # bad
|
12
|
+
# add_column :users, :name, :string, null: false
|
13
|
+
#
|
14
|
+
# # good
|
15
|
+
# add_column :users, :name, :string, null: true
|
16
|
+
# add_column :users, :name, :string, null: false, default: ''
|
17
|
+
class NotNullColumn < Cop
|
18
|
+
MSG = 'Do not add a NOT NULL column without a default value'.freeze
|
19
|
+
|
20
|
+
def_node_matcher :add_not_null_column?, <<-PATTERN
|
21
|
+
(send nil :add_column _ _ _ (hash $...))
|
22
|
+
PATTERN
|
23
|
+
|
24
|
+
def_node_matcher :null_false?, <<-PATTERN
|
25
|
+
(pair (sym :null) (false))
|
26
|
+
PATTERN
|
27
|
+
|
28
|
+
def_node_matcher :has_default?, <<-PATTERN
|
29
|
+
(pair (sym :default) !(:nil))
|
30
|
+
PATTERN
|
31
|
+
|
32
|
+
def on_send(node)
|
33
|
+
pairs = add_not_null_column?(node)
|
34
|
+
return unless pairs
|
35
|
+
return if pairs.any? { |pair| has_default?(pair) }
|
36
|
+
|
37
|
+
null_false = pairs.find { |pair| null_false?(pair) }
|
38
|
+
return unless null_false
|
39
|
+
|
40
|
+
add_offense(null_false, :expression)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -10,9 +10,9 @@ module RuboCop
|
|
10
10
|
include ConfigurableEnforcedStyle
|
11
11
|
|
12
12
|
def on_send(node)
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
return unless offense?(node)
|
14
|
+
|
15
|
+
add_offense(node.source_range, node.source_range, message)
|
16
16
|
end
|
17
17
|
|
18
18
|
def autocorrect(node)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Rails
|
7
|
+
# This cop converts usages of `try!` to `&.`. It can also be configured
|
8
|
+
# to convert `try`. It will convert code to use safe navigation if the
|
9
|
+
# target Ruby version is set to 2.3+
|
10
|
+
#
|
11
|
+
# @example
|
12
|
+
# # ConvertTry: false
|
13
|
+
# # bad
|
14
|
+
# foo.try!(:bar)
|
15
|
+
# foo.try!(:bar, baz)
|
16
|
+
# foo.try!(:bar) { |e| e.baz }
|
17
|
+
#
|
18
|
+
# foo.try!(:[], 0)
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# foo.try(:bar)
|
22
|
+
# foo.try(:bar, baz)
|
23
|
+
# foo.try(:bar) { |e| e.baz }
|
24
|
+
#
|
25
|
+
# foo&.bar
|
26
|
+
# foo&.bar(baz)
|
27
|
+
# foo&.bar { |e| e.baz }
|
28
|
+
#
|
29
|
+
#
|
30
|
+
# # ConvertTry: true
|
31
|
+
# # bad
|
32
|
+
# foo.try!(:bar)
|
33
|
+
# foo.try!(:bar, baz)
|
34
|
+
# foo.try!(:bar) { |e| e.baz }
|
35
|
+
# foo.try(:bar)
|
36
|
+
# foo.try(:bar, baz)
|
37
|
+
# foo.try(:bar) { |e| e.baz }
|
38
|
+
#
|
39
|
+
# # good
|
40
|
+
# foo&.bar
|
41
|
+
# foo&.bar(baz)
|
42
|
+
# foo&.bar { |e| e.baz }
|
43
|
+
class SafeNavigation < Cop
|
44
|
+
MSG = 'Use safe navigation (`&.`) instead of `%s`.'.freeze
|
45
|
+
|
46
|
+
def_node_matcher :try_call, <<-PATTERN
|
47
|
+
(send _ ${:try :try!} $_ ...)
|
48
|
+
PATTERN
|
49
|
+
|
50
|
+
def on_send(node)
|
51
|
+
return if target_ruby_version < 2.3
|
52
|
+
|
53
|
+
try_call(node) do |try_method, method_to_try|
|
54
|
+
return if try_method == :try && !cop_config['ConvertTry']
|
55
|
+
return unless method_to_try.sym_type?
|
56
|
+
method, = *method_to_try
|
57
|
+
return unless method =~ /\w+[=!?]?/
|
58
|
+
add_offense(node, :expression, format(MSG, try_method))
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def autocorrect(node)
|
65
|
+
_receiver, _try, method_node, *params = *node
|
66
|
+
method = method_node.source[1..-1]
|
67
|
+
range = range_between(node.loc.dot.begin_pos,
|
68
|
+
node.loc.expression.end_pos)
|
69
|
+
|
70
|
+
lambda do |corrector|
|
71
|
+
corrector.replace(range, replacement(method, params))
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def replacement(method, params)
|
76
|
+
new_params = params.map(&:source).join(', ')
|
77
|
+
|
78
|
+
if method.end_with?('=')
|
79
|
+
"&.#{method[0...-1]} = #{new_params}"
|
80
|
+
elsif params.empty?
|
81
|
+
"&.#{method}"
|
82
|
+
else
|
83
|
+
"&.#{method}(#{new_params})"
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -8,10 +8,12 @@ module RuboCop
|
|
8
8
|
# should be used instead of save because the model might have failed to
|
9
9
|
# save and an exception is better than unhandled failure.
|
10
10
|
#
|
11
|
-
# This will ignore calls that
|
12
|
-
#
|
13
|
-
#
|
14
|
-
#
|
11
|
+
# This will ignore calls that return a boolean for success if the result
|
12
|
+
# is assigned to a variable or used as the condition in an if/unless
|
13
|
+
# statement. It will also ignore calls that return a model assigned to a
|
14
|
+
# variable that has a call to `persisted?`. Finally, it will ignore any
|
15
|
+
# call with more than 2 arguments as that is likely not an Active Record
|
16
|
+
# call or a Model.update(id, attributes) call.
|
15
17
|
#
|
16
18
|
# @example
|
17
19
|
#
|
@@ -29,17 +31,57 @@ module RuboCop
|
|
29
31
|
# user.update!(name: 'Joe')
|
30
32
|
# user.find_or_create_by!(name: 'Joe')
|
31
33
|
# user.destroy!
|
34
|
+
#
|
35
|
+
# user = User.find_or_create_by(name: 'Joe')
|
36
|
+
# unless user.persisted?
|
37
|
+
# . . .
|
38
|
+
# end
|
32
39
|
class SaveBang < Cop
|
33
40
|
MSG = 'Use `%s` instead of `%s` if the return value is not checked.'
|
34
41
|
.freeze
|
42
|
+
CREATE_MSG = (MSG +
|
43
|
+
' Or check `persisted?` on model returned from `%s`.')
|
44
|
+
.freeze
|
45
|
+
CREATE_CONDITIONAL_MSG = '`%s` returns a model which is always truthy.'
|
46
|
+
.freeze
|
47
|
+
|
48
|
+
CREATE_PERSIST_METHODS = [:create,
|
49
|
+
:first_or_create, :find_or_create_by].freeze
|
50
|
+
MODIFY_PERSIST_METHODS = [:save, :update, :destroy].freeze
|
51
|
+
PERSIST_METHODS = (CREATE_PERSIST_METHODS +
|
52
|
+
MODIFY_PERSIST_METHODS).freeze
|
53
|
+
|
54
|
+
def join_force?(force_class)
|
55
|
+
force_class == VariableForce
|
56
|
+
end
|
35
57
|
|
36
|
-
|
37
|
-
|
58
|
+
def after_leaving_scope(scope, _variable_table)
|
59
|
+
scope.variables.each do |_name, variable|
|
60
|
+
variable.assignments.each do |assignment|
|
61
|
+
check_assignment(assignment)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def check_assignment(assignment)
|
67
|
+
node = right_assignment_node(assignment)
|
68
|
+
return unless node
|
69
|
+
return unless CREATE_PERSIST_METHODS.include?(node.method_name)
|
70
|
+
return unless expected_signature?(node)
|
71
|
+
return if persisted_referenced?(assignment)
|
72
|
+
|
73
|
+
add_offense(node, node.loc.selector,
|
74
|
+
format(CREATE_MSG,
|
75
|
+
"#{node.method_name}!",
|
76
|
+
node.method_name.to_s,
|
77
|
+
node.method_name.to_s))
|
78
|
+
end
|
38
79
|
|
39
80
|
def on_send(node)
|
40
81
|
return unless PERSIST_METHODS.include?(node.method_name)
|
41
|
-
return if return_value_used?(node)
|
42
82
|
return unless expected_signature?(node)
|
83
|
+
return if return_value_assigned?(node)
|
84
|
+
return if check_used_in_conditional(node)
|
43
85
|
|
44
86
|
add_offense(node, node.loc.selector,
|
45
87
|
format(MSG,
|
@@ -56,11 +98,38 @@ module RuboCop
|
|
56
98
|
|
57
99
|
private
|
58
100
|
|
101
|
+
def right_assignment_node(assignment)
|
102
|
+
node = assignment.node.child_nodes.first
|
103
|
+
return node unless node && node.block_type?
|
104
|
+
node.child_nodes.first
|
105
|
+
end
|
106
|
+
|
107
|
+
def persisted_referenced?(assignment)
|
108
|
+
return unless assignment.referenced?
|
109
|
+
assignment.variable.references.any? do |reference|
|
110
|
+
reference.node.parent.method_name == :persisted?
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def check_used_in_conditional(node)
|
115
|
+
return false unless node.parent
|
116
|
+
return false unless node.parent.if_type? && node.sibling_index.zero?
|
117
|
+
|
118
|
+
unless MODIFY_PERSIST_METHODS.include?(node.method_name)
|
119
|
+
add_offense(node, node.loc.selector,
|
120
|
+
format(CREATE_CONDITIONAL_MSG,
|
121
|
+
node.method_name.to_s))
|
122
|
+
end
|
123
|
+
|
124
|
+
true
|
125
|
+
end
|
126
|
+
|
59
127
|
# Ignore simple assignment or if condition
|
60
|
-
def
|
128
|
+
def return_value_assigned?(node)
|
61
129
|
return false unless node.parent
|
62
130
|
node.parent.lvasgn_type? ||
|
63
|
-
(node.parent.
|
131
|
+
(node.parent.block_type? && node.parent.parent &&
|
132
|
+
node.parent.parent.lvasgn_type?)
|
64
133
|
end
|
65
134
|
|
66
135
|
# Check argument signature as no arguments or one hash
|
@@ -72,9 +72,8 @@ module RuboCop
|
|
72
72
|
end
|
73
73
|
|
74
74
|
def dot_method_with_whitespace(method, node)
|
75
|
-
|
76
|
-
|
77
|
-
node.loc.selector.end_pos)
|
75
|
+
range_between(dot_method_begin_pos(method, node),
|
76
|
+
node.loc.selector.end_pos)
|
78
77
|
end
|
79
78
|
|
80
79
|
def dot_method_begin_pos(method, node)
|
@@ -51,7 +51,7 @@ module RuboCop
|
|
51
51
|
|
52
52
|
def correct_validate_type(corrector, node)
|
53
53
|
_receiver, method_name, *args = *node
|
54
|
-
options = args.find { |arg| arg.
|
54
|
+
options = args.find { |arg| !arg.sym_type? }
|
55
55
|
validate_type = method_name.to_s.split('_')[1]
|
56
56
|
|
57
57
|
if options
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
# frozen_string_literal: true
|
3
|
+
|
4
|
+
module RuboCop
|
5
|
+
module Cop
|
6
|
+
module Security
|
7
|
+
# This cop checks for the use of unsecure JSON methods.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# # always offense
|
11
|
+
# JSON.load("{}")
|
12
|
+
# JSON.restore("{}")
|
13
|
+
#
|
14
|
+
# # no offense
|
15
|
+
# JSON.parse("{}")
|
16
|
+
#
|
17
|
+
class JSONLoad < Cop
|
18
|
+
MSG = 'Prefer `JSON.parse` instead of `JSON#%s`.'.freeze
|
19
|
+
|
20
|
+
def_node_matcher :json_load, <<-END
|
21
|
+
(send (const nil :JSON) ${:load :restore} ...)
|
22
|
+
END
|
23
|
+
|
24
|
+
def on_send(node)
|
25
|
+
json_load(node) do |method|
|
26
|
+
add_offense(node, :selector, format(MSG, method))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
def autocorrect(node)
|
31
|
+
->(corrector) { corrector.replace(node.loc.selector, 'parse') }
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|