rubocop 1.8.0 → 1.11.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.
- checksums.yaml +4 -4
- data/README.md +14 -13
- data/assets/output.html.erb +1 -1
- data/config/default.yml +89 -22
- data/config/obsoletion.yml +4 -0
- data/lib/rubocop.rb +9 -0
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +5 -4
- data/lib/rubocop/cli/command/execute_runner.rb +1 -1
- data/lib/rubocop/cli/command/suggest_extensions.rb +1 -1
- data/lib/rubocop/config.rb +5 -2
- data/lib/rubocop/config_loader.rb +7 -14
- data/lib/rubocop/config_store.rb +12 -1
- data/lib/rubocop/cop/base.rb +2 -1
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -1
- data/lib/rubocop/cop/bundler/gem_comment.rb +1 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -0
- data/lib/rubocop/cop/bundler/ordered_gems.rb +1 -0
- data/lib/rubocop/cop/exclude_limit.rb +26 -0
- data/lib/rubocop/cop/gemspec/date_assignment.rb +57 -0
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +2 -0
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -0
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +2 -0
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +2 -0
- data/lib/rubocop/cop/generator.rb +3 -5
- data/lib/rubocop/cop/internal_affairs.rb +6 -1
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +68 -0
- data/lib/rubocop/cop/internal_affairs/example_description.rb +90 -0
- data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +2 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +151 -0
- data/lib/rubocop/cop/internal_affairs/node_type_predicate.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/offense_location_keyword.rb +2 -0
- data/lib/rubocop/cop/internal_affairs/redundant_described_class_as_subject.rb +62 -0
- data/lib/rubocop/cop/internal_affairs/redundant_let_rubocop_config_new.rb +65 -0
- data/lib/rubocop/cop/internal_affairs/redundant_location_argument.rb +1 -0
- data/lib/rubocop/cop/internal_affairs/redundant_message_argument.rb +3 -0
- data/lib/rubocop/cop/internal_affairs/style_detected_api_use.rb +4 -0
- data/lib/rubocop/cop/internal_affairs/useless_message_assertion.rb +2 -0
- data/lib/rubocop/cop/layout/block_alignment.rb +1 -0
- data/lib/rubocop/cop/layout/class_structure.rb +8 -2
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +37 -17
- data/lib/rubocop/cop/layout/extra_spacing.rb +2 -2
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +22 -3
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -0
- data/lib/rubocop/cop/layout/line_length.rb +2 -1
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +26 -0
- data/lib/rubocop/cop/layout/space_before_block_braces.rb +1 -1
- data/lib/rubocop/cop/layout/space_before_brackets.rb +9 -4
- data/lib/rubocop/cop/layout/space_inside_block_braces.rb +1 -1
- data/lib/rubocop/cop/lint/big_decimal_new.rb +1 -0
- data/lib/rubocop/cop/lint/boolean_symbol.rb +1 -0
- data/lib/rubocop/cop/lint/constant_definition_in_block.rb +2 -0
- data/lib/rubocop/cop/lint/constant_resolution.rb +1 -0
- data/lib/rubocop/cop/lint/debugger.rb +60 -14
- data/lib/rubocop/cop/lint/deprecated_constants.rb +5 -0
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +14 -4
- data/lib/rubocop/cop/lint/duplicate_branch.rb +1 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +3 -0
- data/lib/rubocop/cop/lint/duplicate_require.rb +3 -2
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -0
- data/lib/rubocop/cop/lint/else_layout.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -0
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +1 -0
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +1 -0
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -0
- data/lib/rubocop/cop/lint/inherit_exception.rb +1 -0
- data/lib/rubocop/cop/lint/multiple_comparison.rb +5 -4
- data/lib/rubocop/cop/lint/nested_method_definition.rb +3 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +1 -0
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +7 -0
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +3 -0
- data/lib/rubocop/cop/lint/number_conversion.rb +43 -6
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +47 -0
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +39 -0
- data/lib/rubocop/cop/lint/raise_exception.rb +2 -0
- data/lib/rubocop/cop/lint/rand_one.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_dir_glob_sort.rb +5 -3
- data/lib/rubocop/cop/lint/redundant_require_statement.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +7 -3
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_with_index.rb +1 -0
- data/lib/rubocop/cop/lint/redundant_with_object.rb +1 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +1 -0
- data/lib/rubocop/cop/lint/safe_navigation_with_empty.rb +1 -0
- data/lib/rubocop/cop/lint/send_with_mixin_argument.rb +1 -0
- data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -0
- data/lib/rubocop/cop/lint/struct_new_override.rb +1 -0
- data/lib/rubocop/cop/lint/symbol_conversion.rb +103 -0
- data/lib/rubocop/cop/lint/to_enum_arguments.rb +3 -0
- data/lib/rubocop/cop/lint/triple_quotes.rb +71 -0
- data/lib/rubocop/cop/lint/unified_integer.rb +1 -0
- data/lib/rubocop/cop/lint/unmodified_reduce_accumulator.rb +5 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +1 -0
- data/lib/rubocop/cop/lint/unreachable_loop.rb +1 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +1 -0
- data/lib/rubocop/cop/lint/uri_escape_unescape.rb +1 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +4 -0
- data/lib/rubocop/cop/lint/useless_setter_call.rb +1 -0
- data/lib/rubocop/cop/lint/useless_times.rb +3 -0
- data/lib/rubocop/cop/message_annotator.rb +4 -1
- data/lib/rubocop/cop/metrics/block_nesting.rb +2 -2
- data/lib/rubocop/cop/metrics/module_length.rb +1 -0
- data/lib/rubocop/cop/metrics/parameter_lists.rb +6 -2
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +6 -4
- data/lib/rubocop/cop/metrics/utils/repeated_attribute_discount.rb +2 -0
- data/lib/rubocop/cop/mixin/check_line_breakable.rb +5 -0
- data/lib/rubocop/cop/mixin/code_length.rb +3 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +0 -1
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -0
- data/lib/rubocop/cop/mixin/def_node.rb +1 -0
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +3 -0
- data/lib/rubocop/cop/mixin/empty_parameter.rb +1 -0
- data/lib/rubocop/cop/mixin/enforce_superclass.rb +2 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +1 -0
- data/lib/rubocop/cop/mixin/method_complexity.rb +4 -1
- data/lib/rubocop/cop/mixin/negative_conditional.rb +3 -0
- data/lib/rubocop/cop/mixin/preferred_delimiters.rb +3 -3
- data/lib/rubocop/cop/mixin/rational_literal.rb +1 -0
- data/lib/rubocop/cop/mixin/safe_assignment.rb +5 -0
- data/lib/rubocop/cop/mixin/uncommunicative_name.rb +5 -1
- data/lib/rubocop/cop/mixin/visibility_help.rb +1 -0
- data/lib/rubocop/cop/naming/binary_operator_parameter_name.rb +1 -0
- data/lib/rubocop/cop/naming/constant_name.rb +2 -0
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +2 -0
- data/lib/rubocop/cop/naming/method_name.rb +3 -0
- data/lib/rubocop/cop/naming/predicate_name.rb +1 -0
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +38 -5
- data/lib/rubocop/cop/naming/variable_number.rb +1 -1
- data/lib/rubocop/cop/registry.rb +1 -1
- data/lib/rubocop/cop/security/eval.rb +1 -0
- data/lib/rubocop/cop/security/json_load.rb +1 -0
- data/lib/rubocop/cop/security/marshal_load.rb +1 -0
- data/lib/rubocop/cop/security/open.rb +1 -0
- data/lib/rubocop/cop/security/yaml_load.rb +1 -0
- data/lib/rubocop/cop/severity.rb +3 -3
- data/lib/rubocop/cop/style/access_modifier_declarations.rb +1 -0
- data/lib/rubocop/cop/style/alias.rb +1 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +3 -0
- data/lib/rubocop/cop/style/array_coercion.rb +2 -0
- data/lib/rubocop/cop/style/array_join.rb +1 -0
- data/lib/rubocop/cop/style/ascii_comments.rb +1 -1
- data/lib/rubocop/cop/style/attr.rb +1 -0
- data/lib/rubocop/cop/style/case_equality.rb +2 -1
- data/lib/rubocop/cop/style/class_equality_comparison.rb +1 -0
- data/lib/rubocop/cop/style/collection_compact.rb +2 -0
- data/lib/rubocop/cop/style/colon_method_call.rb +1 -0
- data/lib/rubocop/cop/style/command_literal.rb +1 -1
- data/lib/rubocop/cop/style/conditional_assignment.rb +2 -0
- data/lib/rubocop/cop/style/constant_visibility.rb +28 -0
- data/lib/rubocop/cop/style/date_time.rb +3 -0
- data/lib/rubocop/cop/style/dir.rb +1 -0
- data/lib/rubocop/cop/style/disable_cops_within_source_code_directive.rb +49 -9
- data/lib/rubocop/cop/style/documentation.rb +5 -0
- data/lib/rubocop/cop/style/documentation_method.rb +1 -0
- data/lib/rubocop/cop/style/double_negation.rb +3 -2
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +1 -0
- data/lib/rubocop/cop/style/each_with_object.rb +1 -0
- data/lib/rubocop/cop/style/empty_literal.rb +9 -0
- data/lib/rubocop/cop/style/endless_method.rb +1 -0
- data/lib/rubocop/cop/style/eval_with_location.rb +140 -49
- data/lib/rubocop/cop/style/even_odd.rb +1 -0
- data/lib/rubocop/cop/style/expand_path_arguments.rb +3 -0
- data/lib/rubocop/cop/style/explicit_block_argument.rb +12 -1
- data/lib/rubocop/cop/style/exponential_notation.rb +6 -7
- data/lib/rubocop/cop/style/float_division.rb +7 -0
- data/lib/rubocop/cop/style/format_string.rb +2 -0
- data/lib/rubocop/cop/style/format_string_token.rb +19 -2
- data/lib/rubocop/cop/style/global_std_stream.rb +1 -0
- data/lib/rubocop/cop/style/hash_conversion.rb +105 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +1 -0
- data/lib/rubocop/cop/style/hash_except.rb +1 -0
- data/lib/rubocop/cop/style/hash_like_case.rb +1 -0
- data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -0
- data/lib/rubocop/cop/style/hash_transform_values.rb +4 -0
- data/lib/rubocop/cop/style/if_inside_else.rb +14 -7
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +122 -0
- data/lib/rubocop/cop/style/implicit_runtime_error.rb +1 -0
- data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
- data/lib/rubocop/cop/style/min_max.rb +1 -0
- data/lib/rubocop/cop/style/mixin_usage.rb +2 -0
- data/lib/rubocop/cop/style/module_function.rb +5 -0
- data/lib/rubocop/cop/style/multiple_comparison.rb +21 -2
- data/lib/rubocop/cop/style/mutable_constant.rb +3 -0
- data/lib/rubocop/cop/style/negated_if_else_condition.rb +1 -0
- data/lib/rubocop/cop/style/nil_comparison.rb +6 -0
- data/lib/rubocop/cop/style/nil_lambda.rb +1 -0
- data/lib/rubocop/cop/style/non_nil_check.rb +30 -13
- data/lib/rubocop/cop/style/numeric_literals.rb +6 -9
- data/lib/rubocop/cop/style/numeric_predicate.rb +4 -1
- data/lib/rubocop/cop/style/option_hash.rb +1 -0
- data/lib/rubocop/cop/style/or_assignment.rb +2 -0
- data/lib/rubocop/cop/style/parallel_assignment.rb +6 -0
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -0
- data/lib/rubocop/cop/style/proc.rb +1 -0
- data/lib/rubocop/cop/style/random_with_offset.rb +5 -0
- data/lib/rubocop/cop/style/redundant_assignment.rb +1 -0
- data/lib/rubocop/cop/style/redundant_begin.rb +7 -1
- data/lib/rubocop/cop/style/redundant_conditional.rb +2 -0
- data/lib/rubocop/cop/style/redundant_exception.rb +2 -0
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +2 -0
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +1 -0
- data/lib/rubocop/cop/style/redundant_freeze.rb +1 -0
- data/lib/rubocop/cop/style/redundant_parentheses.rb +13 -0
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +2 -0
- data/lib/rubocop/cop/style/redundant_sort.rb +1 -0
- data/lib/rubocop/cop/style/redundant_sort_by.rb +1 -0
- data/lib/rubocop/cop/style/regexp_literal.rb +1 -1
- data/lib/rubocop/cop/style/rescue_standard_error.rb +2 -0
- data/lib/rubocop/cop/style/return_nil.rb +6 -0
- data/lib/rubocop/cop/style/safe_navigation.rb +2 -0
- data/lib/rubocop/cop/style/sample.rb +1 -0
- data/lib/rubocop/cop/style/signal_exception.rb +3 -0
- data/lib/rubocop/cop/style/single_argument_dig.rb +1 -0
- data/lib/rubocop/cop/style/single_line_methods.rb +5 -2
- data/lib/rubocop/cop/style/slicing_with_range.rb +1 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +28 -4
- data/lib/rubocop/cop/style/special_global_vars.rb +3 -3
- data/lib/rubocop/cop/style/stderr_puts.rb +1 -0
- data/lib/rubocop/cop/style/string_concatenation.rb +2 -1
- data/lib/rubocop/cop/style/string_hash_keys.rb +2 -0
- data/lib/rubocop/cop/style/strip.rb +1 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +1 -0
- data/lib/rubocop/cop/style/symbol_proc.rb +25 -1
- data/lib/rubocop/cop/style/ternary_parentheses.rb +2 -1
- data/lib/rubocop/cop/style/trailing_body_on_method_definition.rb +1 -0
- data/lib/rubocop/cop/style/trailing_method_end_statement.rb +1 -1
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -0
- data/lib/rubocop/cop/style/unless_logical_operators.rb +99 -0
- data/lib/rubocop/cop/style/unpack_first.rb +1 -0
- data/lib/rubocop/cop/style/while_until_modifier.rb +2 -4
- data/lib/rubocop/cop/style/yoda_condition.rb +1 -0
- data/lib/rubocop/cop/style/zero_length_predicate.rb +5 -0
- data/lib/rubocop/formatter/git_hub_actions_formatter.rb +1 -0
- data/lib/rubocop/formatter/offense_count_formatter.rb +1 -1
- data/lib/rubocop/formatter/simple_text_formatter.rb +2 -1
- data/lib/rubocop/formatter/worst_offenders_formatter.rb +1 -1
- data/lib/rubocop/magic_comment.rb +30 -1
- data/lib/rubocop/name_similarity.rb +1 -1
- data/lib/rubocop/options.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +5 -2
- data/lib/rubocop/runner.rb +1 -0
- data/lib/rubocop/target_ruby.rb +21 -13
- data/lib/rubocop/version.rb +2 -2
- metadata +21 -7
@@ -5,6 +5,9 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# Use symbols as procs when possible.
|
7
7
|
#
|
8
|
+
# If you prefer a style that allows block for method with arguments,
|
9
|
+
# please set `true` to `AllowMethodsWithArguments`.
|
10
|
+
#
|
8
11
|
# @example
|
9
12
|
# # bad
|
10
13
|
# something.map { |s| s.upcase }
|
@@ -12,6 +15,17 @@ module RuboCop
|
|
12
15
|
#
|
13
16
|
# # good
|
14
17
|
# something.map(&:upcase)
|
18
|
+
#
|
19
|
+
# @example AllowMethodsWithArguments: false (default)
|
20
|
+
# # bad
|
21
|
+
# something.do_something(foo) { |o| o.bar }
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# something.do_something(foo, &:bar)
|
25
|
+
#
|
26
|
+
# @example AllowMethodsWithArguments: true
|
27
|
+
# # good
|
28
|
+
# something.do_something(foo) { |o| o.bar }
|
15
29
|
class SymbolProc < Base
|
16
30
|
include RangeHelp
|
17
31
|
include IgnoredMethods
|
@@ -21,8 +35,13 @@ module RuboCop
|
|
21
35
|
'instead of a block.'
|
22
36
|
SUPER_TYPES = %i[super zsuper].freeze
|
23
37
|
|
38
|
+
# @!method proc_node?(node)
|
24
39
|
def_node_matcher :proc_node?, '(send (const {nil? cbase} :Proc) :new)'
|
40
|
+
|
41
|
+
# @!method symbol_proc_receiver?(node)
|
25
42
|
def_node_matcher :symbol_proc_receiver?, '{(send ...) (super ...) zsuper}'
|
43
|
+
|
44
|
+
# @!method symbol_proc?(node)
|
26
45
|
def_node_matcher :symbol_proc?, <<~PATTERN
|
27
46
|
{
|
28
47
|
(block $#symbol_proc_receiver? $(args (arg _var)) (send (lvar _var) $_))
|
@@ -37,11 +56,12 @@ module RuboCop
|
|
37
56
|
def on_block(node)
|
38
57
|
symbol_proc?(node) do |dispatch_node, arguments_node, method_name|
|
39
58
|
# TODO: Rails-specific handling that we should probably make
|
40
|
-
# configurable - https://github.com/rubocop
|
59
|
+
# configurable - https://github.com/rubocop/rubocop/issues/1485
|
41
60
|
# we should ignore lambdas & procs
|
42
61
|
return if proc_node?(dispatch_node)
|
43
62
|
return if %i[lambda proc].include?(dispatch_node.method_name)
|
44
63
|
return if ignored_method?(dispatch_node.method_name)
|
64
|
+
return if allow_if_method_has_argument?(node)
|
45
65
|
return if node.block_type? && destructuring_block_argument?(arguments_node)
|
46
66
|
|
47
67
|
register_offense(node, method_name, dispatch_node.method_name)
|
@@ -103,6 +123,10 @@ module RuboCop
|
|
103
123
|
node.loc.begin.begin_pos
|
104
124
|
end
|
105
125
|
end
|
126
|
+
|
127
|
+
def allow_if_method_has_argument?(node)
|
128
|
+
!!cop_config.fetch('AllowMethodsWithArguments', false) && !node.arguments.count.zero?
|
129
|
+
end
|
106
130
|
end
|
107
131
|
end
|
108
132
|
end
|
@@ -120,7 +120,7 @@ module RuboCop
|
|
120
120
|
if condition.begin_type?
|
121
121
|
condition.to_a.any? { |x| complex_condition?(x) }
|
122
122
|
else
|
123
|
-
non_complex_expression?(condition)
|
123
|
+
!non_complex_expression?(condition)
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
@@ -191,6 +191,7 @@ module RuboCop
|
|
191
191
|
(child.send_type? && child.prefix_not?)
|
192
192
|
end
|
193
193
|
|
194
|
+
# @!method method_name(node)
|
194
195
|
def_node_matcher :method_name, <<~PATTERN
|
195
196
|
{($:defined? _ ...)
|
196
197
|
(send {_ nil?} $_ _ ...)}
|
@@ -120,6 +120,7 @@ module RuboCop
|
|
120
120
|
!allowed_method_name?(node) && !allowed_writer?(node.method_name)
|
121
121
|
end
|
122
122
|
|
123
|
+
# @!method looks_like_trivial_writer?(node)
|
123
124
|
def_node_matcher :looks_like_trivial_writer?, <<~PATTERN
|
124
125
|
{(def _ (args (arg ...)) (ivasgn _ (lvar _)))
|
125
126
|
(defs _ _ (args (arg ...)) (ivasgn _ (lvar _)))}
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for the use of logical operators in an `unless` condition.
|
7
|
+
# It discourages such code, as the condition becomes more difficult
|
8
|
+
# to read and understand.
|
9
|
+
#
|
10
|
+
# This cop supports two styles:
|
11
|
+
# - `forbid_mixed_logical_operators` (default)
|
12
|
+
# - `forbid_logical_operators`
|
13
|
+
#
|
14
|
+
# `forbid_mixed_logical_operators` style forbids the use of more than one type
|
15
|
+
# of logical operators. This makes the `unless` condition easier to read
|
16
|
+
# because either all conditions need to be met or any condition need to be met
|
17
|
+
# in order for the expression to be truthy or falsey.
|
18
|
+
#
|
19
|
+
# `forbid_logical_operators` style forbids any use of logical operator.
|
20
|
+
# This makes it even more easy to read the `unless` condition as
|
21
|
+
# there is only one condition in the expression.
|
22
|
+
#
|
23
|
+
# @example EnforcedStyle: forbid_mixed_logical_operators (default)
|
24
|
+
# # bad
|
25
|
+
# return unless a || b && c
|
26
|
+
# return unless a && b || c
|
27
|
+
# return unless a && b and c
|
28
|
+
# return unless a || b or c
|
29
|
+
# return unless a && b or c
|
30
|
+
# return unless a || b and c
|
31
|
+
#
|
32
|
+
# # good
|
33
|
+
# return unless a && b && c
|
34
|
+
# return unless a || b || c
|
35
|
+
# return unless a and b and c
|
36
|
+
# return unless a or b or c
|
37
|
+
# return unless a?
|
38
|
+
#
|
39
|
+
# @example EnforcedStyle: forbid_logical_operators
|
40
|
+
# # bad
|
41
|
+
# return unless a || b
|
42
|
+
# return unless a && b
|
43
|
+
# return unless a or b
|
44
|
+
# return unless a and b
|
45
|
+
#
|
46
|
+
# # good
|
47
|
+
# return unless a
|
48
|
+
# return unless a?
|
49
|
+
class UnlessLogicalOperators < Base
|
50
|
+
include ConfigurableEnforcedStyle
|
51
|
+
|
52
|
+
FORBID_MIXED_LOGICAL_OPERATORS = 'Do not use mixed logical operators in an `unless`.'
|
53
|
+
FORBID_LOGICAL_OPERATORS = 'Do not use any logical operator in an `unless`.'
|
54
|
+
|
55
|
+
# @!method or_with_and?(node)
|
56
|
+
def_node_matcher :or_with_and?, <<~PATTERN
|
57
|
+
(if (or <`and ...> ) ...)
|
58
|
+
PATTERN
|
59
|
+
|
60
|
+
# @!method and_with_or?(node)
|
61
|
+
def_node_matcher :and_with_or?, <<~PATTERN
|
62
|
+
(if (and <`or ...> ) ...)
|
63
|
+
PATTERN
|
64
|
+
|
65
|
+
# @!method logical_operator?(node)
|
66
|
+
def_node_matcher :logical_operator?, <<~PATTERN
|
67
|
+
(if ({and or} ... ) ...)
|
68
|
+
PATTERN
|
69
|
+
|
70
|
+
def on_if(node)
|
71
|
+
return unless node.unless?
|
72
|
+
|
73
|
+
if style == :forbid_mixed_logical_operators && mixed_logical_operator?(node)
|
74
|
+
add_offense(node, message: FORBID_MIXED_LOGICAL_OPERATORS)
|
75
|
+
elsif style == :forbid_logical_operators && logical_operator?(node)
|
76
|
+
add_offense(node, message: FORBID_LOGICAL_OPERATORS)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def mixed_logical_operator?(node)
|
83
|
+
or_with_and?(node) ||
|
84
|
+
and_with_or?(node) ||
|
85
|
+
mixed_precedence_and?(node) ||
|
86
|
+
mixed_precedence_or?(node)
|
87
|
+
end
|
88
|
+
|
89
|
+
def mixed_precedence_and?(node)
|
90
|
+
node.source.include?('&&') && node.source.include?('and')
|
91
|
+
end
|
92
|
+
|
93
|
+
def mixed_precedence_or?(node)
|
94
|
+
node.source.include?('||') && node.source.include?('or')
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -24,6 +24,7 @@ module RuboCop
|
|
24
24
|
'`%<receiver>s.unpack(%<format>s)%<method>s`.'
|
25
25
|
RESTRICT_ON_SEND = %i[first [] slice at].freeze
|
26
26
|
|
27
|
+
# @!method unpack_and_first_element?(node)
|
27
28
|
def_node_matcher :unpack_and_first_element?, <<~PATTERN
|
28
29
|
{
|
29
30
|
(send $(send (...) :unpack $(...)) :first)
|
@@ -41,12 +41,10 @@ module RuboCop
|
|
41
41
|
'having a single-line body.'
|
42
42
|
|
43
43
|
def on_while(node)
|
44
|
-
return unless
|
44
|
+
return unless single_line_as_modifier?(node)
|
45
45
|
|
46
46
|
add_offense(node.loc.keyword, message: format(MSG, keyword: node.keyword)) do |corrector|
|
47
|
-
|
48
|
-
|
49
|
-
corrector.replace(node, oneline)
|
47
|
+
corrector.replace(node, to_modifier_form(node))
|
50
48
|
end
|
51
49
|
end
|
52
50
|
alias on_until on_while
|
@@ -72,6 +72,7 @@ module RuboCop
|
|
72
72
|
|
73
73
|
PROGRAM_NAMES = %i[$0 $PROGRAM_NAME].freeze
|
74
74
|
|
75
|
+
# @!method file_constant_equal_program_name?(node)
|
75
76
|
def_node_matcher :file_constant_equal_program_name?, <<~PATTERN
|
76
77
|
(send #source_file_path_constant? {:== :!=} (gvar #program_name?))
|
77
78
|
PATTERN
|
@@ -71,6 +71,7 @@ module RuboCop
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
+
# @!method zero_length_predicate(node)
|
74
75
|
def_node_matcher :zero_length_predicate, <<~PATTERN
|
75
76
|
{(send (send (...) ${:length :size}) $:== (int $0))
|
76
77
|
(send (int $0) $:== (send (...) ${:length :size}))
|
@@ -78,6 +79,7 @@ module RuboCop
|
|
78
79
|
(send (int $1) $:> (send (...) ${:length :size}))}
|
79
80
|
PATTERN
|
80
81
|
|
82
|
+
# @!method nonzero_length_predicate(node)
|
81
83
|
def_node_matcher :nonzero_length_predicate, <<~PATTERN
|
82
84
|
{(send (send (...) ${:length :size}) ${:> :!=} (int $0))
|
83
85
|
(send (int $0) ${:< :!=} (send (...) ${:length :size}))}
|
@@ -90,6 +92,7 @@ module RuboCop
|
|
90
92
|
"!#{other_receiver(node).source}.empty?"
|
91
93
|
end
|
92
94
|
|
95
|
+
# @!method zero_length_receiver(node)
|
93
96
|
def_node_matcher :zero_length_receiver, <<~PATTERN
|
94
97
|
{(send (send $_ _) :== (int 0))
|
95
98
|
(send (int 0) :== (send $_ _))
|
@@ -97,6 +100,7 @@ module RuboCop
|
|
97
100
|
(send (int 1) :> (send $_ _))}
|
98
101
|
PATTERN
|
99
102
|
|
103
|
+
# @!method other_receiver(node)
|
100
104
|
def_node_matcher :other_receiver, <<~PATTERN
|
101
105
|
{(send (send $_ _) _ _)
|
102
106
|
(send _ _ (send $_ _))}
|
@@ -105,6 +109,7 @@ module RuboCop
|
|
105
109
|
# Some collection like objects in the Ruby standard library
|
106
110
|
# implement `#size`, but not `#empty`. We ignore those to
|
107
111
|
# reduce false positives.
|
112
|
+
# @!method non_polymorphic_collection?(node)
|
108
113
|
def_node_matcher :non_polymorphic_collection?, <<~PATTERN
|
109
114
|
{(send (send (send (const {nil? cbase} :File) :stat _) ...) ...)
|
110
115
|
(send (send (send (const {nil? cbase} {:Tempfile :StringIO}) {:new :open} ...) ...) ...)}
|
@@ -23,6 +23,7 @@ module RuboCop
|
|
23
23
|
|
24
24
|
def minimum_severity_to_fail
|
25
25
|
@minimum_severity_to_fail ||= begin
|
26
|
+
# Unless given explicitly as `fail_level`, `:info` severity offenses do not fail
|
26
27
|
name = options.fetch(:fail_level, :refactor)
|
27
28
|
RuboCop::Cop::Severity.new(name)
|
28
29
|
end
|
@@ -13,6 +13,7 @@ module RuboCop
|
|
13
13
|
include PathUtil
|
14
14
|
|
15
15
|
COLOR_FOR_SEVERITY = {
|
16
|
+
info: :gray,
|
16
17
|
refactor: :yellow,
|
17
18
|
convention: :yellow,
|
18
19
|
warning: :magenta,
|
@@ -76,7 +77,7 @@ module RuboCop
|
|
76
77
|
end
|
77
78
|
|
78
79
|
def colored_severity_code(offense)
|
79
|
-
color = COLOR_FOR_SEVERITY
|
80
|
+
color = COLOR_FOR_SEVERITY.fetch(offense.severity.name)
|
80
81
|
colorize(offense.severity.code, color)
|
81
82
|
end
|
82
83
|
|
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def any?
|
30
|
-
frozen_string_literal_specified? || encoding_specified?
|
30
|
+
frozen_string_literal_specified? || encoding_specified? || shareable_constant_value_specified?
|
31
31
|
end
|
32
32
|
|
33
33
|
# Does the magic comment enable the frozen string literal feature.
|
@@ -46,6 +46,10 @@ module RuboCop
|
|
46
46
|
[true, false].include?(frozen_string_literal)
|
47
47
|
end
|
48
48
|
|
49
|
+
def valid_shareable_constant_value?
|
50
|
+
%w[none literal experimental_everything experimental_copy].include?(shareable_constant_values)
|
51
|
+
end
|
52
|
+
|
49
53
|
# Was a magic comment for the frozen string literal found?
|
50
54
|
#
|
51
55
|
# @return [Boolean]
|
@@ -53,6 +57,13 @@ module RuboCop
|
|
53
57
|
specified?(frozen_string_literal)
|
54
58
|
end
|
55
59
|
|
60
|
+
# Was a shareable_constant_value specified?
|
61
|
+
#
|
62
|
+
# @return [Boolean]
|
63
|
+
def shareable_constant_value_specified?
|
64
|
+
specified?(shareable_constant_value)
|
65
|
+
end
|
66
|
+
|
56
67
|
# Expose the `frozen_string_literal` value coerced to a boolean if possible.
|
57
68
|
#
|
58
69
|
# @return [Boolean] if value is `true` or `false`
|
@@ -69,6 +80,13 @@ module RuboCop
|
|
69
80
|
end
|
70
81
|
end
|
71
82
|
|
83
|
+
# Expose the `shareable_constant_value` value coerced to a boolean if possible.
|
84
|
+
#
|
85
|
+
# @return [String] for shareable_constant_value config
|
86
|
+
def shareable_constant_value
|
87
|
+
extract_shareable_constant_value
|
88
|
+
end
|
89
|
+
|
72
90
|
def encoding_specified?
|
73
91
|
specified?(encoding)
|
74
92
|
end
|
@@ -146,6 +164,10 @@ module RuboCop
|
|
146
164
|
def extract_frozen_string_literal
|
147
165
|
match('frozen[_-]string[_-]literal')
|
148
166
|
end
|
167
|
+
|
168
|
+
def extract_shareable_constant_value
|
169
|
+
match('shareable[_-]constant[_-]values')
|
170
|
+
end
|
149
171
|
end
|
150
172
|
|
151
173
|
# Wrapper for Vim style magic comments.
|
@@ -176,6 +198,9 @@ module RuboCop
|
|
176
198
|
|
177
199
|
# Vim comments cannot specify frozen string literal behavior.
|
178
200
|
def frozen_string_literal; end
|
201
|
+
|
202
|
+
# Vim comments cannot specify shareable constant values behavior.
|
203
|
+
def shareable_constant_value; end
|
179
204
|
end
|
180
205
|
|
181
206
|
# Wrapper for regular magic comments not bound to an editor.
|
@@ -209,6 +234,10 @@ module RuboCop
|
|
209
234
|
def extract_frozen_string_literal
|
210
235
|
extract(/\A\s*#\s*frozen[_-]string[_-]literal:\s*(#{TOKEN})\s*\z/io)
|
211
236
|
end
|
237
|
+
|
238
|
+
def extract_shareable_constant_value
|
239
|
+
extract(/\A\s*#\s*shareable[_-]constant[_-]value:\s*(#{TOKEN})\s*\z/io)
|
240
|
+
end
|
212
241
|
end
|
213
242
|
end
|
214
243
|
end
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
16
16
|
# DidYouMean::SpellChecker is not available in all versions of Ruby, and
|
17
17
|
# even on versions where it *is* available (>= 2.3), it is not always
|
18
18
|
# required correctly. So we do a feature check first.
|
19
|
-
# See: https://github.com/rubocop
|
19
|
+
# See: https://github.com/rubocop/rubocop/issues/7979
|
20
20
|
return [] unless defined?(DidYouMean::SpellChecker)
|
21
21
|
|
22
22
|
names = names.dup
|
data/lib/rubocop/options.rb
CHANGED
@@ -470,7 +470,7 @@ module RuboCop
|
|
470
470
|
'This option applies to the previously',
|
471
471
|
'specified --format, or the default format',
|
472
472
|
'if no format is specified.'],
|
473
|
-
fail_level: ['Minimum severity (A/R/C/W/E/F) for exit',
|
473
|
+
fail_level: ['Minimum severity (A/I/R/C/W/E/F) for exit',
|
474
474
|
'with error code.'],
|
475
475
|
display_time: 'Display elapsed time in seconds.',
|
476
476
|
display_only_failed: ['Only output offense messages. Omit passing',
|
@@ -111,9 +111,12 @@ module RuboCop
|
|
111
111
|
source
|
112
112
|
end
|
113
113
|
|
114
|
-
def expect_offense(source, file = nil, severity: nil, **replacements)
|
114
|
+
def expect_offense(source, file = nil, severity: nil, chomp: false, **replacements)
|
115
115
|
expected_annotations = parse_annotations(source, **replacements)
|
116
|
-
|
116
|
+
source = expected_annotations.plain_source
|
117
|
+
source = source.chomp if chomp
|
118
|
+
|
119
|
+
@processed_source = parse_processed_source(source, file)
|
117
120
|
@offenses = _investigate(cop, @processed_source)
|
118
121
|
actual_annotations =
|
119
122
|
expected_annotations.with_offense_annotations(@offenses)
|