-
Notifications
You must be signed in to change notification settings - Fork 27
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new
Sorbet/RedundantExtendTSig
cop
- Loading branch information
1 parent
0d1d5c9
commit 0931663
Showing
6 changed files
with
170 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Sorbet | ||
# Forbids the use of redundant `extend T::Sig`. Only for use in | ||
# applications that monkey patch `Module.include(T::Sig)` globally, | ||
# which would make it redundant. | ||
# | ||
# @safety | ||
# This cop should not be enabled in applications that have not monkey | ||
# patched `Module`. | ||
# | ||
# @example | ||
# # bad | ||
# class Greeter | ||
# extend T::Sig | ||
# sig { void } | ||
# def say_hello = puts "hello" | ||
# end | ||
# | ||
# # good | ||
# class Greeter | ||
# sig { void } | ||
# def say_hello = puts "hello" | ||
# end | ||
# | ||
class RedundantExtendTSig < RuboCop::Cop::Cop | ||
MSG = "Do not redundantly `extend T::Sig` when it is already included in all modules." | ||
RESTRICT_ON_SEND = [:extend].freeze | ||
|
||
def_node_matcher :extend_t_sig?, <<~PATTERN | ||
(send _ :extend (const (const {nil? | cbase} :T) :Sig)) | ||
PATTERN | ||
|
||
def on_send(node) | ||
return unless extend_t_sig?(node) | ||
|
||
add_offense(node) | ||
end | ||
|
||
def autocorrect(node) | ||
lambda do |corrector| | ||
corrector.remove(node) | ||
end | ||
end | ||
end | ||
end | ||
end | ||
end |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,81 @@ | ||
# frozen_string_literal: true | ||
|
||
RSpec.describe(RuboCop::Cop::Sorbet::RedundantExtendTSig, :config) do | ||
let(:config) { RuboCop::Config.new } | ||
let(:message) { "Do not redundantly `extend T::Sig` when it is already included in all modules." } | ||
|
||
shared_examples "block form" do |label, header| # rubocop:disable Lint/UnusedBlockArgument | ||
it 'registers an offense when using `extend T::Sig` #{label}' do | ||
expect_offense(<<~RUBY) | ||
#{header} | ||
extend T::Sig | ||
^^^^^^^^^^^^^ #{message} | ||
end | ||
RUBY | ||
|
||
expect_correction(<<~RUBY) | ||
#{header} | ||
#{trailing_whitespace} | ||
end | ||
RUBY | ||
end | ||
|
||
private | ||
|
||
def trailing_whitespace | ||
"" | ||
end | ||
end | ||
|
||
include_examples "block form", "in a module", "module M" | ||
include_examples "block form", "in a class", "class C" | ||
include_examples "block form", "in an anonymous module", "Module.new do" | ||
include_examples "block form", "in an anonymous class", "Class.new do" | ||
include_examples "block form", "in `self`'s singleton class", "class << self" | ||
include_examples "block form", "in an arbitrary singleton class", "class << object" | ||
include_examples "block form", "in a module with other contents", <<~RUBY.chomp | ||
module M | ||
extend SomethingElse | ||
RUBY | ||
|
||
it "registers an offense when using `extend T::Sig` on its own" do | ||
expect_offense(<<~RUBY) | ||
extend T::Sig | ||
^^^^^^^^^^^^^ #{message} | ||
RUBY | ||
|
||
expect_correction(a_blank_line) | ||
end | ||
|
||
it "registers an offense when using `extend ::T::Sig` (fully qualified)" do | ||
expect_offense(<<~RUBY) | ||
extend ::T::Sig | ||
^^^^^^^^^^^^^^^ #{message} | ||
RUBY | ||
|
||
expect_correction(a_blank_line) | ||
end | ||
|
||
it "registers an offense when using `extend T::Sig` with an explicit receiver" do | ||
expect_offense(<<~RUBY) | ||
some_module.extend T::Sig | ||
^^^^^^^^^^^^^^^^^^^^^^^^^ #{message} | ||
RUBY | ||
|
||
expect_correction(a_blank_line) | ||
end | ||
|
||
it "does not register an offense when extending other modules in the T namespace" do | ||
expect_no_offenses(<<~RUBY) | ||
module M | ||
extend T::Helpers | ||
end | ||
RUBY | ||
end | ||
|
||
private | ||
|
||
def a_blank_line | ||
"\n" | ||
end | ||
end |