rubocop 0.28.0 → 0.29.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/.rubocop_todo.yml +7 -7
- data/.travis.yml +4 -0
- data/CHANGELOG.md +59 -0
- data/README.md +62 -28
- data/config/default.yml +31 -0
- data/config/disabled.yml +1 -1
- data/config/enabled.yml +17 -0
- data/lib/rubocop.rb +4 -0
- data/lib/rubocop/cli.rb +1 -1
- data/lib/rubocop/config.rb +12 -8
- data/lib/rubocop/config_loader.rb +20 -10
- data/lib/rubocop/cop/cop.rb +13 -7
- data/lib/rubocop/cop/corrector.rb +10 -10
- data/lib/rubocop/cop/lint/assignment_in_condition.rb +6 -1
- data/lib/rubocop/cop/lint/block_alignment.rb +9 -2
- data/lib/rubocop/cop/lint/debugger.rb +13 -1
- data/lib/rubocop/cop/lint/duplicate_methods.rb +104 -0
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/require_parentheses.rb +3 -3
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +27 -0
- data/lib/rubocop/cop/mixin/on_normal_if_unless.rb +0 -4
- data/lib/rubocop/cop/rails/delegate.rb +4 -5
- data/lib/rubocop/cop/rails/read_write_attribute.rb +33 -0
- data/lib/rubocop/cop/style/access_modifier_indentation.rb +0 -7
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +4 -2
- data/lib/rubocop/cop/style/class_methods.rb +25 -9
- data/lib/rubocop/cop/style/empty_lines_around_access_modifier.rb +7 -1
- data/lib/rubocop/cop/style/empty_literal.rb +25 -10
- data/lib/rubocop/cop/style/even_odd.rb +32 -14
- data/lib/rubocop/cop/style/first_parameter_indentation.rb +106 -0
- data/lib/rubocop/cop/style/format_string.rb +2 -2
- data/lib/rubocop/cop/style/global_vars.rb +1 -5
- data/lib/rubocop/cop/style/hash_syntax.rb +0 -4
- data/lib/rubocop/cop/style/indentation_consistency.rb +5 -5
- data/lib/rubocop/cop/style/indentation_width.rb +13 -14
- data/lib/rubocop/cop/style/lambda.rb +48 -2
- data/lib/rubocop/cop/style/line_end_concatenation.rb +43 -47
- data/lib/rubocop/cop/style/method_called_on_do_end_block.rb +3 -3
- data/lib/rubocop/cop/style/module_function.rb +3 -3
- data/lib/rubocop/cop/style/multiline_block_layout.rb +65 -17
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +2 -1
- data/lib/rubocop/cop/style/perl_backrefs.rb +2 -2
- data/lib/rubocop/cop/style/redundant_exception.rb +12 -0
- data/lib/rubocop/cop/style/self_assignment.rb +27 -0
- data/lib/rubocop/cop/style/semicolon.rb +2 -1
- data/lib/rubocop/cop/style/space_around_block_parameters.rb +92 -0
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +0 -8
- data/lib/rubocop/cop/style/struct_inheritance.rb +42 -0
- data/lib/rubocop/cop/style/trivial_accessors.rb +10 -4
- data/lib/rubocop/cop/util.rb +32 -7
- data/lib/rubocop/formatter/simple_text_formatter.rb +0 -15
- data/lib/rubocop/options.rb +28 -41
- data/lib/rubocop/processed_source.rb +6 -0
- data/lib/rubocop/rake_task.rb +6 -3
- data/lib/rubocop/runner.rb +55 -15
- data/lib/rubocop/version.rb +1 -1
- data/relnotes/v0.29.0.md +116 -0
- data/rubocop.gemspec +3 -3
- data/spec/rubocop/cli_spec.rb +329 -25
- data/spec/rubocop/config_loader_spec.rb +20 -0
- data/spec/rubocop/cop/lint/assignment_in_condition_spec.rb +27 -3
- data/spec/rubocop/cop/lint/block_alignment_spec.rb +3 -4
- data/spec/rubocop/cop/lint/condition_position_spec.rb +1 -1
- data/spec/rubocop/cop/lint/debugger_spec.rb +20 -7
- data/spec/rubocop/cop/lint/duplicate_methods_spec.rb +189 -0
- data/spec/rubocop/cop/lint/empty_interpolation_spec.rb +1 -1
- data/spec/rubocop/cop/lint/end_in_method_spec.rb +1 -1
- data/spec/rubocop/cop/lint/eval_spec.rb +4 -4
- data/spec/rubocop/cop/lint/literal_in_condition_spec.rb +18 -0
- data/spec/rubocop/cop/lint/literal_in_interpolation_spec.rb +2 -2
- data/spec/rubocop/cop/lint/loop_spec.rb +4 -4
- data/spec/rubocop/cop/lint/parentheses_as_grouped_expression_spec.rb +7 -7
- data/spec/rubocop/cop/lint/space_before_first_arg_spec.rb +5 -4
- data/spec/rubocop/cop/lint/useless_assignment_spec.rb +3 -9
- data/spec/rubocop/cop/lint/useless_comparison_spec.rb +1 -1
- data/spec/rubocop/cop/lint/void_spec.rb +1 -1
- data/spec/rubocop/cop/metrics/abc_size_spec.rb +10 -0
- data/spec/rubocop/cop/metrics/line_length_spec.rb +2 -2
- data/spec/rubocop/cop/metrics/parameter_lists_spec.rb +2 -2
- data/spec/rubocop/cop/rails/action_filter_spec.rb +6 -12
- data/spec/rubocop/cop/rails/default_scope_spec.rb +5 -5
- data/spec/rubocop/cop/rails/delegate_spec.rb +8 -0
- data/spec/rubocop/cop/rails/has_and_belongs_to_many_spec.rb +1 -1
- data/spec/rubocop/cop/rails/read_write_attribute_spec.rb +119 -8
- data/spec/rubocop/cop/rails/scope_args_spec.rb +3 -3
- data/spec/rubocop/cop/rails/validation_spec.rb +3 -3
- data/spec/rubocop/cop/style/alias_spec.rb +5 -5
- data/spec/rubocop/cop/style/align_hash_spec.rb +1 -1
- data/spec/rubocop/cop/style/align_parameters_spec.rb +8 -8
- data/spec/rubocop/cop/style/and_or_spec.rb +15 -30
- data/spec/rubocop/cop/style/array_join_spec.rb +4 -4
- data/spec/rubocop/cop/style/ascii_comments_spec.rb +1 -2
- data/spec/rubocop/cop/style/ascii_identifiers_spec.rb +2 -2
- data/spec/rubocop/cop/style/begin_block_spec.rb +1 -1
- data/spec/rubocop/cop/style/block_comments_spec.rb +1 -1
- data/spec/rubocop/cop/style/block_end_newline_spec.rb +1 -1
- data/spec/rubocop/cop/style/blocks_spec.rb +2 -2
- data/spec/rubocop/cop/style/braces_around_hash_parameters_spec.rb +38 -33
- data/spec/rubocop/cop/style/case_equality_spec.rb +1 -1
- data/spec/rubocop/cop/style/character_literal_spec.rb +4 -4
- data/spec/rubocop/cop/style/class_and_module_children_spec.rb +4 -2
- data/spec/rubocop/cop/style/class_methods_spec.rb +12 -0
- data/spec/rubocop/cop/style/class_vars_spec.rb +2 -2
- data/spec/rubocop/cop/style/collection_methods_spec.rb +4 -4
- data/spec/rubocop/cop/style/colon_method_call_spec.rb +8 -8
- data/spec/rubocop/cop/style/comment_annotation_spec.rb +10 -10
- data/spec/rubocop/cop/style/constant_name_spec.rb +7 -7
- data/spec/rubocop/cop/style/def_with_parentheses_spec.rb +1 -1
- data/spec/rubocop/cop/style/deprecated_hash_methods_spec.rb +4 -4
- data/spec/rubocop/cop/style/dot_position_spec.rb +8 -6
- data/spec/rubocop/cop/style/each_with_object_spec.rb +2 -2
- data/spec/rubocop/cop/style/else_alignment_spec.rb +2 -4
- data/spec/rubocop/cop/style/empty_lines_around_access_modifier_spec.rb +78 -0
- data/spec/rubocop/cop/style/empty_lines_around_class_body_spec.rb +60 -0
- data/spec/rubocop/cop/style/empty_lines_spec.rb +3 -3
- data/spec/rubocop/cop/style/empty_literal_spec.rb +29 -12
- data/spec/rubocop/cop/style/encoding_spec.rb +3 -3
- data/spec/rubocop/cop/style/end_block_spec.rb +1 -1
- data/spec/rubocop/cop/style/end_of_line_spec.rb +2 -2
- data/spec/rubocop/cop/style/even_odd_spec.rb +109 -20
- data/spec/rubocop/cop/style/extra_spacing_spec.rb +3 -3
- data/spec/rubocop/cop/style/first_parameter_indentation_spec.rb +293 -0
- data/spec/rubocop/cop/style/for_spec.rb +2 -2
- data/spec/rubocop/cop/style/format_string_spec.rb +45 -21
- data/spec/rubocop/cop/style/global_vars_spec.rb +4 -4
- data/spec/rubocop/cop/style/guard_clause_spec.rb +17 -0
- data/spec/rubocop/cop/style/hash_syntax_spec.rb +15 -15
- data/spec/rubocop/cop/{metrics → style}/if_unless_modifier_spec.rb +2 -2
- data/spec/rubocop/cop/style/if_with_semicolon_spec.rb +2 -2
- data/spec/rubocop/cop/style/indent_array_spec.rb +3 -6
- data/spec/rubocop/cop/style/indent_hash_spec.rb +4 -4
- data/spec/rubocop/cop/style/indentation_consistency_spec.rb +1 -2
- data/spec/rubocop/cop/style/indentation_width_spec.rb +1 -2
- data/spec/rubocop/cop/style/infinite_loop_spec.rb +1 -1
- data/spec/rubocop/cop/style/lambda_call_spec.rb +4 -4
- data/spec/rubocop/cop/style/lambda_spec.rb +37 -2
- data/spec/rubocop/cop/style/leading_comment_space_spec.rb +7 -12
- data/spec/rubocop/cop/style/line_end_concatenation_spec.rb +41 -1
- data/spec/rubocop/cop/style/method_call_parentheses_spec.rb +4 -4
- data/spec/rubocop/cop/style/method_called_on_do_end_block_spec.rb +3 -3
- data/spec/rubocop/cop/style/method_name_spec.rb +1 -1
- data/spec/rubocop/cop/style/multiline_block_layout_spec.rb +61 -0
- data/spec/rubocop/cop/style/multiline_if_then_spec.rb +1 -3
- data/spec/rubocop/cop/style/multiline_operation_indentation_spec.rb +8 -0
- data/spec/rubocop/cop/style/multiline_ternary_operator_spec.rb +1 -1
- data/spec/rubocop/cop/style/nested_ternary_operator_spec.rb +1 -1
- data/spec/rubocop/cop/style/next_spec.rb +16 -0
- data/spec/rubocop/cop/style/numeric_literals_spec.rb +5 -5
- data/spec/rubocop/cop/style/one_line_conditional_spec.rb +1 -1
- data/spec/rubocop/cop/style/parentheses_around_condition_spec.rb +22 -4
- data/spec/rubocop/cop/style/percent_literal_delimiters_spec.rb +31 -31
- data/spec/rubocop/cop/style/percent_q_literals_spec.rb +12 -12
- data/spec/rubocop/cop/style/perl_backrefs_spec.rb +3 -3
- data/spec/rubocop/cop/style/proc_spec.rb +3 -3
- data/spec/rubocop/cop/style/raise_args_spec.rb +9 -9
- data/spec/rubocop/cop/style/redundant_begin_spec.rb +1 -1
- data/spec/rubocop/cop/style/redundant_exception_spec.rb +36 -4
- data/spec/rubocop/cop/style/redundant_self_spec.rb +89 -45
- data/spec/rubocop/cop/style/regexp_literal_spec.rb +9 -9
- data/spec/rubocop/cop/style/rescue_modifier_spec.rb +2 -2
- data/spec/rubocop/cop/style/self_assignment_spec.rb +16 -10
- data/spec/rubocop/cop/style/semicolon_spec.rb +9 -9
- data/spec/rubocop/cop/style/single_line_block_params_spec.rb +2 -2
- data/spec/rubocop/cop/style/single_space_before_first_arg_spec.rb +1 -1
- data/spec/rubocop/cop/style/space_after_colon_spec.rb +5 -5
- data/spec/rubocop/cop/style/space_after_comma_spec.rb +3 -3
- data/spec/rubocop/cop/style/space_after_control_keyword_spec.rb +4 -4
- data/spec/rubocop/cop/style/space_after_not_spec.rb +2 -2
- data/spec/rubocop/cop/style/space_after_semicolon_spec.rb +2 -2
- data/spec/rubocop/cop/style/space_around_block_parameters_spec.rb +150 -0
- data/spec/rubocop/cop/style/space_around_equals_in_parameter_default_spec.rb +18 -9
- data/spec/rubocop/cop/style/space_around_operators_spec.rb +24 -21
- data/spec/rubocop/cop/style/space_before_block_braces_spec.rb +4 -4
- data/spec/rubocop/cop/style/space_before_comma_spec.rb +4 -4
- data/spec/rubocop/cop/style/space_before_comment_spec.rb +3 -3
- data/spec/rubocop/cop/style/space_before_semicolon_spec.rb +2 -2
- data/spec/rubocop/cop/style/space_inside_block_braces_spec.rb +33 -24
- data/spec/rubocop/cop/style/space_inside_brackets_spec.rb +2 -2
- data/spec/rubocop/cop/style/space_inside_hash_literal_braces_spec.rb +9 -9
- data/spec/rubocop/cop/style/space_inside_parens_spec.rb +1 -1
- data/spec/rubocop/cop/style/special_global_vars_spec.rb +6 -6
- data/spec/rubocop/cop/style/string_literals_in_interpolation_spec.rb +3 -3
- data/spec/rubocop/cop/style/string_literals_spec.rb +16 -16
- data/spec/rubocop/cop/style/struct_inheritance_spec.rb +44 -0
- data/spec/rubocop/cop/style/symbol_array_spec.rb +9 -9
- data/spec/rubocop/cop/style/symbol_proc_spec.rb +12 -12
- data/spec/rubocop/cop/style/tab_spec.rb +4 -4
- data/spec/rubocop/cop/style/trailing_blank_lines_spec.rb +2 -2
- data/spec/rubocop/cop/style/trailing_whitespace_spec.rb +2 -2
- data/spec/rubocop/cop/style/trivial_accessors_spec.rb +16 -0
- data/spec/rubocop/cop/style/unneeded_capital_w_spec.rb +11 -22
- data/spec/rubocop/cop/style/variable_interpolation_spec.rb +7 -7
- data/spec/rubocop/cop/style/while_until_do_spec.rb +2 -2
- data/spec/rubocop/cop/{metrics → style}/while_until_modifier_spec.rb +2 -2
- data/spec/rubocop/cop/style/word_array_spec.rb +11 -11
- data/spec/rubocop/cop/util_spec.rb +51 -0
- data/spec/rubocop/cop/variable_force/reference_spec.rb +19 -0
- data/spec/rubocop/cop/variable_force/variable_table_spec.rb +7 -0
- data/spec/rubocop/formatter/disabled_lines_formatter_spec.rb +7 -8
- data/spec/rubocop/formatter/text_util_spec.rb +55 -0
- data/spec/rubocop/options_spec.rb +26 -20
- data/spec/rubocop/rake_task_spec.rb +122 -0
- data/spec/rubocop/runner_spec.rb +37 -2
- data/spec/rubocop/token_spec.rb +5 -1
- data/spec/spec_helper.rb +5 -2
- data/spec/support/cop_helper.rb +3 -0
- data/spec/support/cops/class_must_be_a_module_cop.rb +19 -0
- data/spec/support/cops/module_must_be_a_class_cop.rb +19 -0
- data/spec/support/custom_matchers.rb +1 -1
- metadata +35 -12
@@ -0,0 +1,92 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# Checks the spacing inside and after block parameters pipes.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
#
|
10
|
+
# # bad
|
11
|
+
# {}.each { | x, y |puts x }
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# {}.each { |x, y| puts x }
|
15
|
+
class SpaceAroundBlockParameters < Cop
|
16
|
+
include ConfigurableEnforcedStyle
|
17
|
+
|
18
|
+
def on_block(node)
|
19
|
+
_method, args, body = *node
|
20
|
+
opening_pipe, closing_pipe = args.loc.begin, args.loc.end
|
21
|
+
return unless opening_pipe
|
22
|
+
|
23
|
+
check_inside_pipes(args.children, opening_pipe, closing_pipe)
|
24
|
+
|
25
|
+
if body
|
26
|
+
check_space(closing_pipe.end_pos, body.loc.expression.begin_pos,
|
27
|
+
closing_pipe, 'after closing `|`')
|
28
|
+
end
|
29
|
+
|
30
|
+
check_each_arg(args)
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def parameter_name
|
36
|
+
'EnforcedStyleInsidePipes'
|
37
|
+
end
|
38
|
+
|
39
|
+
def check_inside_pipes(args, opening_pipe, closing_pipe)
|
40
|
+
first, last = args.first.loc.expression, args.last.loc.expression
|
41
|
+
|
42
|
+
if style == :no_space
|
43
|
+
check_no_space(opening_pipe.end_pos, first.begin_pos,
|
44
|
+
'Space before first')
|
45
|
+
check_no_space(last.end_pos, closing_pipe.begin_pos,
|
46
|
+
'Space after last')
|
47
|
+
elsif style == :space
|
48
|
+
check_space(opening_pipe.end_pos, first.begin_pos, first,
|
49
|
+
'before first block parameter')
|
50
|
+
check_space(last.end_pos, closing_pipe.begin_pos, last,
|
51
|
+
'after last block parameter')
|
52
|
+
check_no_space(opening_pipe.end_pos, first.begin_pos - 1,
|
53
|
+
'Extra space before first')
|
54
|
+
check_no_space(last.end_pos + 1, closing_pipe.begin_pos,
|
55
|
+
'Extra space after last')
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def check_each_arg(args)
|
60
|
+
args.children[1..-1].each do |arg|
|
61
|
+
expr = arg.loc.expression
|
62
|
+
check_no_space(range_with_surrounding_space(expr, :left).begin_pos,
|
63
|
+
expr.begin_pos - 1, 'Extra space before')
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
def check_space(space_begin_pos, space_end_pos, range, msg)
|
68
|
+
return if space_begin_pos != space_end_pos
|
69
|
+
|
70
|
+
add_offense(range, range, "Space #{msg} missing.")
|
71
|
+
end
|
72
|
+
|
73
|
+
def check_no_space(space_begin_pos, space_end_pos, msg)
|
74
|
+
return if space_begin_pos >= space_end_pos
|
75
|
+
|
76
|
+
range = Parser::Source::Range.new(processed_source.buffer,
|
77
|
+
space_begin_pos, space_end_pos)
|
78
|
+
add_offense(range, range, "#{msg} block parameter detected.")
|
79
|
+
end
|
80
|
+
|
81
|
+
def autocorrect(range)
|
82
|
+
@corrections << lambda do |corrector|
|
83
|
+
case range.source
|
84
|
+
when /^\s+$/ then corrector.remove(range)
|
85
|
+
else corrector.insert_after(range, ' ')
|
86
|
+
end
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
92
|
+
end
|
@@ -24,14 +24,6 @@ module RuboCop
|
|
24
24
|
|
25
25
|
wrong_quotes?(node, style)
|
26
26
|
end
|
27
|
-
|
28
|
-
def autocorrect(node)
|
29
|
-
@corrections << lambda do |corrector|
|
30
|
-
replacement = node.loc.begin.is?('"') ? "'" : '"'
|
31
|
-
corrector.replace(node.loc.begin, replacement)
|
32
|
-
corrector.replace(node.loc.end, replacement)
|
33
|
-
end
|
34
|
-
end
|
35
27
|
end
|
36
28
|
end
|
37
29
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
module Cop
|
5
|
+
module Style
|
6
|
+
# This cop checks for inheritance from Struct.new.
|
7
|
+
#
|
8
|
+
# @example
|
9
|
+
# # bad
|
10
|
+
# class Person < Struct.new(:first_name, :last_name)
|
11
|
+
# end
|
12
|
+
#
|
13
|
+
# # good
|
14
|
+
# Person = Struct.new(:first_name, :last_name)
|
15
|
+
class StructInheritance < Cop
|
16
|
+
MSG = "Don't extend an instance initialized by `Struct.new`."
|
17
|
+
|
18
|
+
def on_class(node)
|
19
|
+
_name, superclass, _body = *node
|
20
|
+
return unless struct_constructor?(superclass)
|
21
|
+
|
22
|
+
add_offense(node, superclass.loc.expression, MSG)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def struct_constructor?(node)
|
28
|
+
if node && node.send_type?
|
29
|
+
receiver, method_name = *node
|
30
|
+
|
31
|
+
receiver &&
|
32
|
+
receiver.const_type? &&
|
33
|
+
receiver.children.last == :Struct &&
|
34
|
+
method_name == :new
|
35
|
+
else
|
36
|
+
false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
@@ -107,13 +107,17 @@ module RuboCop
|
|
107
107
|
autocorrect_instance(node)
|
108
108
|
elsif node.type == :defs && node.children.first.type == :self
|
109
109
|
autocorrect_class(node)
|
110
|
+
else
|
111
|
+
fail CorrectionNotPossible
|
110
112
|
end
|
111
113
|
end
|
112
114
|
|
113
115
|
def autocorrect_instance(node)
|
114
116
|
method_name, args, body = *node
|
115
|
-
|
116
|
-
|
117
|
+
unless names_match?(method_name, body) &&
|
118
|
+
(kind = trivial_accessor_kind(method_name, args, body))
|
119
|
+
fail CorrectionNotPossible
|
120
|
+
end
|
117
121
|
|
118
122
|
@corrections << lambda do |corrector|
|
119
123
|
corrector.replace(
|
@@ -125,8 +129,10 @@ module RuboCop
|
|
125
129
|
|
126
130
|
def autocorrect_class(node)
|
127
131
|
_, method_name, args, body = *node
|
128
|
-
|
129
|
-
|
132
|
+
unless names_match?(method_name, body) &&
|
133
|
+
(kind = trivial_accessor_kind(method_name, args, body))
|
134
|
+
fail CorrectionNotPossible
|
135
|
+
end
|
130
136
|
|
131
137
|
@corrections << lambda do |corrector|
|
132
138
|
indent = ' ' * node.loc.column
|
data/lib/rubocop/cop/util.rb
CHANGED
@@ -141,16 +141,41 @@ module RuboCop
|
|
141
141
|
Parser::Source::Range.new(source_buffer, begin_pos, end_pos)
|
142
142
|
end
|
143
143
|
|
144
|
-
def
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
144
|
+
def range_with_surrounding_comma(range, side = :both, buffer = nil)
|
145
|
+
buffer ||= @processed_source.buffer
|
146
|
+
src = buffer.source
|
147
|
+
|
148
|
+
if side == :both
|
149
|
+
go_left, go_right = true, true
|
150
|
+
else
|
151
|
+
go_left = side == :left
|
152
|
+
go_right = side == :right
|
153
|
+
end
|
154
|
+
|
155
|
+
begin_pos, end_pos = range.begin_pos, range.end_pos
|
156
|
+
begin_pos -= 1 if go_left && src[begin_pos - 1] == ','
|
157
|
+
end_pos += 1 if go_right && src[end_pos] == ','
|
158
|
+
|
159
|
+
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
160
|
+
end
|
161
|
+
|
162
|
+
def range_with_surrounding_space(range, side = :both, buffer = nil)
|
163
|
+
buffer ||= @processed_source.buffer
|
164
|
+
src = buffer.source
|
165
|
+
|
166
|
+
if side == :both
|
167
|
+
go_left, go_right = true, true
|
168
|
+
else
|
169
|
+
go_left = side == :left
|
170
|
+
go_right = side == :right
|
171
|
+
end
|
172
|
+
|
173
|
+
begin_pos, end_pos = range.begin_pos, range.end_pos
|
149
174
|
begin_pos -= 1 while go_left && src[begin_pos - 1] =~ /[ \t]/
|
150
|
-
|
175
|
+
begin_pos -= 1 if go_left && src[begin_pos - 1] == "\n"
|
151
176
|
end_pos += 1 while go_right && src[end_pos] =~ /[ \t]/
|
152
177
|
end_pos += 1 if go_right && src[end_pos] == "\n"
|
153
|
-
Parser::Source::Range.new(
|
178
|
+
Parser::Source::Range.new(buffer, begin_pos, end_pos)
|
154
179
|
end
|
155
180
|
|
156
181
|
def begins_its_line?(range)
|
@@ -97,21 +97,6 @@ module RuboCop
|
|
97
97
|
message = offense.corrected? ? green('[Corrected] ') : ''
|
98
98
|
message << annotate_message(offense.message)
|
99
99
|
end
|
100
|
-
|
101
|
-
def pluralize(number, thing, options = {})
|
102
|
-
text = ''
|
103
|
-
|
104
|
-
if number == 0 && options[:no_for_zero]
|
105
|
-
text = 'no'
|
106
|
-
else
|
107
|
-
text << number.to_s
|
108
|
-
end
|
109
|
-
|
110
|
-
text << " #{thing}"
|
111
|
-
text << 's' unless number == 1
|
112
|
-
|
113
|
-
text
|
114
|
-
end
|
115
100
|
end
|
116
101
|
end
|
117
102
|
end
|
data/lib/rubocop/options.rb
CHANGED
@@ -9,6 +9,7 @@ module RuboCop
|
|
9
9
|
only: 'Run only the given cop(s).',
|
10
10
|
only_guide_cops: ['Run only cops for rules that link to a',
|
11
11
|
'style guide.'],
|
12
|
+
except: 'Disable the given cop(s).',
|
12
13
|
require: 'Require Ruby file.',
|
13
14
|
config: 'Specify configuration file.',
|
14
15
|
auto_gen_config: ['Generate a configuration file acting as a',
|
@@ -34,7 +35,8 @@ module RuboCop
|
|
34
35
|
'This option applies to the previously',
|
35
36
|
'specified --format, or the default format',
|
36
37
|
'if no format is specified.'],
|
37
|
-
fail_level:
|
38
|
+
fail_level: ['Minimum severity (A/R/C/W/E/F) for exit',
|
39
|
+
'with error code.'],
|
38
40
|
show_cops: ['Shows the given cops, or all cops by',
|
39
41
|
'default, and their configurations for the',
|
40
42
|
'current directory.'],
|
@@ -62,9 +64,6 @@ module RuboCop
|
|
62
64
|
end
|
63
65
|
|
64
66
|
def parse(args)
|
65
|
-
ignore_dropped_options(args)
|
66
|
-
convert_deprecated_options(args)
|
67
|
-
|
68
67
|
define_options(args).parse!(args)
|
69
68
|
|
70
69
|
validate_compatibility
|
@@ -72,6 +71,19 @@ module RuboCop
|
|
72
71
|
[@options, args]
|
73
72
|
end
|
74
73
|
|
74
|
+
# Cop name validation must be done later than option parsing, so it's not
|
75
|
+
# called from within this class.
|
76
|
+
def self.validate_cop_list(names)
|
77
|
+
return unless names
|
78
|
+
|
79
|
+
namespaces = Cop::Cop.all.types.map { |t| t.to_s.capitalize }
|
80
|
+
names.each do |name|
|
81
|
+
next if Cop::Cop.all.any? { |c| c.cop_name == name } ||
|
82
|
+
namespaces.include?(name)
|
83
|
+
fail ArgumentError, "Unrecognized cop or namespace: #{name}."
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
75
87
|
private
|
76
88
|
|
77
89
|
def define_options(args)
|
@@ -96,13 +108,17 @@ module RuboCop
|
|
96
108
|
end
|
97
109
|
|
98
110
|
def add_only_options(opts)
|
99
|
-
|
100
|
-
|
101
|
-
|
111
|
+
add_cop_selection_csv_option('except', opts)
|
112
|
+
add_cop_selection_csv_option('only', opts)
|
113
|
+
option(opts, '--only-guide-cops')
|
114
|
+
end
|
115
|
+
|
116
|
+
def add_cop_selection_csv_option(option, opts)
|
117
|
+
option(opts, "--#{option} [COP1,COP2,...]") do |list|
|
118
|
+
@options[:"#{option}"] = list.split(',').map do |c|
|
119
|
+
Cop::Cop.qualified_cop_name(c, "--#{option} option")
|
102
120
|
end
|
103
121
|
end
|
104
|
-
|
105
|
-
option(opts, '--only-guide-cops')
|
106
122
|
end
|
107
123
|
|
108
124
|
def add_configuration_options(opts, args)
|
@@ -131,9 +147,10 @@ module RuboCop
|
|
131
147
|
end
|
132
148
|
|
133
149
|
def add_severity_option(opts)
|
150
|
+
table = RuboCop::Cop::Severity::CODE_TABLE.merge(A: :autocorrect)
|
134
151
|
option(opts, '--fail-level SEVERITY',
|
135
|
-
RuboCop::Cop::Severity::NAMES,
|
136
|
-
|
152
|
+
RuboCop::Cop::Severity::NAMES + [:autocorrect],
|
153
|
+
table) do |severity|
|
137
154
|
@options[:fail_level] = severity
|
138
155
|
end
|
139
156
|
end
|
@@ -177,36 +194,6 @@ module RuboCop
|
|
177
194
|
long_opt[2..-1].sub(/ .*/, '').gsub(/-/, '_').to_sym
|
178
195
|
end
|
179
196
|
|
180
|
-
def ignore_dropped_options(args)
|
181
|
-
# Currently we don't make -s/--silent option raise error
|
182
|
-
# since those are mostly used by external tools.
|
183
|
-
rejected = args.reject! { |a| %w(-s --silent).include?(a) }
|
184
|
-
return unless rejected
|
185
|
-
|
186
|
-
warn '-s/--silent options is dropped. ' \
|
187
|
-
'`emacs` and `files` formatters no longer display summary.'
|
188
|
-
end
|
189
|
-
|
190
|
-
def convert_deprecated_options(args)
|
191
|
-
args.map! do |arg|
|
192
|
-
case arg
|
193
|
-
when '-e', '--emacs'
|
194
|
-
deprecate("#{arg} option", '--format emacs', '1.0.0')
|
195
|
-
%w(--format emacs)
|
196
|
-
else
|
197
|
-
arg
|
198
|
-
end
|
199
|
-
end.flatten!
|
200
|
-
end
|
201
|
-
|
202
|
-
def deprecate(subject, alternative = nil, version = nil)
|
203
|
-
message = "#{subject} is deprecated"
|
204
|
-
message << " and will be removed in RuboCop #{version}" if version
|
205
|
-
message << '.'
|
206
|
-
message << " Please use #{alternative} instead." if alternative
|
207
|
-
warn message
|
208
|
-
end
|
209
|
-
|
210
197
|
def validate_auto_gen_config_option(args)
|
211
198
|
return unless args.any?
|
212
199
|
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# encoding: utf-8
|
2
2
|
|
3
3
|
require 'astrolabe/builder'
|
4
|
+
require 'digest/md5'
|
4
5
|
|
5
6
|
module RuboCop
|
6
7
|
# ProcessedSource contains objects which are generated by Parser
|
@@ -48,6 +49,11 @@ module RuboCop
|
|
48
49
|
@diagnostics.none? { |d| [:error, :fatal].include?(d.level) }
|
49
50
|
end
|
50
51
|
|
52
|
+
# Raw source checksum for tracking infinite loops.
|
53
|
+
def checksum
|
54
|
+
Digest::MD5.hexdigest(@raw_source)
|
55
|
+
end
|
56
|
+
|
51
57
|
private
|
52
58
|
|
53
59
|
def parse(source)
|
data/lib/rubocop/rake_task.rb
CHANGED
@@ -31,7 +31,7 @@ module RuboCop
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
setup_subtasks(name)
|
34
|
+
setup_subtasks(name, *args, &task_block)
|
35
35
|
end
|
36
36
|
|
37
37
|
def run_main_task(verbose)
|
@@ -73,11 +73,14 @@ module RuboCop
|
|
73
73
|
@formatters = [RuboCop::Options::DEFAULT_FORMATTER]
|
74
74
|
end
|
75
75
|
|
76
|
-
def setup_subtasks(name)
|
76
|
+
def setup_subtasks(name, *args, &task_block)
|
77
77
|
namespace name do
|
78
78
|
desc 'Auto-correct RuboCop offenses'
|
79
79
|
|
80
|
-
task
|
80
|
+
task(:auto_correct, *args) do |_, task_args|
|
81
|
+
if task_block
|
82
|
+
task_block.call(*[self, task_args].slice(0, task_block.arity))
|
83
|
+
end
|
81
84
|
options = full_options.unshift('--auto-correct')
|
82
85
|
run_cli(verbose, options)
|
83
86
|
end
|
data/lib/rubocop/runner.rb
CHANGED
@@ -4,6 +4,17 @@ module RuboCop
|
|
4
4
|
# This class handles the processing of files, which includes dealing with
|
5
5
|
# formatters and letting cops inspect the files.
|
6
6
|
class Runner
|
7
|
+
# An exception indicating that the inspection loop got stuck correcting
|
8
|
+
# offenses back and forth.
|
9
|
+
class InfiniteCorrectionLoop < Exception
|
10
|
+
attr_reader :offenses
|
11
|
+
|
12
|
+
def initialize(path, offenses)
|
13
|
+
super "Infinite loop detected in #{path}."
|
14
|
+
@offenses = offenses
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
7
18
|
attr_reader :errors, :aborting
|
8
19
|
alias_method :aborting?, :aborting
|
9
20
|
|
@@ -30,10 +41,10 @@ module RuboCop
|
|
30
41
|
break if @options[:fail_fast] && !all_passed
|
31
42
|
end
|
32
43
|
|
44
|
+
all_passed
|
45
|
+
ensure
|
33
46
|
formatter_set.finished(inspected_files.freeze)
|
34
47
|
formatter_set.close_output_files
|
35
|
-
|
36
|
-
all_passed
|
37
48
|
end
|
38
49
|
|
39
50
|
def abort
|
@@ -58,34 +69,57 @@ module RuboCop
|
|
58
69
|
offenses = do_inspection_loop(file, processed_source)
|
59
70
|
|
60
71
|
formatter_set.file_finished(file, offenses.compact.sort.freeze)
|
72
|
+
|
61
73
|
offenses
|
74
|
+
rescue InfiniteCorrectionLoop => e
|
75
|
+
formatter_set.file_finished(file, e.offenses.compact.sort.freeze)
|
76
|
+
raise
|
62
77
|
end
|
63
78
|
|
64
79
|
def do_inspection_loop(file, processed_source)
|
65
80
|
offenses = []
|
66
81
|
|
82
|
+
# Keep track of the state of the source. If a cop modifies the source
|
83
|
+
# and another cop undoes it producing identical source we have an
|
84
|
+
# infinite loop.
|
85
|
+
@processed_sources = []
|
86
|
+
|
67
87
|
# When running with --auto-correct, we need to inspect the file (which
|
68
88
|
# includes writing a corrected version of it) until no more corrections
|
69
89
|
# are made. This is because automatic corrections can introduce new
|
70
90
|
# offenses. In the normal case the loop is only executed once.
|
71
91
|
loop do
|
92
|
+
check_for_infinite_loop(processed_source, offenses)
|
93
|
+
|
72
94
|
# The offenses that couldn't be corrected will be found again so we
|
73
95
|
# only keep the corrected ones in order to avoid duplicate reporting.
|
74
96
|
offenses.select!(&:corrected?)
|
75
|
-
|
76
97
|
new_offenses, updated_source_file = inspect_file(processed_source)
|
77
98
|
offenses.concat(new_offenses).uniq!
|
78
|
-
break unless updated_source_file
|
79
99
|
|
80
100
|
# We have to reprocess the source to pickup the changes. Since the
|
81
101
|
# change could (theoretically) introduce parsing errors, we break the
|
82
102
|
# loop if we find any.
|
103
|
+
break unless updated_source_file
|
104
|
+
|
83
105
|
processed_source = ProcessedSource.from_file(file)
|
84
106
|
end
|
85
107
|
|
86
108
|
offenses
|
87
109
|
end
|
88
110
|
|
111
|
+
# Check whether a run created source identical to a previous run, which
|
112
|
+
# means that we definitely have an infinite loop.
|
113
|
+
def check_for_infinite_loop(processed_source, offenses)
|
114
|
+
checksum = processed_source.checksum
|
115
|
+
|
116
|
+
if @processed_sources.include?(checksum)
|
117
|
+
fail InfiniteCorrectionLoop.new(processed_source.path, offenses)
|
118
|
+
end
|
119
|
+
|
120
|
+
@processed_sources << checksum
|
121
|
+
end
|
122
|
+
|
89
123
|
def inspect_file(processed_source)
|
90
124
|
config = @config_store.for(processed_source.path)
|
91
125
|
team = Cop::Team.new(mobilized_cop_classes(config), config, @options)
|
@@ -99,20 +133,31 @@ module RuboCop
|
|
99
133
|
@mobilized_cop_classes[config.object_id] ||= begin
|
100
134
|
cop_classes = Cop::Cop.all
|
101
135
|
|
102
|
-
|
103
|
-
validate_only_option
|
136
|
+
[:only, :except].each { |opt| Options.validate_cop_list(@options[opt]) }
|
104
137
|
|
138
|
+
if @options[:only]
|
105
139
|
cop_classes.select! do |c|
|
106
|
-
@options[:only]
|
140
|
+
cop_match?(c, @options[:only]) || @options[:lint] && c.lint?
|
107
141
|
end
|
108
142
|
else
|
109
143
|
filter_cop_classes(cop_classes, config)
|
110
144
|
end
|
111
145
|
|
146
|
+
cop_classes.reject! { |c| cop_match?(c, @options[:except]) }
|
147
|
+
|
112
148
|
cop_classes
|
113
149
|
end
|
114
150
|
end
|
115
151
|
|
152
|
+
# Returns true if the cop name or the cop namespace matches any of the
|
153
|
+
# given names.
|
154
|
+
def cop_match?(cop, given_names)
|
155
|
+
return false unless given_names
|
156
|
+
|
157
|
+
given_names.include?(cop.cop_name) ||
|
158
|
+
given_names.include?(cop.cop_type.to_s.capitalize)
|
159
|
+
end
|
160
|
+
|
116
161
|
def filter_cop_classes(cop_classes, config)
|
117
162
|
# use only cops that link to a style guide if requested
|
118
163
|
if style_guide_cops_only?(config)
|
@@ -126,13 +171,6 @@ module RuboCop
|
|
126
171
|
cop_classes.select!(&:lint?) if @options[:lint]
|
127
172
|
end
|
128
173
|
|
129
|
-
def validate_only_option
|
130
|
-
@options[:only].each do |cop_to_run|
|
131
|
-
next unless Cop::Cop.all.none? { |c| c.cop_name == cop_to_run }
|
132
|
-
fail ArgumentError, "Unrecognized cop name: #{cop_to_run}."
|
133
|
-
end
|
134
|
-
end
|
135
|
-
|
136
174
|
def run_rails_cops?(config)
|
137
175
|
@options[:rails] || config['AllCops']['RunRailsCops']
|
138
176
|
end
|
@@ -157,7 +195,9 @@ module RuboCop
|
|
157
195
|
end
|
158
196
|
|
159
197
|
def considered_failure?(offense)
|
160
|
-
|
198
|
+
# For :autocorrect level, any offense - corrected or not - is a failure.
|
199
|
+
@options[:fail_level] == :autocorrect ||
|
200
|
+
!offense.corrected? && offense.severity >= minimum_severity_to_fail
|
161
201
|
end
|
162
202
|
|
163
203
|
def minimum_severity_to_fail
|