15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)"""Nodes for PPAPI IDL AST.""" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_namespace import IDLNamespace 8a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)from idl_node import IDLNode 95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_option import GetOption 105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)from idl_visitor import IDLVisitor 11a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles)from idl_release import IDLReleaseMap 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLLabelResolver 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which traverses the AST, building a mapping of 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Release names to Versions numbers and calculating a min version. 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# The mapping is applied to the File nodes within the AST. 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLLabelResolver(IDLVisitor): 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Depart(self, node, ignore, childdata): 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Build list of Release=Version 235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.IsA('LabelItem'): 245d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel = node.GetProperty('channel') 255d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if not channel: 265d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) channel = 'stable' 275d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return (node.GetName(), node.GetProperty('VALUE'), channel) 285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # On completion of the Label, apply to the parent File if the 305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # name of the label matches the generation label. 315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.IsA('Label') and node.GetName() == GetOption('label'): 325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) try: 33f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) node.parent.release_map = IDLReleaseMap(childdata) 345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) except Exception as err: 355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.Error('Unable to build release map: %s' % str(err)) 365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # For File objects, set the minimum version 385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.IsA('File'): 39a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) file_min, _ = node.release_map.GetReleaseRange() 405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.SetMin(file_min) 415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return None 435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLNamespaceVersionResolver 475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which traverses the AST, building a namespace tree 495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# as it goes. The namespace tree is mapping from a name to a version list. 505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# Labels must already be resolved to use. 515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLNamespaceVersionResolver(IDLVisitor): 535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) NamespaceSet = set(['AST', 'Callspec', 'Interface', 'Member', 'Struct']) 545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # 555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # When we arrive at a node we must assign it a namespace and if the 565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # node is named, then place it in the appropriate namespace. 575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # 585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Arrive(self, node, parent_namespace): 595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # If we are a File, grab the Min version and replease mapping 605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.IsA('File'): 615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.rmin = node.GetMinMax()[0] 625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.release_map = node.release_map 635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Set the min version on any non Label within the File 655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not node.IsA('AST', 'File', 'Label', 'LabelItem'): 66a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) my_min, _ = node.GetMinMax() 675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not my_min: 685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.SetMin(self.rmin) 695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # If this object is not a namespace aware object, use the parent's one 715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.cls not in self.NamespaceSet: 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.namespace = parent_namespace 735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # otherwise create one. 75a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) node.namespace = IDLNamespace(parent_namespace) 765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # If this node is named, place it in its parent's namespace 785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if parent_namespace and node.cls in IDLNode.NamedSet: 795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Set version min and max based on properties 805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if self.release_map: 815d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) vmin = node.GetProperty('dev_version') 825d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if vmin == None: 835d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) vmin = node.GetProperty('version') 845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) vmax = node.GetProperty('deprecate') 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # If no min is available, the use the parent File's min 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if vmin == None: 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rmin = self.rmin 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rmin = self.release_map.GetRelease(vmin) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) rmax = self.release_map.GetRelease(vmax) 915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.SetReleaseRange(rmin, rmax) 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) parent_namespace.AddNode(node) 935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Pass this namespace to each child in case they inherit it 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return node.namespace 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLFileTypeRessolver 1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which traverses the AST and sets a FILE property 1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# on all file nodes. In addition, searches the namespace resolving all 1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# type references. The namespace tree must already have been populated 1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# before this visitor is used. 1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLFileTypeResolver(IDLVisitor): 1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def VisitFilter(self, node, data): 1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return not node.IsA('Comment', 'Copyright') 1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Arrive(self, node, filenode): 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Track the file node to update errors 1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if node.IsA('File'): 1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.SetProperty('FILE', node) 1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) filenode = node 1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not node.IsA('AST'): 117a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) file_min, _ = filenode.release_map.GetReleaseRange() 1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not file_min: 1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) print 'Resetting min on %s to %s' % (node, file_min) 1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.SetMinRange(file_min) 1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # If this node has a TYPEREF, resolve it to a version list 123a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) typeref = node.GetPropertyLocal('TYPEREF') 1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if typeref: 1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.typelist = node.parent.namespace.FindList(typeref) 1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if not node.typelist: 1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.Error('Could not resolve %s.' % typeref) 1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) else: 1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.typelist = None 1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return filenode 1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLReleaseResolver 1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized visitor which will traverse the AST, and generate a mapping 1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# from any release to the first release in which that version of the object 1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# was generated. Types must already be resolved to use. 1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLReleaseResolver(IDLVisitor): 1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Arrive(self, node, releases): 1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) node.BuildReleaseMap(releases) 1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) return releases 1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# IDLAst 1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# A specialized version of the IDLNode for containing the whole of the 1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# AST. Construction of the AST object will cause resolution of the 1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# tree including versions, types, etc... Errors counts will be collected 1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# both per file, and on the AST itself. 1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)# 1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)class IDLAst(IDLNode): 1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def __init__(self, children): 1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDLNode.__init__(self, 'AST', 'BuiltIn', 1, 0, children) 1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) self.Resolve() 1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) def Resolve(self): 1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Set the appropriate Release=Version mapping for each File 1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDLLabelResolver().Visit(self, None) 1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Generate the Namesapce Tree 163a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) self.namespace = IDLNamespace(None) 1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDLNamespaceVersionResolver().Visit(self, self.namespace) 1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Using the namespace, resolve type references 1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDLFileTypeResolver().Visit(self, None) 1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Build an ordered list of all releases 1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) releases = set() 1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for filenode in self.GetListOf('File'): 1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) releases |= set(filenode.release_map.GetReleases()) 1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) # Generate a per node list of releases and release mapping 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) IDLReleaseResolver().Visit(self, sorted(releases)) 1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) for filenode in self.GetListOf('File'): 178a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) errors = filenode.GetProperty('ERRORS') 179a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) if errors: 180a3f6a49ab37290eeeb8db0f41ec0f1cb74a68be7Torne (Richard Coles) self.errors += errors 1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 183