rubocop-sorbet 0.7.0 → 0.7.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/ci.yml +1 -1
  3. data/.rubocop.yml +12 -1
  4. data/.yardopts +1 -0
  5. data/Gemfile +1 -0
  6. data/Gemfile.lock +23 -17
  7. data/README.md +1 -1
  8. data/Rakefile +1 -1
  9. data/bin/rspec +4 -2
  10. data/bin/rubocop +4 -2
  11. data/config/default.yml +23 -2
  12. data/lib/rubocop/cop/sorbet/binding_constant_without_type_alias.rb +105 -0
  13. data/lib/rubocop/cop/sorbet/callback_conditionals_binding.rb +39 -11
  14. data/lib/rubocop/cop/sorbet/constants_from_strings.rb +5 -3
  15. data/lib/rubocop/cop/sorbet/forbid_include_const_literal.rb +27 -23
  16. data/lib/rubocop/cop/sorbet/forbid_superclass_const_literal.rb +26 -27
  17. data/lib/rubocop/cop/sorbet/forbid_t_unsafe.rb +7 -3
  18. data/lib/rubocop/cop/sorbet/forbid_t_untyped.rb +7 -3
  19. data/lib/rubocop/cop/sorbet/forbid_untyped_struct_props.rb +13 -11
  20. data/lib/rubocop/cop/sorbet/implicit_conversion_method.rb +56 -0
  21. data/lib/rubocop/cop/sorbet/mixin/target_sorbet_version.rb +49 -0
  22. data/lib/rubocop/cop/sorbet/mutable_constant_sorbet_aware_behaviour.rb +8 -5
  23. data/lib/rubocop/cop/sorbet/obsolete_strict_memoization.rb +92 -0
  24. data/lib/rubocop/cop/sorbet/one_ancestor_per_line.rb +8 -3
  25. data/lib/rubocop/cop/sorbet/rbi/forbid_extend_t_sig_helpers_in_shims.rb +12 -18
  26. data/lib/rubocop/cop/sorbet/rbi/forbid_rbi_outside_of_allowed_paths.rb +8 -7
  27. data/lib/rubocop/cop/sorbet/rbi/single_line_rbi_class_module_definitions.rb +12 -18
  28. data/lib/rubocop/cop/sorbet/redundant_extend_t_sig.rb +5 -6
  29. data/lib/rubocop/cop/sorbet/sigils/enforce_sigil_order.rb +3 -2
  30. data/lib/rubocop/cop/sorbet/sigils/enforce_single_sigil.rb +6 -5
  31. data/lib/rubocop/cop/sorbet/sigils/false_sigil.rb +1 -1
  32. data/lib/rubocop/cop/sorbet/sigils/has_sigil.rb +1 -1
  33. data/lib/rubocop/cop/sorbet/sigils/ignore_sigil.rb +1 -1
  34. data/lib/rubocop/cop/sorbet/sigils/strict_sigil.rb +1 -1
  35. data/lib/rubocop/cop/sorbet/sigils/strong_sigil.rb +1 -1
  36. data/lib/rubocop/cop/sorbet/sigils/true_sigil.rb +1 -1
  37. data/lib/rubocop/cop/sorbet/sigils/valid_sigil.rb +50 -25
  38. data/lib/rubocop/cop/sorbet/signatures/allow_incompatible_override.rb +19 -30
  39. data/lib/rubocop/cop/sorbet/signatures/checked_true_in_signature.rb +3 -2
  40. data/lib/rubocop/cop/sorbet/signatures/empty_line_after_sig.rb +3 -3
  41. data/lib/rubocop/cop/sorbet/signatures/enforce_signatures.rb +8 -4
  42. data/lib/rubocop/cop/sorbet/signatures/keyword_argument_ordering.rb +5 -4
  43. data/lib/rubocop/cop/sorbet/signatures/signature_build_order.rb +8 -3
  44. data/lib/rubocop/cop/sorbet/signatures/signature_cop.rb +6 -1
  45. data/lib/rubocop/cop/sorbet/type_alias_name.rb +10 -17
  46. data/lib/rubocop/cop/sorbet_cops.rb +6 -1
  47. data/lib/rubocop/sorbet/inject.rb +9 -7
  48. data/lib/rubocop/sorbet/version.rb +2 -1
  49. data/lib/rubocop/sorbet.rb +1 -0
  50. data/manual/cops.md +2 -0
  51. data/manual/cops_sorbet.md +137 -31
  52. data/rubocop-sorbet.gemspec +1 -0
  53. data/tasks/cops_documentation.rake +16 -5
  54. metadata +8 -4
  55. data/lib/rubocop/cop/sorbet/binding_constants_without_type_alias.rb +0 -127
