rubocop 0.76.0 → 0.80.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.
Files changed (155) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE.txt +1 -1
  3. data/README.md +4 -4
  4. data/config/default.yml +325 -283
  5. data/lib/rubocop.rb +43 -23
  6. data/lib/rubocop/ast/builder.rb +43 -42
  7. data/lib/rubocop/ast/node.rb +1 -13
  8. data/lib/rubocop/ast/node/block_node.rb +2 -0
  9. data/lib/rubocop/ast/node/def_node.rb +11 -0
  10. data/lib/rubocop/ast/node/forward_args_node.rb +18 -0
  11. data/lib/rubocop/ast/node/regexp_node.rb +2 -4
  12. data/lib/rubocop/ast/traversal.rb +20 -3
  13. data/lib/rubocop/cli.rb +11 -230
  14. data/lib/rubocop/cli/command.rb +21 -0
  15. data/lib/rubocop/cli/command/auto_genenerate_config.rb +105 -0
  16. data/lib/rubocop/cli/command/base.rb +33 -0
  17. data/lib/rubocop/cli/command/execute_runner.rb +76 -0
  18. data/lib/rubocop/cli/command/init_dotfile.rb +45 -0
  19. data/lib/rubocop/cli/command/show_cops.rb +80 -0
  20. data/lib/rubocop/cli/command/version.rb +17 -0
  21. data/lib/rubocop/cli/environment.rb +21 -0
  22. data/lib/rubocop/comment_config.rb +6 -1
  23. data/lib/rubocop/config.rb +28 -10
  24. data/lib/rubocop/config_loader.rb +19 -19
  25. data/lib/rubocop/config_obsoletion.rb +65 -11
  26. data/lib/rubocop/config_validator.rb +56 -98
  27. data/lib/rubocop/cop/autocorrect_logic.rb +7 -4
  28. data/lib/rubocop/cop/bundler/gem_comment.rb +4 -4
  29. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +2 -2
  30. data/lib/rubocop/cop/cop.rb +21 -0
  31. data/lib/rubocop/cop/correctors/space_corrector.rb +1 -2
  32. data/lib/rubocop/cop/gemspec/ordered_dependencies.rb +1 -1
  33. data/lib/rubocop/cop/generator.rb +3 -4
  34. data/lib/rubocop/cop/generator/configuration_injector.rb +1 -1
  35. data/lib/rubocop/cop/internal_affairs.rb +1 -0
  36. data/lib/rubocop/cop/internal_affairs/method_name_equal.rb +59 -0
  37. data/lib/rubocop/cop/layout/{align_arguments.rb → argument_alignment.rb} +1 -1
  38. data/lib/rubocop/cop/layout/{align_array.rb → array_alignment.rb} +1 -1
  39. data/lib/rubocop/cop/layout/{indent_assignment.rb → assignment_indentation.rb} +1 -1
  40. data/lib/rubocop/cop/layout/empty_line_between_defs.rb +2 -1
  41. data/lib/rubocop/cop/layout/extra_spacing.rb +1 -1
  42. data/lib/rubocop/cop/layout/{indent_first_argument.rb → first_argument_indentation.rb} +5 -5
  43. data/lib/rubocop/cop/layout/{indent_first_array_element.rb → first_array_element_indentation.rb} +4 -4
  44. data/lib/rubocop/cop/layout/{indent_first_hash_element.rb → first_hash_element_indentation.rb} +3 -3
  45. data/lib/rubocop/cop/layout/{indent_first_parameter.rb → first_parameter_indentation.rb} +3 -3
  46. data/lib/rubocop/cop/layout/{align_hash.rb → hash_alignment.rb} +10 -6
  47. data/lib/rubocop/cop/layout/{indent_heredoc.rb → heredoc_indentation.rb} +5 -5
  48. data/lib/rubocop/cop/layout/leading_comment_space.rb +33 -2
  49. data/lib/rubocop/cop/layout/{leading_blank_lines.rb → leading_empty_lines.rb} +1 -1
  50. data/lib/rubocop/cop/{metrics → layout}/line_length.rb +67 -108
  51. data/lib/rubocop/cop/layout/multiline_block_layout.rb +14 -5
  52. data/lib/rubocop/cop/layout/multiline_hash_brace_layout.rb +0 -4
  53. data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +1 -1
  54. data/lib/rubocop/cop/layout/{align_parameters.rb → parameter_alignment.rb} +1 -1
  55. data/lib/rubocop/cop/layout/space_around_keyword.rb +12 -0
  56. data/lib/rubocop/cop/layout/space_around_operators.rb +50 -7
  57. data/lib/rubocop/cop/layout/space_before_block_braces.rb +17 -0
  58. data/lib/rubocop/cop/layout/space_before_first_arg.rb +8 -0
  59. data/lib/rubocop/cop/layout/space_inside_hash_literal_braces.rb +2 -9
  60. data/lib/rubocop/cop/layout/{trailing_blank_lines.rb → trailing_empty_lines.rb} +1 -1
  61. data/lib/rubocop/cop/lint/debugger.rb +1 -1
  62. data/lib/rubocop/cop/lint/disjunctive_assignment_in_constructor.rb +1 -1
  63. data/lib/rubocop/cop/lint/{duplicated_key.rb → duplicate_hash_key.rb} +1 -1
  64. data/lib/rubocop/cop/lint/each_with_object_argument.rb +1 -1
  65. data/lib/rubocop/cop/lint/ineffective_access_modifier.rb +1 -1
  66. data/lib/rubocop/cop/lint/{multiple_compare.rb → multiple_comparison.rb} +1 -1
  67. data/lib/rubocop/cop/lint/non_deterministic_require_order.rb +89 -0
  68. data/lib/rubocop/cop/lint/redundant_cop_disable_directive.rb +3 -3
  69. data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +13 -8
  70. data/lib/rubocop/cop/lint/redundant_splat_expansion.rb +1 -1
  71. data/lib/rubocop/cop/lint/{string_conversion_in_interpolation.rb → redundant_string_coercion.rb} +1 -1
  72. data/lib/rubocop/cop/lint/redundant_with_index.rb +2 -2
  73. data/lib/rubocop/cop/lint/redundant_with_object.rb +2 -2
  74. data/lib/rubocop/cop/lint/{handle_exceptions.rb → suppressed_exception.rb} +1 -1
  75. data/lib/rubocop/cop/lint/useless_access_modifier.rb +57 -23
  76. data/lib/rubocop/cop/lint/useless_setter_call.rb +5 -1
  77. data/lib/rubocop/cop/metrics/method_length.rb +1 -1
  78. data/lib/rubocop/cop/migration/department_name.rb +30 -2
  79. data/lib/rubocop/cop/mixin/alignment.rb +1 -1
  80. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +4 -0
  81. data/lib/rubocop/cop/mixin/frozen_string_literal.rb +7 -7
  82. data/lib/rubocop/cop/mixin/{hash_alignment.rb → hash_alignment_styles.rb} +1 -1
  83. data/lib/rubocop/cop/mixin/hash_transform_method.rb +171 -0
  84. data/lib/rubocop/cop/mixin/line_length_help.rb +88 -0
  85. data/lib/rubocop/cop/mixin/nil_methods.rb +4 -4
  86. data/lib/rubocop/cop/mixin/rational_literal.rb +18 -0
  87. data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -2
  88. data/lib/rubocop/cop/mixin/trailing_comma.rb +8 -12
  89. data/lib/rubocop/cop/naming/{uncommunicative_block_param_name.rb → block_parameter_name.rb} +3 -3
  90. data/lib/rubocop/cop/naming/heredoc_delimiter_naming.rb +5 -5
  91. data/lib/rubocop/cop/naming/memoized_instance_variable_name.rb +1 -1
  92. data/lib/rubocop/cop/naming/{uncommunicative_method_param_name.rb → method_parameter_name.rb} +4 -4
  93. data/lib/rubocop/cop/naming/predicate_name.rb +6 -6
  94. data/lib/rubocop/cop/offense.rb +11 -0
  95. data/lib/rubocop/cop/registry.rb +7 -2
  96. data/lib/rubocop/cop/style/alias.rb +1 -1
  97. data/lib/rubocop/cop/style/array_join.rb +1 -1
  98. data/lib/rubocop/cop/style/attr.rb +8 -0
  99. data/lib/rubocop/cop/style/block_delimiters.rb +60 -1
  100. data/lib/rubocop/cop/style/conditional_assignment.rb +2 -2
  101. data/lib/rubocop/cop/style/eval_with_location.rb +1 -1
  102. data/lib/rubocop/cop/style/even_odd.rb +1 -1
  103. data/lib/rubocop/cop/style/frozen_string_literal_comment.rb +89 -11
  104. data/lib/rubocop/cop/style/guard_clause.rb +3 -2
  105. data/lib/rubocop/cop/style/hash_each_methods.rb +87 -0
  106. data/lib/rubocop/cop/style/hash_transform_keys.rb +79 -0
  107. data/lib/rubocop/cop/style/hash_transform_values.rb +79 -0
  108. data/lib/rubocop/cop/style/if_unless_modifier.rb +38 -3
  109. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  110. data/lib/rubocop/cop/style/inverse_methods.rb +8 -4
  111. data/lib/rubocop/cop/style/ip_addresses.rb +4 -4
  112. data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -205
  113. data/lib/rubocop/cop/style/method_call_with_args_parentheses/omit_parentheses.rb +169 -0
  114. data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +54 -0
  115. data/lib/rubocop/cop/style/mixin_grouping.rb +1 -1
  116. data/lib/rubocop/cop/style/multiline_method_signature.rb +1 -1
  117. data/lib/rubocop/cop/style/multiline_when_then.rb +5 -1
  118. data/lib/rubocop/cop/style/nested_parenthesized_calls.rb +7 -7
  119. data/lib/rubocop/cop/style/next.rb +5 -5
  120. data/lib/rubocop/cop/style/numeric_literals.rb +7 -3
  121. data/lib/rubocop/cop/style/numeric_predicate.rb +4 -3
  122. data/lib/rubocop/cop/style/option_hash.rb +3 -3
  123. data/lib/rubocop/cop/style/or_assignment.rb +3 -2
  124. data/lib/rubocop/cop/style/percent_literal_delimiters.rb +7 -7
  125. data/lib/rubocop/cop/style/redundant_condition.rb +17 -4
  126. data/lib/rubocop/cop/style/redundant_parentheses.rb +3 -3
  127. data/lib/rubocop/cop/style/redundant_return.rb +2 -8
  128. data/lib/rubocop/cop/style/redundant_sort.rb +1 -1
  129. data/lib/rubocop/cop/style/symbol_array.rb +2 -2
  130. data/lib/rubocop/cop/style/ternary_parentheses.rb +1 -1
  131. data/lib/rubocop/cop/style/trailing_comma_in_arguments.rb +0 -22
  132. data/lib/rubocop/cop/style/trailing_underscore_variable.rb +7 -1
  133. data/lib/rubocop/cop/style/trivial_accessors.rb +5 -5
  134. data/lib/rubocop/cop/style/while_until_modifier.rb +1 -1
  135. data/lib/rubocop/cop/style/yoda_condition.rb +16 -1
  136. data/lib/rubocop/cop/team.rb +5 -0
  137. data/lib/rubocop/cop/variable_force.rb +4 -1
  138. data/lib/rubocop/formatter/base_formatter.rb +2 -2
  139. data/lib/rubocop/formatter/clang_style_formatter.rb +1 -3
  140. data/lib/rubocop/formatter/formatter_set.rb +1 -0
  141. data/lib/rubocop/formatter/json_formatter.rb +6 -5
  142. data/lib/rubocop/formatter/junit_formatter.rb +63 -0
  143. data/lib/rubocop/formatter/tap_formatter.rb +1 -3
  144. data/lib/rubocop/node_pattern.rb +97 -11
  145. data/lib/rubocop/options.rb +8 -8
  146. data/lib/rubocop/processed_source.rb +1 -1
  147. data/lib/rubocop/rake_task.rb +1 -0
  148. data/lib/rubocop/result_cache.rb +23 -7
  149. data/lib/rubocop/rspec/shared_contexts.rb +5 -0
  150. data/lib/rubocop/runner.rb +18 -2
  151. data/lib/rubocop/target_ruby.rb +151 -0
  152. data/lib/rubocop/version.rb +1 -1
  153. metadata +60 -27
  154. data/lib/rubocop/cop/mixin/safe_mode.rb +0 -24
  155. data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +0 -209
