Exemple #1
0
def render_ns(ns, all_functions, all_classes, all_usings):

    R = make_header(ns, '#')
    ns = ns.split('::',1)[-1]

    if len(all_usings) > 0:
        R += make_header('Type aliases')
        R += render_table([(t.spelling, re.sub(ns+'::','',t.underlying_typedef_type.spelling),
                            replace_latex(clean_doc_string(t.raw_comment)) if t.raw_comment else '') for t in all_usings])

    if all_classes:
        R += make_header('Classes')
        R += ".. table::\n   :width: 50% 50%\n\n"
        #R += render_table([(":ref:`%s <_%s_%s>`"%(cls.spelling,escape_lg(ns), escape_lg(cls.spelling)), cls.processed_doc.elements['brief']) for cls in all_classes ])
        R += render_table([(":ref:`%s <%s>`"%(escape_lg(cls.name), cls.name_for_label), cls.processed_doc.elements['brief']) for cls in all_classes ])
        R += toctree_hidden
        for cls in all_classes:
            R += "    {ns}/{filename}\n".format(ns = ns, filename = replace_ltgt(cls.name))


    if all_functions:
        R += make_header('Functions')
        R += render_table([(":ref:`%s <%s>`"%(name, make_label(CL.fully_qualified_name(f_list[0]))),
                            f_list[0].processed_doc.elements['brief']) for (name, f_list) in list(all_functions.items()) ])
        #R += render_table([(":ref:`%s <%s>`"%(name, escape_lg(name)), f_list[0].processed_doc.elements['brief']) for (name, f_list) in all_functions.items() ])
        #R += render_table([(":ref:`%s <%s_%s>`"%(name,escape_lg(ns), escape_lg(name)), f_list[0].processed_doc.elements['brief']) for (name, f_list) in all_functions.items() ])
        R += toctree_hidden
        for f_name in all_functions:
           R += "    {ns}/{f_name}\n".format(ns = ns, f_name = f_name)

    return R
Exemple #2
0
def render_fnt(parent_class, f_name, f_overloads):
    """
       Generate the rst page for a function
        
        * f_name : name of the function
        * overload_docs : ??
        * parent_class : None or the parent class if it is a method
        * f_overloads : a list of WHAT ?
    """
    # Start of the page
    R = rst_start

    # tag and name of the class
    parent_cls_name_fully_qualified = (CL.fully_qualified_name(parent_class) +
                                       "::") if parent_class else ""
    parent_cls_spelling = (parent_class.spelling + '_') if parent_class else ''
    f_name_full = parent_cls_name_fully_qualified + f_name

    R += """
.. _{class_rst_ref}:

{f_name_full}
""".format(f_name_full=f_name_full, class_rst_ref=parent_cls_spelling + f_name)

    R += '=' * (len(f_name_full) + 0) + '\n' + """

"""
    # Synopsis
    R += make_synopsis_list(f_overloads) + '\n\n'

    # HOW DO WE GROUP THE OVERLOAD
    # Enumerate all overloads
    for n, f in enumerate(f_overloads):
        doc = f.processed_doc
        doc_elem = doc.elements

        num = '%s.' % (n + 1) if len(f_overloads) > 1 else ''
        R += '\n' + num + ' ' + doc.brief_doc + '\n'
        R += doc.doc

        # TODO which order ?
        if 'note' in doc_elem: R += render_note(doc_elem.pop('note'))
        if 'warning' in doc_elem: R += render_warning(doc_elem.pop('warning'))
        if 'figure' in doc_elem: R += render_fig(doc_elem.pop('figure'))
        if 'tparam' in doc_elem:
            R += render_list(doc_elem.pop('tparam'), 'Template parameters')
        if 'param' in doc_elem:
            R += render_list(doc_elem.pop('param'), 'Parameters')
        if 'return' in doc_elem:
            R += make_header('Return value') + doc_elem.pop('return')

    # any example from the overloads
    # Should we TAKE ONLY ONE ????? Error ??
    example_file_name = reduce(
        lambda x, y: x or y,
        [f.processed_doc.elements.pop('example', '') for f in f_overloads], '')
    R += render_example(example_file_name)

    return R