@@ -5,7 +5,7 @@ require "rubocop"
5
5
  module RuboCop
6
6
  module Cop
7
7
  module Sorbet
8
- # This cop checks that every Ruby file contains a valid Sorbet sigil.
8
+ # Checks that every Ruby file contains a valid Sorbet sigil.
9
9
  # Adapted from: https://gist.github.com/clarkdave/85aca4e16f33fd52aceb6a0a29936e52
10
10
  #
11
11
  # Options:
@@ -13,9 +13,11 @@ module RuboCop
13
13
  # * `RequireSigilOnAllFiles`: make offense if the Sorbet typed is not found in the file (default: false)
14
14
  # * `SuggestedStrictness`: Sorbet strictness level suggested in offense messages (default: 'false')
15
15
  # * `MinimumStrictness`: If set, make offense if the strictness level in the file is below this one
16
+ # * `ExactStrictness`: If set, make offense if the strictness level in the file is different than this one
16
17
  #
17
- # If a `MinimumStrictness` level is specified, it will be used in offense messages and autocorrect.
18
- class ValidSigil < RuboCop::Cop::Cop
18
+ # If an `ExactStrictness` level is specified, it will be used in offense messages and autocorrect.
19
+ # Otherwise, if a `MinimumStrictness` level is specified, it will be used in offense messages and autocorrect.
20
+ class ValidSigil < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
19
21
  @registry = Cop.registry # So we can properly subclass this cop
20
22
 
21
23
  def investigate(processed_source)
@@ -36,7 +38,7 @@ module RuboCop
36
38
  return unless extract_sigil(processed_source).nil?
37
39
 
38
40
  token = processed_source.tokens.first
39
- replace_with = suggested_strictness_level(minimum_strictness, suggested_strictness)
41
+ replace_with = suggested_strictness_level
40
42
  sigil = "# typed: #{replace_with}"
41
43
  if token.text.start_with?("#!") # shebang line
42
44
  corrector.insert_after(token.pos, "\n#{sigil}")
@@ -70,34 +72,37 @@ module RuboCop
70
72
 
71
73
  token = processed_source.tokens.first
72
74
  if require_sigil_on_all_files?
73
- strictness = suggested_strictness_level(minimum_strictness, suggested_strictness)
75
+ strictness = suggested_strictness_level
74
76
  add_offense(
75
77
  token,
76
78
  location: token.pos,
77
79
  message: "No Sorbet sigil found in file. " \
78
- "Try a `typed: #{strictness}` to start (you can also use `rubocop -a` to automatically add this)."
80
+ "Try a `typed: #{strictness}` to start (you can also use `rubocop -a` to automatically add this).",
79
81
  )
80
82
  end
81
83
  false
82
84
  end
83
85
 
84
- def suggested_strictness_level(minimum_strictness, suggested_strictness)
86
+ def suggested_strictness_level
87
+ return exact_strictness if exact_strictness
85
88
  # if no minimum strictness is set (eg. using Sorbet/HasSigil without config) then
86
89
  # we always use the suggested strictness which defaults to `false`
87
90
  return suggested_strictness unless minimum_strictness
88
91
 
89
92
  # special case: if you're using Sorbet/IgnoreSigil without config, we should recommend `ignore`
90
- return "ignore" if minimum_strictness == "ignore" && cop_config["SuggestedStrictness"].nil?
93
+ return "ignore" if minimum_strictness == "ignore" && cop_config["SuggestedStrictness"].nil? # rubocop:todo InternalAffairs/UndefinedConfig
91
94
 
92
95
  # if a minimum strictness is set (eg. you're using Sorbet/FalseSigil)
93
96
  # we want to compare the minimum strictness and suggested strictness. this is because
94
97
  # the suggested strictness might be higher than the minimum (eg. if you want all new files
95
98
  # at a higher strictness level, without having to migrate existing files at lower levels).
96
99
 
97
- suggested_level = STRICTNESS_LEVELS.index(suggested_strictness)
98
- minimum_level = STRICTNESS_LEVELS.index(minimum_strictness)
100
+ levels = [
101
+ STRICTNESS_LEVELS.index(suggested_strictness),
102
+ STRICTNESS_LEVELS.index(minimum_strictness),
103
+ ]
99
104
 