@@ -20,7 +20,7 @@ module RuboCop
20
20
  # a = ['run',
21
21
  # 'forrest',
22
22
  # 'run']
23
- class AlignArray < Cop
23
+ class ArrayAlignment < Cop
24
24
  include Alignment
25
25
 
26
26
  MSG = 'Align the elements of an array literal if they span more ' \
@@ -21,7 +21,7 @@ module RuboCop
21
21
  #
22
22
  # The indentation of the remaining lines can be corrected with
23
23
  # other cops such as `IndentationConsistency` and `EndAlignment`.
24
- class IndentAssignment < Cop
24
+ class AssignmentIndentation < Cop
25
25
  include CheckAssignment
26
26
  include Alignment
27
27
 
@@ -56,7 +56,8 @@ module RuboCop
56
56
  return if nodes.all?(&:single_line?) &&
57
57
  cop_config['AllowAdjacentOneLineDefs']
58
58
 
59
- add_offense(nodes.last, location: :keyword)
59
+ location = nodes.last.loc.keyword.join(nodes.last.loc.name)
60
+ add_offense(nodes.last, location: location)
60
61
  end
61
62
 
62
63
  def autocorrect(node)
@@ -114,7 +114,7 @@ module RuboCop
114
114
 
115
115
  # Returns an array of ranges that should not be reported. It's the
