diff options
Diffstat (limited to 'tools')
-rw-r--r-- | tools/json_schema_compiler/cc_generator.py | 101 | ||||
-rw-r--r-- | tools/json_schema_compiler/cpp_type_generator.py | 8 | ||||
-rwxr-xr-x | tools/json_schema_compiler/cpp_type_generator_test.py | 16 | ||||
-rw-r--r-- | tools/json_schema_compiler/h_generator.py | 30 | ||||
-rw-r--r-- | tools/json_schema_compiler/idl_schema.py | 120 | ||||
-rwxr-xr-x | tools/json_schema_compiler/idl_schema_test.py | 11 | ||||
-rw-r--r-- | tools/json_schema_compiler/model.py | 4 | ||||
-rw-r--r-- | tools/json_schema_compiler/schema_util.py | 4 | ||||
-rw-r--r-- | tools/json_schema_compiler/test/idl_basics.idl | 4 |
9 files changed, 168 insertions, 130 deletions
diff --git a/tools/json_schema_compiler/cc_generator.py b/tools/json_schema_compiler/cc_generator.py index 1a7f80c..99e0eb3 100644 --- a/tools/json_schema_compiler/cc_generator.py +++ b/tools/json_schema_compiler/cc_generator.py @@ -42,12 +42,6 @@ class CCGenerator(object): ) (c.Append() - .Append('using base::Value;') - .Append('using base::DictionaryValue;') - .Append('using base::ListValue;') - .Append('using base::BinaryValue;') - .Append('using %s;' % any_helper.ANY_CLASS) - .Append() .Concat(self._cpp_type_generator.GetRootNamespaceStart()) .Concat(self._cpp_type_generator.GetNamespaceStart()) .Append() @@ -173,13 +167,13 @@ class CCGenerator(object): c = Code() (c.Append('// static') .Sblock('bool %(namespace)s::Populate' - '(const Value& value, %(name)s* out) {') - .Append('if (!value.IsType(Value::TYPE_DICTIONARY))') + '(const base::Value& value, %(name)s* out) {') + .Append('if (!value.IsType(base::Value::TYPE_DICTIONARY))') .Append(' return false;') ) if type_.properties: - (c.Append('const DictionaryValue* dict = ' - 'static_cast<const DictionaryValue*>(&value);') + (c.Append('const base::DictionaryValue* dict = ' + 'static_cast<const base::DictionaryValue*>(&value);') .Append() ) for prop in type_.properties.values(): @@ -204,12 +198,12 @@ class CCGenerator(object): def _GenerateTypePopulateProperty(self, prop, src, dst): """Generate the code to populate a single property in a type. - src: DictionaryValue* + src: base::DictionaryValue* dst: Type* """ c = Code() value_var = prop.unix_name + '_value' - c.Append('Value* %(value_var)s = NULL;') + c.Append('base::Value* %(value_var)s = NULL;') if prop.optional: (c.Sblock( 'if (%(src)s->GetWithoutPathExpansion("%(key)s", &%(value_var)s)) {' @@ -230,14 +224,16 @@ class CCGenerator(object): return c def _GenerateTypeToValue(self, cpp_namespace, type_): - """Generates a function that serializes the type into a |DictionaryValue|. + """Generates a function that serializes the type into a + |base::DictionaryValue|. E.g. for type "Foo" generates Foo::ToValue() """ c = Code() - (c.Sblock('scoped_ptr<DictionaryValue> %s::ToValue() const {' % + (c.Sblock('scoped_ptr<base::DictionaryValue> %s::ToValue() const {' % cpp_namespace) - .Append('scoped_ptr<DictionaryValue> value(new DictionaryValue());') + .Append('scoped_ptr<base::DictionaryValue> value(' + 'new base::DictionaryValue());') .Append() ) for prop in type_.properties.values(): @@ -287,27 +283,29 @@ class CCGenerator(object): return c def _GenerateCreateEnumValue(self, cpp_namespace, prop): - """Generates CreateEnumValue() that returns the |StringValue| + """Generates CreateEnumValue() that returns the |base::StringValue| representation of an enum. """ c = Code() c.Append('// static') - c.Sblock('scoped_ptr<Value> %(cpp_namespace)s::CreateEnumValue(%(arg)s) {') + c.Sblock('scoped_ptr<base::Value> %(cpp_namespace)s::CreateEnumValue(' + '%(arg)s) {') c.Sblock('switch (%s) {' % prop.unix_name) if prop.optional: (c.Append('case %s: {' % self._cpp_type_generator.GetEnumNoneValue(prop)) - .Append(' return scoped_ptr<Value>();') + .Append(' return scoped_ptr<base::Value>();') .Append('}') ) for enum_value in prop.enum_values: (c.Append('case %s: {' % self._cpp_type_generator.GetEnumValue(prop, enum_value)) - .Append(' return scoped_ptr<Value>(Value::CreateStringValue("%s"));' % - enum_value) + .Append(' return scoped_ptr<base::Value>(' + 'base::Value::CreateStringValue("%s"));' % + enum_value) .Append('}') ) (c.Append('default: {') - .Append(' return scoped_ptr<Value>();') + .Append(' return scoped_ptr<base::Value>();') .Append('}') ) c.Eblock('}') @@ -320,20 +318,20 @@ class CCGenerator(object): return c def _CreateValueFromProperty(self, prop, var): - """Creates a Value given a property. Generated code passes ownership + """Creates a base::Value given a property. Generated code passes ownership to caller. var: variable or variable* - E.g for std::string, generate Value::CreateStringValue(var) + E.g for std::string, generate base::Value::CreateStringValue(var) """ if prop.type_ == PropertyType.CHOICES: # CHOICES conversion not implemented. If needed, write something to - # generate a function that returns a scoped_ptr<Value> and put it in + # generate a function that returns a scoped_ptr<base::Value> and put it in # _GeneratePropertyFunctions, then use it here. Look at CreateEnumValue() # for reference. raise NotImplementedError( - 'Conversion of CHOICES to Value not implemented') + 'Conversion of CHOICES to base::Value not implemented') if self._IsObjectOrObjectRef(prop): if prop.optional: return '%s->ToValue().release()' % var @@ -356,13 +354,13 @@ class CCGenerator(object): var = '*' + var prop = self._cpp_type_generator.GetReferencedProperty(prop); return { - PropertyType.STRING: 'Value::CreateStringValue(%s)', - PropertyType.BOOLEAN: 'Value::CreateBooleanValue(%s)', - PropertyType.INTEGER: 'Value::CreateIntegerValue(%s)', - PropertyType.DOUBLE: 'Value::CreateDoubleValue(%s)', + PropertyType.STRING: 'base::Value::CreateStringValue(%s)', + PropertyType.BOOLEAN: 'base::Value::CreateBooleanValue(%s)', + PropertyType.INTEGER: 'base::Value::CreateIntegerValue(%s)', + PropertyType.DOUBLE: 'base::Value::CreateDoubleValue(%s)', }[prop.type_] % var else: - raise NotImplementedError('Conversion of %s to Value not ' + raise NotImplementedError('Conversion of %s to base::Value not ' 'implemented' % repr(prop.type_)) def _GenerateParamsCheck(self, function, var): @@ -391,14 +389,14 @@ class CCGenerator(object): def _GenerateFunctionParamsCreate(self, cpp_namespace, function): """Generate function to create an instance of Params. The generated - function takes a ListValue of arguments. + function takes a base::ListValue of arguments. E.g for function "Bar", generate Bar::Params::Create() """ c = Code() (c.Append('// static') .Sblock('scoped_ptr<%(cpp_namespace)s::Params> ' - '%(cpp_namespace)s::Params::Create(const ListValue& args) {') + '%(cpp_namespace)s::Params::Create(const base::ListValue& args) {') .Concat(self._GenerateParamsCheck(function, 'args')) .Append('scoped_ptr<Params> params(new Params());') ) @@ -415,9 +413,9 @@ class CCGenerator(object): failure_value = 'scoped_ptr<Params>()' c.Append() value_var = param.unix_name + '_value' - (c.Append('Value* %(value_var)s = NULL;') - .Append('if (args.Get(%(i)s, &%(value_var)s) && ' - '!%(value_var)s->IsType(Value::TYPE_NULL))') + (c.Append('base::Value* %(value_var)s = NULL;') + .Append('if (args.Get(%(i)s, &%(value_var)s) &&\n' + ' !%(value_var)s->IsType(base::Value::TYPE_NULL))') .Sblock('{') .Concat(self._GeneratePopulatePropertyFromValue( param, value_var, 'params', failure_value)) @@ -439,16 +437,17 @@ class CCGenerator(object): def _GeneratePopulatePropertyFromValue( self, prop, value_var, dst, failure_value, check_type=True): - """Generates code to populate a model.Property given a Value*. The - existence of data inside the Value* is assumed so checks for existence + """Generates code to populate a model.Property given a base::Value*. The + existence of data inside the base::Value* is assumed so checks for existence should be performed before the code this generates. prop: the property the code is populating. - value_var: a Value* that should represent |prop|. + value_var: a base::Value* that should represent |prop|. dst: the object with |prop| as a member. failure_value: the value to return if |prop| cannot be extracted from |value_var| - check_type: if true, will check if |value_var| is the correct Value::Type + check_type: if true, will check if |value_var| is the correct + base::Value::Type """ c = Code() c.Sblock('{') @@ -474,7 +473,7 @@ class CCGenerator(object): ) elif self._IsObjectOrObjectRef(prop): if prop.optional: - (c.Append('DictionaryValue* dictionary = NULL;') + (c.Append('base::DictionaryValue* dictionary = NULL;') .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') .Append(' return %(failure_value)s;') .Append('scoped_ptr<%(ctype)s> temp(new %(ctype)s());') @@ -483,7 +482,7 @@ class CCGenerator(object): .Append('%(dst)s->%(name)s = temp.Pass();') ) else: - (c.Append('DictionaryValue* dictionary = NULL;') + (c.Append('base::DictionaryValue* dictionary = NULL;') .Append('if (!%(value_var)s->GetAsDictionary(&dictionary))') .Append(' return %(failure_value)s;') .Append( @@ -492,11 +491,11 @@ class CCGenerator(object): ) elif prop.type_ == PropertyType.ANY: if prop.optional: - c.Append('%(dst)s->%(name)s.reset(new Any());') + c.Append('%(dst)s->%(name)s.reset(new ' + any_helper.ANY_CLASS + '());') c.Append(self._any_helper.Init(prop, value_var, dst) + ';') elif self._IsArrayOrArrayRef(prop): # util_cc_helper deals with optional and required arrays - (c.Append('ListValue* list = NULL;') + (c.Append('base::ListValue* list = NULL;') .Append('if (!%(value_var)s->GetAsList(&list))') .Append(' return %(failure_value)s;')) if prop.item_type.type_ == PropertyType.ENUM: @@ -533,12 +532,13 @@ class CCGenerator(object): c.Eblock('}') elif prop.type_ == PropertyType.BINARY: # This is the same if the property is optional or not. We need a pointer - # to the BinaryValue to be able to populate it, so a scoped_ptr is used - # whether it is optional or required. + # to the base::BinaryValue to be able to populate it, so a scoped_ptr is + # used whether it is optional or required. (c.Append('if (!%(value_var)s->IsType(%(value_type)s))') .Append(' return %(failure_value)s;') .Append('%(dst)s->%(name)s.reset(') - .Append(' static_cast<BinaryValue*>(%(value_var)s)->DeepCopy());') + .Append(' static_cast<base::BinaryValue*>(%(value_var)s)' + '->DeepCopy());') ) else: raise NotImplementedError(prop.type_) @@ -632,8 +632,8 @@ class CCGenerator(object): params = function.callback.params if not params: - (c.Append('Value* %s::Result::Create() {' % cpp_namespace) - .Append(' return Value::CreateNullValue();') + (c.Append('base::Value* %s::Result::Create() {' % cpp_namespace) + .Append(' return base::Value::CreateNullValue();') .Append('}') ) else: @@ -648,13 +648,14 @@ class CCGenerator(object): # time. for param in expanded_params: if param.type_ == PropertyType.ANY: - # Generation of Value* Create(Value*) is redundant. + # Generation of base::Value* Create(base::Value*) is redundant. continue # We treat this argument as 'required' to avoid wrapping it in a # scoped_ptr if it's optional. param_copy = param.Copy() param_copy.optional = False - c.Sblock('Value* %(cpp_namespace)s::Result::Create(const %(arg)s) {') + c.Sblock('base::Value* %(cpp_namespace)s::Result::Create(' + 'const %(arg)s) {') c.Append('return %s;' % self._CreateValueFromProperty(param_copy, param_copy.unix_name)) c.Eblock('}') diff --git a/tools/json_schema_compiler/cpp_type_generator.py b/tools/json_schema_compiler/cpp_type_generator.py index 55cb36e..28967b0 100644 --- a/tools/json_schema_compiler/cpp_type_generator.py +++ b/tools/json_schema_compiler/cpp_type_generator.py @@ -7,7 +7,6 @@ from model import PropertyType import any_helper import cpp_util import schema_util -import string class CppTypeGenerator(object): """Manages the types of properties and provides utilities for getting the @@ -191,9 +190,10 @@ class CppTypeGenerator(object): c.Append('typedef std::string %s;' % type_name) elif namespace.types[type_].type_ == PropertyType.ARRAY: c.Append('typedef std::vector<%(item_type)s> %(name)s;') - c.Substitute({'name': type_name, 'item_type': - self.GetType(namespace.types[type_].item_type, - wrap_optional=True)}) + c.Substitute({ + 'name': type_name, + 'item_type': self.GetType(namespace.types[type_].item_type, + wrap_optional=True)}) else: c.Append('struct %s;' % type_name) c.Append('}') diff --git a/tools/json_schema_compiler/cpp_type_generator_test.py b/tools/json_schema_compiler/cpp_type_generator_test.py index b22c430..7c74fad 100755 --- a/tools/json_schema_compiler/cpp_type_generator_test.py +++ b/tools/json_schema_compiler/cpp_type_generator_test.py @@ -59,12 +59,14 @@ class CppTypeGeneratorTest(unittest.TestCase): def testGenerateIncludesAndForwardDeclarationsMultipleTypes(self): m = model.Model() self.tabs_json[0]['types'].append(self.permissions_json[0]['types'][0]) - tabs_namespace = m.AddNamespace(self.tabs_json[0], - 'path/to/tabs.json') self.windows_json[0]['functions'].append( self.permissions_json[0]['functions'][1]) + # Insert 'windows' before 'tabs' in order to test that they are sorted + # properly. windows = m.AddNamespace(self.windows_json[0], 'path/to/windows.json') + tabs_namespace = m.AddNamespace(self.tabs_json[0], + 'path/to/tabs.json') manager = CppTypeGenerator('', windows, self.windows.unix_name) manager.AddNamespace(tabs_namespace, self.tabs.unix_name) self.assertEquals('#include "path/to/tabs.h"', @@ -81,16 +83,18 @@ class CppTypeGeneratorTest(unittest.TestCase): def testGenerateIncludesAndForwardDeclarationsDependencies(self): m = model.Model() - browser_action_namespace = m.AddNamespace(self.browser_action_json[0], - 'path/to/browser_action.json') + # Insert 'font_settings' before 'browser_action' in order to test that + # CppTypeGenerator sorts them properly. font_settings_namespace = m.AddNamespace(self.font_settings_json[0], 'path/to/font_settings.json') + browser_action_namespace = m.AddNamespace(self.browser_action_json[0], + 'path/to/browser_action.json') manager = CppTypeGenerator('', self.dependency_tester, self.dependency_tester.unix_name) - manager.AddNamespace(browser_action_namespace, - self.browser_action.unix_name) manager.AddNamespace(font_settings_namespace, self.font_settings.unix_name) + manager.AddNamespace(browser_action_namespace, + self.browser_action.unix_name) self.assertEquals('#include "path/to/browser_action.h"\n' '#include "path/to/font_settings.h"', manager.GenerateIncludes().Render()) diff --git a/tools/json_schema_compiler/h_generator.py b/tools/json_schema_compiler/h_generator.py index b5801ef..30a357d 100644 --- a/tools/json_schema_compiler/h_generator.py +++ b/tools/json_schema_compiler/h_generator.py @@ -5,8 +5,6 @@ from code import Code from model import PropertyType import cpp_util -import model -import os import schema_util class HGenerator(object): @@ -110,7 +108,8 @@ class HGenerator(object): raise ValueError("Illegal circular dependency via cycle " + ", ".join(map(lambda x: x.name, path + [type_]))) for prop in type_.properties.values(): - if not prop.optional and prop.type_ == PropertyType.REF: + if (prop.type_ == PropertyType.REF and + schema_util.GetNamespace(prop.ref_type) == self._namespace.name): ExpandType(path + [type_], self._namespace.types[prop.ref_type]) if not type_ in dependency_order: dependency_order.append(type_) @@ -177,7 +176,6 @@ class HGenerator(object): if type_.description: c.Comment(type_.description) c.Append('typedef std::string %(classname)s;') - c.Substitute({'classname': classname}) else: if type_.description: c.Comment(type_.description) @@ -189,18 +187,18 @@ class HGenerator(object): .Concat(self._GenerateFields(type_.properties.values())) ) if type_.from_json: - (c.Comment('Populates a %s object from a Value. Returns' + (c.Comment('Populates a %s object from a base::Value. Returns' ' whether |out| was successfully populated.' % classname) - .Append( - 'static bool Populate(const Value& value, %(classname)s* out);') + .Append('static bool Populate(const base::Value& value, ' + '%(classname)s* out);') .Append() ) if type_.from_client: - (c.Comment('Returns a new DictionaryValue representing the' + (c.Comment('Returns a new base::DictionaryValue representing the' ' serialized form of this %s object. Passes ' 'ownership to caller.' % classname) - .Append('scoped_ptr<DictionaryValue> ToValue() const;') + .Append('scoped_ptr<base::DictionaryValue> ToValue() const;') ) (c.Eblock() @@ -238,7 +236,8 @@ class HGenerator(object): .Concat(self._GenerateFields(function.params)) .Append('~Params();') .Append() - .Append('static scoped_ptr<Params> Create(const ListValue& args);') + .Append('static scoped_ptr<Params> Create(' + 'const base::ListValue& args);') .Eblock() .Sblock(' private:') .Append('Params();') @@ -273,7 +272,7 @@ class HGenerator(object): enum_name, prop, prop.enum_values)) - c.Append('static scoped_ptr<Value> CreateEnumValue(%s %s);' % + c.Append('static scoped_ptr<base::Value> CreateEnumValue(%s %s);' % (enum_name, prop.unix_name)) return c @@ -285,7 +284,7 @@ class HGenerator(object): c.Sblock('namespace Result {') params = function.callback.params if not params: - c.Append('Value* Create();') + c.Append('base::Value* Create();') else: c.Concat(self._GeneratePropertyStructures(params)) @@ -297,11 +296,12 @@ class HGenerator(object): if param.description: c.Comment(param.description) if param.type_ == PropertyType.ANY: - c.Comment("Value* Result::Create(Value*) not generated " + c.Comment("base::Value* Result::Create(base::Value*) not generated " "because it's redundant.") continue - c.Append('Value* Create(const %s);' % cpp_util.GetParameterDeclaration( - param, self._cpp_type_generator.GetType(param))) + c.Append('base::Value* Create(const %s);' % + cpp_util.GetParameterDeclaration( + param, self._cpp_type_generator.GetType(param))) c.Eblock('};') return c diff --git a/tools/json_schema_compiler/idl_schema.py b/tools/json_schema_compiler/idl_schema.py index 09b75a2..d59103b 100644 --- a/tools/json_schema_compiler/idl_schema.py +++ b/tools/json_schema_compiler/idl_schema.py @@ -55,7 +55,7 @@ def ProcessComment(comment): # Escape double quotes. comment = comment.replace('"', '\\"'); - # Find all the parameter comments of the form "|name|: comment". + # Find all the parameter comments of the form '|name|: comment'. parameter_starts = list(re.finditer(r'\n *\|([^|]*)\| *: *', comment)) # Get the parent comment (everything before the first parameter comment. @@ -104,9 +104,9 @@ class Param(object): self.node = param_node def process(self, callbacks): - return Typeref(self.node.GetProperty( 'TYPEREF'), + return Typeref(self.node.GetProperty('TYPEREF'), self.node, - { 'name': self.node.GetName() }).process(callbacks) + {'name': self.node.GetName()}).process(callbacks) class Dictionary(object): ''' @@ -122,30 +122,12 @@ class Dictionary(object): if node.cls == 'Member': k, v = Member(node).process(callbacks) properties[k] = v - return { 'id': self.node.GetName(), - 'properties': properties, - 'type': 'object' } - -class Enum(object): - ''' - Given an IDL Enum node, converts into a Python dictionary that the JSON - schema compiler expects to see. - ''' - def __init__(self, enum_node): - self.node = enum_node - - def process(self, callbacks): - enum = [] - for node in self.node.children: - if node.cls == 'EnumItem': - name = node.GetName() - enum.append(name) - else: - sys.exit("Did not process %s %s" % (node.cls, node)) - return { "id" : self.node.GetName(), - 'enum': enum, - 'type': 'string' } - + result = {'id': self.node.GetName(), + 'properties': properties, + 'type': 'object'} + if self.node.GetProperty('inline_doc'): + result['inline_doc'] = True + return result class Member(object): @@ -169,8 +151,7 @@ class Member(object): if node.cls == 'Comment': (parent_comment, parameter_comments) = ProcessComment(node.GetName()) properties['description'] = parent_comment - for node in self.node.children: - if node.cls == 'Callspec': + elif node.cls == 'Callspec': is_function = True name, parameters = Callspec(node, parameter_comments).process(callbacks) properties['parameters'] = parameters @@ -180,6 +161,13 @@ class Member(object): else: properties = Typeref(self.node.GetProperty('TYPEREF'), self.node, properties).process(callbacks) + enum_values = self.node.GetProperty('legalValues') + if enum_values: + if properties['type'] == 'integer': + enum_values = map(int, enum_values) + elif properties['type'] == 'double': + enum_values = map(float, enum_values) + properties['enum'] = enum_values return name, properties class Typeref(object): @@ -240,42 +228,70 @@ class Typeref(object): return result + +class Enum(object): + ''' + Given an IDL Enum node, converts into a Python dictionary that the JSON + schema compiler expects to see. + ''' + def __init__(self, enum_node): + self.node = enum_node + self.description = '' + + def process(self, callbacks): + enum = [] + for node in self.node.children: + if node.cls == 'EnumItem': + enum.append(node.GetName()) + elif node.cls == 'Comment': + self.description = ProcessComment(node.GetName())[0] + else: + sys.exit('Did not process %s %s' % (node.cls, node)) + result = {'id' : self.node.GetName(), + 'description': self.description, + 'type': 'string', + 'enum': enum} + if self.node.GetProperty('inline_doc'): + result['inline_doc'] = True + return result + + 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, nodoc=False): + def __init__(self, namespace_node, nodoc=False, permissions=None): self.namespace = namespace_node self.nodoc = nodoc self.events = [] self.functions = [] self.types = [] self.callbacks = {} + self.permissions = permissions or [] def process(self): for node in self.namespace.children: - cls = node.cls - if cls == "Dictionary": + if node.cls == 'Dictionary': self.types.append(Dictionary(node).process(self.callbacks)) - elif cls == "Callback": + elif node.cls == 'Callback': k, v = Member(node).process(self.callbacks) self.callbacks[k] = v - elif cls == "Interface" and node.GetName() == "Functions": + elif node.cls == 'Interface' and node.GetName() == 'Functions': self.functions = self.process_interface(node) - elif cls == "Interface" and node.GetName() == "Events": + elif node.cls == 'Interface' and node.GetName() == 'Events': self.events = self.process_interface(node) - elif cls == "Enum": + elif node.cls == 'Enum': self.types.append(Enum(node).process(self.callbacks)) else: - sys.exit("Did not process %s %s" % (node.cls, node)) - - return { 'events': self.events, - 'functions': self.functions, - 'types': self.types, - 'namespace': self.namespace.GetName(), - 'nodoc': self.nodoc } + sys.exit('Did not process %s %s' % (node.cls, node)) + return {'namespace': self.namespace.GetName(), + 'nodoc': self.nodoc, + 'documentation_permissions_required': self.permissions, + 'types': self.types, + 'functions': self.functions, + 'events': self.events} def process_interface(self, node): members = [] @@ -296,23 +312,25 @@ class IDLSchema(object): def process(self): namespaces = [] + nodoc = False + permissions = None for node in self.idl: - nodoc = False - cls = node.cls - if cls == 'Namespace': - namespace = Namespace(node, nodoc) + if node.cls == 'Namespace': + namespace = Namespace(node, nodoc, permissions) namespaces.append(namespace.process()) - elif cls == 'Copyright': + elif node.cls == 'Copyright': continue - elif cls == 'Comment': + elif node.cls == 'Comment': continue - elif cls == 'ExtAttribute': + elif node.cls == 'ExtAttribute': if node.name == 'nodoc': nodoc = bool(node.value) + elif node.name == 'permissions': + permission = node.value.split(',') else: continue else: - sys.exit("Did not process %s %s" % (node.cls, node)) + sys.exit('Did not process %s %s' % (node.cls, node)) schema_util.PrefixSchemasWithNamespace(namespaces) return namespaces diff --git a/tools/json_schema_compiler/idl_schema_test.py b/tools/json_schema_compiler/idl_schema_test.py index f83d616..71bf987 100755 --- a/tools/json_schema_compiler/idl_schema_test.py +++ b/tools/json_schema_compiler/idl_schema_test.py @@ -56,11 +56,18 @@ class IdlSchemaTest(unittest.TestCase): 'parameters':[{'type':'integer', 'name':'x'}]}}] self.assertEquals(expected, getParams(schema, 'whatever')) + def testLegalValues(self): + self.assertEquals({ + 'x': {'name': 'x', 'type': 'integer', 'enum': [1,2], + 'description': 'This comment tests \\\"double-quotes\\\".'}, + 'y': {'name': 'y', 'type': 'string'}}, + getType(self.idl_basics, 'idl_basics.MyType1')['properties']) + def testEnum(self): schema = self.idl_basics - expected = {'enum': ['name1', 'name2'], + expected = {'enum': ['name1', 'name2'], 'description': 'Enum description', 'type': 'string', 'id': 'idl_basics.EnumType'} - self.assertEquals(expected, getType(schema, 'idl_basics.EnumType')) + self.assertEquals(expected, getType(schema, expected['id'])) expected = [{'name':'type', '$ref':'idl_basics.EnumType'}, {'type':'function', 'name':'Callback5', diff --git a/tools/json_schema_compiler/model.py b/tools/json_schema_compiler/model.py index 63973d4..bb3fe0e 100644 --- a/tools/json_schema_compiler/model.py +++ b/tools/json_schema_compiler/model.py @@ -193,7 +193,9 @@ class Property(object): elif '$ref' in json: self.ref_type = json['$ref'] self.type_ = PropertyType.REF - elif 'enum' in json: + elif 'enum' in json and json.get('type') == 'string': + # Non-string enums (as in the case of [legalValues=(1,2)]) should fall + # through to the next elif. self.enum_values = [] for value in json['enum']: self.enum_values.append(value) diff --git a/tools/json_schema_compiler/schema_util.py b/tools/json_schema_compiler/schema_util.py index 289d24d..177e77f 100644 --- a/tools/json_schema_compiler/schema_util.py +++ b/tools/json_schema_compiler/schema_util.py @@ -4,6 +4,10 @@ """Utilies for the processing of schema python structures. """ +def GetNamespace(ref_type): + if '.' in ref_type: + return ref_type[:ref_type.rindex('.')] + def StripSchemaNamespace(s): last_dot = s.rfind('.') if not last_dot == -1: diff --git a/tools/json_schema_compiler/test/idl_basics.idl b/tools/json_schema_compiler/test/idl_basics.idl index af5442e..39298ec 100644 --- a/tools/json_schema_compiler/test/idl_basics.idl +++ b/tools/json_schema_compiler/test/idl_basics.idl @@ -5,13 +5,15 @@ // Tests a variety of basic API definition features. namespace idl_basics { + // Enum description enum EnumType { name1, name2 }; dictionary MyType1 { - long x; // This comment tests "double-quotes". + // This comment tests "double-quotes". + [legalValues=(1,2)] long x; DOMString y; }; |