rubocop 0.59.2 → 0.60.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.
Files changed (155) hide show
  1. checksums.yaml +5 -5
  2. data/README.md +3 -2
  3. data/config/default.yml +2960 -552
  4. data/lib/rubocop.rb +1 -0
  5. data/lib/rubocop/ast/builder.rb +29 -29
  6. data/lib/rubocop/ast/node.rb +29 -25
  7. data/lib/rubocop/ast/node/args_node.rb +1 -1
  8. data/lib/rubocop/ast/node/mixin/binary_operator_node.rb +1 -1
  9. data/lib/rubocop/ast/node/mixin/method_dispatch_node.rb +26 -0
  10. data/lib/rubocop/ast/node/mixin/method_identifier_predicates.rb +5 -1
  11. data/lib/rubocop/ast/node/pair_node.rb +8 -1
  12. data/lib/rubocop/ast/node/str_node.rb +1 -1
  13. data/lib/rubocop/cached_data.rb +2 -2
  14. data/lib/rubocop/config.rb +1 -1
  15. data/lib/rubocop/config_loader.rb +8 -0
  16. data/lib/rubocop/cop/autocorrect_logic.rb +7 -1
  17. data/lib/rubocop/cop/bundler/insecure_protocol_source.rb +1 -1
  18. data/lib/rubocop/cop/correctors/alignment_corrector.rb +2 -1
  19. data/lib/rubocop/cop/gemspec/duplicated_assignment.rb +1 -1
  20. data/lib/rubocop/cop/generator.rb +10 -3
  21. data/lib/rubocop/cop/generator/require_file_injector.rb +1 -1
  22. data/lib/rubocop/cop/internal_affairs/node_destructuring.rb +1 -1
  23. data/lib/rubocop/cop/layout/align_hash.rb +9 -1
  24. data/lib/rubocop/cop/layout/block_end_newline.rb +2 -4
  25. data/lib/rubocop/cop/layout/closing_parenthesis_indentation.rb +7 -7
  26. data/lib/rubocop/cop/layout/comment_indentation.rb +1 -1
  27. data/lib/rubocop/cop/layout/dot_position.rb +2 -2
  28. data/lib/rubocop/cop/layout/else_alignment.rb +1 -1
  29. data/lib/rubocop/cop/layout/empty_line_after_magic_comment.rb +1 -2
  30. data/lib/rubocop/cop/layout/empty_lines.rb +1 -1
  31. data/lib/rubocop/cop/layout/empty_lines_around_access_modifier.rb +25 -25
  32. data/lib/rubocop/cop/layout/empty_lines_around_arguments.rb +1 -1
  33. data/lib/rubocop/cop/layout/empty_lines_around_begin_body.rb +1 -1
  34. data/lib/rubocop/cop/layout/empty_lines_around_block_body.rb +1 -1
  35. data/lib/rubocop/cop/layout/empty_lines_around_class_body.rb +1 -1
  36. data/lib/rubocop/cop/layout/empty_lines_around_exception_handling_keywords.rb +1 -1
  37. data/lib/rubocop/cop/layout/empty_lines_around_method_body.rb +1 -1
  38. data/lib/rubocop/cop/layout/empty_lines_around_module_body.rb +1 -1
  39. data/lib/rubocop/cop/layout/end_alignment.rb +1 -1
  40. data/lib/rubocop/cop/layout/first_parameter_indentation.rb +1 -1
  41. data/lib/rubocop/cop/layout/indent_hash.rb +1 -1
  42. data/lib/rubocop/cop/layout/indent_heredoc.rb +2 -2
  43. data/lib/rubocop/cop/layout/indentation_consistency.rb +1 -1
  44. data/lib/rubocop/cop/layout/indentation_width.rb +1 -1
  45. data/lib/rubocop/cop/layout/initial_indentation.rb +1 -1
  46. data/lib/rubocop/cop/layout/multiline_array_brace_layout.rb +1 -1
  47. data/lib/rubocop/cop/layout/multiline_operation_indentation.rb +1 -1
  48. data/lib/rubocop/cop/layout/rescue_ensure_alignment.rb +84 -43
  49. data/lib/rubocop/cop/layout/space_after_method_name.rb +1 -1
  50. data/lib/rubocop/cop/layout/space_around_keyword.rb +1 -1
  51. data/lib/rubocop/cop/layout/space_around_operators.rb +3 -2
  52. data/lib/rubocop/cop/layout/space_inside_array_percent_literal.rb +1 -1
  53. data/lib/rubocop/cop/layout/space_inside_percent_literal_delimiters.rb +2 -2
  54. data/lib/rubocop/cop/lint/ambiguous_operator.rb +5 -5
  55. data/lib/rubocop/cop/lint/assignment_in_condition.rb +10 -20
  56. data/lib/rubocop/cop/lint/ensure_return.rb +3 -0
  57. data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +3 -3
  58. data/lib/rubocop/cop/lint/literal_as_condition.rb +1 -1
  59. data/lib/rubocop/cop/lint/percent_string_array.rb +2 -2
  60. data/lib/rubocop/cop/lint/percent_symbol_array.rb +10 -7
  61. data/lib/rubocop/cop/lint/safe_navigation_consistency.rb +3 -4
  62. data/lib/rubocop/cop/lint/shadowed_argument.rb +1 -2
  63. data/lib/rubocop/cop/lint/syntax.rb +3 -2
  64. data/lib/rubocop/cop/lint/uri_escape_unescape.rb +3 -3
  65. data/lib/rubocop/cop/lint/useless_setter_call.rb +4 -7
  66. data/lib/rubocop/cop/metrics/abc_size.rb +1 -17
  67. data/lib/rubocop/cop/metrics/line_length.rb +14 -10
  68. data/lib/rubocop/cop/metrics/utils/abc_size_calculator.rb +45 -0
  69. data/lib/rubocop/cop/mixin/check_assignment.rb +12 -6
  70. data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +1 -1
  71. data/lib/rubocop/cop/mixin/configurable_formatting.rb +0 -2
  72. data/lib/rubocop/cop/mixin/configurable_max.rb +4 -2
  73. data/lib/rubocop/cop/mixin/configurable_naming.rb +1 -1
  74. data/lib/rubocop/cop/mixin/configurable_numbering.rb +2 -2
  75. data/lib/rubocop/cop/mixin/hash_alignment.rb +32 -5
  76. data/lib/rubocop/cop/mixin/heredoc.rb +1 -1
  77. data/lib/rubocop/cop/mixin/multiline_expression_indentation.rb +3 -4
  78. data/lib/rubocop/cop/mixin/multiline_literal_brace_layout.rb +1 -1
  79. data/lib/rubocop/cop/mixin/statement_modifier.rb +4 -0
  80. data/lib/rubocop/cop/mixin/trailing_comma.rb +1 -1
  81. data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +1 -1
  82. data/lib/rubocop/cop/naming/constant_name.rb +1 -1
  83. data/lib/rubocop/cop/naming/file_name.rb +1 -1
  84. data/lib/rubocop/cop/naming/method_name.rb +2 -0
  85. data/lib/rubocop/cop/naming/variable_number.rb +1 -1
  86. data/lib/rubocop/cop/offense.rb +1 -1
  87. data/lib/rubocop/cop/performance/regexp_match.rb +1 -1
  88. data/lib/rubocop/cop/performance/sample.rb +3 -2
  89. data/lib/rubocop/cop/performance/start_with.rb +1 -1
  90. data/lib/rubocop/cop/performance/string_replacement.rb +1 -1
  91. data/lib/rubocop/cop/rails/date.rb +8 -8
  92. data/lib/rubocop/cop/rails/dynamic_find_by.rb +1 -1
  93. data/lib/rubocop/cop/rails/exit.rb +8 -9
  94. data/lib/rubocop/cop/rails/output_safety.rb +3 -3
  95. data/lib/rubocop/cop/rails/read_write_attribute.rb +5 -4
  96. data/lib/rubocop/cop/rails/refute_methods.rb +13 -13
  97. data/lib/rubocop/cop/rails/reversible_migration.rb +2 -1
  98. data/lib/rubocop/cop/rails/skips_model_validations.rb +17 -0
  99. data/lib/rubocop/cop/registry.rb +11 -2
  100. data/lib/rubocop/cop/style/and_or.rb +3 -3
  101. data/lib/rubocop/cop/style/collection_methods.rb +26 -0
  102. data/lib/rubocop/cop/style/empty_literal.rb +1 -1
  103. data/lib/rubocop/cop/style/encoding.rb +1 -1
  104. data/lib/rubocop/cop/style/even_odd.rb +2 -2
  105. data/lib/rubocop/cop/style/for.rb +3 -3
  106. data/lib/rubocop/cop/style/global_vars.rb +1 -1
  107. data/lib/rubocop/cop/style/identical_conditional_branches.rb +1 -1
  108. data/lib/rubocop/cop/style/if_unless_modifier.rb +1 -13
  109. data/lib/rubocop/cop/style/infinite_loop.rb +1 -1
  110. data/lib/rubocop/cop/style/inverse_methods.rb +1 -1
  111. data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +4 -7
  112. data/lib/rubocop/cop/style/method_def_parentheses.rb +1 -1
  113. data/lib/rubocop/cop/style/module_function.rb +1 -1
  114. data/lib/rubocop/cop/style/multiline_if_then.rb +1 -1
  115. data/lib/rubocop/cop/style/mutable_constant.rb +15 -1
  116. data/lib/rubocop/cop/style/nested_modifier.rb +1 -1
  117. data/lib/rubocop/cop/style/not.rb +2 -1
  118. data/lib/rubocop/cop/style/numeric_literal_prefix.rb +6 -6
  119. data/lib/rubocop/cop/style/numeric_literals.rb +1 -1
  120. data/lib/rubocop/cop/style/numeric_predicate.rb +1 -1
  121. data/lib/rubocop/cop/style/one_line_conditional.rb +2 -2
  122. data/lib/rubocop/cop/style/parentheses_around_condition.rb +1 -1
  123. data/lib/rubocop/cop/style/proc.rb +1 -1
  124. data/lib/rubocop/cop/style/redundant_freeze.rb +10 -0
  125. data/lib/rubocop/cop/style/redundant_parentheses.rb +6 -2
  126. data/lib/rubocop/cop/style/redundant_self.rb +1 -1
  127. data/lib/rubocop/cop/style/special_global_vars.rb +1 -1
  128. data/lib/rubocop/cop/style/stderr_puts.rb +1 -1
  129. data/lib/rubocop/cop/style/ternary_parentheses.rb +4 -3
  130. data/lib/rubocop/cop/style/unneeded_condition.rb +2 -2
  131. data/lib/rubocop/cop/style/unneeded_percent_q.rb +2 -2
  132. data/lib/rubocop/cop/style/unpack_first.rb +1 -1
  133. data/lib/rubocop/cop/team.rb +3 -2
  134. data/lib/rubocop/cop/util.rb +2 -22
  135. data/lib/rubocop/cop/variable_force/scope.rb +3 -3
  136. data/lib/rubocop/cop/variable_force/variable.rb +3 -4
  137. data/lib/rubocop/cop/variable_force/variable_table.rb +2 -2
  138. data/lib/rubocop/formatter/base_formatter.rb +3 -3
  139. data/lib/rubocop/formatter/disabled_config_formatter.rb +16 -1
  140. data/lib/rubocop/formatter/formatter_set.rb +14 -14
  141. data/lib/rubocop/formatter/html_formatter.rb +4 -4
  142. data/lib/rubocop/formatter/json_formatter.rb +13 -13
  143. data/lib/rubocop/formatter/simple_text_formatter.rb +4 -4
  144. data/lib/rubocop/magic_comment.rb +4 -4
  145. data/lib/rubocop/node_pattern.rb +17 -17
  146. data/lib/rubocop/options.rb +93 -82
  147. data/lib/rubocop/result_cache.rb +9 -1
  148. data/lib/rubocop/rspec/expect_offense.rb +2 -2
  149. data/lib/rubocop/rspec/shared_contexts.rb +11 -11
  150. data/lib/rubocop/rspec/shared_examples.rb +4 -4
  151. data/lib/rubocop/string_interpreter.rb +1 -1
  152. data/lib/rubocop/version.rb +1 -1
  153. metadata +6 -13
  154. data/config/disabled.yml +0 -161
  155. data/config/enabled.yml +0 -2092