116
116
  # extra spaces between the keys and values in a multiline hash,
117
- # since those are handled by the Style/AlignHash cop.
117
+ # since those are handled by the Layout/HashAlignment cop.
118
118
  def ignored_ranges(ast)
119
119
  return [] unless ast
120
120
 
@@ -2,14 +2,14 @@
2
2
 
3
3
  module RuboCop
4
4
  module Cop
5
- # rubocop:disable Metrics/LineLength
5
+ # rubocop:disable Layout/LineLength
6
6
  module Layout
7
7
  # This cop checks the indentation of the first argument in a method call.
8
- # Arguments after the first one are checked by Layout/AlignArguments,
8
+ # Arguments after the first one are checked by Layout/ArgumentAlignment,
9
9
  # not by this cop.
10
10
  #
11
11
  # For indenting the first parameter of method *definitions*, check out
12
- # Layout/IndentFirstParameter.
12
+ # Layout/FirstParameterIndentation.
13
13
  #
14
14
  # @example
15
15
  #
@@ -142,8 +142,8 @@ module RuboCop
142
142
  # nested_first_param),
143
143
  # second_param
144
144
  #
145
- class IndentFirstArgument < Cop
146
- # rubocop:enable Metrics/LineLength
145
+ class FirstArgumentIndentation < Cop
146
+ # rubocop:enable Layout/LineLength
147
147
  include Alignment
