File: Synopsis/Formatters/HTML/Views/XRef.py
  1#
  2# Copyright (C) 2000 Stephen Davies
  3# Copyright (C) 2000 Stefan Seefeld
  4# All rights reserved.
  5# Licensed to the public under the terms of the GNU LGPL (>= 2),
  6# see the file COPYING for details.
  7#
  8
  9from Synopsis import config
 10from Synopsis.Processor import Parameter
 11from Synopsis import ASG
 12from Synopsis.Formatters.TOC import TOC, Linker
 13from Synopsis.Formatters.HTML.View import View
 14from Synopsis.Formatters.HTML.Tags import *
 15import os, time
 16
 17class XRef(View):
 18    """A module for creating views full of xref infos"""
 19
 20    link_to_scope = Parameter(True, '')
 21
 22    def register(self, frame):
 23
 24        super(XRef, self).register(frame)
 25        self.__filename = None
 26        self.__title = None
 27        self.__toc = TOC(None)
 28
 29        if self.processor.sxr_prefix is None: return
 30
 31        self.icon = 'xref.png'
 32        share = config.datadir
 33        src = os.path.join(share, 'xref.png')
 34        self.directory_layout.copy_file(src, self.icon)
 35
 36        # Add an entry for every xref
 37        for name in self.processor.ir.sxr.keys():
 38            page = self.processor.xref.get(name)
 39            file = self.directory_layout.special('xref%d'%page)
 40            file += '#' + quote_as_id(str(name))
 41            self.__toc.insert(TOC.Entry(name, file, 'C++', 'xref'))
 42
 43    def toc(self, start):
 44
 45        return self.__toc
 46
 47    def filename(self):
 48
 49        return self.__filename
 50
 51    def title(self):
 52
 53        return self.__title
 54
 55    def process(self):
 56
 57        if self.processor.sxr_prefix is None: return
 58
 59        pages = self.processor.xref.pages()
 60        if not pages: return
 61        for p in range(len(pages)):
 62            self.__filename = self.directory_layout.xref(p)
 63
 64            first, last = pages[p][0], pages[p][-1]
 65            self.__title = 'Cross Reference : %s - %s'%(escape(str(first)), escape(str(last)))
 66
 67            self.start_file()
 68            self.write_navigation_bar()
 69            self.write(element('h1', self.title()))
 70            for name in pages[p]:
 71                self.write('<div class="xref-name">')
 72                self.process_name(name)
 73                self.write('</div>')
 74            self.end_file()
 75
 76    def register_filenames(self):
 77        """Registers each view"""
 78
 79        if self.processor.sxr_prefix is None: return
 80
 81        pages = self.processor.xref.pages()
 82        if not pages: return
 83        for p in range(len(pages)):
 84            filename = self.directory_layout.special('xref%d'%p)
 85            self.processor.register_filename(filename, self, p)
 86
 87    def process_link(self, file, line, scope):
 88        """Outputs the info for one link"""
 89
 90        file_link = self.directory_layout.file_source(file)
 91        file_link = rel(self.filename(), file_link) + "#%d"%line
 92        desc = ''
 93        type = self.processor.ir.asg.types.get(scope)
 94        if isinstance(type, ASG.DeclaredTypeId):
 95            desc = ' ' + type.declaration.type
 96        entry = self.processor.toc[scope]
 97        if entry:
 98            label = href(rel(self.filename(), entry.link), escape(str(scope)))
 99        else:
100            label = escape(str(scope))
101        self.write('<li><a href="%s">%s:%s</a>: in%s %s</li>\n'%(
102            file_link, file, line, desc, label))
103
104    def describe_declaration(self, decl):
105        """Returns a description of the declaration. Detects constructors and
106        destructors"""
107
108        name = decl.name
109        if isinstance(decl, ASG.Function) and len(name) > 1:
110            real = decl.real_name[-1]
111            if name[-2] == real:
112                return 'Constructor '
113            elif real[0] == '~' and name[-2] == real[1:]:
114                return 'Destructor '
115        return decl.type.capitalize() + ' '
116
117    def process_name(self, name):
118        """Outputs the info for a given name"""
119
120        entry = self.processor.ir.sxr.get(name)
121        if not entry: return
122        self.write(element('a', '', id=quote_as_id(str(name))))
123        desc = ''
124        decl = None
125        type = self.processor.ir.asg.types.get(name)
126        if isinstance(type, ASG.DeclaredTypeId):
127            decl = type.declaration
128            desc = self.describe_declaration(decl)
129        self.write(element('h2', desc + escape(str(name))) + '<ul>\n')
130
131        if self.link_to_scope:
132            type = self.processor.ir.asg.types.get(name, None)
133            if isinstance(type, ASG.DeclaredTypeId):
134                link = self.directory_layout.link(type.declaration)
135                self.write('<li>'+href(rel(self.__filename, link), 'Documentation')+'</li>')
136        if entry.definitions:
137            self.write('<li>Defined at:\n<ul>\n')
138            for file, line, scope in entry.definitions:
139                self.process_link(file, line, scope)
140            self.write('</ul></li>\n')
141        if entry.calls:
142            self.write('<li>Called from:\n<ul>\n')
143            for file, line, scope in entry.calls:
144                self.process_link(file, line, scope)
145            self.write('</ul></li>\n')
146        if entry.references:
147            self.write('<li>Referenced from:\n<ul>\n')
148            for file, line, scope in entry.references:
149                self.process_link(file, line, scope)
150            self.write('</ul></li>\n')
151        if isinstance(decl, ASG.Scope) and decl.declarations:
152            self.write('<li>Declarations:\n<ul>\n')
153            for child in decl.declarations:
154                if isinstance(child, ASG.Builtin) and child.type == 'EOS':
155                    continue
156                file, line = child.file.name, child.line
157                file_link = self.directory_layout.file_source(file)
158                file_link = rel(self.filename(),file_link) + '#%d'%line
159                file_href = '<a href="%s">%s:%s</a>: '%(file_link,file,line)
160                cname = child.name
161                entry = self.processor.toc[cname]
162                type = self.describe_declaration(child)
163                if entry:
164                    link = href(rel(self.filename(), entry.link), escape(str(name.prune(cname))))
165                    self.write(element('li', file_href + type + link))
166                else:
167                    self.write(element('li', file_href + type + str(name.prune(cname))))
168            self.write('</ul>\n</li>\n')
169        self.write('</ul>\n')
170
171    def end_file(self):
172        """Overrides end_file to provide synopsis logo"""
173
174        self.write('\n')
175        now = time.strftime(r'%c', time.localtime(time.time()))
176        logo = img(src=rel(self.filename(), 'synopsis.png'), alt='logo')
177        logo = href('http://synopsis.fresco.org', logo + ' synopsis', target='_blank')
178        logo += ' (version %s)'%config.version
179        self.write(div('logo', 'Generated on ' + now + ' by \n<br/>\n' + logo))
180        View.end_file(self)
181