@@ -27,7 +27,7 @@ module RuboCop
27
27
  expr = args.source_range
28
28
  pos_before_left_paren = range_between(expr.begin_pos - 1,
29
29
  expr.begin_pos)
30
- return unless pos_before_left_paren.source =~ /\s/
30
+ return unless pos_before_left_paren.source.start_with?(' ')
31
31
 
32
32
  add_offense(pos_before_left_paren, location: pos_before_left_paren)
33
33
  end
@@ -222,7 +222,7 @@ module RuboCop
222
222
  node.each_ancestor do |ancestor|
223
223
  return true if ancestor.and_type? || ancestor.or_type?
224
224
  return false unless ancestor.send_type?
225
- return true if operator?(ancestor.method_name)
225
+ return true if ancestor.operator_method?
226
226
  end
227
227
  false
228
228
  end
@@ -23,6 +23,7 @@ module RuboCop
23
23
  include RangeHelp
24
24
 
25
25
  IRREGULAR_METHODS = %i[[] ! []=].freeze
26
+ EXCESSIVE_SPACE = ' '.freeze
26
27
 
27
28
  def self.autocorrect_incompatible_with
28
29
  [Style::SelfAssignment]
@@ -139,12 +140,12 @@ module RuboCop
139
140
  end
140
141
 