148
148
  include ConfigurableEnforcedStyle
149
149
  include RangeHelp
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Layout
6
6
  # This cop checks the indentation of the first element in an array literal
7
7
  # where the opening bracket and the first element are on separate lines.
8
- # The other elements' indentations are handled by the AlignArray cop.
8
+ # The other elements' indentations are handled by the ArrayAlignment cop.
9
9
  #
10
10
  # By default, array literals that are arguments in a method call with
11
11
  # parentheses, and where the opening square bracket of the array is on the
@@ -22,7 +22,7 @@ module RuboCop
22
22
  # @example EnforcedStyle: special_inside_parentheses (default)
23
23
  # # The `special_inside_parentheses` style enforces that the first
24
24
  # # element in an array literal where the opening bracket and first
25
- # # element are on seprate lines is indented one step (two spaces) more
25
+ # # element are on separate lines is indented one step (two spaces) more
26
26
  # # than the position inside the opening parenthesis.
27
27
  #
28
28
  # #bad
@@ -44,7 +44,7 @@ module RuboCop
44
44
  # @example EnforcedStyle: consistent
45
45
  # # The `consistent` style enforces that the first element in an array
46
46
  # # literal where the opening bracket and the first element are on
47
- # # seprate lines is indented the same as an array literal which is not
47
+ # # separate lines is indented the same as an array literal which is not
48
48
  # # defined inside a method call.
49
49
  #
50
50
  # #bad
@@ -79,7 +79,7 @@ module RuboCop
79
79
  # and_now_for_something = [
80
80
  # :completely_different
81
81
  # ]
82
- class IndentFirstArrayElement < Cop
82
+ class FirstArrayElementIndentation < Cop
83
83
  include Alignment
84
84
  include ConfigurableEnforcedStyle
85
85
  include MultilineElementIndentation
@@ -5,7 +5,7 @@ module RuboCop
5
5
  module Layout
6
6
  # This cop checks the indentation of the first key in a hash literal
