rubocop 0.47.1 → 0.48.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/README.md +28 -16
- data/config/default.yml +203 -115
- data/config/disabled.yml +0 -5
- data/config/enabled.yml +92 -8
- data/lib/rubocop.rb +24 -1
- data/lib/rubocop/ast/builder.rb +7 -2
- data/lib/rubocop/ast/node.rb +23 -20
- data/lib/rubocop/ast/node/and_node.rb +37 -0
- data/lib/rubocop/ast/node/array_node.rb +4 -1
- data/lib/rubocop/ast/node/case_node.rb +1 -0
- data/lib/rubocop/ast/node/ensure_node.rb +25 -0
- data/lib/rubocop/ast/node/hash_node.rb +10 -3
- data/lib/rubocop/ast/node/if_node.rb +2 -0
- data/lib/rubocop/ast/node/mixin/binary_operator_node.rb +23 -0
- data/lib/rubocop/ast/node/mixin/predicate_operator_node.rb +35 -0
- data/lib/rubocop/ast/node/or_node.rb +37 -0
- data/lib/rubocop/ast/node/resbody_node.rb +25 -0
- data/lib/rubocop/ast/node/send_node.rb +190 -0
- data/lib/rubocop/ast/node/when_node.rb +1 -1
- data/lib/rubocop/ast/traversal.rb +15 -15
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +39 -15
- data/lib/rubocop/config_loader.rb +34 -13
- data/lib/rubocop/cop/bundler/ordered_gems.rb +23 -4
- data/lib/rubocop/cop/commissioner.rb +4 -0
- data/lib/rubocop/cop/cop.rb +5 -0
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +53 -0
- data/lib/rubocop/cop/lint/debugger.rb +8 -1
- data/lib/rubocop/cop/lint/def_end_alignment.rb +2 -1
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +2 -4
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +1 -1
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +3 -1
- data/lib/rubocop/cop/lint/empty_ensure.rb +6 -2
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -1
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +20 -18
- data/lib/rubocop/cop/lint/handle_exceptions.rb +1 -3
- data/lib/rubocop/cop/lint/literal_in_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +1 -1
- data/lib/rubocop/cop/lint/multiple_compare.rb +5 -3
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +26 -18
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +7 -8
- data/lib/rubocop/cop/lint/require_parentheses.rb +7 -13
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +7 -3
- data/lib/rubocop/cop/lint/shadowed_exception.rb +2 -6
- data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +7 -8
- data/lib/rubocop/cop/lint/unneeded_disable.rb +35 -11
- data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +1 -1
- data/lib/rubocop/cop/lint/unreachable_code.rb +5 -2
- data/lib/rubocop/cop/lint/unused_block_argument.rb +6 -6
- data/lib/rubocop/cop/lint/useless_assignment.rb +2 -1
- data/lib/rubocop/cop/lint/useless_comparison.rb +5 -4
- data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -1
- data/lib/rubocop/cop/message_annotator.rb +7 -3
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +4 -4
- data/lib/rubocop/cop/metrics/cyclomatic_complexity.rb +2 -2
- data/lib/rubocop/cop/metrics/line_length.rb +2 -9
- data/lib/rubocop/cop/metrics/parameter_lists.rb +4 -3
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +2 -2
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +1 -1
- data/lib/rubocop/cop/mixin/array_hash_indentation.rb +2 -2
- data/lib/rubocop/cop/mixin/check_assignment.rb +6 -6
- data/lib/rubocop/cop/mixin/duplication.rb +1 -1
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +1 -1
- data/lib/rubocop/cop/mixin/ignored_pattern.rb +27 -0
- data/lib/rubocop/cop/mixin/method_preference.rb +2 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +17 -29
- data/lib/rubocop/cop/mixin/on_method_def.rb +3 -3
- data/lib/rubocop/cop/mixin/percent_literal.rb +27 -0
- data/lib/rubocop/cop/mixin/rescue_node.rb +21 -0
- data/lib/rubocop/cop/mixin/safe_mode.rb +1 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -1
- data/lib/rubocop/cop/mixin/target_rails_version.rb +16 -0
- data/lib/rubocop/cop/mixin/unused_argument.rb +1 -1
- data/lib/rubocop/cop/offense.rb +3 -3
- data/lib/rubocop/cop/performance/casecmp.rb +1 -1
- data/lib/rubocop/cop/performance/detect.rb +2 -1
- data/lib/rubocop/cop/performance/double_start_end_with.rb +35 -1
- data/lib/rubocop/cop/performance/end_with.rb +3 -1
- data/lib/rubocop/cop/performance/flat_map.rb +6 -6
- data/lib/rubocop/cop/performance/lstrip_rstrip.rb +2 -2
- data/lib/rubocop/cop/performance/range_include.rb +3 -1
- data/lib/rubocop/cop/performance/redundant_match.rb +6 -5
- data/lib/rubocop/cop/performance/regexp_match.rb +10 -3
- data/lib/rubocop/cop/performance/reverse_each.rb +2 -1
- data/lib/rubocop/cop/performance/size.rb +6 -11
- data/lib/rubocop/cop/performance/start_with.rb +3 -1
- data/lib/rubocop/cop/performance/string_replacement.rb +13 -18
- data/lib/rubocop/cop/performance/times_map.rb +4 -4
- data/lib/rubocop/cop/rails/action_filter.rb +42 -42
- data/lib/rubocop/cop/rails/active_support_aliases.rb +68 -0
- data/lib/rubocop/cop/rails/blank.rb +131 -0
- data/lib/rubocop/cop/rails/date.rb +25 -28
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +5 -7
- data/lib/rubocop/cop/rails/dynamic_find_by.rb +7 -3
- data/lib/rubocop/cop/rails/exit.rb +9 -9
- data/lib/rubocop/cop/rails/file_path.rb +5 -14
- data/lib/rubocop/cop/rails/find_by.rb +8 -10
- data/lib/rubocop/cop/rails/find_each.rb +6 -9
- data/lib/rubocop/cop/rails/has_and_belongs_to_many.rb +1 -0
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +15 -7
- data/lib/rubocop/cop/rails/output.rb +3 -5
- data/lib/rubocop/cop/rails/output_safety.rb +4 -8
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +25 -24
- data/lib/rubocop/cop/rails/present.rb +137 -0
- data/lib/rubocop/cop/rails/read_write_attribute.rb +9 -18
- data/lib/rubocop/cop/rails/relative_date_constant.rb +53 -0
- data/lib/rubocop/cop/rails/request_referer.rb +7 -4
- data/lib/rubocop/cop/rails/reversible_migration.rb +1 -2
- data/lib/rubocop/cop/rails/safe_navigation.rb +2 -1
- data/lib/rubocop/cop/rails/save_bang.rb +10 -10
- data/lib/rubocop/cop/rails/skips_model_validations.rb +23 -6
- data/lib/rubocop/cop/rails/time_zone.rb +20 -18
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +3 -2
- data/lib/rubocop/cop/rails/validation.rb +8 -11
- data/lib/rubocop/cop/registry.rb +3 -3
- data/lib/rubocop/cop/security/json_load.rb +1 -1
- data/lib/rubocop/cop/security/marshal_load.rb +5 -1
- data/lib/rubocop/cop/security/yaml_load.rb +3 -3
- data/lib/rubocop/cop/severity.rb +1 -1
- data/lib/rubocop/cop/style/alias.rb +5 -5
- data/lib/rubocop/cop/style/align_hash.rb +1 -1
- data/lib/rubocop/cop/style/align_parameters.rb +5 -5
- data/lib/rubocop/cop/style/and_or.rb +16 -31
- data/lib/rubocop/cop/style/attr.rb +14 -8
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +8 -11
- data/lib/rubocop/cop/style/block_delimiters.rb +11 -13
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +19 -23
- data/lib/rubocop/cop/style/case_indentation.rb +2 -0
- data/lib/rubocop/cop/style/class_and_module_children.rb +1 -1
- data/lib/rubocop/cop/style/class_check.rb +5 -7
- data/lib/rubocop/cop/style/closing_parenthesis_indentation.rb +5 -4
- data/lib/rubocop/cop/style/collection_methods.rb +8 -8
- data/lib/rubocop/cop/style/colon_method_call.rb +2 -9
- data/lib/rubocop/cop/style/conditional_assignment.rb +38 -45
- data/lib/rubocop/cop/style/constant_name.rb +1 -1
- data/lib/rubocop/cop/style/documentation_method.rb +1 -0
- data/lib/rubocop/cop/style/dot_position.rb +3 -7
- data/lib/rubocop/cop/style/double_negation.rb +2 -1
- data/lib/rubocop/cop/style/each_with_object.rb +1 -1
- data/lib/rubocop/cop/style/empty_else.rb +2 -2
- data/lib/rubocop/cop/style/empty_line_after_magic_comment.rb +63 -0
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +74 -4
- data/lib/rubocop/cop/style/empty_lines_around_begin_body.rb +42 -0
- data/lib/rubocop/cop/style/empty_lines_around_exception_handling_keywords.rb +127 -0
- data/lib/rubocop/cop/style/empty_literal.rb +17 -9
- data/lib/rubocop/cop/style/end_of_line.rb +25 -3
- data/lib/rubocop/cop/style/file_name.rb +1 -1
- data/lib/rubocop/cop/style/first_method_argument_line_break.rb +1 -1
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +17 -19
- data/lib/rubocop/cop/style/for.rb +2 -4
- data/lib/rubocop/cop/style/format_string.rb +5 -4
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +1 -1
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +27 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +2 -2
- data/lib/rubocop/cop/style/indent_assignment.rb +2 -2
- data/lib/rubocop/cop/style/indent_hash.rb +2 -1
- data/lib/rubocop/cop/style/indent_heredoc.rb +173 -0
- data/lib/rubocop/cop/style/indentation_width.rb +61 -29
- data/lib/rubocop/cop/style/inverse_methods.rb +130 -0
- data/lib/rubocop/cop/style/lambda_call.rb +15 -11
- data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +26 -14
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +6 -16
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +4 -1
- data/lib/rubocop/cop/style/missing_else.rb +4 -3
- data/lib/rubocop/cop/style/mixin_grouping.rb +97 -0
- data/lib/rubocop/cop/style/multiline_memoization.rb +38 -5
- data/lib/rubocop/cop/style/multiline_method_call_brace_layout.rb +2 -3
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +38 -19
- data/lib/rubocop/cop/style/mutable_constant.rb +5 -1
- data/lib/rubocop/cop/style/negated_if.rb +73 -1
- data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +21 -19
- data/lib/rubocop/cop/style/next.rb +5 -5
- data/lib/rubocop/cop/style/non_nil_check.rb +7 -10
- data/lib/rubocop/cop/style/not.rb +3 -4
- data/lib/rubocop/cop/style/numeric_literals.rb +25 -3
- data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
- data/lib/rubocop/cop/style/one_line_conditional.rb +2 -2
- data/lib/rubocop/cop/style/op_method.rb +2 -2
- data/lib/rubocop/cop/style/parallel_assignment.rb +6 -3
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +52 -6
- data/lib/rubocop/cop/style/perl_backrefs.rb +1 -1
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -9
- data/lib/rubocop/cop/style/raise_args.rb +28 -24
- data/lib/rubocop/cop/style/redundant_freeze.rb +5 -7
- data/lib/rubocop/cop/style/redundant_parentheses.rb +2 -3
- data/lib/rubocop/cop/style/redundant_self.rb +17 -35
- data/lib/rubocop/cop/style/rescue_modifier.rb +2 -14
- data/lib/rubocop/cop/style/self_assignment.rb +3 -3
- data/lib/rubocop/cop/style/send.rb +4 -5
- data/lib/rubocop/cop/style/space_after_not.rb +7 -8
- data/lib/rubocop/cop/style/space_around_keyword.rb +8 -9
- data/lib/rubocop/cop/style/space_around_operators.rb +19 -15
- data/lib/rubocop/cop/style/space_before_first_arg.rb +17 -14
- data/lib/rubocop/cop/style/space_inside_brackets.rb +1 -1
- data/lib/rubocop/cop/style/space_inside_hash_literal_braces.rb +3 -3
- data/lib/rubocop/cop/style/space_inside_parens.rb +1 -1
- data/lib/rubocop/cop/style/special_global_vars.rb +14 -14
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/string_literals.rb +1 -1
- data/lib/rubocop/cop/style/string_methods.rb +10 -5
- data/lib/rubocop/cop/style/struct_inheritance.rb +4 -15
- data/lib/rubocop/cop/style/symbol_array.rb +31 -35
- data/lib/rubocop/cop/style/symbol_proc.rb +2 -2
- data/lib/rubocop/cop/style/ternary_parentheses.rb +41 -13
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +6 -9
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +4 -1
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/unneeded_capital_w.rb +1 -2
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +12 -34
- data/lib/rubocop/cop/style/zero_length_predicate.rb +11 -4
- data/lib/rubocop/cop/team.rb +4 -1
- data/lib/rubocop/cop/util.rb +33 -26
- data/lib/rubocop/cop/variable_force.rb +13 -13
- data/lib/rubocop/cop/variable_force/assignment.rb +1 -8
- data/lib/rubocop/cop/variable_force/branch.rb +318 -0
- data/lib/rubocop/cop/variable_force/branchable.rb +21 -0
- data/lib/rubocop/cop/variable_force/reference.rb +1 -3
- data/lib/rubocop/cop/variable_force/scope.rb +36 -20
- data/lib/rubocop/cop/variable_force/variable.rb +9 -8
- data/lib/rubocop/formatter/colorizable.rb +10 -10
- data/lib/rubocop/formatter/formatter_set.rb +1 -1
- data/lib/rubocop/formatter/html_formatter.rb +2 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +4 -2
- data/lib/rubocop/magic_comment.rb +20 -6
- data/lib/rubocop/options.rb +1 -1
- data/lib/rubocop/platform.rb +11 -0
- data/lib/rubocop/processed_source.rb +1 -1
- data/lib/rubocop/remote_config.rb +18 -6
- data/lib/rubocop/result_cache.rb +8 -8
- data/lib/rubocop/rspec/cop_helper.rb +2 -0
- data/lib/rubocop/rspec/shared_contexts.rb +20 -0
- data/lib/rubocop/rspec/shared_examples.rb +1 -1
- data/lib/rubocop/runner.rb +2 -2
- data/lib/rubocop/target_finder.rb +64 -6
- data/lib/rubocop/version.rb +2 -4
- metadata +27 -4
- data/lib/rubocop/cop/variable_force/locatable.rb +0 -200
@@ -25,10 +25,8 @@ module RuboCop
|
|
25
25
|
return if block_length(node).zero?
|
26
26
|
|
27
27
|
method, _args, _body = *node
|
28
|
-
return unless method.send_type?
|
29
|
-
|
30
|
-
_receiver, method_name, *args = *method
|
31
|
-
return unless method_name == :each && args.empty?
|
28
|
+
return unless method.send_type? && method.method?(:each) &&
|
29
|
+
!method.arguments?
|
32
30
|
|
33
31
|
if style == :for
|
34
32
|
incorrect_style_detected(method)
|
@@ -24,12 +24,13 @@ module RuboCop
|
|
24
24
|
PATTERN
|
25
25
|
|
26
26
|
def on_send(node)
|
27
|
-
|
27
|
+
formatter(node) do |selector|
|
28
|
+
detected_style = selector == :% ? :percent : selector
|
28
29
|
|
29
|
-
|
30
|
-
return if detected_style == style
|
30
|
+
return if detected_style == style
|
31
31
|
|
32
|
-
|
32
|
+
add_offense(node, :selector, message(detected_style))
|
33
|
+
end
|
33
34
|
end
|
34
35
|
|
35
36
|
def message(detected_style)
|
@@ -12,7 +12,7 @@ module RuboCop
|
|
12
12
|
include ConfigurableEnforcedStyle
|
13
13
|
include FrozenStringLiteral
|
14
14
|
|
15
|
-
MSG = 'Missing
|
15
|
+
MSG = 'Missing magic comment `# frozen_string_literal: true`.'.freeze
|
16
16
|
MSG_UNNECESSARY = 'Unnecessary frozen string literal comment.'.freeze
|
17
17
|
SHEBANG = '#!'.freeze
|
18
18
|
|
@@ -40,6 +40,28 @@ module RuboCop
|
|
40
40
|
# else
|
41
41
|
# do_y
|
42
42
|
# end
|
43
|
+
#
|
44
|
+
# @bad
|
45
|
+
# switch foo
|
46
|
+
# when 1
|
47
|
+
# do_x
|
48
|
+
# when 2
|
49
|
+
# do_x
|
50
|
+
# else
|
51
|
+
# do_x
|
52
|
+
# end
|
53
|
+
#
|
54
|
+
# @good
|
55
|
+
# switch foo
|
56
|
+
# when 1
|
57
|
+
# do_x
|
58
|
+
# do_y
|
59
|
+
# when 2
|
60
|
+
# # nothing
|
61
|
+
# else
|
62
|
+
# do_x
|
63
|
+
# do_z
|
64
|
+
# end
|
43
65
|
class IdenticalConditionalBranches < Cop
|
44
66
|
MSG = 'Move `%s` out of the conditional.'.freeze
|
45
67
|
|
@@ -58,7 +80,11 @@ module RuboCop
|
|
58
80
|
def on_case(node)
|
59
81
|
return unless node.else? && node.else_branch
|
60
82
|
|
61
|
-
|
83
|
+
branches = node.when_branches.map(&:body).push(node.else_branch)
|
84
|
+
|
85
|
+
return if branches.any?(&:nil?)
|
86
|
+
|
87
|
+
check_branches(branches)
|
62
88
|
end
|
63
89
|
|
64
90
|
private
|
@@ -13,8 +13,8 @@ module RuboCop
|
|
13
13
|
'Another good alternative is the usage of control flow ' \
|
14
14
|
'`&&`/`||`.'.freeze
|
15
15
|
|
16
|
-
ASSIGNMENT_TYPES =
|
17
|
-
|
16
|
+
ASSIGNMENT_TYPES = %i(lvasgn casgn cvasgn
|
17
|
+
gvasgn ivasgn masgn).freeze
|
18
18
|
|
19
19
|
def on_if(node)
|
20
20
|
return unless eligible_node?(node)
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cops checks the indentation of the here document bodies. The bodies
|
7
|
+
# are indented one step.
|
8
|
+
# In Ruby 2.3 or newer, squiggly heredocs (`<<~`) should be used. If you
|
9
|
+
# use the older rubies, you should introduce some library to your project
|
10
|
+
# (e.g. ActiveSupport, Powerpack or Unindent).
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# # bad
|
15
|
+
# <<-END
|
16
|
+
# something
|
17
|
+
# END
|
18
|
+
#
|
19
|
+
# # good
|
20
|
+
# # When EnforcedStyle is squiggly, bad code is auto-corrected to the
|
21
|
+
# # following code.
|
22
|
+
# <<~END
|
23
|
+
# something
|
24
|
+
# END
|
25
|
+
#
|
26
|
+
# # good
|
27
|
+
# # When EnforcedStyle is active_support, bad code is auto-corrected to
|
28
|
+
# # the following code.
|
29
|
+
# <<-END.strip_heredoc
|
30
|
+
# something
|
31
|
+
# END
|
32
|
+
class IndentHeredoc < Cop
|
33
|
+
include ConfigurableEnforcedStyle
|
34
|
+
include SafeMode
|
35
|
+
|
36
|
+
RUBY23_MSG = 'Use %d spaces for indentation in a heredoc by using ' \
|
37
|
+
'`<<~` instead of `%s`.'.freeze
|
38
|
+
LIBRARY_MSG = 'Use %d spaces for indentation in a heredoc by using %s.'
|
39
|
+
.freeze
|
40
|
+
StripMethods = {
|
41
|
+
unindent: 'unindent',
|
42
|
+
active_support: 'strip_heredoc',
|
43
|
+
powerpack: 'strip_indent'
|
44
|
+
}.freeze
|
45
|
+
|
46
|
+
def on_str(node)
|
47
|
+
return unless heredoc?(node)
|
48
|
+
|
49
|
+
body_indent_level = body_indent_level(node)
|
50
|
+
|
51
|
+
if heredoc_indent_type(node) == '~'
|
52
|
+
expected_indent_level = base_indent_level(node) + indentation_width
|
53
|
+
return if expected_indent_level == body_indent_level
|
54
|
+
else
|
55
|
+
return unless body_indent_level.zero?
|
56
|
+
end
|
57
|
+
|
58
|
+
add_offense(node, :heredoc_body)
|
59
|
+
end
|
60
|
+
|
61
|
+
alias on_dstr on_str
|
62
|
+
alias on_xstr on_str
|
63
|
+
|
64
|
+
def autocorrect(node)
|
65
|
+
check_style!
|
66
|
+
|
67
|
+
case style
|
68
|
+
when :squiggly
|
69
|
+
correct_by_squiggly(node)
|
70
|
+
else
|
71
|
+
correct_by_library(node)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def style
|
78
|
+
style = super
|
79
|
+
return style unless style == :auto_detection
|
80
|
+
|
81
|
+
if target_ruby_version >= 2.3
|
82
|
+
:squiggly
|
83
|
+
elsif rails?
|
84
|
+
:active_support
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def message(node)
|
89
|
+
case style
|
90
|
+
when :squiggly
|
91
|
+
current_indent_type = "<<#{heredoc_indent_type(node)}"
|
92
|
+
format(RUBY23_MSG, indentation_width, current_indent_type)
|
93
|
+
when nil
|
94
|
+
method = "some library(e.g. ActiveSupport's `String#strip_heredoc`)"
|
95
|
+
format(LIBRARY_MSG, indentation_width, method)
|
96
|
+
else
|
97
|
+
method = "`String##{StripMethods[style]}`"
|
98
|
+
format(LIBRARY_MSG, indentation_width, method)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def correct_by_squiggly(node)
|
103
|
+
return if target_ruby_version < 2.3
|
104
|
+
lambda do |corrector|
|
105
|
+
if heredoc_indent_type(node) == '~'
|
106
|
+
corrector.replace(node.loc.heredoc_body, indented_body(node))
|
107
|
+
else
|
108
|
+
heredoc_begenning = node.loc.expression.source
|
109
|
+
corrected = heredoc_begenning.sub(/<<-?/, '<<~')
|
110
|
+
corrector.replace(node.loc.expression, corrected)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def correct_by_library(node)
|
116
|
+
lambda do |corrector|
|
117
|
+
corrector.replace(node.loc.heredoc_body, indented_body(node))
|
118
|
+
corrected = ".#{StripMethods[style]}"
|
119
|
+
corrector.insert_after(node.loc.expression, corrected)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
def check_style!
|
124
|
+
case style
|
125
|
+
when nil
|
126
|
+
raise Warning, "Auto-correction does not work for #{cop_name}. " \
|
127
|
+
'Please configure EnforcedStyle.'
|
128
|
+
when :squiggly
|
129
|
+
if target_ruby_version < 2.3
|
130
|
+
raise Warning, '`squiggly` style is selectable only on Ruby ' \
|
131
|
+
"2.3 or higher for #{cop_name}."
|
132
|
+
end
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def heredoc?(node)
|
137
|
+
node.loc.is_a?(Parser::Source::Map::Heredoc)
|
138
|
+
end
|
139
|
+
|
140
|
+
def indented_body(node)
|
141
|
+
body = node.loc.heredoc_body.source
|
142
|
+
body_indent_level = body_indent_level(node)
|
143
|
+
correct_indent_level = base_indent_level(node) + indentation_width
|
144
|
+
body.gsub(/^\s{#{body_indent_level}}/, ' ' * correct_indent_level)
|
145
|
+
end
|
146
|
+
|
147
|
+
def body_indent_level(node)
|
148
|
+
body = node.loc.heredoc_body.source
|
149
|
+
indent_level(body)
|
150
|
+
end
|
151
|
+
|
152
|
+
def base_indent_level(node)
|
153
|
+
base_line_num = node.loc.expression.line
|
154
|
+
base_line = processed_source.lines[base_line_num - 1]
|
155
|
+
indent_level(base_line)
|
156
|
+
end
|
157
|
+
|
158
|
+
def indent_level(str)
|
159
|
+
str.scan(/^\s*/).reject { |line| line == "\n" }.min_by(&:size).size
|
160
|
+
end
|
161
|
+
|
162
|
+
# Returns '~', '-' or nil
|
163
|
+
def heredoc_indent_type(node)
|
164
|
+
node.source[/^<<([~-])/, 1]
|
165
|
+
end
|
166
|
+
|
167
|
+
def indentation_width
|
168
|
+
@config.for_cop('IndentationWidth')['Width'] || 2
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|
@@ -3,38 +3,70 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
|
-
# This cops checks for indentation that doesn't use
|
6
|
+
# This cops checks for indentation that doesn't use the specified number
|
7
|
+
# of spaces.
|
7
8
|
#
|
8
|
-
#
|
9
|
+
# See also the IndentationConsistency cop which is the companion to this
|
10
|
+
# one.
|
9
11
|
#
|
12
|
+
# @example
|
13
|
+
# # bad, Width: 2
|
10
14
|
# class A
|
11
15
|
# def test
|
12
16
|
# puts 'hello'
|
13
17
|
# end
|
14
18
|
# end
|
15
|
-
|
19
|
+
#
|
20
|
+
# # bad, Width: 2,
|
21
|
+
# IgnoredPatterns:
|
22
|
+
# - '^\s*module'
|
23
|
+
# module A
|
24
|
+
# class B
|
25
|
+
# def test
|
26
|
+
# puts 'hello'
|
27
|
+
# end
|
28
|
+
# end
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# # good, Width: 2
|
32
|
+
# class A
|
33
|
+
# def test
|
34
|
+
# puts 'hello'
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
#
|
38
|
+
# # good, Width: 2,
|
39
|
+
# IgnoredPatterns:
|
40
|
+
# - '^\s*module'
|
41
|
+
# module A
|
42
|
+
# class B
|
43
|
+
# def test
|
44
|
+
# puts 'hello'
|
45
|
+
# end
|
46
|
+
# end
|
47
|
+
# end
|
48
|
+
class IndentationWidth < Cop # rubocop:disable Metrics/ClassLength
|
16
49
|
include EndKeywordAlignment
|
17
50
|
include AutocorrectAlignment
|
18
51
|
include OnMethodDef
|
19
52
|
include CheckAssignment
|
20
53
|
include AccessModifierNode
|
54
|
+
include IgnoredPattern
|
21
55
|
|
22
56
|
SPECIAL_MODIFIERS = %w(private protected).freeze
|
23
57
|
|
24
58
|
def on_rescue(node)
|
25
|
-
_begin_node, *
|
26
|
-
rescue_nodes.each do |rescue_node|
|
27
|
-
_, _, body = *rescue_node
|
28
|
-
check_indentation(rescue_node.loc.keyword, body)
|
29
|
-
end
|
59
|
+
_begin_node, *_rescue_nodes, else_node = *node
|
30
60
|
check_indentation(node.loc.else, else_node)
|
31
61
|
end
|
32
62
|
|
33
63
|
def on_ensure(node)
|
34
|
-
|
35
|
-
check_indentation(node.loc.keyword, ensure_body)
|
64
|
+
check_indentation(node.loc.keyword, node.body)
|
36
65
|
end
|
37
66
|
|
67
|
+
alias on_resbody on_ensure
|
68
|
+
alias on_for on_ensure
|
69
|
+
|
38
70
|
def on_kwbegin(node)
|
39
71
|
# Check indentation against end keyword but only if it's first on its
|
40
72
|
# line.
|
@@ -69,26 +101,21 @@ module RuboCop
|
|
69
101
|
def on_send(node)
|
70
102
|
super
|
71
103
|
return unless modifier_and_def_on_same_line?(node)
|
72
|
-
_, _, *args = *node
|
73
104
|
|
74
|
-
*_, body = *
|
105
|
+
*_, body = *node.first_argument
|
75
106
|
|
76
107
|
def_end_config = config.for_cop('Lint/DefEndAlignment')
|
77
108
|
style = def_end_config['EnforcedStyleAlignWith'] || 'start_of_line'
|
78
|
-
base = style == 'def' ?
|
109
|
+
base = style == 'def' ? node.first_argument : node
|
79
110
|
|
80
111
|
check_indentation(base.source_range, body)
|
81
|
-
ignore_node(
|
112
|
+
ignore_node(node.first_argument)
|
82
113
|
end
|
83
114
|
|
84
115
|
def on_method_def(node, _method_name, _args, body)
|
85
116
|
check_indentation(node.loc.keyword, body) unless ignored_node?(node)
|
86
117
|
end
|
87
118
|
|
88
|
-
def on_for(node)
|
89
|
-
check_indentation(node.loc.keyword, node.body)
|
90
|
-
end
|
91
|
-
|
92
119
|
def on_while(node, base = node)
|
93
120
|
return if ignored_node?(node)
|
94
121
|
|
@@ -230,24 +257,29 @@ module RuboCop
|
|
230
257
|
end
|
231
258
|
|
232
259
|
def indentation_to_check?(base_loc, body_node)
|
233
|
-
return false
|
260
|
+
return false if skip_check?(base_loc, body_node)
|
261
|
+
|
262
|
+
if %i(rescue ensure).include?(body_node.type)
|
263
|
+
block_body, = *body_node
|
264
|
+
return unless block_body
|
265
|
+
end
|
266
|
+
|
267
|
+
true
|
268
|
+
end
|
269
|
+
|
270
|
+
def skip_check?(base_loc, body_node)
|
271
|
+
return true if ignored_line?(base_loc)
|
272
|
+
return true unless body_node
|
234
273
|
|
235
274
|
# Don't check if expression is on same line as "then" keyword, etc.
|
236
|
-
return
|
275
|
+
return true if body_node.loc.line == base_loc.line
|
237
276
|
|
238
|
-
return
|
277
|
+
return true if starts_with_access_modifier?(body_node)
|
239
278
|
|
240
279
|
# Don't check indentation if the line doesn't start with the body.
|
241
280
|
# For example, lines like "else do_something".
|
242
281
|
first_char_pos_on_line = body_node.source_range.source_line =~ /\S/
|
243
|
-
return
|
244
|
-
|
245
|
-
if [:rescue, :ensure].include?(body_node.type)
|
246
|
-
block_body, = *body_node
|
247
|
-
return unless block_body
|
248
|
-
end
|
249
|
-
|
250
|
-
true
|
282
|
+
return true unless body_node.loc.column == first_char_pos_on_line
|
251
283
|
end
|
252
284
|
|
253
285
|
def offending_range(body_node, indentation)
|
@@ -0,0 +1,130 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop check for usages of not (`not` or `!`) called on a method
|
7
|
+
# when an inverse of that method can be used instead.
|
8
|
+
# Methods that can be inverted by a not (`not` or `!`) should be defined
|
9
|
+
# in `InverseMethods`
|
10
|
+
# Methods that are inverted by inverting the return
|
11
|
+
# of the block that is passed to the method should be defined in
|
12
|
+
# `InverseBlocks`
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# # bad
|
16
|
+
# !foo.none?
|
17
|
+
# !foo.any? { |f| f.even? }
|
18
|
+
# !foo.blank?
|
19
|
+
# !(foo == bar)
|
20
|
+
# foo.select { |f| !f.even? }
|
21
|
+
# foo.reject { |f| f != 7 }
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# foo.none?
|
25
|
+
# foo.blank?
|
26
|
+
# foo.any? { |f| f.even? }
|
27
|
+
# foo != bar
|
28
|
+
# foo == bar
|
29
|
+
class InverseMethods < Cop
|
30
|
+
MSG = 'Use `%{inverse}` instead of inverting `%{method}`.'.freeze
|
31
|
+
EQUALITY_METHODS = %i(== != =~ !~ <= >= < >).freeze
|
32
|
+
|
33
|
+
def_node_matcher :inverse_candidate?, <<-PATTERN
|
34
|
+
{
|
35
|
+
(send $(send (...) $_ ...) :!)
|
36
|
+
(send (block $(send (...) $_) ...) :!)
|
37
|
+
(send (begin $(send (...) $_ ...)) :!)
|
38
|
+
}
|
39
|
+
PATTERN
|
40
|
+
|
41
|
+
def_node_matcher :inverse_block?, <<-PATTERN
|
42
|
+
(block $(send (...) $_) ... { $(send ... :!)
|
43
|
+
$(send (...) {:!= :!~} ...)
|
44
|
+
(begin ... $(send ... :!))
|
45
|
+
(begin ... $(send (...) {:!= :!~} ...))
|
46
|
+
})
|
47
|
+
PATTERN
|
48
|
+
|
49
|
+
def on_send(node)
|
50
|
+
inverse_candidate?(node) do |_method_call, method|
|
51
|
+
return unless inverse_methods.key?(method)
|
52
|
+
|
53
|
+
add_offense(node,
|
54
|
+
:expression,
|
55
|
+
format(MSG, method: method,
|
56
|
+
inverse: inverse_methods[method]))
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def on_block(node)
|
61
|
+
inverse_block?(node) do |_method_call, method, _block|
|
62
|
+
return unless inverse_blocks.key?(method)
|
63
|
+
|
64
|
+
add_offense(node,
|
65
|
+
:expression,
|
66
|
+
format(MSG, method: method,
|
67
|
+
inverse: inverse_blocks[method]))
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def autocorrect(node)
|
72
|
+
method_call, method = inverse_candidate?(node)
|
73
|
+
|
74
|
+
if method_call && method
|
75
|
+
lambda do |corrector|
|
76
|
+
corrector.remove(not_to_receiver(node, method_call))
|
77
|
+
corrector.replace(method_call.loc.selector,
|
78
|
+
inverse_methods[method].to_s)
|
79
|
+
|
80
|
+
if EQUALITY_METHODS.include?(method)
|
81
|
+
corrector.remove(end_parentheses(node, method_call))
|
82
|
+
end
|
83
|
+
end
|
84
|
+
else
|
85
|
+
correct_inverse_block(node)
|
86
|
+
end
|
87
|
+
end
|
88
|
+
|
89
|
+
def correct_inverse_block(node)
|
90
|
+
method_call, method, block = inverse_block?(node)
|
91
|
+
selector = block.loc.selector.source
|
92
|
+
|
93
|
+
lambda do |corrector|
|
94
|
+
corrector.replace(method_call.loc.selector,
|
95
|
+
inverse_blocks[method].to_s)
|
96
|
+
|
97
|
+
if ['!=', '!~'].include?(selector)
|
98
|
+
selector[0] = '='
|
99
|
+
corrector.replace(block.loc.selector, selector)
|
100
|
+
else
|
101
|
+
corrector.remove(block.loc.selector)
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
def inverse_methods
|
107
|
+
@inverse_methods ||= cop_config['InverseMethods']
|
108
|
+
.merge(cop_config['InverseMethods'].invert)
|
109
|
+
end
|
110
|
+
|
111
|
+
def inverse_blocks
|
112
|
+
@inverse_blocks ||= cop_config['InverseBlocks']
|
113
|
+
.merge(cop_config['InverseBlocks'].invert)
|
114
|
+
end
|
115
|
+
|
116
|
+
def not_to_receiver(node, method_call)
|
117
|
+
Parser::Source::Range.new(node.loc.expression.source_buffer,
|
118
|
+
node.loc.selector.begin_pos,
|
119
|
+
method_call.loc.expression.begin_pos)
|
120
|
+
end
|
121
|
+
|
122
|
+
def end_parentheses(node, method_call)
|
123
|
+
Parser::Source::Range.new(node.loc.expression.source_buffer,
|
124
|
+
method_call.loc.expression.end_pos,
|
125
|
+
node.loc.expression.end_pos)
|
126
|
+
end
|
127
|
+
end
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|