lib/yard/parser/c/comment_parser.rb
# frozen_string_literal: true
module YARD
module Parser
module C
module CommentParser
protected
def parse_comments(comments)
@overrides = []
spaces = nil
comments = remove_private_comments(comments)
comments = comments.split(/\r?\n/).map do |line|
line.gsub!(%r{^\s*/?\*/?}, '')
line.gsub!(%r{\*/\s*$}, '')
if line =~ /^\s*$/
next if spaces.nil?
next ""
end
spaces = (line[/^(\s+)/, 1] || "").size if spaces.nil?
line.gsub(/^\s{0,#{spaces}}/, '').rstrip
end.compact
comments = parse_overrides(comments)
comments = parse_callseq(comments)
comments.join("\n")
end
private
def parse_overrides(comments)
comments.map do |line|
type, name = *line.scan(/^\s*Document-(class|module|method|attr|const):\s*(\S.*)\s*$/).first
if type
@overrides << [type.to_sym, name]
nil
else
line
end
end.compact
end
def parse_callseq(comments)
return comments unless comments[0] =~ /\Acall-seq:\s*(\S.+)?/
if $1
comments[0] = " #{$1}"
else
comments.shift
end
overloads = []
seen_data = false
while comments.first =~ /^\s+(\S.+)/ || comments.first =~ /^\s*$/
line = comments.shift.strip
break if line.empty? && seen_data
next if line.empty?
seen_data = true
line.sub!(/^\w+[\.#]/, '')
signature, types = *line.split(/ [-=]> /)
types = parse_types(types)
if signature.sub!(/\[?\s*(\{(?:\s*\|(.+?)\|)?.*\})\s*\]?\s*$/, '') && $1
blk = $1
blkparams = $2
else
blk = nil
blkparams = nil
end
case signature
when /^(\w+)\s*=\s+(\w+)/
signature = "#{$1}=(#{$2})"
when /^\w+\s+\S/
signature = signature.split(/\s+/)
signature = "#{signature[1]}#{signature[2] ? '(' + signature[2..-1].join(' ') + ')' : ''}"
when /^\w+\[(.+?)\]\s*(=)?/
signature = "[]#{$2}(#{$1})"
when /^\w+\s+(#{CodeObjects::METHODMATCH})\s+(\w+)/
signature = "#{$1}(#{$2})"
end
break unless signature =~ /^#{CodeObjects::METHODNAMEMATCH}/
signature = signature.rstrip
overloads << "@overload #{signature}"
overloads << " @yield [#{blkparams}]" if blk
overloads << " @return [#{types.join(', ')}]" unless types.empty?
end
comments + [""] + overloads
end
def parse_types(types)
if types =~ /true or false/
["Boolean"]
else
(types || "").split(/,| or /).map do |t|
case t.strip.gsub(/^an?_/, '')
when "class"; "Class"
when "obj", "object", "anObject"; "Object"
when "arr", "array", "anArray", "ary", "new_ary", /^\[/; "Array"
when /^char\s*\*/, "char", "str", "string", "new_str"; "String"
when "enum", "anEnumerator"; "Enumerator"
when "exc", "exception"; "Exception"
when "proc", "proc_obj", "prc"; "Proc"
when "binding"; "Binding"
when "hsh", "hash", "aHash"; "Hash"
when "ios", "io"; "IO"
when "file"; "File"
when "float"; "Float"
when "time", "new_time"; "Time"
when "dir", "aDir"; "Dir"
when "regexp", "new_regexp"; "Regexp"
when "matchdata"; "MatchData"
when "encoding"; "Encoding"
when "fixnum", "fix"; "Fixnum"
when /^(?:un)?signed$/, /^(?:(?:un)?signed\s*)?(?:short|int|long|long\s+long)$/, "integer", "Integer"; "Integer"
when "num", "numeric", "Numeric", "number"; "Numeric"
when "aBignum"; "Bignum"
when "nil"; "nil"
when "true"; "true"
when "false"; "false"
when "bool", "boolean", "Boolean"; "Boolean"
when "self"; "self"
when /^[-+]?\d/; t
when /[A-Z][_a-z0-9]+/; t
end
end.compact
end
end
def remove_private_comments(comment)
comment = comment.gsub(%r{/?\*--\n(.*?)/?\*\+\+}m, '')
comment = comment.sub(%r{/?\*--\n.*}m, '')
comment
end
end
end
end
end