7
7
  # where the opening brace and the first key are on separate lines. The
8
- # other keys' indentations are handled by the AlignHash cop.
8
+ # other keys' indentations are handled by the HashAlignment cop.
9
9
  #
10
10
  # By default, Hash literals that are arguments in a method call with
11
11
  # parentheses, and where the opening curly brace of the hash is on the
@@ -77,7 +77,7 @@ module RuboCop
77
77
  # and_now_for_something = {
78
78
  # completely: :different
79
79
  # }
80
- class IndentFirstHashElement < Cop
80
+ class FirstHashElementIndentation < Cop
81
81
  include Alignment
82
82
  include ConfigurableEnforcedStyle
83
83
  include MultilineElementIndentation
@@ -149,7 +149,7 @@ module RuboCop
149
149
  def separator_style?(first_pair)
150
150
  separator = first_pair.loc.operator
151
151
  key = "Enforced#{separator.is?(':') ? 'Colon' : 'HashRocket'}Style"
152
- config.for_cop('Layout/AlignHash')[key] == 'separator'
152
+ config.for_cop('Layout/HashAlignment')[key] == 'separator'
153
153
  end
154
154
 
155
155
  def check_based_on_longest_key(hash_node, left_brace, left_parenthesis)
@@ -5,10 +5,10 @@ module RuboCop
5
5
  module Layout
6
6
  # This cop checks the indentation of the first parameter in a method
7
7
  # definition. Parameters after the first one are checked by
8
- # Layout/AlignParameters, not by this cop.
8
+ # Layout/ParameterAlignment, not by this cop.
9
9
  #
10
10
  # For indenting the first argument of method *calls*, check out
11
- # Layout/IndentFirstArgument, which supports options related to
11
+ # Layout/FirstArgumentIndentation, which supports options related to
12
12
  # nesting that are irrelevant for method *definitions*.
13
13
  #
14
14
  # @example
@@ -41,7 +41,7 @@ module RuboCop
41
41
  # second_param)
42
42
  # 123
43
43
  # end
44
- class IndentFirstParameter < Cop
44
+ class FirstParameterIndentation < Cop
45
45
  include Alignment
46
46
  include ConfigurableEnforcedStyle
47
47
  include MultilineElementIndentation
@@ -175,12 +175,16 @@ module RuboCop
175
175
  # do_something({foo: 1,
176
176
  # bar: 2})
177
177
  #
178
- class AlignHash < Cop
179
- include HashAlignment
178
+ class HashAlignment < Cop
179
+ include HashAlignmentStyles
180
180
  include RangeHelp
181
181
 
182
- MSG = 'Align the elements of a hash literal if they span more than ' \
183
- 'one line.'
182
+ MESSAGES = { KeyAlignment => 'Align the keys of a hash literal if ' \
183
+ 'they span more than one line.',
184
+ SeparatorAlignment => 'Align the separators of a hash ' \
185
+ 'literal if they span more than one line.',
186
+ TableAlignment => 'Align the keys and values of a hash ' \
187
+ 'literal if they span more than one line.' }.freeze
184
188
 
185
189
  def on_send(node)
186
190
  return if double_splat?(node)
@@ -249,9 +253,9 @@ module RuboCop
249
253
  end
250
254
 
251
255
  def add_offences
252
- _format, offences = offences_by.min_by { |_, v| v.length }
256
+ format, offences = offences_by.min_by { |_, v| v.length }
253
257
  (offences || []).each do |offence|
254
- add_offense offence
258
+ add_offense(offence, message: MESSAGES[format])
255
259
  end
256
260
  end
257
261
 
@@ -8,9 +8,9 @@ module RuboCop
8
8
  # In Ruby 2.3 or newer, squiggly heredocs (`<<~`) should be used. If you
9
9
  # use the older rubies, you should introduce some library to your project
10
10
  # (e.g. ActiveSupport, Powerpack or Unindent).
11
- # Note: When `Metrics/LineLength`'s `AllowHeredoc` is false (not default),
11
+ # Note: When `Layout/LineLength`'s `AllowHeredoc` is false (not default),
12
12
  # this cop does not add any offenses for long here documents to
13
- # avoid `Metrics/LineLength`'s offenses.
13
+ # avoid `Layout/LineLength`'s offenses.
14
14
  #
15
15
  # @example EnforcedStyle: squiggly (default)
16
16
  # # bad
