Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(357)

Unified Diff: ppapi/generators/idl_namespace.py

Issue 7253025: Add version aware name resolution (Closed) Base URL: svn://chrome-svn/chrome/trunk/src/
Patch Set: '' Created 9 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: ppapi/generators/idl_namespace.py
===================================================================
--- ppapi/generators/idl_namespace.py (revision 0)
+++ ppapi/generators/idl_namespace.py (revision 0)
@@ -0,0 +1,345 @@
+#!/usr/bin/python
+#
+# Copyright (c) 2011 The Chromium Authors. All rights reserved.
+# Use of this source code is governed by a BSD-style license that can be
+# found in the LICENSE file.
+
+"""
+IDLNamespace for PPAPI
+
+This file defines the behavior of the AST namespace which allows for resolving
+a symbol as one or more AST nodes given a version or range of versions.
+"""
+
+import sys
+
+from idl_option import GetOption, Option, ParseOptions
+from idl_log import ErrOut, InfoOut, WarnOut
+from idl_version import IDLVersion
+
+Option('label', 'Use the specifed label blocks.', default='Chrome')
+Option('version', 'Use the specified version', default='M14')
+Option('namespace_debug', 'Use the specified version')
+
+
+#
+# IDLVersionList
+#
+# IDLVersionList is a list based container for holding IDLVersion
+# objects. The IDLVersionList can be added to, and searched by
+# range.
+#
+class IDLVersionList(object):
+ def __init__(self):
+ self.nodes = []
+
+ def FindVersion(self, version):
+ assert type(version) == float
+
+ for node in self.nodes:
+ if node.IsVersion(version):
+ return node
+ return None
+
+ def FindRange(self, vmin, vmax):
+ assert type(vmin) == float
+ assert type(vmax) == float
+ assert vmin != vmax
+
+ out = []
+ for node in self.nodes:
+ if node.InRange(vmin, vmax):
+ out.append(node)
+ return out
+
+ def AddNode(self, node):
+ if GetOption('version_debug'): InfoOut.Log('\nAdding %s' % node)
+ last = None
+
+ # Check current versions in that namespace
+ for cver in self.nodes:
+ if GetOption('version_debug'): InfoOut.Log(' Checking %s' % cver)
+
+ # We should only be missing a 'version' tag for the first item.
+ if not node.vmin:
+ node.Error('Missing version on overload of previous %s.' %
+ cver.Location())
+ raise RuntimeError('DSFSD')
+ return False
+
+ # If the node has no max, then set it to this one
+ if not cver.vmax:
+ cver.vmax = node.vmin
+ if GetOption('version_debug'): InfoOut.Log(' Update %s' % cver)
+
+ # if the max and min overlap, than's an error
sehr (please use chromium) 2011/07/01 22:58:51 This requires that versioned information appear in
noelallen1 2011/07/02 19:51:32 Done.
+ if cver.vmax > node.vmin:
+ if node.vmax and cver.vmin >= node.vmax:
+ node.Error('Declarations out of order.')
+ else:
+ node.Error('Overlap in versions.')
+ return False
+ last = cver
+
+ # Otherwise, the previous max and current min should match
+ # unless this is the unlikely case of something being only
+ # temporarily deprecated.
+ if last and last.vmax != node.vmin:
+ node.Warn('Gap in version numbers.')
+
+ # If we made it here, this new node must be the 'newest'
+ # and does not overlap with anything previously added, so
+ # we can add it to the end of the list.
+ if GetOption('version_debug'): InfoOut.Log('Done %s' % node)
+ self.nodes.append(node)
+ return True
+
+#
+# IDLVersionMap
+#
+# A version map, can map from an float interface version, to a global
+# release string.
+#
+class IDLVersionMap(object):
+ def __init__(self):
+ self.version_to_release = {}
+ self.release_to_version = {}
+ self.versions = []
+
+ def AddReleaseVersionMapping(self, release, version):
+ self.version_to_release[version] = release
+ self.release_to_version[release] = version
+ self.versions = sorted(self.version_to_release.keys())
+
+ def GetRelease(self, version):
+ # Check for exact match
+ if version in self.versions:
+ return self.version_to_release[version]
+
+ def GetVersion(self, release):
+ return self.release_to_version[release]
+
+
+
+#
+# IDLNamespace
+#
+# IDLNamespace provides a mapping between a symbol name and an IDLVersionList
+# which contains IDLVersion objects. It provides an interface for fetching
+# one or more IDLNodes based on a version or range of versions.
+#
+class IDLNamespace(object):
+ def __init__(self, parent):
+ self.namespace = {}
+ self.parent = parent
+
+ def Dump(self):
+ for name in self.namespace:
+ InfoOut.Log('NAME=%s' % name)
+ for cver in self.namespace[name]:
+ InfoOut.Log(' %s' % cver)
+ InfoOut.Log('')
+
+ def FindVersion(self, name, version):
+ list = self.namespace.get(name, None)
+ if list == None:
+ if self.parent:
+ return self.parent.FindVersion(name, version)
+ else:
+ return None
+ return list.FindVersion(version)
+
+ def FindRange(self, name, vmin, vmax):
+ list = self.namespace.get(name, None)
+ if list == None:
+ if self.parent:
+ return self.parent.FindRange(name, vmin, vmax)
+ else:
+ return []
+ return list.FindRange(vmin, vmax)
+
+ def FindList(self, name):
+ list = self.namespace.get(name, None)
+ if list == None:
+ if self.parent:
+ return self.parent.FindList(name)
+ return list
+
+ def AddNode(self, node):
+ name = node.GetName()
+ list = self.namespace.setdefault(name,IDLVersionList())
+ if GetOption('namespace_debug'):
+ print "Adding to namespace: %s" % node
+ return list.AddNode(node)
+
+
+
+#
+# Testing Code
+#
+
+#
+# MockNode
+#
+# Mocks the IDLNode to support error, warning handling, and string functions.
+#
+class MockNode(IDLVersion):
+ def __init__(self, name, vmin, vmax):
+ self.name = name
+ self.vmin = vmin
+ self.vmax = vmax
+ self.errors = []
+ self.warns = []
+ self.properties = {
+ 'NAME': name,
+ 'version': vmin,
+ 'deprecate' : vmax
+ }
+
+ def __str__(self):
+ return '%s (%s : %s)' % (self.name, self.vmin, self.vmax)
+
+ def GetName(self):
+ return self.name
+
+ def Error(self, msg):
+ if GetOption('version_debug'): print 'Error: %s' % msg
+ self.errors.append(msg)
+
+ def Warn(self, msg):
+ if GetOption('version_debug'): print 'Warn: %s' % msg
+ self.warns.append(msg)
+
+ def GetProperty(self, name):
+ return self.properties.get(name, None)
+
+errors = 0
+#
+# DumpFailure
+#
+# Dumps all the information relavent to an add failure.
sehr (please use chromium) 2011/07/01 22:58:51 relevant
noelallen1 2011/07/02 19:51:32 Done.
+def DumpFailure(namespace, node, msg):
+ global errors
+ print '\n******************************'
+ print 'Failure: %s %s' % (node, msg)
+ for warn in node.warns:
+ print ' WARN: %s' % warn
+ for err in node.errors:
+ print ' ERROR: %s' % err
+ print '\n'
+ namespace.Dump()
+ print '******************************\n'
+ errors += 1
+
+# Add expecting no errors or warnings
+def AddOkay(namespace, node):
+ okay = namespace.AddNode(node)
+ if not okay or node.errors or node.warns:
+ DumpFailure(namespace, node, 'Expected success')
+
+# Add expecting a specific warning
+def AddWarn(namespace, node, msg):
+ okay = namespace.AddNode(node)
+ if not okay or node.errors or not node.warns:
+ DumpFailure(namespace, node, 'Expected warnings')
+ if msg not in node.warns:
+ DumpFailure(namespace, node, 'Expected warning: %s' % msg)
+
+# Add expecting a specific error any any number of warnings
+def AddError(namespace, node, msg):
+ okay = namespace.AddNode(node)
+ if okay or not node.errors:
+ DumpFailure(namespace, node, 'Expected errors')
+ if msg not in node.errors:
+ DumpFailure(namespace, node, 'Expected error: %s' % msg)
+
+# Verify the namespace find the correct node based on version
+def VerifyFindOne(namespace, name, version, node):
+ global errors
+ if (namespace.FindVersion(name, version) != node):
+ print "Failed to find %s as version %f of %s" % (node, version, name)
+ namespace.Dump()
+ print "\n"
+ errors += 1
+
+# Verify the namespace find the correct nodes based on range
sehr (please use chromium) 2011/07/01 22:58:51 Can't parse this comment.
noelallen1 2011/07/02 19:51:32 Done.
+def VerifyFindAll(namespace, name, vmin, vmax, nodes):
+ global errors
+ out = namespace.FindRange(name, vmin, vmax)
+ if (out != nodes):
+ print "Found [%s] instead of[%s] for versions %f to %f of %s" % (
+ ' '.join([str(x) for x in out]),
+ ' '.join([str(x) for x in nodes]),
+ vmin,
+ vmax,
+ name)
+ namespace.Dump()
+ print "\n"
+ errors += 1
+
+def Main(args):
+ global errors
+ ParseOptions(args)
+
+ InfoOut.SetConsole(True)
+
+ namespace = IDLNamespace(None)
+
+ FooXX = MockNode('foo', None, None)
+ Foo1X = MockNode('foo', 1.0, None)
+ Foo2X = MockNode('foo', 2.0, None)
+ Foo3X = MockNode('foo', 3.0, None)
+
+ #Verify we succeed with undeprecated adds
sehr (please use chromium) 2011/07/01 22:58:51 s/#V/# V/
noelallen1 2011/07/02 19:51:32 Done.
+ AddOkay(namespace, FooXX)
+ AddOkay(namespace, Foo1X)
+ AddOkay(namespace, Foo3X)
+ # Verify we fail to add a node between undeprecated versions
+ AddError(namespace, Foo2X, 'Overlap in versions.')
+
+ BarXX = MockNode('bar', None, None)
+ Bar12 = MockNode('bar', 1.0, 2.0)
+ Bar23 = MockNode('bar', 2.0, 3.0)
+ Bar34 = MockNode('bar', 3.0, 4.0)
+
+ # Verify we succeed with fully qualified versions
+ namespace = IDLNamespace(namespace)
+ AddOkay(namespace, BarXX)
+ AddOkay(namespace, Bar12)
+ # Verify we warn when detecting a gap
+ AddWarn(namespace, Bar34, 'Gap in version numbers.')
+ # Verify we fail when inserting into this gap
+ # (NOTE: while this could be legal, it is sloppy so we disallow it)
+ AddError(namespace, Bar23, 'Declarations out of order.')
+
+ # Verify local namespace
+ VerifyFindOne(namespace, 'bar', 0.0, BarXX)
+ VerifyFindAll(namespace, 'bar', 0.5, 1.5, [BarXX, Bar12])
+
+ # Verify the correct version of the object is found recursively
+ VerifyFindOne(namespace, 'foo', 0.0, FooXX)
+ VerifyFindOne(namespace, 'foo', 0.5, FooXX)
+ VerifyFindOne(namespace, 'foo', 1.0, Foo1X)
+ VerifyFindOne(namespace, 'foo', 1.5, Foo1X)
+ VerifyFindOne(namespace, 'foo', 3.0, Foo3X)
+ VerifyFindOne(namespace, 'foo', 100.0, Foo3X)
+
+ # Verify the correct range of objects is found
+ VerifyFindAll(namespace, 'foo', 0.0, 1.0, [FooXX])
+ VerifyFindAll(namespace, 'foo', 0.5, 1.0, [FooXX])
+ VerifyFindAll(namespace, 'foo', 1.0, 1.1, [Foo1X])
+ VerifyFindAll(namespace, 'foo', 0.5, 1.5, [FooXX, Foo1X])
+ VerifyFindAll(namespace, 'foo', 0.0, 3.0, [FooXX, Foo1X])
+ VerifyFindAll(namespace, 'foo', 3.0, 100.0, [Foo3X])
+
+
+
+ if errors:
+ print 'Test failed with %d errors.' % errors
+ else:
+ print 'Passed.'
+ return errors
+
+if __name__ == '__main__':
+ sys.exit(Main(sys.argv[1:]))
+
Property changes on: ppapi/generators/idl_namespace.py
___________________________________________________________________
Added: svn:eol-style
+ LF
« no previous file with comments | « no previous file | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698