rubocop 0.34.2 → 0.35.0
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of rubocop might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +86 -0
- data/README.md +103 -31
- data/config/default.yml +32 -2
- data/config/disabled.yml +24 -0
- data/config/enabled.yml +20 -2
- data/lib/rubocop.rb +13 -0
- data/lib/rubocop/ast_node.rb +48 -0
- data/lib/rubocop/cli.rb +9 -0
- data/lib/rubocop/config.rb +8 -6
- data/lib/rubocop/config_loader.rb +30 -8
- data/lib/rubocop/cop/commissioner.rb +1 -1
- data/lib/rubocop/cop/cop.rb +19 -6
- data/lib/rubocop/cop/lint/circular_argument_reference.rb +33 -2
- data/lib/rubocop/cop/lint/debugger.rb +9 -56
- data/lib/rubocop/cop/lint/end_alignment.rb +29 -9
- data/lib/rubocop/cop/lint/eval.rb +6 -2
- data/lib/rubocop/cop/lint/format_parameter_mismatch.rb +24 -6
- data/lib/rubocop/cop/lint/literal_in_condition.rb +0 -5
- data/lib/rubocop/cop/lint/non_local_exit_from_iterator.rb +10 -1
- data/lib/rubocop/cop/lint/parentheses_as_grouped_expression.rb +1 -1
- data/lib/rubocop/cop/lint/space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/lint/unused_block_argument.rb +6 -0
- data/lib/rubocop/cop/lint/unused_method_argument.rb +8 -0
- data/lib/rubocop/cop/metrics/abc_size.rb +1 -1
- data/lib/rubocop/cop/mixin/access_modifier_node.rb +1 -1
- data/lib/rubocop/cop/mixin/autocorrect_alignment.rb +1 -1
- data/lib/rubocop/cop/mixin/autocorrect_unless_changing_ast.rb +26 -3
- data/lib/rubocop/cop/mixin/check_assignment.rb +2 -3
- data/lib/rubocop/cop/mixin/configurable_enforced_style.rb +59 -12
- data/lib/rubocop/cop/mixin/configurable_max.rb +1 -1
- data/lib/rubocop/cop/mixin/configurable_naming.rb +1 -1
- data/lib/rubocop/cop/mixin/first_element_line_break.rb +41 -0
- data/lib/rubocop/cop/mixin/negative_conditional.rb +1 -1
- data/lib/rubocop/cop/mixin/safe_assignment.rb +3 -14
- data/lib/rubocop/cop/mixin/statement_modifier.rb +2 -2
- data/lib/rubocop/cop/performance/detect.rb +5 -1
- data/lib/rubocop/cop/performance/fixed_size.rb +50 -0
- data/lib/rubocop/cop/performance/size.rb +1 -1
- data/lib/rubocop/cop/performance/string_replacement.rb +14 -8
- data/lib/rubocop/cop/rails/pluralization_grammar.rb +97 -0
- data/lib/rubocop/cop/style/align_hash.rb +1 -12
- data/lib/rubocop/cop/style/align_parameters.rb +19 -7
- data/lib/rubocop/cop/style/and_or.rb +42 -13
- data/lib/rubocop/cop/style/block_comments.rb +4 -2
- data/lib/rubocop/cop/style/block_delimiters.rb +57 -18
- data/lib/rubocop/cop/style/braces_around_hash_parameters.rb +1 -1
- data/lib/rubocop/cop/style/command_literal.rb +2 -10
- data/lib/rubocop/cop/style/copyright.rb +5 -3
- data/lib/rubocop/cop/style/documentation.rb +9 -6
- data/lib/rubocop/cop/style/dot_position.rb +6 -0
- data/lib/rubocop/cop/style/double_negation.rb +4 -15
- data/lib/rubocop/cop/style/each_with_object.rb +17 -4
- data/lib/rubocop/cop/style/empty_line_between_defs.rb +1 -5
- data/lib/rubocop/cop/style/encoding.rb +10 -4
- data/lib/rubocop/cop/style/extra_spacing.rb +23 -13
- data/lib/rubocop/cop/style/first_array_element_line_break.rb +41 -0
- data/lib/rubocop/cop/style/first_hash_element_line_break.rb +35 -0
- data/lib/rubocop/cop/style/first_method_argument_line_break.rb +37 -0
- data/lib/rubocop/cop/style/first_method_parameter_line_break.rb +42 -0
- data/lib/rubocop/cop/style/for.rb +2 -1
- data/lib/rubocop/cop/style/if_unless_modifier.rb +31 -0
- data/lib/rubocop/cop/style/indent_hash.rb +67 -37
- data/lib/rubocop/cop/style/indentation_width.rb +1 -1
- data/lib/rubocop/cop/style/leading_comment_space.rb +3 -2
- data/lib/rubocop/cop/style/method_call_parentheses.rb +8 -0
- data/lib/rubocop/cop/style/method_def_parentheses.rb +10 -7
- data/lib/rubocop/cop/style/multiline_operation_indentation.rb +8 -13
- data/lib/rubocop/cop/style/nested_modifier.rb +97 -0
- data/lib/rubocop/cop/style/next.rb +18 -0
- data/lib/rubocop/cop/style/parallel_assignment.rb +57 -15
- data/lib/rubocop/cop/style/predicate_name.rb +7 -2
- data/lib/rubocop/cop/style/regexp_literal.rb +2 -10
- data/lib/rubocop/cop/style/single_line_methods.rb +7 -5
- data/lib/rubocop/cop/style/single_space_before_first_arg.rb +1 -1
- data/lib/rubocop/cop/style/space_around_operators.rb +2 -0
- data/lib/rubocop/cop/style/special_global_vars.rb +4 -2
- data/lib/rubocop/cop/style/stabby_lambda_parentheses.rb +108 -0
- data/lib/rubocop/cop/style/trailing_comma.rb +9 -6
- data/lib/rubocop/cop/style/trailing_underscore_variable.rb +23 -2
- data/lib/rubocop/cop/style/unneeded_percent_q.rb +31 -20
- data/lib/rubocop/cop/style/variable_name.rb +5 -0
- data/lib/rubocop/cop/style/word_array.rb +2 -1
- data/lib/rubocop/cop/team.rb +17 -4
- data/lib/rubocop/cop/util.rb +5 -0
- data/lib/rubocop/cop/variable_force/locatable.rb +1 -1
- data/lib/rubocop/formatter/base_formatter.rb +1 -1
- data/lib/rubocop/formatter/disabled_config_formatter.rb +22 -10
- data/lib/rubocop/formatter/simple_text_formatter.rb +1 -1
- data/lib/rubocop/node_pattern.rb +390 -0
- data/lib/rubocop/options.rb +48 -36
- data/lib/rubocop/processed_source.rb +3 -1
- data/lib/rubocop/rake_task.rb +1 -1
- data/lib/rubocop/remote_config.rb +60 -0
- data/lib/rubocop/result_cache.rb +4 -2
- data/lib/rubocop/runner.rb +33 -10
- data/lib/rubocop/token.rb +2 -1
- data/lib/rubocop/version.rb +1 -1
- data/lib/rubocop/warning.rb +11 -0
- data/relnotes/v0.35.0.md +210 -0
- data/rubocop.gemspec +2 -2
- metadata +20 -6
data/lib/rubocop/options.rb
CHANGED
@@ -11,6 +11,7 @@ module RuboCop
|
|
11
11
|
|
12
12
|
def initialize
|
13
13
|
@options = {}
|
14
|
+
@validator = OptionsValidator.new(@options)
|
14
15
|
end
|
15
16
|
|
16
17
|
def parse(args)
|
@@ -19,7 +20,7 @@ module RuboCop
|
|
19
20
|
# `no_color` key, which is created automatically.
|
20
21
|
@options.delete(:no_color)
|
21
22
|
|
22
|
-
validate_compatibility
|
23
|
+
@validator.validate_compatibility
|
23
24
|
|
24
25
|
if @options[:stdin] && !args.one?
|
25
26
|
fail ArgumentError, '-s/--stdin requires exactly one path.'
|
@@ -28,19 +29,6 @@ module RuboCop
|
|
28
29
|
[@options, args]
|
29
30
|
end
|
30
31
|
|
31
|
-
# Cop name validation must be done later than option parsing, so it's not
|
32
|
-
# called from within this class.
|
33
|
-
def self.validate_cop_list(names)
|
34
|
-
return unless names
|
35
|
-
|
36
|
-
namespaces = Cop::Cop.all.types.map { |t| t.to_s.capitalize }
|
37
|
-
names.each do |name|
|
38
|
-
next if Cop::Cop.all.any? { |c| c.cop_name == name } ||
|
39
|
-
namespaces.include?(name)
|
40
|
-
fail ArgumentError, "Unrecognized cop or namespace: #{name}."
|
41
|
-
end
|
42
|
-
end
|
43
|
-
|
44
32
|
private
|
45
33
|
|
46
34
|
def define_options(args)
|
@@ -60,18 +48,6 @@ module RuboCop
|
|
60
48
|
end
|
61
49
|
end
|
62
50
|
|
63
|
-
def validate_compatibility
|
64
|
-
if @options.key?(:only) &&
|
65
|
-
(@options[:only] & %w(Lint/UnneededDisable UnneededDisable)).any?
|
66
|
-
fail ArgumentError, 'Lint/UnneededDisable can not be used with --only.'
|
67
|
-
end
|
68
|
-
if @options.key?(:cache) && !%w(true false).include?(@options[:cache])
|
69
|
-
fail ArgumentError, '-C/--cache argument must be true or false'
|
70
|
-
end
|
71
|
-
return unless (incompat = @options.keys & EXITING_OPTIONS).size > 1
|
72
|
-
fail ArgumentError, "Incompatible cli options: #{incompat.inspect}"
|
73
|
-
end
|
74
|
-
|
75
51
|
def add_only_options(opts)
|
76
52
|
add_cop_selection_csv_option('except', opts)
|
77
53
|
add_cop_selection_csv_option('only', opts)
|
@@ -80,9 +56,14 @@ module RuboCop
|
|
80
56
|
|
81
57
|
def add_cop_selection_csv_option(option, opts)
|
82
58
|
option(opts, "--#{option} [COP1,COP2,...]") do |list|
|
83
|
-
@options[:"#{option}"] =
|
84
|
-
|
85
|
-
|
59
|
+
@options[:"#{option}"] =
|
60
|
+
if list.empty?
|
61
|
+
['']
|
62
|
+
else
|
63
|
+
list.split(',').map do |c|
|
64
|
+
Cop::Cop.qualified_cop_name(c, "--#{option} option")
|
65
|
+
end
|
66
|
+
end
|
86
67
|
end
|
87
68
|
end
|
88
69
|
|
@@ -90,14 +71,13 @@ module RuboCop
|
|
90
71
|
option(opts, '-c', '--config FILE')
|
91
72
|
|
92
73
|
option(opts, '--auto-gen-config') do
|
93
|
-
validate_auto_gen_config_option(args)
|
94
74
|
@options[:formatters] = [[DEFAULT_FORMATTER],
|
95
75
|
[Formatter::DisabledConfigFormatter,
|
96
76
|
ConfigLoader::AUTO_GENERATED_FILE]]
|
97
77
|
end
|
98
78
|
|
99
79
|
option(opts, '--exclude-limit COUNT') do
|
100
|
-
validate_exclude_limit_option(args)
|
80
|
+
@validator.validate_exclude_limit_option(args)
|
101
81
|
end
|
102
82
|
|
103
83
|
option(opts, '--force-exclusion')
|
@@ -135,6 +115,7 @@ module RuboCop
|
|
135
115
|
option(opts, '-C', '--cache FLAG')
|
136
116
|
option(opts, '-d', '--debug')
|
137
117
|
option(opts, '-D', '--display-cop-names')
|
118
|
+
option(opts, '-E', '--extra-details')
|
138
119
|
option(opts, '-S', '--display-style-guide')
|
139
120
|
option(opts, '-R', '--rails')
|
140
121
|
option(opts, '-l', '--lint') do
|
@@ -172,13 +153,43 @@ module RuboCop
|
|
172
153
|
long_opt = args.find { |arg| arg.start_with?('--') }
|
173
154
|
long_opt[2..-1].sub(/ .*/, '').tr('-', '_').to_sym
|
174
155
|
end
|
156
|
+
end
|
157
|
+
|
158
|
+
# Validates option arguments and the options' compatibilty with each other.
|
159
|
+
class OptionsValidator
|
160
|
+
def initialize(options)
|
161
|
+
@options = options
|
162
|
+
end
|
163
|
+
|
164
|
+
# Cop name validation must be done later than option parsing, so it's not
|
165
|
+
# called from within Options.
|
166
|
+
def self.validate_cop_list(names)
|
167
|
+
return unless names
|
175
168
|
|
176
|
-
|
177
|
-
|
178
|
-
|
169
|
+
namespaces = Cop::Cop.all.types.map { |t| t.to_s.capitalize }
|
170
|
+
names.each do |name|
|
171
|
+
next if Cop::Cop.all.any? { |c| c.cop_name == name }
|
172
|
+
next if namespaces.include?(name)
|
173
|
+
next if %w(Syntax Lint/Syntax).include?(name)
|
174
|
+
|
175
|
+
fail ArgumentError, "Unrecognized cop or namespace: #{name}."
|
176
|
+
end
|
177
|
+
end
|
179
178
|
|
180
|
-
|
181
|
-
|
179
|
+
def validate_compatibility
|
180
|
+
if @options.key?(:only) &&
|
181
|
+
(@options[:only] & %w(Lint/UnneededDisable UnneededDisable)).any?
|
182
|
+
fail ArgumentError, 'Lint/UnneededDisable can not be used with --only.'
|
183
|
+
end
|
184
|
+
if @options.key?(:except) &&
|
185
|
+
(@options[:except] & %w(Lint/Syntax Syntax)).any?
|
186
|
+
fail ArgumentError, 'Syntax checking can not be turned off.'
|
187
|
+
end
|
188
|
+
if @options.key?(:cache) && !%w(true false).include?(@options[:cache])
|
189
|
+
fail ArgumentError, '-C/--cache argument must be true or false'
|
190
|
+
end
|
191
|
+
return if (incompat = @options.keys & Options::EXITING_OPTIONS).size <= 1
|
192
|
+
fail ArgumentError, "Incompatible cli options: #{incompat.inspect}"
|
182
193
|
end
|
183
194
|
|
184
195
|
def validate_exclude_limit_option(args)
|
@@ -247,6 +258,7 @@ module RuboCop
|
|
247
258
|
debug: 'Display debug info.',
|
248
259
|
display_cop_names: 'Display cop names in offense messages.',
|
249
260
|
display_style_guide: 'Display style guide URLs in offense messages.',
|
261
|
+
extra_details: 'Display extra details in offense messages.',
|
250
262
|
rails: 'Run extra Rails cops.',
|
251
263
|
lint: 'Run only lint cops.',
|
252
264
|
list_target_files: 'List all files RuboCop will inspect.',
|
@@ -15,8 +15,10 @@ module RuboCop
|
|
15
15
|
def self.from_file(path)
|
16
16
|
file = File.read(path)
|
17
17
|
new(file, path)
|
18
|
-
rescue
|
18
|
+
rescue Errno::ENOENT
|
19
19
|
abort("#{Rainbow('rubocop: No such file or directory').red} -- #{path}")
|
20
|
+
rescue => ex
|
21
|
+
abort("#{Rainbow("rubocop: #{ex.message}").red} -- #{path}")
|
20
22
|
end
|
21
23
|
|
22
24
|
def initialize(source, path = nil)
|
data/lib/rubocop/rake_task.rb
CHANGED
@@ -0,0 +1,60 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'net/http'
|
4
|
+
|
5
|
+
module RuboCop
|
6
|
+
# Common methods and behaviors for dealing with remote config files.
|
7
|
+
class RemoteConfig
|
8
|
+
CACHE_LIFETIME = 24 * 60 * 60
|
9
|
+
|
10
|
+
def initialize(url)
|
11
|
+
@uri = URI.parse(url)
|
12
|
+
end
|
13
|
+
|
14
|
+
def file
|
15
|
+
return cache_path unless cache_path_expired?
|
16
|
+
|
17
|
+
http = Net::HTTP.new(@uri.hostname, @uri.port)
|
18
|
+
http.use_ssl = true if @uri.instance_of? URI::HTTPS
|
19
|
+
|
20
|
+
request = Net::HTTP::Get.new(@uri.request_uri)
|
21
|
+
if cache_path_exists?
|
22
|
+
request['If-Modified-Since'] = File.stat(cache_path).mtime.rfc2822
|
23
|
+
end
|
24
|
+
response = http.request(request)
|
25
|
+
|
26
|
+
cache_path.tap do |f|
|
27
|
+
if response.is_a?(Net::HTTPSuccess)
|
28
|
+
open f, 'w' do |io|
|
29
|
+
io.write response.body
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def cache_path
|
38
|
+
".rubocop-#{cache_name_from_uri}"
|
39
|
+
end
|
40
|
+
|
41
|
+
def cache_path_exists?
|
42
|
+
@cache_path_exists ||= File.exist?(cache_path)
|
43
|
+
end
|
44
|
+
|
45
|
+
def cache_path_expired?
|
46
|
+
return true unless cache_path_exists?
|
47
|
+
|
48
|
+
@cache_path_expired ||= begin
|
49
|
+
file_age = (Time.now - File.stat(cache_path).mtime).to_f
|
50
|
+
(file_age / CACHE_LIFETIME) > 1
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def cache_name_from_uri
|
55
|
+
uri = @uri.clone
|
56
|
+
uri.query = nil
|
57
|
+
uri.to_s.gsub!(/[^0-9A-Za-z]/, '-')
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/rubocop/result_cache.rb
CHANGED
@@ -3,6 +3,7 @@
|
|
3
3
|
require 'digest/md5'
|
4
4
|
require 'find'
|
5
5
|
require 'tmpdir'
|
6
|
+
require 'etc'
|
6
7
|
|
7
8
|
module RuboCop
|
8
9
|
# Provides functionality for caching rubocop runs.
|
@@ -11,7 +12,8 @@ module RuboCop
|
|
11
12
|
# collisions.
|
12
13
|
def initialize(file, options, config_store, cache_root = nil)
|
13
14
|
cache_root ||= ResultCache.cache_root(config_store)
|
14
|
-
@path = File.join(cache_root, rubocop_checksum,
|
15
|
+
@path = File.join(cache_root, rubocop_checksum, RUBY_VERSION,
|
16
|
+
relevant_options(options),
|
15
17
|
file_checksum(file, config_store))
|
16
18
|
end
|
17
19
|
|
@@ -77,7 +79,7 @@ module RuboCop
|
|
77
79
|
|
78
80
|
def self.cache_root(config_store)
|
79
81
|
root = config_store.for('.')['AllCops']['CacheRootDirectory']
|
80
|
-
root = Dir.tmpdir if root == '/tmp'
|
82
|
+
root = File.join(Dir.tmpdir, Etc.getlogin) if root == '/tmp'
|
81
83
|
File.join(root, 'rubocop_cache')
|
82
84
|
end
|
83
85
|
|
data/lib/rubocop/runner.rb
CHANGED
@@ -15,13 +15,14 @@ module RuboCop
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
attr_reader :errors, :aborting
|
18
|
+
attr_reader :errors, :warnings, :aborting
|
19
19
|
alias_method :aborting?, :aborting
|
20
20
|
|
21
21
|
def initialize(options, config_store)
|
22
22
|
@options = options
|
23
23
|
@config_store = config_store
|
24
24
|
@errors = []
|
25
|
+
@warnings = []
|
25
26
|
@aborting = false
|
26
27
|
end
|
27
28
|
|
@@ -82,13 +83,16 @@ module RuboCop
|
|
82
83
|
file_started(file, disabled_line_ranges, comments)
|
83
84
|
else
|
84
85
|
processed_source = get_processed_source(file)
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
86
|
+
# Use delegators for objects sent to the formatters. These can be
|
87
|
+
# updated when the file is re-inspected.
|
88
|
+
disabled_line_ranges =
|
89
|
+
SimpleDelegator.new(processed_source.disabled_line_ranges)
|
90
|
+
comments = SimpleDelegator.new(processed_source.comments)
|
91
|
+
|
92
|
+
file_started(file, disabled_line_ranges, comments)
|
93
|
+
offenses = do_inspection_loop(file, processed_source,
|
94
|
+
disabled_line_ranges, comments)
|
95
|
+
save_in_cache(cache, offenses, processed_source)
|
92
96
|
end
|
93
97
|
|
94
98
|
offenses = formatter_set.file_finished(file, offenses.compact.sort.freeze)
|
@@ -120,7 +124,19 @@ module RuboCop
|
|
120
124
|
!@options[:auto_correct]
|
121
125
|
end
|
122
126
|
|
123
|
-
def
|
127
|
+
def save_in_cache(cache, offenses, processed_source)
|
128
|
+
return unless cache
|
129
|
+
# Caching results when a cop has crashed would prevent the crash in the
|
130
|
+
# next run, since the cop would not be called then. We want crashes to
|
131
|
+
# show up the same in each run.
|
132
|
+
return if errors.any? || warnings.any?
|
133
|
+
|
134
|
+
cache.save(offenses, processed_source.disabled_line_ranges,
|
135
|
+
processed_source.comments)
|
136
|
+
end
|
137
|
+
|
138
|
+
def do_inspection_loop(file, processed_source, disabled_line_ranges,
|
139
|
+
comments)
|
124
140
|
offenses = []
|
125
141
|
|
126
142
|
# Keep track of the state of the source. If a cop modifies the source
|
@@ -147,6 +163,10 @@ module RuboCop
|
|
147
163
|
break unless updated_source_file
|
148
164
|
|
149
165
|
processed_source = get_processed_source(file)
|
166
|
+
|
167
|
+
# Update delegators with new objects.
|
168
|
+
disabled_line_ranges.__setobj__(processed_source.disabled_line_ranges)
|
169
|
+
comments.__setobj__(processed_source.comments)
|
150
170
|
end
|
151
171
|
|
152
172
|
offenses
|
@@ -169,6 +189,7 @@ module RuboCop
|
|
169
189
|
team = Cop::Team.new(mobilized_cop_classes(config), config, @options)
|
170
190
|
offenses = team.inspect_file(processed_source)
|
171
191
|
@errors.concat(team.errors)
|
192
|
+
@warnings.concat(team.warnings)
|
172
193
|
[offenses, team.updated_source_file?]
|
173
194
|
end
|
174
195
|
|
@@ -177,7 +198,9 @@ module RuboCop
|
|
177
198
|
@mobilized_cop_classes[config.object_id] ||= begin
|
178
199
|
cop_classes = Cop::Cop.all
|
179
200
|
|
180
|
-
[:only, :except].each
|
201
|
+
[:only, :except].each do |opt|
|
202
|
+
OptionsValidator.validate_cop_list(@options[opt])
|
203
|
+
end
|
181
204
|
|
182
205
|
if @options[:only]
|
183
206
|
cop_classes.select! { |c| c.match?(@options[:only]) }
|
data/lib/rubocop/token.rb
CHANGED
data/lib/rubocop/version.rb
CHANGED
@@ -0,0 +1,11 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
module RuboCop
|
4
|
+
# A Warning exception is different from an Offense with severity 'warning'
|
5
|
+
# When a Warning is raised, this means that RuboCop was unable to perform a
|
6
|
+
# requested operation (such as inspecting or correcting a source file) due to
|
7
|
+
# user error
|
8
|
+
# For example, a configuration value in .rubocop.yml might be malformed
|
9
|
+
class Warning < StandardError
|
10
|
+
end
|
11
|
+
end
|
data/relnotes/v0.35.0.md
ADDED
@@ -0,0 +1,210 @@
|
|
1
|
+
Special thanks to [Alex Dowad](https://github.com/alexdowad) who
|
2
|
+
contributed an amazing number of bug fixes and improvements for this
|
3
|
+
release! Much appreciated!
|
4
|
+
|
5
|
+
And happy birthday to my beloved granny Vasilka, who turns today 78 years!
|
6
|
+
This release is dedicated to her!
|
7
|
+
|
8
|
+
### New features
|
9
|
+
|
10
|
+
* [#2028](https://github.com/bbatsov/rubocop/issues/2028): New config `ExtraDetails` supports addition of `Details` param to all cops to allow extra details on offense to be displayed. ([@tansaku][])
|
11
|
+
* [#2036](https://github.com/bbatsov/rubocop/issues/2036): New cop `Style/StabbyLambdaParentheses` will find and correct cases where a stabby lambda's paramaters are not wrapped in parentheses. ([@hmadison][])
|
12
|
+
* [#2246](https://github.com/bbatsov/rubocop/pull/2246): `Style/TrailingUnderscoreVariable` will now register an offense for `*_`. ([@rrosenblum][])
|
13
|
+
* [#2246](https://github.com/bbatsov/rubocop/pull/2246): `Style/TrailingUnderscoreVariable` now has a configuration to remove named underscore variables (Defaulted to false). ([@rrosenblum][])
|
14
|
+
* [#2276](https://github.com/bbatsov/rubocop/pull/2276): New cop `Performance/FixedSize` will register an offense when calling `length`, `size`, or `count` on statically sized objected (strings, symbols, arrays, and hashes). ([@rrosenblum][])
|
15
|
+
* New cop `Style/NestedModifier` checks for nested `if`, `unless`, `while` and `until` modifier statements. ([@lumeet][])
|
16
|
+
* [#2270](https://github.com/bbatsov/rubocop/pull/2270): Add a new `inherit_gem` configuration to inherit a config file from an installed gem [(originally requested in #290)](https://github.com/bbatsov/rubocop/issues/290). ([@jhansche][])
|
17
|
+
* Allow `StyleGuide` parameters in local configuration for all cops, so users can add references to custom style guide documents. ([@cornelius][])
|
18
|
+
* `UnusedMethodArgument` cop allows configuration to skip keyword arguments. ([@apiology][])
|
19
|
+
* [#2318](https://github.com/bbatsov/rubocop/pull/2318): `Lint/Debugger` cop now checks for `Pry.rescue`. ([@rrosenblum][])
|
20
|
+
* [#2277](https://github.com/bbatsov/rubocop/pull/2277): New cop `Style/FirstArrayElementLineBreak` checks for a line break before the first element in a multi-line array. ([@panthomakos][])
|
21
|
+
* [#2277](https://github.com/bbatsov/rubocop/pull/2277): New cop `Style/FirstHashElementLineBreak` checks for a line break before the first element in a multi-line hash. ([@panthomakos][])
|
22
|
+
* [#2277](https://github.com/bbatsov/rubocop/pull/2277): New cop `Style/FirstMethodArgumentLineBreak` checks for a line break before the first argument in a multi-line method call. ([@panthomakos][])
|
23
|
+
* [#2277](https://github.com/bbatsov/rubocop/pull/2277): New cop `Style/FirstMethodParameterLineBreak` checks for a line break before the first parameter in a multi-line method parameter definition. ([@panthomakos][])
|
24
|
+
* Add `Rails/PluralizationGrammar` cop, checks for incorrect grammar when using methods like `3.day.ago`, when you should write `3.days.ago`. ([@maxjacobson][])
|
25
|
+
* [#2347](https://github.com/bbatsov/rubocop/pull/2347): `Lint/Eval` cop does not warn about "security risk" when eval argument is a string literal without interpolations. ([@alexdowad][])
|
26
|
+
* [#2335](https://github.com/bbatsov/rubocop/issues/2335): `Style/VariableName` cop checks naming style of method parameters. ([@alexdowad][])
|
27
|
+
* [#2329](https://github.com/bbatsov/rubocop/pull/2329): New style `braces_for_chaining` for `Style/BlockDelimiters` cop enforces braces on a multi-line block if its return value is being chained with another method. ([@panthomakos][])
|
28
|
+
* `Lint/LiteralInCondition` warns if a symbol or dynamic symbol is used as a condition. ([@alexdowad][])
|
29
|
+
* [#2369](https://github.com/bbatsov/rubocop/issues/2369): `Style/TrailingComma` doesn't add a trailing comma to a multiline method chain which is the only arg to a method call. ([@alexdowad][])
|
30
|
+
* `CircularArgumentReference` cop updated to lint for ordinal circular argument references on top of optional keyword arguments. ([@maxjacobson][])
|
31
|
+
* Added ability to download shared rubocop config files from remote urls. ([@ptrippett][])
|
32
|
+
* [#1601](https://github.com/bbatsov/rubocop/issues/1601): Add `IgnoreEmptyMethods` config parameter for `Lint/UnusedMethodArgument` and `IgnoreEmptyBlocks` config parameter for `Lint/UnusedBlockArgument` cops. ([@alexdowad][])
|
33
|
+
* [#1729](https://github.com/bbatsov/rubocop/issues/1729): `Style/MethodDefParentheses` supports new 'require_no_parentheses_except_multiline' style. ([@alexdowad][])
|
34
|
+
* [#2173](https://github.com/bbatsov/rubocop/issues/2173): `Style/AlignParameters` also checks parameter alignment for method definitions. ([@alexdowad][])
|
35
|
+
* [#1825](https://github.com/bbatsov/rubocop/issues/1825): New `NameWhitelist` configuration parameter for `Style/PredicateName` can be used to suppress errors on known-good predicate names. ([@alexdowad][])
|
36
|
+
* `Style/Documentation` recognizes 'Constant = Class.new' as a class definition. ([@alexdowad][])
|
37
|
+
* [#1608](https://github.com/bbatsov/rubocop/issues/1608): Add new 'align_braces' style for `Style/IndentHash`. ([@alexdowad][])
|
38
|
+
* `Style/Next` can autocorrect. ([@alexdowad][])
|
39
|
+
|
40
|
+
### Bug Fixes
|
41
|
+
|
42
|
+
* [#2265](https://github.com/bbatsov/rubocop/issues/2265): Handle unary `+` in `ExtraSpacing` cop. ([@jonas054][])
|
43
|
+
* [#2275](https://github.com/bbatsov/rubocop/pull/2275): Copy default `Exclude` into `Exclude` lists in `.rubocop_todo.yml`. ([@jonas054][])
|
44
|
+
* `Style/IfUnlessModifier` accepts blocks followed by a chained call. ([@lumeet][])
|
45
|
+
* [#2261](https://github.com/bbatsov/rubocop/issues/2261): Make relative `Exclude` paths in `$HOME/.rubocop_todo.yml` be relative to current directory. ([@jonas054][])
|
46
|
+
* [#2286](https://github.com/bbatsov/rubocop/issues/2286): Handle auto-correction of empty method when `AllowIfMethodIsEmpty` is `false` in `Style/SingleLineMethods`. ([@jonas054][])
|
47
|
+
* [#2246](https://github.com/bbatsov/rubocop/pull/2246): Do not register an offense for `Style/TrailingUnderscoreVariable` when the underscore variable is preceeded by a splat variable. ([@rrosenblum][])
|
48
|
+
* [#2292](https://github.com/bbatsov/rubocop/pull/2292): Results should not be stored in the cache if affected by errors (crashes). ([@jonas054][])
|
49
|
+
* [#2280](https://github.com/bbatsov/rubocop/issues/2280): Avoid reporting space between hash literal keys and values in `Style/ExtraSpacing`. ([@jonas054][])
|
50
|
+
* [#2284](https://github.com/bbatsov/rubocop/issues/2284): Fix result cache being shared between ruby versions. ([@miquella][])
|
51
|
+
* [#2285](https://github.com/bbatsov/rubocop/issues/2285): Fix `ConfigurableNaming#class_emitter_method?` error when handling singleton class methods. ([@palkan][])
|
52
|
+
* [#2295](https://github.com/bbatsov/rubocop/issues/2295): Fix Performance/Detect autocorrect to handle rogue newlines. ([@palkan][])
|
53
|
+
* [#2294](https://github.com/bbatsov/rubocop/issues/2294): Do not register an offense in `Performance/StringReplacement` for regex with options. ([@rrosenblum][])
|
54
|
+
* Fix `Style/UnneededPercentQ` condition for single-quoted literal containing interpolation-like string. ([@eagletmt][])
|
55
|
+
* [#2324](https://github.com/bbatsov/rubocop/issues/2324): Handle `--only Lint/Syntax` and `--except Lint/Syntax` correctly. ([@jonas054][])
|
56
|
+
* [#2317](https://github.com/bbatsov/rubocop/issues/2317): Handle `case` as an argument correctly in `Lint/EndAlignment`. ([@lumeet][])
|
57
|
+
* [#2287](https://github.com/bbatsov/rubocop/issues/2287): Fix auto-correct of lines with only whitespace in `Style/IndentationWidth`. ([@lumeet][])
|
58
|
+
* [#2331](https://github.com/bbatsov/rubocop/issues/2331): Do not register an offense in `Performance/Size` for `count` with an argument. ([@rrosenblum][])
|
59
|
+
* Handle a backslash at the end of a line in `Style/SpaceAroundOperators`. ([@lumeet][])
|
60
|
+
* Don't warn about lack of "leading space" in a =begin/=end comment. ([@alexdowad][])
|
61
|
+
* [#2307](https://github.com/bbatsov/rubocop/issues/2307): In `Lint/FormatParameterMismatch`, don't register an offense if either argument to % is not a literal. ([@alexdowad][])
|
62
|
+
* [#2356](https://github.com/bbatsov/rubocop/pull/2356): `Style/Encoding` will now place the encoding comment on the second line if the first line is a shebang. ([@rrosenblum][])
|
63
|
+
* `Style/InitialIndentation` cop doesn't error out when a line begins with an integer literal. ([@alexdowad][])
|
64
|
+
* [#2296](https://github.com/bbatsov/rubocop/issues/2296): In `Style/DotPosition`, don't "correct" (and break) a method call which has a line comment (or blank line) between the dot and the selector. ([@alexdowad][])
|
65
|
+
* [#2272](https://github.com/bbatsov/rubocop/issues/2272): `Lint/NonLocalExitFromIterator` does not warn about `return` in a block which is passed to `Module#define_method`. ([@alexdowad][])
|
66
|
+
* [#2262](https://github.com/bbatsov/rubocop/issues/2262): Replace `Rainbow` reference with `Colorizable#yellow`. ([@minustehbare][])
|
67
|
+
* [#2068](https://github.com/bbatsov/rubocop/issues/2068): Display warning if `Style/Copyright` is misconfigured. ([@alexdowad][])
|
68
|
+
* [#2321](https://github.com/bbatsov/rubocop/issues/2321): In `Style/EachWithObject`, don't replace reduce with each_with_object if the accumulator parameter is assigned to in the block. ([@alexdowad][])
|
69
|
+
* [#1981](https://github.com/bbatsov/rubocop/issues/1981): `Lint/UselessAssignment` doesn't erroneously identify assignments in identical if branches as useless. ([@alexdowad][])
|
70
|
+
* [#2323](https://github.com/bbatsov/rubocop/issues/2323): `Style/IfUnlessModifier` cop parenthesizes autocorrected code when necessary due to operator precedence, to avoid changing its meaning. ([@alexdowad][])
|
71
|
+
* [#2003](https://github.com/bbatsov/rubocop/issues/2003): Make `Lint/UnneededDisable` work with `--auto-correct`. ([@jonas054][])
|
72
|
+
* Default RuboCop cache dir moved to per-user folders. ([@br3nda][])
|
73
|
+
* [#2393](https://github.com/bbatsov/rubocop/pull/2393): `Style/MethodCallParentheses` doesn't fail on `obj.method ||= func()`. ([@alexdowad][])
|
74
|
+
* [#2344](https://github.com/bbatsov/rubocop/pull/2344): When autocorrecting, `Style/ParallelAssignment` reorders assignment statements, if necessary, to avoid breaking code. ([@alexdowad][])
|
75
|
+
* `Style/MultilineOperationAlignment` does not try to align the receiver and selector of a method call if both are on the LHS of an assignment. ([@alexdowad][])
|
76
|
+
|
77
|
+
### Changes
|
78
|
+
|
79
|
+
* [#2194](https://github.com/bbatsov/rubocop/issues/2194): Allow any options with `--auto-gen-config`. ([@agrimm][])
|
80
|
+
|
81
|
+
[@bbatsov]: https://github.com/bbatsov
|
82
|
+
[@jonas054]: https://github.com/jonas054
|
83
|
+
[@yujinakayama]: https://github.com/yujinakayama
|
84
|
+
[@dblock]: https://github.com/dblock
|
85
|
+
[@nevir]: https://github.com/nevir
|
86
|
+
[@daviddavis]: https://github.com/daviddavis
|
87
|
+
[@sds]: https://github.com/sds
|
88
|
+
[@fancyremarker]: https://github.com/fancyremarker
|
89
|
+
[@sinisterchipmunk]: https://github.com/sinisterchipmunk
|
90
|
+
[@vonTronje]: https://github.com/vonTronje
|
91
|
+
[@agrimm]: https://github.com/agrimm
|
92
|
+
[@pmenglund]: https://github.com/pmenglund
|
93
|
+
[@chulkilee]: https://github.com/chulkilee
|
94
|
+
[@codez]: https://github.com/codez
|
95
|
+
[@emou]: https://github.com/emou
|
96
|
+
[@skanev]: http://github.com/skanev
|
97
|
+
[@claco]: http://github.com/claco
|
98
|
+
[@rifraf]: http://github.com/rifraf
|
99
|
+
[@scottmatthewman]: https://github.com/scottmatthewman
|
100
|
+
[@ma2gedev]: http://github.com/ma2gedev
|
101
|
+
[@jeremyolliver]: https://github.com/jeremyolliver
|
102
|
+
[@hannestyden]: https://github.com/hannestyden
|
103
|
+
[@geniou]: https://github.com/geniou
|
104
|
+
[@jkogara]: https://github.com/jkogara
|
105
|
+
[@tmorris-fiksu]: https://github.com/tmorris-fiksu
|
106
|
+
[@mockdeep]: https://github.com/mockdeep
|
107
|
+
[@hiroponz]: https://github.com/hiroponz
|
108
|
+
[@tamird]: https://github.com/tamird
|
109
|
+
[@fshowalter]: https://github.com/fshowalter
|
110
|
+
[@cschramm]: https://github.com/cschramm
|
111
|
+
[@bquorning]: https://github.com/bquorning
|
112
|
+
[@bcobb]: https://github.com/bcobb
|
113
|
+
[@irrationalfab]: https://github.com/irrationalfab
|
114
|
+
[@tommeier]: https://github.com/tommeier
|
115
|
+
[@sfeldon]: https://github.com/sfeldon
|
116
|
+
[@biinari]: https://github.com/biinari
|
117
|
+
[@barunio]: https://github.com/barunio
|
118
|
+
[@molawson]: https://github.com/molawson
|
119
|
+
[@wndhydrnt]: https://github.com/wndhydrnt
|
120
|
+
[@ggilder]: https://github.com/ggilder
|
121
|
+
[@salbertson]: https://github.com/salbertson
|
122
|
+
[@camilleldn]: https://github.com/camilleldn
|
123
|
+
[@mcls]: https://github.com/mcls
|
124
|
+
[@yous]: https://github.com/yous
|
125
|
+
[@vrthra]: https://github.com/vrthra
|
126
|
+
[@SkuliOskarsson]: https://github.com/SkuliOskarsson
|
127
|
+
[@jspanjers]: https://github.com/jspanjers
|
128
|
+
[@sch1zo]: https://github.com/sch1zo
|
129
|
+
[@smangelsdorf]: https://github.com/smangelsdorf
|
130
|
+
[@mvz]: https://github.com/mvz
|
131
|
+
[@jfelchner]: https://github.com/jfelchner
|
132
|
+
[@janraasch]: https://github.com/janraasch
|
133
|
+
[@jcarbo]: https://github.com/jcarbo
|
134
|
+
[@oneamtu]: https://github.com/oneamtu
|
135
|
+
[@toy]: https://github.com/toy
|
136
|
+
[@Koronen]: https://github.com/Koronen
|
137
|
+
[@blainesch]: https://github.com/blainesch
|
138
|
+
[@marxarelli]: https://github.com/marxarelli
|
139
|
+
[@katieschilling]: https://github.com/katieschilling
|
140
|
+
[@kakutani]: https://github.com/kakutani
|
141
|
+
[@rrosenblum]: https://github.com/rrosenblum
|
142
|
+
[@mattjmcnaughton]: https://github.com/mattjmcnaughton
|
143
|
+
[@huerlisi]: https://github.com/huerlisi
|
144
|
+
[@volkert]: https://github.com/volkert
|
145
|
+
[@lumeet]: https://github.com/lumeet
|
146
|
+
[@mmozuras]: https://github.com/mmozuras
|
147
|
+
[@d4rk5eed]: https://github.com/d4rk5eed
|
148
|
+
[@cshaffer]: https://github.com/cshaffer
|
149
|
+
[@eitoball]: https://github.com/eitoball
|
150
|
+
[@iainbeeston]: https://github.com/iainbeeston
|
151
|
+
[@pimterry]: https://github.com/pimterry
|
152
|
+
[@palkan]: https://github.com/palkan
|
153
|
+
[@jdoconnor]: https://github.com/jdoconnor
|
154
|
+
[@meganemura]: https://github.com/meganemura
|
155
|
+
[@zvkemp]: https://github.com/zvkemp
|
156
|
+
[@vassilevsky]: https://github.com/vassilevsky
|
157
|
+
[@gerry3]: https://github.com/gerry3
|
158
|
+
[@ypresto]: https://github.com/ypresto
|
159
|
+
[@clowder]: https://github.com/clowder
|
160
|
+
[@mudge]: https://github.com/mudge
|
161
|
+
[@mzp]: https://github.com/mzp
|
162
|
+
[@bankair]: https://github.com/bankair
|
163
|
+
[@crimsonknave]: https://github.com/crimsonknave
|
164
|
+
[@renuo]: https://github.com/renuo
|
165
|
+
[@sdeframond]: https://github.com/sdeframond
|
166
|
+
[@til]: https://github.com/til
|
167
|
+
[@carhartl]: https://github.com/carhartl
|
168
|
+
[@dylandavidson]: https://github.com/dylandavidson
|
169
|
+
[@tmr08c]: https://github.com/tmr08c
|
170
|
+
[@hbd225]: https://github.com/hbd225
|
171
|
+
[@l8nite]: https://github.com/l8nite
|
172
|
+
[@sumeet]: https://github.com/sumeet
|
173
|
+
[@ojab]: https://github.com/ojab
|
174
|
+
[@chastell]: https://github.com/chastell
|
175
|
+
[@glasnt]: https://github.com/glasnt
|
176
|
+
[@crazydog115]: https://github.com/crazydog115
|
177
|
+
[@RGBD]: https://github.com/RGBD
|
178
|
+
[@panthomakos]: https://github.com/panthomakos
|
179
|
+
[@matugm]: https://github.com/matugm
|
180
|
+
[@m1foley]: https://github.com/m1foley
|
181
|
+
[@tejasbubane]: https://github.com/tejasbubane
|
182
|
+
[@bmorrall]: https://github.com/bmorrall
|
183
|
+
[@fphilipe]: https://github.com/fphilipe
|
184
|
+
[@gotrevor]: https://github.com/gotrevor
|
185
|
+
[@awwaiid]: https://github.com/awwaiid
|
186
|
+
[@segiddins]: https://github.com/segiddins
|
187
|
+
[@urbanautomaton]: https://github.com/urbanautomaton.com
|
188
|
+
[@unmanbearpig]: https://github.com/unmanbearpig
|
189
|
+
[@maxjacobson]: https://github.com/maxjacobson
|
190
|
+
[@sliuu]: https://github.com/sliuu
|
191
|
+
[@edmz]: https://github.com/edmz
|
192
|
+
[@syndbg]: https://github.com/syndbg
|
193
|
+
[@wli]: https://github.com/wli
|
194
|
+
[@caseywebdev]: https://github.com/caseywebdev
|
195
|
+
[@MGerrior]: https://github.com/MGerrior
|
196
|
+
[@imtayadeway]: https://github.com/imtayadeway
|
197
|
+
[@mrfoto]: https://github.com/mrfoto
|
198
|
+
[@karreiro]: https://github.com/karreiro
|
199
|
+
[@dreyks]: https://github.com/dreyks
|
200
|
+
[@hmadison]: https://github.com/hmadison
|
201
|
+
[@miquella]: https://github.com/miquella
|
202
|
+
[@jhansche]: https://github.com/jhansche
|
203
|
+
[@cornelius]: https://github.com/cornelius
|
204
|
+
[@eagletmt]: https://github.com/eagletmt
|
205
|
+
[@apiology]: https://github.com/apiology
|
206
|
+
[@alexdowad]: https://github.com/alexdowad
|
207
|
+
[@minustehbare]: https://github.com/minustehbare
|
208
|
+
[@tansaku]: https://github.com/tansaku
|
209
|
+
[@ptrippett]: https://github.com/ptrippett
|
210
|
+
[@br3nda]: https://github.com/br3nda
|