141
142
  def excess_leading_space?(operator, with_space)
142
- with_space.source =~ /^ / &&
143
+ with_space.source.start_with?(EXCESSIVE_SPACE) &&
143
144
  (!allow_for_alignment? || !aligned_with_operator?(operator))
144
145
  end
145
146
 
146
147
  def excess_trailing_space?(right_operand, with_space)
147
- with_space.source =~ / $/ &&
148
+ with_space.source.end_with?(EXCESSIVE_SPACE) &&
148
149
  (!allow_for_alignment? || !aligned_with_something?(right_operand))
149
150
  end
150
151
 
@@ -18,7 +18,7 @@ module RuboCop
18
18
 
19
19
  MSG = 'Use only a single space inside array percent literal.'.freeze
20
20
  MULTIPLE_SPACES_BETWEEN_ITEMS_REGEX =
21
- /(?:[\S&&[^\\]](?:\\ )*)( {2,})(?=\S)/
21
+ /(?:[\S&&[^\\]](?:\\ )*)( {2,})(?=\S)/.freeze
22
22
 
23
23
  def on_array(node)
24
24
  process(node, '%i', '%I', '%w', '%W')
@@ -21,8 +21,8 @@ module RuboCop
21
21
  include PercentLiteral
22
22
 
23
23
  MSG = 'Do not use spaces inside percent literal delimiters.'.freeze