Exemple #3
0
    def __init__(self, node):
        raw_doc = node.raw_comment

        if not raw_doc : raw_doc = "\n\n" # default value

        # Clean *, &&, /// and co.
        doc = clean_doc_string(raw_doc).rstrip() # do NOT remove leading space

        # split : the first line is brief, and the rest
        doc = replace_latex(doc)
        if '$' in doc :
            print("FAILED to process the latex for node %s"%CL.fully_qualified(node))
            print(doc)
        doc2 = doc.split('@',1)[0] # Get rid of everything after the first @
        self.doc = doc2

        assert '@' not in self.doc, "Internal Error in doc processing !"

        # Process the main part of the doc
        self.doc = strip_left_spaces(self.doc)

        # Extract the @XXXX elements with a regex @XXXX YYYY (YYYY can be multiline).
        d = dict( (key, []) for key in self.fields_with_multiple_entry)
        regex = r'@(\w+)\s(\s*[^@]*)'
        for m in re.finditer(regex, doc, re.DOTALL):
            key, val = m.group(1), replace_latex(m.group(2)).rstrip()
            if key not in self.fields_allowed_in_docs:
                print("Field %s is not recognized"%key)
            if key in self.fields_with_multiple_entry:
                d[key].append(val)
            else:
                d[key] = val
        self.elements = d
        if 'brief' not in d : d['brief']=''

        # if 'return' in d : print d['return']

        # print doc
        # print raw_doc
        # print d['param']

        # Final adjustement
        if 'brief' not in d : d['brief']=''

        if 'example' not in d : # take the default
            filename=  "%s.cpp"%(CL.fully_qualified_name(node).replace("::",'/'))
            filename = os.path.join(global_vars.examples_root, filename)
            if os.path.exists(filename):
                d['example'] =  filename

        if 'include' not in d :
           ns = CL.get_namespace_list(node)
           d['include'] = '/'.join(ns) + '.hpp'
Exemple #4
0
def render_cls(cls, all_methods, all_friend_functions):
    """
       Generate the rst page for a class
        
        * cls : node for the classf_name : name of the function
        * doc_methods : ??
    """

    cls_doc = cls.processed_doc
    doc_elem = cls_doc.elements
    R = rst_start

    # include
    incl = doc_elem.pop('include', '')

    # class header
    cls_name_fully_qualified = CL.fully_qualified_name(cls)
    R += """
.. _{cls.spelling}:

{cls_name_fully_qualified}
{separator}

Defined in header <*{incl}*>

.. code-block:: c

    {templ_synop}class {cls.spelling};

{cls_doc.brief_doc}

{cls_doc.doc}
    """.format(cls=cls,
               incl=incl.strip(),
               separator='=' * (len(cls_name_fully_qualified)),
               templ_synop=make_synopsis_template_decl(cls),
               cls_doc=cls_doc,
               cls_name_fully_qualified=cls_name_fully_qualified)

    #
    R += cls_doc.doc
    if 'tparam' in doc_elem:
        R += render_list(doc_elem.pop('tparam'), 'Template parameters')
    if 'note' in doc_elem: R += render_note(doc_elem.pop('note'))
    if 'warning' in doc_elem: R += render_warning(doc_elem.pop('warning'))
    if 'figure' in doc_elem: R += render_fig(doc_elem.pop('figure'))

    # Members
    c_members = list(CL.get_members(cls, True))
    if len(c_members) > 0:
        R += make_header('Public members')
        R += render_table([(t.spelling, t.type.spelling,
                            replace_latex(clean_doc_string(t.raw_comment))
                            if t.raw_comment else '') for t in c_members])

    # Using : TODO : KEEP THIS ?
    c_usings = list(CL.get_usings(cls))
    for t in c_usings:
        t.my_tag = t.spelling

    if len(c_usings) > 0:
        R += make_header('Member types')
        R += render_table([(t.spelling,
                            replace_latex(clean_doc_string(t.raw_comment))
                            if t.raw_comment else '') for t in c_usings])

    # A table for all member functions and all friend functions
    def group_of_overload(f_list):
        s = set(f.processed_doc.elements['group'] for f in f_list
                if 'group' in f.processed_doc.elements)
        assert len(s) < 2, "Can not have different group for various overload"
        return s.pop if s else ''

    def make_func_list(all_f, header_name):
        R = ''
        if len(all_f) > 0:
            R += make_header(header_name)
            R += render_table([
                (":ref:`%s <%s_%s>`" %
                 (name, escape_lg(cls.spelling), escape_lg(name)),
                 f_list[0].processed_doc.brief_doc)
                for (name, f_list) in all_f.items()
            ])
            R += toctree_hidden
            for f_name in all_f:
                R += "    {cls.spelling}/{f_name}\n".format(cls=cls,
                                                            f_name=f_name)
        return R

    R += make_func_list(all_methods, 'Member functions')
    R += make_func_list(all_friend_functions, 'Non Member functions')

    # Example
    if 'example' in doc_elem: R += render_example(doc_elem.pop('example'))

    return R
