Ticket #868: doxygen_methods.diff

File doxygen_methods.diff, 8.0 kB (added by dirk@users.sf.net, 2 years ago)

Method link patch

  • doxygentrac.py

    old new  
    6868    encoding = Option('doxygen', 'encoding', 'iso-8859-1', 
    6969      """Default encoding used by the generated documentation files.""") 
    7070 
     71    default_namespace = Option('doxygen', 'default_namespace', '', 
     72      """Default namespace to search for named objects in.""") 
     73 
    7174    SUMMARY_PAGES = """ 
    7275    annotated classes dirs files functions globals hierarchy 
    7376    index inherits main namespaces namespacemembers 
     
    147150                req.hdf['doxygen.wiki_page'] = wiki 
    148151                return 'doxygen.cs', 'text/html' 
    149152            # use configured Doxygen index 
    150             path = os.path.join(self.base_path, self.default_doc, 
    151                                 self.html_output, self.index
     153            req.redirect(os.path.join('trac', 'doxygen', self.default_doc, 
     154                                      self.html_output, self.index)
    152155 
    153156        # view  
    154157        mimetype = mimetypes.guess_type(path)[0] 
     
    224227            if action == 'search': 
    225228                return html.a(label, title=params, class_='missing', 
    226229                              href=formatter.href.doxygen()) 
     230            if action == 'anchor': 
     231                # This is a hack!!! It ignore multiple projects/docsdirs, and it shouldn't 
     232                # create the HTML explicitly 
     233                return '<a href="%s/%s/%s" title="%s">%s</a>' % (formatter.href.base, "doxygen", link, params[1:], params[1:]) 
    227234            else: 
    228235                return html.a(label, title=params, 
    229236                              href=formatter.href.doxygen(link, path=path)) 
    230237        yield ('doxygen', doxygen_link) 
     238        yield ('dox', doxygen_link) 
    231239 
    232240    def get_wiki_syntax(self): 
    233241        return [] 
     
    267275                                            path+" (not found)")) 
    268276            return existing_path, link 
    269277 
     278        # do doxygen-style name->file mapping 
     279        # this is a little different than doxygen, but I don't see another 
     280        # way to make doxygen:Type<bool> links work, as it inserts a ' ' (or 
     281        # '_01') after/before the type name. 
     282 
     283        doxygen_file_map = { '_':'__', ':':'_1', '/':'_2', '<':'_3_01', '>':'_01_4', \ 
     284                             '*':'_5', '&':'_6', '|':'_7', '.':'_8', '!':'_9', \ 
     285                             ',':'_00',' ':'_01' } 
     286 
     287        re_name_map = { '+':'\\+', '*':'\\*', '(':'\\(', ')':'\\)', '[':'\\[', ']':'\\]', ' ':'' } 
     288 
     289        space_map = {' ':'' } 
     290 
     291        def map_string(str, map): 
     292            if str == None: 
     293                return None 
     294            mangledstring = '' 
     295            for i in str: 
     296                if i in map.keys(): 
     297                    mangledstring += map[i] 
     298                else: 
     299                    mangledstring += i 
     300 
     301            return mangledstring 
     302 
     303        # Mangle doxygen arguments from WikiLink format to doxygen format 
     304        def mangle_doxygen_args(args): 
     305            charmap = { '<':'&lt; ',  '>':' &gt;',  '&':'&amp;'} 
     306            spaceargs = re.sub('%20', ' ', args) 
     307            mangledargs = '' 
     308            for i in spaceargs: 
     309                if i in charmap.keys(): 
     310                    mangledargs += charmap[i] 
     311                else: 
     312                    mangledargs += i 
     313 
     314            return mangledargs 
     315 
    270316        self.log.debug('Looking up "%s" in documentation "%s"' % (file, doc)) 
    271317 
    272318        # Direct request for searching 
     
    275321 
    276322        # Request for a documentation file. 
    277323        doc_ext_re = '|'.join(self.ext.split(' ')) 
    278         if re.match(r'''^(.*)[.](%s)''' % doc_ext_re, file): 
    279             path, link = lookup(file, 'documentation') 
     324        m = re.match(r'''(^.*[.](?:%s))(#.*)?$''' % doc_ext_re, file) 
     325        if m != None: 
     326            if m.groups()[1] == None: # No anchor  
     327                path, link = lookup(file, 'documentation') 
     328            else: 
     329                path, link = lookup(m.groups()[0], 'documentation') 
     330                link += m.groups()[1] 
    280331            if path: 
    281332                return 'view', path, link 
    282333            else: 
     
    305356        #  - do something about dirs 
    306357        #  - expand with enum, defs, etc. 
    307358        #  - this doesn't work well with the CREATE_SUBDIRS Doxygen option 
    308         path, link = lookup('class%s.html' % file, 'class') 
     359 
     360        mangledfile = map_string(file, doxygen_file_map) 
     361 
     362        path, link = lookup('class%s.html' % mangledfile, 'class') 
    309363        if not path: 
    310             path, link = lookup('struct%s.html' % file, 'struct') 
     364            path, link = lookup('struct%s.html' % mangledfile, 'struct') 
    311365        if path: 
    312366            return 'view', path, link 
    313367 
     368        # Try in the default_namespace 
     369        if self.default_namespace != "": 
     370            dnmangledfile = self.default_namespace + '_1_1' + mangledfile 
     371            path, link = lookup('class%s.html' % dnmangledfile, 'class') 
     372            if not path: 
     373                path, link = lookup('struct%s.html' % dnmangledfile, 'struct') 
     374            if path: 
     375                return 'view', path, link 
     376 
     377        # Could have a method attached to the classname... 
     378        # Remove the last ::XXX segment and try again 
     379        method_re = '::([^:]*)$' 
     380        nmfile = re.sub(method_re, "", file); 
     381 
     382        mangledfile = map_string(nmfile, doxygen_file_map) 
     383        namespace = '' 
     384 
     385        path, link = lookup('class%s.html' % mangledfile, 'class') 
     386        if not path: 
     387            path, link = lookup('struct%s.html' % mangledfile, 'struct') 
     388        if not path and self.default_namespace != "": 
     389            # Try in the default_namespace 
     390            namespace = self.default_namespace 
     391            dnmangledfile = self.default_namespace + '_1_1' + mangledfile 
     392            path, link = lookup('class%s.html' % dnmangledfile, 'class') 
     393            if not path: 
     394                path, link = lookup('struct%s.html' % dnmangledfile, 'struct') 
     395 
     396        if path: 
     397            self.log.debug('Found method %s %s' % (path, link)) 
     398            member = re.search(method_re, file).group(1) 
     399            mangledmember = mangle_doxygen_args(member) 
     400            pieces = re.search("([^(]*)(\(([^)]*)\)(.*))?$", mangledmember) 
     401            classname = mangle_doxygen_args(nmfile) 
     402            if namespace != '': 
     403                classname = namespace + '::' + classname 
     404            re_name = map_string(classname + "::" + pieces.groups()[0], re_name_map) 
     405            if pieces.groups()[2] != None: 
     406                re_args = '(%s)%s' % (pieces.groups()[2], pieces.groups()[3]) 
     407                re_args = map_string(re_args, re_name_map) 
     408            else: 
     409                re_args = None 
     410            self.log.debug("re_name = %s, re_args = %s" % (re_name, re_args)) 
     411            fd = open(path) 
     412            filedata = fd.read() 
     413            anchor = None 
     414            anchor_pat='<!-- doxytag: member="([\w:;<>& !=\+\*\-/%]*)" ref="([\w]*)"(?: args="([\w, ()\*\&]*)")?' 
     415            for p in re.finditer(anchor_pat, filedata): 
     416                n = map_string(p.groups()[0], re_name_map) 
     417                #self.log.debug("match: %s %s %s" % (n, p.groups()[1], p.groups()[2])) 
     418                if n != re_name: 
     419                    continue 
     420                if re_args == None: 
     421                    anchor = p.groups()[1] 
     422                    break 
     423                a = map_string(p.groups()[2], re_name_map) 
     424                if a == re_args: 
     425                    anchor = p.groups()[1] 
     426                    break 
     427            if anchor != None: 
     428                link = link + '#' + anchor 
     429                self.log.debug('Found method in %s: %s %s' % (file, path, link)) 
     430                return 'anchor', None, link 
     431 
    314432        # Revert to search... 
    315433        results = self._search_in_documentation(doc, [file]) 
    316         class_ref = file+' Class Reference' 
     434        class_ref = file +' Class Reference' 
    317435        for result in results: 
    318436            self.log.debug('Reverted to search, found: ' + repr(result)) 
    319437            name = result['name']