加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

make doxygen comments in Obj-C/C/C++ files

发布时间:2020-12-17 04:12:11 所属栏目:百科 来源:网络整理
导读:今天PHP站长网 52php.cn把收集自互联网的代码分享给大家,仅供参考。 #!/usr/bin/env ruby## v2.0# This script helps you make doxygen comments in Obj-C/C/C++ files in XCode## Created by Fred McCann on 03/16/2010

以下代码由PHP站长网 52php.cn收集自互联网

现在PHP站长网小编把它分享给大家,仅供参考

#!/usr/bin/env ruby

#
# v2.0
# This script helps you make doxygen comments in Obj-C/C/C++ files in XCode
#
# Created by Fred McCann on 03/16/2010 - and Edwin.
# http://www.duckrowing.com
#
# Adapted for ThisService by Martin Pichlmair 03/29/2011
#
# Modified for Objectiv-c by Dake 07/22/2012
# http://glade.tk
#

module Duckrowing
  # TAILMATCH1 = /[s*;.*]/
  # Convenience class to hold name and type information  
  class Argument
    def initialize(type = nil,name = nil)
      self.type = type
      self.name = name
    end
    
    def name
      @name
    end
    
    def name=(name)
      if name != nil
        name.gsub!(/^&/,'')
        name.gsub!(/^*/,'')
        name.gsub!(/[.*$/,'')
        name.gsub!(/,$/,'')
        name.gsub!(/;$/,'')
        name.gsub!(/^s*/,'')
        name.gsub!(/s*$/,'')
      end
      if name == '...'
        @name = 'vararg_list'
      else
        @name = name
      end
    end

    def type
      @type
    end

    def type=(type)
      if type != nil
        type.gsub!(/&$/,'')
        type.gsub!(/s**$/,'')
        type.gsub!(/^s*/,'')
        type.gsub!(/s*$/,'')
      end
      @type = type
    end
  end
  
  # Base implementation of commenter
  class BaseCommenter
    # Creates a new commenter object
    def initialize(indent,code)
      @indent = indent
      @code = code
      @arguments = []
      @returns = false
    end
    
    # Creates an opening comment
    def start_comment(description = 'Description')
      #str = "/**n"
      str = "#{@indent}/**n"
      str += "#{@indent} *[email?protected]t<##{description}#>n"
      str      
    end
    
    def arguments_comment
	  str = ''
      @arguments.each do |arg|
		if str == '' 
			str += "#{@indent} *n"
		end
        str += "#{@indent} *[email?protected] t#{arg.name} [IN|OUT] t<##{arg.name} description#>n"
      end
      str
    end
    
    def return_comment
      return '' if [email?protected]
      "#{@indent} *n#{@indent} *[email?protected]t<#return value description#>n"
    end

    # Creates closing comment
    def end_comment()
      "#{@indent} */n"
      #"#{@indent} */n#{@indent}"
    end
    
    # Convenience method to detect multiline statements
    def is_multiline?
      @code =~ /n/
    end
    
    # Adds inline comments to a comma delimited list
    def comment_list(list,base_indent='')
      commented_list = ""
      matches = list.scan(/@pS*/)
      if matches.size > 0
        # class contains @protected @private @public
        list.insert(matches[0].to_s.length+1,"t")
      end

      # 获取类型标识符
      # prefix = list.scan(/^s*(.+?)[s*+]/)
      # puts prefix
                
      # 分隔符
      seperator = ','

      ids = list.split(/,/)
      ids.each do |id|
        if matches.size > 0
          # class contains @protected...
          id.gsub!(/40*$/,'')
          id.gsub!(/^40*/,'')
        # enum、struct、define
        else 
          id.gsub!(/s*$/,'')
          id.gsub!(/^s*/,'')
          # seperator = ','
        end

        if id != "" 
          list_id = "#{id}"
          list_id += seperator if id != ids.last

          id.gsub!(/=.*$/,'') 
          id.gsub!(/[.*]/,'')                   
          id.gsub!(/s*$/,'')              
          id.gsub!(/;/,'') 
          id.gsub!(/s*:s*d+/,'') 

          doc_id = id.split(/s/).last
          doc_id.gsub!(/*/,'')

          commented_list += "t" if id != ids.first && base_indent.length == 0      
          commented_list += "#{@indent}#{base_indent}#{list_id} /**< <##{doc_id} description#> */"
          commented_list += "n" if id != ids.last 
        end
      end
      commented_list.chomp
    end
    
    # Parses a comma delimited list into an array of Argument objects
    def parse_c_style_argument_list(str)
      arguments = []
      str.split(/,/).each do |a|
        arg = Argument.new
        parts = a.split(/s+/)
        arg.name = parts.last
        parts.delete_at(parts.size - 1)
        arg.type = parts.join(" ")
        @arguments << arg
      end            
    end

    # def parse_c_style_argument_list(str)
    #   arguments = []
    #   matches = str.scan(/s*(.*?)s+(w+)?/)
    #   matches.each do |m|
    #     # puts m
    #     next if m.size != 2
    #     arg = Argument.new
    #     arg.type = m[0].to_s.gsub(TAILMATCH1,'')
    #     arg.name = m[1].to_s.gsub(TAILMATCH1,'')
    #     puts arg.type
    #     puts arg.name
    #     @arguments << arg
    #   end
    # end
    
    # Add Xcode selection markup to first editable field
    def select_first_field(str)
      # Add PBX selection to first field
      matches = str.scan(/&;#.*#&;/)
      if matches.size > 0
        first_field = matches[0].to_s
        # str.gsub!(/#{first_field}/,"%%%{PBXSelection}%%%#{first_field}%%%{PBXSelection}%%%")
        str.gsub!(/#{first_field}/,"#{first_field}")
      end
      
      str
    end
    
    # Returns a comment above the code and the original section of commented code
    def document
      str = start_comment()
      str += arguments_comment()
      str += return_comment()
      str += end_comment()
      str += "#{@code}"
      select_first_field(str)
    end    
  end
  
  class VariableCommenter < BaseCommenter
    # Adds a basic comment above individual variables and rewrites multiple
    # declaritions into an inline commented list
    def document
      matches = @code.scan(/;+s**/)
      if matches.size > 0
        comment_variable_list(@code)
      elsif @code.gsub(/n/,' ') =~ /^([^{]+,)/
        # "int i,j,k;"style
        commented_code = comment_list(@code,"")
        commented_code.sub!(/^s*/,@indent);
        select_first_field("#{commented_code}")
      else
        super
      end
    end 

    def comment_variable_list(list)
      commented_list = ""
      ids = list.gsub(/^s*/,'').gsub(/s*$/,'').split(/;/)
      ids.each do |id|
        id.gsub!(/s*$/,'')
        id.gsub!(/^s*/,'')
        list_id = "#{id};"        
        commented_list += "#{comment_list(list_id,"")}n"        
      end
      commented_list.chomp
    end 

  end

  class IfWhileForDoCommenter < BaseCommenter
    # Adds a basic comment above individual properties
  end

  class PropertyCommenter < BaseCommenter
    def document
      comment_property_list(@code)
    end 

    def comment_property_list(list)
      commented_list = ""
      ids = list.gsub(/^s*/,'').split(/n/)
      ids.each do |id|
        id.gsub!(/s*$/,'')
        # puts id

        if id =~ /^@propertys*([^<>]*)/
          matches = id.scan(/(@propertys*(.*))(.+;)/)
        else
          matches = id.scan(/(@property)(.+;)/)
        end

        matches.each do |m|
          next if m.size != 2
          # puts m[0]
          # puts m[1]     
          list_id = m[1]        
          commented_list += m[0].gsub!(/s*/,'')+" #{comment_list(list_id,'')}n"
        end        
      end
      commented_list.chomp
    end 
  end

  # class IntrefaceCommenter < BaseCommenter
  # # Comments semicolon delimited list of interface members
  #   def comment_interface_list(list)
  #     commented_list = ""
  #     ids = list.gsub(/^s*/,'').split(/;/)
  #     ids.each do |id|
  #       id.gsub!(/s*$/,'')
  #       id.gsub!(/^s*/,'')
  #       list_id = "#{id};"        
  #       base_indent = "t"
  #       commented_list += "#{comment_list(list_id,base_indent)}n"        
  #     end
  #     commented_list   
  #   end

  class MacroCommenter < BaseCommenter
    # Parse out args for inclusion in comment
    def capture_args
      matches = @code.scan(/(([^()]*))/)
      parse_c_style_argument_list(matches[0].to_s)
      @returns = true
    end

    def comment_list(list2,base_indent='')
      commented_list2 = ""
      doc_id = ""
      commented_list2 += "#{base_indent}#{list2} /**< <##{doc_id} description#> */"
    end
    
    def comment_macro_list(list)
      commented_list = ""
      ids = list.gsub(/^s*/,'')
        list_id = "#{id}"        
        commented_list += "#{comment_list(list_id,"")}n"        
      end
      commented_list.chomp
    end 

    # Adds a basic comment above individual variables and rewrites multiple
    # declaritions into an inline commented list
    def document
      # 带参宏
      if @code =~ /#defines*w+(/
        capture_args 
        super
      else
        comment_macro_list(@code)
      end
    end    
  end
  
  # Implementation of commenter to comment C style enums
  class EnumCommenter < BaseCommenter    
    # Comments identifiers in the code block
    def comment_code
      block_match = /{([^{}]*)}/
      matches = @code.scan(block_match)
      return if matches.size != 1
      
      block = matches[0].to_s
      @code.gsub!(block_match,"{n#{comment_list(block,"t")}n#{@indent}}")
    end
    
    # Comments the enum. This will write comments next to each name for a multiline
    # statement. It will not for single line enumerations.
    def document
      comment_code if is_multiline?
      super
    end
  end

  # Implementation of commenter to comment C style enums
  class StructCommenter < BaseCommenter
    # Comments semicolon delimited list of struct members
    def comment_struct_list(list)
      commented_list = ""
      ids = list.gsub(/^s*/,"t")}n"        
      end
      commented_list   
    end
    
    # Comments identifiers in the code block
    def comment_code
      block_match = /{([^{}]*)}/
      matches = @code.scan(block_match)
      return if matches.size != 1
      
      block = matches[0].to_s
      @code.gsub!(block_match,"{n#{comment_struct_list(block)}#{@indent}}")
    end
    
    # Adds inline comments for members and a comment for the entire struct
    def document
      comment_code
      super
    end
  end
  
  class FunctionCommenter < BaseCommenter
    # Parse out args for inclusion in comment
    def capture_args
      matches = @code.scan(/((.*))/)
      parse_c_style_argument_list(matches[0].to_s)
      # parse_c_style_argument_list(@code)
    end
    
    # Decides whether or not to add a returns tag to comment
    def capture_return
      @returns = @code.split(/(/).first !~ /void/ 
    end
    
    # Adds a basic comment above individual variables and rewrites multiple
    # declaritions into an inline commented list
    def document
      capture_args
      capture_return
      super
    end        
  end

  class MethodCommenter < BaseCommenter
    TAILMATCH = /[s*;.*]/
    
    # Find the return type
    def capture_return_type
      matches = @code.scan(/^s*[+-]s*(([^()]*))/)
      return nil if matches.size != 1
      type = matches[0].to_s.gsub(TAILMATCH,'')

      if type == 'void' || type == 'IBAction'
        @returns = nil
      else
        @returns = type
      end
    end
    
    # Parse out params
    def capture_parameters
      params = []
      matches = @code.scan(/s*:s*(+s*(.*?)s*)s*(w+)/)
      matches.each do |m|
        next if m.size != 2
        arg = Argument.new
        arg.type = m[0].to_s.gsub(TAILMATCH,'')
        arg.name = m[1].to_s.gsub(TAILMATCH,'')
        # puts arg.type
        # puts arg.name
        @arguments << arg        
      end
    end
        
    # Adds a basic comment above individual variables and rewrites multiple
    # declaritions into an inline commented list
    def document
      capture_parameters
      capture_return_type
      super
    end        
  end
  
  class Documenter    
    def document(code)
      # 此句刷格式缩进了
      #code.gsub!(/s*$/,'')
      indent = base_indentation(code)     
      
      klass = nil
      
      if is_objc_property?(code)
        klass = PropertyCommenter
      elsif is_objc_interface?(code)
        klass = StructCommenter
      elsif is_objc_implementation?(code)
        klass = StructCommenter
      elsif is_objc_method?(code)
        klass = MethodCommenter 
      elsif is_if_while_for_do?(code)
        klass = IfWhileForDoCommenter         
      elsif is_function?(code)
        klass = FunctionCommenter
      elsif is_macro?(code)
        klass = MacroCommenter
      elsif is_struct?(code)
        klass = StructCommenter
      elsif is_union?(code)
        klass = StructCommenter
      elsif is_enum?(code)
        klass = EnumCommenter
      else
        klass = VariableCommenter
      end
      
      # puts "USE --> #{klass}"
      commenter = klass.new(indent,code)
      commenter.document
    end
    
    private
    def is_objc_interface?(code)
      code =~ /^s*@interface/
    end

    def is_objc_implementation?(code)
      code =~ /^s*@implementation/
    end

    def is_objc_method?(code)
      # code =~ /^s*[+-]{1,1}s*(+/ 
      matches = code.scan(/^s*[+-]{1,1}s*(+/)
      return nil if matches.size == 0
      matches.size  
    end

    def is_objc_property?(code)
      code =~ /^s*@property/      
    end

    def is_if_while_for_do?(code)
      code =~ /^s*ifs*[({]|fors*[({]|whiles*[({]|dos*[({]/ 
    end

    def is_function?(code)
      !is_macro?(code) && !is_objc_method?(code) && !is_if_while_for_do?(code) && code =~ /(/
    end
    
    def is_macro?(code)
      code =~ /^s*#define/      
    end

    def is_enum?(code)
      code.gsub(/n/,' ') =~ /^s*(w+s)?enum.*{.*}/      
    end
    
    def is_struct?(code)
      code.gsub(/n/,' ') =~ /^s*(w+s)?struct.*{.*}/      
    end

    def is_union?(code)
      code.gsub(/n/,' ') =~ /^s*(w+s)?union.*{.*}/      
    end
    
    def base_indentation(code)
      matches = code.scan(/^(s*)/)
      return '' if matches.size == 0
      matches[0].to_s
    end
  end
end


# Unicode considerations:
#  Set $KCODE to 'u'. This makes STDIN and STDOUT both act as containing UTF-8.
$KCODE = 'u'

#  Since any Ruby version before 1.9 doesn't much care for Unicode,#  patch in a new String#utf8_length method that returns the correct length
#  for UTF-8 strings.
UNICODE_COMPETENT = ((RUBY_VERSION)[0..2].to_f > 1.8)

unless UNICODE_COMPETENT # lower than 1.9
  class String
    def utf8_length
      i = 0
      i = self.scan(/(.)/).length
      i
    end
  end
else # 1.9 and above
  class String
    alias_method :utf8_length,:length
  end
end

input = STDIN.gets nil
# input now contains the contents of STDIN.
# Write your script here. 
# Be sure to print anything you want the service to output.
documenter = Duckrowing::Documenter.new
replacement = documenter.document(input)
print replacement

以上内容由PHP站长网【52php.cn】收集整理供大家参考研究

如果以上内容对您有帮助,欢迎收藏、点赞、推荐、分享。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读