Exemple #5
0
def render_cls(cls, all_methods, all_friend_functions):
    """
       Generate the rst page for a class

        * cls : node for the classf_name : name of the function
        * doc_methods : ??
    """

    cls_doc = cls.processed_doc
    doc_elem = cls_doc.elements
    R= rst_start

    # include
    incl = doc_elem.pop('include', '')

    # class header
    fully_qualified_name = CL.fully_qualified_name(cls)
    R +="""
.. _{cls.name_for_label}:

{cls.fully_qualified_name}
{separator}

*#include <{incl}>*

.. rst-class:: cppsynopsis

     {templ_synop} class  :red:`{cls.name}`

{cls_doc.doc}
    """.format(cls = cls, incl = incl.strip(), separator = '=' * (len(cls.fully_qualified_name)), templ_synop = make_synopsis_template_decl(cls), cls_doc = cls_doc)

    #
    if 'tparam' in doc_elem:    R += render_list(doc_elem.pop('tparam'), 'Template parameters', '-')
    if 'note' in doc_elem :     R += render_note(doc_elem.pop('note'))
    if 'warning' in doc_elem:   R += render_warning(doc_elem.pop('warning'))
    if 'figure' in doc_elem:    R += render_fig(doc_elem.pop('figure'))

    # Members
    if len(cls.members) > 0:
        R += make_header('Public members')
        R += render_table([(t.spelling,t.type.spelling, replace_latex(clean_doc_string(t.raw_comment)) if t.raw_comment else '') for t in cls.members])

    # Usings
    if len(cls.usings) > 0:
        R += make_header('Member types')
        R += render_table([(t.spelling, re.sub(cls.namespace + '::','',t.underlying_typedef_type.spelling),
                            replace_latex(clean_doc_string(t.raw_comment)) if t.raw_comment else '') for t in cls.usings])

    # A table for all member functions and all friend functions
    def group_of_overload(f_list):
        s = set(f.processed_doc.elements['group'] for f in f_list if 'group' in f.processed_doc.elements)
        assert len(s) < 2, "Can not have different group for various overload"
        return s.pop if s else ''

    def make_func_list(all_f, header_name):
        if not all_f : return ''
        R = make_header(header_name)

        # Regroup the function by sub category
        D = OrderedDict()
        for name, flist in list(all_f.items()):
            cat =flist[0].processed_doc.elements.get('category', None)
            name_for_user = escape_lg(name)
            if name_for_user in ['constructor', 'destructor'] : name_for_user = '******'%name_for_user
            D.setdefault(cat, list()).append((":ref:`%s <%s>`"%(name_for_user,make_label(cls.fully_qualified_name + '__' + name)), flist[0].processed_doc.elements['brief']))

        # Make the sub lists
        for cat, list_table_args in list(D.items()) :
            if cat : R += make_header(cat, '~')
            R += render_table(list_table_args)

        # the hidden toctree is not regrouped
        R += toctree_hidden
        for f_name in all_f:
           R += "    {cls_name}/{f_name}\n".format(cls_name = replace_ltgt(cls.name), f_name = f_name)
        return R

    R += make_func_list(all_methods, 'Member functions')
    R += make_func_list(all_friend_functions, 'Non Member functions')

    # Example
    if 'example' in doc_elem: R += render_example(doc_elem.pop('example'))

    return R
