lib/sord/rbi_generator.rb in sord-0.9.0 vs lib/sord/rbi_generator.rb in sord-0.10.0
- old
+ new
@@ -36,15 +36,16 @@
@method_count = 0
@warnings = []
@replace_errors_with_untyped = options[:replace_errors_with_untyped]
@replace_unresolved_with_untyped = options[:replace_unresolved_with_untyped]
+ @keep_original_comments = options[:keep_original_comments]
# Hook the logger so that messages are added as comments to the RBI file
Logging.add_hook do |type, msg, item|
@current_object.add_comment_to_next_child("sord #{type} - #{msg}")
- end if options[:comments]
+ end if options[:sord_comments]
# Hook the logger so that warnings are collected
Logging.add_hook do |type, msg, item|
# TODO: is it possible to get line numbers here?
warnings << [msg, item, 0] if type == :warn
@@ -86,11 +87,13 @@
# Take a constant (like "A::B::CONSTANT"), split it on each '::', and
# set the constant name to the last string in the array.
constant_name = constant.to_s.split('::').last
# Add the constant to the current object being generated.
- @current_object.create_constant(constant_name, value: "T.let(#{constant.value}, T.untyped)")
+ @current_object.create_constant(constant_name, value: "T.let(#{constant.value}, T.untyped)") do |c|
+ c.add_comments(constant.docstring.all.split("\n"))
+ end
end
end
# Given a YARD NamespaceObject, add lines defining its methods and their
# signatures to the current RBI file.
@@ -156,12 +159,17 @@
Logging.omit("no YARD type given for #{name.inspect}, using T.untyped", meth)
next 'T.untyped'
end
end
+ return_types = getter.tags('return').flat_map(&:types)
+ unless return_types.any?
+ Logging.omit("no YARD type given for #{name.inspect}, using T.untyped", meth)
+ next 'T.untyped'
+ end
inferred_type = TypeConverter.yard_to_sorbet(
- getter.tags('return').flat_map(&:types), meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
+ return_types, meth, @replace_errors_with_untyped, @replace_unresolved_with_untyped)
Logging.infer("inferred type of parameter #{name.inspect} as #{inferred_type} using getter's return type", meth)
inferred_type
else
# Is this the only argument, and was a @param specified without an
@@ -207,11 +215,93 @@
@current_object.create_method(
meth.name.to_s,
parameters: parlour_params,
returns: returns,
class_method: meth.scope == :class
- )
+ ) do |m|
+ if @keep_original_comments
+ m.add_comments(meth.docstring.all.split("\n"))
+ else
+ parser = YARD::Docstring.parser
+ parser.parse(meth.docstring.all)
+
+ docs_array = parser.text.split("\n")
+
+ # Add @param tags if there are any with names and descriptions.
+ params = parser.tags.select { |tag| tag.tag_name == 'param' && tag.is_a?(YARD::Tags::Tag) && !tag.name.nil? }
+ # Add a blank line if there's anything before the params.
+ docs_array << '' if docs_array.length.positive? && params.length.positive?
+ params.each do |param|
+ docs_array << '' if docs_array.last != '' && docs_array.length.positive?
+ # Output params in the form of:
+ # _@param_ `foo` — Lorem ipsum.
+ # _@param_ `foo`
+ if param.text.nil?
+ docs_array << "_@param_ `#{param.name}`"
+ else
+ docs_array << "_@param_ `#{param.name}` — #{param.text}"
+ end
+ end
+
+ # Add @return tags (there could possibly be more than one, despite this not being supported)
+ returns = parser.tags.select { |tag| tag.tag_name == 'return' && tag.is_a?(YARD::Tags::Tag) && !tag.text.nil? && tag.text.strip != '' }
+ # Add a blank line if there's anything before the returns.
+ docs_array << '' if docs_array.length.positive? && returns.length.positive?
+ returns.each do |retn|
+ docs_array << '' if docs_array.last != '' && docs_array.length.positive?
+ # Output returns in the form of:
+ # _@return_ — Lorem ipsum.
+ docs_array << "_@return_ — #{retn.text}"
+ end
+
+ # Iterate through the @example tags for a given YARD doc and output them in Markdown codeblocks.
+ examples = parser.tags.select { |tag| tag.tag_name == 'example' && tag.is_a?(YARD::Tags::Tag) }
+ examples.each do |example|
+ # Only add a blank line if there's anything before the example.
+ docs_array << '' if docs_array.length.positive?
+ # Include the example's 'name' if there is one.
+ docs_array << example.name unless example.name.nil? || example.name == ""
+ docs_array << "```ruby"
+ docs_array.concat(example.text.split("\n"))
+ docs_array << "```"
+ end if examples.length.positive?
+
+ # Add @note and @deprecated tags.
+ notice_tags = parser.tags.select { |tag| ['note', 'deprecated'].include?(tag.tag_name) && tag.is_a?(YARD::Tags::Tag) }
+ # Add a blank line if there's anything before the params.
+ docs_array << '' if docs_array.last != '' && docs_array.length.positive? && notice_tags.length.positive?
+ notice_tags.each do |notice_tag|
+ docs_array << '' if docs_array.last != ''
+ # Output note/deprecated/see in the form of:
+ # _@note_ — Lorem ipsum.
+ # _@note_
+ if notice_tag.text.nil?
+ docs_array << "_@#{notice_tag.tag_name}_"
+ else
+ docs_array << "_@#{notice_tag.tag_name}_ — #{notice_tag.text}"
+ end
+ end
+
+ # Add @see tags.
+ see_tags = parser.tags.select { |tag| tag.tag_name == 'see' && tag.is_a?(YARD::Tags::Tag) }
+ # Add a blank line if there's anything before the params.
+ docs_array << '' if docs_array.last != '' && docs_array.length.positive? && see_tags.length.positive?
+ see_tags.each do |see_tag|
+ docs_array << '' if docs_array.last != ''
+ # Output note/deprecated/see in the form of:
+ # _@see_ `B` — Lorem ipsum.
+ # _@see_ `B`
+ if see_tag.text.nil?
+ docs_array << "_@see_ `#{see_tag.name}`"
+ else
+ docs_array << "_@see_ `#{see_tag.name}` — #{see_tag.text}"
+ end
+ end
+
+ m.add_comments(docs_array)
+ end
+ end
end
end
# Given a YARD NamespaceObject, add lines defining its mixins, methods
# and children to the RBI file.
@@ -225,9 +315,10 @@
parent = @current_object
@current_object = item.type == :class \
? parent.create_class(item.name.to_s, superclass: superclass)
: parent.create_module(item.name.to_s)
+ @current_object.add_comments(item.docstring.all.split("\n"))
add_mixins(item)
add_methods(item)
add_constants(item)