Adding instrumentation to locate the source of jankiness.
[chromium-blink-merge.git] / tools / idl_parser / idl_node.py
blobe50fc4e1baead7d9b5498c4138e83211d0af2946
1 #!/usr/bin/env python
2 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
3 # Use of this source code is governed by a BSD-style license that can be
4 # found in the LICENSE file.
6 import sys
9 # IDL Node
11 # IDL Node defines the IDLAttribute and IDLNode objects which are constructed
12 # by the parser as it processes the various 'productions'. The IDLAttribute
13 # objects are assigned to the IDLNode's property dictionary instead of being
14 # applied as children of The IDLNodes, so they do not exist in the final tree.
15 # The AST of IDLNodes is the output from the parsing state and will be used
16 # as the source data by the various generators.
21 # CopyToList
23 # Takes an input item, list, or None, and returns a new list of that set.
24 def CopyToList(item):
25 # If the item is 'Empty' make it an empty list
26 if not item:
27 item = []
29 # If the item is not a list
30 if type(item) is not type([]):
31 item = [item]
33 # Make a copy we can modify
34 return list(item)
37 # IDLSearch
39 # A temporary object used by the parsing process to hold an Extended Attribute
40 # which will be passed as a child to a standard IDLNode.
42 class IDLSearch(object):
43 def __init__(self):
44 self.depth = 0
46 def Enter(self, node):
47 pass
49 def Exit(self, node):
50 pass
53 # IDLAttribute
55 # A temporary object used by the parsing process to hold an Extended Attribute
56 # which will be passed as a child to a standard IDLNode.
58 class IDLAttribute(object):
59 def __init__(self, name, value):
60 self._cls = 'Property'
61 self.name = name
62 self.value = value
64 def __str__(self):
65 return '%s=%s' % (self.name, self.value)
67 def GetClass(self):
68 return self._cls
71 # IDLNode
73 # This class implements the AST tree, providing the associations between
74 # parents and children. It also contains a namepsace and propertynode to
75 # allow for look-ups. IDLNode is derived from IDLRelease, so it is
76 # version aware.
78 class IDLNode(object):
79 def __init__(self, cls, filename, lineno, pos, children=None):
80 self._cls = cls
81 self._properties = {
82 'ERRORS' : [],
83 'WARNINGS': [],
84 'FILENAME': filename,
85 'LINENO' : lineno,
86 'POSSITION' : pos,
89 self._children = []
90 self._parent = None
91 self.AddChildren(children)
96 # Return a string representation of this node
97 def __str__(self):
98 name = self.GetProperty('NAME','')
99 return '%s(%s)' % (self._cls, name)
101 def GetLogLine(self, msg):
102 filename, lineno = self.GetFileAndLine()
103 return '%s(%d) : %s\n' % (filename, lineno, msg)
105 # Log an error for this object
106 def Error(self, msg):
107 self.GetProperty('ERRORS').append(msg)
108 sys.stderr.write(self.GetLogLine('error: ' + msg))
110 # Log a warning for this object
111 def Warning(self, msg):
112 self.GetProperty('WARNINGS').append(msg)
113 sys.stdout.write(self.GetLogLine('warning:' + msg))
115 # Return file and line number for where node was defined
116 def GetFileAndLine(self):
117 return self.GetProperty('FILENAME'), self.GetProperty('LINENO')
119 def GetClass(self):
120 return self._cls
122 def GetName(self):
123 return self.GetProperty('NAME')
125 def GetParent(self):
126 return self._parent
128 def Traverse(self, search, filter_nodes):
129 if self._cls in filter_nodes:
130 return ''
132 search.Enter(self)
133 search.depth += 1
134 for child in self._children:
135 child.Traverse(search, filter_nodes)
136 search.depth -= 1
137 search.Exit(self)
140 def Tree(self, filter_nodes=None, accept_props=None):
141 class DumpTreeSearch(IDLSearch):
142 def __init__(self, props):
143 IDLSearch.__init__(self)
144 self.out = []
145 self.props = props
147 def Enter(self, node):
148 tab = ''.rjust(self.depth * 2)
149 self.out.append(tab + str(node))
150 if self.props:
151 proplist = []
152 for key, value in node.GetProperties().iteritems():
153 if key in self.props:
154 proplist.append(tab + ' %s: %s' % (key, str(value)))
155 if proplist:
156 self.out.append(tab + ' PROPERTIES')
157 self.out.extend(proplist)
159 if filter_nodes == None:
160 filter_nodes = ['Comment', 'Copyright']
162 search = DumpTreeSearch(accept_props)
163 self.Traverse(search, filter_nodes)
164 return search.out
167 # Search related functions
169 # Check if node is of a given type
170 def IsA(self, *typelist):
171 if self._cls in typelist:
172 return True
173 return False
175 # Get a list of all children
176 def GetChildren(self):
177 return self._children
179 def GetListOf(self, *keys):
180 out = []
181 for child in self.GetChildren():
182 if child.GetClass() in keys:
183 out.append(child)
184 return out
186 def GetOneOf(self, *keys):
187 out = self.GetListOf(*keys)
188 if out:
189 return out[0]
190 return None
192 def AddChildren(self, children):
193 children = CopyToList(children)
194 for child in children:
195 if not child:
196 continue
197 if type(child) == IDLAttribute:
198 self.SetProperty(child.name, child.value)
199 continue
200 if type(child) == IDLNode:
201 child._parent = self
202 self._children.append(child)
203 continue
204 raise RuntimeError('Adding child of type %s.\n' % type(child).__name__)
208 # Property Functions
210 def SetProperty(self, name, val):
211 self._properties[name] = val
213 def GetProperty(self, name, default=None):
214 return self._properties.get(name, default)
216 def GetProperties(self):
217 return self._properties