rubocop 0.59.2 → 0.60.0

Sign up to get free protection for your applications and to get access to all the features.
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