@@ -49,7 +49,7 @@ module RuboCop
49
49
  # something
50
50
  # RUBY
51
51
  #
52
- class IndentHeredoc < Cop
52
+ class HeredocIndentation < Cop
53
53
  include Heredoc
54
54
  include ConfigurableEnforcedStyle
55
55
 
@@ -159,11 +159,11 @@ module RuboCop
159
159
  end
160
160
 
161
161
  def unlimited_heredoc_length?
162
- config.for_cop('Metrics/LineLength')['AllowHeredoc']
162
+ config.for_cop('Layout/LineLength')['AllowHeredoc']
163
163
  end
164
164
 
165
165
  def max_line_length
166
- config.for_cop('Metrics/LineLength')['Max']
166
+ config.for_cop('Layout/LineLength')['Max']
167
167
  end
168
168
 
169
169
  def correct_by_squiggly(node)
@@ -35,6 +35,20 @@ module RuboCop
35
35
  # # Another line of comment
36
36
  # #*
37
37
  #
38
+ # @example AllowGemfileRubyComment: false (default)
39
+ #
40
+ # # bad
41
+ #
42
+ # #ruby=2.7.0
43
+ # #ruby-gemset=myproject
44
+ #
45
+ # @example AllowGemfileRubyComment: true
46
+ #
47
+ # # good
48
+ #
49
+ # #ruby=2.7.0
50
+ # #ruby-gemset=myproject
51
+ #
38
52
  class LeadingCommentSpace < Cop
39
53
  include RangeHelp
40
54
 
@@ -44,7 +58,8 @@ module RuboCop
44
58
  processed_source.each_comment do |comment|
45
59
  next unless comment.text =~ /\A#+[^#\s=:+-]/
46
60
  next if comment.loc.line == 1 && allowed_on_first_line?(comment)
47
- next if allow_doxygen_comment? && doxygen_comment_style?(comment)
61
+ next if doxygen_comment_style?(comment)
62
+ next if gemfile_ruby_comment?(comment)
48
63
 
49
64
  add_offense(comment)
50
65
  end
@@ -80,7 +95,23 @@ module RuboCop
80
95
  end
81
96
 
82
97
  def doxygen_comment_style?(comment)
83
- comment.text.start_with?('#*')
98
+ allow_doxygen_comment? && comment.text.start_with?('#*')
99
+ end
100
+
101
+ def allow_gemfile_ruby_comment?
102
+ cop_config['AllowGemfileRubyComment']
103
+ end
104
+
105
+ def gemfile?
106
+ File.basename(processed_source.file_path).eql?('Gemfile')
107
+ end
108
+
109
+ def ruby_comment_in_gemfile?(comment)
110
+ gemfile? && comment.text.start_with?('#ruby')
111
+ end
112
+
113
+ def gemfile_ruby_comment?(comment)
114
+ allow_gemfile_ruby_comment? && ruby_comment_in_gemfile?(comment)
84
115
  end
85
116
  end
86
117
  end
@@ -27,7 +27,7 @@ module RuboCop
27
27
  # # good
28
28
  # # (start of file)
29
29
  # # a comment
30
- class LeadingBlankLines < Cop
30
+ class LeadingEmptyLines < Cop
31
31
  MSG = 'Unnecessary blank line at the beginning of the source.'
32
32
 
33
33
  def investigate(processed_source)
@@ -2,10 +2,9 @@
2
2
 
3
3
  require 'uri'
4
4
 
5
- # rubocop:disable Metrics/ClassLength
6
5
  module RuboCop
7
6
  module Cop
8
- module Metrics
7
+ module Layout
9
8
  # This cop checks the length of lines in the source code.
10
9
  # The maximum length is configurable.
11
10
  # The tab size is configured in the `IndentationWidth`
@@ -20,19 +19,25 @@ module RuboCop
20
19
  #
21
20
  # If autocorrection is enabled, the following Layout cops
22
21
  # are recommended to further format the broken lines.
22
+ # (Many of these are enabled by default.)
23
23
  #
24
- # - AlignArray
25
- # - AlignHash
26
- # - AlignParameters
24
+ # - ArgumentAlignment
25
+ # - BlockAlignment
26
+ # - BlockDelimiters
27
+ # - BlockEndNewline
27
28
  # - ClosingParenthesisIndentation
