It will check whether base is set, whether discriminator is found in base, whether the values specified are written correctly, and whether all enum values are covered, when discriminator is a pre-defined enum type. Exprs now have addtional info inside qapi.py to form better error message.
Signed-off-by: Wenchao Xia <xiaw...@linux.vnet.ibm.com> --- scripts/qapi.py | 84 +++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 files changed, 82 insertions(+), 2 deletions(-) diff --git a/scripts/qapi.py b/scripts/qapi.py index c504eb4..8af8cfd 100644 --- a/scripts/qapi.py +++ b/scripts/qapi.py @@ -50,6 +50,15 @@ class QAPISchemaError(Exception): def __str__(self): return "%s:%s:%s: %s" % (self.fp.name, self.line, self.col, self.msg) +class QAPIExprError(Exception): + def __init__(self, expr_elem, msg): + self.fp = expr_elem['fp'] + self.line = expr_elem['line'] + self.msg = msg + + def __str__(self): + return "%s:%s: %s" % (self.fp.name, self.line, self.msg) + class QAPISchema: def __init__(self, fp): @@ -64,7 +73,11 @@ class QAPISchema: self.accept() while self.tok != None: - self.exprs.append(self.get_expr(False)) + line = self.line + expr_elem = {'expr': self.get_expr(False), + 'fp': fp, + 'line': line} + self.exprs.append(expr_elem) def accept(self): while True: @@ -162,6 +175,66 @@ class QAPISchema: raise QAPISchemaError(self, 'Expected "{", "[" or string') return expr +# This function can be used to check whether "base" is valid +def find_base_fields(base): + base_struct_define = find_struct(base) + if not base_struct_define: + return None + return base_struct_define.get('data') + +# Return the discriminator enum define, if discriminator is specified in +# @expr_elem["expr"] and it is a pre-defined enum type +def discriminator_find_enum_define(expr_elem): + expr = expr_elem['expr'] + discriminator = expr.get('discriminator') + base = expr.get('base') + + # Only support discriminator when base present + if not (discriminator and base): + return None + + base_fields = find_base_fields(base) + + if not base_fields: + raise QAPIExprError(expr_elem, + "Base '%s' is not a valid type" + % base) + + discriminator_type = base_fields.get(discriminator) + + if not discriminator_type: + raise QAPIExprError(expr_elem, + "Discriminator '%s' not found in schema" + % discriminator) + + return find_enum(discriminator_type) + +def check_union(expr_elem): + # If discriminator is specified and it is a pre-defined enum in schema, + # check its correctness + enum_define = discriminator_find_enum_define(expr_elem) + name = expr_elem['expr']['union'] + members = expr_elem['expr']['data'] + if enum_define: + for key in members: + if not key in enum_define['enum_values']: + raise QAPIExprError(expr_elem, + "Discriminator value '%s' is not found in " + "enum '%s'" % + (key, enum_define["enum_name"])) + for key in enum_define['enum_values']: + if not key in members: + raise QAPIExprError(expr_elem, + "Enum value '%s' is not covered by a " + "branch of union '%s'" % + (key, name)) + +def check_exprs(schema): + for expr_elem in schema.exprs: + expr = expr_elem['expr'] + if expr.has_key('union'): + check_union(expr_elem) + def parse_schema(fp): try: schema = QAPISchema(fp) @@ -171,7 +244,8 @@ def parse_schema(fp): exprs = [] - for expr in schema.exprs: + for expr_elem in schema.exprs: + expr = expr_elem['expr'] if expr.has_key('enum'): add_enum(expr['enum'], expr['data']) elif expr.has_key('union'): @@ -181,6 +255,12 @@ def parse_schema(fp): add_struct(expr) exprs.append(expr) + try: + check_exprs(schema) + except QAPIExprError, e: + print >>sys.stderr, e + exit(1) + return exprs def parse_args(typeinfo): -- 1.7.1