rubocop 1.65.0 → 1.66.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +67 -67
- data/config/default.yml +18 -2
- data/exe/rubocop +4 -3
- data/lib/rubocop/comment_config.rb +1 -1
- data/lib/rubocop/config.rb +5 -1
- data/lib/rubocop/config_loader.rb +14 -8
- data/lib/rubocop/config_loader_resolver.rb +1 -2
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/base.rb +4 -0
- data/lib/rubocop/cop/cop.rb +2 -2
- data/lib/rubocop/cop/correctors/line_break_corrector.rb +2 -0
- data/lib/rubocop/cop/documentation.rb +18 -1
- data/lib/rubocop/cop/internal_affairs/empty_line_between_expect_offense_and_correction.rb +2 -1
- data/lib/rubocop/cop/internal_affairs/node_matcher_directive.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/undefined_config.rb +11 -1
- data/lib/rubocop/cop/layout/assignment_indentation.rb +3 -2
- data/lib/rubocop/cop/layout/block_alignment.rb +30 -12
- data/lib/rubocop/cop/layout/condition_position.rb +0 -4
- data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
- data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +8 -3
- data/lib/rubocop/cop/layout/first_array_element_indentation.rb +0 -3
- data/lib/rubocop/cop/layout/line_length.rb +14 -14
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +0 -2
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +0 -2
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +0 -2
- data/lib/rubocop/cop/lint/boolean_symbol.rb +0 -2
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +0 -13
- data/lib/rubocop/cop/lint/debugger.rb +0 -4
- data/lib/rubocop/cop/lint/deprecated_open_ssl_constant.rb +0 -10
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +0 -4
- data/lib/rubocop/cop/lint/duplicate_hash_key.rb +0 -4
- data/lib/rubocop/cop/lint/duplicate_methods.rb +0 -10
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +0 -4
- data/lib/rubocop/cop/lint/else_layout.rb +0 -2
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +27 -6
- data/lib/rubocop/cop/lint/empty_ensure.rb +1 -11
- data/lib/rubocop/cop/lint/empty_interpolation.rb +0 -4
- data/lib/rubocop/cop/lint/empty_when.rb +0 -2
- data/lib/rubocop/cop/lint/ensure_return.rb +1 -6
- data/lib/rubocop/cop/lint/float_out_of_range.rb +0 -4
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +0 -10
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +5 -7
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +0 -7
- data/lib/rubocop/cop/lint/interpolation_check.rb +0 -4
- data/lib/rubocop/cop/lint/literal_assignment_in_condition.rb +1 -1
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +0 -4
- data/lib/rubocop/cop/lint/loop.rb +6 -12
- data/lib/rubocop/cop/lint/nested_method_definition.rb +0 -6
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +0 -4
- data/lib/rubocop/cop/lint/no_return_in_begin_end_blocks.rb +0 -5
- data/lib/rubocop/cop/lint/percent_string_array.rb +0 -4
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +0 -4
- data/lib/rubocop/cop/lint/rand_one.rb +0 -4
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +3 -1
- data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
- data/lib/rubocop/cop/lint/redundant_string_coercion.rb +0 -4
- data/lib/rubocop/cop/lint/require_parentheses.rb +0 -4
- data/lib/rubocop/cop/lint/rescue_exception.rb +0 -4
- data/lib/rubocop/cop/lint/return_in_void_context.rb +0 -2
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +0 -4
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +6 -10
- data/lib/rubocop/cop/lint/unified_integer.rb +0 -4
- data/lib/rubocop/cop/lint/unreachable_code.rb +0 -5
- data/lib/rubocop/cop/lint/useless_assignment.rb +19 -16
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +0 -4
- data/lib/rubocop/cop/lint/useless_numeric_operation.rb +77 -0
- data/lib/rubocop/cop/lint/useless_setter_call.rb +0 -4
- data/lib/rubocop/cop/lint/void.rb +30 -8
- data/lib/rubocop/cop/metrics/block_length.rb +6 -5
- data/lib/rubocop/cop/metrics/class_length.rb +6 -5
- data/lib/rubocop/cop/metrics/method_length.rb +6 -5
- data/lib/rubocop/cop/metrics/module_length.rb +6 -5
- data/lib/rubocop/cop/mixin/annotation_comment.rb +0 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +19 -9
- data/lib/rubocop/cop/mixin/line_length_help.rb +7 -2
- data/lib/rubocop/cop/mixin/string_literals_help.rb +12 -0
- data/lib/rubocop/cop/naming/accessor_method_name.rb +5 -0
- data/lib/rubocop/cop/naming/predicate_name.rb +52 -26
- data/lib/rubocop/cop/naming/rescued_exceptions_variable_name.rb +10 -1
- data/lib/rubocop/cop/style/alias.rb +1 -1
- data/lib/rubocop/cop/style/arguments_forwarding.rb +8 -3
- data/lib/rubocop/cop/style/def_with_parentheses.rb +0 -2
- data/lib/rubocop/cop/style/each_for_simple_loop.rb +0 -1
- data/lib/rubocop/cop/style/empty_else.rb +6 -5
- data/lib/rubocop/cop/style/empty_heredoc.rb +1 -14
- data/lib/rubocop/cop/style/empty_literal.rb +31 -22
- data/lib/rubocop/cop/style/eval_with_location.rb +12 -11
- data/lib/rubocop/cop/style/file_read.rb +2 -5
- data/lib/rubocop/cop/style/file_write.rb +2 -5
- data/lib/rubocop/cop/style/format_string_token.rb +2 -2
- data/lib/rubocop/cop/style/global_std_stream.rb +7 -1
- data/lib/rubocop/cop/style/guard_clause.rb +2 -0
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
- data/lib/rubocop/cop/style/if_with_boolean_literal_branches.rb +0 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +45 -6
- data/lib/rubocop/cop/style/in_pattern_then.rb +6 -2
- data/lib/rubocop/cop/style/invertible_unless_condition.rb +2 -2
- data/lib/rubocop/cop/style/magic_comment_format.rb +1 -1
- data/lib/rubocop/cop/style/map_into_array.rb +12 -5
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +1 -1
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +2 -2
- data/lib/rubocop/cop/style/missing_else.rb +0 -4
- data/lib/rubocop/cop/style/multiline_when_then.rb +0 -4
- data/lib/rubocop/cop/style/multiple_comparison.rb +3 -11
- data/lib/rubocop/cop/style/numeric_predicate.rb +2 -2
- data/lib/rubocop/cop/style/one_line_conditional.rb +1 -1
- data/lib/rubocop/cop/style/parallel_assignment.rb +5 -4
- data/lib/rubocop/cop/style/quoted_symbols.rb +0 -2
- data/lib/rubocop/cop/style/redundant_condition.rb +3 -3
- data/lib/rubocop/cop/style/redundant_interpolation_unfreeze.rb +46 -0
- data/lib/rubocop/cop/style/redundant_regexp_argument.rb +4 -1
- data/lib/rubocop/cop/style/redundant_regexp_escape.rb +8 -24
- data/lib/rubocop/cop/style/safe_navigation.rb +2 -2
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +21 -2
- data/lib/rubocop/cop/style/while_until_do.rb +0 -2
- data/lib/rubocop/cop/style/while_until_modifier.rb +0 -1
- data/lib/rubocop/cop/style/zero_length_predicate.rb +5 -1
- data/lib/rubocop/cop/team.rb +6 -2
- data/lib/rubocop/cop/variable_force.rb +13 -1
- data/lib/rubocop/core_ext/string.rb +2 -6
- data/lib/rubocop/ext/regexp_node.rb +9 -31
- data/lib/rubocop/formatter/junit_formatter.rb +70 -23
- data/lib/rubocop/lockfile.rb +6 -4
- data/lib/rubocop/options.rb +3 -1
- data/lib/rubocop/remote_config.rb +5 -1
- data/lib/rubocop/result_cache.rb +2 -8
- data/lib/rubocop/rspec/shared_contexts.rb +2 -2
- data/lib/rubocop/server/cache.rb +1 -1
- data/lib/rubocop/target_ruby.rb +7 -3
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/yaml_duplication_checker.rb +1 -0
- data/lib/rubocop.rb +7 -1
- metadata +8 -26
@@ -8,10 +8,11 @@ module RuboCop
|
|
8
8
|
# The maximum allowed length is configurable.
|
9
9
|
#
|
10
10
|
# You can set constructs you want to fold with `CountAsOne`.
|
11
|
-
# Available are: 'array', 'hash', 'heredoc', and 'method_call'. Each construct
|
12
|
-
# will be counted as one line regardless of its actual size.
|
13
11
|
#
|
14
|
-
#
|
12
|
+
# Available are: 'array', 'hash', 'heredoc', and 'method_call'.
|
13
|
+
# Each construct will be counted as one line regardless of its actual size.
|
14
|
+
#
|
15
|
+
# @example CountAsOne: ['array', 'hash', 'heredoc', 'method_call']
|
15
16
|
#
|
16
17
|
# module M
|
17
18
|
# ARRAY = [ # +1
|
@@ -19,7 +20,7 @@ module RuboCop
|
|
19
20
|
# 2
|
20
21
|
# ]
|
21
22
|
#
|
22
|
-
# HASH = { # +
|
23
|
+
# HASH = { # +1
|
23
24
|
# key: 'value'
|
24
25
|
# }
|
25
26
|
#
|
@@ -32,7 +33,7 @@ module RuboCop
|
|
32
33
|
# 1,
|
33
34
|
# 2
|
34
35
|
# )
|
35
|
-
# end #
|
36
|
+
# end # 4 points
|
36
37
|
#
|
37
38
|
class ModuleLength < Base
|
38
39
|
include CodeLength
|
@@ -4,8 +4,6 @@ module RuboCop
|
|
4
4
|
module Cop
|
5
5
|
# Representation of an annotation comment in source code (eg. `# TODO: blah blah blah`).
|
6
6
|
class AnnotationComment
|
7
|
-
extend Forwardable
|
8
|
-
|
9
7
|
attr_reader :comment, :margin, :keyword, :colon, :space, :note
|
10
8
|
|
11
9
|
# @param [Parser::Source::Comment] comment
|
@@ -20,7 +20,7 @@ module RuboCop
|
|
20
20
|
|
21
21
|
def frozen_string_literal?(node)
|
22
22
|
frozen_string = if target_ruby_version >= 3.0
|
23
|
-
uninterpolated_string?(node) ||
|
23
|
+
uninterpolated_string?(node) || uninterpolated_heredoc?(node)
|
24
24
|
else
|
25
25
|
FROZEN_STRING_LITERAL_TYPES_RUBY27.include?(node.type)
|
26
26
|
end
|
@@ -32,29 +32,39 @@ module RuboCop
|
|
32
32
|
node.str_type? || (node.dstr_type? && node.each_descendant(:begin).none?)
|
33
33
|
end
|
34
34
|
|
35
|
-
def
|
35
|
+
def uninterpolated_heredoc?(node)
|
36
36
|
return false unless node.dstr_type? && node.heredoc?
|
37
37
|
|
38
38
|
node.children.all?(&:str_type?)
|
39
39
|
end
|
40
|
+
alias frozen_heredoc? uninterpolated_heredoc?
|
40
41
|
|
41
42
|
def frozen_string_literals_enabled?
|
42
43
|
ruby_version = processed_source.ruby_version
|
43
44
|
return false unless ruby_version
|
44
45
|
|
46
|
+
# Check if a magic string literal comment specifies what to do
|
47
|
+
magic_comments = leading_comment_lines.filter_map { |line| MagicComment.parse(line) }
|
48
|
+
if (literal_magic_comment = magic_comments.find(&:frozen_string_literal_specified?))
|
49
|
+
return literal_magic_comment.frozen_string_literal?
|
50
|
+
end
|
51
|
+
|
45
52
|
# TODO: Ruby officially abandon making frozen string literals default
|
46
53
|
# for Ruby 3.0.
|
47
54
|
# https://bugs.ruby-lang.org/issues/11473#note-53
|
48
|
-
# Whether frozen string literals will be the default after Ruby
|
49
|
-
# or not is still unclear as of
|
55
|
+
# Whether frozen string literals will be the default after Ruby 4.0
|
56
|
+
# or not is still unclear as of July 2024.
|
50
57
|
# It may be necessary to add this code in the future.
|
51
58
|
#
|
52
|
-
# return
|
59
|
+
# return ruby_version >= 4.0 if string_literals_frozen_by_default?.nil?
|
53
60
|
#
|
54
|
-
# And the above `ruby_version >=
|
55
|
-
# Ruby
|
56
|
-
# See https://bugs.ruby-lang.org/issues/
|
57
|
-
|
61
|
+
# And the above `ruby_version >= 4.0` is undecided whether it will be
|
62
|
+
# Ruby 4.0 or others.
|
63
|
+
# See https://bugs.ruby-lang.org/issues/20205 for details.
|
64
|
+
# For now, offer a configuration value to override behavior is using RUBYOPT.
|
65
|
+
return false if string_literals_frozen_by_default?.nil?
|
66
|
+
|
67
|
+
string_literals_frozen_by_default?
|
58
68
|
end
|
59
69
|
|
60
70
|
def frozen_string_literals_disabled?
|
@@ -91,8 +91,13 @@ module RuboCop
|
|
91
91
|
end
|
92
92
|
|
93
93
|
def uri_regexp
|
94
|
-
@uri_regexp ||=
|
95
|
-
|
94
|
+
@uri_regexp ||= begin
|
95
|
+
# Ruby 3.4 changes the default parser to RFC3986 which warns on make_regexp.
|
96
|
+
# Additionally, the RFC2396_PARSER alias is only available on 3.4 for now.
|
97
|
+
# Extra info at https://github.com/ruby/uri/issues/118
|
98
|
+
parser = defined?(URI::RFC2396_PARSER) ? URI::RFC2396_PARSER : URI::DEFAULT_PARSER
|
99
|
+
parser.make_regexp(config.for_cop('Layout/LineLength')['URISchemes'])
|
100
|
+
end
|
96
101
|
end
|
97
102
|
|
98
103
|
def valid_uri?(uri_ish_string)
|
@@ -16,6 +16,18 @@ module RuboCop
|
|
16
16
|
!/" | \\[^'\\] | \#[@{$]/x.match?(src)
|
17
17
|
end
|
18
18
|
end
|
19
|
+
|
20
|
+
def preferred_string_literal
|
21
|
+
enforce_double_quotes? ? '""' : "''"
|
22
|
+
end
|
23
|
+
|
24
|
+
def enforce_double_quotes?
|
25
|
+
string_literals_config['EnforcedStyle'] == 'double_quotes'
|
26
|
+
end
|
27
|
+
|
28
|
+
def string_literals_config
|
29
|
+
config.for_cop('Style/StringLiterals')
|
30
|
+
end
|
19
31
|
end
|
20
32
|
end
|
21
33
|
end
|
@@ -40,6 +40,7 @@ module RuboCop
|
|
40
40
|
MSG_WRITER = 'Do not prefix writer method names with `set_`.'
|
41
41
|
|
42
42
|
def on_def(node)
|
43
|
+
return unless proper_attribute_name?(node)
|
43
44
|
return unless bad_reader_name?(node) || bad_writer_name?(node)
|
44
45
|
|
45
46
|
message = message(node)
|
@@ -58,6 +59,10 @@ module RuboCop
|
|
58
59
|
end
|
59
60
|
end
|
60
61
|
|
62
|
+
def proper_attribute_name?(node)
|
63
|
+
!node.method_name.to_s.end_with?('!', '?', '=')
|
64
|
+
end
|
65
|
+
|
61
66
|
def bad_reader_name?(node)
|
62
67
|
node.method_name.to_s.start_with?('get_') && !node.arguments?
|
63
68
|
end
|
@@ -3,59 +3,75 @@
|
|
3
3
|
module RuboCop
|
4
4
|
module Cop
|
5
5
|
module Naming
|
6
|
-
# Checks that predicate
|
6
|
+
# Checks that predicate method names end with a question mark and
|
7
7
|
# do not start with a forbidden prefix.
|
8
8
|
#
|
9
|
-
# A method is determined to be a predicate method if its name starts
|
10
|
-
#
|
11
|
-
#
|
12
|
-
# Any method name that starts with one of these prefixes is required by
|
13
|
-
# the cop to end with a `?`. Other methods can be allowed by adding to
|
14
|
-
# the `AllowedMethods` configuration.
|
9
|
+
# A method is determined to be a predicate method if its name starts with
|
10
|
+
# one of the prefixes listed in the `NamePrefix` configuration. The list
|
11
|
+
# defaults to `is_`, `has_`, and `have_` but may be overridden.
|
15
12
|
#
|
16
|
-
#
|
13
|
+
# Predicate methods must end with a question mark.
|
17
14
|
#
|
18
|
-
#
|
19
|
-
#
|
15
|
+
# When `ForbiddenPrefixes` is also set (as it is by default), predicate
|
16
|
+
# methods which begin with a forbidden prefix are not allowed, even if
|
17
|
+
# they end with a `?`. These methods should be changed to remove the
|
18
|
+
# prefix.
|
20
19
|
#
|
21
|
-
#
|
22
|
-
# will register an offense only due to the lack of question mark (and will be
|
23
|
-
# autocorrected to `is_foo?`). If `ForbiddenPrefixes` contains `is_`,
|
24
|
-
# `is_foo` will register an offense both because the ? is missing and because of
|
25
|
-
# the `is_` prefix, and will be corrected to `foo?`.
|
26
|
-
#
|
27
|
-
# NOTE: `ForbiddenPrefixes` is only applied to prefixes in `NamePrefix`;
|
28
|
-
# a prefix in the former but not the latter will not be considered by
|
29
|
-
# this cop.
|
30
|
-
#
|
31
|
-
# @example
|
20
|
+
# @example NamePrefix: ['is_', 'has_', 'have_'] (default)
|
32
21
|
# # bad
|
33
22
|
# def is_even(value)
|
34
23
|
# end
|
35
24
|
#
|
36
|
-
#
|
25
|
+
# # When ForbiddenPrefixes: ['is_', 'has_', 'have_'] (default)
|
26
|
+
# # good
|
27
|
+
# def even?(value)
|
37
28
|
# end
|
38
29
|
#
|
30
|
+
# # When ForbiddenPrefixes: []
|
39
31
|
# # good
|
40
|
-
# def
|
32
|
+
# def is_even?(value)
|
41
33
|
# end
|
42
34
|
#
|
35
|
+
# @example NamePrefix: ['seems_to_be_']
|
43
36
|
# # bad
|
44
|
-
# def
|
37
|
+
# def seems_to_be_even(value)
|
45
38
|
# end
|
46
39
|
#
|
47
|
-
#
|
40
|
+
# # When ForbiddenPrefixes: ['seems_to_be_']
|
41
|
+
# # good
|
42
|
+
# def even?(value)
|
48
43
|
# end
|
49
44
|
#
|
45
|
+
# # When ForbiddenPrefixes: []
|
50
46
|
# # good
|
51
|
-
# def value
|
47
|
+
# def seems_to_be_even?(value)
|
52
48
|
# end
|
53
49
|
#
|
54
50
|
# @example AllowedMethods: ['is_a?'] (default)
|
51
|
+
# # Despite starting with the `is_` prefix, this method is allowed
|
55
52
|
# # good
|
56
53
|
# def is_a?(value)
|
57
54
|
# end
|
58
55
|
#
|
56
|
+
# @example AllowedMethods: ['is_even?']
|
57
|
+
# # good
|
58
|
+
# def is_even?(value)
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# @example MethodDefinitionMacros: ['define_method', 'define_singleton_method'] (default)
|
62
|
+
# # bad
|
63
|
+
# define_method(:is_even) { |value| }
|
64
|
+
#
|
65
|
+
# # good
|
66
|
+
# define_method(:even?) { |value| }
|
67
|
+
#
|
68
|
+
# @example MethodDefinitionMacros: ['def_node_matcher']
|
69
|
+
# # bad
|
70
|
+
# def_node_matcher(:is_even) { |value| }
|
71
|
+
#
|
72
|
+
# # good
|
73
|
+
# def_node_matcher(:even?) { |value| }
|
74
|
+
#
|
59
75
|
class PredicateName < Base
|
60
76
|
include AllowedMethods
|
61
77
|
|
@@ -93,6 +109,16 @@ module RuboCop
|
|
93
109
|
end
|
94
110
|
alias on_defs on_def
|
95
111
|
|
112
|
+
def validate_config
|
113
|
+
forbidden_prefixes.each do |forbidden_prefix|
|
114
|
+
next if predicate_prefixes.include?(forbidden_prefix)
|
115
|
+
|
116
|
+
raise ValidationError, <<~MSG.chomp
|
117
|
+
The `Naming/PredicateName` cop is misconfigured. Prefix #{forbidden_prefix} must be included in NamePrefix because it is included in ForbiddenPrefixes.
|
118
|
+
MSG
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
96
122
|
private
|
97
123
|
|
98
124
|
def allowed_method_name?(method_name, prefix)
|
@@ -113,13 +113,21 @@ module RuboCop
|
|
113
113
|
end
|
114
114
|
end
|
115
115
|
|
116
|
+
# rubocop:disable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
116
117
|
def correct_node(corrector, node, offending_name, preferred_name)
|
117
118
|
return unless node
|
118
119
|
|
119
120
|
node.each_node(:lvar, :lvasgn, :masgn) do |child_node|
|
120
121
|
next unless variable_name_matches?(child_node, offending_name)
|
121
122
|
|
122
|
-
|
123
|
+
if child_node.lvar_type?
|
124
|
+
parent_node = child_node.parent
|
125
|
+
if parent_node.respond_to?(:value_omission?) && parent_node.value_omission?
|
126
|
+
corrector.insert_after(parent_node.loc.operator, " #{preferred_name}")
|
127
|
+
else
|
128
|
+
corrector.replace(child_node, preferred_name)
|
129
|
+
end
|
130
|
+
end
|
123
131
|
|
124
132
|
if child_node.masgn_type? || child_node.lvasgn_type?
|
125
133
|
correct_reassignment(corrector, child_node, offending_name, preferred_name)
|
@@ -127,6 +135,7 @@ module RuboCop
|
|
127
135
|
end
|
128
136
|
end
|
129
137
|
end
|
138
|
+
# rubocop:enable Metrics/CyclomaticComplexity, Metrics/MethodLength, Metrics/PerceivedComplexity
|
130
139
|
|
131
140
|
# If the exception variable is reassigned, that assignment needs to be corrected.
|
132
141
|
# Further `lvar` nodes will not be corrected though since they now refer to a
|
@@ -334,13 +334,18 @@ module RuboCop
|
|
334
334
|
end
|
335
335
|
end
|
336
336
|
|
337
|
+
# rubocop:disable Metrics/AbcSize
|
337
338
|
def arguments_range(node, first_node)
|
338
|
-
arguments = node.arguments.reject
|
339
|
+
arguments = node.arguments.reject do |arg|
|
340
|
+
next true if ADDITIONAL_ARG_TYPES.include?(arg.type) || arg.variable? || arg.call_type?
|
339
341
|
|
340
|
-
|
342
|
+
arg.literal? && arg.each_descendant(:kwsplat).none?
|
343
|
+
end
|
341
344
|
|
342
|
-
|
345
|
+
start_node = first_node || arguments.first
|
346
|
+
start_node.source_range.begin.join(arguments.last.source_range.end)
|
343
347
|
end
|
348
|
+
# rubocop:enable Metrics/AbcSize
|
344
349
|
|
345
350
|
def allow_only_rest_arguments?
|
346
351
|
cop_config.fetch('AllowOnlyRestArgument', true)
|
@@ -143,7 +143,7 @@ module RuboCop
|
|
143
143
|
private
|
144
144
|
|
145
145
|
def check(node)
|
146
|
-
return if cop_config['AllowComments'] && comment_in_else?(node
|
146
|
+
return if cop_config['AllowComments'] && comment_in_else?(node)
|
147
147
|
|
148
148
|
empty_check(node) if empty_style?
|
149
149
|
nil_check(node) if nil_style?
|
@@ -171,16 +171,17 @@ module RuboCop
|
|
171
171
|
|
172
172
|
def autocorrect(corrector, node)
|
173
173
|
return false if autocorrect_forbidden?(node.type.to_s)
|
174
|
-
return false if comment_in_else?(node
|
174
|
+
return false if comment_in_else?(node)
|
175
175
|
|
176
176
|
end_pos = base_node(node).loc.end.begin_pos
|
177
177
|
corrector.remove(range_between(node.loc.else.begin_pos, end_pos))
|
178
178
|
end
|
179
179
|
|
180
|
-
def comment_in_else?(
|
181
|
-
|
180
|
+
def comment_in_else?(node)
|
181
|
+
node = node.parent while node.if_type? && node.elsif?
|
182
|
+
return false unless node.else?
|
182
183
|
|
183
|
-
processed_source.contains_comment?(loc.else.join(
|
184
|
+
processed_source.contains_comment?(node.loc.else.join(node.source_range.end))
|
184
185
|
end
|
185
186
|
|
186
187
|
def base_node(node)
|
@@ -36,6 +36,7 @@ module RuboCop
|
|
36
36
|
class EmptyHeredoc < Base
|
37
37
|
include Heredoc
|
38
38
|
include RangeHelp
|
39
|
+
include StringLiteralsHelp
|
39
40
|
extend AutoCorrector
|
40
41
|
|
41
42
|
MSG = 'Use an empty string literal instead of heredoc.'
|
@@ -53,20 +54,6 @@ module RuboCop
|
|
53
54
|
corrector.remove(range_by_whole_lines(heredoc_end, include_final_newline: true))
|
54
55
|
end
|
55
56
|
end
|
56
|
-
|
57
|
-
private
|
58
|
-
|
59
|
-
def preferred_string_literal
|
60
|
-
enforce_double_quotes? ? '""' : "''"
|
61
|
-
end
|
62
|
-
|
63
|
-
def enforce_double_quotes?
|
64
|
-
string_literals_config['EnforcedStyle'] == 'double_quotes'
|
65
|
-
end
|
66
|
-
|
67
|
-
def string_literals_config
|
68
|
-
config.for_cop('Style/StringLiterals')
|
69
|
-
end
|
70
57
|
end
|
71
58
|
end
|
72
59
|
end
|
@@ -9,7 +9,9 @@ module RuboCop
|
|
9
9
|
# @example
|
10
10
|
# # bad
|
11
11
|
# a = Array.new
|
12
|
+
# a = Array[]
|
12
13
|
# h = Hash.new
|
14
|
+
# h = Hash[]
|
13
15
|
# s = String.new
|
14
16
|
#
|
15
17
|
# # good
|
@@ -19,16 +21,17 @@ module RuboCop
|
|
19
21
|
class EmptyLiteral < Base
|
20
22
|
include FrozenStringLiteral
|
21
23
|
include RangeHelp
|
24
|
+
include StringLiteralsHelp
|
22
25
|
extend AutoCorrector
|
23
26
|
|
24
|
-
ARR_MSG = 'Use array literal `[]` instead of
|
25
|
-
HASH_MSG = 'Use hash literal `{}` instead of
|
27
|
+
ARR_MSG = 'Use array literal `[]` instead of `%<current>s`.'
|
28
|
+
HASH_MSG = 'Use hash literal `{}` instead of `%<current>s`.'
|
26
29
|
STR_MSG = 'Use string literal `%<prefer>s` instead of `String.new`.'
|
27
30
|
|
28
|
-
RESTRICT_ON_SEND = %i[new].freeze
|
31
|
+
RESTRICT_ON_SEND = %i[new [] Array Hash].freeze
|
29
32
|
|
30
33
|
# @!method array_node(node)
|
31
|
-
def_node_matcher :array_node, '(send (const {nil? cbase} :Array) :new)'
|
34
|
+
def_node_matcher :array_node, '(send (const {nil? cbase} :Array) :new (array)?)'
|
32
35
|
|
33
36
|
# @!method hash_node(node)
|
34
37
|
def_node_matcher :hash_node, '(send (const {nil? cbase} :Hash) :new)'
|
@@ -47,6 +50,22 @@ module RuboCop
|
|
47
50
|
}
|
48
51
|
PATTERN
|
49
52
|
|
53
|
+
# @!method array_with_index(node)
|
54
|
+
def_node_matcher :array_with_index, <<~PATTERN
|
55
|
+
{
|
56
|
+
(send (const {nil? cbase} :Array) :[])
|
57
|
+
(send nil? :Array (array))
|
58
|
+
}
|
59
|
+
PATTERN
|
60
|
+
|
61
|
+
# @!method hash_with_index(node)
|
62
|
+
def_node_matcher :hash_with_index, <<~PATTERN
|
63
|
+
{
|
64
|
+
(send (const {nil? cbase} :Hash) :[])
|
65
|
+
(send nil? :Hash (array))
|
66
|
+
}
|
67
|
+
PATTERN
|
68
|
+
|
50
69
|
def on_send(node)
|
51
70
|
return unless (message = offense_message(node))
|
52
71
|
|
@@ -59,26 +78,14 @@ module RuboCop
|
|
59
78
|
|
60
79
|
def offense_message(node)
|
61
80
|
if offense_array_node?(node)
|
62
|
-
ARR_MSG
|
81
|
+
format(ARR_MSG, current: node.source)
|
63
82
|
elsif offense_hash_node?(node)
|
64
|
-
HASH_MSG
|
83
|
+
format(HASH_MSG, current: node.source)
|
65
84
|
elsif str_node(node) && !frozen_strings?
|
66
85
|
format(STR_MSG, prefer: preferred_string_literal)
|
67
86
|
end
|
68
87
|
end
|
69
88
|
|
70
|
-
def preferred_string_literal
|
71
|
-
enforce_double_quotes? ? '""' : "''"
|
72
|
-
end
|
73
|
-
|
74
|
-
def enforce_double_quotes?
|
75
|
-
string_literals_config['EnforcedStyle'] == 'double_quotes'
|
76
|
-
end
|
77
|
-
|
78
|
-
def string_literals_config
|
79
|
-
config.for_cop('Style/StringLiterals')
|
80
|
-
end
|
81
|
-
|
82
89
|
def first_argument_unparenthesized?(node)
|
83
90
|
parent = node.parent
|
84
91
|
return false unless parent && %i[send super zsuper].include?(parent.type)
|
@@ -100,12 +107,12 @@ module RuboCop
|
|
100
107
|
end
|
101
108
|
|
102
109
|
def offense_array_node?(node)
|
103
|
-
array_node(node) && !array_with_block(node.parent)
|
110
|
+
(array_node(node) && !array_with_block(node.parent)) || array_with_index(node)
|
104
111
|
end
|
105
112
|
|
106
113
|
def offense_hash_node?(node)
|
107
114
|
# If Hash.new takes a block, it can't be changed to {}.
|
108
|
-
hash_node(node) && !hash_with_block(node.parent)
|
115
|
+
(hash_node(node) && !hash_with_block(node.parent)) || hash_with_index(node)
|
109
116
|
end
|
110
117
|
|
111
118
|
def correction(node)
|
@@ -129,8 +136,10 @@ module RuboCop
|
|
129
136
|
def frozen_strings?
|
130
137
|
return true if frozen_string_literals_enabled?
|
131
138
|
|
132
|
-
frozen_string_cop_enabled = config.for_cop('Style/
|
133
|
-
frozen_string_cop_enabled &&
|
139
|
+
frozen_string_cop_enabled = config.for_cop('Style/FrozenStringLiteralComment')['Enabled']
|
140
|
+
frozen_string_cop_enabled &&
|
141
|
+
!frozen_string_literals_disabled? &&
|
142
|
+
string_literals_frozen_by_default?.nil?
|
134
143
|
end
|
135
144
|
end
|
136
145
|
end
|
@@ -17,6 +17,18 @@ module RuboCop
|
|
17
17
|
# will not attempt to automatically add a binding, or add filename and
|
18
18
|
# line values.
|
19
19
|
#
|
20
|
+
# NOTE: This cop works only when a string literal is given as a code string.
|
21
|
+
# No offense is reported if a string variable is given as below:
|
22
|
+
#
|
23
|
+
# [source,ruby]
|
24
|
+
# ----
|
25
|
+
# code = <<-RUBY
|
26
|
+
# def do_something
|
27
|
+
# end
|
28
|
+
# RUBY
|
29
|
+
# eval code # not checked.
|
30
|
+
# ----
|
31
|
+
#
|
20
32
|
# @example
|
21
33
|
# # bad
|
22
34
|
# eval <<-RUBY
|
@@ -42,17 +54,6 @@ module RuboCop
|
|
42
54
|
# end
|
43
55
|
# RUBY
|
44
56
|
#
|
45
|
-
# This cop works only when a string literal is given as a code string.
|
46
|
-
# No offense is reported if a string variable is given as below:
|
47
|
-
#
|
48
|
-
# @example
|
49
|
-
# # not checked
|
50
|
-
# code = <<-RUBY
|
51
|
-
# def do_something
|
52
|
-
# end
|
53
|
-
# RUBY
|
54
|
-
# eval code
|
55
|
-
#
|
56
57
|
class EvalWithLocation < Base
|
57
58
|
extend AutoCorrector
|
58
59
|
|
@@ -6,8 +6,7 @@ module RuboCop
|
|
6
6
|
# Favor `File.(bin)read` convenience methods.
|
7
7
|
#
|
8
8
|
# @example
|
9
|
-
#
|
10
|
-
# # bad
|
9
|
+
# # bad - text mode
|
11
10
|
# File.open(filename).read
|
12
11
|
# File.open(filename, &:read)
|
13
12
|
# File.open(filename) { |f| f.read }
|
@@ -23,9 +22,7 @@ module RuboCop
|
|
23
22
|
# # good
|
24
23
|
# File.read(filename)
|
25
24
|
#
|
26
|
-
#
|
27
|
-
# ## binary mode
|
28
|
-
# # bad
|
25
|
+
# # bad - binary mode
|
29
26
|
# File.open(filename, 'rb').read
|
30
27
|
# File.open(filename, 'rb', &:read)
|
31
28
|
# File.open(filename, 'rb') do |f|
|
@@ -17,8 +17,7 @@ module RuboCop
|
|
17
17
|
# ----
|
18
18
|
#
|
19
19
|
# @example
|
20
|
-
#
|
21
|
-
# # bad
|
20
|
+
# # bad - text mode
|
22
21
|
# File.open(filename, 'w').write(content)
|
23
22
|
# File.open(filename, 'w') do |f|
|
24
23
|
# f.write(content)
|
@@ -27,9 +26,7 @@ module RuboCop
|
|
27
26
|
# # good
|
28
27
|
# File.write(filename, content)
|
29
28
|
#
|
30
|
-
#
|
31
|
-
# ## binary mode
|
32
|
-
# # bad
|
29
|
+
# # bad - binary mode
|
33
30
|
# File.open(filename, 'wb').write(content)
|
34
31
|
# File.open(filename, 'wb') do |f|
|
35
32
|
# f.write(content)
|
@@ -11,8 +11,8 @@ module RuboCop
|
|
11
11
|
# The reason is that _unannotated_ format is very similar
|
12
12
|
# to encoded URLs or Date/Time formatting strings.
|
13
13
|
#
|
14
|
-
# This cop can be customized
|
15
|
-
# By default, there are no methods
|
14
|
+
# This cop's allowed methods can be customized with `AllowedMethods`.
|
15
|
+
# By default, there are no allowed methods.
|
16
16
|
#
|
17
17
|
# @example EnforcedStyle: annotated (default)
|
18
18
|
#
|
@@ -44,7 +44,9 @@ module RuboCop
|
|
44
44
|
PATTERN
|
45
45
|
|
46
46
|
def on_const(node)
|
47
|
-
|
47
|
+
return if namespaced?(node)
|
48
|
+
|
49
|
+
const_name = node.short_name
|
48
50
|
return unless STD_STREAMS.include?(const_name)
|
49
51
|
|
50
52
|
gvar_name = gvar_name(const_name).to_sym
|
@@ -61,6 +63,10 @@ module RuboCop
|
|
61
63
|
format(MSG, gvar_name: gvar_name(const_name), const_name: const_name)
|
62
64
|
end
|
63
65
|
|
66
|
+
def namespaced?(node)
|
67
|
+
!node.namespace.nil? && (node.relative? || !node.namespace.cbase_type?)
|
68
|
+
end
|
69
|
+
|
64
70
|
def gvar_name(const_name)
|
65
71
|
"$#{const_name.to_s.downcase}"
|
66
72
|
end
|
@@ -155,7 +155,7 @@ module RuboCop
|
|
155
155
|
condition_variable = assignable_condition_value(node)
|
156
156
|
|
157
157
|
head = heads.first
|
158
|
-
if head.assignment?
|
158
|
+
if head.respond_to?(:assignment?) && head.assignment?
|
159
159
|
# The `send` node is used instead of the `indexasgn` node, so `name` cannot be used.
|
160
160
|
# https://github.com/rubocop/rubocop-ast/blob/v1.29.0/lib/rubocop/ast/node/indexasgn_node.rb
|
161
161
|
#
|