from . import index from . import compound from breathe import file_state_cache, path_handler from breathe.project import ProjectInfo from sphinx.application import Sphinx class ParserError(Exception): def __init__(self, error: Exception, filename: str): super().__init__(error) self.error = error self.filename = filename def __str__(self): return ("file %s: %s" % (self.filename, self.error)) class FileIOError(Exception): def __init__(self, error: Exception, filename: str): super().__init__(error) self.error = error self.filename = filename class Parser: def __init__(self, app: Sphinx, cache): self.app = app self.cache = cache class DoxygenIndexParser(Parser): def parse(self, project_info: ProjectInfo): filename = path_handler.resolve_path(self.app, project_info.project_path(), "index.xml") file_state_cache.update(self.app, filename) try: # Try to get from our cache return self.cache[filename] except KeyError: # If that fails, parse it afresh try: result = index.parse(filename) self.cache[filename] = result return result except index.ParseError as e: raise ParserError(e, filename) except index.FileIOError as e: raise FileIOError(e, filename) class DoxygenCompoundParser(Parser): def __init__(self, app: Sphinx, cache, project_info: ProjectInfo) -> None: super().__init__(app, cache) self.project_info = project_info def parse(self, refid: str): filename = path_handler.resolve_path( self.app, self.project_info.project_path(), "%s.xml" % refid ) file_state_cache.update(self.app, filename) try: # Try to get from our cache return self.cache[filename] except KeyError: # If that fails, parse it afresh try: result = compound.parse(filename) self.cache[filename] = result return result except compound.ParseError as e: raise ParserError(e, filename) except compound.FileIOError as e: raise FileIOError(e, filename) class DoxygenParserFactory: def __init__(self, app: Sphinx) -> None: self.app = app # TODO: do we have a base class for all the Doxygen XML node types # that we can use for typing? self.cache = {} # type: ignore def create_index_parser(self) -> DoxygenIndexParser: return DoxygenIndexParser(self.app, self.cache) def create_compound_parser(self, project_info: ProjectInfo) -> DoxygenCompoundParser: return DoxygenCompoundParser(self.app, self.cache, project_info)