rubocop 1.19.0 → 1.23.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 +1 -1
- data/config/default.yml +129 -21
- data/lib/rubocop/config.rb +5 -0
- data/lib/rubocop/config_loader.rb +5 -3
- data/lib/rubocop/config_validator.rb +9 -1
- data/lib/rubocop/cop/base.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_comment.rb +3 -3
- data/lib/rubocop/cop/bundler/gem_filename.rb +103 -0
- data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +45 -21
- data/lib/rubocop/cop/bundler/ordered_gems.rb +3 -12
- data/lib/rubocop/cop/correctors/lambda_literal_to_method_corrector.rb +2 -2
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +1 -1
- data/lib/rubocop/cop/correctors/ordered_gem_corrector.rb +11 -10
- data/lib/rubocop/cop/documentation.rb +1 -1
- data/lib/rubocop/cop/gemspec/date_assignment.rb +2 -10
- data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -10
- data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +3 -12
- data/lib/rubocop/cop/gemspec/require_mfa.rb +146 -0
- data/lib/rubocop/cop/gemspec/required_ruby_version.rb +31 -24
- data/lib/rubocop/cop/gemspec/ruby_version_globals_usage.rb +3 -10
- data/lib/rubocop/cop/generator.rb +14 -8
- data/lib/rubocop/cop/internal_affairs/location_line_equality_comparison.rb +60 -0
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs.rb +1 -0
- data/lib/rubocop/cop/layout/argument_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/assignment_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/block_alignment.rb +3 -3
- data/lib/rubocop/cop/layout/class_structure.rb +2 -1
- data/lib/rubocop/cop/layout/dot_position.rb +34 -5
- data/lib/rubocop/cop/layout/empty_comment.rb +1 -1
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +22 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +7 -4
- data/lib/rubocop/cop/layout/end_alignment.rb +2 -3
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_hash_element_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/hash_alignment.rb +1 -1
- data/lib/rubocop/cop/layout/heredoc_argument_closing_parenthesis.rb +1 -1
- data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
- data/lib/rubocop/cop/layout/leading_comment_space.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +9 -7
- data/lib/rubocop/cop/layout/multiline_assignment_layout.rb +1 -1
- data/lib/rubocop/cop/layout/multiline_block_layout.rb +3 -3
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +3 -0
- data/lib/rubocop/cop/layout/multiline_method_call_indentation.rb +1 -1
- data/lib/rubocop/cop/layout/redundant_line_break.rb +1 -0
- data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +6 -5
- data/lib/rubocop/cop/layout/single_line_block_chain.rb +15 -4
- data/lib/rubocop/cop/layout/space_after_not.rb +1 -0
- data/lib/rubocop/cop/layout/space_around_equals_in_parameter_default.rb +2 -1
- data/lib/rubocop/cop/layout/space_around_keyword.rb +2 -2
- data/lib/rubocop/cop/layout/space_before_brackets.rb +1 -0
- data/lib/rubocop/cop/layout/space_before_comment.rb +1 -1
- data/lib/rubocop/cop/layout/space_in_lambda_literal.rb +11 -5
- data/lib/rubocop/cop/layout/space_inside_parens.rb +74 -28
- data/lib/rubocop/cop/layout/space_inside_reference_brackets.rb +1 -1
- data/lib/rubocop/cop/lint/ambiguous_operator_precedence.rb +111 -0
- data/lib/rubocop/cop/lint/ambiguous_range.rb +11 -11
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +7 -5
- data/lib/rubocop/cop/lint/binary_operator_with_identical_operands.rb +18 -5
- data/lib/rubocop/cop/lint/boolean_symbol.rb +5 -0
- data/lib/rubocop/cop/lint/debugger.rb +2 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +4 -4
- data/lib/rubocop/cop/lint/deprecated_constants.rb +3 -2
- data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +24 -1
- data/lib/rubocop/cop/lint/else_layout.rb +10 -6
- data/lib/rubocop/cop/lint/empty_in_pattern.rb +1 -1
- data/lib/rubocop/cop/lint/erb_new_arguments.rb +1 -1
- data/lib/rubocop/cop/lint/float_out_of_range.rb +1 -1
- data/lib/rubocop/cop/lint/hash_compare_by_identity.rb +12 -3
- data/lib/rubocop/cop/lint/incompatible_io_select_with_fiber_scheduler.rb +67 -0
- data/lib/rubocop/cop/lint/interpolation_check.rb +5 -0
- data/lib/rubocop/cop/lint/loop.rb +4 -3
- data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +5 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +16 -2
- data/lib/rubocop/cop/lint/numbered_parameter_assignment.rb +1 -1
- data/lib/rubocop/cop/lint/or_assignment_to_constant.rb +4 -2
- data/lib/rubocop/cop/lint/out_of_range_regexp_ref.rb +17 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +10 -0
- data/lib/rubocop/cop/lint/raise_exception.rb +4 -0
- data/lib/rubocop/cop/lint/redundant_safe_navigation.rb +5 -4
- data/lib/rubocop/cop/lint/require_relative_self_path.rb +50 -0
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +1 -1
- data/lib/rubocop/cop/lint/symbol_conversion.rb +1 -1
- data/lib/rubocop/cop/lint/triple_quotes.rb +1 -1
- data/lib/rubocop/cop/lint/unexpected_block_arity.rb +8 -3
- data/lib/rubocop/cop/lint/unused_method_argument.rb +2 -3
- data/lib/rubocop/cop/lint/useless_method_definition.rb +3 -2
- data/lib/rubocop/cop/lint/useless_ruby2_keywords.rb +117 -0
- data/lib/rubocop/cop/lint/useless_setter_call.rb +7 -4
- data/lib/rubocop/cop/lint/useless_times.rb +4 -3
- data/lib/rubocop/cop/metrics/abc_size.rb +6 -0
- data/lib/rubocop/cop/metrics/parameter_lists.rb +5 -2
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +1 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +57 -34
- data/lib/rubocop/cop/mixin/code_length.rb +1 -1
- data/lib/rubocop/cop/mixin/documentation_comment.rb +5 -2
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +1 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +23 -1
- data/lib/rubocop/cop/mixin/gemspec_help.rb +30 -0
- data/lib/rubocop/cop/mixin/hash_transform_method.rb +3 -3
- data/lib/rubocop/cop/mixin/heredoc.rb +1 -3
- data/lib/rubocop/cop/mixin/multiline_element_indentation.rb +1 -1
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +2 -2
- data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
- data/lib/rubocop/cop/mixin/ordered_gem_node.rb +9 -1
- data/lib/rubocop/cop/mixin/percent_array.rb +11 -3
- data/lib/rubocop/cop/mixin/preceding_following_alignment.rb +9 -1
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +1 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/mixin/trailing_body.rb +1 -1
- data/lib/rubocop/cop/naming/ascii_identifiers.rb +0 -3
- data/lib/rubocop/cop/naming/block_parameter_name.rb +1 -1
- data/lib/rubocop/cop/naming/constant_name.rb +1 -1
- data/lib/rubocop/cop/naming/file_name.rb +37 -4
- data/lib/rubocop/cop/naming/inclusive_language.rb +9 -9
- data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +5 -4
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +7 -0
- data/lib/rubocop/cop/security/io_methods.rb +49 -0
- data/lib/rubocop/cop/security/json_load.rb +8 -7
- data/lib/rubocop/cop/security/open.rb +4 -0
- data/lib/rubocop/cop/security/yaml_load.rb +4 -0
- data/lib/rubocop/cop/style/accessor_grouping.rb +2 -2
- data/lib/rubocop/cop/style/and_or.rb +5 -0
- data/lib/rubocop/cop/style/arguments_forwarding.rb +13 -2
- data/lib/rubocop/cop/style/array_coercion.rb +21 -3
- data/lib/rubocop/cop/style/ascii_comments.rb +0 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +23 -6
- data/lib/rubocop/cop/style/case_equality.rb +6 -9
- data/lib/rubocop/cop/style/case_like_if.rb +5 -0
- data/lib/rubocop/cop/style/class_and_module_children.rb +9 -0
- data/lib/rubocop/cop/style/collection_compact.rb +7 -5
- data/lib/rubocop/cop/style/collection_methods.rb +8 -6
- data/lib/rubocop/cop/style/combinable_loops.rb +3 -2
- data/lib/rubocop/cop/style/comment_annotation.rb +25 -39
- data/lib/rubocop/cop/style/commented_keyword.rb +9 -4
- data/lib/rubocop/cop/style/date_time.rb +5 -0
- data/lib/rubocop/cop/style/document_dynamic_eval_definition.rb +1 -1
- data/lib/rubocop/cop/style/documentation.rb +23 -8
- data/lib/rubocop/cop/style/double_negation.rb +27 -6
- data/lib/rubocop/cop/style/empty_method.rb +2 -2
- data/lib/rubocop/cop/style/encoding.rb +26 -15
- data/lib/rubocop/cop/style/explicit_block_argument.rb +21 -11
- data/lib/rubocop/cop/style/float_division.rb +10 -2
- data/lib/rubocop/cop/style/format_string_token.rb +2 -1
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +7 -2
- data/lib/rubocop/cop/style/global_std_stream.rb +4 -0
- data/lib/rubocop/cop/style/hash_as_last_array_item.rb +11 -0
- data/lib/rubocop/cop/style/hash_each_methods.rb +5 -0
- data/lib/rubocop/cop/style/hash_except.rb +4 -3
- data/lib/rubocop/cop/style/hash_transform_keys.rb +4 -6
- data/lib/rubocop/cop/style/hash_transform_values.rb +4 -6
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +18 -16
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +18 -4
- data/lib/rubocop/cop/style/infinite_loop.rb +4 -3
- data/lib/rubocop/cop/style/inverse_methods.rb +9 -2
- data/lib/rubocop/cop/style/lambda_call.rb +1 -1
- data/lib/rubocop/cop/style/line_end_concatenation.rb +14 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +6 -6
- data/lib/rubocop/cop/style/module_function.rb +8 -9
- data/lib/rubocop/cop/style/multiline_in_pattern_then.rb +1 -1
- data/lib/rubocop/cop/style/multiline_when_then.rb +1 -1
- data/lib/rubocop/cop/style/mutable_constant.rb +73 -6
- data/lib/rubocop/cop/style/negated_if.rb +1 -1
- data/lib/rubocop/cop/style/negated_unless.rb +1 -1
- data/lib/rubocop/cop/style/non_nil_check.rb +2 -2
- data/lib/rubocop/cop/style/not.rb +2 -2
- data/lib/rubocop/cop/style/numbered_parameters.rb +46 -0
- data/lib/rubocop/cop/style/numbered_parameters_limit.rb +50 -0
- data/lib/rubocop/cop/style/numeric_literals.rb +7 -8
- data/lib/rubocop/cop/style/numeric_predicate.rb +5 -0
- data/lib/rubocop/cop/style/open_struct_use.rb +69 -0
- data/lib/rubocop/cop/style/optional_arguments.rb +4 -0
- data/lib/rubocop/cop/style/optional_boolean_parameter.rb +14 -4
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -1
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +12 -2
- data/lib/rubocop/cop/style/percent_q_literals.rb +2 -2
- data/lib/rubocop/cop/style/preferred_hash_methods.rb +9 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +21 -7
- data/lib/rubocop/cop/style/raise_args.rb +1 -1
- data/lib/rubocop/cop/style/redundant_argument.rb +19 -9
- data/lib/rubocop/cop/style/redundant_begin.rb +25 -0
- data/lib/rubocop/cop/style/redundant_condition.rb +2 -3
- data/lib/rubocop/cop/style/redundant_fetch_block.rb +4 -0
- data/lib/rubocop/cop/style/redundant_file_extension_in_require.rb +12 -3
- data/lib/rubocop/cop/style/redundant_freeze.rb +4 -4
- data/lib/rubocop/cop/style/redundant_interpolation.rb +1 -1
- data/lib/rubocop/cop/style/redundant_percent_q.rb +2 -3
- data/lib/rubocop/cop/style/redundant_self.rb +10 -0
- data/lib/rubocop/cop/style/redundant_self_assignment.rb +4 -3
- data/lib/rubocop/cop/style/redundant_self_assignment_branch.rb +23 -28
- data/lib/rubocop/cop/style/redundant_sort.rb +51 -18
- data/lib/rubocop/cop/style/regexp_literal.rb +3 -3
- data/lib/rubocop/cop/style/return_nil.rb +2 -1
- data/lib/rubocop/cop/style/safe_navigation.rb +13 -2
- data/lib/rubocop/cop/style/select_by_regexp.rb +139 -0
- data/lib/rubocop/cop/style/single_argument_dig.rb +5 -0
- data/lib/rubocop/cop/style/slicing_with_range.rb +13 -0
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +4 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +4 -0
- data/lib/rubocop/cop/style/static_class.rb +5 -5
- data/lib/rubocop/cop/style/string_chars.rb +4 -2
- data/lib/rubocop/cop/style/string_concatenation.rb +5 -1
- data/lib/rubocop/cop/style/string_hash_keys.rb +4 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +4 -0
- data/lib/rubocop/cop/style/swap_values.rb +4 -2
- data/lib/rubocop/cop/style/symbol_array.rb +3 -3
- data/lib/rubocop/cop/style/symbol_proc.rb +26 -0
- data/lib/rubocop/cop/style/trailing_comma_in_block_args.rb +19 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +3 -3
- data/lib/rubocop/cop/style/yoda_condition.rb +24 -7
- data/lib/rubocop/cop/style/zero_length_predicate.rb +6 -0
- data/lib/rubocop/cop/util.rb +15 -4
- data/lib/rubocop/cops_documentation_generator.rb +17 -5
- data/lib/rubocop/formatter/html_formatter.rb +5 -2
- data/lib/rubocop/formatter/json_formatter.rb +4 -1
- data/lib/rubocop/magic_comment.rb +44 -15
- data/lib/rubocop/options.rb +126 -112
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +1 -1
- data/lib/rubocop/result_cache.rb +3 -3
- data/lib/rubocop/rspec/cop_helper.rb +1 -1
- data/lib/rubocop/rspec/expect_offense.rb +6 -2
- data/lib/rubocop/rspec/parallel_formatter.rb +90 -0
- data/lib/rubocop/rspec/support.rb +1 -0
- data/lib/rubocop/runner.rb +2 -3
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/yaml_duplication_checker.rb +1 -1
- data/lib/rubocop.rb +14 -2
- metadata +20 -5
@@ -5,6 +5,10 @@ module RuboCop
|
|
5
5
|
module Style
|
6
6
|
# This cop checks for inheritance from Struct.new.
|
7
7
|
#
|
8
|
+
# @safety
|
9
|
+
# Auto-correction is unsafe because it will change the inheritance
|
10
|
+
# tree (e.g. return value of `Module#ancestors`) of the constant.
|
11
|
+
#
|
8
12
|
# @example
|
9
13
|
# # bad
|
10
14
|
# class Person < Struct.new(:first_name, :last_name)
|
@@ -4,8 +4,10 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
module Style
|
6
6
|
# This cop enforces the use of shorthand-style swapping of 2 variables.
|
7
|
-
#
|
8
|
-
#
|
7
|
+
#
|
8
|
+
# @safety
|
9
|
+
# Autocorrection is unsafe, because the temporary variable used to
|
10
|
+
# swap variables will be removed, but may be referred to elsewhere.
|
9
11
|
#
|
10
12
|
# @example
|
11
13
|
# # bad
|
@@ -35,7 +35,7 @@ module RuboCop
|
|
35
35
|
extend AutoCorrector
|
36
36
|
|
37
37
|
PERCENT_MSG = 'Use `%i` or `%I` for an array of symbols.'
|
38
|
-
ARRAY_MSG = 'Use `
|
38
|
+
ARRAY_MSG = 'Use `%<prefer>s` for an array of symbols.'
|
39
39
|
|
40
40
|
class << self
|
41
41
|
attr_accessor :largest_brackets
|
@@ -60,7 +60,7 @@ module RuboCop
|
|
60
60
|
end
|
61
61
|
end
|
62
62
|
|
63
|
-
def
|
63
|
+
def build_bracketed_array(node)
|
64
64
|
syms = node.children.map do |c|
|
65
65
|
if c.dsym_type?
|
66
66
|
string_literal = to_string_literal(c.source)
|
@@ -71,7 +71,7 @@ module RuboCop
|
|
71
71
|
end
|
72
72
|
end
|
73
73
|
|
74
|
-
|
74
|
+
"[#{syms.join(', ')}]"
|
75
75
|
end
|
76
76
|
|
77
77
|
def to_symbol_literal(string)
|
@@ -8,6 +8,32 @@ module RuboCop
|
|
8
8
|
# If you prefer a style that allows block for method with arguments,
|
9
9
|
# please set `true` to `AllowMethodsWithArguments`.
|
10
10
|
#
|
11
|
+
# @safety
|
12
|
+
# This cop is unsafe because `proc`s and blocks work differently
|
13
|
+
# when additional arguments are passed in. A block will silently
|
14
|
+
# ignore additional arguments, but a `proc` will raise
|
15
|
+
# an `ArgumentError`.
|
16
|
+
#
|
17
|
+
# For example:
|
18
|
+
#
|
19
|
+
# [source,ruby]
|
20
|
+
# ----
|
21
|
+
# class Foo
|
22
|
+
# def bar
|
23
|
+
# :bar
|
24
|
+
# end
|
25
|
+
# end
|
26
|
+
#
|
27
|
+
# def call(options = {}, &block)
|
28
|
+
# block.call(Foo.new, options)
|
29
|
+
# end
|
30
|
+
#
|
31
|
+
# call { |x| x.bar }
|
32
|
+
# #=> :bar
|
33
|
+
# call(&:bar)
|
34
|
+
# # ArgumentError: wrong number of arguments (given 1, expected 0)
|
35
|
+
# ----
|
36
|
+
#
|
11
37
|
# @example
|
12
38
|
# # bad
|
13
39
|
# something.map { |s| s.upcase }
|
@@ -8,6 +8,25 @@ module RuboCop
|
|
8
8
|
# that comma to be present. Blocks with more than one argument never
|
9
9
|
# require a trailing comma.
|
10
10
|
#
|
11
|
+
# @safety
|
12
|
+
# This cop is unsafe because a trailing comma can indicate there are
|
13
|
+
# more parameters that are not used.
|
14
|
+
#
|
15
|
+
# For example:
|
16
|
+
# [source,ruby]
|
17
|
+
# ----
|
18
|
+
# # with a trailing comma
|
19
|
+
# {foo: 1, bar: 2, baz: 3}.map {|key,| key }
|
20
|
+
# #=> [:foo, :bar, :baz]
|
21
|
+
#
|
22
|
+
# # without a trailing comma
|
23
|
+
# {foo: 1, bar: 2, baz: 3}.map {|key| key }
|
24
|
+
# #=> [[:foo, 1], [:bar, 2], [:baz, 3]]
|
25
|
+
# ----
|
26
|
+
#
|
27
|
+
# This can be fixed by replacing the trailing comma with a placeholder
|
28
|
+
# argument (such as `|key, _value|`).
|
29
|
+
#
|
11
30
|
# @example
|
12
31
|
# # bad
|
13
32
|
# add { |foo, bar,| foo + bar }
|
@@ -44,7 +44,7 @@ module RuboCop
|
|
44
44
|
extend AutoCorrector
|
45
45
|
|
46
46
|
PERCENT_MSG = 'Use `%w` or `%W` for an array of words.'
|
47
|
-
ARRAY_MSG = 'Use `
|
47
|
+
ARRAY_MSG = 'Use `%<prefer>s` for an array of words.'
|
48
48
|
|
49
49
|
class << self
|
50
50
|
attr_accessor :largest_brackets
|
@@ -82,7 +82,7 @@ module RuboCop
|
|
82
82
|
Regexp.new(cop_config['WordRegex'])
|
83
83
|
end
|
84
84
|
|
85
|
-
def
|
85
|
+
def build_bracketed_array(node)
|
86
86
|
words = node.children.map do |word|
|
87
87
|
if word.dstr_type?
|
88
88
|
string_literal = to_string_literal(word.source)
|
@@ -93,7 +93,7 @@ module RuboCop
|
|
93
93
|
end
|
94
94
|
end
|
95
95
|
|
96
|
-
|
96
|
+
"[#{words.join(', ')}]"
|
97
97
|
end
|
98
98
|
end
|
99
99
|
end
|
@@ -7,6 +7,26 @@ module RuboCop
|
|
7
7
|
# i.e. comparison operations where the order of expression is reversed.
|
8
8
|
# eg. `5 == x`
|
9
9
|
#
|
10
|
+
# @safety
|
11
|
+
# This cop is unsafe because comparison operators can be defined
|
12
|
+
# differently on different classes, and are not guaranteed to
|
13
|
+
# have the same result if reversed.
|
14
|
+
#
|
15
|
+
# For example:
|
16
|
+
#
|
17
|
+
# [source,ruby]
|
18
|
+
# ----
|
19
|
+
# class MyKlass
|
20
|
+
# def ==(other)
|
21
|
+
# true
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# obj = MyKlass.new
|
26
|
+
# obj == 'string' #=> true
|
27
|
+
# 'string' == obj #=> false
|
28
|
+
# ----
|
29
|
+
#
|
10
30
|
# @example EnforcedStyle: forbid_for_all_comparison_operators (default)
|
11
31
|
# # bad
|
12
32
|
# 99 == foo
|
@@ -58,14 +78,11 @@ module RuboCop
|
|
58
78
|
extend AutoCorrector
|
59
79
|
|
60
80
|
MSG = 'Reverse the order of the operands `%<source>s`.'
|
61
|
-
|
62
81
|
REVERSE_COMPARISON = { '<' => '>', '<=' => '>=', '>' => '<', '>=' => '<=' }.freeze
|
63
|
-
|
64
82
|
EQUALITY_OPERATORS = %i[== !=].freeze
|
65
|
-
|
66
83
|
NONCOMMUTATIVE_OPERATORS = %i[===].freeze
|
67
|
-
|
68
84
|
PROGRAM_NAMES = %i[$0 $PROGRAM_NAME].freeze
|
85
|
+
RESTRICT_ON_SEND = RuboCop::AST::Node::COMPARISON_OPERATORS
|
69
86
|
|
70
87
|
# @!method file_constant_equal_program_name?(node)
|
71
88
|
def_node_matcher :file_constant_equal_program_name?, <<~PATTERN
|
@@ -74,7 +91,7 @@ module RuboCop
|
|
74
91
|
|
75
92
|
def on_send(node)
|
76
93
|
return unless yoda_compatible_condition?(node)
|
77
|
-
return if equality_only? && non_equality_operator?(node) ||
|
94
|
+
return if (equality_only? && non_equality_operator?(node)) ||
|
78
95
|
file_constant_equal_program_name?(node)
|
79
96
|
|
80
97
|
valid_yoda?(node) || add_offense(node) do |corrector|
|
@@ -102,8 +119,8 @@ module RuboCop
|
|
102
119
|
lhs = node.receiver
|
103
120
|
rhs = node.first_argument
|
104
121
|
|
105
|
-
return true if lhs.literal? && rhs.literal? ||
|
106
|
-
!lhs.literal? && !rhs.literal? ||
|
122
|
+
return true if (lhs.literal? && rhs.literal?) ||
|
123
|
+
(!lhs.literal? && !rhs.literal?) ||
|
107
124
|
interpolation?(lhs)
|
108
125
|
|
109
126
|
enforce_yoda? ? lhs.literal? : rhs.literal?
|
@@ -9,6 +9,12 @@ module RuboCop
|
|
9
9
|
# receiver.length < 1 and receiver.size == 0 that can be
|
10
10
|
# replaced by receiver.empty? and !receiver.empty?.
|
11
11
|
#
|
12
|
+
# @safety
|
13
|
+
# This cop is unsafe because it cannot be guaranteed that the receiver
|
14
|
+
# has an `empty?` method that is defined in terms of `length`. If there
|
15
|
+
# is a non-standard class that redefines `length` or `empty?`, the cop
|
16
|
+
# may register a false positive.
|
17
|
+
#
|
12
18
|
# @example
|
13
19
|
# # bad
|
14
20
|
# [1, 2, 3].length == 0
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -113,7 +113,8 @@ module RuboCop
|
|
113
113
|
if needs_escaping?(string) && compatible_external_encoding_for?(string)
|
114
114
|
string.inspect
|
115
115
|
else
|
116
|
-
|
116
|
+
# In a single-quoted strings, double quotes don't need to be escaped
|
117
|
+
"'#{string.gsub('\"', '"').gsub('\\') { '\\\\' }}'"
|
117
118
|
end
|
118
119
|
end
|
119
120
|
|
@@ -125,12 +126,22 @@ module RuboCop
|
|
125
126
|
StringInterpreter.interpret(string)
|
126
127
|
end
|
127
128
|
|
129
|
+
def line(node_or_range)
|
130
|
+
if node_or_range.respond_to?(:line)
|
131
|
+
node_or_range.line
|
132
|
+
elsif node_or_range.respond_to?(:loc)
|
133
|
+
node_or_range.loc.line
|
134
|
+
end
|
135
|
+
end
|
136
|
+
|
128
137
|
def same_line?(node1, node2)
|
129
|
-
|
138
|
+
line1 = line(node1)
|
139
|
+
line2 = line(node2)
|
140
|
+
line1 && line2 && line1 == line2
|
130
141
|
end
|
131
142
|
|
132
|
-
def indent(node)
|
133
|
-
' ' * node.loc.column
|
143
|
+
def indent(node, offset: 0)
|
144
|
+
' ' * (node.loc.column + offset)
|
134
145
|
end
|
135
146
|
|
136
147
|
def to_supported_styles(enforced_style)
|
@@ -33,11 +33,12 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
33
33
|
cops.with_department(department).sort!
|
34
34
|
end
|
35
35
|
|
36
|
-
def cops_body(cop, description, examples_objects, pars)
|
36
|
+
def cops_body(cop, description, examples_objects, safety_objects, pars) # rubocop:disable Metrics/AbcSize
|
37
37
|
content = h2(cop.cop_name)
|
38
38
|
content << required_ruby_version(cop)
|
39
39
|
content << properties(cop)
|
40
40
|
content << "#{description}\n"
|
41
|
+
content << safety_object(safety_objects) if safety_objects.any? { |s| !s.text.blank? }
|
41
42
|
content << examples(examples_objects) if examples_objects.count.positive?
|
42
43
|
content << configurations(pars)
|
43
44
|
content << references(cop)
|
@@ -52,6 +53,16 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
52
53
|
end
|
53
54
|
end
|
54
55
|
|
56
|
+
def safety_object(safety_object_objects)
|
57
|
+
safety_object_objects.each_with_object(h3('Safety').dup) do |safety_object, content|
|
58
|
+
next if safety_object.text.blank?
|
59
|
+
|
60
|
+
content << "\n" unless content.end_with?("\n\n")
|
61
|
+
content << safety_object.text
|
62
|
+
content << "\n"
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
55
66
|
def required_ruby_version(cop)
|
56
67
|
return '' unless cop.respond_to?(:required_minimum_ruby_version)
|
57
68
|
|
@@ -61,8 +72,8 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
61
72
|
# rubocop:disable Metrics/MethodLength
|
62
73
|
def properties(cop)
|
63
74
|
header = [
|
64
|
-
'Enabled by default', 'Safe', 'Supports autocorrection', '
|
65
|
-
'
|
75
|
+
'Enabled by default', 'Safe', 'Supports autocorrection', 'Version Added',
|
76
|
+
'Version Changed'
|
66
77
|
]
|
67
78
|
autocorrect = if cop.support_autocorrect?
|
68
79
|
"Yes#{' (Unsafe)' unless cop.new(config).safe_autocorrect?}"
|
@@ -217,12 +228,13 @@ class CopsDocumentationGenerator # rubocop:disable Metrics/ClassLength
|
|
217
228
|
]
|
218
229
|
pars = cop_config.reject { |k| non_display_keys.include? k }
|
219
230
|
description = 'No documentation'
|
220
|
-
examples_object = []
|
231
|
+
examples_object = safety_object = []
|
221
232
|
cop_code(cop) do |code_object|
|
222
233
|
description = code_object.docstring unless code_object.docstring.blank?
|
223
234
|
examples_object = code_object.tags('example')
|
235
|
+
safety_object = code_object.tags('safety')
|
224
236
|
end
|
225
|
-
cops_body(cop, description, examples_object, pars)
|
237
|
+
cops_body(cop, description, examples_object, safety_object, pars)
|
226
238
|
end
|
227
239
|
|
228
240
|
def cop_code(cop)
|
@@ -23,12 +23,15 @@ module RuboCop
|
|
23
23
|
end
|
24
24
|
end
|
25
25
|
|
26
|
+
Summary = Struct.new(:offense_count, :inspected_files, :target_files, keyword_init: true)
|
27
|
+
FileOffenses = Struct.new(:path, :offenses, keyword_init: true)
|
28
|
+
|
26
29
|
attr_reader :files, :summary
|
27
30
|
|
28
31
|
def initialize(output, options = {})
|
29
32
|
super
|
30
33
|
@files = []
|
31
|
-
@summary =
|
34
|
+
@summary = Summary.new(offense_count: 0)
|
32
35
|
end
|
33
36
|
|
34
37
|
def started(target_files)
|
@@ -36,7 +39,7 @@ module RuboCop
|
|
36
39
|
end
|
37
40
|
|
38
41
|
def file_finished(file, offenses)
|
39
|
-
files <<
|
42
|
+
files << FileOffenses.new(path: file, offenses: offenses)
|
40
43
|
summary.offense_count += offenses.count
|
41
44
|
end
|
42
45
|
|
@@ -59,12 +59,15 @@ module RuboCop
|
|
59
59
|
end
|
60
60
|
|
61
61
|
# TODO: Consider better solution for Offense#real_column.
|
62
|
+
# The minimum value of `start_column: real_column` is 1.
|
63
|
+
# So, the minimum value of `last_column` should be 1.
|
64
|
+
# And non-zero value of `last_column` should be used as is.
|
62
65
|
def hash_for_location(offense)
|
63
66
|
{
|
64
67
|
start_line: offense.line,
|
65
68
|
start_column: offense.real_column,
|
66
69
|
last_line: offense.last_line,
|
67
|
-
last_column: offense.last_column,
|
70
|
+
last_column: offense.last_column.zero? ? 1 : offense.last_column,
|
68
71
|
length: offense.location.length,
|
69
72
|
# `line` and `column` exist for compatibility.
|
70
73
|
# Use `start_line` and `start_column` instead.
|
@@ -7,6 +7,11 @@ module RuboCop
|
|
7
7
|
class MagicComment
|
8
8
|
# @see https://git.io/vMC1C IRB's pattern for matching magic comment tokens
|
9
9
|
TOKEN = /[[:alnum:]\-_]+/.freeze
|
10
|
+
KEYWORDS = {
|
11
|
+
encoding: '(?:en)?coding',
|
12
|
+
frozen_string_literal: 'frozen[_-]string[_-]literal',
|
13
|
+
shareable_constant_value: 'shareable[_-]constant[_-]value'
|
14
|
+
}.freeze
|
10
15
|
|
11
16
|
# Detect magic comment format and pass it to the appropriate wrapper.
|
12
17
|
#
|
@@ -15,8 +20,8 @@ module RuboCop
|
|
15
20
|
# @return [RuboCop::MagicComment]
|
16
21
|
def self.parse(comment)
|
17
22
|
case comment
|
18
|
-
when EmacsComment::
|
19
|
-
when VimComment::
|
23
|
+
when EmacsComment::REGEXP then EmacsComment.new(comment)
|
24
|
+
when VimComment::REGEXP then VimComment.new(comment)
|
20
25
|
else
|
21
26
|
SimpleComment.new(comment)
|
22
27
|
end
|
@@ -30,6 +35,10 @@ module RuboCop
|
|
30
35
|
frozen_string_literal_specified? || encoding_specified? || shareable_constant_value_specified?
|
31
36
|
end
|
32
37
|
|
38
|
+
def valid?
|
39
|
+
@comment.start_with?('#') && any?
|
40
|
+
end
|
41
|
+
|
33
42
|
# Does the magic comment enable the frozen string literal feature.
|
34
43
|
#
|
35
44
|
# Test whether the frozen string literal value is `true`. Cannot
|
@@ -111,6 +120,18 @@ module RuboCop
|
|
111
120
|
#
|
112
121
|
# @abstract
|
113
122
|
class EditorComment < MagicComment
|
123
|
+
def encoding
|
124
|
+
match(self.class::KEYWORDS[:encoding])
|
125
|
+
end
|
126
|
+
|
127
|
+
# Rewrite the comment without a given token type
|
128
|
+
def without(type)
|
129
|
+
remaining = tokens.grep_v(/\A#{self.class::KEYWORDS[type.to_sym]}/)
|
130
|
+
return '' if remaining.empty?
|
131
|
+
|
132
|
+
self.class::FORMAT % remaining.join(self.class::SEPARATOR)
|
133
|
+
end
|
134
|
+
|
114
135
|
private
|
115
136
|
|
116
137
|
# Find a token starting with the provided keyword and extract its value.
|
@@ -135,7 +156,7 @@ module RuboCop
|
|
135
156
|
#
|
136
157
|
# @return [Array<String>]
|
137
158
|
def tokens
|
138
|
-
extract(self.class::
|
159
|
+
extract(self.class::REGEXP).split(self.class::SEPARATOR).map(&:strip)
|
139
160
|
end
|
140
161
|
end
|
141
162
|
|
@@ -151,22 +172,19 @@ module RuboCop
|
|
151
172
|
# @see https://www.gnu.org/software/emacs/manual/html_node/emacs/Specify-Coding.html
|
152
173
|
# @see https://git.io/vMCXh Emacs handling in Ruby's parse.y
|
153
174
|
class EmacsComment < EditorComment
|
154
|
-
|
175
|
+
REGEXP = /-\*-(.+)-\*-/.freeze
|
176
|
+
FORMAT = '# -*- %s -*-'
|
155
177
|
SEPARATOR = ';'
|
156
178
|
OPERATOR = ':'
|
157
179
|
|
158
|
-
def encoding
|
159
|
-
match('(?:en)?coding')
|
160
|
-
end
|
161
|
-
|
162
180
|
private
|
163
181
|
|
164
182
|
def extract_frozen_string_literal
|
165
|
-
match(
|
183
|
+
match(KEYWORDS[:frozen_string_literal])
|
166
184
|
end
|
167
185
|
|
168
186
|
def extract_shareable_constant_value
|
169
|
-
match(
|
187
|
+
match(KEYWORDS[:shareable_constant_value])
|
170
188
|
end
|
171
189
|
end
|
172
190
|
|
@@ -179,9 +197,11 @@ module RuboCop
|
|
179
197
|
#
|
180
198
|
# comment.encoding # => 'ascii-8bit'
|
181
199
|
class VimComment < EditorComment
|
182
|
-
|
200
|
+
REGEXP = /#\s*vim:\s*(.+)/.freeze
|
201
|
+
FORMAT = '# vim: %s'
|
183
202
|
SEPARATOR = ', '
|
184
203
|
OPERATOR = '='
|
204
|
+
KEYWORDS = MagicComment::KEYWORDS.merge(encoding: 'fileencoding').freeze
|
185
205
|
|
186
206
|
# For some reason the fileencoding keyword only works if there
|
187
207
|
# is at least one other token included in the string. For example
|
@@ -193,7 +213,7 @@ module RuboCop
|
|
193
213
|
# # vim: foo=bar, fileencoding=ascii-8bit
|
194
214
|
#
|
195
215
|
def encoding
|
196
|
-
|
216
|
+
super if tokens.size > 1
|
197
217
|
end
|
198
218
|
|
199
219
|
# Vim comments cannot specify frozen string literal behavior.
|
@@ -219,7 +239,16 @@ module RuboCop
|
|
219
239
|
class SimpleComment < MagicComment
|
220
240
|
# Match `encoding` or `coding`
|
221
241
|
def encoding
|
222
|
-
extract(/\A\s*\#.*\b
|
242
|
+
extract(/\A\s*\#.*\b#{KEYWORDS[:encoding]}: (#{TOKEN})/io)
|
243
|
+
end
|
244
|
+
|
245
|
+
# Rewrite the comment without a given token type
|
246
|
+
def without(type)
|
247
|
+
if @comment.match?(/\A#\s*#{self.class::KEYWORDS[type.to_sym]}/)
|
248
|
+
''
|
249
|
+
else
|
250
|
+
@comment
|
251
|
+
end
|
223
252
|
end
|
224
253
|
|
225
254
|
private
|
@@ -232,11 +261,11 @@ module RuboCop
|
|
232
261
|
# Case-insensitive and dashes/underscores are acceptable.
|
233
262
|
# @see https://git.io/vM7Mg
|
234
263
|
def extract_frozen_string_literal
|
235
|
-
extract(/\A\s*#\s
|
264
|
+
extract(/\A\s*#\s*#{KEYWORDS[:frozen_string_literal]}:\s*(#{TOKEN})\s*\z/io)
|
236
265
|
end
|
237
266
|
|
238
267
|
def extract_shareable_constant_value
|
239
|
-
extract(/\A\s*#\s
|
268
|
+
extract(/\A\s*#\s*#{KEYWORDS[:shareable_constant_value]}:\s*(#{TOKEN})\s*\z/io)
|
240
269
|
end
|
241
270
|
end
|
242
271
|
end
|