100
- suggested_level > minimum_level ? suggested_strictness : minimum_strictness
105
+ STRICTNESS_LEVELS[levels.compact.max]
101
106
  end
102
107
 
103
108
  def check_strictness_not_empty(sigil, strictness)
@@ -106,7 +111,7 @@ module RuboCop
106
111
  add_offense(
107
112
  sigil,
108
113
  location: sigil.pos,
109
- message: "Sorbet sigil should not be empty."
114
+ message: "Sorbet sigil should not be empty.",
110
115
  )
111
116
  false
112
117
  end
@@ -117,24 +122,38 @@ module RuboCop
117
122
  add_offense(
118
123
  sigil,
119
124
  location: sigil.pos,
120
- message: "Invalid Sorbet sigil `#{strictness}`."
125
+ message: "Invalid Sorbet sigil `#{strictness}`.",
121
126
  )
122
127
  false
123
128
  end
124
129
 
125
130
  def check_strictness_level(sigil, strictness)
126
- return true unless minimum_strictness
131
+ return true if !minimum_strictness && !exact_strictness
127
132
 
128
- minimum_level = STRICTNESS_LEVELS.index(minimum_strictness)
129
133
  current_level = STRICTNESS_LEVELS.index(strictness)
130
- if current_level < minimum_level
131
- add_offense(
132
- sigil,
133
- location: sigil.pos,
134
- message: "Sorbet sigil should be at least `#{minimum_strictness}` got `#{strictness}`."
135
- )
136
- return false
134
+
135
+ if exact_strictness
136
+ exact_level = STRICTNESS_LEVELS.index(exact_strictness)
137
+ if current_level != exact_level
138
+ add_offense(
139
+ sigil,
140
+ location: sigil.pos,
141
+ message: "Sorbet sigil should be `#{exact_strictness}` got `#{strictness}`.",
142
+ )
143
+ return false
144
+ end
145
+ else
146
+ minimum_level = STRICTNESS_LEVELS.index(minimum_strictness)
147
+ if current_level < minimum_level
148
+ add_offense(
149
+ sigil,
150
+ location: sigil.pos,
151
+ message: "Sorbet sigil should be at least `#{minimum_strictness}` got `#{strictness}`.",
152
+ )
153
+ return false
154
+ end
137
155
  end
156
+
138
157
  true
139
158
  end
140
159
 
@@ -142,18 +161,24 @@ module RuboCop
142
161
 
143
162
  # Default is `false`
144
163
  def require_sigil_on_all_files?
145
- !!cop_config["RequireSigilOnAllFiles"]
164
+ !!cop_config["RequireSigilOnAllFiles"] # rubocop:todo InternalAffairs/UndefinedConfig
146
165
  end
147
166
 
148
167
  # Default is `'false'`
149
168
  def suggested_strictness
150
- config = cop_config["SuggestedStrictness"].to_s
169
+ config = cop_config["SuggestedStrictness"].to_s # rubocop:todo InternalAffairs/UndefinedConfig
151
170
  STRICTNESS_LEVELS.include?(config) ? config : "false"
152
171
  end
153
172
 
154
173
  # Default is `nil`
155
174
  def minimum_strictness
156
- config = cop_config["MinimumStrictness"].to_s
175
+ config = cop_config["MinimumStrictness"].to_s # rubocop:todo InternalAffairs/UndefinedConfig
176
+ config if STRICTNESS_LEVELS.include?(config)
177
+ end
178
+
179
+ # Default is `nil`
180
+ def exact_strictness
181
+ config = cop_config["ExactStrictness"].to_s # rubocop:todo InternalAffairs/UndefinedConfig
157
182
  config if STRICTNESS_LEVELS.include?(config)
158
183
  end
159
184
  end
@@ -5,10 +5,10 @@ require "rubocop"
5
5
  module RuboCop
6
6
  module Cop
7
7
  module Sorbet
8
- # This cop disallows using `.override(allow_incompatible: true)`.
8
+ # Disallows using `.override(allow_incompatible: true)`.
9
9
  # Using `allow_incompatible` suggests a violation of the Liskov
10
10
  # Substitution Principle, meaning that a subclass is not a valid
