File: Part.py

package info (click to toggle)
synopsis 0.8.0-5
  • links: PTS
  • area: main
  • in suites: etch, etch-m68k
  • size: 10,112 kB
  • ctags: 12,996
  • sloc: cpp: 34,254; ansic: 33,620; python: 10,975; sh: 7,261; xml: 6,369; makefile: 773; asm: 445
file content (259 lines) | stat: -rw-r--r-- 10,380 bytes parent folder | download | duplicates (2)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
#
# Copyright (C) 2000 Stephen Davies
# Copyright (C) 2000 Stefan Seefeld
# All rights reserved.
# Licensed to the public under the terms of the GNU LGPL (>= 2),
# see the file COPYING for details.
#

"""AST Formatting classes.

This module contains classes for formatting parts of a scope view (class,
module, etc with methods, variables etc. The actual formatting of the
declarations is delegated to multiple strategies for each part of the view,
and are defined in the FormatStrategy module.
"""

from Synopsis.Processor import Parametrized, Parameter
from Synopsis import AST, Type, Util
from Fragment import Fragment
import Tags # need both because otherwise 'Tags.name' would be ambiguous
from Tags import *

import string, os

class Part(Parametrized, Type.Visitor, AST.Visitor):
   """Base class for formatting a Part of a Scope View.
    
   This class contains functionality for modularly formatting an AST node and
   its children for display. It is typically used to contruct Heading,
   Summary and Detail formatters. Strategy objects are added according to
   configuration, and this base class  then checks which format methods each
   strategy implements. For each AST declaration visited, the Part asks all
   Strategies which implement the appropriate format method to generate
   output for that declaration. The final writing of the formatted html is
   delegated to the write_section_start, write_section_end, and write_section_item
   methods, which myst be implemented in a subclass.
   """

   fragments = Parameter([], "list of Fragments")

   def register(self, view):

      self.processor = view.processor
      self.__view = view
      self.__fragments = []
      self.__id_holder = None
      # Lists of format methods for each AST type
      self.__formatdict = {'format_declaration':[],
                           'format_forward':[],
                           'format_group':[],
                           'format_scope':[],
                           'format_module':[],
                           'format_meta_module':[],
                           'format_class':[],
                           'format_typedef':[],
                           'format_enum':[],
                           'format_variable':[],
                           'format_const':[],
                           'format_function':[],
                           'format_operation':[]}

      # Why not just apply all formatters ? is this an optimization ?
      # ask chalky...
      for fragment in self.fragments:
         fragment.register(self)
         for method in self.__formatdict.keys():
            no_func = getattr(Fragment, method).im_func
            method_obj = getattr(fragment, method)
            # If it was overridden in fragment
            if method_obj.im_func is not no_func:
               # Add to the dictionary
               self.__formatdict[method].append(method_obj)
    
   def view(self): return self.__view
   def filename(self): return self.__view.filename()
   def os(self): return self.__view.os()
   def scope(self): return self.__view.scope()
   def write(self, text): self.os().write(text)

   # Access to generated values
   def type_ref(self): return self.__type_ref
   def type_label(self): return self.__type_label
   def declarator(self): return self.__declarator
   def parameter(self): return self.__parameter
    
   def reference(self, name, label=None, **keys):
      """Returns a reference to the given name. The name is a scoped name,
      and the optional label is an alternative name to use as the link text.
      The name is looked up in the TOC so the link may not be local. The
      optional keys are appended as attributes to the A tag."""

      if not label: label = escape(Util.ccolonName(name, self.scope()))
      entry = self.processor.toc[name]
      if entry: return apply(href, (rel(self.filename(), entry.link), escape(label)), keys)
      return label or ''

   def label(self, name, label=None):
      """Create a label for the given name. The label is an anchor so it can
      be referenced by other links. The name of the label is derived by
      looking up the name in the TOC and using the link in the TOC entry.
      The optional label is an alternative name to use as the displayed
      name. If the name is not found in the TOC then the name is not
      anchored and just label is returned (or name if no label is given).
      """

      if label is None: label = name
      # some labels are templates with <>'s
      entry = self.processor.toc[name]
      label = escape(Util.ccolonName(label, self.scope()))
      if entry is None: return label
      location = entry.link
      index = string.find(location, '#')
      if index >= 0: location = location[index+1:]
      return location and Tags.name(location, label) or label


   def format_declaration(self, decl, method):
      """Format decl using named method of each fragment. Each fragment
      returns two strings - type and name. All the types are joined and all
      the names are joined separately. The consolidated type and name
      strings are then passed to write_section_item."""

      # TODO - investigate quickest way of doing this. I tried.
      # A Lambda that calls the given function with decl
      format = lambda func, decl=decl: func(decl)
      # Get a list of 2tuples [('type','name'),('type','name'),...]
      type_name = map(format, self.__formatdict[method])
      if not len(type_name): return
      # NEW CODE:
      text = string.strip(string.join(type_name))
      self.write_section_item(text)

   def process(self, decl):
      """Formats the given decl, creating the output for this Part of the
      view. This method is implemented in various subclasses in different
      ways, for example Summary and Detail iterate through the children of
      'decl' section by section, whereas Heading only formats decl itself.
      """

      pass
	
   #################### AST Visitor ############################################
   def visitDeclaration(self, decl): self.format_declaration(decl, 'format_declaration')
   def visitForward(self, decl): self.format_declaration(decl, 'format_forward')
   def visitGroup(self, decl): self.format_declaration(decl, 'format_group')
   def visitScope(self, decl): self.format_declaration(decl, 'format_scope')
   def visitModule(self, decl):	self.format_declaration(decl, 'format_module')
   def visitMetaModule(self, decl): self.format_declaration(decl, 'format_meta_module')
   def visitClass(self, decl): self.format_declaration(decl, 'format_class')
   def visitTypedef(self, decl): self.format_declaration(decl, 'format_typedef')
   def visitEnum(self, decl): self.format_declaration(decl, 'format_enum')
   def visitVariable(self, decl): self.format_declaration(decl, 'format_variable')
   def visitConst(self, decl): self.format_declaration(decl, 'format_const')
   def visitFunction(self, decl): self.format_declaration(decl, 'format_function')
   def visitOperation(self, decl): self.format_declaration(decl, 'format_operation')


   #################### Type Formatter/Visitor #################################
   def format_type(self, typeObj, id_holder = None):
      "Returns a reference string for the given type object"

      if typeObj is None: return "(unknown)"
      if id_holder:
         save_id = self.__id_holder
         self.__id_holder = id_holder
      typeObj.accept(self)
      if id_holder:
         self.__id_holder = save_id
      return self.__type_label

   def visitBaseType(self, type):
      "Sets the label to be a reference to the type's name"

      self.__type_label = self.reference(type.name())
        
   def visitUnknown(self, type):
      "Sets the label to be a reference to the type's link"

      self.__type_label = self.reference(type.link())
        
   def visitDeclared(self, type):
      "Sets the label to be a reference to the type's name"

      self.__type_label = self.reference(type.name())

   def visitDependent(self, type):
      "Sets the label to be the type's name (which has no proper scope)"

      self.__type_label = type.name()[-1]
        
   def visitModifier(self, type):
      "Adds modifiers to the formatted label of the modifier's alias"

      alias = self.format_type(type.alias())
      def amp(x):
         if x == '&': return '&amp;'
         return x
      pre = string.join(map(lambda x:x+"&#160;", map(amp, type.premod())), '')
      post = string.join(map(amp, type.postmod()), '')
      self.__type_label = "%s%s%s"%(pre,alias,post)
            
   def visitParametrized(self, type):
      "Adds the parameters to the template name in angle brackets"

      if type.template():
         type_label = self.reference(type.template().name())
      else:
         type_label = "(unknown)"
      params = map(self.format_type, type.parameters())
      self.__type_label = "%s&lt;%s&gt;"%(type_label,string.join(params, ", "))

   def visitTemplate(self, type):
      "Labs the template with the parameters"

      self.__type_label = "template&lt;%s&gt;"%(
         string.join(map(lambda x:"typename "+x,
                         map(self.format_type, type.parameters())), ",")
         )

   def visitFunctionType(self, type):
      "Labels the function type with return type, name and parameters"
      
      ret = self.format_type(type.returnType())
      params = map(self.format_type, type.parameters())
      pre = string.join(type.premod(), '')
      if self.__id_holder:
         ident = self.__id_holder[0]
         del self.__id_holder[0]
      else:
         ident = ''
      self.__type_label = "%s(%s%s)(%s)"%(ret,pre,ident,string.join(params,", "))



   # These are overridden in {Summary,Detail}Formatter
   def write_start(self):
      "Abstract method to start the output, eg table headings"

      self.write('<!-- this part was generated by ' + self.__class__.__name__ + ' -->\n')

   def write_section_start(self, heading):
      "Abstract method to start a section of declaration types"

      pass

   def write_section_end(self, heading):
      "Abstract method to end a section of declaration types"

      pass

   def write_section_item(self, text):
      "Abstract method to write the output of one formatted declaration"

      pass

   def write_end(self):
      "Abstract method to end the output, eg close the table"

      pass