Exemple #6
0
def render_fnt(parent_class, f_name, f_overloads):
    """
       Generate the rst page for a function

        * f_name : name of the function
        * overload_docs : ??
        * parent_class : None or the parent class if it is a method
        * f_overloads : a list of WHAT ?
    """
    # Start of the page
    R = rst_start

    # include
    incl = f_overloads[0].processed_doc.elements.pop('include', '')

    # tag and name of the class
    if parent_class:
        f_name_full = parent_class.fully_qualified_name + "::" + f_name
    else :
        f_name_full = CL.fully_qualified_name(f_overloads[0]) # full name of the function


    R += """
.. _{class_rst_ref}:

{f_name_full}
{separator}

*#include <{incl}>*

""".format(f_name_full = f_name_full, incl = incl, class_rst_ref = make_label(f_name_full), separator =  '=' * (len(f_name_full)+0) )
#""".format(f_name_full = f_name_full, incl = incl, class_rst_ref = make_label(parent_cls_name + f_name), separator =  '=' * (len(f_name_full)+0) )

    R += """

"""
    # Synopsis
    R += make_synopsis_list(f_overloads) + '\n\n'

    # We regroup the overload as in cppreference

    def make_unique(topic) :
        rets = set(f.processed_doc.elements.pop(topic, '').rstrip() for f in f_overloads)
        rets = list(x for x in rets if x)
        if len(rets)> 1: print("Warning : Multiple documentation of %s across overloads. Picking first one"%topic)
        return rets[0] if rets else ''

    def make_unique_list(topic) :
        D = OrderedDict()
        for n, f in enumerate(f_overloads):
           plist = f.processed_doc.elements.pop(topic) # p is a string "NAME REST"
           for p in plist :
               name, desc = (p + '   ').split(' ',1)
               if name not in D:
                   D[name] = desc.rstrip()
               else:
                   if D[name] != desc.strip() :
                       print("Warning : multiple definition of parameter %s at overload %s"%(name, n))
        return D

    def render_dict(d, header, char, role):
        """
           Make rst code for a list of items with  a header
           It splits the first word in a separate column
        """
        if not d: return ''
        head = make_header(header, char) if header else ''
        return head + '\n'.join(" * :%s:`%s` %s\n"%(role, k.strip(),v) for (k,v) in list(d.items()))

    has_overload = len(f_overloads)> 1

    # Head doc
    head = make_unique('head') or ("Documentation" if has_overload else '')
    R += '%s\n\n'%head

    # The piece of doc which is overload dependent
    if has_overload :
        for num, f in enumerate(f_overloads):
            pd =  f.processed_doc
            num_s =  '**%s)**  '%(num+1) if has_overload else ''
            if pd.doc : R +=  '\n\n %s %s\n '%(num_s,  pd.doc.replace('\n', '\n        '))+ '\n'
    else :
        R+='\n\n%s\n\n'%(f_overloads[0].processed_doc.doc)

    # Tail doc
    R += '%s\n\n' %make_unique('tail')

    # Figure
    figure = make_unique('figure')
    if figure : R += render_fig(figure)

    # tparam and param
    tparam_dict = make_unique_list('tparam')
    param_dict = make_unique_list('param')


    R += render_dict(tparam_dict, 'Template parameters', '^', role = 'param')
    R += render_dict(param_dict, 'Parameters','^', role = 'param')

    # Returns
    rets = make_unique("return")
    if rets : R += make_header('Returns', '^') + "%s"%rets

    # Examples
    example_file_name = make_unique("example")
    R += "\n" + render_example(example_file_name.strip())

    # Warning
    w = make_unique("warning")
    R += render_warning(w)

    return R
Exemple #7
0
 def mkchdir_for_one_node(node):
     mkchdir(*(CL.fully_qualified_name(node).split('::')[:-1]))
Exemple #8
0
    def analyse_one_ns(self, namespace):

        print "*** Namespace %s ***"%namespace

        # ----------------------
        #      Filters
        # ----------------------
        def keep_ns(n):
            """Given a namespace node n, shall we keep it ?"""
            ns = CL.fully_qualified(n) 
            return ns in namespace
        
        def keep_cls(c):
            """ Given a class node, shall we keep it ? 

               Reject if no raw_comment.
               Keeps if its namespace is EXACTLY in self.namespaces
               e.g. A::B::cls will be kept iif A::B is in self.namespaces, not it A is.

               The filter to keep a class/struct or an enum :
                 it must have a raw comment
                 if we a namespace list, it must be in it.
                 if target_file_only it has to be in the file given to c++2py
            """
            if c.spelling.startswith('_') : return False
            if not c.raw_comment : return False
            if namespace:
                qualified_ns = CL.get_namespace(c) 
                if qualified_ns != namespace : return False
            return (c.location.file.name == self.filename) if self.target_file_only else True
        
        def keep_fnt(f):
            if not f.raw_comment : return False
            if  f.spelling.startswith('operator') or f.spelling in ['begin','end'] : return False
            return keep_cls(f) 

        def keep_using(c):
            if namespace:
                qualified_ns = CL.get_namespace(c) 
                if qualified_ns != namespace : return False
            return (c.location.file.name == self.filename) if self.target_file_only else True

        def keep_is_documented(c):
            return True if c.raw_comment else False

        # ----------------------

        # A list of AST nodes for classes
        classes = CL.get_classes(self.root, keep_cls, traverse_namespaces = True, keep_ns = keep_ns)
        classes = list(classes) # make a list to avoid exhaustion of the generator
  
        D = OrderedDict()
        for cls in classes: 
            cls.namespace = CL.get_namespace(cls)
            cls.name = CL.get_name_with_template_specialization(cls) or cls.spelling 
            cls.fully_qualified_name = '::'.join([cls.namespace, cls.name])
            cls.fully_qualified_name_no_template = CL.fully_qualified_name(cls)
            cls.name_for_label = synopsis.make_label(cls.fully_qualified_name)
            D[cls.fully_qualified_name] = cls
       
            print " ... class :  %s"%cls.fully_qualified_name, cls.location
            #assert ',' not in cls.fully_qualified_name, "Not implemented"

            # process the doc of the class and add it to the node
            cls.processed_doc = ProcessedDoc(cls)

            # all methods and constructors
            # we build a OrderedDict of the constructors (first) and the methods, in order of declaration 
            constructors = list(CL.get_constructors(cls))
            for f in constructors : f.is_constructor = True # tag them for later use
            methods = OrderedDict()
            if constructors: methods['constructor'] = constructors
            methods.update(self.regroup_func_by_names(CL.get_methods(cls, True, keep = keep_is_documented))) # True : with inherited 

            # all non member functions
            friend_functions = self.regroup_func_by_names(CL.get_friend_functions(cls, keep = keep_is_documented))

            # Analyse the doc string for all methods and functions, and store the result in the node itself
            for (n,f_list) in (methods.items() + friend_functions.items()):
                for f in f_list:
                    f.processed_doc = ProcessedDoc(f)

            # attach to the node
            cls.methods, cls.friend_functions = methods, friend_functions

            # members 
            cls.members = list(CL.get_members(cls, True)) 
            
            # using 
            cls.usings = list(CL.get_usings(cls)) # , keep_using)) 
             
        # Eliminate doublons, like forward declarations
        classes = D.values()

        # A list of AST nodes for the methods and functions
        functions = CL.get_functions(self.root, keep_fnt, traverse_namespaces = True, keep_ns = keep_ns)
        functions = list(functions) # make a to avoid exhaustion of the generator

        # Analyse the doc strings 
        for f in functions:
            f.processed_doc = ProcessedDoc(f)
        
        # Find the using of this namespace, and make the list unique based on the fully_qualified_name 
        usings = list(CL.get_usings(self.root, keep_using, traverse_namespaces = True, keep_ns = keep_ns)) 
        D = OrderedDict()
        for c in usings:
            c.namespace = CL.get_namespace(c)
            c.fully_qualified_name = '::'.join([c.namespace, c.spelling])
            D[c.fully_qualified_name] = c
        usings = D.values()

        return classes, functions, usings
