mirror of https://gitee.com/openkylin/qemu.git
qapi/schema: Reorder classes so related ones are together
Move QAPISchemaAlternateType up some, so that all QAPISchemaFOOType are together. Move QAPISchemaObjectTypeVariants right behind its users. Signed-off-by: Markus Armbruster <armbru@redhat.com> Reviewed-by: Marc-André Lureau <marcandre.lureau@redhat.com> Message-Id: <20200317115459.31821-18-armbru@redhat.com>
This commit is contained in:
parent
ed30f58dde
commit
226b5be6d4
|
@ -444,82 +444,72 @@ def visit(self, visitor):
|
||||||
self.members, self.variants)
|
self.members, self.variants)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaMember:
|
class QAPISchemaAlternateType(QAPISchemaType):
|
||||||
""" Represents object members, enum members and features """
|
meta = 'alternate'
|
||||||
role = 'member'
|
|
||||||
|
|
||||||
def __init__(self, name, info, ifcond=None):
|
def __init__(self, name, info, doc, ifcond, features, variants):
|
||||||
assert isinstance(name, str)
|
super().__init__(name, info, doc, ifcond, features)
|
||||||
self.name = name
|
assert isinstance(variants, QAPISchemaObjectTypeVariants)
|
||||||
self.info = info
|
assert variants.tag_member
|
||||||
self.ifcond = ifcond or []
|
variants.set_defined_in(name)
|
||||||
self.defined_in = None
|
variants.tag_member.set_defined_in(self.name)
|
||||||
|
self.variants = variants
|
||||||
def set_defined_in(self, name):
|
|
||||||
assert not self.defined_in
|
|
||||||
self.defined_in = name
|
|
||||||
|
|
||||||
def check_clash(self, info, seen):
|
|
||||||
cname = c_name(self.name)
|
|
||||||
if cname in seen:
|
|
||||||
raise QAPISemError(
|
|
||||||
info,
|
|
||||||
"%s collides with %s"
|
|
||||||
% (self.describe(info), seen[cname].describe(info)))
|
|
||||||
seen[cname] = self
|
|
||||||
|
|
||||||
def describe(self, info):
|
|
||||||
role = self.role
|
|
||||||
defined_in = self.defined_in
|
|
||||||
assert defined_in
|
|
||||||
|
|
||||||
if defined_in.startswith('q_obj_'):
|
|
||||||
# See QAPISchema._make_implicit_object_type() - reverse the
|
|
||||||
# mapping there to create a nice human-readable description
|
|
||||||
defined_in = defined_in[6:]
|
|
||||||
if defined_in.endswith('-arg'):
|
|
||||||
# Implicit type created for a command's dict 'data'
|
|
||||||
assert role == 'member'
|
|
||||||
role = 'parameter'
|
|
||||||
elif defined_in.endswith('-base'):
|
|
||||||
# Implicit type created for a flat union's dict 'base'
|
|
||||||
role = 'base ' + role
|
|
||||||
else:
|
|
||||||
# Implicit type created for a simple union's branch
|
|
||||||
assert defined_in.endswith('-wrapper')
|
|
||||||
# Unreachable and not implemented
|
|
||||||
assert False
|
|
||||||
elif defined_in.endswith('Kind'):
|
|
||||||
# See QAPISchema._make_implicit_enum_type()
|
|
||||||
# Implicit enum created for simple union's branches
|
|
||||||
assert role == 'value'
|
|
||||||
role = 'branch'
|
|
||||||
elif defined_in != info.defn_name:
|
|
||||||
return "%s '%s' of type '%s'" % (role, self.name, defined_in)
|
|
||||||
return "%s '%s'" % (role, self.name)
|
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaEnumMember(QAPISchemaMember):
|
|
||||||
role = 'value'
|
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaFeature(QAPISchemaMember):
|
|
||||||
role = 'feature'
|
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaObjectTypeMember(QAPISchemaMember):
|
|
||||||
def __init__(self, name, info, typ, optional, ifcond=None):
|
|
||||||
super().__init__(name, info, ifcond)
|
|
||||||
assert isinstance(typ, str)
|
|
||||||
assert isinstance(optional, bool)
|
|
||||||
self._type_name = typ
|
|
||||||
self.type = None
|
|
||||||
self.optional = optional
|
|
||||||
|
|
||||||
def check(self, schema):
|
def check(self, schema):
|
||||||
assert self.defined_in
|
super().check(schema)
|
||||||
self.type = schema.resolve_type(self._type_name, self.info,
|
self.variants.tag_member.check(schema)
|
||||||
self.describe)
|
# Not calling self.variants.check_clash(), because there's nothing
|
||||||
|
# to clash with
|
||||||
|
self.variants.check(schema, {})
|
||||||
|
# Alternate branch names have no relation to the tag enum values;
|
||||||
|
# so we have to check for potential name collisions ourselves.
|
||||||
|
seen = {}
|
||||||
|
types_seen = {}
|
||||||
|
for v in self.variants.variants:
|
||||||
|
v.check_clash(self.info, seen)
|
||||||
|
qtype = v.type.alternate_qtype()
|
||||||
|
if not qtype:
|
||||||
|
raise QAPISemError(
|
||||||
|
self.info,
|
||||||
|
"%s cannot use %s"
|
||||||
|
% (v.describe(self.info), v.type.describe()))
|
||||||
|
conflicting = set([qtype])
|
||||||
|
if qtype == 'QTYPE_QSTRING':
|
||||||
|
if isinstance(v.type, QAPISchemaEnumType):
|
||||||
|
for m in v.type.members:
|
||||||
|
if m.name in ['on', 'off']:
|
||||||
|
conflicting.add('QTYPE_QBOOL')
|
||||||
|
if re.match(r'[-+0-9.]', m.name):
|
||||||
|
# lazy, could be tightened
|
||||||
|
conflicting.add('QTYPE_QNUM')
|
||||||
|
else:
|
||||||
|
conflicting.add('QTYPE_QNUM')
|
||||||
|
conflicting.add('QTYPE_QBOOL')
|
||||||
|
for qt in conflicting:
|
||||||
|
if qt in types_seen:
|
||||||
|
raise QAPISemError(
|
||||||
|
self.info,
|
||||||
|
"%s can't be distinguished from '%s'"
|
||||||
|
% (v.describe(self.info), types_seen[qt]))
|
||||||
|
types_seen[qt] = v.name
|
||||||
|
|
||||||
|
def connect_doc(self, doc=None):
|
||||||
|
super().connect_doc(doc)
|
||||||
|
doc = doc or self.doc
|
||||||
|
if doc:
|
||||||
|
for v in self.variants.variants:
|
||||||
|
doc.connect_member(v)
|
||||||
|
|
||||||
|
def c_type(self):
|
||||||
|
return c_name(self.name) + pointer_suffix
|
||||||
|
|
||||||
|
def json_type(self):
|
||||||
|
return 'value'
|
||||||
|
|
||||||
|
def visit(self, visitor):
|
||||||
|
super().visit(visitor)
|
||||||
|
visitor.visit_alternate_type(
|
||||||
|
self.name, self.info, self.ifcond, self.features, self.variants)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaObjectTypeVariants:
|
class QAPISchemaObjectTypeVariants:
|
||||||
|
@ -613,6 +603,84 @@ def check_clash(self, info, seen):
|
||||||
v.type.check_clash(info, dict(seen))
|
v.type.check_clash(info, dict(seen))
|
||||||
|
|
||||||
|
|
||||||
|
class QAPISchemaMember:
|
||||||
|
""" Represents object members, enum members and features """
|
||||||
|
role = 'member'
|
||||||
|
|
||||||
|
def __init__(self, name, info, ifcond=None):
|
||||||
|
assert isinstance(name, str)
|
||||||
|
self.name = name
|
||||||
|
self.info = info
|
||||||
|
self.ifcond = ifcond or []
|
||||||
|
self.defined_in = None
|
||||||
|
|
||||||
|
def set_defined_in(self, name):
|
||||||
|
assert not self.defined_in
|
||||||
|
self.defined_in = name
|
||||||
|
|
||||||
|
def check_clash(self, info, seen):
|
||||||
|
cname = c_name(self.name)
|
||||||
|
if cname in seen:
|
||||||
|
raise QAPISemError(
|
||||||
|
info,
|
||||||
|
"%s collides with %s"
|
||||||
|
% (self.describe(info), seen[cname].describe(info)))
|
||||||
|
seen[cname] = self
|
||||||
|
|
||||||
|
def describe(self, info):
|
||||||
|
role = self.role
|
||||||
|
defined_in = self.defined_in
|
||||||
|
assert defined_in
|
||||||
|
|
||||||
|
if defined_in.startswith('q_obj_'):
|
||||||
|
# See QAPISchema._make_implicit_object_type() - reverse the
|
||||||
|
# mapping there to create a nice human-readable description
|
||||||
|
defined_in = defined_in[6:]
|
||||||
|
if defined_in.endswith('-arg'):
|
||||||
|
# Implicit type created for a command's dict 'data'
|
||||||
|
assert role == 'member'
|
||||||
|
role = 'parameter'
|
||||||
|
elif defined_in.endswith('-base'):
|
||||||
|
# Implicit type created for a flat union's dict 'base'
|
||||||
|
role = 'base ' + role
|
||||||
|
else:
|
||||||
|
# Implicit type created for a simple union's branch
|
||||||
|
assert defined_in.endswith('-wrapper')
|
||||||
|
# Unreachable and not implemented
|
||||||
|
assert False
|
||||||
|
elif defined_in.endswith('Kind'):
|
||||||
|
# See QAPISchema._make_implicit_enum_type()
|
||||||
|
# Implicit enum created for simple union's branches
|
||||||
|
assert role == 'value'
|
||||||
|
role = 'branch'
|
||||||
|
elif defined_in != info.defn_name:
|
||||||
|
return "%s '%s' of type '%s'" % (role, self.name, defined_in)
|
||||||
|
return "%s '%s'" % (role, self.name)
|
||||||
|
|
||||||
|
|
||||||
|
class QAPISchemaEnumMember(QAPISchemaMember):
|
||||||
|
role = 'value'
|
||||||
|
|
||||||
|
|
||||||
|
class QAPISchemaFeature(QAPISchemaMember):
|
||||||
|
role = 'feature'
|
||||||
|
|
||||||
|
|
||||||
|
class QAPISchemaObjectTypeMember(QAPISchemaMember):
|
||||||
|
def __init__(self, name, info, typ, optional, ifcond=None):
|
||||||
|
super().__init__(name, info, ifcond)
|
||||||
|
assert isinstance(typ, str)
|
||||||
|
assert isinstance(optional, bool)
|
||||||
|
self._type_name = typ
|
||||||
|
self.type = None
|
||||||
|
self.optional = optional
|
||||||
|
|
||||||
|
def check(self, schema):
|
||||||
|
assert self.defined_in
|
||||||
|
self.type = schema.resolve_type(self._type_name, self.info,
|
||||||
|
self.describe)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
|
class QAPISchemaObjectTypeVariant(QAPISchemaObjectTypeMember):
|
||||||
role = 'branch'
|
role = 'branch'
|
||||||
|
|
||||||
|
@ -620,74 +688,6 @@ def __init__(self, name, info, typ, ifcond=None):
|
||||||
super().__init__(name, info, typ, False, ifcond)
|
super().__init__(name, info, typ, False, ifcond)
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaAlternateType(QAPISchemaType):
|
|
||||||
meta = 'alternate'
|
|
||||||
|
|
||||||
def __init__(self, name, info, doc, ifcond, features, variants):
|
|
||||||
super().__init__(name, info, doc, ifcond, features)
|
|
||||||
assert isinstance(variants, QAPISchemaObjectTypeVariants)
|
|
||||||
assert variants.tag_member
|
|
||||||
variants.set_defined_in(name)
|
|
||||||
variants.tag_member.set_defined_in(self.name)
|
|
||||||
self.variants = variants
|
|
||||||
|
|
||||||
def check(self, schema):
|
|
||||||
super().check(schema)
|
|
||||||
self.variants.tag_member.check(schema)
|
|
||||||
# Not calling self.variants.check_clash(), because there's nothing
|
|
||||||
# to clash with
|
|
||||||
self.variants.check(schema, {})
|
|
||||||
# Alternate branch names have no relation to the tag enum values;
|
|
||||||
# so we have to check for potential name collisions ourselves.
|
|
||||||
seen = {}
|
|
||||||
types_seen = {}
|
|
||||||
for v in self.variants.variants:
|
|
||||||
v.check_clash(self.info, seen)
|
|
||||||
qtype = v.type.alternate_qtype()
|
|
||||||
if not qtype:
|
|
||||||
raise QAPISemError(
|
|
||||||
self.info,
|
|
||||||
"%s cannot use %s"
|
|
||||||
% (v.describe(self.info), v.type.describe()))
|
|
||||||
conflicting = set([qtype])
|
|
||||||
if qtype == 'QTYPE_QSTRING':
|
|
||||||
if isinstance(v.type, QAPISchemaEnumType):
|
|
||||||
for m in v.type.members:
|
|
||||||
if m.name in ['on', 'off']:
|
|
||||||
conflicting.add('QTYPE_QBOOL')
|
|
||||||
if re.match(r'[-+0-9.]', m.name):
|
|
||||||
# lazy, could be tightened
|
|
||||||
conflicting.add('QTYPE_QNUM')
|
|
||||||
else:
|
|
||||||
conflicting.add('QTYPE_QNUM')
|
|
||||||
conflicting.add('QTYPE_QBOOL')
|
|
||||||
for qt in conflicting:
|
|
||||||
if qt in types_seen:
|
|
||||||
raise QAPISemError(
|
|
||||||
self.info,
|
|
||||||
"%s can't be distinguished from '%s'"
|
|
||||||
% (v.describe(self.info), types_seen[qt]))
|
|
||||||
types_seen[qt] = v.name
|
|
||||||
|
|
||||||
def connect_doc(self, doc=None):
|
|
||||||
super().connect_doc(doc)
|
|
||||||
doc = doc or self.doc
|
|
||||||
if doc:
|
|
||||||
for v in self.variants.variants:
|
|
||||||
doc.connect_member(v)
|
|
||||||
|
|
||||||
def c_type(self):
|
|
||||||
return c_name(self.name) + pointer_suffix
|
|
||||||
|
|
||||||
def json_type(self):
|
|
||||||
return 'value'
|
|
||||||
|
|
||||||
def visit(self, visitor):
|
|
||||||
super().visit(visitor)
|
|
||||||
visitor.visit_alternate_type(
|
|
||||||
self.name, self.info, self.ifcond, self.features, self.variants)
|
|
||||||
|
|
||||||
|
|
||||||
class QAPISchemaCommand(QAPISchemaEntity):
|
class QAPISchemaCommand(QAPISchemaEntity):
|
||||||
meta = 'command'
|
meta = 'command'
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue