Skip to content

Commit

Permalink
Support auto-correction for Lint/DuplicateRequire
Browse files Browse the repository at this point in the history
This PR supports auto-correction for `Lint/DuplicateRequire`.
The auto-correction is unsafe because it may break the dependency order of `require`.
  • Loading branch information
koic authored and bbatsov committed Apr 17, 2022
1 parent 9bea0d3 commit 6193277
Show file tree
Hide file tree
Showing 4 changed files with 50 additions and 7 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
* [#10544](https://github.com/rubocop/rubocop/pull/10544): Support auto-correction for `Lint/DuplicateRequire`. ([@koic][])
2 changes: 2 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -1661,7 +1661,9 @@ Lint/DuplicateRegexpCharacterClassElement:
Lint/DuplicateRequire:
Description: 'Check for duplicate `require`s and `require_relative`s.'
Enabled: true
SafeAutoCorrect: false
VersionAdded: '0.90'
VersionChanged: '<<next>>'

Lint/DuplicateRescueException:
Description: 'Checks that there are no repeated exceptions used in `rescue` expressions.'
Expand Down
11 changes: 10 additions & 1 deletion lib/rubocop/cop/lint/duplicate_require.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,10 @@ module Cop
module Lint
# This cop checks for duplicate `require`s and `require_relative`s.
#
# @safety
# This cop's autocorrection is unsafe because it may break the dependency order
# of `require`.
#
# @example
# # bad
# require 'foo'
Expand All @@ -20,6 +24,9 @@ module Lint
# require_relative 'foo'
#
class DuplicateRequire < Base
include RangeHelp
extend AutoCorrector

MSG = 'Duplicate `%<method>s` detected.'
REQUIRE_METHODS = Set.new(%i[require require_relative]).freeze
RESTRICT_ON_SEND = REQUIRE_METHODS
Expand All @@ -39,7 +46,9 @@ def on_send(node)
return unless require_call?(node)
return if @required[node.parent].add?("#{node.method_name}#{node.first_argument}")

add_offense(node, message: format(MSG, method: node.method_name))
add_offense(node, message: format(MSG, method: node.method_name)) do |corrector|
corrector.remove(range_by_whole_lines(node.source_range, include_final_newline: true))
end
end
end
end
Expand Down
43 changes: 37 additions & 6 deletions spec/rubocop/cop/lint/duplicate_require_spec.rb
Original file line number Diff line number Diff line change
@@ -1,31 +1,43 @@
# frozen_string_literal: true

RSpec.describe RuboCop::Cop::Lint::DuplicateRequire, :config do
it 'registers an offense when duplicate `require` is detected' do
it 'registers and corrects an offense when duplicate `require` is detected' do
expect_offense(<<~RUBY)
require 'foo'
require 'foo'
^^^^^^^^^^^^^ Duplicate `require` detected.
RUBY

expect_correction(<<~RUBY)
require 'foo'
RUBY
end

it 'registers an offense when duplicate `require_relative` is detected' do
it 'registers and corrects an offense when duplicate `require_relative` is detected' do
expect_offense(<<~RUBY)
require_relative '../bar'
require_relative '../bar'
^^^^^^^^^^^^^^^^^^^^^^^^^ Duplicate `require_relative` detected.
RUBY

expect_correction(<<~RUBY)
require_relative '../bar'
RUBY
end

it 'registers an offense when duplicate `require` through `Kernel` is detected' do
it 'registers and corrects an offense when duplicate `require` through `Kernel` is detected' do
expect_offense(<<~RUBY)
require 'foo'
Kernel.require 'foo'
^^^^^^^^^^^^^^^^^^^^ Duplicate `require` detected.
RUBY

expect_correction(<<~RUBY)
require 'foo'
RUBY
end

it 'registers an offense for multiple duplicate requires' do
it 'registers and corrects an offense for multiple duplicate requires' do
expect_offense(<<~RUBY)
require 'foo'
require_relative '../bar'
Expand All @@ -36,26 +48,45 @@
^^^^^^^^^^^^^^^^^^^^ Duplicate `require` detected.
require 'quux'
RUBY

expect_correction(<<~RUBY)
require 'foo'
require_relative '../bar'
require 'foo/baz'
require 'quux'
RUBY
end

it 'registers an offense when duplicate requires are interleaved with some other code' do
it 'registers and corrects an offense when duplicate requires are interleaved with some other code' do
expect_offense(<<~RUBY)
require 'foo'
def m
end
require 'foo'
^^^^^^^^^^^^^ Duplicate `require` detected.
RUBY

expect_correction(<<~RUBY)
require 'foo'
def m
end
RUBY
end

it 'registers an offense for duplicate non top-level requires' do
it 'registers and corrects an offense for duplicate non top-level requires' do
expect_offense(<<~RUBY)
def m
require 'foo'
require 'foo'
^^^^^^^^^^^^^ Duplicate `require` detected.
end
RUBY

expect_correction(<<~RUBY)
def m
require 'foo'
end
RUBY
end

it 'does not register an offense when there are no duplicate `require`s' do
Expand Down

0 comments on commit 6193277

Please sign in to comment.