Skip to content

Commit

Permalink
Add cop to forbid extend T::Sig in shims
Browse files Browse the repository at this point in the history
  • Loading branch information
Ryan Brushett committed Mar 11, 2021
1 parent 68c0113 commit b8d285f
Show file tree
Hide file tree
Showing 6 changed files with 144 additions and 0 deletions.
7 changes: 7 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,13 @@ Sorbet/FalseSigil:
- db/**/*.rb
- script/**/*

Sorbet/ForbidExtendTSigInShims:
Description: 'Forbid the use of `extend T::Sig` in RBI shims'
Enabled: false
VersionAdded: '0.86'
Include:
- "sorbet/rbi/shims/**/*.rbi"

Sorbet/ForbidIncludeConstLiteral:
Description: 'Forbids include of non-literal constants.'
Enabled: false
Expand Down
47 changes: 47 additions & 0 deletions lib/rubocop/cop/sorbet/forbid_extend_t_sig_in_shims.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# frozen_string_literal: true

module RuboCop
module Cop
module Sorbet
# This cop ensures RBI shims do not include a call to extend T::Sig
#
# @example
#
# # bad
# module SomeModule
# extend T::Sig
#
# sig { returns(String) }
# def foo; end
# end
#
# # good
# module SomeModule
# sig { returns(String) }
# def foo; end
# end
class ForbidExtendTSigInShims < RuboCop::Cop::Cop
include RangeHelp

MSG = 'Extending T::Sig in a shim is unnecessary'
RESTRICT_ON_SEND = [:extend]

def_node_matcher :extend_t_sig?, <<~PATTERN
(send nil? :extend (const (const nil? :T) :Sig))
PATTERN

def autocorrect(node)
-> (corrector) do
corrector.remove(
range_by_whole_lines(node.source_range, include_final_newline: true)
)
end
end

def on_send(node)
add_offense(node) if extend_t_sig?(node)
end
end
end
end
end
1 change: 1 addition & 0 deletions lib/rubocop/cop/sorbet_cops.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
# frozen_string_literal: true
require_relative 'sorbet/binding_constants_without_type_alias'
require_relative 'sorbet/constants_from_strings'
require_relative 'sorbet/forbid_extend_t_sig_in_shims'
require_relative 'sorbet/forbid_superclass_const_literal'
require_relative 'sorbet/forbid_include_const_literal'
require_relative 'sorbet/forbid_untyped_struct_props'
Expand Down
1 change: 1 addition & 0 deletions manual/cops.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ In the following section you find all available cops:
* [Sorbet/EnforceSigilOrder](cops_sorbet.md#sorbetenforcesigilorder)
* [Sorbet/EnforceSignatures](cops_sorbet.md#sorbetenforcesignatures)
* [Sorbet/FalseSigil](cops_sorbet.md#sorbetfalsesigil)
* [Sorbet/ForbidExtendTSigInShims](cops_sorbet.md#sorbetforbidextendtsiginshims)
* [Sorbet/ForbidIncludeConstLiteral](cops_sorbet.md#sorbetforbidincludeconstliteral)
* [Sorbet/ForbidSuperclassConstLiteral](cops_sorbet.md#sorbetforbidsuperclassconstliteral)
* [Sorbet/ForbidUntypedStructProps](cops_sorbet.md#sorbetforbiduntypedstructprops)
Expand Down
32 changes: 32 additions & 0 deletions manual/cops_sorbet.md
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,38 @@ SuggestedStrictness | `true` | Boolean
Include | `**/*.rb`, `**/*.rbi`, `**/*.rake`, `**/*.ru` | Array
Exclude | `bin/**/*`, `db/**/*.rb`, `script/**/*` | Array

## Sorbet/ForbidExtendTSigInShims

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
--- | --- | --- | --- | ---
Disabled | Yes | Yes | 0.86 | -

This cop ensures RBI shims do not include a call to extend T::Sig

### Examples

```ruby
# bad
module SomeModule
extend T::Sig

sig { returns(String) }
def foo; end
end

# good
module SomeModule
sig { returns(String) }
def foo; end
end
```

### Configurable attributes

Name | Default value | Configurable values
--- | --- | ---
Include | `sorbet/rbi/shims/**/*.rbi` | Array

## Sorbet/ForbidIncludeConstLiteral

Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
Expand Down
56 changes: 56 additions & 0 deletions spec/rubocop/cop/sorbet/forbid_extend_t_sig_in_shims_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
# frozen_string_literal: true

require 'spec_helper'

RSpec.describe(RuboCop::Cop::Sorbet::ForbidExtendTSigInShims, :config) do
subject(:cop) { described_class.new(config) }

describe('offences') do
it 'adds an offence when a targeted class or module extends T::Sig' do
expect_offense(<<~RBI)
module MyModule
extend T::Sig
^^^^^^^^^^^^^ Extending T::Sig in a shim is unnecessary
sig { returns(String) }
def foo; end
end
RBI
end
end

describe('no offences') do
it 'does not add an offence to uses of extend that are not T::Sig' do
expect_no_offenses(<<~RBI)
module MyModule
extend ActiverSupport::Concern
def foo; end
end
RBI
end
end

describe('autocorrect') do
it 'autocorrects usages of extend T::Sig by removing them' do
source = <<~RBI
module MyModule
extend T::Sig
extend ActiveSupport::Concern
sig { returns(String) }
def foo; end
end
RBI
expect(autocorrect_source(source))
.to(eq(<<~RBI))
module MyModule
extend ActiveSupport::Concern
sig { returns(String) }
def foo; end
end
RBI
end
end
end

0 comments on commit b8d285f

Please sign in to comment.