Synopsis - Synopsis/Formatters/HTML/Part.py

File: Synopsis/Formatters/HTML/Part.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
      9"""ASG Formatting classes.
     10
     11This module contains classes for formatting parts of a scope view (class,
     12module, etc with methods, variables etc. The actual formatting of the
     13declarations is delegated to multiple strategies for each part of the view,
     14and are defined in the FormatStrategy module.
     15"""
     16
     17from Synopsis.Processor import Parametrized, Parameter
     18from Synopsis import ASG
     19from Fragment import Fragment
     20import Tags # need both because otherwise 'Tags.name' would be ambiguous
     21from Tags import *
     22
     23class Part(Parametrized, ASG.Visitor):
     24    """Base class for formatting a Part of a Scope View.
     25
     26    This class contains functionality for modularly formatting an ASG node and
     27    its children for display. It is typically used to construct Heading,
     28    Summary and Detail formatters. Strategy objects are added according to
     29    configuration, and this base class  then checks which format methods each
     30    strategy implements. For each ASG declaration visited, the Part asks all
     31    Strategies which implement the appropriate format method to generate
     32    output for that declaration. The final writing of the formatted html is
     33    delegated to the write_section_start, write_section_end, and write_section_item
     34    methods, which must be implemented in a subclass.
     35    """
     36
     37    fragments = Parameter([], "list of Fragments")
     38
     39    def register(self, view):
     40
     41        self.processor = view.processor
     42        self.__view = view
     43        self.__fragments = []
     44        self.__id_holder = None
     45        # Lists of format methods for each ASG type
     46        self.__formatdict = {'format_declaration':[],
     47                             'format_macro':[],
     48                             'format_forward':[],
     49                             'format_group':[],
     50                             'format_scope':[],
     51                             'format_module':[],
     52                             'format_meta_module':[],
     53                             'format_class':[],
     54                             'format_class_template':[],
     55                             'format_typedef':[],
     56                             'format_enum':[],
     57                             'format_variable':[],
     58                             'format_const':[],
     59                             'format_function':[],
     60                             'format_function_template':[],
     61                             'format_operation':[],
     62                             'format_operation_template':[]}
     63
     64        for fragment in self.fragments:
     65            fragment.register(self)
     66            for method in self.__formatdict.keys():
     67                no_func = getattr(Fragment, method).im_func
     68                method_obj = getattr(fragment, method)
     69                # If it was overridden in fragment
     70                if method_obj.im_func is not no_func:
     71                    # Add to the dictionary
     72                    self.__formatdict[method].append(method_obj)
     73
     74    def view(self): return self.__view
     75    def filename(self): return self.__view.filename()
     76    def os(self): return self.__view.os()
     77    def scope(self): return self.__view.scope()
     78    def write(self, text): self.os().write(text)
     79
     80    # Access to generated values
     81    def type_ref(self): return self.__type_ref
     82    def type_label(self): return self.__type_label
     83    def declarator(self): return self.__declarator
     84    def parameter(self): return self.__parameter
     85
     86    def reference(self, name, label=None, **keys):
     87        """Returns a reference to the given name. The name is a scoped name,
     88        and the optional label is an alternative name to use as the link text.
     89        The name is looked up in the TOC so the link may not be local. The
     90        optional keys are appended as attributes to the A tag."""
     91
     92        if not label: label = escape(str(self.scope().prune(name)))
     93        entry = self.processor.toc[name]
     94        if entry: return href(rel(self.filename(), entry.link), label, **keys)
     95        else: return label or ''
     96
     97    def label(self, name, label=None):
     98        """Create a label for the given name. The label is an anchor so it can
     99        be referenced by other links. The name of the label is derived by
    100        looking up the name in the TOC and using the link in the TOC entry.
    101        The optional label is an alternative name to use as the displayed
    102        name. If the name is not found in the TOC then the name is not
    103        anchored and just label is returned (or name if no label is given).
    104        """
    105
    106        if label is None: label = name
    107        # some labels are templates with <>'s
    108        entry = self.processor.toc[name]
    109        label = escape(str(self.scope().prune(label)))
    110        if entry is None: return label
    111        location = entry.link
    112        index = location.find('#')
    113        if index >= 0: location = location[index+1:]
    114        return location and Tags.name(location, label) or label
    115
    116
    117    def format_declaration(self, decl, method):
    118        """Format decl using named method of each fragment. Each fragment
    119        returns two strings - type and name. All the types are joined and all
    120        the names are joined separately. The consolidated type and name
    121        strings are then passed to write_section_item."""
    122
    123        type_name = [f(decl) for f in self.__formatdict[method]]
    124        if type_name:
    125            text = ' '.join(type_name).strip()
    126            self.write_section_item(text)
    127
    128    def process(self, decl):
    129        """Formats the given decl, creating the output for this Part of the
    130        view. This method is implemented in various subclasses in different
    131        ways, for example Summary and Detail iterate through the children of
    132        'decl' section by section, whereas Heading only formats decl itself.
    133        """
    134
    135        pass
    136
    137    #################### ASG Visitor ############################################
    138    def visit_declaration(self, decl): self.format_declaration(decl, 'format_declaration')
    139    def visit_macro(self, decl): self.format_declaration(decl, 'format_macro')
    140    def visit_forward(self, decl): self.format_declaration(decl, 'format_forward')
    141    def visit_group(self, decl): self.format_declaration(decl, 'format_group')
    142    def visit_scope(self, decl): self.format_declaration(decl, 'format_scope')
    143    def visit_module(self, decl): self.format_declaration(decl, 'format_module')
    144    def visit_meta_module(self, decl): self.format_declaration(decl, 'format_meta_module')
    145    def visit_class(self, decl): self.format_declaration(decl, 'format_class')
    146    def visit_class_template(self, decl): self.format_declaration(decl, 'format_class_template')
    147    def visit_typedef(self, decl): self.format_declaration(decl, 'format_typedef')
    148    def visit_enum(self, decl): self.format_declaration(decl, 'format_enum')
    149    def visit_variable(self, decl): self.format_declaration(decl, 'format_variable')
    150    def visit_const(self, decl): self.format_declaration(decl, 'format_const')
    151    def visit_function(self, decl): self.format_declaration(decl, 'format_function')
    152    def visit_function_template(self, decl): self.format_declaration(decl, 'format_function_template')
    153    def visit_operation(self, decl): self.format_declaration(decl, 'format_operation')
    154    def visit_operation_template(self, decl): self.format_declaration(decl, 'format_operation_template')
    155
    156
    157    #################### Type Formatter/Visitor #################################
    158    def format_type(self, typeObj, id_holder = None):
    159        "Returns a reference string for the given type object"
    160
    161        if typeObj is None: return "(unknown)"
    162        if id_holder:
    163            save_id = self.__id_holder
    164            self.__id_holder = id_holder
    165        typeObj.accept(self)
    166        if id_holder:
    167            self.__id_holder = save_id
    168        return self.__type_label
    169
    170    def visit_builtin_type_id(self, type):
    171        "Sets the label to be a reference to the type's name"
    172
    173        self.__type_label = self.reference(type.name)
    174
    175    def visit_unknown_type_id(self, type):
    176        "Sets the label to be a reference to the type's link"
    177
    178        self.__type_label = self.reference(type.link)
    179
    180    def visit_declared_type_id(self, type):
    181        "Sets the label to be a reference to the type's name"
    182
    183        self.__type_label = self.reference(type.name)
    184
    185    def visit_dependent_type_id(self, type):
    186        "Sets the label to be the type's name (which has no proper scope)"
    187
    188        self.__type_label = type.name[-1]
    189
    190    def visit_modifier_type_id(self, type):
    191        "Adds modifiers to the formatted label of the modifier's alias"
    192
    193        alias = self.format_type(type.alias)
    194        def amp(x):
    195            if x == '&': return '&amp;'
    196            return x
    197        pre = ''.join(['%s&#160;'%amp(x) for x in type.premod])
    198        post = ''.join([amp(x) for x in type.postmod])
    199        self.__type_label = "%s%s%s"%(pre,alias,post)
    200
    201    def visit_parametrized_type_id(self, type):
    202        "Adds the parameters to the template name in angle brackets"
    203
    204        if type.template:
    205            type_label = self.reference(type.template.name)
    206        else:
    207            type_label = "(unknown)"
    208        parameters = [self.format_type(p) for p in type.parameters]
    209        self.__type_label = "%s&lt;%s&gt;"%(type_label,', '.join(parameters))
    210
    211    def visit_template_id(self, type):
    212        "Labs the template with the parameters"
    213
    214        self.__type_label = "template&lt;%s&gt;"%','.join(['typename %s'%self.format_type(p)
    215                                                           for p in type.parameters])
    216
    217    def visit_function_type_id(self, type):
    218        "Labels the function type with return type, name and parameters"
    219
    220        ret = self.format_type(type.return_type)
    221        params = map(self.format_type, type.parameters)
    222        pre = ''.join(type.premod)
    223        if self.__id_holder:
    224            ident = self.__id_holder[0]
    225            del self.__id_holder[0]
    226        else:
    227            ident = ''
    228        self.__type_label = "%s(%s%s)(%s)"%(ret,pre,ident,', '.join(params))
    229
    230
    231    # These are overridden in {Summary,Detail}Formatter
    232    def write_start(self):
    233        "Abstract method to start the output, eg table headings"
    234
    235        self.write('<!-- this part was generated by ' + self.__class__.__name__ + ' -->\n')
    236
    237    def write_section_start(self, heading):
    238        "Abstract method to start a section of declaration types"
    239
    240        pass
    241
    242    def write_section_end(self, heading):
    243        "Abstract method to end a section of declaration types"
    244
    245        pass
    246
    247    def write_section_item(self, text):
    248        "Abstract method to write the output of one formatted declaration"
    249
    250        pass
    251
    252    def write_end(self):
    253        "Abstract method to end the output, eg close the table"
    254
    255        pass
    256

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