Exemple #9
0
 def mkchdir_for_one_node(node): 
     mkchdir(* ( CL.fully_qualified_name(node).split('::')[:-1]))
Exemple #10
0
    def run(self, output_directory):

        print "Generating the documentation ..."
        mkchdir(output_directory)

        # Filters
        def keep_ns(n):
            ns = CL.fully_qualified(n)
            if 'std' in ns or 'boost' in ns or 'detail' in ns or 'impl' in ns:
                return False
            if len(self.namespaces) == 0: return True
            return any((ns in x) for x in self.namespaces)

        def keep_cls(c):
            """
               The filter to keep a class/struct or an enum :
                 it must have a raw comment
                 if we a namespace list, it must be in it.
                 if target_file_only it has to be in the file given to c++2py
            """
            if not c.raw_comment: return False
            if self.namespaces:
                qualified_ns = CL.get_namespace(c)
                if not any((x in qualified_ns) for x in self.namespaces):
                    return False
            return (c.location.file.name
                    == self.filename) if self.target_file_only else True

        def keep_fnt(f):
            if not f.raw_comment: return False
            if f.spelling.startswith('operator') or f.spelling in [
                    'begin', 'end'
            ]:
                return False
            return keep_cls(f)

        # A list of AST nodes for classes
        classes = CL.get_classes(self.root,
                                 keep_cls,
                                 traverse_namespaces=True,
                                 keep_ns=keep_ns)
        classes = list(classes)  # to avoid exhaustion of the generator

        # A list of AST nodes for the methods and functions
        all_functions = CL.get_functions(self.root,
                                         keep_fnt,
                                         traverse_namespaces=True,
                                         keep_ns=keep_ns)
        all_functions = list(
            all_functions)  # to avoid exhaustion of the generator

        # Build the doc for all functions
        for f in all_functions:
            f.processed_doc = ProcessedDoc(f)

        # c : AST node of name A::B::C::clsname makes and cd into A/B/C
        def mkchdir_for_one_node(node):
            mkchdir(*(CL.fully_qualified_name(node).split('::')[:-1]))

        # regroup the functions into a list of overloads
        def regroup_func_by_names(fs):
            """ Given a list of functions, regroup them by names"""
            d = OrderedDict()

            def decay(name):
                if 'operator' not in name: return name
                a, ca, c, co = '+ - * /', '+= -= \*= /=', "== !=", r" comparison"
                d = {
                    '*=': ca,
                    '+=': ca,
                    '/=': ca,
                    '-=': ca,
                    '*': a,
                    '+': a,
                    '/': a,
                    '-': a,
                    '==': c,
                    '!=': c,
                    '<': co,
                    '>': co,
                    '<=': co,
                    '>=': co
                }
                n = name.replace('operator', '').strip()
                return 'operator' + d[n] if n in d else name

            for f in fs:
                d.setdefault(decay(f.spelling), []).append(f)
            return d

        synopsis.class_list = classes
        synopsis.class_list_name = [n.spelling for n in classes]

        for c in classes:
            if not c.spelling.strip():
                print "Skipping a class with an empty name !"
                continue

            print " ... class :  " + c.spelling, CL.fully_qualified_name(
                c), c.kind, CL.get_name_with_template_specialization(c)

            # process the doc of the class and add it to the node
            c.processed_doc = ProcessedDoc(c)

            # all methods and constructors
            constructors = list(CL.get_constructors(c))
            for f in constructors:
                f.is_constructor = True  # tag them for later use
            all_methods = OrderedDict()
            if constructors: all_methods['constructor'] = constructors
            all_methods.update(regroup_func_by_names(CL.get_methods(
                c, True)))  # True : with inherited ?

            # all non member functions
            all_friend_functions = regroup_func_by_names(
                CL.get_friend_functions(c))

            # process the doc for all methods and functions, and store it in the node.
            for (n, f_list) in (all_methods.items() +
                                all_friend_functions.items()):
                for f in f_list:
                    f.processed_doc = ProcessedDoc(f)

            # One directory for the class
            cur_dir = os.getcwd()
            mkchdir_for_one_node(c)

            # the file for the class
            r = render_cls(c, all_methods, all_friend_functions)
            safe_write(c.spelling, r)

            # create a directory with the class name
            mkchdir(c.spelling)

            # write a file for each function
            def render(mess, d):
                for f_name, f_overloads in d.items():
                    print " ...... %s %s" % (mess, f_name)
                    r = render_fnt(parent_class=c,
                                   f_name=f_name,
                                   f_overloads=f_overloads)
                    safe_write(f_name, r)

            render('methods', all_methods)
            render('non member functions', all_friend_functions)

            # Change back to up directory
            os.chdir(cur_dir)

        all_functions = regroup_func_by_names(all_functions)

        docs = dict((n, [ProcessedDoc(f) for f in fs])
                    for (n, fs) in all_functions.items())

        for f_name, f_overloads in all_functions.items():
            print " ... function " + f_name, "      [", f_overloads[
                0].location.file.name, ']'
            cur_dir = os.getcwd()
            mkchdir_for_one_node(f_overloads[0])
            r = render_fnt(parent_class=None,
                           f_name=f_name,
                           f_overloads=f_overloads)
            safe_write(f_name, r)
            os.chdir(cur_dir)

        print "... done"
