Skip to content

Commit ac2f94d

Browse files
authored
Merge pull request #340 from Shopify/at-inline-assertions-cops
Add cops to forbid usages of `T.` inline assertions and annotations
2 parents 10b66f1 + c5fabd2 commit ac2f94d

18 files changed

+498
-1
lines changed

config/default.yml

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -171,6 +171,36 @@ Sorbet/ForbidTStruct:
171171
VersionAdded: 0.7.4
172172
Safe: false
173173

174+
Sorbet/ForbidTAbsurd:
175+
Description: 'Forbid usage of T.absurd.'
176+
Enabled: false
177+
VersionAdded: <<next>>
178+
179+
Sorbet/ForbidTBind:
180+
Description: 'Forbid usage of T.bind.'
181+
Enabled: false
182+
VersionAdded: <<next>>
183+
184+
Sorbet/ForbidTCast:
185+
Description: 'Forbid usage of T.cast.'
186+
Enabled: false
187+
VersionAdded: <<next>>
188+
189+
Sorbet/ForbidTLet:
190+
Description: 'Forbid usage of T.let.'
191+
Enabled: false
192+
VersionAdded: <<next>>
193+
194+
Sorbet/ForbidTMust:
195+
Description: 'Forbid usage of T.must.'
196+
Enabled: false
197+
VersionAdded: <<next>>
198+
199+
Sorbet/ForbidTTypeAlias:
200+
Description: 'Forbid usage of T.type_alias.'
201+
Enabled: false
202+
VersionAdded: <<next>>
203+
174204
Sorbet/ForbidTUnsafe:
175205
Description: 'Forbid usage of T.unsafe.'
176206
Enabled: false
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
require "rubocop"
4+
5+
module RuboCop
6+
module Cop
7+
module Sorbet
8+
# Disallows using `T.absurd` anywhere.
9+
#
10+
# @example
11+
#
12+
# # bad
13+
# T.absurd(foo)
14+
#
15+
# # good
16+
# x #: absurd
17+
class ForbidTAbsurd < RuboCop::Cop::Base
18+
MSG = "Do not use `T.absurd`."
19+
RESTRICT_ON_SEND = [:absurd].freeze
20+
21+
# @!method t_absurd?(node)
22+
def_node_matcher(:t_absurd?, "(send (const nil? :T) :absurd _)")
23+
24+
def on_send(node)
25+
add_offense(node) if t_absurd?(node)
26+
end
27+
alias_method :on_csend, :on_send
28+
end
29+
end
30+
end
31+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
require "rubocop"
4+
5+
module RuboCop
6+
module Cop
7+
module Sorbet
8+
# Disallows using `T.bind` anywhere.
9+
#
10+
# @example
11+
#
12+
# # bad
13+
# T.bind(self, Integer)
14+
#
15+
# # good
16+
# #: self as Integer
17+
class ForbidTBind < RuboCop::Cop::Base
18+
MSG = "Do not use `T.bind`."
19+
RESTRICT_ON_SEND = [:bind].freeze
20+
21+
# @!method t_bind?(node)
22+
def_node_matcher(:t_bind?, "(send (const nil? :T) :bind _ _)")
23+
24+
def on_send(node)
25+
add_offense(node) if t_bind?(node)
26+
end
27+
alias_method :on_csend, :on_send
28+
end
29+
end
30+
end
31+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
require "rubocop"
4+
5+
module RuboCop
6+
module Cop
7+
module Sorbet
8+
# Disallows using `T.cast` anywhere.
9+
#
10+
# @example
11+
#
12+
# # bad
13+
# T.cast(foo, Integer)
14+
#
15+
# # good
16+
# foo #: as Integer
17+
class ForbidTCast < RuboCop::Cop::Base
18+
MSG = "Do not use `T.cast`."
19+
RESTRICT_ON_SEND = [:cast].freeze
20+
21+
# @!method t_cast?(node)
22+
def_node_matcher(:t_cast?, "(send (const nil? :T) :cast _ _)")
23+
24+
def on_send(node)
25+
add_offense(node) if t_cast?(node)
26+
end
27+
alias_method :on_csend, :on_send
28+
end
29+
end
30+
end
31+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
require "rubocop"
4+
5+
module RuboCop
6+
module Cop
7+
module Sorbet
8+
# Disallows using `T.let` anywhere.
9+
#
10+
# @example
11+
#
12+
# # bad
13+
# T.let(foo, Integer)
14+
#
15+
# # good
16+
# foo #: Integer
17+
class ForbidTLet < RuboCop::Cop::Base
18+
MSG = "Do not use `T.let`."
19+
RESTRICT_ON_SEND = [:let].freeze
20+
21+
# @!method t_let?(node)
22+
def_node_matcher(:t_let?, "(send (const nil? :T) :let _ _)")
23+
24+
def on_send(node)
25+
add_offense(node) if t_let?(node)
26+
end
27+
alias_method :on_csend, :on_send
28+
end
29+
end
30+
end
31+
end
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# frozen_string_literal: true
2+
3+
require "rubocop"
4+
5+
module RuboCop
6+
module Cop
7+
module Sorbet
8+
# Disallows using `T.must` anywhere.
9+
#
10+
# @example
11+
#
12+
# # bad
13+
# T.must(foo)
14+
#
15+
# # good
16+
# foo #: as !nil
17+
class ForbidTMust < RuboCop::Cop::Base
18+
MSG = "Do not use `T.must`."
19+
RESTRICT_ON_SEND = [:must].freeze
20+
21+
# @!method t_must?(node)
22+
def_node_matcher(:t_must?, "(send (const nil? :T) :must _)")
23+
24+
def on_send(node)
25+
add_offense(node) if t_must?(node)
26+
end
27+
alias_method :on_csend, :on_send
28+
end
29+
end
30+
end
31+
end
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
# frozen_string_literal: true
2+
3+
require "rubocop"
4+
5+
module RuboCop
6+
module Cop
7+
module Sorbet
8+
# Disallows using `T.type_alias` anywhere.
9+
#
10+
# @example
11+
#
12+
# # bad
13+
# STRING_OR_INTEGER = T.type_alias { T.any(Integer, String) }
14+
#
15+
# # good
16+
# #: type string_or_integer = Integer | String
17+
class ForbidTTypeAlias < RuboCop::Cop::Base
18+
MSG = "Do not use `T.type_alias`."
19+
20+
# @!method t_type_alias?(node)
21+
def_node_matcher(:t_type_alias?, "(block (call (const nil? :T) :type_alias) _ _)")
22+
23+
def on_block(node)
24+
add_offense(node) if t_type_alias?(node)
25+
end
26+
alias_method :on_numblock, :on_block
27+
end
28+
end
29+
end
30+
end

