qapi: Fix code generation for empty modules

When a sub-module doesn't contain any definitions, we don't generate
code for it, but we do generate the #include.

We generate code only for modules that get visited.
QAPISchema.visit() visits only modules that have definitions.  It can
visit modules multiple times.

Clean this up as follows.  Collect entities in their QAPISchemaModule.
Have QAPISchema.visit() call QAPISchemaModule.visit() for each module.
Have QAPISchemaModule.visit() call .visit_module() for itself, and
QAPISchemaEntity.visit() for each of its entities.  This way, we visit
each module exactly once.

Signed-off-by: Markus Armbruster <armbru@redhat.com>
Message-Id: <20191120182551.23795-6-armbru@redhat.com>
Reviewed-by: Eric Blake <eblake@redhat.com>
master
Markus Armbruster 2019-11-20 19:25:50 +01:00
parent a9f1dd7ee0
commit 3e7fb5811b
4 changed files with 26 additions and 29 deletions

View File

@ -68,6 +68,7 @@ class QAPISchemaEntity(object):
def _set_module(self, schema, info): def _set_module(self, schema, info):
assert self._checked assert self._checked
self._module = schema.module_by_fname(info and info.fname) self._module = schema.module_by_fname(info and info.fname)
self._module.add_entity(self)
def set_module(self, schema): def set_module(self, schema):
self._set_module(schema, self.info) self._set_module(schema, self.info)
@ -77,11 +78,6 @@ class QAPISchemaEntity(object):
assert self._checked assert self._checked
return self._ifcond return self._ifcond
@property
def module(self):
assert self._module or not self.info
return self._module
def is_implicit(self): def is_implicit(self):
return not self.info return not self.info
@ -142,6 +138,16 @@ class QAPISchemaVisitor(object):
class QAPISchemaModule(object): class QAPISchemaModule(object):
def __init__(self, name): def __init__(self, name):
self.name = name self.name = name
self._entity_list = []
def add_entity(self, ent):
self._entity_list.append(ent)
def visit(self, visitor):
visitor.visit_module(self.name)
for entity in self._entity_list:
if visitor.visit_needed(entity):
entity.visit(visitor)
class QAPISchemaInclude(QAPISchemaEntity): class QAPISchemaInclude(QAPISchemaEntity):
@ -1093,10 +1099,6 @@ class QAPISchema(object):
def visit(self, visitor): def visit(self, visitor):
visitor.visit_begin(self) visitor.visit_begin(self)
module = None module = None
for entity in self._entity_list: for mod in self._module_dict.values():
if visitor.visit_needed(entity): mod.visit(visitor)
if entity.module != module:
module = entity.module
visitor.visit_module(module.name)
entity.visit(visitor)
visitor.visit_end() visitor.visit_end()

View File

@ -9,3 +9,4 @@ enum QType
member qdict member qdict
member qlist member qlist
member qbool member qbool
module empty.json

View File

@ -11,15 +11,13 @@ enum QType
member qbool member qbool
module include-repetition.json module include-repetition.json
include comments.json include comments.json
include include-repetition-sub.json
include comments.json
module comments.json module comments.json
enum Status enum Status
member good member good
member bad member bad
member ugly member ugly
module include-repetition.json
include include-repetition-sub.json
module include-repetition-sub.json module include-repetition-sub.json
include comments.json include comments.json
include comments.json include comments.json
module include-repetition.json
include comments.json

View File

@ -153,9 +153,6 @@ object q_obj_sizeList-wrapper
member data: sizeList optional=False member data: sizeList optional=False
object q_obj_anyList-wrapper object q_obj_anyList-wrapper
member data: anyList optional=False member data: anyList optional=False
module sub-sub-module.json
array StatusList Status
module qapi-schema-test.json
object q_obj_StatusList-wrapper object q_obj_StatusList-wrapper
member data: StatusList optional=False member data: StatusList optional=False
enum UserDefListUnionKind enum UserDefListUnionKind
@ -193,17 +190,6 @@ object UserDefListUnion
case any: q_obj_anyList-wrapper case any: q_obj_anyList-wrapper
case user: q_obj_StatusList-wrapper case user: q_obj_StatusList-wrapper
include include/sub-module.json include include/sub-module.json
module include/sub-module.json
include sub-sub-module.json
module sub-sub-module.json
enum Status
member good
member bad
member ugly
module include/sub-module.json
object SecondArrayRef
member s: StatusList optional=False
module qapi-schema-test.json
command user_def_cmd None -> None command user_def_cmd None -> None
gen=True success_response=True boxed=False oob=False preconfig=False gen=True success_response=True boxed=False oob=False preconfig=False
object q_obj_user_def_cmd1-arg object q_obj_user_def_cmd1-arg
@ -435,3 +421,13 @@ command test-command-cond-features3 None -> None
gen=True success_response=True boxed=False oob=False preconfig=False gen=True success_response=True boxed=False oob=False preconfig=False
feature feature1 feature feature1
if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)'] if ['defined(TEST_IF_COND_1)', 'defined(TEST_IF_COND_2)']
module include/sub-module.json
include sub-sub-module.json
object SecondArrayRef
member s: StatusList optional=False
module sub-sub-module.json
array StatusList Status
enum Status
member good
member bad
member ugly