Synopsis - Cross-Reference

File: Synopsis/Formatters/Dump.py
  1#
  2# Copyright (C) 2003 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
  8"""
  9Verbose attribute-oriented xml dump of ASG, useful for validation,
 10introspection, and debugging.
 11"""
 12
 13from Synopsis import config
 14from Synopsis.Processor import *
 15from Synopsis.SourceFile import SourceFile
 16from Synopsis.DocString import DocString
 17from Synopsis.QualifiedName import *
 18
 19import sys, getopt, os, os.path, string, types
 20from xml.dom.minidom import getDOMImplementation
 21
 22dom = getDOMImplementation().createDocument(None, "dump", None)
 23
 24class Formatter(Processor):
 25
 26    show_ids = Parameter(True, 'output object ids as attributes')
 27    show_declarations = Parameter(True, 'output declarations')
 28    show_types = Parameter(True, 'output types')
 29    show_files = Parameter(True, 'output files')
 30    stylesheet = Parameter(config.datadir + '/dump.css', 'stylesheet to be referenced for rendering')
 31
 32    def process(self, ir, **kwds):
 33
 34        self.set_parameters(kwds)
 35        if not self.output: raise MissingArgument('output')
 36        self.ir = self.merge_input(ir)
 37
 38        self.handlers = {types.NoneType : self.visit_none,
 39                         types.TypeType : self.visit_type,
 40                         types.IntType : self.visit_string,
 41                         types.LongType : self.visit_string,
 42                         types.FloatType : self.visit_string,
 43                         types.StringType : self.visit_string,
 44                         types.BooleanType : self.visit_string,
 45                         types.TupleType : self.visit_tuple,
 46                         types.ListType : self.visit_list,
 47                         types.DictType : self.visit_dict,
 48                         types.InstanceType : self.visit_instance,
 49                         QualifiedName : self.visit_string,
 50                         QualifiedCxxName : self.visit_string,
 51                         QualifiedPythonName : self.visit_string,
 52                         SourceFile : self.visit_sourcefile,
 53                         DocString : self.visit_docstring}
 54        self.visited = {}
 55
 56        self.os = open(self.output, "w")
 57        self.os.write("<?xml version='1.0' encoding='ISO-8859-1'?>\n")
 58        if self.stylesheet:
 59            self.os.write("<?xml-stylesheet href='%s' type='text/css'?>\n"%self.stylesheet)
 60
 61        self.os.write("<ir>\n")
 62        self.os.write("<asg>\n")
 63
 64        if self.show_declarations:
 65            self.write_declarations(self.ir.asg.declarations)
 66
 67        if self.show_types:
 68            self.write_types(self.ir.asg.types)
 69        self.os.write("</asg>\n")
 70
 71        if self.show_files:
 72            self.write_files(self.ir.files)
 73
 74        self.os.write("</ir>\n")
 75
 76        return self.ir
 77
 78    def push(self, name):
 79
 80        element = dom.createElement(name)
 81        self.node.appendChild(element)
 82        self.node = element
 83
 84    def pop(self):
 85
 86        self.node = self.node.parentNode
 87
 88    def add_text(self, text):
 89
 90        node = dom.createTextNode(text)
 91        self.node.appendChild(node)
 92
 93    def visit(self, obj):
 94
 95        i,t = id(obj), type(obj)
 96        if self.visited.has_key(i):
 97            if self.show_ids:
 98                self.node.setAttribute('xref', str(i))
 99            return
100        if self.handlers.has_key(t):
101            self.handlers[t](obj)
102        elif issubclass(t, object):
103            self.visit_instance(obj)
104        else:
105            print "Unknown type %s for object: '%s'"%(t,obj)
106
107    def visit_none(self, obj): pass
108    def visit_string(self, obj): self.add_text(str(obj))
109    def visit_type(self, obj): self.write(obj) # where is that used ??
110
111    def visit_tuple(self, obj):
112
113        if len(obj) == 0: return
114        for i in obj:
115            self.push('item')
116            self.visit(i)
117            self.pop()
118
119    def visit_list(self, obj):
120
121        if len(obj) == 0: return
122        for i in obj:
123            self.push('item')
124            self.visit(i)
125            self.pop()
126
127    def visit_dict(self, dict):
128
129        items = dict.items()
130        if len(items) == 0: return
131        items.sort()
132        for i in items:
133            self.push("key")
134            self.visit(i[0])
135            self.pop()
136            self.push("value")
137            self.visit(i[1])
138            self.pop()
139
140
141    def visit_sourcefile(self, obj):
142
143        self.node.setAttribute('name', obj.name)
144        self.node.setAttribute('language', obj.annotations.get('language', ''))
145        self.node.setAttribute('primary', str(obj.annotations.get('primary', False)))
146
147        includes = getattr(obj, 'includes')
148        if includes:
149            self.push('includes')
150            self.visit(includes)
151            self.pop()
152
153        if self.show_declarations:
154            for name in ['declarations', 'macro_calls']:
155                self.push(name)
156                self.visit(getattr(obj, name))
157                self.pop()
158
159    def visit_docstring(self, obj):
160
161        self.node.setAttribute('markup', obj.markup)
162        self.push('text')
163        self.visit(obj.text)
164        self.pop()
165
166
167    def visit_instance(self, obj):
168
169        self.visited[id(obj)] = None
170        self.push("instance")
171        self.node.setAttribute('class', "%s.%s"%(obj.__class__.__module__,obj.__class__.__name__))
172        if self.show_ids:
173            self.node.setAttribute('id', str(id(obj)))
174        if self.handlers.has_key(obj.__class__):
175            self.handlers[obj.__class__](obj)
176        else:
177            attrs = obj.__dict__.items()
178            attrs.sort()
179            for name, value in attrs:
180                # ignore None values
181                if value in (None, [], ()):
182                    continue
183                # ignore private attributes
184                if name[0] == '_':
185                    continue
186
187                # String attributes map to xml attributes.
188                if self.handlers.get(type(value)) == self.visit_string:
189                    self.node.setAttribute(name, str(value))
190                    # Everything else maps to sub-elements.
191                else:
192                    self.push(name)
193                    self.visit(value)
194                    self.pop()
195        self.pop()
196
197    def write_declarations(self, declarations):
198
199        self.node = dom.createElement("declarations")
200        for d in declarations: self.visit(d)
201        self.node.writexml(self.os, indent=" ", addindent=" ", newl="\n")
202        self.node.unlink()
203        del self.node
204
205    def write_types(self, types):
206
207        self.node = dom.createElement("types")
208        values = types.values()
209        values.sort()
210        for t in values: self.visit(t)
211        self.node.writexml(self.os, indent=" ", addindent=" ", newl="\n")
212        self.node.unlink()
213        del self.node
214
215    def write_files(self, files):
216
217        self.node = dom.createElement("files")
218        for f in files: self.visit(files[f])
219        self.node.writexml(self.os, indent=" ", addindent=" ", newl="\n")
220        self.node.unlink()
221        del self.node
222
223