Synopsis - Synopsis/Formatters/HTML/Fragments/DeclarationFormatter.py

File: Synopsis/Formatters/HTML/Fragments/DeclarationFormatter.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 ASG
     10from Synopsis.Formatters.HTML.Fragment import Fragment
     11from Synopsis.Formatters.HTML.Tags import *
     12from SourceLinker import SourceLinker
     13from XRefLinker import XRefLinker
     14
     15class DeclarationFormatter(Fragment):
     16    """Base class for SummaryFormatter and DetailFormatter.
     17
     18    The two classes SummaryFormatter and DetailFormatter are actually
     19    very similar in operation, and so most of their methods are defined here.
     20    Both of them print out the definition of the declarations, including type,
     21    parameters, etc. Some things such as exception specifications are only
     22    printed out in the detailed version.
     23    """
     24
     25    def register(self, formatter):
     26
     27        super(DeclarationFormatter, self).register(formatter)
     28        if self.processor.has_view('XRef'):
     29            self.xref = XRefLinker()
     30            self.xref.register(formatter)
     31        else:
     32            self.xref = None
     33        if self.processor.has_view('Source'):
     34            self.source = SourceLinker()
     35            self.source.register(formatter)
     36        else:
     37            self.source = None
     38
     39    def format_parameters(self, parameters):
     40        """Returns formatted string for the given parameter list."""
     41
     42        return ', '.join([self.format_parameter(p) for p in parameters])
     43
     44    def format_declaration(self, decl):
     45        """The default is to return no type and just the declarations name for
     46        the name."""
     47
     48        return div('synopsis', self.label(decl.name))
     49
     50    def format_macro(self, decl):
     51        """"""
     52
     53        chunk = div('synopsis', self.label(decl.name))
     54        if self.xref: chunk += ' %s'%div('xref', self.xref.format_macro(decl))
     55        if self.source: chunk += ' %s'%div('source', self.source.format_macro(decl))
     56        return chunk
     57
     58    def format_forward(self, decl):
     59
     60        # treat template syntax like a premodifier
     61        if decl.template:
     62            templ = 'template &lt;%s&gt;'%(self.format_parameters(decl.template.parameters),)
     63            templ = div('template', templ)
     64            type = '%s %s'%(templ, decl.type)
     65        else:
     66            type = decl.type
     67
     68        if decl.specializations:
     69            # Treat it like a (non-forward declared) class template.
     70            name  = self.format_scope(decl)
     71        else:
     72            name = self.label(decl.name)
     73        chunk = div('synopsis', type + ' ' + name)
     74        if self.xref: chunk += ' %s'%div('xref', self.xref.format_forward(decl))
     75        if self.source: chunk += ' %s'%div('source', self.source.format_forward(decl))
     76        return chunk
     77
     78    def format_group(self, decl):
     79
     80        return ''
     81
     82    def format_scope(self, decl):
     83        """Scopes have their own views, so return a reference to it."""
     84
     85        name = decl.name
     86        link = rel(self.formatter.filename(),
     87                   self.directory_layout.scope(name))
     88        return href(link, escape(name[-1]))
     89
     90    def format_module(self, decl):
     91
     92        return self.format_scope(decl)
     93
     94    def format_meta_module(self, decl):
     95
     96        return self.format_module(decl)
     97
     98    def format_class(self, decl):
     99
    100        chunk = div('synopsis', decl.type + ' ' + self.format_scope(decl))
    101        if self.xref: chunk += ' %s'%div('xref', self.xref.format_class(decl))
    102        if self.source: chunk += ' %s'%div('source', self.source.format_class(decl))
    103        return chunk
    104
    105    def format_class_template(self, decl):
    106
    107        # treat template syntax like a premodifier
    108        if decl.template:
    109            templ = 'template &lt;%s&gt;'%(self.format_parameters(decl.template.parameters),)
    110            templ = div('template', templ)
    111            type = '%s %s'%(templ, decl.type)
    112
    113        name  = self.format_scope(decl)
    114        chunk = div('synopsis', type + ' ' + name)
    115        if self.xref: chunk += ' %s'%div('xref', self.xref.format_class(decl))
    116        if self.source: chunk += ' %s'%div('source', self.source.format_class(decl))
    117        return chunk
    118
    119
    120    def format_typedef(self, decl):
    121        "(typedef type, typedef name)"
    122
    123        type = self.format_type(decl.alias)
    124        chunk = '%s'%div('synopsis', type + ' ' + self.label(decl.name))
    125        if self.xref: chunk += ' %s'%div('xref', self.xref.format_class(decl))
    126        if self.source: chunk += ' %s'%div('source', self.source.format_class(decl))
    127        return chunk
    128
    129    def format_enumerator(self, decl):
    130        """This is only called by formatEnum"""
    131
    132        self.format_declaration(decl)
    133
    134    def format_enum(self, decl):
    135        "(enum name, list of enumerator names)"
    136
    137        type = self.label(decl.name)
    138        name = ', '.join([e.name[-1] for e in decl.enumerators])
    139        chunk = '%s'%div('synopsis', type + ' ' + name)
    140        if self.xref: chunk += ' %s'%div('xref', self.xref.format_class(decl))
    141        if self.source: chunk += ' %s'%div('source', self.source.format_class(decl))
    142        return chunk
    143
    144    def format_variable(self, decl):
    145
    146        # TODO: deal with sizes
    147        type = self.format_type(decl.vtype)
    148        chunk = '%s'%div('synopsis', type + ' ' + self.label(decl.name))
    149        if self.xref: chunk += ' %s'%div('xref', self.xref.format_class(decl))
    150        if self.source: chunk += ' %s'%div('source', self.source.format_class(decl))
    151        return chunk
    152
    153    def format_const(self, decl):
    154        "(const type, const name = const value)"
    155
    156        type = self.format_type(decl.ctype)
    157        name = self.label(decl.name) + " = " + escape(decl.value)
    158        chunk = '%s'%div('synopsis', type + ' ' + name)
    159        if self.xref: chunk += ' %s'%div('xref', self.xref.format_class(decl))
    160        if self.source: chunk += ' %s'%div('source', self.source.format_class(decl))
    161        return chunk
    162
    163    def format_function(self, decl):
    164        "(return type, func + params + exceptions)"
    165
    166        premod = self.format_modifiers(decl.premodifier)
    167        type = self.format_type(decl.return_type)
    168        name = self.label(decl.name, decl.real_name)
    169        # Special C++ functions  TODO: maybe move to a separate ASG formatter...
    170        if decl.file.annotations['language'] == 'C++' and len(decl.real_name)>1:
    171            lt = decl.real_name[-2].find('<') # check whether this is a template
    172            sname = lt == -1 and decl.real_name[-2] or decl.real_name[-2][:lt]
    173            if decl.real_name[-1] == sname: type = '<i>constructor</i>'
    174            elif decl.real_name[-1] == '~'+sname: type = '<i>destructor</i>'
    175            elif decl.real_name[-1] == '(conversion)': name = '(%s)'%type
    176        params = self.format_parameters(decl.parameters)
    177        postmod = self.format_modifiers(decl.postmodifier)
    178        raises = self.format_exceptions(decl)
    179        # prepend the type by the premodifier(s)
    180        type = '%s %s'%(premod,type)
    181        # Prevent linebreaks on shorter lines
    182        if len(type) < 60:
    183            type = replace_spaces(type)
    184        if decl.type == 'attribute': name = '%s %s %s'%(name, postmod, raises)
    185        else: name = '%s(%s) %s %s'%(name, params, postmod, raises)
    186
    187        chunk = '%s'%div('synopsis', type + ' ' + name)
    188        if self.xref: chunk += ' %s'%div('xref', self.xref.format_class(decl))
    189        if self.source: chunk += ' %s'%div('source', self.source.format_class(decl))
    190
    191        return chunk
    192
    193    def format_function_template(self, decl):
    194        "(return type, func + params + exceptions)"
    195
    196        premod = self.format_modifiers(decl.premodifier)
    197        type = self.format_type(decl.return_type)
    198        name = self.label(decl.name, decl.real_name)
    199        # Special C++ functions  TODO: maybe move to a separate ASG formatter...
    200        if decl.file.annotations['language'] == 'C++' and len(decl.real_name)>1:
    201            lt = decl.real_name[-2].find('<') # check whether this is a template
    202            sname = lt == -1 and decl.real_name[-2] or decl.real_name[-2][:lt]
    203            if decl.real_name[-1] == sname: type = '<i>constructor</i>'
    204            elif decl.real_name[-1] == '~'+sname: type = '<i>destructor</i>'
    205            elif decl.real_name[-1] == '(conversion)': name = '(%s)'%type
    206        params = self.format_parameters(decl.parameters)
    207        postmod = self.format_modifiers(decl.postmodifier)
    208        raises = self.format_exceptions(decl)
    209        # prepend the type by the premodifier(s)
    210        type = '%s %s'%(premod,type)
    211        # Prevent linebreaks on shorter lines
    212        if len(type) < 60:
    213            type = replace_spaces(type)
    214        if decl.type == 'attribute': name = '%s %s %s'%(name, postmod, raises)
    215        else: name = '%s(%s) %s %s'%(name, params, postmod, raises)
    216        # treat template syntax like a premodifier
    217        if decl.template:
    218            templ = 'template &lt;%s&gt;'%(self.format_parameters(decl.template.parameters),)
    219            templ = div('template', templ)
    220            type = '%s %s'%(templ, type)
    221
    222        chunk = '%s'%div('synopsis', type + ' ' + name)
    223        if self.xref: chunk += ' %s'%div('xref', self.xref.format_class(decl))
    224        if self.source: chunk += ' %s'%div('source', self.source.format_class(decl))
    225
    226        return chunk
    227
    228    def format_operation(self, decl):
    229
    230        # Default operation is same as function, and quickest way is to assign:
    231        return self.format_function(decl)
    232
    233    def format_operation_template(self, decl):
    234
    235        # Default operation is same as function, and quickest way is to assign:
    236        return self.format_function_template(decl)
    237
    238    def format_parameter(self, parameter):
    239        """Returns one string for the given parameter"""
    240
    241        text = []
    242        # Premodifiers
    243        text.extend([span('keyword', escape(m)) for m in parameter.premodifier])
    244        # Param Type
    245        id_holder = [parameter.name]
    246        typestr = self.format_type(parameter.type, id_holder)
    247        if typestr: text.append(typestr)
    248        # Postmodifiers
    249        text.extend([span('keyword', escape(m)) for m in parameter.postmodifier])
    250        # Param name
    251        if id_holder and len(parameter.name) != 0:
    252            text.append(span('variable', escape(parameter.name)))
    253        # Param value
    254        if len(parameter.value) != 0:
    255            text.append('= %s'%span('value', escape(parameter.value)))
    256        return ' '.join(text)
    257
    258
    259class DeclarationSummaryFormatter(DeclarationFormatter):
    260    """Derives from BaseStrategy to provide summary-specific methods.
    261    Currently the only one is format_exceptions"""
    262
    263    def format_exceptions(self, oper):
    264        """Returns a reference to the detail if there are any exceptions."""
    265
    266        if len(oper.exceptions):
    267            return self.reference(oper.name, ' raises')
    268        return ''
    269
    270
    271class DeclarationDetailFormatter(DeclarationFormatter):
    272    """Provide detail-specific Declaration formatting."""
    273
    274    def format_exceptions(self, oper):
    275        """Prints out the full exception spec"""
    276
    277        if len(oper.exceptions):
    278            raises = span('keyword', 'raises')
    279            exceptions = []
    280            for exception in oper.exceptions:
    281                exceptions.append(self.reference(exception.name))
    282            exceptions = span('raises', ', '.join(exceptions))
    283            return '%s (%s)'%(raises, exceptions)
    284        else:
    285            return ''
    286
    287    def format_enum(self, enum):
    288
    289        name = span('keyword', 'enum') + ' ' + self.label(enum.name)
    290        enumors = ''.join([self.format_enumerator(e) for e in enum.enumerators])
    291        return name + div('enum', enumors)
    292
    293    def format_enumerator(self, enumerator):
    294
    295        text = self.label(enumerator.name)
    296        if len(enumerator.value):
    297            value = ' = ' + span('value', escape(enumerator.value))
    298        else:
    299            value = ''
    300        doc = self.processor.documentation.details(enumerator, self.view)
    301        return div('enumerator','%s%s%s'%(text, value, doc))
    302

Generated on Thu Apr 16 16:27:16 2009 by
synopsis (version devel)