rubocop 0.31.0 → 0.35.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/CHANGELOG.md +315 -0
- data/README.md +199 -38
- data/config/default.yml +91 -12
- data/config/disabled.yml +45 -4
- data/config/enabled.yml +107 -9
- data/lib/rubocop/ast_node.rb +48 -0
- data/lib/rubocop/cli.rb +11 -1
- data/lib/rubocop/comment_config.rb +4 -1
- data/lib/rubocop/config.rb +26 -17
- data/lib/rubocop/config_loader.rb +61 -14
- data/lib/rubocop/cop/commissioner.rb +7 -12
- data/lib/rubocop/cop/cop.rb +43 -20
- data/lib/rubocop/cop/lint/block_alignment.rb +1 -1
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +69 -0
- data/lib/rubocop/cop/lint/debugger.rb +9 -48
- data/lib/rubocop/cop/lint/def_end_alignment.rb +8 -4
- data/lib/rubocop/cop/lint/deprecated_class_methods.rb +42 -23
- data/lib/rubocop/cop/lint/duplicate_methods.rb +2 -2
- data/lib/rubocop/cop/lint/duplicated_key.rb +37 -0
- data/lib/rubocop/cop/lint/end_alignment.rb +33 -13
- data/lib/rubocop/cop/lint/eval.rb +6 -2
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +175 -0
- data/lib/rubocop/cop/lint/literal_in_condition.rb +0 -5
- data/lib/rubocop/cop/lint/literal_in_interpolation.rb +10 -0
- data/lib/rubocop/cop/lint/nested_method_definition.rb +31 -0
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +19 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/lint/unneeded_disable.rb +72 -0
- data/lib/rubocop/cop/lint/unused_block_argument.rb +6 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +8 -0
- data/lib/rubocop/cop/metrics/abc_size.rb +17 -6
- data/lib/rubocop/cop/metrics/class_length.rb +1 -1
- data/lib/rubocop/cop/metrics/method_length.rb +1 -3
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/parameter_lists.rb +1 -1
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +1 -1
- data/lib/rubocop/cop/mixin/annotation_comment.rb +1 -2
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +28 -4
- data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +26 -3
- data/lib/rubocop/cop/mixin/check_assignment.rb +2 -3
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +59 -12
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_naming.rb +14 -3
- data/lib/rubocop/cop/mixin/empty_lines_around_body.rb +1 -3
- data/lib/rubocop/cop/mixin/end_keyword_alignment.rb +10 -1
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +41 -0
- data/lib/rubocop/cop/mixin/if_node.rb +10 -0
- data/lib/rubocop/cop/mixin/method_preference.rb +28 -0
- data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -1
- data/lib/rubocop/cop/mixin/on_method_def.rb +4 -5
- data/lib/rubocop/cop/mixin/safe_assignment.rb +3 -14
- data/lib/rubocop/cop/mixin/space_after_punctuation.rb +8 -1
- data/lib/rubocop/cop/mixin/space_before_punctuation.rb +8 -1
- data/lib/rubocop/cop/mixin/statement_modifier.rb +4 -7
- data/lib/rubocop/cop/mixin/string_help.rb +1 -1
- data/lib/rubocop/cop/mixin/string_literals_help.rb +1 -1
- data/lib/rubocop/cop/mixin/surrounding_space.rb +5 -4
- data/lib/rubocop/cop/offense.rb +16 -3
- data/lib/rubocop/cop/performance/case_when_splat.rb +160 -0
- data/lib/rubocop/cop/performance/count.rb +35 -30
- data/lib/rubocop/cop/performance/detect.rb +16 -3
- data/lib/rubocop/cop/performance/fixed_size.rb +50 -0
- data/lib/rubocop/cop/performance/flat_map.rb +3 -3
- data/lib/rubocop/cop/performance/sample.rb +103 -59
- data/lib/rubocop/cop/performance/size.rb +2 -1
- data/lib/rubocop/cop/performance/string_replacement.rb +187 -0
- data/lib/rubocop/cop/rails/action_filter.rb +31 -5
- data/lib/rubocop/cop/rails/date.rb +15 -14
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +97 -0
- data/lib/rubocop/cop/rails/read_write_attribute.rb +1 -1
- data/lib/rubocop/cop/rails/time_zone.rb +46 -18
- data/lib/rubocop/cop/style/alias.rb +1 -0
- data/lib/rubocop/cop/style/align_hash.rb +8 -15
- data/lib/rubocop/cop/style/align_parameters.rb +19 -7
- data/lib/rubocop/cop/style/and_or.rb +42 -13
- data/lib/rubocop/cop/style/auto_resource_cleanup.rb +2 -1
- data/lib/rubocop/cop/style/block_comments.rb +4 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +69 -24
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +40 -12
- data/lib/rubocop/cop/style/case_indentation.rb +18 -4
- data/lib/rubocop/cop/style/collection_methods.rb +2 -20
- data/lib/rubocop/cop/style/command_literal.rb +2 -10
- data/lib/rubocop/cop/style/comment_annotation.rb +29 -8
- data/lib/rubocop/cop/style/copyright.rb +5 -3
- data/lib/rubocop/cop/style/documentation.rb +21 -12
- data/lib/rubocop/cop/style/dot_position.rb +6 -0
- data/lib/rubocop/cop/style/double_negation.rb +4 -15
- data/lib/rubocop/cop/style/each_with_object.rb +17 -4
- data/lib/rubocop/cop/style/else_alignment.rb +2 -1
- data/lib/rubocop/cop/style/empty_else.rb +25 -0
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +39 -14
- data/lib/rubocop/cop/style/encoding.rb +10 -4
- data/lib/rubocop/cop/style/extra_spacing.rb +126 -5
- data/lib/rubocop/cop/style/first_array_element_line_break.rb +41 -0
- data/lib/rubocop/cop/style/first_hash_element_line_break.rb +35 -0
- data/lib/rubocop/cop/style/first_method_argument_line_break.rb +37 -0
- data/lib/rubocop/cop/style/first_method_parameter_line_break.rb +42 -0
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +5 -3
- data/lib/rubocop/cop/style/for.rb +2 -1
- data/lib/rubocop/cop/style/hash_syntax.rb +5 -0
- data/lib/rubocop/cop/style/if_unless_modifier.rb +32 -5
- data/lib/rubocop/cop/style/indent_hash.rb +67 -37
- data/lib/rubocop/cop/style/indentation_width.rb +36 -10
- data/lib/rubocop/cop/style/initial_indentation.rb +37 -0
- data/lib/rubocop/cop/style/leading_comment_space.rb +3 -2
- data/lib/rubocop/cop/style/method_call_parentheses.rb +28 -1
- data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -7
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +21 -24
- data/lib/rubocop/cop/style/mutable_constant.rb +35 -0
- data/lib/rubocop/cop/style/nested_modifier.rb +97 -0
- data/lib/rubocop/cop/style/next.rb +50 -15
- data/lib/rubocop/cop/style/non_nil_check.rb +12 -8
- data/lib/rubocop/cop/style/one_line_conditional.rb +8 -4
- data/lib/rubocop/cop/style/option_hash.rb +64 -0
- data/lib/rubocop/cop/style/optional_arguments.rb +49 -0
- data/lib/rubocop/cop/style/parallel_assignment.rb +218 -0
- data/lib/rubocop/cop/style/percent_literal_delimiters.rb +3 -66
- data/lib/rubocop/cop/style/predicate_name.rb +7 -2
- data/lib/rubocop/cop/style/redundant_begin.rb +2 -13
- data/lib/rubocop/cop/style/redundant_freeze.rb +37 -0
- data/lib/rubocop/cop/style/redundant_return.rb +32 -3
- data/lib/rubocop/cop/style/regexp_literal.rb +2 -10
- data/lib/rubocop/cop/style/rescue_ensure_alignment.rb +81 -0
- data/lib/rubocop/cop/style/rescue_modifier.rb +30 -22
- data/lib/rubocop/cop/style/send.rb +18 -0
- data/lib/rubocop/cop/style/signal_exception.rb +24 -11
- data/lib/rubocop/cop/style/single_line_methods.rb +8 -9
- data/lib/rubocop/cop/style/single_space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/style/space_around_operators.rb +2 -0
- data/lib/rubocop/cop/style/space_inside_string_interpolation.rb +61 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +4 -2
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +108 -0
- data/lib/rubocop/cop/style/string_methods.rb +32 -0
- data/lib/rubocop/cop/style/struct_inheritance.rb +11 -10
- data/lib/rubocop/cop/style/symbol_literal.rb +1 -1
- data/lib/rubocop/cop/style/symbol_proc.rb +62 -13
- data/lib/rubocop/cop/style/trailing_blank_lines.rb +9 -1
- data/lib/rubocop/cop/style/trailing_comma.rb +17 -7
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -2
- data/lib/rubocop/cop/style/trivial_accessors.rb +10 -1
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +31 -20
- data/lib/rubocop/cop/style/variable_name.rb +5 -0
- data/lib/rubocop/cop/style/while_until_do.rb +1 -1
- data/lib/rubocop/cop/style/word_array.rb +15 -2
- data/lib/rubocop/cop/team.rb +25 -5
- data/lib/rubocop/cop/util.rb +7 -2
- data/lib/rubocop/cop/variable_force/locatable.rb +6 -6
- data/lib/rubocop/cop/variable_force.rb +10 -10
- data/lib/rubocop/formatter/base_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +70 -8
- data/lib/rubocop/formatter/formatter_set.rb +27 -1
- data/lib/rubocop/formatter/progress_formatter.rb +10 -2
- data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
- data/lib/rubocop/node_pattern.rb +390 -0
- data/lib/rubocop/options.rb +148 -81
- data/lib/rubocop/processed_source.rb +7 -2
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +60 -0
- data/lib/rubocop/result_cache.rb +123 -0
- data/lib/rubocop/runner.rb +85 -22
- data/lib/rubocop/target_finder.rb +4 -4
- data/lib/rubocop/token.rb +2 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/warning.rb +11 -0
- data/lib/rubocop.rb +32 -3
- data/relnotes/v0.32.0.md +139 -0
- data/relnotes/v0.32.1.md +122 -0
- data/relnotes/v0.33.0.md +157 -0
- data/relnotes/v0.34.0.md +182 -0
- data/relnotes/v0.34.1.md +129 -0
- data/relnotes/v0.34.2.md +139 -0
- data/relnotes/v0.35.0.md +210 -0
- data/rubocop.gemspec +4 -4
- metadata +50 -12
- data/lib/rubocop/cop/performance/parallel_assignment.rb +0 -79
|
@@ -17,23 +17,31 @@ module RuboCop
|
|
|
17
17
|
PROC_NODE = s(:send, s(:const, nil, :Proc), :new)
|
|
18
18
|
|
|
19
19
|
def on_block(node)
|
|
20
|
-
|
|
20
|
+
block_send_or_super, block_args, block_body = *node
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
if super?(block_send_or_super)
|
|
23
|
+
bmethod_name = :super
|
|
24
|
+
else
|
|
25
|
+
_breceiver, bmethod_name, _bargs = *block_send_or_super
|
|
26
|
+
end
|
|
23
27
|
|
|
24
28
|
# TODO: Rails-specific handling that we should probably make
|
|
25
29
|
# configurable - https://github.com/bbatsov/rubocop/issues/1485
|
|
26
30
|
# we should ignore lambdas & procs
|
|
27
|
-
return if
|
|
31
|
+
return if block_send_or_super == PROC_NODE
|
|
28
32
|
return if [:lambda, :proc].include?(bmethod_name)
|
|
29
33
|
return if ignored_method?(bmethod_name)
|
|
30
|
-
# File.open(file) { |f| f.readlines }
|
|
31
|
-
return if bargs
|
|
32
34
|
return unless can_shorten?(block_args, block_body)
|
|
33
35
|
|
|
34
36
|
_receiver, method_name, _args = *block_body
|
|
37
|
+
|
|
38
|
+
sb = node.loc.expression.source_buffer
|
|
39
|
+
block_start = node.loc.begin.begin_pos
|
|
40
|
+
block_end = node.loc.end.end_pos
|
|
41
|
+
range = Parser::Source::Range.new(sb, block_start, block_end)
|
|
42
|
+
|
|
35
43
|
add_offense(node,
|
|
36
|
-
|
|
44
|
+
range,
|
|
37
45
|
format(MSG,
|
|
38
46
|
method_name,
|
|
39
47
|
bmethod_name))
|
|
@@ -41,16 +49,52 @@ module RuboCop
|
|
|
41
49
|
|
|
42
50
|
def autocorrect(node)
|
|
43
51
|
lambda do |corrector|
|
|
44
|
-
|
|
52
|
+
block_send_or_super, _block_args, block_body = *node
|
|
45
53
|
_receiver, method_name, _args = *block_body
|
|
46
54
|
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
55
|
+
if super?(block_send_or_super)
|
|
56
|
+
args = *block_send_or_super
|
|
57
|
+
autocorrect_method(corrector, node, args, method_name)
|
|
58
|
+
else
|
|
59
|
+
_breceiver, _bmethod_name, *args = *block_send_or_super
|
|
60
|
+
autocorrect_method(corrector, node, args, method_name)
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
end
|
|
51
64
|
|
|
52
|
-
|
|
53
|
-
|
|
65
|
+
def autocorrect_method(corrector, node, args, method_name)
|
|
66
|
+
if args.empty?
|
|
67
|
+
autocorrect_no_args(corrector, node, method_name)
|
|
68
|
+
else
|
|
69
|
+
autocorrect_with_args(corrector, node, args, method_name)
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def autocorrect_no_args(corrector, node, method_name)
|
|
74
|
+
corrector.replace(block_range_with_space(node), "(&:#{method_name})")
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def autocorrect_with_args(corrector, node, args, method_name)
|
|
78
|
+
corrector.insert_after(args.last.loc.expression, ", &:#{method_name}")
|
|
79
|
+
corrector.remove(block_range_with_space(node))
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def block_range_with_space(node)
|
|
83
|
+
block_range =
|
|
84
|
+
Parser::Source::Range.new(node.loc.expression.source_buffer,
|
|
85
|
+
begin_pos_for_replacement(node),
|
|
86
|
+
node.loc.end.end_pos)
|
|
87
|
+
range_with_surrounding_space(block_range, :left)
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def begin_pos_for_replacement(node)
|
|
91
|
+
block_send_or_super, _block_args, _block_body = *node
|
|
92
|
+
expr = block_send_or_super.loc.expression
|
|
93
|
+
|
|
94
|
+
if (paren_pos = (expr.source =~ /\(\s*\)$/))
|
|
95
|
+
expr.begin_pos + paren_pos
|
|
96
|
+
else
|
|
97
|
+
node.loc.begin.begin_pos
|
|
54
98
|
end
|
|
55
99
|
end
|
|
56
100
|
|
|
@@ -65,6 +109,7 @@ module RuboCop
|
|
|
65
109
|
def can_shorten?(block_args, block_body)
|
|
66
110
|
# something { |x, y| ... }
|
|
67
111
|
return false unless block_args.children.size == 1
|
|
112
|
+
return false if block_args.children.first.blockarg_type?
|
|
68
113
|
return false unless block_body && block_body.type == :send
|
|
69
114
|
|
|
70
115
|
receiver, _method_name, args = *block_body
|
|
@@ -78,6 +123,10 @@ module RuboCop
|
|
|
78
123
|
|
|
79
124
|
block_arg_name == receiver_name
|
|
80
125
|
end
|
|
126
|
+
|
|
127
|
+
def super?(node)
|
|
128
|
+
[:super, :zsuper].include?(node.type)
|
|
129
|
+
end
|
|
81
130
|
end
|
|
82
131
|
end
|
|
83
132
|
end
|
|
@@ -24,10 +24,18 @@ module RuboCop
|
|
|
24
24
|
|
|
25
25
|
return unless blank_lines != wanted_blank_lines
|
|
26
26
|
|
|
27
|
+
offense_detected(sb, wanted_blank_lines, blank_lines,
|
|
28
|
+
whitespace_at_end)
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
private
|
|
32
|
+
|
|
33
|
+
def offense_detected(sb, wanted_blank_lines, blank_lines,
|
|
34
|
+
whitespace_at_end)
|
|
27
35
|
begin_pos = sb.source.length - whitespace_at_end.length
|
|
28
36
|
autocorrect_range = Parser::Source::Range.new(sb, begin_pos,
|
|
29
37
|
sb.source.length)
|
|
30
|
-
begin_pos +=
|
|
38
|
+
begin_pos += 1 unless whitespace_at_end.length == 0
|
|
31
39
|
report_range = Parser::Source::Range.new(sb, begin_pos,
|
|
32
40
|
sb.source.length)
|
|
33
41
|
add_offense(autocorrect_range, report_range,
|
|
@@ -68,18 +68,17 @@ module RuboCop
|
|
|
68
68
|
node.loc.end.begin_pos)
|
|
69
69
|
end
|
|
70
70
|
|
|
71
|
-
# rubocop:disable Metrics/MethodLength
|
|
72
71
|
def check(node, items, kind, begin_pos, end_pos)
|
|
73
72
|
sb = items.first.loc.expression.source_buffer
|
|
73
|
+
|
|
74
74
|
after_last_item = Parser::Source::Range.new(sb, begin_pos, end_pos)
|
|
75
75
|
|
|
76
76
|
return if heredoc?(after_last_item.source)
|
|
77
77
|
|
|
78
78
|
comma_offset = after_last_item.source =~ /,/
|
|
79
|
-
|
|
80
|
-
[:comma, :consistent_comma].include?(style) && multiline?(node)
|
|
79
|
+
|
|
81
80
|
if comma_offset && !inside_comment?(after_last_item, comma_offset)
|
|
82
|
-
unless should_have_comma
|
|
81
|
+
unless should_have_comma?(style, node, items)
|
|
83
82
|
extra_info = case style
|
|
84
83
|
when :comma
|
|
85
84
|
', unless each item is on its own line'
|
|
@@ -91,11 +90,16 @@ module RuboCop
|
|
|
91
90
|
avoid_comma(kind, after_last_item.begin_pos + comma_offset, sb,
|
|
92
91
|
extra_info)
|
|
93
92
|
end
|
|
94
|
-
elsif should_have_comma
|
|
93
|
+
elsif should_have_comma?(style, node, items)
|
|
95
94
|
put_comma(items, kind, sb)
|
|
96
95
|
end
|
|
97
96
|
end
|
|
98
|
-
|
|
97
|
+
|
|
98
|
+
def should_have_comma?(style, node, items)
|
|
99
|
+
[:comma, :consistent_comma].include?(style) &&
|
|
100
|
+
multiline?(node) &&
|
|
101
|
+
(items.size > 1 || items.last.hash_type?)
|
|
102
|
+
end
|
|
99
103
|
|
|
100
104
|
def inside_comment?(range, comma_offset)
|
|
101
105
|
processed_source.comments.any? do |comment|
|
|
@@ -119,10 +123,16 @@ module RuboCop
|
|
|
119
123
|
def multiline?(node)
|
|
120
124
|
elements = if node.type == :send
|
|
121
125
|
_receiver, _method_name, *args = *node
|
|
122
|
-
args
|
|
126
|
+
args.flat_map { |a| a.type == :hash ? a.children : a }
|
|
123
127
|
else
|
|
124
128
|
node.children
|
|
125
129
|
end
|
|
130
|
+
|
|
131
|
+
# Without this check, Foo.new({}) is considered multiline, which
|
|
132
|
+
# it should not be. Essentially, if there are no elements, the
|
|
133
|
+
# expression can not be multiline.
|
|
134
|
+
return if elements.empty?
|
|
135
|
+
|
|
126
136
|
items = elements.map { |e| e.loc.expression }
|
|
127
137
|
if style == :consistent_comma
|
|
128
138
|
items.each_cons(2).any? { |a, b| !on_same_line?(a, b) }
|
|
@@ -15,10 +15,13 @@ module RuboCop
|
|
|
15
15
|
# #good
|
|
16
16
|
# a, b, = foo()
|
|
17
17
|
# a, = foo()
|
|
18
|
+
# *a, b, _ = foo() => We need to know to not include 2 variables in a
|
|
19
|
+
# a, *b, _ = foo() => The correction `a, *b, = foo()` is a syntax error
|
|
18
20
|
class TrailingUnderscoreVariable < Cop
|
|
19
21
|
include SurroundingSpace
|
|
20
22
|
|
|
21
|
-
MSG = 'Do not use trailing `_`s in parallel assignment.'
|
|
23
|
+
MSG = 'Do not use trailing `_`s in parallel assignment.'.freeze
|
|
24
|
+
UNDERSCORE = '_'.freeze
|
|
22
25
|
|
|
23
26
|
def on_masgn(node)
|
|
24
27
|
left, = *node
|
|
@@ -60,12 +63,30 @@ module RuboCop
|
|
|
60
63
|
first_offense = nil
|
|
61
64
|
|
|
62
65
|
variables.reverse_each do |variable|
|
|
63
|
-
|
|
66
|
+
var, = *variable
|
|
67
|
+
var, = *var
|
|
68
|
+
if allow_named_underscore_variables
|
|
69
|
+
break unless var == :_
|
|
70
|
+
else
|
|
71
|
+
break unless var.to_s.start_with?(UNDERSCORE)
|
|
72
|
+
end
|
|
64
73
|
first_offense = variable
|
|
65
74
|
end
|
|
66
75
|
|
|
76
|
+
return nil if first_offense.nil?
|
|
77
|
+
|
|
78
|
+
first_offense_index = variables.index(first_offense)
|
|
79
|
+
0.upto(first_offense_index - 1).each do |index|
|
|
80
|
+
return nil if variables[index].splat_type?
|
|
81
|
+
end
|
|
82
|
+
|
|
67
83
|
first_offense
|
|
68
84
|
end
|
|
85
|
+
|
|
86
|
+
def allow_named_underscore_variables
|
|
87
|
+
@allow_named_underscore_variables ||=
|
|
88
|
+
cop_config['AllowNamedUnderscoreVariables']
|
|
89
|
+
end
|
|
69
90
|
end
|
|
70
91
|
end
|
|
71
92
|
end
|
|
@@ -9,11 +9,13 @@ module RuboCop
|
|
|
9
9
|
MSG = 'Use `attr_%s` to define trivial %s methods.'
|
|
10
10
|
|
|
11
11
|
def on_def(node)
|
|
12
|
+
return if in_module?(node)
|
|
12
13
|
method_name, args, body = *node
|
|
13
14
|
on_method_def(node, method_name, args, body)
|
|
14
15
|
end
|
|
15
16
|
|
|
16
17
|
def on_defs(node)
|
|
18
|
+
return if in_module?(node)
|
|
17
19
|
return if ignore_class_methods?
|
|
18
20
|
_scope, method_name, args, body = *node
|
|
19
21
|
on_method_def(node, method_name, args, body)
|
|
@@ -21,6 +23,12 @@ module RuboCop
|
|
|
21
23
|
|
|
22
24
|
private
|
|
23
25
|
|
|
26
|
+
def in_module?(node)
|
|
27
|
+
pnode = node.parent
|
|
28
|
+
pnode = pnode.parent if pnode && pnode.type == :begin
|
|
29
|
+
!pnode.nil? && pnode.type == :module
|
|
30
|
+
end
|
|
31
|
+
|
|
24
32
|
def on_method_def(node, method_name, args, body)
|
|
25
33
|
kind = if trivial_reader?(method_name, args, body)
|
|
26
34
|
'reader'
|
|
@@ -100,7 +108,7 @@ module RuboCop
|
|
|
100
108
|
def names_match?(method_name, body)
|
|
101
109
|
ivar_name, = *body
|
|
102
110
|
|
|
103
|
-
method_name.to_s.
|
|
111
|
+
method_name.to_s.sub(/[=?]$/, '') == ivar_name[1..-1]
|
|
104
112
|
end
|
|
105
113
|
|
|
106
114
|
def trivial_accessor_kind(method_name, args, body)
|
|
@@ -127,6 +135,7 @@ module RuboCop
|
|
|
127
135
|
def autocorrect_instance(node)
|
|
128
136
|
method_name, args, body = *node
|
|
129
137
|
unless names_match?(method_name, body) &&
|
|
138
|
+
!predicate?(method_name) &&
|
|
130
139
|
(kind = trivial_accessor_kind(method_name, args, body))
|
|
131
140
|
return
|
|
132
141
|
end
|
|
@@ -7,51 +7,62 @@ module RuboCop
|
|
|
7
7
|
class UnneededPercentQ < Cop
|
|
8
8
|
MSG = 'Use `%s` only for strings that contain both single quotes and ' \
|
|
9
9
|
'double quotes%s.'
|
|
10
|
+
DYNAMIC_MSG = ', or for dynamic strings that contain double quotes'
|
|
11
|
+
SINGLE_QUOTE = "'".freeze
|
|
12
|
+
QUOTE = '"'.freeze
|
|
13
|
+
EMPTY = ''.freeze
|
|
14
|
+
PERCENT_Q = '%q'.freeze
|
|
15
|
+
PERCENT_CAPITAL_Q = '%Q'.freeze
|
|
16
|
+
STRING_INTERPOLATION_REGEXP = /#\{.+}/
|
|
10
17
|
|
|
11
18
|
def on_dstr(node)
|
|
12
|
-
|
|
13
|
-
check(node) unless node.loc.expression.source =~ /"/
|
|
19
|
+
check(node)
|
|
14
20
|
end
|
|
15
21
|
|
|
16
22
|
def on_str(node)
|
|
23
|
+
# Interpolated strings that contain more than just interpolation
|
|
24
|
+
# will call `on_dstr` for the entire string and `on_str` for the
|
|
25
|
+
# non interpolated portion of the string
|
|
26
|
+
return unless string_literal?(node)
|
|
17
27
|
check(node)
|
|
18
28
|
end
|
|
19
29
|
|
|
20
|
-
# We process regexp nodes because the inner str nodes can cause
|
|
21
|
-
# confusion in on_str if they start with %( or %Q(.
|
|
22
|
-
def on_regexp(node)
|
|
23
|
-
string_parts = node.children.select { |child| child.type == :str }
|
|
24
|
-
string_parts.each { |s| ignore_node(s) }
|
|
25
|
-
end
|
|
26
|
-
|
|
27
30
|
private
|
|
28
31
|
|
|
29
32
|
def check(node)
|
|
30
|
-
if node.loc.respond_to?(:heredoc_body)
|
|
31
|
-
ignore_node(node)
|
|
32
|
-
return
|
|
33
|
-
end
|
|
34
|
-
return if ignored_node?(node) || part_of_ignored_node?(node)
|
|
35
33
|
src = node.loc.expression.source
|
|
36
|
-
return unless
|
|
37
|
-
return if src
|
|
34
|
+
return unless start_with_percent_q_variant?(src)
|
|
35
|
+
return if src.include?(SINGLE_QUOTE) && src.include?(QUOTE)
|
|
38
36
|
return if src =~ StringHelp::ESCAPED_CHAR_REGEXP
|
|
37
|
+
if src.start_with?(PERCENT_Q) && src =~ STRING_INTERPOLATION_REGEXP
|
|
38
|
+
return
|
|
39
|
+
end
|
|
39
40
|
|
|
40
|
-
extra = if src.start_with?(
|
|
41
|
-
|
|
41
|
+
extra = if src.start_with?(PERCENT_CAPITAL_Q)
|
|
42
|
+
DYNAMIC_MSG
|
|
42
43
|
else
|
|
43
|
-
|
|
44
|
+
EMPTY
|
|
44
45
|
end
|
|
45
46
|
add_offense(node, :expression, format(MSG, src[0, 2], extra))
|
|
46
47
|
end
|
|
47
48
|
|
|
48
49
|
def autocorrect(node)
|
|
49
|
-
delimiter =
|
|
50
|
+
delimiter =
|
|
51
|
+
node.loc.expression.source =~ /^%Q[^"]+$|'/ ? QUOTE : SINGLE_QUOTE
|
|
50
52
|
lambda do |corrector|
|
|
51
53
|
corrector.replace(node.loc.begin, delimiter)
|
|
52
54
|
corrector.replace(node.loc.end, delimiter)
|
|
53
55
|
end
|
|
54
56
|
end
|
|
57
|
+
|
|
58
|
+
def string_literal?(node)
|
|
59
|
+
node.loc.respond_to?(:begin) && node.loc.respond_to?(:end) &&
|
|
60
|
+
node.loc.begin && node.loc.end
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def start_with_percent_q_variant?(string)
|
|
64
|
+
string.start_with?(PERCENT_Q) || string.start_with?(PERCENT_CAPITAL_Q)
|
|
65
|
+
end
|
|
55
66
|
end
|
|
56
67
|
end
|
|
57
68
|
end
|
|
@@ -16,7 +16,7 @@ module RuboCop
|
|
|
16
16
|
def handle(node)
|
|
17
17
|
length = node.loc.expression.source.lines.to_a.size
|
|
18
18
|
return unless length > 1
|
|
19
|
-
return unless
|
|
19
|
+
return unless node.loc.begin && node.loc.begin.is?('do')
|
|
20
20
|
|
|
21
21
|
add_offense(node, :begin, error_message(node.type))
|
|
22
22
|
end
|
|
@@ -13,6 +13,7 @@ module RuboCop
|
|
|
13
13
|
include ConfigurableMax
|
|
14
14
|
|
|
15
15
|
MSG = 'Use `%w` or `%W` for array of words.'
|
|
16
|
+
QUESTION_MARK_SIZE = '?'.size
|
|
16
17
|
|
|
17
18
|
def on_array(node)
|
|
18
19
|
array_elems = node.children
|
|
@@ -61,7 +62,8 @@ module RuboCop
|
|
|
61
62
|
|
|
62
63
|
def autocorrect(node)
|
|
63
64
|
@interpolated = false
|
|
64
|
-
contents = node.children
|
|
65
|
+
contents = autocorrect_words(node.children, node.loc.line)
|
|
66
|
+
|
|
65
67
|
char = @interpolated ? 'W' : 'w'
|
|
66
68
|
|
|
67
69
|
lambda do |corrector|
|
|
@@ -69,10 +71,21 @@ module RuboCop
|
|
|
69
71
|
end
|
|
70
72
|
end
|
|
71
73
|
|
|
74
|
+
def autocorrect_words(word_nodes, base_line_number)
|
|
75
|
+
previous_node_line_number = base_line_number
|
|
76
|
+
word_nodes.map do |node|
|
|
77
|
+
number_of_line_breaks = node.loc.line - previous_node_line_number
|
|
78
|
+
line_breaks = "\n" * number_of_line_breaks
|
|
79
|
+
previous_node_line_number = node.loc.line
|
|
80
|
+
|
|
81
|
+
line_breaks + source_for(node)
|
|
82
|
+
end.join(' ')
|
|
83
|
+
end
|
|
84
|
+
|
|
72
85
|
def source_for(str_node)
|
|
73
86
|
if character_literal?(str_node)
|
|
74
87
|
@interpolated = true
|
|
75
|
-
begin_pos = str_node.loc.expression.begin_pos +
|
|
88
|
+
begin_pos = str_node.loc.expression.begin_pos + QUESTION_MARK_SIZE
|
|
76
89
|
end_pos = str_node.loc.expression.end_pos
|
|
77
90
|
else
|
|
78
91
|
begin_pos = str_node.loc.begin.end_pos
|
data/lib/rubocop/cop/team.rb
CHANGED
|
@@ -4,7 +4,7 @@ module RuboCop
|
|
|
4
4
|
module Cop
|
|
5
5
|
# FIXME
|
|
6
6
|
class Team
|
|
7
|
-
attr_reader :errors, :updated_source_file
|
|
7
|
+
attr_reader :errors, :warnings, :updated_source_file
|
|
8
8
|
|
|
9
9
|
alias_method :updated_source_file?, :updated_source_file
|
|
10
10
|
|
|
@@ -13,6 +13,7 @@ module RuboCop
|
|
|
13
13
|
@config = config
|
|
14
14
|
@options = options || { auto_correct: false, debug: false }
|
|
15
15
|
@errors = []
|
|
16
|
+
@warnings = []
|
|
16
17
|
end
|
|
17
18
|
|
|
18
19
|
def autocorrect?
|
|
@@ -79,7 +80,14 @@ module RuboCop
|
|
|
79
80
|
cop.relevant_file?(buffer.name) && cop.corrections.any?
|
|
80
81
|
end
|
|
81
82
|
if cop_with_corrections
|
|
82
|
-
|
|
83
|
+
corrections = cop_with_corrections.corrections
|
|
84
|
+
# Be extra careful if there are tabs in the source and just correct
|
|
85
|
+
# one offense, because inserting or removing space next to a tab has
|
|
86
|
+
# special implications, and existing ranges can't be used after such
|
|
87
|
+
# a change.
|
|
88
|
+
corrections = [corrections.first] if buffer.source =~ /\t/
|
|
89
|
+
|
|
90
|
+
corrector = Corrector.new(buffer, corrections)
|
|
83
91
|
corrector.rewrite
|
|
84
92
|
else
|
|
85
93
|
buffer.source
|
|
@@ -89,13 +97,25 @@ module RuboCop
|
|
|
89
97
|
def process_commissioner_errors(file, file_errors)
|
|
90
98
|
file_errors.each do |cop, errors|
|
|
91
99
|
errors.each do |e|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
100
|
+
if e.is_a?(Warning)
|
|
101
|
+
handle_warning(e,
|
|
102
|
+
Rainbow("#{e.message} (from file: " \
|
|
103
|
+
"#{file})").yellow)
|
|
104
|
+
else
|
|
105
|
+
handle_error(e,
|
|
106
|
+
Rainbow("An error occurred while #{cop.name}" \
|
|
107
|
+
" cop was inspecting #{file}.").red)
|
|
108
|
+
end
|
|
95
109
|
end
|
|
96
110
|
end
|
|
97
111
|
end
|
|
98
112
|
|
|
113
|
+
def handle_warning(e, message)
|
|
114
|
+
@warnings << message
|
|
115
|
+
warn message
|
|
116
|
+
puts e.backtrace if debug?
|
|
117
|
+
end
|
|
118
|
+
|
|
99
119
|
def handle_error(e, message)
|
|
100
120
|
@errors << message
|
|
101
121
|
warn message
|
data/lib/rubocop/cop/util.rb
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
# encoding: utf-8
|
|
2
2
|
|
|
3
|
+
# rubocop:disable Metrics/ModuleLength
|
|
3
4
|
module RuboCop
|
|
4
5
|
module Cop
|
|
5
6
|
# This module contains a collection of useful utility methods.
|
|
@@ -12,6 +13,10 @@ module RuboCop
|
|
|
12
13
|
SHORTHAND_ASGN_NODES = [:op_asgn, :or_asgn, :and_asgn]
|
|
13
14
|
ASGN_NODES = EQUALS_ASGN_NODES + SHORTHAND_ASGN_NODES
|
|
14
15
|
|
|
16
|
+
LITERALS = [:str, :dstr, :int, :float, :sym, :dsym, :array,
|
|
17
|
+
:hash, :regexp, :nil, :true, :false]
|
|
18
|
+
BASIC_LITERALS = LITERALS - [:dstr, :dsym, :array, :hash]
|
|
19
|
+
|
|
15
20
|
# http://phrogz.net/programmingruby/language.html#table_18.4
|
|
16
21
|
# Backtick is added last just to help editors parse this code.
|
|
17
22
|
OPERATOR_METHODS = %w(
|
|
@@ -186,8 +191,8 @@ module RuboCop
|
|
|
186
191
|
end
|
|
187
192
|
|
|
188
193
|
def begins_its_line?(range)
|
|
189
|
-
|
|
190
|
-
|
|
194
|
+
source_before_range = range.source_buffer.source[0...range.begin_pos]
|
|
195
|
+
source_before_range.rpartition("\n").last.strip.empty?
|
|
191
196
|
end
|
|
192
197
|
|
|
193
198
|
def within_node?(inner, outer)
|
|
@@ -80,9 +80,9 @@ module RuboCop
|
|
|
80
80
|
case branch_point_node.type
|
|
81
81
|
when :if then if_body_name
|
|
82
82
|
when :case then case_body_name
|
|
83
|
-
when *LOGICAL_OPERATOR_TYPES then logical_operator_body_name
|
|
84
83
|
when RESCUE_TYPE then rescue_body_name
|
|
85
84
|
when ENSURE_TYPE then ensure_body_name
|
|
85
|
+
when *LOGICAL_OPERATOR_TYPES then logical_operator_body_name
|
|
86
86
|
else fail InvalidBranchBodyError
|
|
87
87
|
end
|
|
88
88
|
rescue InvalidBranchBodyError
|
|
@@ -133,7 +133,7 @@ module RuboCop
|
|
|
133
133
|
end
|
|
134
134
|
|
|
135
135
|
def body_index
|
|
136
|
-
branch_point_node.children.index(branch_body_node)
|
|
136
|
+
branch_point_node.children.index { |n| n.equal?(branch_body_node) }
|
|
137
137
|
end
|
|
138
138
|
|
|
139
139
|
def set_branch_point_and_body_nodes!
|
|
@@ -157,14 +157,14 @@ module RuboCop
|
|
|
157
157
|
child_index = parent_node.children.index(child_node)
|
|
158
158
|
|
|
159
159
|
case parent_node.type
|
|
160
|
-
when *BRANCH_TYPES
|
|
161
|
-
child_index != CONDITION_INDEX_OF_BRANCH_NODE
|
|
162
|
-
when *LOGICAL_OPERATOR_TYPES
|
|
163
|
-
child_index != LEFT_SIDE_INDEX_OF_LOGICAL_OPERATOR_NODE
|
|
164
160
|
when RESCUE_TYPE
|
|
165
161
|
true
|
|
166
162
|
when ENSURE_TYPE
|
|
167
163
|
child_index != ENSURE_INDEX_OF_ENSURE_NODE
|
|
164
|
+
when *BRANCH_TYPES
|
|
165
|
+
child_index != CONDITION_INDEX_OF_BRANCH_NODE
|
|
166
|
+
when *LOGICAL_OPERATOR_TYPES
|
|
167
|
+
child_index != LEFT_SIDE_INDEX_OF_LOGICAL_OPERATOR_NODE
|
|
168
168
|
else
|
|
169
169
|
false
|
|
170
170
|
end
|
|
@@ -106,28 +106,28 @@ module RuboCop
|
|
|
106
106
|
# rubocop:disable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
107
107
|
def dispatch_node(node)
|
|
108
108
|
case node.type
|
|
109
|
-
when *ARGUMENT_DECLARATION_TYPES
|
|
110
|
-
process_variable_declaration(node)
|
|
111
109
|
when VARIABLE_ASSIGNMENT_TYPE
|
|
112
110
|
process_variable_assignment(node)
|
|
113
111
|
when REGEXP_NAMED_CAPTURE_TYPE
|
|
114
112
|
process_regexp_named_captures(node)
|
|
115
|
-
when *OPERATOR_ASSIGNMENT_TYPES
|
|
116
|
-
process_variable_operator_assignment(node)
|
|
117
113
|
when MULTIPLE_ASSIGNMENT_TYPE
|
|
118
114
|
process_variable_multiple_assignment(node)
|
|
119
115
|
when VARIABLE_REFERENCE_TYPE
|
|
120
116
|
process_variable_referencing(node)
|
|
121
|
-
when *LOOP_TYPES
|
|
122
|
-
process_loop(node)
|
|
123
117
|
when RESCUE_TYPE
|
|
124
118
|
process_rescue(node)
|
|
125
119
|
when ZERO_ARITY_SUPER_TYPE
|
|
126
120
|
process_zero_arity_super(node)
|
|
127
|
-
when *SCOPE_TYPES
|
|
128
|
-
process_scope(node)
|
|
129
121
|
when SEND_TYPE
|
|
130
122
|
process_send(node)
|
|
123
|
+
when *ARGUMENT_DECLARATION_TYPES
|
|
124
|
+
process_variable_declaration(node)
|
|
125
|
+
when *OPERATOR_ASSIGNMENT_TYPES
|
|
126
|
+
process_variable_operator_assignment(node)
|
|
127
|
+
when *LOOP_TYPES
|
|
128
|
+
process_loop(node)
|
|
129
|
+
when *SCOPE_TYPES
|
|
130
|
+
process_scope(node)
|
|
131
131
|
end
|
|
132
132
|
end
|
|
133
133
|
# rubocop:enable Metrics/MethodLength, Metrics/CyclomaticComplexity
|
|
@@ -326,13 +326,13 @@ module RuboCop
|
|
|
326
326
|
case node.type
|
|
327
327
|
when :lvar
|
|
328
328
|
referenced_variable_names_in_loop << node.children.first
|
|
329
|
+
when :lvasgn
|
|
330
|
+
assignment_nodes_in_loop << node
|
|
329
331
|
when *OPERATOR_ASSIGNMENT_TYPES
|
|
330
332
|
asgn_node = node.children.first
|
|
331
333
|
if asgn_node.type == :lvasgn
|
|
332
334
|
referenced_variable_names_in_loop << asgn_node.children.first
|
|
333
335
|
end
|
|
334
|
-
when :lvasgn
|
|
335
|
-
assignment_nodes_in_loop << node
|
|
336
336
|
end
|
|
337
337
|
end
|
|
338
338
|
|