Exemple #11
0
def render_cls(cls, all_methods, all_friend_functions):
    """
       Generate the rst page for a class
        
        * cls : node for the classf_name : name of the function
        * doc_methods : ??
    """
   
    cls_doc = cls.processed_doc
    doc_elem = cls_doc.elements
    R= rst_start
    
    # include
    incl = doc_elem.pop('include', '')

    # class header
    fully_qualified_name = CL.fully_qualified_name(cls)
    R +="""
.. _{cls.name_for_label}:

{cls.fully_qualified_name}
{separator}

Defined in header <*{incl}*>

.. code-block:: c

    {templ_synop} class {cls.spelling}

{cls_doc.brief_doc}

{cls_doc.doc}
    """.format(cls = cls, incl = incl.strip(), separator = '=' * (len(cls.fully_qualified_name)), templ_synop = make_synopsis_template_decl(cls), cls_doc = cls_doc)

    # 
    R += cls_doc.doc
    if 'tparam' in doc_elem:    R += render_list(doc_elem.pop('tparam'), 'Template parameters', '-')
    if 'note' in doc_elem :     R += render_note(doc_elem.pop('note'))
    if 'warning' in doc_elem:   R += render_warning(doc_elem.pop('warning'))
    if 'figure' in doc_elem:    R += render_fig(doc_elem.pop('figure'))

    # Members
    if len(cls.members) > 0:
        R += make_header('Public members') 
        R += render_table([(t.spelling,t.type.spelling, replace_latex(clean_doc_string(t.raw_comment)) if t.raw_comment else '') for t in cls.members])

    # Usings 
    if len(cls.usings) > 0:
        R += make_header('Member types') 
        R += render_table([(t.spelling, t.underlying_typedef_type.spelling, replace_latex(clean_doc_string(t.raw_comment)) if t.raw_comment else '') for t in cls.usings])

    # A table for all member functions and all friend functions
    def group_of_overload(f_list): 
        s = set(f.processed_doc.elements['group'] for f in f_list if 'group' in f.processed_doc.elements)
        assert len(s) < 2, "Can not have different group for various overload"
        return s.pop if s else ''
   
    def make_func_list(all_f, header_name):
        if not all_f : return ''
        R = make_header(header_name)
        
        # Regroup the function by sub category
        D = OrderedDict()
        for name, flist in all_f.items():
            cat =flist[0].processed_doc.elements.get('category', None) 
            D.setdefault(cat, list()).append((":ref:`%s <%s>`"%(escape_lg(name),make_label(cls.name + '_' + name)), flist[0].processed_doc.brief_doc))
        
        # Make the sub lists
        for cat, list_table_args in D.items() : 
            if cat : R += make_header(cat, '~')
            R += render_table(list_table_args)
        
        # the hidden toctree is not regrouped
        R += toctree_hidden
        for f_name in all_f:
           R += "    {cls_name}/{f_name}\n".format(cls_name = replace_ltgt(cls.name), f_name = f_name)
        return R

    R += make_func_list(all_methods, 'Member functions')
    R += make_func_list(all_friend_functions, 'Non Member functions')

    # Example
    if 'example' in doc_elem: R += render_example(doc_elem.pop('example'))
    
    return R