11
- # subtype of it's superclass. This Cop prevents these design smells
11
+ # subtype of its superclass. This Cop prevents these design smells
12
12
  # from occurring.
13
13
  #
14
14
  # @example
@@ -18,40 +18,29 @@ module RuboCop
18
18
  #
19
19
  # # good
20
20
  # sig.override
21
- class AllowIncompatibleOverride < RuboCop::Cop::Cop
22
- def_node_search(:sig?, <<-PATTERN)
23
- (
24
- send
25
- nil?
26
- :sig
27
- ...
28
- )
29
- PATTERN
21
+ class AllowIncompatibleOverride < RuboCop::Cop::Base
22
+ MSG = "Usage of `allow_incompatible` suggests a violation of the Liskov Substitution Principle. " \
23
+ "Instead, strive to write interfaces which respect subtyping principles and remove `allow_incompatible`"
24
+ RESTRICT_ON_SEND = [:override].freeze
30
25
 
31
- def not_nil?(node)
32
- !node.nil?
33
- end
34
-
35
- def_node_search(:allow_incompatible?, <<-PATTERN)
36
- (pair (sym :allow_incompatible) (true))
37
- PATTERN
38
-
39
- def_node_matcher(:allow_incompatible_override?, <<-PATTERN)
40
- (
41
- send
42
- [#not_nil? #sig?]
26
+ # @!method allow_incompatible_override?(node)
27
+ def_node_matcher(:allow_incompatible_override?, <<~PATTERN)
28
+ (send
29
+ #sig?
43
30
  :override
44
- [#not_nil? #allow_incompatible?]
31
+ (hash <$(pair (sym :allow_incompatible) true) ...>)
45
32
  )
46
33
  PATTERN
47
34
 
35
+ # @!method sig?(node)
36
+ def_node_search :sig?, <<~PATTERN
37
+ (send _ :sig ...)
38
+ PATTERN
39
+
48
40
  def on_send(node)
49
- return unless allow_incompatible_override?(node)
50
- add_offense(
51
- node.children[2],
52
- message: "Usage of `allow_incompatible` suggests a violation of the Liskov Substitution Principle. "\
53
- "Instead, strive to write interfaces which respect subtyping principles and remove `allow_incompatible`",
54
- )
41
+ allow_incompatible_override?(node) do |allow_incompatible_pair|
42
+ add_offense(allow_incompatible_pair)
43
+ end
55
44
  end
56
45
  end
57
46
  end
@@ -6,7 +6,7 @@ require_relative "signature_cop"
6
6
  module RuboCop
7
7
  module Cop
8
8
  module Sorbet
9
- # This cop disallows the usage of `checked(true)`. This usage could cause
9
+ # Disallows the usage of `checked(true)`. This usage could cause
10
10
  # confusion; it could lead some people to believe that a method would be checked
11
11
  # even if runtime checks have not been enabled on the class or globally.
12
12
  # Additionally, in the event where checks are enabled, `checked(true)` would
@@ -22,6 +22,7 @@ module RuboCop
22
22
  class CheckedTrueInSignature < SignatureCop
23
23
  include(RuboCop::Cop::RangeHelp)
24
24
 
25
+ # @!method offending_node(node)
25
26
  def_node_search(:offending_node, <<~PATTERN)
26
27
  (send _ :checked (true))
27
28
  PATTERN
@@ -44,7 +45,7 @@ module RuboCop
44
45
  error.location.line,
45
46
  (error.location.selector.begin_pos)..(error.location.end.begin_pos),
46
47
  ),
47
- message: MESSAGE
48
+ message: MESSAGE,
48
49
  )
49
50
  end
50
51
  end
@@ -5,7 +5,7 @@ require_relative "signature_cop"
5
5
  module RuboCop
6
6
  module Cop
7
7
  module Sorbet
8
- # This cop checks for blank lines after signatures.
8
+ # Checks for blank lines after signatures.
9
9
  #
10
10
  # It also suggests an autocorrect
11
11
  #
@@ -31,10 +31,10 @@ module RuboCop
31
31
  end
32
32
 
33
33
  def autocorrect(node)
34
- -> (corrector) do
34
+ ->(corrector) do
35
35
  offending_range = node.source_range.with(
36
36
  begin_pos: node.source_range.end_pos + 1,
37
- end_pos: processed_source.buffer.line_range(next_method(node).line).begin_pos
37
+ end_pos: processed_source.buffer.line_range(next_method(node).line).begin_pos,
38
38
  )
39
39
  corrector.remove(offending_range)
40
40
  clean_range = offending_range.source.split("\n").reject(&:empty?).join("\n")
@@ -7,7 +7,7 @@ require_relative "signature_cop"
7
7
  module RuboCop
8
8
  module Cop
9
9
  module Sorbet
10
- # This cop checks that every method definition and attribute accessor has a Sorbet signature.
10
+ # Checks that every method definition and attribute accessor has a Sorbet signature.
11
11
  #
12
12
  # It also suggest an autocorrect with placeholders so the following code:
13
13
  #
@@ -32,6 +32,7 @@ module RuboCop
32
32
  @last_sig_for_scope = {}
33
33
  end
34
34
 
35
+ # @!method accessor?(node)
35
36
  def_node_matcher(:accessor?, <<-PATTERN)
36
37
  (send nil? {:attr_reader :attr_writer :attr_accessor} ...)
37
38
  PATTERN
@@ -67,13 +68,14 @@ module RuboCop
67
68
  suggest.returns = "void" if method == :attr_writer
68
69
  end
69
70
 
70
- corrector.insert_before(node.loc.expression, suggest.to_autocorrect)
71
+ corrector.insert_before(node, suggest.to_autocorrect)
71
72
  end
72
73
  end
73
74
 
74
75
  def scope(node)
75
- return nil unless node.parent
76
+ return unless node.parent
76
77
  return node.parent if [:begin, :block, :class, :module].include?(node.parent.type)
78
+
77
79
  scope(node.parent)
78
80
  end
79
81
 
@@ -84,7 +86,7 @@ module RuboCop
84
86
  unless @last_sig_for_scope[scope]
85
87
  add_offense(
86
88
  node,
87
- message: "Each method is required to have a signature."
89
+ message: "Each method is required to have a signature.",
88
90
  )
89
91
  end
90
92
  @last_sig_for_scope[scope] = nil
@@ -123,6 +125,7 @@ module RuboCop
123
125
 
124
126
  def generate_params
125
127
  return if @params.empty?
128
+
126
129
  out = StringIO.new
127
130
  out << "params("
128
131
  out << @params.map do |param|
@@ -135,6 +138,7 @@ module RuboCop
135
138
  def generate_return
136
139
  return "returns(#{@return_placeholder})" if @returns.nil?
137
140
  return @returns if @returns == "void"
141
+
138
142
  "returns(#{@returns})"
139
143
  end
140
144
  end
@@ -6,7 +6,7 @@ require_relative "signature_cop"
6
6
  module RuboCop
7
7
  module Cop
8
8
  module Sorbet
9
- # This cop checks for the ordering of keyword arguments required by
9
+ # Checks for the ordering of keyword arguments required by
10
10
  # sorbet-runtime. The ordering requires that all keyword arguments
11
11
  # are at the end of the parameters list, and all keyword arguments
12
12
  # with a default value must be after those without default values.
@@ -24,6 +24,7 @@ module RuboCop
24
24
  def on_signature(node)
25
25
  method_node = node.parent.children[node.sibling_index + 1]
26
26
  return if method_node.nil?
27
+
27
28
  method_parameters = method_node.arguments
28
29
 
29
30
  check_order_for_kwoptargs(method_parameters)
@@ -35,13 +36,13 @@ module RuboCop
35
36
  out_of_kwoptarg = false
36
37
 
37
38
  parameters.reverse.each do |param|
38
- out_of_kwoptarg = true unless param.type == :kwoptarg || param.type == :blockarg || param.type == :kwrestarg
39
+ out_of_kwoptarg = true unless param.kwoptarg_type? || param.blockarg_type? || param.kwrestarg_type?
39
40
 
40
- next unless param.type == :kwoptarg && out_of_kwoptarg
41
+ next unless param.kwoptarg_type? && out_of_kwoptarg
41
42
 
42
43
  add_offense(
43
44
  param,
44
- message: "Optional keyword arguments must be at the end of the parameter list."
45
+ message: "Optional keyword arguments must be at the end of the parameter list.",
45
46
  )
46
47
  end
47
48
  end
@@ -27,13 +27,18 @@ module RuboCop
27
27
  :on_failure,
28
28
  ].each_with_index.to_h.freeze
