rubocop 0.46.0 → 0.47.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/LICENSE.txt +1 -1
- data/README.md +77 -2
- data/config/default.yml +151 -74
- data/config/disabled.yml +9 -0
- data/config/enabled.yml +49 -9
- data/lib/rubocop.rb +36 -8
- data/lib/rubocop/ast/builder.rb +59 -0
- data/lib/rubocop/ast/node.rb +607 -0
- data/lib/rubocop/ast/node/array_node.rb +45 -0
- data/lib/rubocop/ast/node/case_node.rb +63 -0
- data/lib/rubocop/ast/node/for_node.rb +53 -0
- data/lib/rubocop/ast/node/hash_node.rb +102 -0
- data/lib/rubocop/ast/node/if_node.rb +136 -0
- data/lib/rubocop/ast/node/keyword_splat_node.rb +45 -0
- data/lib/rubocop/ast/node/mixin/conditional_node.rb +45 -0
- data/lib/rubocop/ast/node/mixin/hash_element_node.rb +125 -0
- data/lib/rubocop/ast/node/mixin/modifier_node.rb +17 -0
- data/lib/rubocop/ast/node/pair_node.rb +64 -0
- data/lib/rubocop/ast/node/until_node.rb +43 -0
- data/lib/rubocop/ast/node/when_node.rb +61 -0
- data/lib/rubocop/ast/node/while_node.rb +43 -0
- data/lib/rubocop/ast/sexp.rb +16 -0
- data/lib/rubocop/{ast_node → ast}/traversal.rb +1 -1
- data/lib/rubocop/cli.rb +18 -14
- data/lib/rubocop/comment_config.rb +1 -3
- data/lib/rubocop/config.rb +93 -35
- data/lib/rubocop/config_loader.rb +1 -1
- data/lib/rubocop/cop/badge.rb +73 -0
- data/lib/rubocop/cop/bundler/duplicated_gem.rb +2 -2
- data/lib/rubocop/cop/bundler/ordered_gems.rb +43 -3
- data/lib/rubocop/cop/commissioner.rb +17 -6
- data/lib/rubocop/cop/cop.rb +25 -112
- data/lib/rubocop/cop/lint/ambiguous_operator.rb +9 -4
- data/lib/rubocop/cop/lint/ambiguous_regexp_literal.rb +7 -0
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +18 -4
- data/lib/rubocop/cop/lint/block_alignment.rb +40 -9
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +14 -0
- data/lib/rubocop/cop/lint/condition_position.rb +14 -16
- data/lib/rubocop/cop/lint/debugger.rb +28 -0
- data/lib/rubocop/cop/lint/def_end_alignment.rb +21 -1
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +13 -1
- data/lib/rubocop/cop/lint/duplicate_case_condition.rb +26 -22
- data/lib/rubocop/cop/lint/duplicate_methods.rb +15 -1
- data/lib/rubocop/cop/lint/duplicated_key.rb +16 -8
- data/lib/rubocop/cop/lint/each_with_object_argument.rb +9 -0
- data/lib/rubocop/cop/lint/else_layout.rb +26 -29
- data/lib/rubocop/cop/lint/empty_ensure.rb +38 -0
- data/lib/rubocop/cop/lint/empty_expression.rb +11 -1
- data/lib/rubocop/cop/lint/empty_interpolation.rb +8 -0
- data/lib/rubocop/cop/lint/empty_when.rb +14 -16
- data/lib/rubocop/cop/lint/end_alignment.rb +48 -28
- data/lib/rubocop/cop/lint/end_in_method.rb +23 -0
- data/lib/rubocop/cop/lint/ensure_return.rb +21 -0
- data/lib/rubocop/cop/lint/float_out_of_range.rb +5 -0
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +29 -4
- data/lib/rubocop/cop/lint/handle_exceptions.rb +40 -0
- data/lib/rubocop/cop/lint/implicit_string_concatenation.rb +7 -2
- data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +11 -2
- data/lib/rubocop/cop/lint/invalid_character_literal.rb +3 -0
- data/lib/rubocop/cop/lint/literal_in_condition.rb +34 -36
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +8 -0
- data/lib/rubocop/cop/lint/loop.rb +36 -0
- data/lib/rubocop/cop/lint/multiple_compare.rb +46 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +22 -0
- data/lib/rubocop/cop/lint/next_without_accumulator.rb +5 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +8 -0
- data/lib/rubocop/cop/lint/percent_string_array.rb +27 -13
- data/lib/rubocop/cop/lint/percent_symbol_array.rb +14 -4
- data/lib/rubocop/cop/lint/rand_one.rb +7 -3
- data/lib/rubocop/cop/lint/require_parentheses.rb +20 -19
- data/lib/rubocop/cop/lint/rescue_exception.rb +20 -0
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +66 -0
- data/lib/rubocop/cop/lint/shadowed_exception.rb +6 -1
- data/lib/rubocop/cop/lint/shadowing_outer_local_variable.rb +24 -0
- data/lib/rubocop/cop/lint/string_conversion_in_interpolation.rb +8 -0
- data/lib/rubocop/cop/lint/underscore_prefixed_variable_name.rb +24 -0
- data/lib/rubocop/cop/lint/unified_integer.rb +5 -0
- data/lib/rubocop/cop/lint/unneeded_disable.rb +2 -2
- data/lib/rubocop/cop/lint/unneeded_splat_expansion.rb +5 -0
- data/lib/rubocop/cop/lint/unreachable_code.rb +17 -0
- data/lib/rubocop/cop/lint/unused_block_argument.rb +2 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +10 -0
- data/lib/rubocop/cop/lint/useless_access_modifier.rb +28 -1
- data/lib/rubocop/cop/lint/useless_assignment.rb +18 -0
- data/lib/rubocop/cop/lint/useless_comparison.rb +3 -1
- data/lib/rubocop/cop/lint/useless_else_without_rescue.rb +16 -1
- data/lib/rubocop/cop/lint/useless_setter_call.rb +16 -4
- data/lib/rubocop/cop/lint/void.rb +52 -0
- data/lib/rubocop/cop/message_annotator.rb +102 -0
- data/lib/rubocop/cop/metrics/block_length.rb +6 -0
- data/lib/rubocop/cop/metrics/block_nesting.rb +17 -5
- data/lib/rubocop/cop/metrics/line_length.rb +11 -4
- data/lib/rubocop/cop/metrics/perceived_complexity.rb +1 -2
- data/lib/rubocop/cop/mixin/array_syntax.rb +2 -11
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +12 -5
- data/lib/rubocop/cop/mixin/configurable_formatting.rb +48 -0
- data/lib/rubocop/cop/mixin/configurable_max.rb +3 -3
- data/lib/rubocop/cop/mixin/configurable_naming.rb +5 -33
- data/lib/rubocop/cop/mixin/configurable_numbering.rb +6 -47
- data/lib/rubocop/cop/mixin/documentation_comment.rb +7 -1
- data/lib/rubocop/cop/mixin/duplication.rb +46 -0
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +2 -2
- data/lib/rubocop/cop/mixin/frozen_string_literal.rb +14 -11
- data/lib/rubocop/cop/mixin/hash_alignment.rb +114 -0
- data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -3
- data/lib/rubocop/cop/mixin/negative_conditional.rb +21 -7
- data/lib/rubocop/cop/mixin/on_method_def.rb +14 -0
- data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +1 -24
- data/lib/rubocop/cop/mixin/statement_modifier.rb +8 -13
- data/lib/rubocop/cop/mixin/target_ruby_version.rb +16 -0
- data/lib/rubocop/cop/mixin/trailing_comma.rb +2 -3
- data/lib/rubocop/cop/offense.rb +1 -1
- data/lib/rubocop/cop/performance/case_when_splat.rb +56 -59
- data/lib/rubocop/cop/performance/detect.rb +2 -2
- data/lib/rubocop/cop/performance/flat_map.rb +3 -3
- data/lib/rubocop/cop/performance/redundant_merge.rb +3 -6
- data/lib/rubocop/cop/performance/regexp_match.rb +201 -0
- data/lib/rubocop/cop/rails/delegate.rb +2 -2
- data/lib/rubocop/cop/rails/delegate_allow_blank.rb +10 -19
- data/lib/rubocop/cop/rails/enum_uniqueness.rb +12 -40
- data/lib/rubocop/cop/rails/file_path.rb +80 -0
- data/lib/rubocop/cop/rails/find_each.rb +5 -14
- data/lib/rubocop/cop/rails/http_positional_arguments.rb +30 -24
- data/lib/rubocop/cop/rails/not_null_column.rb +23 -0
- data/lib/rubocop/cop/rails/reversible_migration.rb +217 -0
- data/lib/rubocop/cop/rails/safe_navigation.rb +4 -2
- data/lib/rubocop/cop/rails/skips_model_validations.rb +46 -0
- data/lib/rubocop/cop/rails/time_zone.rb +1 -1
- data/lib/rubocop/cop/rails/uniq_before_pluck.rb +7 -5
- data/lib/rubocop/cop/registry.rb +170 -0
- data/lib/rubocop/cop/{lint → security}/eval.rb +7 -1
- data/lib/rubocop/cop/security/marshal_load.rb +33 -0
- data/lib/rubocop/cop/security/yaml_load.rb +37 -0
- data/lib/rubocop/cop/style/align_hash.rb +138 -169
- data/lib/rubocop/cop/style/and_or.rb +1 -1
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +10 -15
- data/lib/rubocop/cop/style/case_indentation.rb +36 -27
- data/lib/rubocop/cop/style/conditional_assignment.rb +64 -47
- data/lib/rubocop/cop/style/each_with_object.rb +4 -1
- data/lib/rubocop/cop/style/else_alignment.rb +14 -20
- data/lib/rubocop/cop/style/empty_case_condition.rb +16 -25
- data/lib/rubocop/cop/style/empty_else.rb +20 -22
- data/lib/rubocop/cop/style/empty_literal.rb +4 -4
- data/lib/rubocop/cop/style/empty_method.rb +12 -6
- data/lib/rubocop/cop/style/encoding.rb +1 -1
- data/lib/rubocop/cop/style/file_name.rb +24 -4
- data/lib/rubocop/cop/style/first_method_argument_line_break.rb +1 -1
- data/lib/rubocop/cop/style/format_string.rb +17 -48
- data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +40 -11
- data/lib/rubocop/cop/style/guard_clause.rb +11 -17
- data/lib/rubocop/cop/style/hash_syntax.rb +24 -42
- data/lib/rubocop/cop/style/identical_conditional_branches.rb +40 -28
- data/lib/rubocop/cop/style/if_inside_else.rb +6 -9
- data/lib/rubocop/cop/style/if_unless_modifier.rb +16 -25
- data/lib/rubocop/cop/style/if_unless_modifier_of_if_unless.rb +3 -9
- data/lib/rubocop/cop/style/indent_array.rb +1 -1
- data/lib/rubocop/cop/style/indentation_width.rb +29 -60
- data/lib/rubocop/cop/style/infinite_loop.rb +21 -22
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +86 -0
- data/lib/rubocop/cop/style/{method_call_parentheses.rb → method_call_without_args_parentheses.rb} +8 -1
- data/lib/rubocop/cop/style/missing_else.rb +40 -14
- data/lib/rubocop/cop/style/multiline_if_modifier.rb +5 -15
- data/lib/rubocop/cop/style/multiline_if_then.rb +14 -8
- data/lib/rubocop/cop/style/multiline_method_call_indentation.rb +3 -3
- data/lib/rubocop/cop/style/multiline_ternary_operator.rb +1 -5
- data/lib/rubocop/cop/style/mutable_constant.rb +3 -2
- data/lib/rubocop/cop/style/negated_if.rb +3 -19
- data/lib/rubocop/cop/style/negated_while.rb +2 -17
- data/lib/rubocop/cop/style/nested_modifier.rb +16 -43
- data/lib/rubocop/cop/style/nested_ternary_operator.rb +3 -5
- data/lib/rubocop/cop/style/next.rb +23 -21
- data/lib/rubocop/cop/style/non_nil_check.rb +2 -3
- data/lib/rubocop/cop/style/not.rb +1 -3
- data/lib/rubocop/cop/style/numeric_literals.rb +2 -2
- data/lib/rubocop/cop/style/one_line_conditional.rb +12 -22
- data/lib/rubocop/cop/style/option_hash.rb +4 -15
- data/lib/rubocop/cop/style/parallel_assignment.rb +1 -3
- data/lib/rubocop/cop/style/parentheses_around_condition.rb +8 -12
- data/lib/rubocop/cop/style/percent_q_literals.rb +15 -12
- data/lib/rubocop/cop/style/redundant_freeze.rb +3 -2
- data/lib/rubocop/cop/style/redundant_parentheses.rb +27 -4
- data/lib/rubocop/cop/style/redundant_return.rb +4 -8
- data/lib/rubocop/cop/style/safe_navigation.rb +13 -6
- data/lib/rubocop/cop/style/space_after_colon.rb +2 -4
- data/lib/rubocop/cop/style/space_around_block_parameters.rb +1 -1
- data/lib/rubocop/cop/style/space_around_operators.rb +15 -13
- data/lib/rubocop/cop/style/string_methods.rb +1 -3
- data/lib/rubocop/cop/style/symbol_array.rb +1 -5
- data/lib/rubocop/cop/style/ternary_parentheses.rb +5 -6
- data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +2 -5
- data/lib/rubocop/cop/style/trailing_comma_in_literal.rb +1 -1
- data/lib/rubocop/cop/style/unless_else.rb +1 -5
- data/lib/rubocop/cop/style/when_then.rb +4 -2
- data/lib/rubocop/cop/style/while_until_do.rb +9 -13
- data/lib/rubocop/cop/style/while_until_modifier.rb +12 -11
- data/lib/rubocop/cop/style/word_array.rb +5 -9
- data/lib/rubocop/cop/team.rb +16 -15
- data/lib/rubocop/cop/util.rb +13 -3
- data/lib/rubocop/formatter/clang_style_formatter.rb +2 -2
- data/lib/rubocop/formatter/disabled_config_formatter.rb +2 -1
- data/lib/rubocop/magic_comment.rb +196 -0
- data/lib/rubocop/options.rb +5 -4
- data/lib/rubocop/processed_source.rb +1 -1
- data/lib/rubocop/rspec/cop_helper.rb +9 -0
- data/lib/rubocop/rspec/shared_examples.rb +1 -1
- data/lib/rubocop/runner.rb +7 -2
- data/lib/rubocop/version.rb +1 -1
- metadata +41 -14
- data/lib/rubocop/ast_node.rb +0 -624
- data/lib/rubocop/ast_node/builder.rb +0 -30
- data/lib/rubocop/ast_node/sexp.rb +0 -13
- data/lib/rubocop/cop/mixin/hash_node.rb +0 -14
- data/lib/rubocop/cop/mixin/if_node.rb +0 -42
@@ -30,7 +30,7 @@ module RuboCop
|
|
30
30
|
end
|
31
31
|
return check_uri_line(line, index) if allow_uri?
|
32
32
|
|
33
|
-
|
33
|
+
register_offense(
|
34
34
|
source_range(processed_source.buffer, index + 1, 0...line.length),
|
35
35
|
line
|
36
36
|
)
|
@@ -41,7 +41,7 @@ module RuboCop
|
|
41
41
|
heredocs && line_in_whitelisted_heredoc?(heredocs, index.succ)
|
42
42
|
end
|
43
43
|
|
44
|
-
def
|
44
|
+
def register_offense(loc, line)
|
45
45
|
message = format(MSG, line.length, max)
|
46
46
|
add_offense(nil, loc, message) { self.max = line.length }
|
47
47
|
end
|
@@ -137,7 +137,14 @@ module RuboCop
|
|
137
137
|
return if line_length_without_directive(line) <= max
|
138
138
|
|
139
139
|
range = max..(line_length_without_directive(line) - 1)
|
140
|
-
|
140
|
+
register_offense(
|
141
|
+
source_range(
|
142
|
+
processed_source.buffer,
|
143
|
+
index + 1,
|
144
|
+
range
|
145
|
+
),
|
146
|
+
line
|
147
|
+
)
|
141
148
|
end
|
142
149
|
|
143
150
|
def directive_on_source_line?(index)
|
@@ -160,7 +167,7 @@ module RuboCop
|
|
160
167
|
uri_range = find_excessive_uri_range(line)
|
161
168
|
return if uri_range && allowed_uri_position?(line, uri_range)
|
162
169
|
|
163
|
-
|
170
|
+
register_offense(excess_range(uri_range, line, index), line)
|
164
171
|
end
|
165
172
|
end
|
166
173
|
end
|
@@ -28,7 +28,6 @@ module RuboCop
|
|
28
28
|
# end # 7 complexity points
|
29
29
|
class PerceivedComplexity < Cop
|
30
30
|
include MethodComplexity
|
31
|
-
include IfNode
|
32
31
|
|
33
32
|
MSG = 'Perceived complexity for %s is too high. [%d/%d]'.freeze
|
34
33
|
COUNTED_NODES = [:if, :case, :while, :until,
|
@@ -51,7 +50,7 @@ module RuboCop
|
|
51
50
|
(0.8 + 0.2 * whens.length).round
|
52
51
|
end
|
53
52
|
when :if
|
54
|
-
|
53
|
+
node.else? && !node.elsif? ? 2 : 1
|
55
54
|
else
|
56
55
|
1
|
57
56
|
end
|
@@ -6,18 +6,9 @@ module RuboCop
|
|
6
6
|
# syntax.
|
7
7
|
module ArraySyntax
|
8
8
|
def bracketed_array_of?(element_type, node)
|
9
|
-
return false unless square_brackets?
|
9
|
+
return false unless node.square_brackets? && node.values.size > 1
|
10
10
|
|
11
|
-
|
12
|
-
|
13
|
-
# no need to check empty arrays
|
14
|
-
return false unless array_elems && array_elems.size > 1
|
15
|
-
|
16
|
-
array_elems.all? { |e| e.type == element_type }
|
17
|
-
end
|
18
|
-
|
19
|
-
def square_brackets?(node)
|
20
|
-
node.loc.begin && node.loc.begin.is?('[')
|
11
|
+
node.values.all? { |value| value.type == element_type }
|
21
12
|
end
|
22
13
|
end
|
23
14
|
end
|
@@ -55,7 +55,7 @@ module RuboCop
|
|
55
55
|
return no_acceptable_style! if style.nil?
|
56
56
|
return no_acceptable_style! if style.empty?
|
57
57
|
|
58
|
-
config_to_allow_offenses[
|
58
|
+
config_to_allow_offenses[style_parameter_name] = style.first
|
59
59
|
end
|
60
60
|
|
61
61
|
alias conflicting_styles_detected no_acceptable_style!
|
@@ -63,7 +63,7 @@ module RuboCop
|
|
63
63
|
|
64
64
|
def style
|
65
65
|
@enforced_style ||= begin
|
66
|
-
s = cop_config[
|
66
|
+
s = cop_config[style_parameter_name].to_sym
|
67
67
|
unless supported_styles.include?(s)
|
68
68
|
raise "Unknown style #{s} selected!"
|
69
69
|
end
|
@@ -76,14 +76,21 @@ module RuboCop
|
|
76
76
|
raise 'alternative_style can only be used when there are exactly ' \
|
77
77
|
'2 SupportedStyles'
|
78
78
|
end
|
79
|
-
|
79
|
+
alternative_styles.first
|
80
|
+
end
|
81
|
+
|
82
|
+
def alternative_styles
|
83
|
+
(supported_styles - [style])
|
80
84
|
end
|
81
85
|
|
82
86
|
def supported_styles
|
83
|
-
@supported_styles ||=
|
87
|
+
@supported_styles ||= begin
|
88
|
+
supported_styles = Util.to_supported_styles(style_parameter_name)
|
89
|
+
cop_config[supported_styles].map(&:to_sym)
|
90
|
+
end
|
84
91
|
end
|
85
92
|
|
86
|
-
def
|
93
|
+
def style_parameter_name
|
87
94
|
'EnforcedStyle'
|
88
95
|
end
|
89
96
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Shared functionality between mixins that enforce naming conventions
|
6
|
+
module ConfigurableFormatting
|
7
|
+
include ConfigurableEnforcedStyle
|
8
|
+
|
9
|
+
def check_name(node, name, name_range)
|
10
|
+
return if operator?(name)
|
11
|
+
|
12
|
+
if valid_name?(node, name)
|
13
|
+
correct_style_detected
|
14
|
+
else
|
15
|
+
add_offense(node, name_range, message(style)) do
|
16
|
+
report_opposing_styles(node, name)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def report_opposing_styles(node, name)
|
22
|
+
alternative_styles.each do |alternative|
|
23
|
+
if valid_name?(node, name, alternative)
|
24
|
+
return unexpected_style_detected(alternative)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def valid_name?(node, name, given_style = style)
|
30
|
+
name.match(self.class::FORMATS.fetch(given_style)) ||
|
31
|
+
class_emitter_method?(node, name)
|
32
|
+
end
|
33
|
+
|
34
|
+
# A class emitter method is a singleton method in a class/module, where
|
35
|
+
# the method has the same name as a class defined in the class/module.
|
36
|
+
def class_emitter_method?(node, name)
|
37
|
+
return false unless node.parent && node.defs_type?
|
38
|
+
# a class emitter method may be defined inside `def self.included`,
|
39
|
+
# `def self.extended`, etc.
|
40
|
+
node = node.parent while node.parent.defs_type?
|
41
|
+
|
42
|
+
node.parent.each_child_node(:class).any? do |c|
|
43
|
+
c.loc.name.is?(name.to_s)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -7,11 +7,11 @@ module RuboCop
|
|
7
7
|
module ConfigurableMax
|
8
8
|
def max=(value)
|
9
9
|
cfg = config_to_allow_offenses
|
10
|
-
value = [cfg[
|
11
|
-
cfg[
|
10
|
+
value = [cfg[max_parameter_name], value].max if cfg[max_parameter_name]
|
11
|
+
cfg[max_parameter_name] = value
|
12
12
|
end
|
13
13
|
|
14
|
-
def
|
14
|
+
def max_parameter_name
|
15
15
|
'Max'
|
16
16
|
end
|
17
17
|
end
|
@@ -5,40 +5,12 @@ module RuboCop
|
|
5
5
|
# This module provides functionality for checking if names match the
|
6
6
|
# configured EnforcedStyle.
|
7
7
|
module ConfigurableNaming
|
8
|
-
include
|
8
|
+
include ConfigurableFormatting
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
return if operator?(name)
|
15
|
-
|
16
|
-
if valid_name?(node, name)
|
17
|
-
correct_style_detected
|
18
|
-
else
|
19
|
-
add_offense(node, name_range, message(style)) do
|
20
|
-
opposite_style_detected
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
def valid_name?(node, name)
|
26
|
-
pattern = (style == :snake_case ? SNAKE_CASE : CAMEL_CASE)
|
27
|
-
name.match(pattern) || class_emitter_method?(node, name)
|
28
|
-
end
|
29
|
-
|
30
|
-
# A class emitter method is a singleton method in a class/module, where
|
31
|
-
# the method has the same name as a class defined in the class/module.
|
32
|
-
def class_emitter_method?(node, name)
|
33
|
-
return false unless node.parent && node.defs_type?
|
34
|
-
# a class emitter method may be defined inside `def self.included`,
|
35
|
-
# `def self.extended`, etc.
|
36
|
-
node = node.parent while node.parent.defs_type?
|
37
|
-
|
38
|
-
node.parent.each_child_node(:class).any? do |c|
|
39
|
-
c.loc.name.is?(name.to_s)
|
40
|
-
end
|
41
|
-
end
|
10
|
+
FORMATS = {
|
11
|
+
snake_case: /^@{0,2}[\da-z_]+[!?=]?$/,
|
12
|
+
camelCase: /^@{0,2}_?[a-z][\da-zA-Z]+[!?=]?$/
|
13
|
+
}.freeze
|
42
14
|
end
|
43
15
|
end
|
44
16
|
end
|
@@ -5,54 +5,13 @@ module RuboCop
|
|
5
5
|
# This module provides functionality for checking if numbering match the
|
6
6
|
# configured EnforcedStyle.
|
7
7
|
module ConfigurableNumbering
|
8
|
-
include
|
8
|
+
include ConfigurableFormatting
|
9
9
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
return if operator?(name)
|
16
|
-
|
17
|
-
if valid_name?(node, name, style)
|
18
|
-
correct_style_detected
|
19
|
-
else
|
20
|
-
add_offense(node, name_range, message(style)) do
|
21
|
-
(supported_styles - [style]).each do |other_style|
|
22
|
-
if valid_name?(node, name, other_style)
|
23
|
-
unexpected_style_detected(other_style)
|
24
|
-
break
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
def valid_name?(node, name, given_style)
|
32
|
-
pattern =
|
33
|
-
case given_style
|
34
|
-
when :snake_case
|
35
|
-
SNAKE_CASE
|
36
|
-
when :normalcase
|
37
|
-
NORMAL_CASE
|
38
|
-
when :non_integer
|
39
|
-
NON_INTEGER
|
40
|
-
end
|
41
|
-
name.match(pattern) || class_emitter_method?(node, name)
|
42
|
-
end
|
43
|
-
|
44
|
-
# A class emitter method is a singleton method in a class/module, where
|
45
|
-
# the method has the same name as a class defined in the class/module.
|
46
|
-
def class_emitter_method?(node, name)
|
47
|
-
return false unless node.parent && node.defs_type?
|
48
|
-
# a class emitter method may be defined inside `def self.included`,
|
49
|
-
# `def self.extended`, etc.
|
50
|
-
node = node.parent while node.parent.defs_type?
|
51
|
-
|
52
|
-
node.parent.each_child_node(:class).any? do |c|
|
53
|
-
c.loc.name.is?(name.to_s)
|
54
|
-
end
|
55
|
-
end
|
10
|
+
FORMATS = {
|
11
|
+
snake_case: /(?:[a-z_]|_\d+)$/,
|
12
|
+
normalcase: /(?:_\D*|[A-Za-z]\d*)$/,
|
13
|
+
non_integer: /[A-Za-z_]$/
|
14
|
+
}.freeze
|
56
15
|
end
|
57
16
|
end
|
58
17
|
end
|
@@ -17,7 +17,9 @@ module RuboCop
|
|
17
17
|
return false unless preceding_comment?(node, preceding_lines.last)
|
18
18
|
|
19
19
|
preceding_lines.any? do |comment|
|
20
|
-
!annotation?(comment) &&
|
20
|
+
!annotation?(comment) &&
|
21
|
+
!interpreter_directive_comment?(comment) &&
|
22
|
+
!rubocop_directive_comment?(comment)
|
21
23
|
end
|
22
24
|
end
|
23
25
|
|
@@ -35,6 +37,10 @@ module RuboCop
|
|
35
37
|
def interpreter_directive_comment?(comment)
|
36
38
|
comment.text =~ /^#\s*(frozen_string_literal|encoding):/
|
37
39
|
end
|
40
|
+
|
41
|
+
def rubocop_directive_comment?(comment)
|
42
|
+
comment.text =~ CommentConfig::COMMENT_DIRECTIVE_REGEXP
|
43
|
+
end
|
38
44
|
end
|
39
45
|
end
|
40
46
|
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common functionality for dealing with duplication.
|
6
|
+
module Duplication
|
7
|
+
private
|
8
|
+
|
9
|
+
# Whether the `collection` contains any duplicates.
|
10
|
+
#
|
11
|
+
# @param [Array] collection an array to check for duplicates
|
12
|
+
# @return [Boolean] whether the array contains any duplicates
|
13
|
+
def duplicates?(collection)
|
14
|
+
collection.size > 1 && collection.size > collection.uniq.size
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns all duplicates, including the first instance of the duplicated
|
18
|
+
# elements.
|
19
|
+
#
|
20
|
+
# @param [Array] collection an array to return duplicates for
|
21
|
+
# @return [Array] all the duplicates
|
22
|
+
def duplicates(collection)
|
23
|
+
grouped_duplicates(collection).flatten
|
24
|
+
end
|
25
|
+
|
26
|
+
# Returns the consecutive duplicates, leaving out the first instance of
|
27
|
+
# the duplicated elements.
|
28
|
+
#
|
29
|
+
# @param [Array] collection an array to return consecutive duplicates for
|
30
|
+
# @return [Array] the consecutive duplicates
|
31
|
+
def consecutive_duplicates(collection)
|
32
|
+
grouped_duplicates(collection).flat_map { |items| items[1..-1] }
|
33
|
+
end
|
34
|
+
|
35
|
+
# Returns a hash of grouped duplicates. The key will be the first
|
36
|
+
# instance of the element, and the value an `array` of the initial
|
37
|
+
# element and all duplicate instances.
|
38
|
+
#
|
39
|
+
# @param [Array] collection an array to group duplicates for
|
40
|
+
# @return [Hash] the grouped duplicates
|
41
|
+
def grouped_duplicates(collection)
|
42
|
+
collection.group_by { |item| item }.values.reject(&:one?)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -10,24 +10,27 @@ module RuboCop
|
|
10
10
|
FROZEN_STRING_LITERAL_ENABLED = '# frozen_string_literal: true'.freeze
|
11
11
|
FROZEN_STRING_LITERAL_TYPES = [:str, :dstr].freeze
|
12
12
|
|
13
|
-
def frozen_string_literal_comment_exists?
|
14
|
-
|
15
|
-
|
16
|
-
[processed_source[0], processed_source[1], processed_source[2]]
|
17
|
-
first_three_lines.compact!
|
18
|
-
first_three_lines.any? do |line|
|
19
|
-
line.start_with?(comment)
|
13
|
+
def frozen_string_literal_comment_exists?
|
14
|
+
leading_comment_lines.any? do |line|
|
15
|
+
MagicComment.parse(line).frozen_string_literal_specified?
|
20
16
|
end
|
21
17
|
end
|
22
18
|
|
23
|
-
def frozen_string_literals_enabled?
|
19
|
+
def frozen_string_literals_enabled?
|
24
20
|
ruby_version = processed_source.ruby_version
|
25
21
|
return false unless ruby_version
|
26
22
|
return true if ruby_version >= 3.0
|
27
23
|
return false unless ruby_version >= 2.3
|
28
|
-
|
29
|
-
|
30
|
-
|
24
|
+
|
25
|
+
leading_comment_lines.any? do |line|
|
26
|
+
MagicComment.parse(line).frozen_string_literal?
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def leading_comment_lines
|
33
|
+
processed_source[0..2].compact
|
31
34
|
end
|
32
35
|
end
|
33
36
|
end
|
@@ -0,0 +1,114 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
# Common funcitonality for checking hash alignment.
|
6
|
+
module HashAlignment
|
7
|
+
# Handles calculation of deltas when the enforced style is 'key'.
|
8
|
+
class KeyAlignment
|
9
|
+
def checkable_layout?(_node)
|
10
|
+
true
|
11
|
+
end
|
12
|
+
|
13
|
+
def deltas_for_first_pair(*)
|
14
|
+
{}
|
15
|
+
end
|
16
|
+
|
17
|
+
def deltas(first_pair, current_pair)
|
18
|
+
if Util.begins_its_line?(current_pair.source_range)
|
19
|
+
{ key: first_pair.key_delta(current_pair) }
|
20
|
+
else
|
21
|
+
{}
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
# Common functionality for checking alignment of hash values.
|
27
|
+
module ValueAlignment
|
28
|
+
def checkable_layout?(node)
|
29
|
+
!node.pairs_on_same_line? && !node.mixed_delimiters?
|
30
|
+
end
|
31
|
+
|
32
|
+
def deltas(first_pair, current_pair)
|
33
|
+
key_delta = key_delta(first_pair, current_pair)
|
34
|
+
separator_delta = separator_delta(first_pair, current_pair,
|
35
|
+
key_delta)
|
36
|
+
value_delta = value_delta(first_pair, current_pair) -
|
37
|
+
key_delta - separator_delta
|
38
|
+
|
39
|
+
{ key: key_delta, separator: separator_delta, value: value_delta }
|
40
|
+
end
|
41
|
+
|
42
|
+
private
|
43
|
+
|
44
|
+
def separator_delta(first_pair, current_pair, key_delta)
|
45
|
+
if current_pair.colon?
|
46
|
+
0
|
47
|
+
else
|
48
|
+
hash_rocket_delta(first_pair, current_pair) - key_delta
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# Handles calculation of deltas when the enforced style is 'table'.
|
54
|
+
class TableAlignment
|
55
|
+
include ValueAlignment
|
56
|
+
|
57
|
+
# The table style is the only one where the first key-value pair can
|
58
|
+
# be considered to have bad alignment.
|
59
|
+
def deltas_for_first_pair(first_pair, node)
|
60
|
+
self.max_key_width = node.keys.map { |key| key.source.length }.max
|
61
|
+
|
62
|
+
separator_delta = separator_delta(first_pair, first_pair, 0)
|
63
|
+
{
|
64
|
+
separator: separator_delta,
|
65
|
+
value: value_delta(first_pair, first_pair) - separator_delta
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
attr_accessor :max_key_width
|
72
|
+
|
73
|
+
def key_delta(first_pair, current_pair)
|
74
|
+
first_pair.key_delta(current_pair)
|
75
|
+
end
|
76
|
+
|
77
|
+
def hash_rocket_delta(first_pair, current_pair)
|
78
|
+
first_pair.loc.column + max_key_width + 1 -
|
79
|
+
current_pair.loc.operator.column
|
80
|
+
end
|
81
|
+
|
82
|
+
def value_delta(first_pair, current_pair)
|
83
|
+
correct_value_column = first_pair.key.loc.column +
|
84
|
+
current_pair.delimiter(true).length +
|
85
|
+
max_key_width
|
86
|
+
correct_value_column - current_pair.value.loc.column
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
# Handles calculation of deltas when the enforced style is 'separator'.
|
91
|
+
class SeparatorAlignment
|
92
|
+
include ValueAlignment
|
93
|
+
|
94
|
+
def deltas_for_first_pair(*)
|
95
|
+
{}
|
96
|
+
end
|
97
|
+
|
98
|
+
private
|
99
|
+
|
100
|
+
def key_delta(first_pair, current_pair)
|
101
|
+
first_pair.key_delta(current_pair, :right)
|
102
|
+
end
|
103
|
+
|
104
|
+
def hash_rocket_delta(first_pair, current_pair)
|
105
|
+
first_pair.delimiter_delta(current_pair)
|
106
|
+
end
|
107
|
+
|
108
|
+
def value_delta(first_pair, current_pair)
|
109
|
+
first_pair.value_delta(current_pair)
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|