Exemple #12
0
def render_fnt(parent_class, f_name, f_overloads):
    """
       Generate the rst page for a function
        
        * f_name : name of the function
        * overload_docs : ??
        * parent_class : None or the parent class if it is a method
        * f_overloads : a list of WHAT ?
    """
    # Start of the page
    R = rst_start
    
    # tag and name of the class
    parent_cls_name_fully_qualified = (CL.fully_qualified_name(parent_class) + "::") if parent_class else ""
    parent_cls_name = (parent_class.name + '_') if parent_class else '' 
    f_name_full = parent_cls_name_fully_qualified + f_name
    
    R += """
.. _{class_rst_ref}:

{f_name_full}
""".format(f_name_full = f_name_full, class_rst_ref = make_label(parent_cls_name + f_name))

    R += '=' * (len(f_name_full)+0) + '\n' + """

"""
    # Synopsis
    R += make_synopsis_list(f_overloads) + '\n\n'
     
    # We regroup the overload as in cppreference
   
    def make_unique(topic) :
        rets = set(f.processed_doc.elements.pop(topic, '').strip() for f in f_overloads)
        rets = list(x for x in rets if x)
        if len(rets)> 1: print "Warning : Multiple documentation of %s across overloads. Picking first one"%topic
        return rets[0] if rets else ''
   
    def make_unique_list(topic) : 
        D = OrderedDict()
        for n, f in enumerate(f_overloads):
           plist = f.processed_doc.elements.pop(topic) # p is a string "NAME REST"
           for p in plist : 
               name, desc = (p + '   ').split(' ',1)
               if name not in D:
                   D[name] = desc.strip()
               else:
                   if D[name] != desc.strip() : 
                       print "Warning : multiple definition of parameter %s at overload %s"%(name, n)
        return D

    def render_dict(d, header, char):
        """ 
           Make rst code for a list of items with  a header
           It splits the first word in a separate column
        """
        if not d: return ''
        head = make_header(header, char) if header else ''
        return head + '\n'.join(" * **%s**: %s\n"%(k.strip(),v) for (k,v) in d.items())

    has_overload = len(f_overloads)> 1

    # Head doc 
    head = make_unique('head') or ("Documentation" if has_overload else '')
    R += '%s\n\n'%head 

    # The piece of doc which is overload dependent
    for num, f in enumerate(f_overloads):
        pd =  f.processed_doc
        num_s =  '**%s)**  '%(num+1) if has_overload else '' 
        if pd.doc : R +=  '\n\n %s %s\n '%(num_s,  pd.doc)+ '\n'

    # Tail doc 
    R += '%s\n\n' %make_unique('tail') 

    # tparam and param
    tparam_dict = make_unique_list('tparam')
    param_dict = make_unique_list('param')
    
    R += render_dict(tparam_dict, 'Template parameters', '^')
    R += render_dict(param_dict, 'Parameters','^')
 
    # Returns 
    rets = make_unique("return")
    if rets : R += make_header('Returns', '^') + " * %s"%rets

    # Examples 
    example_file_name = make_unique("example")
    R += render_example(example_file_name.strip())

    # Warning 
    w = make_unique("warning")
    R += render_warning(w)

    return R