Skip to content

Commit

Permalink
Add TypeAliasName to ensure all constants used as T.type_alias are in…
Browse files Browse the repository at this point in the history
… CamelCase

Signed-off-by: Alexandre Terrasa <[email protected]>
  • Loading branch information
Morriar committed Feb 9, 2022
1 parent 6118641 commit 2eed76f
Show file tree
Hide file tree
Showing 7 changed files with 129 additions and 0 deletions.
11 changes: 11 additions & 0 deletions config/default.yml
Original file line number Diff line number Diff line change
Expand Up @@ -197,6 +197,17 @@ Sorbet/TrueSigil:
- db/**/*.rb
- script/**/*

Sorbet/TypeAliasName:
Description: 'Type alias constant names must be in CamelCase.'
Enabled: true
VersionAdded: 0.6.6
Include:
- "**/*.{rb,rbi,rake,ru}"
Exclude:
- bin/**/*
- db/**/*.rb
- script/**/*

Sorbet/ValidSigil:
Description: 'All files must have a valid sigil.'
Enabled: true
Expand Down
3 changes: 3 additions & 0 deletions config/rbi.yml
Original file line number Diff line number Diff line change
Expand Up @@ -220,6 +220,9 @@ Sorbet/SignatureBuildOrder:
Sorbet/SingleLineRbiClassModuleDefinitions:
Enabled: true

Sorbet/TypeAliasName:
Enabled: true

Sorbet/ValidSigil:
Enabled: true
RequireSigilOnAllFiles: true
Expand Down
45 changes: 45 additions & 0 deletions lib/rubocop/cop/sorbet/type_alias_name.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
# frozen_string_literal: true

require "rubocop"

module RuboCop
module Cop
module Sorbet
# This cop ensures all constants used as `T.type_alias` are using CamelCase.
#
# @example
#
# # bad
# FOO_OR_BAR = T.type_alias { T.any(Foo, Bar) }
#
# # good
# FooOrBar = T.type_alias { T.any(Foo, Bar) }
class TypeAliasName < RuboCop::Cop::Cop
MSG = "Type alias constant name should be in CamelCase"

def_node_matcher(:casgn_type_alias?, <<-PATTERN)
(casgn
_
_
(block
(send
(const nil? :T) :type_alias)
_
_
))
PATTERN

def on_casgn(node)
return unless casgn_type_alias?(node)

name = node.children[1]

# From https://github.com/rubocop/rubocop/blob/master/lib/rubocop/cop/naming/class_and_module_camel_case.rb
return unless /_/.match?(name)

add_offense(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
Expand Up @@ -7,6 +7,7 @@
require_relative "sorbet/one_ancestor_per_line"
require_relative "sorbet/callback_conditionals_binding"
require_relative "sorbet/forbid_t_unsafe"
require_relative "sorbet/type_alias_name"

require_relative "sorbet/rbi/forbid_extend_t_sig_helpers_in_shims"
require_relative "sorbet/rbi/forbid_rbi_outside_of_allowed_paths"
Expand Down
1 change: 1 addition & 0 deletions manual/cops.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ In the following section you find all available cops:
* [Sorbet/StrictSigil](cops_sorbet.md#sorbetstrictsigil)
* [Sorbet/StrongSigil](cops_sorbet.md#sorbetstrongsigil)
* [Sorbet/TrueSigil](cops_sorbet.md#sorbettruesigil)
* [Sorbet/TypeAliasName](cops_sorbet.md#sorbettypealiasname)
* [Sorbet/ValidSigil](cops_sorbet.md#sorbetvalidsigil)

<!-- END_COP_LIST -->
25 changes: 25 additions & 0 deletions manual/cops_sorbet.md
Original file line number Diff line number Diff line change
Expand Up @@ -545,6 +545,31 @@ SuggestedStrictness | `true` | String
Include | `**/*.{rb,rbi,rake,ru}` | Array
Exclude | `bin/**/*`, `db/**/*.rb`, `script/**/*` | Array
## Sorbet/TypeAliasName
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
--- | --- | --- | --- | ---
Enabled | Yes | No | 0.6.6 | -
This cop ensures all constants used as `T.type_alias` are using CamelCase.
### Examples
```ruby
# bad
FOO_OR_BAR = T.type_alias { T.any(Foo, Bar) }

# good
FooOrBar = T.type_alias { T.any(Foo, Bar) }
```
### Configurable attributes
Name | Default value | Configurable values
--- | --- | ---
Include | `**/*.{rb,rbi,rake,ru}` | Array
Exclude | `bin/**/*`, `db/**/*.rb`, `script/**/*` | Array
## Sorbet/ValidSigil
Enabled by default | Safe | Supports autocorrection | VersionAdded | VersionChanged
Expand Down
43 changes: 43 additions & 0 deletions spec/rubocop/cop/sorbet/type_alias_name_spec.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# frozen_string_literal: true

require "spec_helper"

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

MSG = "Type alias constant name should be in CamelCase"

describe("offenses") do
it("disallows naming a T.type_alias constant in snake_case") do
expect_offense(<<~RB)
A_B = T.type_alias { T.any(A, B) }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{MSG}
A_ = T.type_alias { T.any(A, B) }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{MSG}
A_0 = T.type_alias { T.any(A, B) }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{MSG}
CONSTANT_NAME = T.type_alias { T.any(A, B) }
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ #{MSG}
RB
end

it("allows naming a T.type_alias constant in CamelCase") do
expect_no_offenses(<<~RB)
X = T.type_alias { T.any(A, B) }
X0 = T.type_alias { X }
Constant = T.type_alias { Foo }
ConstantName = T.type_alias { T.any(A, B) }
HTTP = T.type_alias { Foo }
RB
end

it("martches only T.type_alias casgn") do
expect_no_offenses(<<~RB)
a_or_b = T.type_alias { T.any(A, B) }
x = T.type_alias { X }
constant = T.type_alias { Foo }
constant_name = T.type_alias { T.any(A, B) }
RB
end
end
end

0 comments on commit 2eed76f

Please sign in to comment.