lib/rubocop/cop/sorbet_cops.rb

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,14 @@
1414
require_relative "sorbet/forbid_untyped_struct_props"
1515
require_relative "sorbet/implicit_conversion_method"
1616
require_relative "sorbet/callback_conditionals_binding"
17+
require_relative "sorbet/forbid_t_absurd"
18+
require_relative "sorbet/forbid_t_bind"
19+
require_relative "sorbet/forbid_t_cast"
1720
require_relative "sorbet/forbid_t_enum"
21+
require_relative "sorbet/forbid_t_let"
22+
require_relative "sorbet/forbid_t_must"
1823
require_relative "sorbet/forbid_t_struct"
24+
require_relative "sorbet/forbid_t_type_alias"
1925
require_relative "sorbet/forbid_t_unsafe"
2026
require_relative "sorbet/forbid_t_untyped"
2127
require_relative "sorbet/redundant_extend_t_sig"

manual/cops.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,14 @@ In the following section you find all available cops:
2727
* [Sorbet/ForbidSigWithRuntime](cops_sorbet.md#sorbetforbidsigwithruntime)
2828
* [Sorbet/ForbidSigWithoutRuntime](cops_sorbet.md#sorbetforbidsigwithoutruntime)
2929
* [Sorbet/ForbidSuperclassConstLiteral](cops_sorbet.md#sorbetforbidsuperclassconstliteral)
30+
* [Sorbet/ForbidTAbsurd](cops_sorbet.md#sorbetforbidtabsurd)
31+
* [Sorbet/ForbidTBind](cops_sorbet.md#sorbetforbidtbind)
32+
* [Sorbet/ForbidTCast](cops_sorbet.md#sorbetforbidtcast)
3033
* [Sorbet/ForbidTEnum](cops_sorbet.md#sorbetforbidtenum)
34+
* [Sorbet/ForbidTLet](cops_sorbet.md#sorbetforbidtlet)
35+
* [Sorbet/ForbidTMust](cops_sorbet.md#sorbetforbidtmust)
3136
* [Sorbet/ForbidTStruct](cops_sorbet.md#sorbetforbidtstruct)
37+
* [Sorbet/ForbidTTypeAlias](cops_sorbet.md#sorbetforbidttypealias)
3238
* [Sorbet/ForbidTUnsafe](cops_sorbet.md#sorbetforbidtunsafe)
3339
* [Sorbet/ForbidTUntyped](cops_sorbet.md#sorbetforbidtuntyped)
3440
* [Sorbet/ForbidTypeAliasedShapes](cops_sorbet.md#sorbetforbidtypealiasedshapes)

manual/cops_sorbet.md

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -632,6 +632,60 @@ Name | Default value | Configurable values
632632
--- | --- | ---
633633
Exclude | `db/migrate/*.rb` | Array
634634

635+
## Sorbet/ForbidTAbsurd
636+
637+
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
638+
--- | --- | --- | --- | ---
639+
Disabled | Yes | No | <<next>> | -
640+
641+
Disallows using `T.absurd` anywhere.
642+
643+
### Examples
644+
645+
```ruby
646+
# bad
647+
T.absurd(foo)
648+
649+
# good
650+
x #: absurd
651+
```
652+
653+
## Sorbet/ForbidTBind
654+
655+
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
656+
--- | --- | --- | --- | ---
657+
Disabled | Yes | No | <<next>> | -
658+
659+
Disallows using `T.bind` anywhere.
660+
661+
### Examples
662+
663+
```ruby
664+
# bad
665+
T.bind(self, Integer)
666+
667+
# good
668+
#: self as Integer
669+
```
670+
671+
## Sorbet/ForbidTCast
672+
673+
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
674+
--- | --- | --- | --- | ---
675+
Disabled | Yes | No | <<next>> | -
676+
677+
Disallows using `T.cast` anywhere.
678+
679+
### Examples
680+
681+
```ruby
682+
# bad
683+
T.cast(foo, Integer)
684+
685+
# good
686+
foo #: as Integer
687+
```
688+
635689
## Sorbet/ForbidTEnum
636690

637691
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
@@ -659,6 +713,42 @@ class MyEnum
659713
end
660714
```
661715

716+
## Sorbet/ForbidTLet
717+
718+
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
719+
--- | --- | --- | --- | ---
720+
Disabled | Yes | No | <<next>> | -
721+
722+
Disallows using `T.let` anywhere.
723+
724+
### Examples
725+
726+
```ruby
727+
# bad
728+
T.let(foo, Integer)
729+
730+
# good
731+
foo #: Integer
732+
```
733+
734+
## Sorbet/ForbidTMust
735+
736+
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
737+
--- | --- | --- | --- | ---
738+
Disabled | Yes | No | <<next>> | -
739+
740+
Disallows using `T.must` anywhere.
741+
742+
### Examples
743+
744+
```ruby
745+
# bad
746+
T.must(foo)
747+
748+
# good
749+
foo #: as !nil
750+
```
751+
662752
## Sorbet/ForbidTStruct
663753

664754
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
@@ -698,6 +788,24 @@ class MyStruct
698788
end
699789
```
700790

791+
## Sorbet/ForbidTTypeAlias
792+
793+
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
794+
--- | --- | --- | --- | ---
795+
Disabled | Yes | No | <<next>> | -
796+
797+
Disallows using `T.type_alias` anywhere.
798+
799+
### Examples
800+
801+
```ruby
802+
# bad
803+
STRING_OR_INTEGER = T.type_alias { T.any(Integer, String) }
804+
805+
# good
806+
#: type string_or_integer = Integer | String
807+
```
808+
701809
## Sorbet/ForbidTUnsafe
702810

703811
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged

0 commit comments

Comments
 (0)