29
29
 
30
+ # @!method root_call(node)
30
31
  def_node_search(:root_call, <<~PATTERN)
31
32
  (send nil? {#{ORDER.keys.map(&:inspect).join(" ")}} ...)
32
33
  PATTERN
33
34
 
34
35
  def on_signature(node)
35
36
  calls = call_chain(node.children[2]).map(&:method_name)
36
- return unless calls.any?
37
+ return if calls.empty?
38
+
39
+ # While the developer is typing, we may have an incomplete call statement, which means `ORDER[call]` will
40
+ # return `nil`. In that case, invoking `sort_by` will raise
41
+ return if calls.any? { |call| ORDER[call].nil? }
37
42
 
38
43
  expected_order = calls.sort_by { |call| ORDER[call] }
39
44
  return if expected_order == calls
@@ -52,7 +57,7 @@ module RuboCop
52
57
  end
53
58
 
54
59
  def autocorrect(node)
55
- return nil unless can_autocorrect?
60
+ return unless can_autocorrect?
56
61
 
57
62
  lambda do |corrector|
58
63
  tree = call_chain(node_reparsed_with_modern_features(node))
@@ -62,7 +67,7 @@ module RuboCop
62
67
  end
63
68
 
64
69
  corrector.replace(
65
- node.source_range,
70
+ node,
66
71
  Unparser.unparse(tree),
67
72
  )
68
73
  end
@@ -8,9 +8,10 @@ module RuboCop
8
8
  # Abstract cop specific to Sorbet signatures
9
9
  #
10
10
  # You can subclass it to use the `on_signature` trigger and the `signature?` node matcher.
11
- class SignatureCop < RuboCop::Cop::Cop
11
+ class SignatureCop < RuboCop::Cop::Cop # rubocop:todo InternalAffairs/InheritDeprecatedCopClass
12
12
  @registry = Cop.registry # So we can properly subclass this cop
13
13
 
14
+ # @!method signature?(node)
14
15
  def_node_matcher(:signature?, <<~PATTERN)
15
16
  (block (send
16
17
  {nil? #with_runtime? #without_runtime?}
@@ -19,10 +20,12 @@ module RuboCop
19
20
  ) (args) ...)
20
21
  PATTERN
21
22
 
23
+ # @!method with_runtime?(node)
22
24
  def_node_matcher(:with_runtime?, <<~PATTERN)
23
25
  (const (const nil? :T) :Sig)
24
26
  PATTERN
25
27
 
28
+ # @!method without_runtime?(node)
26
29
  def_node_matcher(:without_runtime?, <<~PATTERN)
27
30
  (const (const (const nil? :T) :Sig) :WithoutRuntime)
28
31
  PATTERN
@@ -31,6 +34,8 @@ module RuboCop
31
34
  on_signature(node) if signature?(node)
32
35
  end
33
36
 
37
+ alias_method :on_numblock, :on_block
38
+
34
39
  def on_signature(_)
35
40
  # To be defined in subclasses
36
41
  end
@@ -5,7 +5,7 @@ require "rubocop"
5
5
  module RuboCop
6
6
  module Cop
7
7
  module Sorbet
8
- # This cop ensures all constants used as `T.type_alias` are using CamelCase.
8
+ # Ensures all constants used as `T.type_alias` are using CamelCase.
9
9
  #
10
10
  # @example
11
11
  #
@@ -14,30 +14,23 @@ module RuboCop
14
14
  #
15
15
  # # good
16
16
  # FooOrBar = T.type_alias { T.any(Foo, Bar) }
17
- class TypeAliasName < RuboCop::Cop::Cop
17
+ class TypeAliasName < RuboCop::Cop::Base
18
18
  MSG = "Type alias constant name should be in CamelCase"
19
19
 
20
- def_node_matcher(:casgn_type_alias?, <<-PATTERN)
20
+ # @!method underscored_type_alias?(node)
21
+ def_node_matcher(:underscored_type_alias?, <<-PATTERN)
21
22
  (casgn
22
23
  _
23
- _
24
+ /_/ # Name matches underscore
24
25
  (block
25
- (send
26
- (const nil? :T) :type_alias)
27
- _
28
- _
29
- ))
26
+ (send (const nil? :T) :type_alias)
27
+ ...
28
+ )
29
+ )
30
30
  PATTERN
31
31
 
32
32
  def on_casgn(node)
33
- return unless casgn_type_alias?(node)
34
-
35
- name = node.children[1]
36
-
37
- # From https://github.com/rubocop/rubocop/blob/master/lib/rubocop/cop/naming/class_and_module_camel_case.rb
38
- return unless /_/.match?(name)
39
-
40
- add_offense(node)
33
+ add_offense(node) if underscored_type_alias?(node)
41
34
  end
42
35
  end
43
36
  end
@@ -1,15 +1,20 @@
1
1
  # frozen_string_literal: true
2
- require_relative "sorbet/binding_constants_without_type_alias"
2
+
3
+ require_relative "sorbet/mixin/target_sorbet_version.rb"
4
+
5
+ require_relative "sorbet/binding_constant_without_type_alias"
3
6
  require_relative "sorbet/constants_from_strings"
4
7
  require_relative "sorbet/forbid_superclass_const_literal"
5
8
  require_relative "sorbet/forbid_include_const_literal"
6
9
  require_relative "sorbet/forbid_untyped_struct_props"
10
+ require_relative "sorbet/implicit_conversion_method"
7
11
  require_relative "sorbet/one_ancestor_per_line"
8
12
  require_relative "sorbet/callback_conditionals_binding"
9
13
  require_relative "sorbet/forbid_t_unsafe"
10
14
  require_relative "sorbet/forbid_t_untyped"
11
15
  require_relative "sorbet/redundant_extend_t_sig"
12
16
  require_relative "sorbet/type_alias_name"
17
+ require_relative "sorbet/obsolete_strict_memoization"
13
18
 
14
19
  require_relative "sorbet/rbi/forbid_extend_t_sig_helpers_in_shims"
15
20
  require_relative "sorbet/rbi/forbid_rbi_outside_of_allowed_paths"
@@ -7,13 +7,15 @@ module RuboCop
7
7
  # Because RuboCop doesn't yet support plugins, we have to monkey patch in a
8
8
  # bit of our configuration.
9
9
  module Inject
10
- def self.defaults!
11
- path = CONFIG_DEFAULT.to_s
12
- hash = ConfigLoader.send(:load_yaml_configuration, path)
13
- config = Config.new(hash, path).tap(&:make_excludes_absolute)
14
- puts "configuration from #{path}" if ConfigLoader.debug?
15
- config = ConfigLoader.merge_with_default(config, path)
16
- ConfigLoader.instance_variable_set(:@default_configuration, config)
10
+ class << self
11
+ def defaults!
12
+ path = CONFIG_DEFAULT.to_s
13
+ hash = ConfigLoader.send(:load_yaml_configuration, path)
14
+ config = Config.new(hash, path).tap(&:make_excludes_absolute)
15
+ puts "configuration from #{path}" if ConfigLoader.debug?
16
+ config = ConfigLoader.merge_with_default(config, path)
17
+ ConfigLoader.instance_variable_set(:@default_configuration, config)
18
+ end
17
19
  end
18
20
  end
19
21
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  module RuboCop
3
4
  module Sorbet
4
- VERSION = "0.7.0"
5
+ VERSION = "0.7.1"
5
6
  end
6
7
  end
@@ -1,4 +1,5 @@
1
1
  # frozen_string_literal: true
2
+
2
3
  require "rubocop/sorbet/version"
3
4
  require "yaml"
4
5
 
data/manual/cops.md CHANGED
@@ -24,7 +24,9 @@ In the following section you find all available cops:
24
24
  * [Sorbet/ForbidUntypedStructProps](cops_sorbet.md#sorbetforbiduntypedstructprops)
25
25
  * [Sorbet/HasSigil](cops_sorbet.md#sorbethassigil)
26
26
  * [Sorbet/IgnoreSigil](cops_sorbet.md#sorbetignoresigil)
27
+ * [Sorbet/ImplicitConversionMethod](cops_sorbet.md#sorbetimplicitconversionmethod)
27
28
  * [Sorbet/KeywordArgumentOrdering](cops_sorbet.md#sorbetkeywordargumentordering)
29
+ * [Sorbet/ObsoleteStrictMemoization](cops_sorbet.md#sorbetobsoletestrictmemoization)
28
30
  * [Sorbet/OneAncestorPerLine](cops_sorbet.md#sorbetoneancestorperline)
29
31
  * [Sorbet/RedundantExtendTSig](cops_sorbet.md#sorbetredundantextendtsig)
30
32
  * [Sorbet/SignatureBuildOrder](cops_sorbet.md#sorbetsignaturebuildorder)