diff --git a/lib/tapioca/gem/listeners/yard_doc.rb b/lib/tapioca/gem/listeners/yard_doc.rb index 75b095421..fcb487929 100644 --- a/lib/tapioca/gem/listeners/yard_doc.rb +++ b/lib/tapioca/gem/listeners/yard_doc.rb @@ -69,7 +69,7 @@ def documentation_comments(name, sigs: []) .reject { |line| IGNORED_COMMENTS.any? { |comment| line.include?(comment) } } .map! do |line| if line.strip.start_with?(RBS_SIGNATURE_PREFIX) - rbs_sigs << RBI::RBSSig.new(line[1..].strip) + rbs_sigs << create_rbs_sig(line) else comments << RBI::Comment.new(line) end @@ -107,6 +107,25 @@ def documentation_comments(name, sigs: []) [comments, rbs_sigs] end + #: (String line) -> RBI::RBSSig + def create_rbs_sig(line) + sig = T.must(line[1..]).strip + + # attr_* methods don't have to specify "->" in their signatures but since we convert it + # to a regular method definitions we need to have "->" to represent the return type. + # Also we need becareful of proc types since they contain a "->" already. + if !sig.include?("->") + sig = "-> #{sig}" + elsif sig.include?("^") # Proc type + # Check if there's a "->" that's not inside a proc type + # A proc type will have the form (^(Arg1, Arg2) -> ReturnType) + outer_arrow_present = !/\([^()]*->[^()]*\)/.match?(sig) + sig = "-> #{sig}" unless outer_arrow_present + end + + RBI::RBSSig.new(sig) + end + # @override #: (NodeAdded event) -> bool def ignore?(event) diff --git a/spec/tapioca/gem/pipeline_spec.rb b/spec/tapioca/gem/pipeline_spec.rb index 30c2d7b7a..622b4ebbb 100644 --- a/spec/tapioca/gem/pipeline_spec.rb +++ b/spec/tapioca/gem/pipeline_spec.rb @@ -4550,16 +4550,44 @@ def foo; end #: -> Integer def self.bar; end + + #: Integer + attr_reader :baz + + #: (^(Integer) -> String) -> void + attr_reader :qux + + #: (^(Integer) -> String proc) -> void + def quux(proc); end + + #: ((^(Integer) -> String proc) -> void) -> void + def corge(nested_proc); end end RUBY output = template(<<~RBI) # source://#{DEFAULT_GEM_NAME}//lib/foo.rb#1 class Foo + # source://#{DEFAULT_GEM_NAME}//lib/foo.rb#9 + #: -> Integer + def baz; end + + # source://#{DEFAULT_GEM_NAME}//lib/foo.rb#18 + #: ((^(Integer) -> String proc) -> void) -> void + def corge(nested_proc); end + # source://#{DEFAULT_GEM_NAME}//lib/foo.rb#3 #: -> String def foo; end + # source://#{DEFAULT_GEM_NAME}//lib/foo.rb#15 + #: (^(Integer) -> String proc) -> void + def quux(proc); end + + # source://#{DEFAULT_GEM_NAME}//lib/foo.rb#12 + #: (^(Integer) -> String) -> void + def qux; end + class << self # source://#{DEFAULT_GEM_NAME}//lib/foo.rb#6 #: -> Integer