28
- # - IndentFirstArgument
29
- # - IndentFirstArrayElement
30
- # - IndentFirstHashElement
31
- # - IndentFirstParameter
29
+ # - FirstArgumentIndentation
30
+ # - FirstArrayElementIndentation
31
+ # - FirstHashElementIndentation
32
+ # - FirstParameterIndentation
33
+ # - HashAlignment
34
+ # - IndentationWidth
32
35
  # - MultilineArrayLineBreaks
36
+ # - MultilineBlockLayout
33
37
  # - MultilineHashBraceLayout
34
38
  # - MultilineHashKeyLineBreaks
35
39
  # - MultilineMethodArgumentLineBreaks
40
+ # - ParameterAlignment
36
41
  #
37
42
  # Together, these cops will pretty print hashes, arrays,
38
43
  # method calls, etc. For example, let's say the max columns
@@ -58,9 +63,14 @@ module RuboCop
58
63
  include ConfigurableMax
59
64
  include IgnoredPattern
60
65
  include RangeHelp
66
+ include LineLengthHelp
61
67
 
62
68
  MSG = 'Line is too long. [%<length>d/%<max>d]'
63
69
 
70
+ def on_block(node)
71
+ check_for_breakable_block(node)
72
+ end
73
+
64
74
  def on_potential_breakable_node(node)
65
75
  check_for_breakable_node(node)
66
76
  end
@@ -68,6 +78,10 @@ module RuboCop
68
78
  alias on_hash on_potential_breakable_node
69
79
  alias on_send on_potential_breakable_node
70
80
 
81
+ def investigate(processed_source)
82
+ check_for_breakable_semicolons(processed_source)
83
+ end
84
+
71
85
  def investigate_post_walk(processed_source)
72
86
  processed_source.lines.each_with_index do |line, line_index|
73
87
  check_line(line, line_index)
@@ -89,29 +103,60 @@ module RuboCop
89
103
  return if breakable_node.nil?
90
104
 
91
105
  line_index = breakable_node.first_line - 1
92
- breakable_nodes_by_line_index[line_index] = breakable_node
106
+ range = breakable_node.source_range
107
+
108
+ existing = breakable_range_by_line_index[line_index]
109
+ return if existing
110
+
111
+ breakable_range_by_line_index[line_index] = range
93
112
  end
94
113
 
95
- def breakable_nodes_by_line_index
96
- @breakable_nodes_by_line_index ||= {}
114
+ def check_for_breakable_semicolons(processed_source)
115
+ tokens = processed_source.tokens.select { |t| t.type == :tSEMI }
116
+ tokens.reverse_each do |token|
117
+ range = breakable_range_after_semicolon(token)
118
+ breakable_range_by_line_index[range.line - 1] = range if range
119
+ end
97
120
  end
98
121
 
99
- def heredocs
100
- @heredocs ||= extract_heredocs(processed_source.ast)
122
+ def check_for_breakable_block(block_node)
123
+ return unless block_node.single_line?
124
+
125
+ line_index = block_node.loc.line - 1
126
+ range = breakable_block_range(block_node)
127
+ pos = range.begin_pos + 1
128
+
129
+ breakable_range_by_line_index[line_index] =
130
+ range_between(pos, pos + 1)
101
131
  end
102
132
 
103
- def tab_indentation_width
104
- config.for_cop('Layout/Tab')['IndentationWidth']
133
+ def breakable_block_range(block_node)
134
+ if block_node.arguments? && !block_node.lambda?
135
+ block_node.arguments.loc.end
136
+ else
137
+ block_node.loc.begin
138
+ end
105
139
  end
106
140
 
107
- def indentation_difference(line)
108
- return 0 unless tab_indentation_width
141
+ def breakable_range_after_semicolon(semicolon_token)
142
+ range = semicolon_token.pos
143
+ end_pos = range.end_pos
144
+ next_range = range_between(end_pos, end_pos + 1)
145
+ return nil unless next_range.line == range.line
109
146
 
110
- line.match(/^\t*/)[0].size * (tab_indentation_width - 1)
147
+ next_char = next_range.source
148
+ return nil if /[\r\n]/ =~ next_char
149
+ return nil if next_char == ';'
150
+
151
+ next_range
152
+ end
153
+
154
+ def breakable_range_by_line_index
155
+ @breakable_range_by_line_index ||= {}
111
156
  end
112
157
 
