Skip to content

Commit

Permalink
Merge branch 'master' into regenerate-todo
Browse files Browse the repository at this point in the history
  • Loading branch information
bbatsov authored Sep 25, 2020
2 parents 32ec02c + fb27511 commit f9a30fe
Show file tree
Hide file tree
Showing 17 changed files with 120 additions and 60 deletions.
8 changes: 8 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,18 @@
### New features

* [#8778](https://github.com/rubocop-hq/rubocop/pull/8778): Add command line option `--regenerate-todo`. ([@dvandersluis][])
* [#8790](https://github.com/rubocop-hq/rubocop/pull/8790): Add `AllowedMethods` option to `Style/OptionalBooleanParameter` cop. ([@fatkodima][])
* [#8738](https://github.com/rubocop-hq/rubocop/issues/8738): Add autocorrection to `Style/DateTime`. ([@dvandersluis][])

### Bug fixes

* [#8774](https://github.com/rubocop-hq/rubocop/issues/8774): Fix a false positive for `Layout/ArrayAlignment` with parallel assignment. ([@dvandersluis][])

### Changes

* [#8785](https://github.com/rubocop-hq/rubocop/pull/8785): Update TargetRubyVersion 2.8 to 3.0 (experimental). ([@em-gazelle][])
* [#8785](https://github.com/rubocop-hq/rubocop/pull/8785): Update TargetRubyVersion 2.8 to 3.0 (experimental). ([@koic][])
* [#8650](https://github.com/rubocop-hq/rubocop/issues/8650): Faster find of hidden files in `TargetFinder` class which improves rubocop initial startup speed. ([@tleish][])

## 0.91.1 (2020-09-23)

Expand Down Expand Up @@ -4913,3 +4920,4 @@
[@fsateler]: https://github.com/fsateler
[@iSarCasm]: https://github.com/iSarCasm
[@em-gazelle]: https://github.com/em-gazelle
[@tleish]: https://github.com/tleish
5 changes: 4 additions & 1 deletion config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2863,7 +2863,8 @@ Style/DateTime:
StyleGuide: '#date--time'
Enabled: false
VersionAdded: '0.51'
VersionChanged: '0.59'
VersionChanged: '0.92'
SafeAutoCorrect: false
AllowCoercion: false

Style/DefWithParentheses:
Expand Down Expand Up @@ -3725,6 +3726,8 @@ Style/OptionalBooleanParameter:
Enabled: pending
Safe: false
VersionAdded: '0.89'
AllowedMethods:
- respond_to_missing?

Style/OrAssignment:
Description: 'Recommend usage of double pipe equals (||=) where applicable.'
Expand Down
2 changes: 1 addition & 1 deletion docs/modules/ROOT/pages/compatibility.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ The following table is the support matrix.
| 2.5 | -
| 2.6 | -
| 2.7 | -
| 2.8 (experimental) | -
| 3.0 (experimental) | -
|===

NOTE: The compatibility xref:configuration.adoc#setting-the-target-ruby-version[target Ruby version mentioned here] is about code analysis (what RuboCop can analyze), not runtime (is RuboCop capable of running on some Ruby or not).
Expand Down
27 changes: 24 additions & 3 deletions docs/modules/ROOT/pages/cops_style.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1879,9 +1879,9 @@ an offense is reported.

| Disabled
| Yes
| No
| Yes (Unsafe)
| 0.51
| 0.59
| 0.92
|===

This cop checks for consistent usage of the `DateTime` class over the
Expand Down Expand Up @@ -6888,7 +6888,8 @@ end
|===

This cop checks for places where keyword arguments can be used instead of
boolean arguments when defining methods.
boolean arguments when defining methods. `respond_to_missing?` method is allowed by default.
These are customizable with `AllowedMethods` option.

=== Examples

Expand All @@ -6911,6 +6912,26 @@ def some_method(bar: false)
end
----

==== AllowedMethods: ['some_method']

[source,ruby]
----
# good
def some_method(bar = false)
puts bar
end
----

=== Configurable attributes

|===
| Name | Default value | Configurable values

| AllowedMethods
| `respond_to_missing?`
| Array
|===

=== References

* https://rubystyle.guide#boolean-keyword-arguments
Expand Down
6 changes: 4 additions & 2 deletions lib/rubocop.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,13 @@
require 'forwardable'
require 'regexp_parser'
require 'unicode/display_width/no_string_ext'

require_relative 'rubocop/version'
require 'rubocop-ast'

require_relative 'rubocop/ast_aliases'
require_relative 'rubocop/ext/regexp_node'

require_relative 'rubocop/version'

require_relative 'rubocop/core_ext/string'
require_relative 'rubocop/ext/processed_source'

Expand Down Expand Up @@ -637,3 +638,4 @@
unless File.exist?("#{__dir__}/../rubocop.gemspec") # Check if we are a gem
RuboCop::ResultCache.rubocop_required_features = $LOADED_FEATURES - before_us
end
RuboCop::AST.rubocop_loaded if RuboCop::AST.respond_to?(:rubocop_loaded)
13 changes: 12 additions & 1 deletion lib/rubocop/cop/style/date_time.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,8 @@ module Style
# # good
# something.to_time
class DateTime < Base
extend AutoCorrector

CLASS_MSG = 'Prefer Time over DateTime.'
COERCION_MSG = 'Do not use #to_datetime.'

Expand All @@ -63,14 +65,23 @@ def on_send(node)
return if historic_date?(node)

message = to_datetime?(node) ? COERCION_MSG : CLASS_MSG
add_offense(node, message: message)

add_offense(node, message: message) do |corrector|
autocorrect(corrector, node)
end
end

private

def disallow_coercion?
!cop_config['AllowCoercion']
end

def autocorrect(corrector, node)
return if to_datetime?(node)

corrector.replace(node.receiver.loc.name, 'Time')
end
end
end
end
Expand Down
34 changes: 7 additions & 27 deletions lib/rubocop/cop/style/mixin_usage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -50,41 +50,21 @@ class MixinUsage < Base
const)
PATTERN

def_node_matcher :wrapped_macro_scope?, <<~PATTERN
{({sclass class module block} ... ({begin if} ...))}
def_node_matcher :in_top_level_scope?, <<~PATTERN
{
root? # either at the top level
^[ {kwbegin begin if def} # or wrapped within one of these
#in_top_level_scope? ] # that is in top level scope
}
PATTERN

def on_send(node)
include_statement(node) do |statement|
return if node.argument? ||
accepted_include?(node) ||
belongs_to_class_or_module?(node)
return unless in_top_level_scope?(node)

add_offense(node, message: format(MSG, statement: statement))
end
end

private

def accepted_include?(node)
node.parent && (node.macro? || ascend_macro_scope?(node.parent))
end

def ascend_macro_scope?(ancestor)
return true if wrapped_macro_scope?(ancestor)

ancestor.parent && ascend_macro_scope?(ancestor.parent)
end

def belongs_to_class_or_module?(node)
if !node.parent
false
else
return true if node.parent.class_type? || node.parent.module_type?

belongs_to_class_or_module?(node.parent)
end
end
end
end
end
Expand Down
14 changes: 11 additions & 3 deletions lib/rubocop/cop/style/optional_boolean_parameter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ module RuboCop
module Cop
module Style
# This cop checks for places where keyword arguments can be used instead of
# boolean arguments when defining methods.
# boolean arguments when defining methods. `respond_to_missing?` method is allowed by default.
# These are customizable with `AllowedMethods` option.
#
# @example
# # bad
Expand All @@ -23,13 +24,20 @@ module Style
# puts bar
# end
#
# @example AllowedMethods: ['some_method']
# # good
# def some_method(bar = false)
# puts bar
# end
#
class OptionalBooleanParameter < Base
include AllowedMethods

MSG = 'Use keyword arguments when defining method with boolean argument.'
BOOLEAN_TYPES = %i[true false].freeze
METHODS_EXCLUDED = %i[respond_to_missing?].freeze

def on_def(node)
return if METHODS_EXCLUDED.include?(node.method_name)
return if allowed_method?(node.method_name)

node.arguments.each do |arg|
next unless arg.optarg_type?
Expand Down
10 changes: 5 additions & 5 deletions lib/rubocop/rspec/expect_offense.rb
Original file line number Diff line number Diff line change
Expand Up @@ -133,14 +133,14 @@ def expect_offense(source, file = nil, severity: nil, **replacements)
"#{@processed_source.diagnostics.map(&:render).join("\n")}"
end

offenses = _investigate(cop, @processed_source)
@offenses = _investigate(cop, @processed_source)
actual_annotations =
expected_annotations.with_offense_annotations(offenses)
expected_annotations.with_offense_annotations(@offenses)

expect(actual_annotations).to eq(expected_annotations), ''
expect(offenses.map(&:severity).uniq).to eq([severity]) if severity
expect(@offenses.map(&:severity).uniq).to eq([severity]) if severity

offenses
@offenses
end

def expect_correction(correction, loop: true)
Expand All @@ -157,7 +157,7 @@ def expect_correction(correction, loop: true)
break corrected_source if corrected_source == @processed_source.buffer.source

if iteration > RuboCop::Runner::MAX_ITERATIONS
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [])
raise RuboCop::Runner::InfiniteCorrectionLoop.new(@processed_source.path, [@offenses])
end

# Prepare for next loop
Expand Down
6 changes: 5 additions & 1 deletion lib/rubocop/runner.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,11 @@ def initialize(path, offenses_by_iteration, loop_start: -1)
root_cause = offenses_by_iteration[loop_start..-1]
.map { |x| x.map(&:cop_name).uniq.join(', ') }
.join(' -> ')
super "Infinite loop detected in #{path} and caused by #{root_cause}"

message = 'Infinite loop detected'
message += " in #{path}" if path
message += " and caused by #{root_cause}" if root_cause
super message
end
end

Expand Down
5 changes: 4 additions & 1 deletion lib/rubocop/target_finder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@ module RuboCop
# and picking ruby files.
# @api private
class TargetFinder
HIDDEN_PATH_SUBSTRING = "#{File::SEPARATOR}."

def initialize(config_store, options = {})
@config_store = config_store
@options = options
Expand Down Expand Up @@ -55,7 +57,8 @@ def target_files_in_dir(base_dir = Dir.pwd)
# Support Windows: Backslashes from command-line -> forward slashes
base_dir = base_dir.gsub(File::ALT_SEPARATOR, File::SEPARATOR) if File::ALT_SEPARATOR
all_files = find_files(base_dir, File::FNM_DOTMATCH)
hidden_files = Set.new(all_files - find_files(base_dir, 0))
# use file.include? for performance optimization
hidden_files = all_files.select { |file| file.include?(HIDDEN_PATH_SUBSTRING) }
base_dir_config = @config_store.for(base_dir)

target_files = all_files.select do |file|
Expand Down
2 changes: 1 addition & 1 deletion lib/rubocop/target_ruby.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ module RuboCop
# The kind of Ruby that code inspected by RuboCop is written in.
# @api private
class TargetRuby
KNOWN_RUBIES = [2.4, 2.5, 2.6, 2.7, 2.8].freeze
KNOWN_RUBIES = [2.4, 2.5, 2.6, 2.7, 3.0].freeze
DEFAULT_VERSION = KNOWN_RUBIES.first

OBSOLETE_RUBIES = {
Expand Down
4 changes: 2 additions & 2 deletions rubocop.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ Gem::Specification.new do |s|
}

s.add_runtime_dependency('parallel', '~> 1.10')
s.add_runtime_dependency('parser', '>= 2.7.1.1')
s.add_runtime_dependency('parser', '>= 2.7.1.5')
s.add_runtime_dependency('rainbow', '>= 2.2.2', '< 4.0')
s.add_runtime_dependency('regexp_parser', '>= 1.7')
s.add_runtime_dependency('rexml')
s.add_runtime_dependency('rubocop-ast', '>= 0.4.0', '< 1.0')
s.add_runtime_dependency('rubocop-ast', '>= 0.5.0')
s.add_runtime_dependency('ruby-progressbar', '~> 1.7')
s.add_runtime_dependency('unicode-display_width', '>= 1.4.0', '< 2.0')

Expand Down
6 changes: 3 additions & 3 deletions spec/rubocop/cli_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -1634,14 +1634,14 @@ def method(foo, bar, qux, fred, arg5, f) end #{'#' * 85}
it 'fails with an error message' do
create_file('.rubocop.yml', <<~YAML)
AllCops:
TargetRubyVersion: 3.0
TargetRubyVersion: 4.0
YAML
expect(cli.run([])).to eq(2)
expect($stderr.string.strip).to start_with(
'Error: RuboCop found unknown Ruby version 3.0 in `TargetRubyVersion`'
'Error: RuboCop found unknown Ruby version 4.0 in `TargetRubyVersion`'
)
expect($stderr.string.strip).to match(
/Supported versions: 2.4, 2.5, 2.6, 2.7, 2.8/
/Supported versions: 2.4, 2.5, 2.6, 2.7, 3.0/
)
end
end
Expand Down
4 changes: 2 additions & 2 deletions spec/rubocop/cop/layout/access_modifier_indentation_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ def test; end
it 'registers an offense and corrects access modifiers ' \
'in arbitrary blocks' do
expect_offense(<<~RUBY)
Test = func do
func do
private
^^^^^^^ Indent access modifiers like `private`.
Expand All @@ -185,7 +185,7 @@ def test; end
RUBY

expect_correction(<<~RUBY)
Test = func do
func do
private
Expand Down
12 changes: 12 additions & 0 deletions spec/rubocop/cop/style/date_time_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,20 +8,32 @@
DateTime.now
^^^^^^^^^^^^ Prefer Time over DateTime.
RUBY

expect_correction(<<~RUBY)
Time.now
RUBY
end

it 'registers an offense when using ::DateTime for current time' do
expect_offense(<<~RUBY)
::DateTime.now
^^^^^^^^^^^^^^ Prefer Time over DateTime.
RUBY

expect_correction(<<~RUBY)
::Time.now
RUBY
end

it 'registers an offense when using DateTime for modern date' do
expect_offense(<<~RUBY)
DateTime.iso8601('2016-06-29')
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Prefer Time over DateTime.
RUBY

expect_correction(<<~RUBY)
Time.iso8601('2016-06-29')
RUBY
end

it 'does not register an offense when using Time for current time' do
Expand Down
Loading

0 comments on commit f9a30fe

Please sign in to comment.