File: Synopsis/Formatters/DocBook/Markup/__init__.py 1
2
3
4
5
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 [('&', '&'), ('"', '"'), ('<', '<'), ('>', '>'),]:
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
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
71 symbol = symbol[:-1] + (symbol[-1] + params,)
72
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
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
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)