rubocop 0.46.0 → 0.47.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of rubocop might be problematic. Click here for more details.

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