+
+ def get_toplevel_modules(self):
+ result = []
+ for module in self.root.children.itervalues():
+ if module.name == 'gromacs':
+ result.extend(module.children.itervalues())
+ else:
+ result.append(module)
+ return result
+
+
+class IncludeFileChecker(object):
+ def __init__(self, deps, options):
+ self._deps = deps
+ self._options = options
+
+ def _check_file(self, checkfile, reporter):
+ if not self._options.check_doc:
+ return
+ if not checkfile.is_documented():
+ if self._options.warn_undoc:
+ reporter.error(checkfile.path, 'file not documented')
+ elif checkfile.doctype == 'implementation' and \
+ checkfile.type in ('publicheader', 'libheader'):
+ reporter.error(checkfile.path,
+ 'file documentation visibility incorrect')
+ elif checkfile.doctype == 'library' and checkfile.type == 'publicheader':
+ reporter.error(checkfile.path,
+ 'file documentation visibility incorrect')
+ elif checkfile.installed and checkfile.doctype not in ('public', 'unknown'):
+ reporter.error(checkfile.path,
+ 'installed header has no public documentation')
+ elif not checkfile.installed and checkfile.doctype == 'public':
+ reporter.error(checkfile.path,
+ 'non-installed file has public documentation')
+ selfmodfullname = checkfile.module.fullname
+ docmodule = checkfile.docmodule
+ if docmodule and \
+ not selfmodfullname.startswith('module_' + docmodule) and \
+ not selfmodfullname.startswith('module_gromacs_' + docmodule):
+ reporter.error(checkfile.path,
+ 'file documented in incorrect module "{0}"'
+ .format(docmodule))
+
+ def _check_included_file(self, checkfile, includedfile, reporter):
+ otherfile = includedfile._included_file
+ if includedfile._is_system:
+ if otherfile:
+ reporter.error(checkfile.path,
+ 'local file included as <{0}>'
+ .format(includedfile._included_path))
+ elif not includedfile._is_relative and checkfile.installed:
+ reporter.error(checkfile.path,
+ 'installed header includes "{0}", '
+ 'which is not found using relative path'
+ .format(includedfile._included_path))
+ if not otherfile:
+ return
+ if checkfile.installed and not otherfile.installed:
+ reporter.error(checkfile.path,
+ 'installed header includes '
+ 'non-installed header "{0}"'
+ .format(includedfile._included_path))
+ if not otherfile.is_documented():
+ return
+ if not self._options.check_doc:
+ return
+ intramodule = \
+ (checkfile.module.get_top_level_module() == \
+ otherfile.module.get_top_level_module())
+ if otherfile.type not in ('publicheader', 'libheader'):
+ if not intramodule:
+ reporter.error(checkfile.path,
+ 'included file "{0}" is missing API definition'
+ .format(otherfile.path))
+ elif checkfile.type == 'publicheader':
+ if not otherfile.type == 'publicheader' and not otherfile.doctype == 'public':
+ reporter.error(checkfile.path,
+ 'public API file includes non-public header "{0}"'
+ .format(otherfile.path))
+
+ def check_all(self, reporter):
+ for checkfile in self._deps.files.itervalues():
+ self._check_file(checkfile, reporter)
+ for includedfile in checkfile.get_included_files():
+ self._check_included_file(checkfile, includedfile, reporter)
+
+
+class GraphBuilder(object):
+ def __init__(self, deps):
+ self._deps = deps
+
+ def create_file_node(self, fileobj, filenodes):
+ nodename = re.subn(r'[-./]', '_', fileobj.path)[0]
+ node = Node(fileobj, nodename, fileobj.name)
+ filenodes[fileobj] = node
+ return node
+
+ def create_file_edges(self, fileobj, filenodes):
+ links = []
+ if fileobj in filenodes:
+ for includedfile in fileobj.get_included_files():
+ otherfile = includedfile._included_file
+ if otherfile and otherfile in filenodes:
+ link = Link(filenodes[fileobj], filenodes[otherfile])
+ links.append(link)
+ return links
+
+ def create_module_node(self, module, filenodes):
+ node = Node(module, module.fullname, module.name)
+ for childfile in module.files:
+ node.add_child(self.create_file_node(childfile, filenodes))
+ for childmodule in module.children.itervalues():
+ node.add_child(self.create_module_node(childmodule, filenodes))
+ return node