113
- def line_length(line)
114
- line.length + indentation_difference(line)
158
+ def heredocs
159
+ @heredocs ||= extract_heredocs(processed_source.ast)
115
160
  end
116
161
 
117
162
  def highlight_start(line)
@@ -147,33 +192,12 @@ module RuboCop
147
192
  def register_offense(loc, line, line_index)
148
193
  message = format(MSG, length: line_length(line), max: max)
149
194
 
150
- breakable_range = breakable_range(line, line_index)
195
+ breakable_range = breakable_range_by_line_index[line_index]
151
196
  add_offense(breakable_range, location: loc, message: message) do
152
197
  self.max = line_length(line)
153
198
  end
154
199
  end
155
200
 
156
- def breakable_range(line, line_index)
157
- return if line_in_heredoc?(line_index + 1)
158
-
159
- semicolon_range = breakable_semicolon_range(line, line_index)
160
- return semicolon_range if semicolon_range
161
-
162
- breakable_node = breakable_nodes_by_line_index[line_index]
163
- return breakable_node.source_range if breakable_node
164
- end
165
-
166
- def breakable_semicolon_range(line, line_index)
167
- semicolon_separated_parts = line.split(';')
168
- return if semicolon_separated_parts.length <= 1
169
-
170
- column = semicolon_separated_parts.first.length + 1
171
- range = source_range(processed_source.buffer, line_index, column, 1)
172
- return if processed_source.commented?(range)
173
-
174
- range
175
- end
176
-
177
201
  def excess_range(uri_range, line, line_index)
178
202
  excessive_position = if uri_range && uri_range.begin < max
179
203
  uri_range.end
@@ -222,53 +246,6 @@ module RuboCop
222
246
  end
223
247
  end
224
248
 
225
- def allow_uri?
226
- cop_config['AllowURI']
227
- end
228
-
229
- def ignore_cop_directives?
230
- cop_config['IgnoreCopDirectives']
231
- end
232
-
233
- def allowed_uri_position?(line, uri_range)
234
- uri_range.begin < max &&
235
- (uri_range.end == line_length(line) ||
236
- uri_range.end == line_length(line) - 1)
237
- end
238
-
239
- def find_excessive_uri_range(line)
240
- last_uri_match = match_uris(line).last
241
- return nil unless last_uri_match
242
-
243
- begin_position, end_position =
244
- last_uri_match.offset(0).map do |pos|
245
- pos + indentation_difference(line)
246
- end
247
- return nil if begin_position < max && end_position < max
248
-
249
- begin_position...end_position
250
- end
251
-
252
- def match_uris(string)
253
- matches = []
254
- string.scan(uri_regexp) do
255
- matches << $LAST_MATCH_INFO if valid_uri?($LAST_MATCH_INFO[0])
256
- end
257
- matches
258
- end
259
-
260
- def valid_uri?(uri_ish_string)
261
- URI.parse(uri_ish_string)
262
- true
263
- rescue URI::InvalidURIError, NoMethodError
264
- false
265
- end
266
-
267
- def uri_regexp
268
- @uri_regexp ||=
269
- URI::DEFAULT_PARSER.make_regexp(cop_config['URISchemes'])
270
- end
271
-
272
249
  def check_directive_line(line, line_index)
273
250
  return if line_length_without_directive(line) <= max
274
251
 
@@ -284,23 +261,6 @@ module RuboCop
284
261
  )
285
262
  end
286
263
 
287
- def directive_on_source_line?(line_index)
288
- source_line_number = line_index + processed_source.buffer.first_line
289
- comment =
290
- processed_source
291
- .comments
292
- .detect { |e| e.location.line == source_line_number }
293
-
294
- return false unless comment
295
-
296
- comment.text.match(CommentConfig::COMMENT_DIRECTIVE_REGEXP)
297
- end
298
-
299
- def line_length_without_directive(line)
300
- before_comment, = line.split(CommentConfig::COMMENT_DIRECTIVE_REGEXP)
301
- before_comment.rstrip.length
302
- end
303
-
304
264
  def check_uri_line(line, line_index)
305
265
  uri_range = find_excessive_uri_range(line)
306
266
  return if uri_range && allowed_uri_position?(line, uri_range)
@@ -315,4 +275,3 @@ module RuboCop
315
275
  end
316
276
  end
317
277
  end
318
- # rubocop:enable Metrics/ClassLength