Synopsis - Synopsis/DeclarationSorter.py

File: Synopsis/DeclarationSorter.py

      1#
      2# Copyright (C) 2007 Stefan Seefeld
      3# All rights reserved.
      4# Licensed to the public under the terms of the GNU LGPL (>= 2),
      5# see the file COPYING for details.
      6#
      7
      8from Synopsis.Processor import Parametrized, Parameter
      9from Synopsis import ASG
     10
     11# The names of the access specifiers
     12_access_specs = {ASG.DEFAULT: '',
     13                 ASG.PUBLIC: 'Public ',
     14                 ASG.PROTECTED: 'Protected ',
     15                 ASG.PRIVATE: 'Private '}
     16
     17# The predefined order for section names
     18_section_order = ('Packages',
     19                  'Modules',
     20                  'Namespaces',
     21                  'Macros',
     22                  'Class templates',
     23                  'Classes',
     24                  'Interfaces',
     25                  'Typedefs',
     26                  'Structs',
     27                  'Enums',
     28                  'Unions',
     29                  'Member function templates',
     30                  'Member functions',
     31                  'Function templates',
     32                  'Functions')
     33
     34def _compare(a, b):
     35    """Compare two section names."""
     36
     37    ai, bi = 0, 0
     38    an, bn = a, b
     39    for i in range(1,4):
     40        access = _access_specs[i]
     41        len_access = len(access)
     42        is_a = (a[:len_access] == access)
     43        is_b = (b[:len_access] == access)
     44        if is_a:
     45            if not is_b: return -1 # a before b
     46            # Both matched
     47            an = a[len_access:]
     48            bn = b[len_access:]
     49            break
     50        if is_b:
     51            return 1 # b before a
     52        # Neither matched
     53    # Same access, sort by predefined order
     54    for section in _section_order:
     55        if an == section: return -1 # a before b
     56        if bn == section: return 1 # b before a
     57    return 0
     58
     59
     60class DeclarationSorter(Parametrized, ASG.Visitor):
     61    """Sort declarations by type and accessibility."""
     62
     63    struct_as_class = Parameter(False, 'Fuse structs and classes into the same section.')
     64    group_as_section = Parameter(True, 'Map group to section, instead of keeping it as a single declaration.')
     65
     66    def __init__(self, declarations = None, **args):
     67
     68        super(DeclarationSorter, self).__init__(**args)
     69        self.__sections = {}
     70        self.__sorted_keys = []
     71        if not declarations: # This is a prototype
     72            return
     73        for d in declarations:
     74            d.accept(self)
     75        self.__sorted_keys = self.__sections.keys()
     76        self.__sorted_keys.sort(_compare)
     77
     78    def __iter__(self): return iter(self.__sorted_keys)
     79    def __getitem__(self, i): return self.__sections[i]
     80    def get(self, *args): return self.__sections.get(*args)
     81    def has_key(self, k): return self.__sections.haskey(k)
     82    def keys(self): return self.__sorted_keys
     83    def values(self): return self.__sections.values()
     84
     85    def _section_of(self, decl, name = None):
     86        """Generate a section name for the given declaration."""
     87
     88        section = name or decl.type.capitalize()
     89        if self.struct_as_class and section == 'Struct':
     90            section = 'Class'
     91        if section[-1] == 's': section += 'es'
     92        else: section += 's'
     93        if decl.accessibility != ASG.DEFAULT:
     94            section = _access_specs[decl.accessibility] + section
     95        return section
     96
     97
     98    def _add_declaration(self, decl, section):
     99        "Adds the given declaration with given name and section."
    100
    101        if section not in self.__sections:
    102            self.__sections[section] = [decl]
    103        else:
    104            self.__sections[section].append(decl)
    105
    106
    107    def visit_declaration(self, decl):
    108        self._add_declaration(decl, self._section_of(decl))
    109
    110    def visit_builtin(self, decl): pass
    111    def visit_macro(self, decl):
    112        self._add_declaration(decl, self._section_of(decl, 'Macro'))
    113    def visit_forward(self, decl):
    114        if decl.template:
    115            self.visit_class_template(decl)
    116        else:
    117            self.visit_declaration(decl)
    118    def visit_group(self, group):
    119        if self.group_as_section:
    120            section = group.name[-1]
    121            for d in group.declarations:
    122                self._add_declaration(d, section)
    123        else:
    124            self.visit_declaration(group)
    125    def visit_scope(self, decl):
    126        self.visit_declaration(decl)
    127    def visit_class_template(self, decl):
    128        self._add_declaration(decl, self._section_of(decl, 'Class template'))
    129    def visit_function(self, decl):
    130        self.visit_declaration(decl)
    131    def visit_function_template(self, decl):
    132        self._add_declaration(decl, self._section_of(decl, 'Function template'))
    133

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