rubocop 1.32.0 → 1.33.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 +2 -2
- data/config/default.yml +45 -16
- data/config/obsoletion.yml +23 -1
- data/lib/rubocop/cache_config.rb +29 -0
- data/lib/rubocop/cli/command/auto_genenerate_config.rb +2 -2
- data/lib/rubocop/cli/command/init_dotfile.rb +1 -1
- data/lib/rubocop/config_finder.rb +68 -0
- data/lib/rubocop/config_loader.rb +5 -45
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +5 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +4 -0
- data/lib/rubocop/config_obsoletion.rb +7 -2
- data/lib/rubocop/cop/layout/block_end_newline.rb +32 -5
- data/lib/rubocop/cop/layout/first_argument_indentation.rb +6 -1
- data/lib/rubocop/cop/lint/ambiguous_block_association.rb +21 -8
- data/lib/rubocop/cop/lint/debugger.rb +11 -1
- data/lib/rubocop/cop/lint/empty_conditional_body.rb +60 -1
- data/lib/rubocop/cop/lint/number_conversion.rb +24 -8
- data/lib/rubocop/cop/metrics/abc_size.rb +3 -1
- data/lib/rubocop/cop/metrics/block_length.rb +6 -7
- data/lib/rubocop/cop/metrics/method_length.rb +8 -8
- data/lib/rubocop/cop/mixin/allowed_methods.rb +15 -1
- data/lib/rubocop/cop/mixin/allowed_pattern.rb +9 -1
- data/lib/rubocop/cop/mixin/comments_help.rb +5 -1
- data/lib/rubocop/cop/mixin/method_complexity.rb +4 -9
- data/lib/rubocop/cop/naming/predicate_name.rb +24 -3
- data/lib/rubocop/cop/style/block_delimiters.rb +26 -7
- data/lib/rubocop/cop/style/class_and_module_children.rb +4 -4
- data/lib/rubocop/cop/style/class_equality_comparison.rb +32 -7
- data/lib/rubocop/cop/style/empty_heredoc.rb +15 -1
- data/lib/rubocop/cop/style/format_string_token.rb +21 -8
- data/lib/rubocop/cop/style/hash_except.rb +0 -4
- data/lib/rubocop/cop/style/method_call_with_args_parentheses/require_parentheses.rb +5 -1
- data/lib/rubocop/cop/style/method_call_with_args_parentheses.rb +7 -7
- data/lib/rubocop/cop/style/method_call_without_args_parentheses.rb +11 -6
- data/lib/rubocop/cop/style/numeric_predicate.rb +28 -8
- data/lib/rubocop/cop/style/redundant_condition.rb +19 -4
- data/lib/rubocop/cop/style/redundant_sort.rb +21 -6
- data/lib/rubocop/cop/style/symbol_proc.rb +29 -9
- data/lib/rubocop/result_cache.rb +22 -20
- data/lib/rubocop/server/cache.rb +33 -1
- data/lib/rubocop/server/cli.rb +19 -2
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop.rb +0 -1
- metadata +5 -4
- data/lib/rubocop/cop/mixin/ignored_methods.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 141b5fc0ee48c7fdf1fc347bb2b59b59933f6d46f575cfb4f380bfc101090345
|
4
|
+
data.tar.gz: 862c5d1952e777ec19bd1b8782c9e98e065c3d80db7a7d2c91da4406afeb886c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2be012822408e3aa884dfe85e8a2153144f53d47550a0f7233a60448a8ab18c5c5411959742a4cb9652e972451f05cf0d447451eba53e46260baefa8f2c234e6
|
7
|
+
data.tar.gz: 063e8ef0056793c86aee9f952db454eac5422c369bdf1ce4a719fcc21279214b86a800f58229b0ade17b963fb2c8e49608bd1883c840d8370b207b3aa4ee916c
|
data/README.md
CHANGED
@@ -46,14 +46,14 @@ If you'd rather install RuboCop using `bundler`, add a line for it in your `Gemf
|
|
46
46
|
gem 'rubocop', require: false
|
47
47
|
```
|
48
48
|
|
49
|
-
RuboCop is stable between
|
49
|
+
RuboCop is stable between minor versions, both in terms of API and cop configuration.
|
50
50
|
We aim to ease the maintenance of RuboCop extensions and the upgrades between RuboCop
|
51
51
|
releases. All big changes are reserved for major releases.
|
52
52
|
To prevent an unwanted RuboCop update you might want to use a conservative version lock
|
53
53
|
in your `Gemfile`:
|
54
54
|
|
55
55
|
```rb
|
56
|
-
gem 'rubocop', '~> 1.
|
56
|
+
gem 'rubocop', '~> 1.33', 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
@@ -1502,7 +1502,9 @@ Lint/AmbiguousBlockAssociation:
|
|
1502
1502
|
Enabled: true
|
1503
1503
|
VersionAdded: '0.48'
|
1504
1504
|
VersionChanged: '1.13'
|
1505
|
-
|
1505
|
+
AllowedMethods: []
|
1506
|
+
AllowedPatterns: []
|
1507
|
+
IgnoredMethods: [] # deprecated
|
1506
1508
|
|
1507
1509
|
Lint/AmbiguousOperator:
|
1508
1510
|
Description: >-
|
@@ -1753,6 +1755,7 @@ Lint/EmptyConditionalBody:
|
|
1753
1755
|
Enabled: true
|
1754
1756
|
AllowComments: true
|
1755
1757
|
VersionAdded: '0.89'
|
1758
|
+
VersionChanged: '1.33'
|
1756
1759
|
|
1757
1760
|
Lint/EmptyEnsure:
|
1758
1761
|
Description: 'Checks for empty ensure block.'
|
@@ -1970,6 +1973,7 @@ Lint/NoReturnInBeginEndBlocks:
|
|
1970
1973
|
|
1971
1974
|
Lint/NonAtomicFileOperation:
|
1972
1975
|
Description: Checks for non-atomic file operations.
|
1976
|
+
StyleGuide: '#atomic-file-operations'
|
1973
1977
|
Enabled: pending
|
1974
1978
|
VersionAdded: '1.31'
|
1975
1979
|
SafeAutoCorrect: false
|
@@ -1991,7 +1995,9 @@ Lint/NumberConversion:
|
|
1991
1995
|
VersionAdded: '0.53'
|
1992
1996
|
VersionChanged: '1.1'
|
1993
1997
|
SafeAutoCorrect: false
|
1994
|
-
|
1998
|
+
AllowedMethods: []
|
1999
|
+
AllowedPatterns: []
|
2000
|
+
IgnoredMethods: [] # deprecated
|
1995
2001
|
IgnoredClasses:
|
1996
2002
|
- Time
|
1997
2003
|
- DateTime
|
@@ -2443,7 +2449,9 @@ Metrics/AbcSize:
|
|
2443
2449
|
VersionChanged: '1.5'
|
2444
2450
|
# The ABC size is a calculated magnitude, so this number can be an Integer or
|
2445
2451
|
# a Float.
|
2446
|
-
|
2452
|
+
AllowedMethods: []
|
2453
|
+
AllowedPatterns: []
|
2454
|
+
IgnoredMethods: [] # deprecated
|
2447
2455
|
CountRepeatedAttributes: true
|
2448
2456
|
Max: 17
|
2449
2457
|
|
@@ -2456,10 +2464,12 @@ Metrics/BlockLength:
|
|
2456
2464
|
Max: 25
|
2457
2465
|
CountAsOne: []
|
2458
2466
|
ExcludedMethods: [] # deprecated, retained for backwards compatibility
|
2459
|
-
|
2467
|
+
AllowedMethods:
|
2460
2468
|
# By default, exclude the `#refine` method, as it tends to have larger
|
2461
2469
|
# associated blocks.
|
2462
2470
|
- refine
|
2471
|
+
AllowedPatterns: []
|
2472
|
+
IgnoredMethods: [] # deprecated
|
2463
2473
|
Exclude:
|
2464
2474
|
- '**/*.gemspec'
|
2465
2475
|
|
@@ -2489,7 +2499,9 @@ Metrics/CyclomaticComplexity:
|
|
2489
2499
|
Enabled: true
|
2490
2500
|
VersionAdded: '0.25'
|
2491
2501
|
VersionChanged: '0.81'
|
2492
|
-
|
2502
|
+
AllowedMethods: []
|
2503
|
+
AllowedPatterns: []
|
2504
|
+
IgnoredMethods: [] # deprecated
|
2493
2505
|
Max: 7
|
2494
2506
|
|
2495
2507
|
Metrics/MethodLength:
|
@@ -2502,7 +2514,9 @@ Metrics/MethodLength:
|
|
2502
2514
|
Max: 10
|
2503
2515
|
CountAsOne: []
|
2504
2516
|
ExcludedMethods: [] # deprecated, retained for backwards compatibility
|
2505
|
-
|
2517
|
+
AllowedMethods: []
|
2518
|
+
AllowedPatterns: []
|
2519
|
+
IgnoredMethods: [] # deprecated
|
2506
2520
|
|
2507
2521
|
Metrics/ModuleLength:
|
2508
2522
|
Description: 'Avoid modules longer than 100 lines of code.'
|
@@ -2530,7 +2544,9 @@ Metrics/PerceivedComplexity:
|
|
2530
2544
|
Enabled: true
|
2531
2545
|
VersionAdded: '0.25'
|
2532
2546
|
VersionChanged: '0.81'
|
2533
|
-
|
2547
|
+
AllowedMethods: []
|
2548
|
+
AllowedPatterns: []
|
2549
|
+
IgnoredMethods: [] # deprecated
|
2534
2550
|
Max: 8
|
2535
2551
|
|
2536
2552
|
################## Migration #############################
|
@@ -3061,7 +3077,7 @@ Style/BlockDelimiters:
|
|
3061
3077
|
# This looks at the usage of a block's method to determine its type (e.g. is
|
3062
3078
|
# the result of a `map` assigned to a variable or passed to another
|
3063
3079
|
# method) but exceptions are permitted in the `ProceduralMethods`,
|
3064
|
-
# `FunctionalMethods` and `
|
3080
|
+
# `FunctionalMethods` and `AllowedMethods` sections below.
|
3065
3081
|
- semantic
|
3066
3082
|
# The `braces_for_chaining` style enforces braces around single line blocks
|
3067
3083
|
# and do..end around multi-line blocks, except for multi-line blocks whose
|
@@ -3102,7 +3118,7 @@ Style/BlockDelimiters:
|
|
3102
3118
|
- let!
|
3103
3119
|
- subject
|
3104
3120
|
- watch
|
3105
|
-
|
3121
|
+
AllowedMethods:
|
3106
3122
|
# Methods that can be either procedural or functional and cannot be
|
3107
3123
|
# categorised from their usage alone, e.g.
|
3108
3124
|
#
|
@@ -3119,6 +3135,8 @@ Style/BlockDelimiters:
|
|
3119
3135
|
- lambda
|
3120
3136
|
- proc
|
3121
3137
|
- it
|
3138
|
+
AllowedPatterns: []
|
3139
|
+
IgnoredMethods: [] # deprecated
|
3122
3140
|
# The AllowBracesOnProceduralOneLiners option is ignored unless the
|
3123
3141
|
# EnforcedStyle is set to `semantic`. If so:
|
3124
3142
|
#
|
@@ -3222,10 +3240,12 @@ Style/ClassEqualityComparison:
|
|
3222
3240
|
StyleGuide: '#instance-of-vs-class-comparison'
|
3223
3241
|
Enabled: true
|
3224
3242
|
VersionAdded: '0.93'
|
3225
|
-
|
3243
|
+
AllowedMethods:
|
3226
3244
|
- ==
|
3227
3245
|
- equal?
|
3228
3246
|
- eql?
|
3247
|
+
AllowedPatterns: []
|
3248
|
+
IgnoredMethods: [] # deprecated
|
3229
3249
|
|
3230
3250
|
Style/ClassMethods:
|
3231
3251
|
Description: 'Use self when defining module/class methods.'
|
@@ -3687,7 +3707,9 @@ Style/FormatStringToken:
|
|
3687
3707
|
MaxUnannotatedPlaceholdersAllowed: 1
|
3688
3708
|
VersionAdded: '0.49'
|
3689
3709
|
VersionChanged: '1.0'
|
3690
|
-
|
3710
|
+
AllowedMethods: []
|
3711
|
+
AllowedPatterns: []
|
3712
|
+
IgnoredMethods: [] # deprecated
|
3691
3713
|
|
3692
3714
|
Style/FrozenStringLiteralComment:
|
3693
3715
|
Description: >-
|
@@ -4006,7 +4028,8 @@ Style/MethodCallWithArgsParentheses:
|
|
4006
4028
|
VersionAdded: '0.47'
|
4007
4029
|
VersionChanged: '1.7'
|
4008
4030
|
IgnoreMacros: true
|
4009
|
-
|
4031
|
+
AllowedMethods: []
|
4032
|
+
IgnoredMethods: [] # deprecated
|
4010
4033
|
AllowedPatterns: []
|
4011
4034
|
IgnoredPatterns: [] # deprecated
|
4012
4035
|
IncludedMacros: []
|
@@ -4023,7 +4046,9 @@ Style/MethodCallWithoutArgsParentheses:
|
|
4023
4046
|
Description: 'Do not use parentheses for method calls with no arguments.'
|
4024
4047
|
StyleGuide: '#method-invocation-parens'
|
4025
4048
|
Enabled: true
|
4026
|
-
|
4049
|
+
AllowedMethods: []
|
4050
|
+
AllowedPatterns: []
|
4051
|
+
IgnoredMethods: [] # deprecated
|
4027
4052
|
VersionAdded: '0.47'
|
4028
4053
|
VersionChanged: '0.55'
|
4029
4054
|
|
@@ -4393,7 +4418,9 @@ Style/NumericPredicate:
|
|
4393
4418
|
SupportedStyles:
|
4394
4419
|
- predicate
|
4395
4420
|
- comparison
|
4396
|
-
|
4421
|
+
AllowedMethods: []
|
4422
|
+
AllowedPatterns: []
|
4423
|
+
IgnoredMethods: [] # deprecated
|
4397
4424
|
# Exclude RSpec specs because assertions like `expect(1).to be > 0` cause
|
4398
4425
|
# false positives.
|
4399
4426
|
Exclude:
|
@@ -5030,11 +5057,13 @@ Style/SymbolProc:
|
|
5030
5057
|
VersionAdded: '0.26'
|
5031
5058
|
VersionChanged: '1.28'
|
5032
5059
|
AllowMethodsWithArguments: false
|
5033
|
-
# A list of method names to be
|
5060
|
+
# A list of method names to be always allowed by the check.
|
5034
5061
|
# The names should be fairly unique, otherwise you'll end up ignoring lots of code.
|
5035
|
-
|
5062
|
+
AllowedMethods:
|
5036
5063
|
- respond_to
|
5037
5064
|
- define_method
|
5065
|
+
AllowedPatterns: []
|
5066
|
+
IgnoredMethods: [] # deprecated
|
5038
5067
|
AllowComments: false
|
5039
5068
|
|
5040
5069
|
Style/TernaryParentheses:
|
data/config/obsoletion.yml
CHANGED
@@ -187,7 +187,9 @@ changed_parameters:
|
|
187
187
|
- Metrics/BlockLength
|
188
188
|
- Metrics/MethodLength
|
189
189
|
parameters: ExcludedMethods
|
190
|
-
|
190
|
+
alternatives:
|
191
|
+
- AllowedMethods
|
192
|
+
- AllowedPatterns
|
191
193
|
severity: warning
|
192
194
|
- cops: Lint/Debugger
|
193
195
|
parameters: DebuggerReceivers
|
@@ -202,6 +204,26 @@ changed_parameters:
|
|
202
204
|
parameters: IgnoredPatterns
|
203
205
|
alternative: AllowedPatterns
|
204
206
|
severity: warning
|
207
|
+
- cops:
|
208
|
+
- Lint/AmbiguousBlockAssociation
|
209
|
+
- Lint/NumberConversion
|
210
|
+
- Metrics/AbcSize
|
211
|
+
- Metrics/BlockLength
|
212
|
+
- Metrics/CyclomaticComplexity
|
213
|
+
- Metrics/MethodLength
|
214
|
+
- Metrics/PerceivedComplexity
|
215
|
+
- Style/BlockDelimiters
|
216
|
+
- Style/ClassEqualityComparison
|
217
|
+
- Style/FormatStringToken
|
218
|
+
- Style/MethodCallWithArgsParentheses
|
219
|
+
- Style/MethodCallWithoutArgsParentheses
|
220
|
+
- Style/NumericPredicate
|
221
|
+
- Style/SymbolLiteral
|
222
|
+
parameters: IgnoredMethods
|
223
|
+
alternatives:
|
224
|
+
- AllowedMethods
|
225
|
+
- AllowedPatterns
|
226
|
+
severity: warning
|
205
227
|
|
206
228
|
# Enforced styles that have been removed or replaced
|
207
229
|
changed_enforced_styles:
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# This class represents the cache config of the caching RuboCop runs.
|
5
|
+
# @api private
|
6
|
+
class CacheConfig
|
7
|
+
def self.root_dir
|
8
|
+
root = ENV.fetch('RUBOCOP_CACHE_ROOT', nil)
|
9
|
+
root ||= yield
|
10
|
+
root ||= if ENV.key?('XDG_CACHE_HOME')
|
11
|
+
# Include user ID in the path to make sure the user has write
|
12
|
+
# access.
|
13
|
+
File.join(ENV.fetch('XDG_CACHE_HOME'), Process.uid.to_s)
|
14
|
+
else
|
15
|
+
# On FreeBSD, the /home path is a symbolic link to /usr/home
|
16
|
+
# and the $HOME environment variable returns the /home path.
|
17
|
+
#
|
18
|
+
# As $HOME is a built-in environment variable, FreeBSD users
|
19
|
+
# always get a warning message.
|
20
|
+
#
|
21
|
+
# To avoid raising warn log messages on FreeBSD, we retrieve
|
22
|
+
# the real path of the home folder.
|
23
|
+
File.join(File.realpath(Dir.home), '.cache')
|
24
|
+
end
|
25
|
+
|
26
|
+
File.join(root, 'rubocop_cache')
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -98,7 +98,7 @@ module RuboCop
|
|
98
98
|
def add_inheritance_from_auto_generated_file(config_file)
|
99
99
|
file_string = " #{relative_path_to_todo_from_options_config}"
|
100
100
|
|
101
|
-
config_file ||=
|
101
|
+
config_file ||= ConfigFinder::DOTFILE
|
102
102
|
|
103
103
|
if File.exist?(config_file)
|
104
104
|
files = Array(ConfigLoader.load_yaml_configuration(config_file)['inherit_from'])
|
@@ -113,7 +113,7 @@ module RuboCop
|
|
113
113
|
write_config_file(config_file, file_string, rubocop_yml_contents)
|
114
114
|
|
115
115
|
puts "Added inheritance from `#{relative_path_to_todo_from_options_config}` " \
|
116
|
-
"in `#{
|
116
|
+
"in `#{ConfigFinder::DOTFILE}`."
|
117
117
|
end
|
118
118
|
|
119
119
|
def existing_configuration(config_file)
|
@@ -0,0 +1,68 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_relative 'file_finder'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
# This class has methods related to finding configuration path.
|
7
|
+
# @api private
|
8
|
+
class ConfigFinder
|
9
|
+
DOTFILE = '.rubocop.yml'
|
10
|
+
XDG_CONFIG = 'config.yml'
|
11
|
+
RUBOCOP_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
|
12
|
+
DEFAULT_FILE = File.join(RUBOCOP_HOME, 'config', 'default.yml')
|
13
|
+
|
14
|
+
class << self
|
15
|
+
include FileFinder
|
16
|
+
|
17
|
+
attr_writer :project_root
|
18
|
+
|
19
|
+
def find_config_path(target_dir)
|
20
|
+
find_project_dotfile(target_dir) || find_user_dotfile || find_user_xdg_config ||
|
21
|
+
DEFAULT_FILE
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns the path RuboCop inferred as the root of the project. No file
|
25
|
+
# searches will go past this directory.
|
26
|
+
def project_root
|
27
|
+
@project_root ||= find_project_root
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def find_project_root
|
33
|
+
pwd = Dir.pwd
|
34
|
+
gems_file = find_last_file_upwards('Gemfile', pwd) || find_last_file_upwards('gems.rb', pwd)
|
35
|
+
return unless gems_file
|
36
|
+
|
37
|
+
File.dirname(gems_file)
|
38
|
+
end
|
39
|
+
|
40
|
+
def find_project_dotfile(target_dir)
|
41
|
+
find_file_upwards(DOTFILE, target_dir, project_root)
|
42
|
+
end
|
43
|
+
|
44
|
+
def find_user_dotfile
|
45
|
+
return unless ENV.key?('HOME')
|
46
|
+
|
47
|
+
file = File.join(Dir.home, DOTFILE)
|
48
|
+
|
49
|
+
return file if File.exist?(file)
|
50
|
+
end
|
51
|
+
|
52
|
+
def find_user_xdg_config
|
53
|
+
xdg_config_home = expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config'))
|
54
|
+
xdg_config = File.join(xdg_config_home, 'rubocop', XDG_CONFIG)
|
55
|
+
|
56
|
+
return xdg_config if File.exist?(xdg_config)
|
57
|
+
end
|
58
|
+
|
59
|
+
def expand_path(path)
|
60
|
+
File.expand_path(path)
|
61
|
+
rescue ArgumentError
|
62
|
+
# Could happen because HOME or ID could not be determined. Fall back on
|
63
|
+
# using the path literally in that case.
|
64
|
+
path
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'erb'
|
4
4
|
require 'yaml'
|
5
5
|
require 'pathname'
|
6
|
+
require_relative 'config_finder'
|
6
7
|
|
7
8
|
module RuboCop
|
8
9
|
# Raised when a RuboCop configuration file is not found.
|
@@ -15,8 +16,7 @@ module RuboCop
|
|
15
16
|
# during a run of the rubocop program, if files in several
|
16
17
|
# directories are inspected.
|
17
18
|
class ConfigLoader
|
18
|
-
DOTFILE =
|
19
|
-
XDG_CONFIG = 'config.yml'
|
19
|
+
DOTFILE = ConfigFinder::DOTFILE
|
20
20
|
RUBOCOP_HOME = File.realpath(File.join(File.dirname(__FILE__), '..', '..'))
|
21
21
|
DEFAULT_FILE = File.join(RUBOCOP_HOME, 'config', 'default.yml')
|
22
22
|
|
@@ -25,7 +25,7 @@ module RuboCop
|
|
25
25
|
|
26
26
|
attr_accessor :debug, :ignore_parent_exclusion, :disable_pending_cops, :enable_pending_cops,
|
27
27
|
:ignore_unrecognized_cops
|
28
|
-
attr_writer :default_configuration
|
28
|
+
attr_writer :default_configuration
|
29
29
|
attr_reader :loaded_features
|
30
30
|
|
31
31
|
alias debug? debug
|
@@ -95,8 +95,7 @@ module RuboCop
|
|
95
95
|
# user's home directory is checked. If there's no .rubocop.yml
|
96
96
|
# there either, the path to the default file is returned.
|
97
97
|
def configuration_file_for(target_dir)
|
98
|
-
|
99
|
-
find_user_xdg_config || DEFAULT_FILE
|
98
|
+
ConfigFinder.find_config_path(target_dir)
|
100
99
|
end
|
101
100
|
|
102
101
|
def configuration_from_file(config_file, check: true)
|
@@ -122,7 +121,7 @@ module RuboCop
|
|
122
121
|
end
|
123
122
|
|
124
123
|
def add_excludes_from_files(config, config_file)
|
125
|
-
exclusion_file = find_last_file_upwards(DOTFILE, config_file, project_root)
|
124
|
+
exclusion_file = find_last_file_upwards(DOTFILE, config_file, ConfigFinder.project_root)
|
126
125
|
|
127
126
|
return unless exclusion_file
|
128
127
|
return if PathUtil.relative_path(exclusion_file) == PathUtil.relative_path(config_file)
|
@@ -138,12 +137,6 @@ module RuboCop
|
|
138
137
|
end
|
139
138
|
end
|
140
139
|
|
141
|
-
# Returns the path RuboCop inferred as the root of the project. No file
|
142
|
-
# searches will go past this directory.
|
143
|
-
def project_root
|
144
|
-
@project_root ||= find_project_root
|
145
|
-
end
|
146
|
-
|
147
140
|
PENDING_BANNER = <<~BANNER
|
148
141
|
The following cops were added to RuboCop, but are not configured. Please set Enabled to either `true` or `false` in your `.rubocop.yml` file.
|
149
142
|
|
@@ -187,39 +180,6 @@ module RuboCop
|
|
187
180
|
File.absolute_path(file.is_a?(RemoteConfig) ? file.file : file)
|
188
181
|
end
|
189
182
|
|
190
|
-
def find_project_dotfile(target_dir)
|
191
|
-
find_file_upwards(DOTFILE, target_dir, project_root)
|
192
|
-
end
|
193
|
-
|
194
|
-
def find_project_root
|
195
|
-
pwd = Dir.pwd
|
196
|
-
gems_file = find_last_file_upwards('Gemfile', pwd) || find_last_file_upwards('gems.rb', pwd)
|
197
|
-
return unless gems_file
|
198
|
-
|
199
|
-
File.dirname(gems_file)
|
200
|
-
end
|
201
|
-
|
202
|
-
def find_user_dotfile
|
203
|
-
return unless ENV.key?('HOME')
|
204
|
-
|
205
|
-
file = File.join(Dir.home, DOTFILE)
|
206
|
-
return file if File.exist?(file)
|
207
|
-
end
|
208
|
-
|
209
|
-
def find_user_xdg_config
|
210
|
-
xdg_config_home = expand_path(ENV.fetch('XDG_CONFIG_HOME', '~/.config'))
|
211
|
-
xdg_config = File.join(xdg_config_home, 'rubocop', XDG_CONFIG)
|
212
|
-
return xdg_config if File.exist?(xdg_config)
|
213
|
-
end
|
214
|
-
|
215
|
-
def expand_path(path)
|
216
|
-
File.expand_path(path)
|
217
|
-
rescue ArgumentError
|
218
|
-
# Could happen because HOME or ID could not be determined. Fall back on
|
219
|
-
# using the path literally in that case.
|
220
|
-
path
|
221
|
-
end
|
222
|
-
|
223
183
|
def resolver
|
224
184
|
@resolver ||= ConfigLoaderResolver.new
|
225
185
|
end
|
@@ -12,6 +12,11 @@ module RuboCop
|
|
12
12
|
|
13
13
|
if alternative
|
14
14
|
"#{base}\n`#{parameter}` has been renamed to `#{alternative.chomp}`."
|
15
|
+
elsif alternatives
|
16
|
+
"#{base}\n`#{parameter}` has been renamed to #{to_sentence(alternatives.map do |item|
|
17
|
+
"`#{item}`"
|
18
|
+
end,
|
19
|
+
connector: 'and/or')}."
|
15
20
|
else
|
16
21
|
"#{base}\n#{reason.chomp}"
|
17
22
|
end
|
@@ -47,10 +47,15 @@ module RuboCop
|
|
47
47
|
|
48
48
|
# Default rules for obsoletions are in config/obsoletion.yml
|
49
49
|
# Additional rules files can be added with `RuboCop::ConfigObsoletion.files << filename`
|
50
|
-
def load_rules
|
50
|
+
def load_rules # rubocop:disable Metrics/AbcSize
|
51
51
|
rules = self.class.files.each_with_object({}) do |filename, hash|
|
52
52
|
hash.merge!(YAML.safe_load(File.read(filename))) do |_key, first, second|
|
53
|
-
first
|
53
|
+
case first
|
54
|
+
when Hash
|
55
|
+
first.merge(second)
|
56
|
+
when Array
|
57
|
+
first.concat(second)
|
58
|
+
end
|
54
59
|
end
|
55
60
|
end
|
56
61
|
|
@@ -36,24 +36,51 @@ module RuboCop
|
|
36
36
|
# If the end is on its own line, there is no offense
|
37
37
|
return if begins_its_line?(node.loc.end)
|
38
38
|
|
39
|
-
|
40
|
-
corrector.replace(delimiter_range(node), "\n#{node.loc.end.source}#{offset(node)}")
|
41
|
-
end
|
39
|
+
register_offense(node)
|
42
40
|
end
|
43
41
|
|
44
42
|
private
|
45
43
|
|
44
|
+
def register_offense(node)
|
45
|
+
add_offense(node.loc.end, message: message(node)) do |corrector|
|
46
|
+
offense_range = offense_range(node)
|
47
|
+
replacement = "\n#{offense_range.source.strip}"
|
48
|
+
|
49
|
+
if (heredoc = last_heredoc_argument(node.body))
|
50
|
+
corrector.remove(offense_range)
|
51
|
+
corrector.insert_after(heredoc.loc.heredoc_end, replacement)
|
52
|
+
else
|
53
|
+
corrector.replace(offense_range, replacement)
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
46
58
|
def message(node)
|
47
59
|
format(MSG, line: node.loc.end.line, column: node.loc.end.column + 1)
|
48
60
|
end
|
49
61
|
|
50
|
-
def
|
62
|
+
def last_heredoc_argument(node)
|
63
|
+
return unless (arguments = node&.arguments)
|
64
|
+
|
65
|
+
heredoc = arguments.reverse.detect(&:heredoc?)
|
66
|
+
return heredoc if heredoc
|
67
|
+
|
68
|
+
last_heredoc_argument(node.children.first)
|
69
|
+
end
|
70
|
+
|
71
|
+
def offense_range(node)
|
51
72
|
Parser::Source::Range.new(
|
52
73
|
node.loc.expression.source_buffer,
|
53
74
|
node.children.compact.last.loc.expression.end_pos,
|
54
|
-
node.loc.expression.end_pos
|
75
|
+
end_of_method_chain(node).loc.expression.end_pos
|
55
76
|
)
|
56
77
|
end
|
78
|
+
|
79
|
+
def end_of_method_chain(node)
|
80
|
+
return node unless node.parent&.call_type?
|
81
|
+
|
82
|
+
end_of_method_chain(node.parent)
|
83
|
+
end
|
57
84
|
end
|
58
85
|
end
|
59
86
|
end
|
@@ -153,7 +153,8 @@ module RuboCop
|
|
153
153
|
MSG = 'Indent the first argument one step more than %<base>s.'
|
154
154
|
|
155
155
|
def on_send(node)
|
156
|
-
return if style != :consistent && enforce_first_argument_with_fixed_indentation?
|
156
|
+
return if style != :consistent && enforce_first_argument_with_fixed_indentation? &&
|
157
|
+
!enable_layout_first_method_argument_line_break?
|
157
158
|
return if !node.arguments? || bare_operator?(node) || node.setter_method?
|
158
159
|
|
159
160
|
indent = base_indentation(node) + configured_indentation_width
|
@@ -267,6 +268,10 @@ module RuboCop
|
|
267
268
|
argument_alignment_config['EnforcedStyle'] == 'with_fixed_indentation'
|
268
269
|
end
|
269
270
|
|
271
|
+
def enable_layout_first_method_argument_line_break?
|
272
|
+
config.for_cop('Layout/FirstMethodArgumentLineBreak')['Enabled']
|
273
|
+
end
|
274
|
+
|
270
275
|
def argument_alignment_config
|
271
276
|
config.for_cop('Layout/ArgumentAlignment')
|
272
277
|
end
|
@@ -6,8 +6,8 @@ module RuboCop
|
|
6
6
|
# Checks for ambiguous block association with method
|
7
7
|
# when param passed without parentheses.
|
8
8
|
#
|
9
|
-
# This cop can customize
|
10
|
-
# By default, there are no methods to
|
9
|
+
# This cop can customize allowed methods with `AllowedMethods`.
|
10
|
+
# By default, there are no methods to allowed.
|
11
11
|
#
|
12
12
|
# @example
|
13
13
|
#
|
@@ -30,18 +30,30 @@ module RuboCop
|
|
30
30
|
# # Lambda arguments require no disambiguation
|
31
31
|
# foo = ->(bar) { bar.baz }
|
32
32
|
#
|
33
|
-
# @example
|
33
|
+
# @example AllowedMethods: [] (default)
|
34
34
|
#
|
35
35
|
# # bad
|
36
36
|
# expect { do_something }.to change { object.attribute }
|
37
37
|
#
|
38
|
-
# @example
|
38
|
+
# @example AllowedMethods: [change]
|
39
39
|
#
|
40
40
|
# # good
|
41
41
|
# expect { do_something }.to change { object.attribute }
|
42
42
|
#
|
43
|
+
# @example AllowedPatterns: [] (default)
|
44
|
+
#
|
45
|
+
# # bad
|
46
|
+
# expect { do_something }.to change { object.attribute }
|
47
|
+
#
|
48
|
+
# @example AllowedPatterns: [/change/]
|
49
|
+
#
|
50
|
+
# # good
|
51
|
+
# expect { do_something }.to change { object.attribute }
|
52
|
+
# expect { do_something }.to not_change { object.attribute }
|
53
|
+
#
|
43
54
|
class AmbiguousBlockAssociation < Base
|
44
|
-
include
|
55
|
+
include AllowedMethods
|
56
|
+
include AllowedPattern
|
45
57
|
|
46
58
|
MSG = 'Parenthesize the param `%<param>s` to make sure that the ' \
|
47
59
|
'block will be associated with the `%<method>s` method ' \
|
@@ -52,7 +64,7 @@ module RuboCop
|
|
52
64
|
|
53
65
|
return unless ambiguous_block_association?(node)
|
54
66
|
return if node.parenthesized? || node.last_argument.lambda? || node.last_argument.proc? ||
|
55
|
-
|
67
|
+
allowed_method_pattern?(node)
|
56
68
|
|
57
69
|
message = message(node)
|
58
70
|
|
@@ -66,9 +78,10 @@ module RuboCop
|
|
66
78
|
send_node.last_argument.block_type? && !send_node.last_argument.send_node.arguments?
|
67
79
|
end
|
68
80
|
|
69
|
-
def
|
81
|
+
def allowed_method_pattern?(node)
|
70
82
|
node.assignment? || node.operator_method? || node.method?(:[]) ||
|
71
|
-
|
83
|
+
allowed_method?(node.last_argument.method_name) ||
|
84
|
+
matches_allowed_pattern?(node.last_argument.method_name)
|
72
85
|
end
|
73
86
|
|
74
87
|
def message(send_node)
|