-
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.
- Loading branch information
1 parent
bd013a0
commit 2460e0a
Showing
4 changed files
with
137 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,49 @@ | ||
# frozen_string_literal: true | ||
|
||
module RuboCop | ||
module Cop | ||
module Sorbet | ||
# Forbids the use of redundant `extend T::Sig`. Meant for use in | ||
# applications that monkey patch `Module` to `extend T::Sig` globally, | ||
# which would make it redundant. | ||
# | ||
# @safety | ||
# This cop cannot know if the host application has monkey patched | ||
# `Module` to `extend T::Sig`, or if the offense is itself the | ||
# monkey-patch. | ||
# | ||
# @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 < Base | ||
extend AutoCorrector | ||
|
||
MSG = "Do not `extend T::Sig` when it is already extended into 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) 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
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 `extend T::Sig` when it is already extended into 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", label: "in a module", header: "module M" | ||
include_examples "block form", label: "in a class", header: "class C" | ||
include_examples "block form", label: "in an anonymous module", header: "Module.new do" | ||
include_examples "block form", label: "in an anonymous class", header: "Class.new do" | ||
include_examples "block form", label: "in `self`'s singleton class", header: "class << self" | ||
include_examples "block form", label: "in an arbitrary singleton class", header: "class << object" | ||
include_examples "block form", label: "in a module with other contents", header: <<~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 |