rubocop 1.14.0 → 1.15.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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bf17e65fbe829bbc1328bfc1898fe4df1fc1a1e9773b946e1136b3dc16625fd5
4
- data.tar.gz: a35649eeecce4e75f2fb623094b4cc5f93323c1b44393482c0b57e3b37358d86
3
+ metadata.gz: 1009c9da04982d8684219d15bcaaf8a09f5aa3523d8fb668fb47b885281e11ef
4
+ data.tar.gz: fac46c18283c960c698d18f5fd6206cef3d309b2d74bc5046c0c6ba30ca60431
5
5
  SHA512:
6
- metadata.gz: 696e932f19f9f47448de8858c7444be66fb1a58fa25588e26a8b3842a786677bcf3bd49f9f80b945cbbbed3f5826939fbdf8a8cf106e93843e9c659e20d47b10
7
- data.tar.gz: 70729c8cc362bca0ee4397881f2acd0ba088430bfc1c6867e17a9a3da61eff8a0aa911d44a673e1e70d44978638675aedd3717dccfafe3f8cfc78c3f09baeabf
6
+ metadata.gz: 292b418ad2da13f7357a6b3189128ed35a84fa662506de26d4973797e430751b158e9cb0c7a0753c0cded518ba0299cf5bcf1394abb9793aa728b4dedf36863a
7
+ data.tar.gz: cfca1c661ace6abafa34d5506c27ef48afe3ba2abc7187d3fabf41db0abce0c93d59d2f5411671d22fbadea6a09987cda71f2600cc85b5b88b18fca7f526f451
data/README.md CHANGED
@@ -29,6 +29,8 @@ RuboCop is extremely flexible and most aspects of its behavior can be tweaked vi
29
29
  [![OpenCollective](https://opencollective.com/rubocop/sponsors/badge.svg)](#open-collective-sponsors)
30
30
  [![Tidelift](https://tidelift.com/badges/package/rubygems/rubocop)](https://tidelift.com/subscription/pkg/rubygems-rubocop?utm_source=rubygems-rubocop&utm_medium=referral&utm_campaign=readme)
31
31
 
32
+ Working on RuboCop is often fun, but it also requires a great deal of time and energy.
33
+
32
34
  **Please consider [financially supporting its ongoing development](#funding).**
33
35
 
34
36
  ## Installation
@@ -52,7 +54,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
52
54
  in your `Gemfile`:
53
55
 
54
56
  ```rb
55
- gem 'rubocop', '~> 1.14', require: false
57
+ gem 'rubocop', '~> 1.15', require: false
56
58
  ```
57
59
 
58
60
  See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
data/config/default.yml CHANGED
@@ -1612,7 +1612,7 @@ Lint/EmptyBlock:
1612
1612
  Description: 'This cop checks for blocks without a body.'
1613
1613
  Enabled: pending
1614
1614
  VersionAdded: '1.1'
1615
- VersionChanged: '1.3'
1615
+ VersionChanged: '1.15'
1616
1616
  AllowComments: true
1617
1617
  AllowEmptyLambdas: true
1618
1618
 
@@ -3480,6 +3480,7 @@ Style/HashAsLastArrayItem:
3480
3480
 
3481
3481
  Style/HashConversion:
3482
3482
  Description: 'Avoid Hash[] in favor of ary.to_h or literal hashes.'
3483
+ StyleGuide: '#avoid-hash-constructor'
3483
3484
  Enabled: pending
3484
3485
  VersionAdded: '1.10'
3485
3486
  VersionChanged: '1.11'
@@ -3998,6 +3999,7 @@ Style/NilLambda:
3998
3999
  Description: 'Prefer `-> {}` to `-> { nil }`.'
3999
4000
  Enabled: pending
4000
4001
  VersionAdded: '1.3'
4002
+ VersionChanged: '1.15'
4001
4003
 
4002
4004
  Style/NonNilCheck:
4003
4005
  Description: 'Checks for redundant nil checks.'
@@ -4651,6 +4653,12 @@ Style/TernaryParentheses:
4651
4653
  - require_parentheses_when_complex
4652
4654
  AllowSafeAssignment: true
4653
4655
 
4656
+ Style/TopLevelMethodDefinition:
4657
+ Description: 'This cop looks for top-level method definitions.'
4658
+ StyleGuide: '#top-level-methods'
4659
+ Enabled: false
4660
+ VersionAdded: '1.15'
4661
+
4654
4662
  Style/TrailingBodyOnClass:
4655
4663
  Description: 'Class body goes below class statement.'
4656
4664
  Enabled: true
@@ -4737,7 +4745,7 @@ Style/TrivialAccessors:
4737
4745
  StyleGuide: '#attr_family'
4738
4746
  Enabled: true
4739
4747
  VersionAdded: '0.9'
4740
- VersionChanged: '0.77'
4748
+ VersionChanged: '1.15'
4741
4749
  # When set to `false` the cop will suggest the use of accessor methods
4742
4750
  # in situations like:
4743
4751
  #
@@ -4756,7 +4764,7 @@ Style/TrivialAccessors:
4756
4764
  # on_exception :restart
4757
4765
  #
4758
4766
  # Commonly used in DSLs
4759
- AllowDSLWriters: false
4767
+ AllowDSLWriters: true
4760
4768
  IgnoreClassMethods: false
4761
4769
  AllowedMethods:
4762
4770
  - to_ary
data/lib/rubocop.rb CHANGED
@@ -598,6 +598,7 @@ require_relative 'rubocop/cop/style/symbol_array'
598
598
  require_relative 'rubocop/cop/style/symbol_literal'
599
599
  require_relative 'rubocop/cop/style/symbol_proc'
600
600
  require_relative 'rubocop/cop/style/ternary_parentheses'
601
+ require_relative 'rubocop/cop/style/top_level_method_definition'
601
602
  require_relative 'rubocop/cop/style/trailing_body_on_class'
602
603
  require_relative 'rubocop/cop/style/trailing_body_on_method_definition'
603
604
  require_relative 'rubocop/cop/style/trailing_body_on_module'
@@ -41,7 +41,7 @@ module RuboCop
41
41
 
42
42
  EXPECT_NO_OFFENSES_INCORRECT_DESCRIPTIONS = [
43
43
  /^(adds|registers|reports|finds) (an? )?offense/,
44
- /^flags\b/
44
+ /^(flags|handles|works)\b/
45
45
  ].freeze
46
46
 
47
47
  EXPECT_OFFENSE_INCORRECT_DESCRIPTIONS = [
@@ -10,33 +10,39 @@ module RuboCop
10
10
  # # good
11
11
  #
12
12
  # foo :bar,
13
- # :baz
13
+ # :baz,
14
+ # key: value
14
15
  #
15
16
  # foo(
16
17
  # :bar,
17
- # :baz
18
+ # :baz,
19
+ # key: value
18
20
  # )
19
21
  #
20
22
  # # bad
21
23
  #
22
24
  # foo :bar,
23
- # :baz
25
+ # :baz,
26
+ # key: value
24
27
  #
25
28
  # foo(
26
29
  # :bar,
27
- # :baz
30
+ # :baz,
31
+ # key: value
28
32
  # )
29
33
  #
30
34
  # @example EnforcedStyle: with_fixed_indentation
31
35
  # # good
32
36
  #
33
37
  # foo :bar,
34
- # :baz
38
+ # :baz,
39
+ # key: value
35
40
  #
36
41
  # # bad
37
42
  #
38
43
  # foo :bar,
39
- # :baz
44
+ # :baz,
45
+ # key: value
40
46
  class ArgumentAlignment < Base
41
47
  include Alignment
42
48
  extend AutoCorrector
@@ -47,14 +53,25 @@ module RuboCop
47
53
  'following the first line of a multi-line method call.'
48
54
 
49
55
  def on_send(node)
50
- return if node.arguments.size < 2 || node.send_type? && node.method?(:[]=)
56
+ first_arg = node.first_argument
57
+ return if !multiple_arguments?(node, first_arg) || node.send_type? && node.method?(:[]=)
51
58
 
52
- check_alignment(node.arguments, base_column(node, node.arguments))
59
+ if first_arg.hash_type?
60
+ check_alignment(first_arg.pairs, base_column(node, first_arg.pairs.first))
61
+ else
62
+ check_alignment(node.arguments, base_column(node, first_arg))
63
+ end
53
64
  end
54
65
  alias on_csend on_send
55
66
 
56
67
  private
57
68
 
69
+ def multiple_arguments?(node, first_argument)
70
+ return true if node.arguments.size >= 2
71
+
72
+ first_argument&.hash_type? && first_argument.pairs.count >= 2
73
+ end
74
+
58
75
  def autocorrect(corrector, node)
59
76
  AlignmentCorrector.correct(corrector, processed_source, node, column_delta)
60
77
  end
@@ -67,14 +84,14 @@ module RuboCop
67
84
  cop_config['EnforcedStyle'] == 'with_fixed_indentation'
68
85
  end
69
86
 
70
- def base_column(node, args)
71
- if fixed_indentation?
87
+ def base_column(node, first_argument)
88
+ if fixed_indentation? || first_argument.nil?
72
89
  lineno = target_method_lineno(node)
73
90
  line = node.source_range.source_buffer.source_line(lineno)
74
91
  indentation_of_line = /\S.*/.match(line).begin(0)
75
92
  indentation_of_line + configured_indentation_width
76
93
  else
77
- display_column(args.first.source_range)
94
+ display_column(first_argument.source_range)
78
95
  end
79
96
  end
80
97
 
@@ -91,6 +91,8 @@ module RuboCop
91
91
  end
92
92
 
93
93
  def on_send(node)
94
+ return if enforce_first_argument_with_fixed_indentation?
95
+
94
96
  each_argument_node(node, :hash) do |hash_node, left_parenthesis|
95
97
  check(hash_node, left_parenthesis)
96
98
  end
@@ -182,6 +184,16 @@ module RuboCop
182
184
  'where the left brace is.'
183
185
  end
184
186
  end
187
+
188
+ def enforce_first_argument_with_fixed_indentation?
189
+ return false unless argument_alignment_config['Enabled']
190
+
191
+ argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
192
+ end
193
+
194
+ def argument_alignment_config
195
+ config.for_cop('Layout/ArgumentAlignment')
196
+ end
185
197
  end
186
198
  end
187
199
  end
@@ -200,14 +200,12 @@ module RuboCop
200
200
  alias on_super on_send
201
201
  alias on_yield on_send
202
202
 
203
- def on_hash(node) # rubocop:todo Metrics/CyclomaticComplexity
204
- return if ignored_node?(node)
205
- return if node.pairs.empty? || node.single_line?
203
+ def on_hash(node)
204
+ return if enforce_first_argument_with_fixed_indentation? || ignored_node?(node) ||
205
+ node.pairs.empty? || node.single_line?
206
206
 
207
- return unless alignment_for_hash_rockets
208
- .any? { |a| a.checkable_layout?(node) } &&
209
- alignment_for_colons
210
- .any? { |a| a.checkable_layout?(node) }
207
+ proc = ->(a) { a.checkable_layout?(node) }
208
+ return unless alignment_for_hash_rockets.any?(proc) && alignment_for_colons.any?(proc)
211
209
 
212
210
  check_pairs(node)
213
211
  end
@@ -353,6 +351,16 @@ module RuboCop
353
351
  def good_alignment?(column_deltas)
354
352
  column_deltas.values.all?(&:zero?)
355
353
  end
354
+
355
+ def enforce_first_argument_with_fixed_indentation?
356
+ return false unless argument_alignment_config['Enabled']
357
+
358
+ argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
359
+ end
360
+
361
+ def argument_alignment_config
362
+ config.for_cop('Layout/ArgumentAlignment')
363
+ end
356
364
  end
357
365
  end
358
366
  end
@@ -313,9 +313,12 @@ module RuboCop
313
313
  check_rescue?(body_node)
314
314
  elsif body_node.ensure_type?
315
315
  block_body, = *body_node
316
- return unless block_body
317
316
 
318
- check_rescue?(block_body) if block_body.rescue_type?
317
+ if block_body&.rescue_type?
318
+ check_rescue?(block_body)
319
+ else
320
+ !block_body.nil?
321
+ end
319
322
  else
320
323
  true
321
324
  end
@@ -12,6 +12,8 @@ module RuboCop
12
12
  # File.exists?(some_path)
13
13
  # Dir.exists?(some_path)
14
14
  # iterator?
15
+ # Socket.gethostbyname(host)
16
+ # Socket.gethostbyaddr(host)
15
17
  #
16
18
  # @example
17
19
  #
@@ -20,6 +22,8 @@ module RuboCop
20
22
  # File.exist?(some_path)
21
23
  # Dir.exist?(some_path)
22
24
  # block_given?
25
+ # Addrinfo.getaddrinfo(nodename, service)
26
+ # Addrinfo.tcp(host, port).getnameinfo
23
27
  class DeprecatedClassMethods < Base
24
28
  extend AutoCorrector
25
29
 
@@ -7,7 +7,11 @@ module RuboCop
7
7
  # Such empty blocks are typically an oversight or we should provide a comment
8
8
  # be clearer what we're aiming for.
9
9
  #
10
- # Empty lambdas are ignored by default.
10
+ # Empty lambdas and procs are ignored by default.
11
+ #
12
+ # NOTE: For backwards compatibility, the configuration that allows/disallows
13
+ # empty lambdas and procs is called `AllowEmptyLambdas`, even though it also
14
+ # applies to procs.
11
15
  #
12
16
  # @example
13
17
  # # bad
@@ -40,6 +44,10 @@ module RuboCop
40
44
  # end
41
45
  # (callable || placeholder).call
42
46
  #
47
+ # proc { }
48
+ #
49
+ # Proc.new { }
50
+ #
43
51
  # @example AllowEmptyLambdas: false
44
52
  # # bad
45
53
  # allow(subject).to receive(:callable).and_return(-> {})
@@ -48,12 +56,16 @@ module RuboCop
48
56
  # end
49
57
  # (callable || placeholder).call
50
58
  #
59
+ # proc { }
60
+ #
61
+ # Proc.new { }
62
+ #
51
63
  class EmptyBlock < Base
52
64
  MSG = 'Empty block detected.'
53
65
 
54
66
  def on_block(node)
55
67
  return if node.body
56
- return if allow_empty_lambdas? && node.lambda?
68
+ return if allow_empty_lambdas? && lambda_or_proc?(node)
57
69
  return if cop_config['AllowComments'] && allow_comment?(node)
58
70
 
59
71
  add_offense(node)
@@ -76,6 +88,10 @@ module RuboCop
76
88
  regexp_pattern = "# rubocop : (disable|todo) ([^,],)* (all|#{cop_name})"
77
89
  Regexp.new(regexp_pattern.gsub(' ', '\s*')).match?(comment)
78
90
  end
91
+
92
+ def lambda_or_proc?(node)
93
+ node.lambda? || node.proc?
94
+ end
79
95
  end
80
96
  end
81
97
  end
@@ -104,7 +104,7 @@ module RuboCop
104
104
  end
105
105
 
106
106
  def check_literal(node)
107
- return if !node.literal? || node.xstr_type?
107
+ return if !node.literal? || node.xstr_type? || node.range_type?
108
108
 
109
109
  add_offense(node, message: format(LIT_MSG, lit: node.source))
110
110
  end
@@ -70,17 +70,33 @@ module RuboCop
70
70
  def extract_first_element_over_column_limit(node, elements, max)
71
71
  line = node.first_line
72
72
 
73
- # If the first argument is a hash pair but the method is not parenthesized,
74
- # the argument cannot be moved to another line because it cause a syntax error.
75
- elements.shift if node.send_type? && !node.parenthesized? && elements.first.pair_type?
73
+ # If a `send` node is not parenthesized, don't move the first element, because it
74
+ # can result in changed behavior or a syntax error.
75
+ elements = elements.drop(1) if node.send_type? && !node.parenthesized?
76
76
 
77
77
  i = 0
78
78
  i += 1 while within_column_limit?(elements[i], max, line)
79
+ i = shift_elements_for_heredoc_arg(node, elements, i)
80
+
81
+ return if i.nil?
79
82
  return elements.first if i.zero?
80
83
 
81
84
  elements[i - 1]
82
85
  end
83
86
 
87
+ # @api private
88
+ # If a send node contains a heredoc argument, splitting cannot happen
89
+ # after the heredoc or else it will cause a syntax error.
90
+ def shift_elements_for_heredoc_arg(node, elements, index)
91
+ return index unless node.send_type?
92
+
93
+ heredoc_index = elements.index { |arg| (arg.str_type? || arg.dstr_type?) && arg.heredoc? }
94
+ return index unless heredoc_index
95
+ return nil if heredoc_index.zero?
96
+
97
+ heredoc_index >= index ? index : heredoc_index + 1
98
+ end
99
+
84
100
  # @api private
85
101
  def within_column_limit?(element, max, line)
86
102
  element && element.loc.column <= max && element.loc.line == line
@@ -35,6 +35,12 @@ module RuboCop
35
35
  leading_comment_lines.any? { |line| MagicComment.parse(line).frozen_string_literal? }
36
36
  end
37
37
 
38
+ def frozen_string_literals_disabled?
39
+ leading_comment_lines.any? do |line|
40
+ MagicComment.parse(line).frozen_string_literal == false
41
+ end
42
+ end
43
+
38
44
  def frozen_string_literal_specified?
39
45
  leading_comment_lines.any? do |line|
40
46
  MagicComment.parse(line).frozen_string_literal_specified?
@@ -87,9 +87,18 @@ module RuboCop
87
87
  end
88
88
 
89
89
  def compact_node(corrector, node)
90
- replacement = "#{node.body.type} #{compact_identifier_name(node)}"
91
90
  range = range_between(node.loc.keyword.begin_pos, node.body.loc.name.end_pos)
92
- corrector.replace(range, replacement)
91
+ corrector.replace(range, compact_replacement(node))
92
+ end
93
+
94
+ def compact_replacement(node)
95
+ replacement = "#{node.body.type} #{compact_identifier_name(node)}"
96
+
97
+ body_comments = processed_source.ast_with_comments[node.body]
98
+ unless body_comments.empty?
99
+ replacement = body_comments.map(&:text).push(replacement).join("\n")
100
+ end
101
+ replacement
93
102
  end
94
103
 
95
104
  def compact_identifier_name(node)
@@ -132,6 +141,9 @@ module RuboCop
132
141
  end
133
142
 
134
143
  def check_compact_style(node, body)
144
+ parent = node.parent
145
+ return if parent&.class_type? || parent&.module_type?
146
+
135
147
  return unless needs_compacting?(body)
136
148
 
137
149
  add_offense(node.loc.name, message: COMPACT_MSG) do |corrector|
@@ -62,7 +62,7 @@ module RuboCop
62
62
  ARR_MSG
63
63
  elsif offense_hash_node?(node)
64
64
  HASH_MSG
65
- elsif str_node(node) && !frozen_string_literals_enabled?
65
+ elsif str_node(node) && !frozen_strings?
66
66
  format(STR_MSG, prefer: preferred_string_literal)
67
67
  end
68
68
  end
@@ -125,6 +125,13 @@ module RuboCop
125
125
  end
126
126
  end
127
127
  end
128
+
129
+ def frozen_strings?
130
+ return true if frozen_string_literals_enabled?
131
+
132
+ frozen_string_cop_enabled = config.for_cop('Style/FrozenStringLiteral')['Enabled']
133
+ frozen_string_cop_enabled && !frozen_string_literals_disabled?
134
+ end
128
135
  end
129
136
  end
130
137
  end
@@ -3,8 +3,8 @@
3
3
  module RuboCop
4
4
  module Cop
5
5
  module Style
6
- # This cop checks for lambdas that always return nil, which can be replaced
7
- # with an empty lambda instead.
6
+ # This cop checks for lambdas and procs that always return nil,
7
+ # which can be replaced with an empty lambda or proc instead.
8
8
  #
9
9
  # @example
10
10
  # # bad
@@ -14,6 +14,12 @@ module RuboCop
14
14
  # next nil
15
15
  # end
16
16
  #
17
+ # proc { nil }
18
+ #
19
+ # Proc.new do
20
+ # break nil
21
+ # end
22
+ #
17
23
  # # good
18
24
  # -> {}
19
25
  #
@@ -22,11 +28,15 @@ module RuboCop
22
28
  #
23
29
  # -> (x) { nil if x }
24
30
  #
31
+ # proc {}
32
+ #
33
+ # Proc.new { nil if x }
34
+ #
25
35
  class NilLambda < Base
26
36
  extend AutoCorrector
27
37
  include RangeHelp
28
38
 
29
- MSG = 'Use an empty lambda instead of always returning nil.'
39
+ MSG = 'Use an empty %<type>s instead of always returning nil.'
30
40
 
31
41
  # @!method nil_return?(node)
32
42
  def_node_matcher :nil_return?, <<~PATTERN
@@ -34,19 +44,26 @@ module RuboCop
34
44
  PATTERN
35
45
 
36
46
  def on_block(node)
37
- return unless node.lambda?
47
+ return unless node.lambda? || node.proc?
38
48
  return unless nil_return?(node.body)
39
49
 
40
- add_offense(node) do |corrector|
41
- range = if node.single_line?
42
- range_with_surrounding_space(range: node.body.loc.expression)
43
- else
44
- range_by_whole_lines(node.body.loc.expression, include_final_newline: true)
45
- end
46
-
47
- corrector.remove(range)
50
+ message = format(MSG, type: node.lambda? ? 'lambda' : 'proc')
51
+ add_offense(node, message: message) do |corrector|
52
+ autocorrect(corrector, node)
48
53
  end
49
54
  end
55
+
56
+ private
57
+
58
+ def autocorrect(corrector, node)
59
+ range = if node.single_line?
60
+ range_with_surrounding_space(range: node.body.loc.expression)
61
+ else
62
+ range_by_whole_lines(node.body.loc.expression, include_final_newline: true)
63
+ end
64
+
65
+ corrector.remove(range)
66
+ end
50
67
  end
51
68
  end
52
69
  end
@@ -110,7 +110,7 @@ module RuboCop
110
110
  first_child = node.children.first
111
111
 
112
112
  source = first_child.source
113
- source = "(#{source})" if first_child.if_type?
113
+ source = "(#{source})" if first_child.if_type? && first_child.modifier_form?
114
114
 
115
115
  corrector.replace(offense_range, source)
116
116
  corrector.remove(range_between(offense_range.end_pos, first_child.source_range.end_pos))
@@ -0,0 +1,75 @@
1
+ # frozen_string_literal: true
2
+
3
+ module RuboCop
4
+ module Cop
5
+ module Style
6
+ # Newcomers to ruby applications may write top-level methods,
7
+ # when ideally they should be organized in appropriate classes or modules.
8
+ # This cop looks for definitions of top-level methods and warns about them.
9
+ #
10
+ # However for ruby scripts it is perfectly fine to use top-level methods.
11
+ # Hence this cop is disabled by default.
12
+ #
13
+ # @example
14
+ # # bad
15
+ # def some_method
16
+ # end
17
+ #
18
+ # # bad
19
+ # def self.some_method
20
+ # end
21
+ #
22
+ # # bad
23
+ # define_method(:foo) { puts 1 }
24
+ #
25
+ # # good
26
+ # module Foo
27
+ # def some_method
28
+ # end
29
+ # end
30
+ #
31
+ # # good
32
+ # class Foo
33
+ # def self.some_method
34
+ # end
35
+ # end
36
+ #
37
+ # # good
38
+ # Struct.new do
39
+ # def some_method
40
+ # end
41
+ # end
42
+ #
43
+ # # good
44
+ # class Foo
45
+ # define_method(:foo) { puts 1 }
46
+ # end
47
+ class TopLevelMethodDefinition < Base
48
+ MSG = 'Do not define methods at the top-level.'
49
+
50
+ RESTRICT_ON_SEND = %i[define_method].freeze
51
+
52
+ def on_def(node)
53
+ return unless node.root?
54
+
55
+ add_offense(node)
56
+ end
57
+ alias on_defs on_def
58
+ alias on_send on_def
59
+
60
+ def on_block(node)
61
+ return unless define_method_block?(node) && node.root?
62
+
63
+ add_offense(node)
64
+ end
65
+
66
+ private
67
+
68
+ # @!method define_method_block?(node)
69
+ def_node_matcher :define_method_block?, <<~PATTERN
70
+ (block (send _ {:define_method} _) ...)
71
+ PATTERN
72
+ end
73
+ end
74
+ end
75
+ end
@@ -27,6 +27,71 @@ module RuboCop
27
27
  # class << self
28
28
  # attr_reader :baz
29
29
  # end
30
+ #
31
+ # @example ExactNameMatch: true (default)
32
+ # # good
33
+ # def name
34
+ # @other_name
35
+ # end
36
+ #
37
+ # @example ExactNameMatch: false
38
+ # # bad
39
+ # def name
40
+ # @other_name
41
+ # end
42
+ #
43
+ # @example AllowPredicates: true (default)
44
+ # # good
45
+ # def foo?
46
+ # @foo
47
+ # end
48
+ #
49
+ # @example AllowPredicates: false
50
+ # # bad
51
+ # def foo?
52
+ # @foo
53
+ # end
54
+ #
55
+ # # good
56
+ # attr_reader :foo
57
+ #
58
+ # @example AllowDSLWriters: true (default)
59
+ # # good
60
+ # def on_exception(action)
61
+ # @on_exception=action
62
+ # end
63
+ #
64
+ # @example AllowDSLWriters: false
65
+ # # bad
66
+ # def on_exception(action)
67
+ # @on_exception=action
68
+ # end
69
+ #
70
+ # # good
71
+ # attr_writer :on_exception
72
+ #
73
+ # @example IgnoreClassMethods: false (default)
74
+ # # bad
75
+ # def self.foo
76
+ # @foo
77
+ # end
78
+ #
79
+ # # good
80
+ # class << self
81
+ # attr_reader :foo
82
+ # end
83
+ #
84
+ # @example IgnoreClassMethods: true
85
+ # # good
86
+ # def self.foo
87
+ # @foo
88
+ # end
89
+ #
90
+ # @example AllowedMethods: ['allowed_method']
91
+ # # good
92
+ # def allowed_method
93
+ # @foo
94
+ # end
30
95
  class TrivialAccessors < Base
31
96
  include AllowedMethods
32
97
  extend AutoCorrector
@@ -22,9 +22,13 @@ module RuboCop
22
22
  testsuites = REXML::Element.new('testsuites', @document)
23
23
  testsuite = REXML::Element.new('testsuite', testsuites)
24
24
  @testsuite = testsuite.tap { |element| element.add_attributes('name' => 'rubocop') }
25
+
26
+ reset_count
25
27
  end
26
28
 
27
29
  def file_finished(file, offenses)
30
+ @inspected_file_count += 1
31
+
28
32
  # TODO: Returns all cops with the same behavior as
29
33
  # the original rubocop-junit-formatter.
30
34
  # https://github.com/mikian/rubocop-junit-formatter/blob/v0.1.4/lib/rubocop/formatter/junit_formatter.rb#L9
@@ -32,15 +36,11 @@ module RuboCop
32
36
  # In the future, it would be preferable to return only enabled cops.
33
37
  Cop::Registry.all.each do |cop|
34
38
  target_offenses = offenses_for_cop(offenses, cop)
39
+ @offense_count += target_offenses.count
35
40
 
36
41
  next unless relevant_for_output?(options, target_offenses)
37
42
 
38
- REXML::Element.new('testcase', @testsuite).tap do |testcase|
39
- testcase.attributes['classname'] = classname_attribute_value(file)
40
- testcase.attributes['name'] = cop.cop_name
41
-
42
- add_failure_to(testcase, target_offenses, cop.cop_name)
43
- end
43
+ add_testcase_element_to_testsuite_element(file, target_offenses, cop)
44
44
  end
45
45
  end
46
46
 
@@ -52,16 +52,31 @@ module RuboCop
52
52
  all_offenses.select { |offense| offense.cop_name == cop.cop_name }
53
53
  end
54
54
 
55
+ def add_testcase_element_to_testsuite_element(file, target_offenses, cop)
56
+ REXML::Element.new('testcase', @testsuite).tap do |testcase|
57
+ testcase.attributes['classname'] = classname_attribute_value(file)
58
+ testcase.attributes['name'] = cop.cop_name
59
+
60
+ add_failure_to(testcase, target_offenses, cop.cop_name)
61
+ end
62
+ end
63
+
55
64
  def classname_attribute_value(file)
56
65
  file.gsub(/\.rb\Z/, '').gsub("#{Dir.pwd}/", '').tr('/', '.')
57
66
  end
58
67
 
59
68
  def finished(_inspected_files)
69
+ @testsuite.add_attributes('tests' => @inspected_file_count, 'failures' => @offense_count)
60
70
  @document.write(output, 2)
61
71
  end
62
72
 
63
73
  private
64
74
 
75
+ def reset_count
76
+ @inspected_file_count = 0
77
+ @offense_count = 0
78
+ end
79
+
65
80
  def add_failure_to(testcase, offenses, cop_name)
66
81
  # One failure per offense. Zero failures is a passing test case,
67
82
  # for most surefire/nUnit parsers.
@@ -297,7 +297,7 @@ module RuboCop
297
297
  validate_auto_gen_config
298
298
  validate_auto_correct
299
299
  validate_display_only_failed
300
- validate_parallel
300
+ disable_parallel_when_invalid_option_combo
301
301
 
302
302
  return if incompatible_options.size <= 1
303
303
 
@@ -334,33 +334,27 @@ module RuboCop
334
334
  format('--disable-uncorrectable can only be used together with --auto-correct.')
335
335
  end
336
336
 
337
- def validate_parallel
337
+ def disable_parallel_when_invalid_option_combo
338
338
  return unless @options.key?(:parallel)
339
339
 
340
- if @options[:cache] == 'false'
341
- raise OptionArgumentError, '-P/--parallel uses caching to speed up ' \
342
- 'execution, so combining with --cache ' \
343
- 'false is not allowed.'
344
- end
345
-
346
- disable_parallel_when_invalid_combo
347
- end
340
+ invalid_options = [
341
+ { name: :auto_gen_config, value: true, flag: '--auto-gen-config' },
342
+ { name: :fail_fast, value: true, flag: '-F/--fail-fast.' },
343
+ { name: :auto_correct, value: true, flag: '--auto-correct.' },
344
+ { name: :cache, value: 'false', flag: '--cache false' }
345
+ ]
348
346
 
349
- def disable_parallel_when_invalid_combo
350
- combos = {
351
- auto_gen_config: '--auto-gen-config',
352
- fail_fast: '-F/--fail-fast.',
353
- auto_correct: '--auto-correct.'
354
- }
355
-
356
- invalid_combos = combos.select { |key, _flag| @options.key?(key) }
347
+ invalid_flags = invalid_options.each_with_object([]) do |option, flags|
348
+ # `>` rather than `>=` because `@options` will also contain `parallel: true`
349
+ flags << option[:flag] if @options > { option[:name] => option[:value] }
350
+ end
357
351
 
358
- return if invalid_combos.empty?
352
+ return if invalid_flags.empty?
359
353
 
360
354
  @options.delete(:parallel)
361
355
 
362
356
  puts '-P/--parallel is being ignored because ' \
363
- "it is not compatible with #{invalid_combos.values.join(', ')}"
357
+ "it is not compatible with #{invalid_flags.join(', ')}"
364
358
  end
365
359
 
366
360
  def only_includes_redundant_disable?
@@ -3,7 +3,7 @@
3
3
  module RuboCop
4
4
  # This module holds the RuboCop version information.
5
5
  module Version
6
- STRING = '1.14.0'
6
+ STRING = '1.15.0'
7
7
 
8
8
  MSG = '%<version>s (using Parser %<parser_version>s, '\
9
9
  'rubocop-ast %<rubocop_ast_version>s, ' \
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rubocop
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.14.0
4
+ version: 1.15.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Bozhidar Batsov
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: exe
12
12
  cert_chain: []
13
- date: 2021-05-05 00:00:00.000000000 Z
13
+ date: 2021-05-17 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: parallel
@@ -786,6 +786,7 @@ files:
786
786
  - lib/rubocop/cop/style/symbol_literal.rb
787
787
  - lib/rubocop/cop/style/symbol_proc.rb
788
788
  - lib/rubocop/cop/style/ternary_parentheses.rb
789
+ - lib/rubocop/cop/style/top_level_method_definition.rb
789
790
  - lib/rubocop/cop/style/trailing_body_on_class.rb
790
791
  - lib/rubocop/cop/style/trailing_body_on_method_definition.rb
791
792
  - lib/rubocop/cop/style/trailing_body_on_module.rb
@@ -875,7 +876,7 @@ metadata:
875
876
  homepage_uri: https://rubocop.org/
876
877
  changelog_uri: https://github.com/rubocop/rubocop/blob/master/CHANGELOG.md
877
878
  source_code_uri: https://github.com/rubocop/rubocop/
878
- documentation_uri: https://docs.rubocop.org/rubocop/1.14/
879
+ documentation_uri: https://docs.rubocop.org/rubocop/1.15/
879
880
  bug_tracker_uri: https://github.com/rubocop/rubocop/issues
880
881
  post_install_message:
881
882
  rdoc_options: []