rubocop 1.65.0 → 1.66.1
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 +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
|
#
|