24
- BEGIN_REGEX = /\A( +)/
25
- END_REGEX = /(?<!\\)( +)\z/
24
+ BEGIN_REGEX = /\A( +)/.freeze
25
+ END_REGEX = /(?<!\\)( +)\z/.freeze
26
26
 
27
27
  def on_array(node)
28
28
  process(node, '%i', '%I', '%w', '%W')
@@ -24,11 +24,11 @@ module RuboCop
24
24
  include ParserDiagnostic
25
25
 
26
26
  AMBIGUITIES = {
27
- '+' => { actual: 'positive number', possible: 'addition' },
28
- '-' => { actual: 'negative number', possible: 'subtraction' },
29
- '*' => { actual: 'splat', possible: 'multiplication' },
30
- '&' => { actual: 'block', possible: 'binary AND' },
31
- '**' => { actual: 'keyword splat', possible: 'exponent' }
27
+ '+' => { actual: 'positive number', possible: 'addition' },
28
+ '-' => { actual: 'negative number', possible: 'subtraction' },
29
+ '*' => { actual: 'splat', possible: 'multiplication' },
30
+ '&' => { actual: 'block', possible: 'binary AND' },
31
+ '**' => { actual: 'keyword splat', possible: 'exponent' }
32
32
  }.each do |key, hash|
