rubocop 1.40.0 → 1.41.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 +4 -4
- data/README.md +1 -1
- data/config/default.yml +18 -0
- data/lib/rubocop/config.rb +28 -5
- data/lib/rubocop/config_loader.rb +9 -0
- data/lib/rubocop/config_validator.rb +1 -1
- data/lib/rubocop/cop/badge.rb +9 -4
- data/lib/rubocop/cop/base.rb +25 -9
- data/lib/rubocop/cop/commissioner.rb +8 -3
- data/lib/rubocop/cop/cop.rb +1 -1
- data/lib/rubocop/cop/internal_affairs/cop_description.rb +3 -1
- data/lib/rubocop/cop/layout/empty_lines.rb +2 -0
- data/lib/rubocop/cop/layout/extra_spacing.rb +10 -6
- data/lib/rubocop/cop/layout/first_array_element_line_break.rb +38 -2
- data/lib/rubocop/cop/layout/first_hash_element_line_break.rb +49 -2
- data/lib/rubocop/cop/layout/first_method_argument_line_break.rb +61 -2
- data/lib/rubocop/cop/layout/first_method_parameter_line_break.rb +52 -2
- data/lib/rubocop/cop/layout/indentation_style.rb +3 -1
- data/lib/rubocop/cop/layout/line_continuation_leading_space.rb +5 -0
- data/lib/rubocop/cop/layout/line_continuation_spacing.rb +7 -1
- data/lib/rubocop/cop/layout/line_length.rb +2 -0
- data/lib/rubocop/cop/layout/multiline_array_line_breaks.rb +51 -2
- data/lib/rubocop/cop/layout/multiline_hash_key_line_breaks.rb +49 -2
- data/lib/rubocop/cop/layout/multiline_method_argument_line_breaks.rb +53 -2
- data/lib/rubocop/cop/layout/multiline_method_parameter_line_breaks.rb +58 -2
- data/lib/rubocop/cop/layout/redundant_line_break.rb +2 -2
- data/lib/rubocop/cop/layout/trailing_empty_lines.rb +1 -1
- data/lib/rubocop/cop/layout/trailing_whitespace.rb +6 -2
- data/lib/rubocop/cop/lint/constant_resolution.rb +4 -0
- data/lib/rubocop/cop/lint/debugger.rb +3 -1
- data/lib/rubocop/cop/lint/duplicate_branch.rb +0 -2
- data/lib/rubocop/cop/lint/duplicate_methods.rb +19 -8
- data/lib/rubocop/cop/lint/non_atomic_file_operation.rb +10 -5
- data/lib/rubocop/cop/lint/redundant_cop_enable_directive.rb +1 -1
- data/lib/rubocop/cop/lint/safe_navigation_chain.rb +8 -19
- data/lib/rubocop/cop/metrics/class_length.rb +1 -1
- data/lib/rubocop/cop/metrics/module_length.rb +1 -1
- data/lib/rubocop/cop/metrics/utils/code_length_calculator.rb +2 -2
- data/lib/rubocop/cop/mixin/alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/allowed_identifiers.rb +2 -2
- data/lib/rubocop/cop/mixin/annotation_comment.rb +13 -6
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +21 -9
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +11 -7
- data/lib/rubocop/cop/mixin/hash_shorthand_syntax.rb +5 -1
- data/lib/rubocop/cop/mixin/line_length_help.rb +8 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +5 -3
- data/lib/rubocop/cop/mixin/multiline_element_line_breaks.rb +5 -3
- data/lib/rubocop/cop/mixin/percent_array.rb +3 -5
- data/lib/rubocop/cop/mixin/require_library.rb +2 -0
- data/lib/rubocop/cop/mixin/rescue_node.rb +3 -3
- data/lib/rubocop/cop/mixin/statement_modifier.rb +1 -1
- data/lib/rubocop/cop/naming/class_and_module_camel_case.rb +2 -0
- data/lib/rubocop/cop/naming/inclusive_language.rb +4 -1
- data/lib/rubocop/cop/registry.rb +6 -3
- data/lib/rubocop/cop/style/concat_array_literals.rb +66 -0
- data/lib/rubocop/cop/style/documentation.rb +1 -1
- data/lib/rubocop/cop/style/guard_clause.rb +5 -1
- data/lib/rubocop/cop/style/if_with_semicolon.rb +2 -3
- data/lib/rubocop/cop/style/inverse_methods.rb +2 -0
- data/lib/rubocop/cop/style/line_end_concatenation.rb +4 -1
- data/lib/rubocop/cop/style/redundant_constant_base.rb +13 -0
- data/lib/rubocop/cop/style/redundant_double_splat_hash_braces.rb +39 -0
- data/lib/rubocop/cop/style/require_order.rb +61 -9
- data/lib/rubocop/cop/style/semicolon.rb +2 -1
- data/lib/rubocop/cop/util.rb +31 -4
- data/lib/rubocop/cops_documentation_generator.rb +22 -3
- data/lib/rubocop/directive_comment.rb +1 -1
- data/lib/rubocop/file_patterns.rb +43 -0
- data/lib/rubocop/options.rb +1 -1
- data/lib/rubocop/path_util.rb +20 -14
- data/lib/rubocop/target_finder.rb +1 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +3 -1
- metadata +6 -4
- data/lib/rubocop/optimized_patterns.rb +0 -38
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 77b5fe782c4a109e75c380273e08f38b9c61eb519f11f19a606a380080f1f0a2
|
4
|
+
data.tar.gz: fa67b5a3f120d6f1538963f9ddbc8bd0508b7f54763bd7c76da725054c9e0459
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1475ad1af84e34c10ccf4905247b6e1090e0bd2969d6eb5ef2c4f4dec116841d438b42c5f4c84678870ffac0703f663e1f1ea79ce588b74caca27162f5ad6c07
|
7
|
+
data.tar.gz: 267189e76baac7ebc2632d3249957987ba9a3db3df26fa1bf7abe4510a7f9baf8cf5bec399b024d1e900accd1b55f2a5c72e8ab3686d1edc656272ef9723bdaf
|
data/README.md
CHANGED
@@ -53,7 +53,7 @@ To prevent an unwanted RuboCop update you might want to use a conservative versi
|
|
53
53
|
in your `Gemfile`:
|
54
54
|
|
55
55
|
```rb
|
56
|
-
gem 'rubocop', '~> 1.
|
56
|
+
gem 'rubocop', '~> 1.41', require: false
|
57
57
|
```
|
58
58
|
|
59
59
|
See [our versioning policy](https://docs.rubocop.org/rubocop/versioning.html) for further details.
|
data/config/default.yml
CHANGED
@@ -762,6 +762,7 @@ Layout/FirstArrayElementLineBreak:
|
|
762
762
|
multi-line array.
|
763
763
|
Enabled: false
|
764
764
|
VersionAdded: '0.49'
|
765
|
+
AllowMultilineFinalElement: false
|
765
766
|
|
766
767
|
Layout/FirstHashElementIndentation:
|
767
768
|
Description: 'Checks the indentation of the first key in a hash literal.'
|
@@ -794,6 +795,7 @@ Layout/FirstHashElementLineBreak:
|
|
794
795
|
multi-line hash.
|
795
796
|
Enabled: false
|
796
797
|
VersionAdded: '0.49'
|
798
|
+
AllowMultilineFinalElement: false
|
797
799
|
|
798
800
|
Layout/FirstMethodArgumentLineBreak:
|
799
801
|
Description: >-
|
@@ -801,6 +803,7 @@ Layout/FirstMethodArgumentLineBreak:
|
|
801
803
|
multi-line method call.
|
802
804
|
Enabled: false
|
803
805
|
VersionAdded: '0.49'
|
806
|
+
AllowMultilineFinalElement: false
|
804
807
|
|
805
808
|
Layout/FirstMethodParameterLineBreak:
|
806
809
|
Description: >-
|
@@ -808,6 +811,7 @@ Layout/FirstMethodParameterLineBreak:
|
|
808
811
|
multi-line method parameter definition.
|
809
812
|
Enabled: false
|
810
813
|
VersionAdded: '0.49'
|
814
|
+
AllowMultilineFinalElement: false
|
811
815
|
|
812
816
|
Layout/FirstParameterIndentation:
|
813
817
|
Description: >-
|
@@ -1067,6 +1071,7 @@ Layout/MultilineArrayLineBreaks:
|
|
1067
1071
|
starts on a separate line.
|
1068
1072
|
Enabled: false
|
1069
1073
|
VersionAdded: '0.67'
|
1074
|
+
AllowMultilineFinalElement: false
|
1070
1075
|
|
1071
1076
|
Layout/MultilineAssignmentLayout:
|
1072
1077
|
Description: 'Check for a newline after the assignment operator in multi-line assignments.'
|
@@ -1117,6 +1122,7 @@ Layout/MultilineHashKeyLineBreaks:
|
|
1117
1122
|
starts on a separate line.
|
1118
1123
|
Enabled: false
|
1119
1124
|
VersionAdded: '0.67'
|
1125
|
+
AllowMultilineFinalElement: false
|
1120
1126
|
|
1121
1127
|
Layout/MultilineMethodArgumentLineBreaks:
|
1122
1128
|
Description: >-
|
@@ -1124,6 +1130,7 @@ Layout/MultilineMethodArgumentLineBreaks:
|
|
1124
1130
|
starts on a separate line.
|
1125
1131
|
Enabled: false
|
1126
1132
|
VersionAdded: '0.67'
|
1133
|
+
AllowMultilineFinalElement: false
|
1127
1134
|
|
1128
1135
|
Layout/MultilineMethodCallBraceLayout:
|
1129
1136
|
Description: >-
|
@@ -1178,6 +1185,7 @@ Layout/MultilineMethodParameterLineBreaks:
|
|
1178
1185
|
starts on a separate line.
|
1179
1186
|
Enabled: false
|
1180
1187
|
VersionAdded: '1.32'
|
1188
|
+
AllowMultilineFinalElement: false
|
1181
1189
|
|
1182
1190
|
Layout/MultilineOperationIndentation:
|
1183
1191
|
Description: >-
|
@@ -3418,6 +3426,11 @@ Style/CommentedKeyword:
|
|
3418
3426
|
VersionAdded: '0.51'
|
3419
3427
|
VersionChanged: '1.19'
|
3420
3428
|
|
3429
|
+
Style/ConcatArrayLiterals:
|
3430
|
+
Description: 'Enforces the use of `Array#push(item)` instead of `Array#concat([item])` to avoid redundant array literals.'
|
3431
|
+
Enabled: pending
|
3432
|
+
VersionAdded: '1.41'
|
3433
|
+
|
3421
3434
|
Style/ConditionalAssignment:
|
3422
3435
|
Description: >-
|
3423
3436
|
Use the return value of `if` and `case` statements for
|
@@ -4731,6 +4744,11 @@ Style/RedundantConstantBase:
|
|
4731
4744
|
Enabled: pending
|
4732
4745
|
VersionAdded: '1.40'
|
4733
4746
|
|
4747
|
+
Style/RedundantDoubleSplatHashBraces:
|
4748
|
+
Description: 'Checks for redundant uses of double splat hash braces.'
|
4749
|
+
Enabled: pending
|
4750
|
+
VersionAdded: '1.41'
|
4751
|
+
|
4734
4752
|
Style/RedundantEach:
|
4735
4753
|
Description: 'Checks for redundant `each`.'
|
4736
4754
|
Enabled: pending
|
data/lib/rubocop/config.rb
CHANGED
@@ -21,6 +21,7 @@ module RuboCop
|
|
21
21
|
DEFAULT_RAILS_VERSION = 5.0
|
22
22
|
attr_reader :loaded_path
|
23
23
|
|
24
|
+
# rubocop:disable Metrics/AbcSize
|
24
25
|
def initialize(hash = {}, loaded_path = nil)
|
25
26
|
@loaded_path = loaded_path
|
26
27
|
@for_cop = Hash.new do |h, cop|
|
@@ -32,7 +33,11 @@ module RuboCop
|
|
32
33
|
end
|
33
34
|
@hash = hash
|
34
35
|
@validator = ConfigValidator.new(self)
|
36
|
+
|
37
|
+
@badge_config_cache = {}.compare_by_identity
|
38
|
+
@clusivity_config_exists_cache = {}
|
35
39
|
end
|
40
|
+
# rubocop:enable Metrics/AbcSize
|
36
41
|
|
37
42
|
def self.create(hash, path, check: true)
|
38
43
|
config = new(hash, path)
|
@@ -123,8 +128,25 @@ module RuboCop
|
|
123
128
|
# @return [Config] for the given cop merged with that of its department (if any)
|
124
129
|
# Note: the 'Enabled' attribute is same as that returned by `for_cop`
|
125
130
|
def for_badge(badge)
|
126
|
-
|
127
|
-
|
131
|
+
@badge_config_cache[badge] ||= begin
|
132
|
+
department_config = self[badge.department_name]
|
133
|
+
cop_config = for_cop(badge.to_s)
|
134
|
+
if department_config
|
135
|
+
department_config.merge(cop_config)
|
136
|
+
else
|
137
|
+
cop_config
|
138
|
+
end
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
# @return [Boolean] whether config for this badge has 'Include' or 'Exclude' keys
|
143
|
+
# @api private
|
144
|
+
def clusivity_config_for_badge?(badge)
|
145
|
+
exists = @clusivity_config_exists_cache[badge.to_s]
|
146
|
+
return exists unless exists.nil?
|
147
|
+
|
148
|
+
cop_config = for_badge(badge)
|
149
|
+
@clusivity_config_exists_cache[badge.to_s] = cop_config['Include'] || cop_config['Exclude']
|
128
150
|
end
|
129
151
|
|
130
152
|
# @return [Config] for the given department name.
|
@@ -273,9 +295,10 @@ module RuboCop
|
|
273
295
|
return nil unless lock_file_path
|
274
296
|
|
275
297
|
File.foreach(lock_file_path) do |line|
|
276
|
-
# If
|
277
|
-
#
|
278
|
-
|
298
|
+
# If Rails (or one of its frameworks) is in Gemfile.lock or gems.lock, there should be
|
299
|
+
# a line like:
|
300
|
+
# railties (X.X.X)
|
301
|
+
result = line.match(/^\s+railties\s+\((\d+\.\d+)/)
|
279
302
|
return result.captures.first.to_f if result
|
280
303
|
end
|
281
304
|
end
|
@@ -137,6 +137,15 @@ module RuboCop
|
|
137
137
|
end
|
138
138
|
end
|
139
139
|
|
140
|
+
# @api private
|
141
|
+
def inject_defaults!(project_root)
|
142
|
+
path = File.join(project_root, 'config', 'default.yml')
|
143
|
+
config = load_file(path)
|
144
|
+
new_config = ConfigLoader.merge_with_default(config, path)
|
145
|
+
puts "configuration from #{path}" if debug?
|
146
|
+
@default_configuration = new_config
|
147
|
+
end
|
148
|
+
|
140
149
|
# Returns the path RuboCop inferred as the root of the project. No file
|
141
150
|
# searches will go past this directory.
|
142
151
|
# @deprecated Use `RuboCop::ConfigFinder.project_root` instead.
|
@@ -162,7 +162,7 @@ module RuboCop
|
|
162
162
|
return unless syntax_config && default_config.merge(syntax_config) != default_config
|
163
163
|
|
164
164
|
raise ValidationError,
|
165
|
-
"configuration for Syntax cop found in #{smart_loaded_path}\n" \
|
165
|
+
"configuration for Lint/Syntax cop found in #{smart_loaded_path}\n" \
|
166
166
|
'It\'s not possible to disable this cop.'
|
167
167
|
end
|
168
168
|
|
data/lib/rubocop/cop/badge.rb
CHANGED
@@ -10,7 +10,7 @@ module RuboCop
|
|
10
10
|
# allow for badge references in source files that omit the department for
|
11
11
|
# RuboCop to infer.
|
12
12
|
class Badge
|
13
|
-
attr_reader :department, :cop_name
|
13
|
+
attr_reader :department, :department_name, :cop_name
|
14
14
|
|
15
15
|
def self.for(class_name)
|
16
16
|
parts = class_name.split('::')
|
@@ -18,19 +18,23 @@ module RuboCop
|
|
18
18
|
new(name_deep_enough ? parts[2..] : parts.last(2))
|
19
19
|
end
|
20
20
|
|
21
|
+
@parse_cache = {}
|
22
|
+
|
21
23
|
def self.parse(identifier)
|
22
|
-
new(identifier.split('/').map { |i| camel_case(i) })
|
24
|
+
@parse_cache[identifier] ||= new(identifier.split('/').map! { |i| camel_case(i) })
|
23
25
|
end
|
24
26
|
|
25
27
|
def self.camel_case(name_part)
|
26
28
|
return 'RSpec' if name_part == 'rspec'
|
29
|
+
return name_part unless name_part.match?(/^[a-z]|_[a-z]/)
|
27
30
|
|
28
|
-
name_part.gsub(
|
31
|
+
name_part.gsub(/^[a-z]|_[a-z]/) { |match| match[-1, 1].upcase }
|
29
32
|
end
|
30
33
|
|
31
34
|
def initialize(class_name_parts)
|
32
35
|
department_parts = class_name_parts[0...-1]
|
33
36
|
@department = (department_parts.join('/').to_sym unless department_parts.empty?)
|
37
|
+
@department_name = @department&.to_s
|
34
38
|
@cop_name = class_name_parts.last
|
35
39
|
end
|
36
40
|
|
@@ -40,7 +44,8 @@ module RuboCop
|
|
40
44
|
alias eql? ==
|
41
45
|
|
42
46
|
def hash
|
43
|
-
|
47
|
+
# Do hashing manually to reduce Array allocations.
|
48
|
+
department.hash ^ cop_name.hash # rubocop:disable Security/CompoundHash
|
44
49
|
end
|
45
50
|
|
46
51
|
def match?(other)
|
data/lib/rubocop/cop/base.rb
CHANGED
@@ -107,8 +107,7 @@ module RuboCop
|
|
107
107
|
def add_global_offense(message = nil, severity: nil)
|
108
108
|
severity = find_severity(nil, severity)
|
109
109
|
message = find_message(nil, message)
|
110
|
-
|
111
|
-
Offense.new(severity, Offense::NO_LOCATION, message, name, :unsupported)
|
110
|
+
current_offenses << Offense.new(severity, Offense::NO_LOCATION, message, name, :unsupported)
|
112
111
|
end
|
113
112
|
|
114
113
|
# Adds an offense on the specified range (or node with an expression)
|
@@ -126,7 +125,7 @@ module RuboCop
|
|
126
125
|
|
127
126
|
status, corrector = enabled_line?(range.line) ? correct(range, &block) : :disabled
|
128
127
|
|
129
|
-
|
128
|
+
current_offenses << Offense.new(severity, range, message, name, status, corrector)
|
130
129
|
end
|
131
130
|
|
132
131
|
# This method should be overridden when a cop's behavior depends
|
@@ -187,7 +186,7 @@ module RuboCop
|
|
187
186
|
def self.match?(given_names)
|
188
187
|
return false unless given_names
|
189
188
|
|
190
|
-
given_names.include?(cop_name) || given_names.include?(
|
189
|
+
given_names.include?(cop_name) || given_names.include?(badge.department_name)
|
191
190
|
end
|
192
191
|
|
193
192
|
def cop_name
|
@@ -225,6 +224,8 @@ module RuboCop
|
|
225
224
|
end
|
226
225
|
|
227
226
|
def relevant_file?(file)
|
227
|
+
return true unless @config.clusivity_config_for_badge?(self.class.badge)
|
228
|
+
|
228
229
|
file == RuboCop::AST::ProcessedSource::STRING_SOURCE_NAME ||
|
229
230
|
(file_name_matches_any?(file, 'Include', true) &&
|
230
231
|
!file_name_matches_any?(file, 'Exclude', false))
|
@@ -292,7 +293,7 @@ module RuboCop
|
|
292
293
|
end
|
293
294
|
|
294
295
|
def apply_correction(corrector)
|
295
|
-
|
296
|
+
current_corrector&.merge!(corrector) if corrector
|
296
297
|
end
|
297
298
|
|
298
299
|
### Reserved for Commissioner:
|
@@ -305,22 +306,37 @@ module RuboCop
|
|
305
306
|
@currently_disabled_lines ||= Set.new
|
306
307
|
end
|
307
308
|
|
309
|
+
def current_corrector
|
310
|
+
@current_corrector ||= Corrector.new(@processed_source) if @processed_source.valid_syntax?
|
311
|
+
end
|
312
|
+
|
313
|
+
def current_offenses
|
314
|
+
@current_offenses ||= []
|
315
|
+
end
|
316
|
+
|
308
317
|
private_class_method def self.restrict_on_send
|
309
318
|
@restrict_on_send ||= self::RESTRICT_ON_SEND.to_a.freeze
|
310
319
|
end
|
311
320
|
|
312
321
|
# Called before any investigation
|
313
322
|
def begin_investigation(processed_source)
|
314
|
-
@current_offenses =
|
323
|
+
@current_offenses = nil
|
315
324
|
@current_offense_locations = nil
|
316
325
|
@currently_disabled_lines = nil
|
317
326
|
@processed_source = processed_source
|
318
|
-
@current_corrector =
|
327
|
+
@current_corrector = nil
|
319
328
|
end
|
320
329
|
|
330
|
+
# rubocop:disable Layout/ClassStructure
|
331
|
+
EMPTY_OFFENSES = [].freeze
|
332
|
+
private_constant :EMPTY_OFFENSES
|
333
|
+
# rubocop:enable Layout/ClassStructure
|
334
|
+
|
321
335
|
# Called to complete an investigation
|
322
336
|
def complete_investigation
|
323
|
-
InvestigationReport.new(
|
337
|
+
InvestigationReport.new(
|
338
|
+
self, processed_source, @current_offenses || EMPTY_OFFENSES, @current_corrector
|
339
|
+
)
|
324
340
|
ensure
|
325
341
|
reset_investigation
|
326
342
|
end
|
@@ -412,7 +428,7 @@ module RuboCop
|
|
412
428
|
patterns = cop_config[parameter]
|
413
429
|
return default_result unless patterns
|
414
430
|
|
415
|
-
patterns =
|
431
|
+
patterns = FilePatterns.from(patterns)
|
416
432
|
patterns.match?(config.path_relative_to_config(file)) || patterns.match?(file)
|
417
433
|
end
|
418
434
|
|
@@ -82,7 +82,8 @@ module RuboCop
|
|
82
82
|
@cops.each { |cop| cop.send :begin_investigation, processed_source }
|
83
83
|
if processed_source.valid_syntax?
|
84
84
|
invoke(:on_new_investigation, @cops)
|
85
|
-
|
85
|
+
invoke_with_argument(:investigate, @forces, processed_source)
|
86
|
+
|
86
87
|
walk(processed_source.ast) unless @cops.empty?
|
87
88
|
invoke(:on_investigation_end, @cops)
|
88
89
|
else
|
@@ -149,8 +150,12 @@ module RuboCop
|
|
149
150
|
map
|
150
151
|
end
|
151
152
|
|
152
|
-
def invoke(callback, cops
|
153
|
-
cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback
|
153
|
+
def invoke(callback, cops)
|
154
|
+
cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback) } }
|
155
|
+
end
|
156
|
+
|
157
|
+
def invoke_with_argument(callback, cops, arg)
|
158
|
+
cops.each { |cop| with_cop_error_handling(cop) { cop.send(callback, arg) } }
|
154
159
|
end
|
155
160
|
|
156
161
|
# Allow blind rescues here, since we're absorbing and packaging or
|
data/lib/rubocop/cop/cop.rb
CHANGED
@@ -28,8 +28,9 @@ module RuboCop
|
|
28
28
|
/^\s+# This cop (?<special>#{SPECIAL_WORDS.join('|')})?\s*(?<word>.+?) .*/.freeze
|
29
29
|
REPLACEMENT_REGEX = /^\s+# This cop (#{SPECIAL_WORDS.join('|')})?\s*(.+?) /.freeze
|
30
30
|
|
31
|
+
# rubocop:disable Metrics/CyclomaticComplexity
|
31
32
|
def on_class(node)
|
32
|
-
return unless (module_node = node.parent)
|
33
|
+
return unless (module_node = node.parent) && node.parent_class
|
33
34
|
|
34
35
|
description_beginning = first_comment_line(module_node)
|
35
36
|
return unless description_beginning
|
@@ -48,6 +49,7 @@ module RuboCop
|
|
48
49
|
end
|
49
50
|
end
|
50
51
|
end
|
52
|
+
# rubocop:enable Metrics/CyclomaticComplexity
|
51
53
|
|
52
54
|
private
|
53
55
|
|
@@ -27,6 +27,8 @@ module RuboCop
|
|
27
27
|
|
28
28
|
def on_new_investigation
|
29
29
|
return if processed_source.tokens.empty?
|
30
|
+
# Quick check if we possibly have consecutive blank lines.
|
31
|
+
return unless processed_source.raw_source.include?("\n\n\n")
|
30
32
|
|
31
33
|
lines = Set.new
|
32
34
|
processed_source.each_token { |token| lines << token.line }
|
@@ -119,12 +119,16 @@ module RuboCop
|
|
119
119
|
def ignored_ranges(ast)
|
120
120
|
return [] unless ast
|
121
121
|
|
122
|
-
@ignored_ranges ||=
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
122
|
+
@ignored_ranges ||= begin
|
123
|
+
ranges = []
|
124
|
+
on_node(:pair, ast) do |pair|
|
125
|
+
next if pair.parent.single_line?
|
126
|
+
|
127
|
+
key, value = *pair
|
128
|
+
ranges << (key.source_range.end_pos...value.source_range.begin_pos)
|
129
|
+
end
|
130
|
+
ranges
|
131
|
+
end
|
128
132
|
end
|
129
133
|
|
130
134
|
def force_equal_sign_alignment?
|
@@ -6,17 +6,49 @@ module RuboCop
|
|
6
6
|
# Checks for a line break before the first element in a
|
7
7
|
# multi-line array.
|
8
8
|
#
|
9
|
-
# @example
|
9
|
+
# @example AllowMultilineFinalElement: false (default)
|
10
|
+
#
|
11
|
+
# # bad
|
12
|
+
# [ :a,
|
13
|
+
# :b]
|
14
|
+
#
|
15
|
+
# # bad
|
16
|
+
# [ :a, {
|
17
|
+
# :b => :c
|
18
|
+
# }]
|
19
|
+
#
|
20
|
+
# # good
|
21
|
+
# [:a, :b]
|
22
|
+
#
|
23
|
+
# # good
|
24
|
+
# [
|
25
|
+
# :a,
|
26
|
+
# :b]
|
27
|
+
#
|
28
|
+
# # good
|
29
|
+
# [
|
30
|
+
# :a, {
|
31
|
+
# :b => :c
|
32
|
+
# }]
|
33
|
+
#
|
34
|
+
# @example AllowMultilineFinalElement: true
|
10
35
|
#
|
11
36
|
# # bad
|
12
37
|
# [ :a,
|
13
38
|
# :b]
|
14
39
|
#
|
15
40
|
# # good
|
41
|
+
# [ :a, {
|
42
|
+
# :b => :c
|
43
|
+
# }]
|
44
|
+
#
|
45
|
+
# # good
|
16
46
|
# [
|
17
47
|
# :a,
|
18
48
|
# :b]
|
19
49
|
#
|
50
|
+
# # good
|
51
|
+
# [:a, :b]
|
20
52
|
class FirstArrayElementLineBreak < Base
|
21
53
|
include FirstElementLineBreak
|
22
54
|
extend AutoCorrector
|
@@ -26,7 +58,7 @@ module RuboCop
|
|
26
58
|
def on_array(node)
|
27
59
|
return if !node.loc.begin && !assignment_on_same_line?(node)
|
28
60
|
|
29
|
-
check_children_line_break(node, node.children)
|
61
|
+
check_children_line_break(node, node.children, ignore_last: ignore_last_element?)
|
30
62
|
end
|
31
63
|
|
32
64
|
private
|
@@ -35,6 +67,10 @@ module RuboCop
|
|
35
67
|
source = node.source_range.source_line[0...node.loc.column]
|
36
68
|
/\s*=\s*$/.match?(source)
|
37
69
|
end
|
70
|
+
|
71
|
+
def ignore_last_element?
|
72
|
+
!!cop_config['AllowMultilineFinalElement']
|
73
|
+
end
|
38
74
|
end
|
39
75
|
end
|
40
76
|
end
|
@@ -6,16 +6,55 @@ module RuboCop
|
|
6
6
|
# Checks for a line break before the first element in a
|
7
7
|
# multi-line hash.
|
8
8
|
#
|
9
|
-
# @example
|
9
|
+
# @example AllowMultilineFinalElement: false (default)
|
10
10
|
#
|
11
11
|
# # bad
|
12
12
|
# { a: 1,
|
13
13
|
# b: 2}
|
14
14
|
#
|
15
|
+
# # bad
|
16
|
+
# { a: 1, b: {
|
17
|
+
# c: 3
|
18
|
+
# }}
|
19
|
+
#
|
15
20
|
# # good
|
16
21
|
# {
|
17
22
|
# a: 1,
|
18
23
|
# b: 2 }
|
24
|
+
#
|
25
|
+
# # good
|
26
|
+
# {
|
27
|
+
# a: 1, b: {
|
28
|
+
# c: 3
|
29
|
+
# }}
|
30
|
+
#
|
31
|
+
# @example AllowMultilineFinalElement: true
|
32
|
+
#
|
33
|
+
# # bad
|
34
|
+
# { a: 1,
|
35
|
+
# b: 2}
|
36
|
+
#
|
37
|
+
# # bad
|
38
|
+
# { a: 1,
|
39
|
+
# b: {
|
40
|
+
# c: 3
|
41
|
+
# }}
|
42
|
+
#
|
43
|
+
# # good
|
44
|
+
# { a: 1, b: {
|
45
|
+
# c: 3
|
46
|
+
# }}
|
47
|
+
#
|
48
|
+
# # good
|
49
|
+
# {
|
50
|
+
# a: 1,
|
51
|
+
# b: 2 }
|
52
|
+
#
|
53
|
+
# # good
|
54
|
+
# {
|
55
|
+
# a: 1, b: {
|
56
|
+
# c: 3
|
57
|
+
# }}
|
19
58
|
class FirstHashElementLineBreak < Base
|
20
59
|
include FirstElementLineBreak
|
21
60
|
extend AutoCorrector
|
@@ -25,7 +64,15 @@ module RuboCop
|
|
25
64
|
def on_hash(node)
|
26
65
|
# node.loc.begin tells us whether the hash opens with a {
|
27
66
|
# If it doesn't, Style/FirstMethodArgumentLineBreak will handle it
|
28
|
-
|
67
|
+
return unless node.loc.begin
|
68
|
+
|
69
|
+
check_children_line_break(node, node.children, ignore_last: ignore_last_element?)
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
|
74
|
+
def ignore_last_element?
|
75
|
+
!!cop_config['AllowMultilineFinalElement']
|
29
76
|
end
|
30
77
|
end
|
31
78
|
end
|
@@ -6,17 +6,70 @@ module RuboCop
|
|
6
6
|
# Checks for a line break before the first argument in a
|
7
7
|
# multi-line method call.
|
8
8
|
#
|
9
|
-
# @example
|
9
|
+
# @example AllowMultilineFinalElement: false (default)
|
10
10
|
#
|
11
11
|
# # bad
|
12
12
|
# method(foo, bar,
|
13
13
|
# baz)
|
14
14
|
#
|
15
|
+
# # bad
|
16
|
+
# method(foo, bar, {
|
17
|
+
# baz: "a",
|
18
|
+
# qux: "b",
|
19
|
+
# })
|
20
|
+
#
|
15
21
|
# # good
|
16
22
|
# method(
|
17
23
|
# foo, bar,
|
18
24
|
# baz)
|
19
25
|
#
|
26
|
+
# # good
|
27
|
+
# method(
|
28
|
+
# foo, bar, {
|
29
|
+
# baz: "a",
|
30
|
+
# qux: "b",
|
31
|
+
# })
|
32
|
+
#
|
33
|
+
# # ignored
|
34
|
+
# method foo, bar,
|
35
|
+
# baz
|
36
|
+
#
|
37
|
+
# @example AllowMultilineFinalElement: true
|
38
|
+
#
|
39
|
+
# # bad
|
40
|
+
# method(foo, bar,
|
41
|
+
# baz)
|
42
|
+
#
|
43
|
+
# # bad
|
44
|
+
# method(foo,
|
45
|
+
# bar,
|
46
|
+
# {
|
47
|
+
# baz: "a",
|
48
|
+
# qux: "b",
|
49
|
+
# }
|
50
|
+
# )
|
51
|
+
#
|
52
|
+
# # good
|
53
|
+
# method(foo, bar, {
|
54
|
+
# baz: "a",
|
55
|
+
# qux: "b",
|
56
|
+
# })
|
57
|
+
#
|
58
|
+
# # good
|
59
|
+
# method(
|
60
|
+
# foo, bar,
|
61
|
+
# baz)
|
62
|
+
#
|
63
|
+
# # good
|
64
|
+
# method(
|
65
|
+
# foo,
|
66
|
+
# bar,
|
67
|
+
# {
|
68
|
+
# baz: "a",
|
69
|
+
# qux: "b",
|
70
|
+
# }
|
71
|
+
# )
|
72
|
+
#
|
20
73
|
# # ignored
|
21
74
|
# method foo, bar,
|
22
75
|
# baz
|
@@ -38,10 +91,16 @@ module RuboCop
|
|
38
91
|
last_arg = args.last
|
39
92
|
args.concat(args.pop.children) if last_arg&.hash_type? && !last_arg&.braces?
|
40
93
|
|
41
|
-
check_method_line_break(node, args)
|
94
|
+
check_method_line_break(node, args, ignore_last: ignore_last_element?)
|
42
95
|
end
|
43
96
|
alias on_csend on_send
|
44
97
|
alias on_super on_send
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def ignore_last_element?
|
102
|
+
!!cop_config['AllowMultilineFinalElement']
|
103
|
+
end
|
45
104
|
end
|
46
105
|
end
|
47
106
|
end
|