| Index: third_party/chrome/ppapi/generators/idl_release.py
|
| diff --git a/third_party/chrome/ppapi/generators/idl_release.py b/third_party/chrome/ppapi/generators/idl_release.py
|
| new file mode 100755
|
| index 0000000000000000000000000000000000000000..eafc95f3ba5acc52928a942b56b1dc6b55d2aa19
|
| --- /dev/null
|
| +++ b/third_party/chrome/ppapi/generators/idl_release.py
|
| @@ -0,0 +1,351 @@
|
| +#!/usr/bin/env python
|
| +# Copyright (c) 2012 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.
|
| +
|
| +"""
|
| +IDLRelease 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 Release or range of Releases.
|
| +"""
|
| +
|
| +import sys
|
| +
|
| +from idl_log import ErrOut, InfoOut, WarnOut
|
| +from idl_option import GetOption, Option, ParseOptions
|
| +
|
| +Option('release_debug', 'Debug Release data')
|
| +Option('wgap', 'Ignore Release gap warning')
|
| +
|
| +
|
| +#
|
| +# Module level functions and data used for testing.
|
| +#
|
| +error = None
|
| +warning = None
|
| +def ReportReleaseError(msg):
|
| + global error
|
| + error = msg
|
| +
|
| +def ReportReleaseWarning(msg):
|
| + global warning
|
| + warning = msg
|
| +
|
| +def ReportClear():
|
| + global error, warning
|
| + error = None
|
| + warning = None
|
| +
|
| +#
|
| +# IDLRelease
|
| +#
|
| +# IDLRelease is an object which stores the association of a given symbol
|
| +# name, with an AST node for a range of Releases for that object.
|
| +#
|
| +# A vmin value of None indicates that the object begins at the earliest
|
| +# available Release number. The value of vmin is always inclusive.
|
| +
|
| +# A vmax value of None indicates that the object is never deprecated, so
|
| +# it exists until it is overloaded or until the latest available Release.
|
| +# The value of vmax is always exclusive, representing the first Release
|
| +# on which the object is no longer valid.
|
| +class IDLRelease(object):
|
| + def __init__(self, rmin, rmax):
|
| + self.rmin = rmin
|
| + self.rmax = rmax
|
| +
|
| + def __str__(self):
|
| + if not self.rmin:
|
| + rmin = '0'
|
| + else:
|
| + rmin = str(self.rmin)
|
| + if not self.rmax:
|
| + rmax = '+oo'
|
| + else:
|
| + rmax = str(self.rmax)
|
| + return '[%s,%s)' % (rmin, rmax)
|
| +
|
| + def SetReleaseRange(self, rmin, rmax):
|
| + self.rmin = rmin
|
| + self.rmax = rmax
|
| +
|
| + # True, if Release falls within the interval [self.vmin, self.vmax)
|
| + def IsRelease(self, release):
|
| + if self.rmax and self.rmax <= release:
|
| + return False
|
| + if self.rmin and self.rmin > release:
|
| + return False
|
| + if GetOption('release_debug'):
|
| + InfoOut.Log('%f is in %s' % (release, self))
|
| + return True
|
| +
|
| + # True, if Release falls within the interval [self.vmin, self.vmax)
|
| + def InReleases(self, releases):
|
| + if not releases: return False
|
| +
|
| + # Check last release first, since InRange does not match last item
|
| + if self.IsRelease(releases[-1]): return True
|
| + if len(releases) > 1:
|
| + return self.InRange(releases[0], releases[-1])
|
| + return False
|
| +
|
| + # True, if interval [vmin, vmax) overlaps interval [self.vmin, self.vmax)
|
| + def InRange(self, rmin, rmax):
|
| + assert (rmin == None) or rmin < rmax
|
| +
|
| + # An min of None always passes a min bound test
|
| + # An max of None always passes a max bound test
|
| + if rmin is not None and self.rmax is not None:
|
| + if self.rmax <= rmin:
|
| + return False
|
| + if rmax is not None and self.rmin is not None:
|
| + if self.rmin >= rmax:
|
| + return False
|
| +
|
| + if GetOption('release_debug'):
|
| + InfoOut.Log('%f to %f is in %s' % (rmin, rmax, self))
|
| + return True
|
| +
|
| + def GetMinMax(self, releases = None):
|
| + if not releases:
|
| + return self.rmin, self.rmax
|
| +
|
| + if not self.rmin:
|
| + rmin = releases[0]
|
| + else:
|
| + rmin = str(self.rmin)
|
| + if not self.rmax:
|
| + rmax = releases[-1]
|
| + else:
|
| + rmax = str(self.rmax)
|
| + return (rmin, rmax)
|
| +
|
| + def SetMin(self, release):
|
| + assert not self.rmin
|
| + self.rmin = release
|
| +
|
| + def Error(self, msg):
|
| + ReportReleaseError(msg)
|
| +
|
| + def Warn(self, msg):
|
| + ReportReleaseWarning(msg)
|
| +
|
| +
|
| +#
|
| +# IDLReleaseList
|
| +#
|
| +# IDLReleaseList is a list based container for holding IDLRelease
|
| +# objects in order. The IDLReleaseList can be added to, and searched by
|
| +# range. Objects are stored in order, and must be added in order.
|
| +#
|
| +class IDLReleaseList(object):
|
| + def __init__(self):
|
| + self._nodes = []
|
| +
|
| + def GetReleases(self):
|
| + return self._nodes
|
| +
|
| + def FindRelease(self, release):
|
| + for node in self._nodes:
|
| + if node.IsRelease(release):
|
| + return node
|
| + return None
|
| +
|
| + def FindRange(self, rmin, rmax):
|
| + assert (rmin == None) or rmin != rmax
|
| +
|
| + out = []
|
| + for node in self._nodes:
|
| + if node.InRange(rmin, rmax):
|
| + out.append(node)
|
| + return out
|
| +
|
| + def AddNode(self, node):
|
| + if GetOption('release_debug'):
|
| + InfoOut.Log('\nAdding %s %s' % (node.Location(), node))
|
| + last = None
|
| +
|
| + # Check current releases in that namespace
|
| + for cver in self._nodes:
|
| + if GetOption('release_debug'): InfoOut.Log(' Checking %s' % cver)
|
| +
|
| + # We should only be missing a 'release' tag for the first item.
|
| + if not node.rmin:
|
| + node.Error('Missing release on overload of previous %s.' %
|
| + cver.Location())
|
| + return False
|
| +
|
| + # If the node has no max, then set it to this one
|
| + if not cver.rmax:
|
| + cver.rmax = node.rmin
|
| + if GetOption('release_debug'): InfoOut.Log(' Update %s' % cver)
|
| +
|
| + # if the max and min overlap, than's an error
|
| + if cver.rmax > node.rmin:
|
| + if node.rmax and cver.rmin >= node.rmax:
|
| + node.Error('Declarations out of order.')
|
| + else:
|
| + node.Error('Overlap in releases: %s vs %s when adding %s' %
|
| + (cver.rmax, node.rmin, node))
|
| + 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.rmax != node.rmin:
|
| + node.Warn('Gap in release 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('release_debug'): InfoOut.Log('Done %s' % node)
|
| + self._nodes.append(node)
|
| + return True
|
| +
|
| +#
|
| +# IDLReleaseMap
|
| +#
|
| +# A release map, can map from an float interface release, to a global
|
| +# release string.
|
| +#
|
| +class IDLReleaseMap(object):
|
| + def __init__(self, release_info):
|
| + self.version_to_release = {}
|
| + self.release_to_version = {}
|
| + for release, version in release_info:
|
| + self.version_to_release[version] = release
|
| + self.release_to_version[release] = version
|
| + self.releases = sorted(self.release_to_version.keys())
|
| + self.versions = sorted(self.version_to_release.keys())
|
| +
|
| + def GetVersion(self, release):
|
| + return self.release_to_version.get(release, None)
|
| +
|
| + def GetVersions(self):
|
| + return self.versions
|
| +
|
| + def GetRelease(self, version):
|
| + return self.version_to_release.get(version, None)
|
| +
|
| + def GetReleases(self):
|
| + return self.releases
|
| +
|
| + def GetReleaseRange(self):
|
| + return (self.releases[0], self.releases[-1])
|
| +
|
| + def GetVersionRange(self):
|
| + return (self.versions[0], self.version[-1])
|
| +
|
| +#
|
| +# Test Code
|
| +#
|
| +def TestReleaseNode():
|
| + FooXX = IDLRelease(None, None)
|
| + Foo1X = IDLRelease('M14', None)
|
| + Foo23 = IDLRelease('M15', 'M16')
|
| +
|
| + assert FooXX.IsRelease('M13')
|
| + assert FooXX.IsRelease('M14')
|
| + assert FooXX.InRange('M13', 'M13A')
|
| + assert FooXX.InRange('M14','M15')
|
| +
|
| + assert not Foo1X.IsRelease('M13')
|
| + assert Foo1X.IsRelease('M14')
|
| + assert Foo1X.IsRelease('M15')
|
| +
|
| + assert not Foo1X.InRange('M13', 'M14')
|
| + assert not Foo1X.InRange('M13A', 'M14')
|
| + assert Foo1X.InRange('M14', 'M15')
|
| + assert Foo1X.InRange('M15', 'M16')
|
| +
|
| + assert not Foo23.InRange('M13', 'M14')
|
| + assert not Foo23.InRange('M13A', 'M14')
|
| + assert not Foo23.InRange('M14', 'M15')
|
| + assert Foo23.InRange('M15', 'M16')
|
| + assert Foo23.InRange('M14', 'M15A')
|
| + assert Foo23.InRange('M15B', 'M17')
|
| + assert not Foo23.InRange('M16', 'M17')
|
| + print "TestReleaseNode - Passed"
|
| +
|
| +
|
| +def TestReleaseListWarning():
|
| + FooXX = IDLRelease(None, None)
|
| + Foo1X = IDLRelease('M14', None)
|
| + Foo23 = IDLRelease('M15', 'M16')
|
| + Foo45 = IDLRelease('M17', 'M18')
|
| +
|
| + # Add nodes out of order should fail
|
| + ReportClear()
|
| + releases = IDLReleaseList()
|
| + assert releases.AddNode(Foo23)
|
| + assert releases.AddNode(Foo45)
|
| + assert warning
|
| + print "TestReleaseListWarning - Passed"
|
| +
|
| +
|
| +def TestReleaseListError():
|
| + FooXX = IDLRelease(None, None)
|
| + Foo1X = IDLRelease('M14', None)
|
| + Foo23 = IDLRelease('M15', 'M16')
|
| + Foo45 = IDLRelease('M17', 'M18')
|
| +
|
| + # Add nodes out of order should fail
|
| + ReportClear()
|
| + releases = IDLReleaseList()
|
| + assert releases.AddNode(FooXX)
|
| + assert releases.AddNode(Foo23)
|
| + assert not releases.AddNode(Foo1X)
|
| + assert error
|
| + print "TestReleaseListError - Passed"
|
| +
|
| +
|
| +def TestReleaseListOK():
|
| + FooXX = IDLRelease(None, None)
|
| + Foo1X = IDLRelease('M14', None)
|
| + Foo23 = IDLRelease('M15', 'M16')
|
| + Foo45 = IDLRelease('M17', 'M18')
|
| +
|
| + # Add nodes in order should work
|
| + ReportClear()
|
| + releases = IDLReleaseList()
|
| + assert releases.AddNode(FooXX)
|
| + assert releases.AddNode(Foo1X)
|
| + assert releases.AddNode(Foo23)
|
| + assert not error and not warning
|
| + assert releases.AddNode(Foo45)
|
| + assert warning
|
| +
|
| + assert releases.FindRelease('M13') == FooXX
|
| + assert releases.FindRelease('M14') == Foo1X
|
| + assert releases.FindRelease('M15') == Foo23
|
| + assert releases.FindRelease('M16') == None
|
| + assert releases.FindRelease('M17') == Foo45
|
| + assert releases.FindRelease('M18') == None
|
| +
|
| + assert releases.FindRange('M13','M14') == [FooXX]
|
| + assert releases.FindRange('M13','M17') == [FooXX, Foo1X, Foo23]
|
| + assert releases.FindRange('M16','M17') == []
|
| + assert releases.FindRange(None, None) == [FooXX, Foo1X, Foo23, Foo45]
|
| +
|
| + # Verify we can find the correct versions
|
| + print "TestReleaseListOK - Passed"
|
| +
|
| +
|
| +def TestReleaseMap():
|
| + print "TestReleaseMap- Passed"
|
| +
|
| +
|
| +def Main(args):
|
| + TestReleaseNode()
|
| + TestReleaseListWarning()
|
| + TestReleaseListError()
|
| + TestReleaseListOK()
|
| + print "Passed"
|
| + return 0
|
| +
|
| +
|
| +if __name__ == '__main__':
|
| + sys.exit(Main(sys.argv[1:]))
|
| +
|
|
|