33
33
  hash[:operator] = key
34
34
  end
@@ -31,19 +31,20 @@ module RuboCop
31
31
  MSG_WITHOUT_SAFE_ASSIGNMENT_ALLOWED =
32
32
  'Use `==` if you meant to do a comparison or move the assignment ' \
33
33
  'up out of the condition.'.freeze
34
- ASGN_TYPES = [:begin, *EQUALS_ASGN_NODES, :send].freeze
34
+ ASGN_TYPES = [:begin, *AST::Node::EQUALS_ASSIGNMENTS, :send].freeze
35
35
 
36
36
  def on_if(node)
37
- check(node)
38
- end
37
+ return if node.condition.block_type?
39
38
 
40
- def on_while(node)
41
- check(node)
42
- end
39
+ traverse_node(node.condition, ASGN_TYPES) do |asgn_node|
40
+ next :skip_children if skip_children?(asgn_node)
41
+ next if allowed_construct?(asgn_node)
43
42
 
44
- def on_until(node)
45
- check(node)
43
+ add_offense(asgn_node, location: :operator)
44
+ end
46
45
  end
46
+ alias on_while on_if
47
+ alias on_until on_if
47
48
 
48
49
  private
49
50
 
@@ -55,17 +56,6 @@ module RuboCop
55
56
  end
56
57
  end
57
58
 
58
- def check(node)
59
- return if node.condition.block_type?
60
-
61
- traverse_node(node.condition, ASGN_TYPES) do |asgn_node|
62
- next :skip_children if skip_children?(asgn_node)
63
- next if allowed_construct?(asgn_node)
64
-
65
- add_offense(asgn_node, location: :operator)
66
- end
67
- end
68
-
69
59
  def allowed_construct?(asgn_node)
70
60
  asgn_node.begin_type? || conditional_assignment?(asgn_node)
71
61
  end
@@ -75,7 +65,7 @@ module RuboCop
75
65
  end
76
66
 
77
67
  def skip_children?(asgn_node)
78
- (asgn_node.send_type? && asgn_node.method_name !~ /=\z/) ||
68
+ (asgn_node.send_type? && !asgn_node.assignment_method?) ||
79
69
  empty_condition?(asgn_node) ||
80
70
  (safe_assignment_allowed? && safe_assignment?(asgn_node))
81
71
  end
@@ -4,6 +4,9 @@ module RuboCop
4
4
  module Cop
5
5
  module Lint
6
6
  # This cop checks for *return* from an *ensure* block.
7
+ # Explicit return from an ensure block alters the control flow
8
+ # as the return will take precedence over any exception being raised,
9
+ # and the exception will be silently thrown away as if it were rescued.
7
10
  #
8
11
  # @example
9
12
  #
@@ -23,14 +23,14 @@ module RuboCop
23
23
  MSG = "Number of arguments (%<arg_num>i) to `%<method>s` doesn't " \
24
24
  'match the number of fields (%<field_num>i).'.freeze
25
25
  FIELD_REGEX =
