Synopsis - Synopsis/Formatters/DocBook/Markup/__init__.py

File: Synopsis/Formatters/DocBook/Markup/__init__.py

      1#
      2# Copyright (C) 2006 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"""Markup formatters."""
      8
      9from Synopsis.Processor import Parametrized, Parameter
     10from Synopsis import ASG
     11from Synopsis.QualifiedName import *
     12import re
     13
     14def escape(text):
     15
     16    for p in [('&', '&amp;'), ('"', '&quot;'), ('<', '&lt;'), ('>', '&gt;'),]:
     17        text = text.replace(*p)
     18    return text
     19
     20class Struct:
     21
     22    def __init__(self, summary = '', details = ''):
     23        self.summary = summary
     24        self.details = details
     25
     26
     27class Formatter(Parametrized):
     28    """Interface class that takes a 'doc' annotation and formats its
     29    text. Markup-specific subclasses should provide appropriate format methods."""
     30
     31    def init(self, processor):
     32
     33        self.processor = processor
     34
     35    def format(self, decl):
     36        """Format the declaration's documentation.
     37        @param view the View to use for references and determining the correct
     38        relative filename.
     39        @param decl the declaration
     40        @returns Struct containing summary / details pair.
     41        """
     42
     43        doc = decl.annotations.get('doc')
     44        text = doc and escape(doc.text) or ''
     45        m = re.match(r'(\s*[\w\W]*?\.)(\s|$)', text)
     46        summary = m and '<para>%s</para>\n'%m.group(1) or ''
     47        if text: text = '<para>%s</para>\n'%text
     48        return Struct(summary, text)
     49
     50    def lookup_symbol(self, symbol, scope):
     51        """Given a symbol and a scope, returns an URL.
     52        Various methods are tried to resolve the symbol. First the
     53        parameters are taken off, then we try to split the symbol using '.' or
     54        '::'. The params are added back, and then we try to match this scoped
     55        name against the current scope. If that fails, then we recursively try
     56        enclosing scopes.
     57        """
     58
     59        # Remove params
     60        index = symbol.find('(')
     61        if index >= 0:
     62            params = symbol[index:]
     63            symbol = symbol[:index]
     64        else:
     65            params = ''
     66        if '.' in symbol:
     67            symbol = QualifiedPythonName(symbol.split('.'))
     68        else:
     69            symbol = QualifiedCxxName(symbol.split('::'))
     70        # Add params back
     71        symbol = symbol[:-1] + (symbol[-1] + params,)
     72        # Find in all scopes
     73        while 1:
     74            entry = self._lookup_symbol_in(symbol, scope)
     75            if entry:
     76                return entry.link
     77            if len(scope) == 0: break
     78            scope = scope[:-1]
     79        # Not found
     80        return None
     81
     82
     83    def _lookup_symbol_in(self, symbol, scope):
     84
     85        paren = symbol[-1].find('(')
     86        if paren != -1:
     87            return self._find_method_entry(symbol[-1], scope + symbol[:-1])
     88        else:
     89            return self.processor.toc.lookup(scope + symbol)
     90
     91
     92    def _find_method_entry(self, name, scope):
     93
     94        try:
     95            scope = self.processor.ir.asg.types[scope]
     96        except KeyError:
     97            return None
     98        if not isinstance(scope, ASG.DeclaredTypeId):
     99            return None
    100        scope = scope.declaration
    101        if not isinstance(scope, ASG.Scope):
    102            return None
    103        # For now disregard parameters during lookup.
    104        name = name[:name.find('(')]
    105        for d in scope.declarations:
    106            if isinstance(d, ASG.Function):
    107                if d.real_name[-1] == name:
    108                    return self.processor.toc.lookup(d.name)
    109        return None
    110

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