lib/rubocop/cop/rbs/style/empty_argument.rb in rubocop-on-rbs-0.4.0 vs lib/rubocop/cop/rbs/style/empty_argument.rb in rubocop-on-rbs-0.5.0
- old
+ new
@@ -15,88 +15,155 @@
# def foo: () -> ^ -> void
#
# # good
# def foo: () { () -> void } -> ^() -> void
class EmptyArgument < RuboCop::RBS::CopBase
- extend AutoCorrector
+ class MethodTypeChecker
+ include RuboCop::RBS::OnTypeHelper
- MSG = 'Insert `()` when empty argument'
+ def initialize(base_type: nil, &block)
+ @base_type = base_type
+ @base = base_type.location.start_pos
+ @tokens = tokenize(base_type.location.source)
+ @block = block
+ end
- def on_rbs_def(decl)
- decl.overloads.each do |overload|
- if !overload.method_type.location.source.start_with?('(')
- range = range_between(overload.method_type.location.start_pos, overload.method_type.location.start_pos)
- add_offense(range) do |corrector|
- corrector.insert_before(range, '()')
- end
+ def check
+ check_method_argument
+ if @base_type.block
+ check_block_argument
end
- if overload.method_type.block
- tokens = tokenize(overload.method_type.location.source)
- block_arrow_index = tokens.find_index { |t| t.type == :pARROW } or raise
- if tokens[block_arrow_index - 1].type != :pRPAREN
- range = range_between(
- overload.method_type.location.start_pos + tokens[block_arrow_index].location.start_pos,
- overload.method_type.location.start_pos + tokens[block_arrow_index].location.start_pos
- )
- add_offense(range) do |corrector|
- corrector.insert_before(range, '()')
- end
- end
+ @base_type.each_type do |type|
+ check_type(type)
end
+ end
- overload.method_type.each_type do |type|
- check_type(type)
+ # [T] () -> void
+ def check_method_argument
+ if @base_type.type_params.empty?
+ will_lparen_token = @tokens[0]
+ else
+ rbracket_index = @tokens.index do |token|
+ token.location.start_pos + @base >= @base_type.type_params.last.location.end_pos
+ end or raise
+ raise unless @tokens[rbracket_index].type == :pRBRACKET
+
+ will_lparen_token = @tokens[rbracket_index + 1]
end
+
+ if will_lparen_token.type != :pLPAREN
+ @block.call(
+ @base + will_lparen_token.location.start_pos,
+ @base + will_lparen_token.location.start_pos + 1
+ )
+ end
end
- end
- def on_rbs_constant(const)
- check_type(const.type)
- end
- alias on_rbs_global on_rbs_constant
- alias on_rbs_type_alias on_rbs_constant
- alias on_rbs_attribute on_rbs_constant
+ # { () [self: instance] -> void } -> void
+ def check_block_argument
+ return unless @base_type.block
+ return unless @base_type.block.type.each_param.first.nil?
- def check_type(type)
- case type
- when ::RBS::Types::Proc
- check_proc(type)
- else
- type.each_type do |t|
- check_type(t)
+ if @base_type.block.self_type
+ self_type_index = bsearch_token_index(@base_type.block.self_type.location.start_pos)
+ # ) [self:
+ # ^ ^^ ^ => pRPAREN, pLBRACKET, kSELF, pCOLON
+ rparen = @tokens[self_type_index - 4]
+ after_rparen = @tokens[self_type_index - 3]
+ else
+ block_arrow_index = @tokens.find_index { |t| t.type == :pARROW } or raise
+ rparen = @tokens[block_arrow_index - 1]
+ after_rparen = @tokens[block_arrow_index]
end
+
+ if rparen.type != :pRPAREN
+ @block.call(
+ @base + after_rparen.location.start_pos,
+ @base + after_rparen.location.start_pos + 1
+ )
+ end
end
- end
- def check_proc(type)
- tokens = tokenize(type.location.source)
- if tokens[1].type != :pLPAREN
- range = range_between(
- type.location.start_pos + tokens[0].location.end_pos,
- type.location.start_pos + tokens[0].location.end_pos
- )
- add_offense(range) do |corrector|
- corrector.insert_after(range, '()')
+ def check_type(type = @base_type)
+ on_type([::RBS::Types::Proc], type) do |proc_type|
+ check_proc(proc_type)
end
end
- if type.block
- block_arrow_index = tokens.find_index { |t| t.type == :pARROW } or raise
- if tokens[block_arrow_index - 1].type != :pRPAREN
- range = range_between(
- type.location.start_pos + tokens[block_arrow_index].location.start_pos,
- type.location.start_pos + tokens[block_arrow_index].location.start_pos
+ def check_proc(type)
+ proc_start_index = bsearch_token_index(type.location.start_pos)
+ proc_end_index = bsearch_token_index(type.location.end_pos)
+ if @tokens[proc_start_index + 1].type != :pLPAREN
+ @block.call(
+ @base + @tokens[proc_start_index + 1].location.start_pos,
+ @base + @tokens[proc_start_index + 1].location.start_pos + 1
)
- add_offense(range) do |corrector|
- corrector.insert_before(range, '()')
+ end
+
+ if type.block
+ if type.block&.self_type
+ self_type_index = bsearch_token_index(type.block.self_type.location.start_pos)
+ # ) [self:
+ # ^ ^^ ^ => pRPAREN, pLBRACKET, kSELF, pCOLON
+ rparen = @tokens[self_type_index - 4]
+ after_rparen = @tokens[self_type_index - 3]
+ else
+ block_arrow_index = @tokens[proc_start_index...proc_end_index].find_index { |t|
+ t.type == :pARROW
+ } or raise
+ block_arrow_index += proc_start_index
+ rparen = @tokens[block_arrow_index - 1]
+ after_rparen = @tokens[block_arrow_index]
end
+
+ if rparen.type != :pRPAREN
+ @block.call(
+ @base + after_rparen.location.start_pos,
+ @base + after_rparen.location.start_pos + 1
+ )
+ end
end
end
+
+ private
+
+ def bsearch_token_index(pos)
+ @tokens.bsearch_index do |token|
+ token.location.start_pos + @base >= pos
+ end or raise
+ end
+
+ def tokenize(source)
+ ::RBS::Parser.lex(source).value.reject { |t| t.type == :tTRIVIA }
+ end
end
- def tokenize(source)
- ::RBS::Parser.lex(source).value.reject { |t| t.type == :tTRIVIA }
+ extend AutoCorrector
+
+ MSG = 'Insert `()` when empty argument'
+
+ def on_rbs_def(decl)
+ decl.overloads.each do |overload|
+ MethodTypeChecker.new(base_type: overload.method_type) do |s, e|
+ range = range_between(s, e)
+ add_offense(range) do |corrector|
+ corrector.insert_before(range, '() ')
+ end
+ end.check
+ end
end
+
+ def on_rbs_constant(const)
+ MethodTypeChecker.new(base_type: const.type) do |s, e|
+ range = range_between(s, e)
+ add_offense(range) do |corrector|
+ corrector.insert_before(range, '() ')
+ end
+ end.check_type
+ end
+ alias on_rbs_global on_rbs_constant
+ alias on_rbs_type_alias on_rbs_constant
+ alias on_rbs_attribute on_rbs_constant
end
end
end
end
end