26
- /(%(([\s#+-0\*]*)(\d*)?(\.\d+)?[bBdiouxXeEfgGaAcps]|%))/
27
- NAMED_FIELD_REGEX = /%\{[_a-zA-Z][_a-zA-Z]+\}/
26
+ /(%(([\s#+-0\*]*)(\d*)?(\.\d+)?[bBdiouxXeEfgGaAcps]|%))/.freeze
27
+ NAMED_FIELD_REGEX = /%\{[_a-zA-Z][_a-zA-Z]+\}/.freeze
28
28
  KERNEL = 'Kernel'.freeze
29
29
  SHOVEL = '<<'.freeze
30
30
  PERCENT = '%'.freeze
31
31
  PERCENT_PERCENT = '%%'.freeze
32
32
  STRING_TYPES = %i[str dstr].freeze
33
- NAMED_INTERPOLATION = /%(?:<\w+>|\{\w+\})/
33
+ NAMED_INTERPOLATION = /%(?:<\w+>|\{\w+\})/.freeze
34
34
 
35
35
  def on_send(node)
36
36
  return unless offending_node?(node)
@@ -101,7 +101,7 @@ module RuboCop
101
101
  def check_node(node)
102
102
  if node.send_type? && node.prefix_bang?
103
103
  handle_node(node.receiver)
104
- elsif LOGICAL_OPERATOR_NODES.include?(node.type)
104
+ elsif node.operator_keyword?
105
105
  node.each_child_node { |op| handle_node(op) }
106
106
  elsif node.begin_type? && node.children.one?
107
107
  handle_node(node.children.first)
@@ -24,8 +24,8 @@ module RuboCop
24
24
  include PercentLiteral
25
25
 
26
26
  QUOTES_AND_COMMAS = [/,$/, /^'.*'$/, /^".*"$/].freeze
27
- LEADING_QUOTE = /^['"]/
28
- TRAILING_QUOTE = /['"]?,?$/
27
+ LEADING_QUOTE = /^['"]/.freeze
28
+ TRAILING_QUOTE = /['"]?,?$/.freeze
29
29
 
30
30
  MSG = "Within `%w`/`%W`, quotes and ',' are unnecessary and may be " \
31
31
  'unwanted in the resulting strings.'.freeze
@@ -41,8 +41,9 @@ module RuboCop
41
41
  node.children.each do |child|
42
42
  range = child.loc.expression
43
43
 
44
- corrector.remove_trailing(range, 1) if /,$/ =~ range.source
45
- corrector.remove_leading(range, 1) if /^:/ =~ range.source
44
+ corrector.remove_trailing(range, 1) if range.source.end_with?(',')
45
+ corrector.remove_leading(range, 1) if
46
+ range.source.start_with?(':')
46
47
  end
47
48
  end
48
49
  end
@@ -50,16 +51,18 @@ module RuboCop
50
51
  private
51
52
 
52
53
  def contains_colons_or_commas?(node)
53
- patterns = [/^:/, /,$/]
54
54
  node.children.any? do |child|
55
- literal = child.children.first
55
+ literal = child.children.first.to_s
56
56
 
57
- # To avoid likely false positives (e.g. a single ' or ")
58
- next if literal.to_s.gsub(/[^[[:alnum:]]]/, '').empty?
57
+ next if non_alphanumeric_literal?(literal)
59
58
 
60
- patterns.any? { |pat| literal =~ pat }
59
+ literal.start_with?(':') || literal.end_with?(',')
61
60
  end
62
61
  end
62
+
63
+ def non_alphanumeric_literal?(literal)
64
+ literal !~ /[[:alnum:]]/
65
+ end
63
66
  end
64
67
  end
65
68
  end
@@ -34,8 +34,7 @@ module RuboCop
34
34
  'inside of `&&` and `||`.'.freeze
35
35
 
36
36
  def on_csend(node)
37
- return unless node.parent &&
38
- AST::Node::OPERATOR_KEYWORDS.include?(node.parent.type)
37
+ return unless node.parent && node.parent.operator_keyword?
39
38
 
40
39
  check(node)
41
40
  end
@@ -72,10 +71,10 @@ module RuboCop
72
71
  def top_conditional_ancestor(node)
73
72
  parent = node.parent
74
73
  unless parent &&
75
- (AST::Node::OPERATOR_KEYWORDS.include?(parent.type) ||
74
+ (parent.operator_keyword? ||
76
75
  (parent.begin_type? &&
77
76
  parent.parent &&
78
- AST::Node::OPERATOR_KEYWORDS.include?(parent.parent.type)))
77
+ parent.parent.operator_keyword?))
79
78
  return node
80
79
  end
81
80
 
@@ -154,8 +154,7 @@ module RuboCop
154
154
  def node_within_block_or_conditional?(node, stop_search_node)
155
155
  return false if node == stop_search_node
156
156
 
157
- CONDITIONAL_NODES.include?(node.type) ||
158
- node.block_type? ||
157
+ node.conditional? || node.block_type? ||
159
158
  node_within_block_or_conditional?(node.parent, stop_search_node)
160
159
  end
161
160
 
@@ -3,8 +3,9 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Lint
6
- # This is actually not a cop and inspects nothing. It just provides
7
- # methods to repack Parser's diagnostics/errors into RuboCop's offenses.
6
+ # This is not actually a cop. It does not inspect anything. It just
7
+ # provides methods to repack Parser's diagnostics/errors
8
+ # into RuboCop's offenses.
8
9
  class Syntax < Cop
9
10
  PseudoSourceRange = Struct.new(:line, :column, :source_line, :begin_pos,
10
11
  :end_pos)
@@ -4,11 +4,11 @@ module RuboCop
4
4
  module Cop
5
5
  module Lint
6
6
  # This cop identifies places where `URI.escape` can be replaced by
7
- # `CGI.escape`, `URI.encode_www_form` or `URI.encode_www_form_component`
7
+ # `CGI.escape`, `URI.encode_www_form`, or `URI.encode_www_form_component`
8
8
  # depending on your specific use case.
9
9
  # Also this cop identifies places where `URI.unescape` can be replaced by
10
- # `CGI.unescape`, `URI.decode_www_form` or `URI.decode_www_form_component`
11
- # depending on your specific use case.
10
+ # `CGI.unescape`, `URI.decode_www_form`,
11
+ # or `URI.decode_www_form_component` depending on your specific use case.
12
12
  #
13
13
  # @example
14
14
  # # bad
@@ -49,19 +49,16 @@ module RuboCop
49
49
 
50
50
  private
51
51
 
52
+ def_node_matcher :setter_call_to_local_variable?, <<-PATTERN
53
+ [(send (lvar _) ...) setter_method?]
54
+ PATTERN
55
+
52
56
  def last_expression(body)
53
57
  expression = body.begin_type? ? body.children : body
54
58
 
55
59
  expression.is_a?(Array) ? expression.last : expression
56
60
  end
57
61
 
58
- def setter_call_to_local_variable?(node)
59
- return unless node && node.send_type?
60
- return unless node.receiver && node.receiver.lvar_type?
61
-
62
- node.method_name =~ /(?:\w|\[\])=$/
63
- end
64
-
65
62
  # This class tracks variable assignments in a method body
66
63
  # and if a variable contains object passed as argument at the end of
67
64
  # the method.
@@ -11,27 +11,11 @@ module RuboCop
11
11
 
12
12
  MSG = 'Assignment Branch Condition size for %<method>s is too high. ' \
13
13
  '[%<complexity>.4g/%<max>.4g]'.freeze
14
- BRANCH_NODES = %i[send csend].freeze
15
- CONDITION_NODES = CyclomaticComplexity::COUNTED_NODES.freeze
16
14
 
17
15
  private
18
16
 
19
17
  def complexity(node)
20
- assignment = 0
21
- branch = 0
22
- condition = 0
23
-
24
- node.each_node do |child|
25
- if child.assignment?
26
- assignment += 1
27
- elsif BRANCH_NODES.include?(child.type)
28
- branch += 1
29
- elsif CONDITION_NODES.include?(child.type)
30
- condition += 1
31
- end
32
- end
33
-
34
- Math.sqrt(assignment**2 + branch**2 + condition**2).round(2)
18
+ Utils::AbcSizeCalculator.calculate(node)
35
19
  end
36
20
  end
37
21
  end
@@ -29,17 +29,18 @@ module RuboCop
29
29
  config.for_cop('Layout/Tab')['IndentationWidth']
30
30
  end
31
31
 
32
+ def indentation_difference(line)
33
+ return 0 unless tab_indentation_width
34
+
35
+ line.match(/^\t*/)[0].size * (tab_indentation_width - 1)
36
+ end
37
+
32
38
  def line_length(line)
33
- if tab_indentation_width
34
- line = line.gsub("\t", ' ' * tab_indentation_width)
35
- end
36
- line.length
39
+ line.length + indentation_difference(line)
37
40
  end
38
41
 
39
42
  def highligh_start(line)
40
- return max unless tab_indentation_width
41
-
42
- max - (tab_indentation_width - 1) * line.count("\t")
43
+ max - indentation_difference(line)
43
44
  end
44
45
 
45
46
  def check_line(line, index, heredocs)
@@ -123,15 +124,18 @@ module RuboCop
123
124
 
124
125
  def allowed_uri_position?(line, uri_range)
125
126
  uri_range.begin < max &&
126
- (uri_range.end == line.length ||
127
- uri_range.end == line.length - 1)
127
+ (uri_range.end == line_length(line) ||
128
+ uri_range.end == line_length(line) - 1)
128
129
  end
129
130
 
130
131
  def find_excessive_uri_range(line)
131
132
  last_uri_match = match_uris(line).last
132
133
  return nil unless last_uri_match
133
134
 
134
- begin_position, end_position = last_uri_match.offset(0)
135
+ begin_position, end_position =
136
+ last_uri_match.offset(0).map do |pos|
137
+ pos + indentation_difference(line)
138
+ end
135
139
  return nil if begin_position < max && end_position < max
136
140
 
137
141
  begin_position...end_position
@@ -0,0 +1,45 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Metrics
6
+ module Utils
7
+ # > ABC is .. a software size metric .. computed by counting the number
8
+ # > of assignments, branches and conditions for a section of code.
9
+ # > http://c2.com/cgi/wiki?AbcMetric
10
+ #
11
+ # We separate the *calculator* from the *cop* so that the calculation,
12
+ # the formula itself, is easier to test.
13
+ module AbcSizeCalculator
14
+ # > Branch -- an explicit forward program branch out of scope -- a
15
+ # > function call, class method call ..
16
+ # > http://c2.com/cgi/wiki?AbcMetric
17
+ BRANCH_NODES = %i[send csend].freeze
18
+
19
+ # > Condition -- a logical/Boolean test, == != <= >= < > else case
20
+ # > default try catch ? and unary conditionals.
21
+ # > http://c2.com/cgi/wiki?AbcMetric
22
+ CONDITION_NODES = CyclomaticComplexity::COUNTED_NODES.freeze
23
+
24
+ def self.calculate(node)
25
+ assignment = 0
26
+ branch = 0
27
+ condition = 0
28
+
29
+ node.each_node do |child|
30
+ if child.assignment?
31
+ assignment += 1
32
+ elsif BRANCH_NODES.include?(child.type)
33
+ branch += 1
34
+ elsif CONDITION_NODES.include?(child.type)
35
+ condition += 1
36
+ end
37
+ end
38
+
39
+ Math.sqrt(assignment**2 + branch**2 + condition**2).round(2)
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
45
+ end
@@ -4,11 +4,17 @@ module RuboCop
4
4
  module Cop
5
5
  # Common functionality for checking assignment nodes.
6
6
  module CheckAssignment
7
- Util::ASGN_NODES.each do |type|
8
- define_method("on_#{type}") do |node|
9
- check_assignment(node, extract_rhs(node))
10
- end
7
+ def on_lvasgn(node)
8
+ check_assignment(node, extract_rhs(node))
11
9
  end
10
+ alias on_ivasgn on_lvasgn
11
+ alias on_cvasgn on_lvasgn
12
+ alias on_gvasgn on_lvasgn
13
+ alias on_casgn on_lvasgn
14
+ alias on_masgn on_lvasgn
15
+ alias on_op_asgn on_lvasgn
16
+ alias on_or_asgn on_lvasgn
17
+ alias on_and_asgn on_lvasgn
12
18
 
13
19
  def on_send(node)
14
20
  rhs = extract_rhs(node)
@@ -25,10 +31,10 @@ module RuboCop
25
31
  _scope, _lhs, rhs = *node
26
32
  elsif node.op_asgn_type?
27
33
  _lhs, _op, rhs = *node
28
- elsif Util::ASGN_NODES.include?(node.type)
29
- _lhs, rhs = *node
30
34
  elsif node.send_type?
31
35
  rhs = node.last_argument
36
+ elsif node.assignment?
37
+ _lhs, rhs = *node
32
38
  end
33
39
 
34
40
  rhs