rubocop 1.5.2 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +1 -1
- data/config/default.yml +5 -2
- data/config/obsoletion.yml +196 -0
- data/lib/rubocop.rb +10 -0
- data/lib/rubocop/cli/command/suggest_extensions.rb +16 -44
- data/lib/rubocop/config_obsoletion.rb +63 -263
- data/lib/rubocop/config_obsoletion/changed_enforced_styles.rb +33 -0
- data/lib/rubocop/config_obsoletion/changed_parameter.rb +21 -0
- data/lib/rubocop/config_obsoletion/cop_rule.rb +34 -0
- data/lib/rubocop/config_obsoletion/extracted_cop.rb +44 -0
- data/lib/rubocop/config_obsoletion/parameter_rule.rb +44 -0
- data/lib/rubocop/config_obsoletion/removed_cop.rb +41 -0
- data/lib/rubocop/config_obsoletion/renamed_cop.rb +34 -0
- data/lib/rubocop/config_obsoletion/rule.rb +41 -0
- data/lib/rubocop/config_obsoletion/split_cop.rb +27 -0
- data/lib/rubocop/config_validator.rb +11 -4
- data/lib/rubocop/cop/base.rb +17 -15
- data/lib/rubocop/cop/cop.rb +2 -2
- data/lib/rubocop/cop/correctors/string_literal_corrector.rb +6 -8
- data/lib/rubocop/cop/layout/empty_lines_around_attribute_accessor.rb +1 -1
- data/lib/rubocop/cop/layout/line_length.rb +6 -16
- data/lib/rubocop/cop/migration/department_name.rb +1 -1
- data/lib/rubocop/cop/mixin/string_help.rb +4 -1
- data/lib/rubocop/cop/naming/accessor_method_name.rb +15 -1
- data/lib/rubocop/cop/style/character_literal.rb +10 -11
- data/lib/rubocop/cop/style/float_division.rb +44 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +4 -0
- data/lib/rubocop/cop/style/ip_addresses.rb +1 -1
- data/lib/rubocop/cop/style/perl_backrefs.rb +86 -9
- data/lib/rubocop/cop/style/redundant_argument.rb +14 -1
- data/lib/rubocop/cop/style/single_line_block_params.rb +30 -7
- data/lib/rubocop/cop/style/sole_nested_conditional.rb +12 -6
- data/lib/rubocop/cop/style/special_global_vars.rb +1 -13
- data/lib/rubocop/cop/style/string_concatenation.rb +19 -0
- data/lib/rubocop/cop/style/string_literals.rb +14 -8
- data/lib/rubocop/cop/style/string_literals_in_interpolation.rb +4 -3
- data/lib/rubocop/formatter/emacs_style_formatter.rb +2 -0
- data/lib/rubocop/formatter/simple_text_formatter.rb +2 -0
- data/lib/rubocop/formatter/tap_formatter.rb +2 -0
- data/lib/rubocop/lockfile.rb +40 -0
- data/lib/rubocop/version.rb +1 -1
- metadata +14 -3
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
class ConfigObsoletion
|
5
|
+
# Encapsulation of a ConfigObsoletion rule for changing a parameter
|
6
|
+
# @api private
|
7
|
+
class ChangedEnforcedStyles < ParameterRule
|
8
|
+
BASE_MESSAGE = 'obsolete `%<parameter>s: %<value>s` (for `%<cop>s`) found in %<path>s'
|
9
|
+
|
10
|
+
def violated?
|
11
|
+
super && config[cop][parameter] == value
|
12
|
+
end
|
13
|
+
|
14
|
+
def message
|
15
|
+
base = format(BASE_MESSAGE,
|
16
|
+
parameter: parameter, value: value, cop: cop, path: smart_loaded_path)
|
17
|
+
|
18
|
+
if alternative
|
19
|
+
"#{base}\n`#{parameter}: #{value}` has been renamed to " \
|
20
|
+
"`#{parameter}: #{alternative.chomp}`."
|
21
|
+
else
|
22
|
+
"#{base}\n#{reason.chomp}"
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def value
|
29
|
+
metadata['value']
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
class ConfigObsoletion
|
5
|
+
# Encapsulation of a ConfigObsoletion rule for changing a parameter
|
6
|
+
# @api private
|
7
|
+
class ChangedParameter < ParameterRule
|
8
|
+
BASE_MESSAGE = 'obsolete parameter `%<parameter>s` (for `%<cop>s`) found in %<path>s'
|
9
|
+
|
10
|
+
def message
|
11
|
+
base = format(BASE_MESSAGE, parameter: parameter, cop: cop, path: smart_loaded_path)
|
12
|
+
|
13
|
+
if alternative
|
14
|
+
"#{base}\n`#{parameter}` has been renamed to `#{alternative.chomp}`."
|
15
|
+
else
|
16
|
+
"#{base}\n#{reason.chomp}"
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
class ConfigObsoletion
|
5
|
+
# Base class for ConfigObsoletion rules relating to cops
|
6
|
+
# @api private
|
7
|
+
class CopRule < Rule
|
8
|
+
attr_reader :old_name
|
9
|
+
|
10
|
+
def initialize(config, old_name)
|
11
|
+
super(config)
|
12
|
+
@old_name = old_name
|
13
|
+
end
|
14
|
+
|
15
|
+
def cop_rule?
|
16
|
+
true
|
17
|
+
end
|
18
|
+
|
19
|
+
def message
|
20
|
+
rule_message + "\n(obsolete configuration found in " \
|
21
|
+
"#{smart_loaded_path}, please update it)"
|
22
|
+
end
|
23
|
+
|
24
|
+
# Cop rules currently can only be failures, not warnings
|
25
|
+
def warning?
|
26
|
+
false
|
27
|
+
end
|
28
|
+
|
29
|
+
def violated?
|
30
|
+
config.key?(old_name) || config.key?(Cop::Badge.parse(old_name).cop_name)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
class ConfigObsoletion
|
5
|
+
# Encapsulation of a ConfigObsoletion rule for splitting a cop's
|
6
|
+
# functionality into multiple new cops.
|
7
|
+
# @api private
|
8
|
+
class ExtractedCop < CopRule
|
9
|
+
attr_reader :gem, :department
|
10
|
+
|
11
|
+
def initialize(config, old_name, gem)
|
12
|
+
super(config, old_name)
|
13
|
+
@department, * = old_name.rpartition('/')
|
14
|
+
@gem = gem
|
15
|
+
end
|
16
|
+
|
17
|
+
def violated?
|
18
|
+
return false if gem_installed?
|
19
|
+
|
20
|
+
affected_gems.any?
|
21
|
+
end
|
22
|
+
|
23
|
+
def rule_message
|
24
|
+
msg = '%<name>s been extracted to the `%<gem>s` gem.'
|
25
|
+
format(msg,
|
26
|
+
name: affected_gems.size > 1 ? "`#{department}` cops have" : "`#{old_name}` has",
|
27
|
+
gem: gem)
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def affected_gems
|
33
|
+
return old_name unless old_name.end_with?('*')
|
34
|
+
|
35
|
+
# Handle whole departments (expressed as `Department/*`)
|
36
|
+
config.keys.grep(Regexp.new("^#{department}"))
|
37
|
+
end
|
38
|
+
|
39
|
+
def gem_installed?
|
40
|
+
Lockfile.new.includes_gem?(gem)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
class ConfigObsoletion
|
5
|
+
# Base class for ConfigObsoletion rules relating to parameters
|
6
|
+
# @api private
|
7
|
+
class ParameterRule < Rule
|
8
|
+
attr_reader :cop, :parameter, :metadata
|
9
|
+
|
10
|
+
def initialize(config, cop, parameter, metadata)
|
11
|
+
super(config)
|
12
|
+
@cop = cop
|
13
|
+
@parameter = parameter
|
14
|
+
@metadata = metadata
|
15
|
+
end
|
16
|
+
|
17
|
+
def parameter_rule?
|
18
|
+
true
|
19
|
+
end
|
20
|
+
|
21
|
+
def violated?
|
22
|
+
config[cop]&.key?(parameter)
|
23
|
+
end
|
24
|
+
|
25
|
+
def warning?
|
26
|
+
severity == 'warning'
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def alternative
|
32
|
+
metadata['alternative']
|
33
|
+
end
|
34
|
+
|
35
|
+
def reason
|
36
|
+
metadata['reason']
|
37
|
+
end
|
38
|
+
|
39
|
+
def severity
|
40
|
+
metadata['severity']
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
class ConfigObsoletion
|
5
|
+
# Encapsulation of a ConfigObsoletion rule for removing
|
6
|
+
# a previously defined cop.
|
7
|
+
# @api private
|
8
|
+
class RemovedCop < CopRule
|
9
|
+
attr_reader :old_name, :metadata
|
10
|
+
|
11
|
+
BASE_MESSAGE = 'The `%<old_name>s` cop has been removed'
|
12
|
+
|
13
|
+
def initialize(config, old_name, metadata)
|
14
|
+
super(config, old_name)
|
15
|
+
@metadata = metadata.is_a?(Hash) ? metadata : {}
|
16
|
+
end
|
17
|
+
|
18
|
+
def rule_message
|
19
|
+
base = format(BASE_MESSAGE, old_name: old_name)
|
20
|
+
|
21
|
+
if reason
|
22
|
+
"#{base} since #{reason.chomp}."
|
23
|
+
elsif alternatives
|
24
|
+
"#{base}. Please use #{to_sentence(alternatives, connector: 'and/or')} instead."
|
25
|
+
else
|
26
|
+
"#{base}."
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
private
|
31
|
+
|
32
|
+
def reason
|
33
|
+
metadata['reason']
|
34
|
+
end
|
35
|
+
|
36
|
+
def alternatives
|
37
|
+
Array(metadata['alternatives']).map { |name| "`#{name}`" }
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
class ConfigObsoletion
|
5
|
+
# Encapsulation of a ConfigObsoletion rule for renaming
|
6
|
+
# a cop or moving it to a new department.
|
7
|
+
# @api private
|
8
|
+
class RenamedCop < CopRule
|
9
|
+
attr_reader :new_name
|
10
|
+
|
11
|
+
def initialize(config, old_name, new_name)
|
12
|
+
super(config, old_name)
|
13
|
+
@new_name = new_name
|
14
|
+
end
|
15
|
+
|
16
|
+
def rule_message
|
17
|
+
"The `#{old_name}` cop has been #{verb} to `#{new_name}`."
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def moved?
|
23
|
+
old_badge = Cop::Badge.parse(old_name)
|
24
|
+
new_badge = Cop::Badge.parse(new_name)
|
25
|
+
|
26
|
+
old_badge.department != new_badge.department && old_badge.cop_name == new_badge.cop_name
|
27
|
+
end
|
28
|
+
|
29
|
+
def verb
|
30
|
+
moved? ? 'moved' : 'renamed'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
class ConfigObsoletion
|
5
|
+
# Abstract base class for ConfigObsoletion rules
|
6
|
+
# @api private
|
7
|
+
class Rule
|
8
|
+
def initialize(config)
|
9
|
+
@config = config
|
10
|
+
end
|
11
|
+
|
12
|
+
# Does this rule relate to cops?
|
13
|
+
def cop_rule?
|
14
|
+
false
|
15
|
+
end
|
16
|
+
|
17
|
+
# Does this rule relate to parameters?
|
18
|
+
def parameter_rule?
|
19
|
+
false
|
20
|
+
end
|
21
|
+
|
22
|
+
def violated?
|
23
|
+
raise NotImplementedError
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
attr_reader :config
|
29
|
+
|
30
|
+
def to_sentence(collection, connector: 'and')
|
31
|
+
return collection.first if collection.size == 1
|
32
|
+
|
33
|
+
[collection[0..-2].join(', '), collection[-1]].join(" #{connector} ")
|
34
|
+
end
|
35
|
+
|
36
|
+
def smart_loaded_path
|
37
|
+
PathUtil.smart_path(config.loaded_path)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
class ConfigObsoletion
|
5
|
+
# Encapsulation of a ConfigObsoletion rule for splitting a cop's
|
6
|
+
# functionality into multiple new cops.
|
7
|
+
# @api private
|
8
|
+
class SplitCop < CopRule
|
9
|
+
attr_reader :metadata
|
10
|
+
|
11
|
+
def initialize(config, old_name, metadata)
|
12
|
+
super(config, old_name)
|
13
|
+
@metadata = metadata
|
14
|
+
end
|
15
|
+
|
16
|
+
def rule_message
|
17
|
+
"The `#{old_name}` cop has been split into #{to_sentence(alternatives)}."
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
def alternatives
|
23
|
+
Array(metadata['alternatives']).map { |name| "`#{name}`" }
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -69,7 +69,7 @@ module RuboCop
|
|
69
69
|
attr_reader :target_ruby
|
70
70
|
|
71
71
|
def check_obsoletions
|
72
|
-
@config_obsoletion.
|
72
|
+
@config_obsoletion.reject_obsolete!
|
73
73
|
return unless @config_obsoletion.warnings.any?
|
74
74
|
|
75
75
|
warn Rainbow("Warning: #{@config_obsoletion.warnings.join("\n")}").yellow
|
@@ -106,10 +106,17 @@ module RuboCop
|
|
106
106
|
# to do so than to pass the value around to various methods.
|
107
107
|
next if name == 'inherit_mode'
|
108
108
|
|
109
|
-
|
110
|
-
|
109
|
+
suggestions = NameSimilarity.find_similar_names(name, Cop::Registry.global.map(&:cop_name))
|
110
|
+
suggestion = "Did you mean `#{suggestions.join('`, `')}`?" if suggestions.any?
|
111
|
+
|
112
|
+
message = <<~MESSAGE.rstrip
|
113
|
+
unrecognized cop #{name} found in #{smart_loaded_path}
|
114
|
+
#{suggestion}
|
115
|
+
MESSAGE
|
116
|
+
|
117
|
+
unknown_cops << message
|
111
118
|
end
|
112
|
-
raise ValidationError, unknown_cops.join(
|
119
|
+
raise ValidationError, unknown_cops.join("\n") if unknown_cops.any?
|
113
120
|
end
|
114
121
|
|
115
122
|
def validate_syntax_cop
|
data/lib/rubocop/cop/base.rb
CHANGED
@@ -288,13 +288,6 @@ module RuboCop
|
|
288
288
|
@current_corrector&.merge!(corrector) if corrector
|
289
289
|
end
|
290
290
|
|
291
|
-
def correction_strategy
|
292
|
-
return :unsupported unless correctable?
|
293
|
-
return :uncorrected unless autocorrect?
|
294
|
-
|
295
|
-
:attempt_correction
|
296
|
-
end
|
297
|
-
|
298
291
|
### Reserved for Commissioner:
|
299
292
|
|
300
293
|
def current_offense_locations
|
@@ -341,33 +334,42 @@ module RuboCop
|
|
341
334
|
|
342
335
|
# @return [Symbol, Corrector] offense status
|
343
336
|
def correct(range)
|
344
|
-
status = correction_strategy
|
345
|
-
|
346
337
|
if block_given?
|
347
338
|
corrector = Corrector.new(self)
|
348
339
|
yield corrector
|
349
|
-
if
|
340
|
+
if corrector.empty?
|
341
|
+
corrector = nil
|
342
|
+
elsif !self.class.support_autocorrect?
|
350
343
|
raise "The Cop #{name} must `extend AutoCorrector` to be able to autocorrect"
|
351
344
|
end
|
352
345
|
end
|
353
346
|
|
354
|
-
|
347
|
+
[use_corrector(range, corrector), corrector]
|
348
|
+
end
|
355
349
|
|
356
|
-
|
350
|
+
# @return [Symbol] offense status
|
351
|
+
def use_corrector(range, corrector)
|
352
|
+
if autocorrect?
|
353
|
+
attempt_correction(range, corrector)
|
354
|
+
elsif corrector
|
355
|
+
:uncorrected
|
356
|
+
else
|
357
|
+
:unsupported
|
358
|
+
end
|
357
359
|
end
|
358
360
|
|
359
361
|
# @return [Symbol] offense status
|
360
362
|
def attempt_correction(range, corrector)
|
361
|
-
if corrector
|
363
|
+
if corrector
|
362
364
|
status = :corrected
|
363
365
|
elsif disable_uncorrectable?
|
364
366
|
corrector = disable_uncorrectable(range)
|
365
367
|
status = :corrected_with_todo
|
366
368
|
else
|
367
|
-
return :
|
369
|
+
return :unsupported
|
368
370
|
end
|
369
371
|
|
370
|
-
apply_correction(corrector)
|
372
|
+
apply_correction(corrector)
|
371
373
|
status
|
372
374
|
end
|
373
375
|
|
data/lib/rubocop/cop/cop.rb
CHANGED
@@ -27,7 +27,7 @@ module RuboCop
|
|
27
27
|
def add_offense(node_or_range, location: :expression, message: nil, severity: nil, &block)
|
28
28
|
@v0_argument = node_or_range
|
29
29
|
range = find_location(node_or_range, location)
|
30
|
-
if block.nil? && !
|
30
|
+
if block.nil? && !support_autocorrect?
|
31
31
|
super(range, message: message, severity: severity)
|
32
32
|
else
|
33
33
|
super(range, message: message, severity: severity) do |corrector|
|
@@ -136,7 +136,7 @@ module RuboCop
|
|
136
136
|
end
|
137
137
|
|
138
138
|
def correction_lambda
|
139
|
-
return unless
|
139
|
+
return unless support_autocorrect?
|
140
140
|
|
141
141
|
dedup_on_node(@v0_argument) do
|
142
142
|
autocorrect(@v0_argument)
|
@@ -7,16 +7,14 @@ module RuboCop
|
|
7
7
|
extend Util
|
8
8
|
|
9
9
|
class << self
|
10
|
-
def correct(node, style)
|
10
|
+
def correct(corrector, node, style)
|
11
11
|
return if node.dstr_type?
|
12
12
|
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
corrector.replace(node, str.inspect)
|
19
|
-
end
|
13
|
+
str = node.str_content
|
14
|
+
if style == :single_quotes
|
15
|
+
corrector.replace(node, to_string_literal(str))
|
16
|
+
else
|
17
|
+
corrector.replace(node, str.inspect)
|
20
18
|
end
|
21
19
|
end
|
22
20
|
end
|