Index: tools/json_schema_compiler/idl_schema.py |
diff --git a/tools/json_schema_compiler/idl_schema.py b/tools/json_schema_compiler/idl_schema.py |
new file mode 100644 |
index 0000000000000000000000000000000000000000..540ba2bc105c4197cb04bb120e3b95f4d9ba42ab |
--- /dev/null |
+++ b/tools/json_schema_compiler/idl_schema.py |
@@ -0,0 +1,182 @@ |
+# 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. |
+ |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
nit: might be worth having an overview comment her
|
+import os.path |
+import sys |
+ |
+idl_generators_path = os.path.join(os.path.dirname(os.path.realpath(__file__)), |
+ os.pardir, os.pardir, 'ppapi', 'generators') |
+if idl_generators_path not in sys.path: |
+ sys.path.insert(0, idl_generators_path) |
+import idl_parser |
+ |
+class Callspec(object): |
+ ''' |
+ Given a Callspec node representing an IDL namespace, converts into a Python |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
"an IDL namespace" -> "an IDL function declaration
|
+ dictionary that the JSON schema compiler expects to see. |
+ ''' |
+ def __init__(self, callspec_node): |
+ self.node = callspec_node |
+ |
+ def process(self, refs): |
+ parameters = [] |
+ for node in self.node.children: |
+ parameters.append(Param(node).process(refs)) |
+ return self.node.GetName(), parameters |
+ |
+class Param(object): |
+ ''' |
+ Given a Param node representing an IDL namespace, converts into a Python |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
"an IDL namespace" -> "a function parameter"
|
+ dictionary that the JSON schema compiler expects to see. |
+ ''' |
+ def __init__(self, param_node): |
+ self.node = param_node |
+ |
+ def process(self, refs): |
+ properties = { 'name': self.node.GetName() } |
+ return dict(properties.items() + |
+ Typeref(self.node.GetProperty( |
+ 'TYPEREF'), self.node).process(refs).items()) |
+ |
+class Dictionary(object): |
+ ''' |
+ Given a Dictionary node representing an IDL namespace, converts into a Python |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
"an IDL namespace" -> "an IDL dictionary"
|
+ dictionary that the JSON schema compiler expects to see. |
+ ''' |
+ def __init__(self, dictionary_node): |
+ self.node = dictionary_node |
+ |
+ def process(self, refs): |
+ properties = {} |
+ for node in self.node.children: |
+ if node.cls == 'Member': |
+ k, v = Member(node).process(refs) |
+ properties[k] = v |
+ return { 'id': self.node.GetName(), |
+ 'properties': properties, |
+ 'type': 'object' } |
+ |
+class Member(object): |
+ ''' |
+ Given a Member node representing an IDL namespace, converts into a Python |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
"an IDL namespace" -> "an IDL dictionary or interf
|
+ dictionary that the JSON schema compiler expects to see. |
+ ''' |
+ def __init__(self, member_node): |
+ self.node = member_node |
+ |
+ def process(self, refs): |
+ properties = {} |
+ name = self.node.GetName() |
+ if self.node.GetProperty('OPTIONAL'): |
+ properties['optional'] = True |
+ if self.node.GetProperty('nodoc'): |
+ properties['nodoc'] = True |
+ for node in self.node.children: |
+ if node.cls == 'Callspec': |
+ name, parameters = Callspec(node).process(refs) |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
It would be nice to enforce somewhere that this ca
|
+ properties['parameters'] = parameters |
+ properties['name'] = name |
+ typeref = self.node.GetProperty('TYPEREF') |
+ if typeref == 'void': |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
Instead of looking for typeref==void to tell if th
miket_OOO
2012/03/07 00:23:01
Done.
|
+ properties['type'] = 'function' |
+ else: |
+ properties = dict(properties.items() + |
+ Typeref(typeref, self.node).process(refs).items()) |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
would it be clearer if instead of merging dict's h
miket_OOO
2012/03/07 00:23:01
Yes, great idea! Done.
|
+ return name, properties |
+ |
+class Typeref(object): |
+ ''' |
+ Given a TYPEREF property representing an IDL namespace, converts into a |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
"an IDL namespace" -> "the type of a dictionary me
|
+ Python dictionary that the JSON schema compiler expects to see. |
+ ''' |
+ def __init__(self, typeref, parent): |
+ self.typeref = typeref |
+ self.parent = parent |
+ |
+ def process(self, refs): |
+ properties = {} |
+ if self.typeref == 'DOMString': |
+ properties['type'] = 'string' |
+ elif self.typeref == 'boolean': |
+ properties['type'] = 'boolean' |
+ elif self.typeref == 'long': |
+ properties['type'] = 'integer' |
+ elif self.typeref is None: |
+ properties['type'] = 'function' |
+ else: |
+ try: |
+ properties = refs[self.typeref] |
+ except KeyError, e: |
+ properties['$ref'] = self.typeref |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
Someday it would be cool to take note of not-yet-d
miket_OOO
2012/03/07 00:23:01
Agreed -- though at present, it's caught loudly an
asargent_no_longer_on_chrome
2012/03/07 00:42:09
Good point!
|
+ return properties |
+ |
+class Namespace(object): |
+ ''' |
+ Given an IDLNode representing an IDL namespace, converts into a Python |
+ dictionary that the JSON schema compiler expects to see. |
+ ''' |
+ |
+ def __init__(self, namespace_node): |
+ self.namespace = namespace_node |
+ self.events = [] |
+ self.functions = [] |
+ self.types = [] |
+ self.refs = {} |
+ |
+ def process(self): |
+ for node in self.namespace.children: |
+ cls = node.cls |
+ if cls == "Dictionary": |
+ self.types.append(Dictionary(node).process(self.refs)) |
+ elif cls == "Callback": |
+ k, v = Member(node).process(self.refs) |
+ self.refs[k] = v |
+ elif cls == "Interface" and node.GetName() == "Functions": |
+ self.functions = self.process_interface(node) |
+ elif cls == "Interface" and node.GetName() == "Events": |
+ self.events = self.process_interface(node) |
+ |
+ return { 'events': self.events, |
+ 'functions': self.functions, |
+ 'types': self.types, |
+ 'namespace': self.namespace.GetName() } |
asargent_no_longer_on_chrome
2012/03/06 22:27:57
looks like you're missing the 'nodoc' attribute if
miket_OOO
2012/03/07 00:23:01
Fixed. I know I'm being inconsistent here because
asargent_no_longer_on_chrome
2012/03/07 00:42:09
Good point. (It was actually seeing the code elsew
|
+ |
+ def process_interface(self, node): |
+ members = [] |
+ for member in node.children: |
+ if member.cls == 'Member': |
+ name, properties = Member(member).process(self.refs) |
+ members.append(properties) |
+ return members |
+ |
+class IDLSchema(object): |
+ ''' |
+ Given a list of IDLNodes and IDLAttributes, converts into a Python list |
+ of api_defs that the JSON schema compiler expects to see. |
+ ''' |
+ |
+ def __init__(self, idl): |
+ self.idl = idl |
+ |
+ def process(self): |
+ namespaces = [] |
+ for node in self.idl: |
+ if node.cls == 'Namespace': |
+ namespace = Namespace(node) |
+ namespaces.append(namespace.process()) |
+ return namespaces |
+ |
+def Load(filename): |
+ ''' |
+ Given the filename of an IDL file, parses it and returns an equivalent |
+ Python dictionary in a format that the JSON schema compiler expects to see. |
+ ''' |
+ |
+ f = open(filename, 'r') |
+ contents = f.read() |
+ f.close() |
+ |
+ idl = idl_parser.IDLParser().ParseData(contents, filename) |
+ idl_schema = IDLSchema(idl) |
+ return idl_schema.process() |