Add a comment clarifying why we don't exit early after checking sys deps
[chromium-blink-merge.git] / ppapi / generators / idl_ast.py
blob515dbb0c128dee5bf89e2b7a0692fe16310b90b4
1 # Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 # Use of this source code is governed by a BSD-style license that can be
3 # found in the LICENSE file.
5 """Nodes for PPAPI IDL AST."""
7 from idl_namespace import IDLNamespace
8 from idl_node import IDLNode
9 from idl_option import GetOption
10 from idl_visitor import IDLVisitor
11 from idl_release import IDLReleaseMap
14 # IDLLabelResolver
16 # A specialized visitor which traverses the AST, building a mapping of
17 # Release names to Versions numbers and calculating a min version.
18 # The mapping is applied to the File nodes within the AST.
20 class IDLLabelResolver(IDLVisitor):
21 def Depart(self, node, ignore, childdata):
22 # Build list of Release=Version
23 if node.IsA('LabelItem'):
24 channel = node.GetProperty('channel')
25 if not channel:
26 channel = 'stable'
27 return (node.GetName(), node.GetProperty('VALUE'), channel)
29 # On completion of the Label, apply to the parent File if the
30 # name of the label matches the generation label.
31 if node.IsA('Label') and node.GetName() == GetOption('label'):
32 try:
33 node.parent.release_map = IDLReleaseMap(childdata)
34 except Exception as err:
35 node.Error('Unable to build release map: %s' % str(err))
37 # For File objects, set the minimum version
38 if node.IsA('File'):
39 file_min, _ = node.release_map.GetReleaseRange()
40 node.SetMin(file_min)
42 return None
46 # IDLNamespaceVersionResolver
48 # A specialized visitor which traverses the AST, building a namespace tree
49 # as it goes. The namespace tree is mapping from a name to a version list.
50 # Labels must already be resolved to use.
52 class IDLNamespaceVersionResolver(IDLVisitor):
53 NamespaceSet = set(['AST', 'Callspec', 'Interface', 'Member', 'Struct'])
55 # When we arrive at a node we must assign it a namespace and if the
56 # node is named, then place it in the appropriate namespace.
58 def Arrive(self, node, parent_namespace):
59 # If we are a File, grab the Min version and replease mapping
60 if node.IsA('File'):
61 self.rmin = node.GetMinMax()[0]
62 self.release_map = node.release_map
64 # Set the min version on any non Label within the File
65 if not node.IsA('AST', 'File', 'Label', 'LabelItem'):
66 my_min, _ = node.GetMinMax()
67 if not my_min:
68 node.SetMin(self.rmin)
70 # If this object is not a namespace aware object, use the parent's one
71 if node.cls not in self.NamespaceSet:
72 node.namespace = parent_namespace
73 else:
74 # otherwise create one.
75 node.namespace = IDLNamespace(parent_namespace)
77 # If this node is named, place it in its parent's namespace
78 if parent_namespace and node.cls in IDLNode.NamedSet:
79 # Set version min and max based on properties
80 if self.release_map:
81 vmin = node.GetProperty('dev_version')
82 if vmin == None:
83 vmin = node.GetProperty('version')
84 vmax = node.GetProperty('deprecate')
85 # If no min is available, the use the parent File's min
86 if vmin == None:
87 rmin = self.rmin
88 else:
89 rmin = self.release_map.GetRelease(vmin)
90 rmax = self.release_map.GetRelease(vmax)
91 node.SetReleaseRange(rmin, rmax)
92 parent_namespace.AddNode(node)
94 # Pass this namespace to each child in case they inherit it
95 return node.namespace
99 # IDLFileTypeRessolver
101 # A specialized visitor which traverses the AST and sets a FILE property
102 # on all file nodes. In addition, searches the namespace resolving all
103 # type references. The namespace tree must already have been populated
104 # before this visitor is used.
106 class IDLFileTypeResolver(IDLVisitor):
107 def VisitFilter(self, node, data):
108 return not node.IsA('Comment', 'Copyright')
110 def Arrive(self, node, filenode):
111 # Track the file node to update errors
112 if node.IsA('File'):
113 node.SetProperty('FILE', node)
114 filenode = node
116 if not node.IsA('AST'):
117 file_min, _ = filenode.release_map.GetReleaseRange()
118 if not file_min:
119 print 'Resetting min on %s to %s' % (node, file_min)
120 node.SetMinRange(file_min)
122 # If this node has a TYPEREF, resolve it to a version list
123 typeref = node.GetPropertyLocal('TYPEREF')
124 if typeref:
125 node.typelist = node.parent.namespace.FindList(typeref)
126 if not node.typelist:
127 node.Error('Could not resolve %s.' % typeref)
128 else:
129 node.typelist = None
130 return filenode
133 # IDLReleaseResolver
135 # A specialized visitor which will traverse the AST, and generate a mapping
136 # from any release to the first release in which that version of the object
137 # was generated. Types must already be resolved to use.
139 class IDLReleaseResolver(IDLVisitor):
140 def Arrive(self, node, releases):
141 node.BuildReleaseMap(releases)
142 return releases
146 # IDLAst
148 # A specialized version of the IDLNode for containing the whole of the
149 # AST. Construction of the AST object will cause resolution of the
150 # tree including versions, types, etc... Errors counts will be collected
151 # both per file, and on the AST itself.
153 class IDLAst(IDLNode):
154 def __init__(self, children):
155 IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, children)
156 self.Resolve()
158 def Resolve(self):
159 # Set the appropriate Release=Version mapping for each File
160 IDLLabelResolver().Visit(self, None)
162 # Generate the Namesapce Tree
163 self.namespace = IDLNamespace(None)
164 IDLNamespaceVersionResolver().Visit(self, self.namespace)
166 # Using the namespace, resolve type references
167 IDLFileTypeResolver().Visit(self, None)
169 # Build an ordered list of all releases
170 releases = set()
171 for filenode in self.GetListOf('File'):
172 releases |= set(filenode.release_map.GetReleases())
174 # Generate a per node list of releases and release mapping
175 IDLReleaseResolver().Visit(self, sorted(releases))
177 for filenode in self.GetListOf('File'):
178 errors = filenode.GetProperty('ERRORS')
179 if errors:
180 self.errors += errors