Chromium Code Reviews| 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() |