#!/usr/bin/python # -*- coding: utf-8 -*- # Copyright (C) 2017 Belledonne Communications SARL # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License # as published by the Free Software Foundation; either version 2 # of the License, or (at your option) any later version. # # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with this program; if not, write to the Free Software # Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. import argparse import logging import os import pystache import sys sys.path.insert(0, os.path.join(os.path.dirname(__file__), '..', '..', '..', '..', 'tools')) import abstractapi import genapixml as capi import metaname import metadoc class RstTools: @staticmethod def make_chapter(text): return RstTools.make_section(text, char='*', overline=True) @staticmethod def make_section(text, char='=', overline=False): size = len(text) underline = (char*size) lines = [text, underline] if overline: lines.insert(0, underline) return '\n'.join(lines) @staticmethod def make_subsection(text): return RstTools.make_section(text, char='-') @staticmethod def make_subsubsection(text): return RstTools.make_section(text, char='^') class Table: def __init__(self): self._rows = [] self._widths = [] self._heights = [] @property def rows(self): return self._rows def addrow(self, row): if len(self._widths) == 0: self._widths.append(0) self._widths *= len(row) elif len(row) != len(self._widths): raise ValueError('row width mismatch table width') height = 0 row2 = [] i = 0 while i 0 @property def hasClassMethods(self): return len(self.classMethods) > 0 @property def hasProperties(self): return len(self.properties) > 0 def _translate_properties(self, properties): translatedProperties = [] for property_ in properties: propertyAttr = { 'name' : property_.name.translate(self.lang.nameTranslator), 'ref_label' : '{0}_{1}'.format(self.lang.langCode, property_.name.to_snake_case(fullName=True)), 'getter' : self._translate_method(property_.getter) if property_.getter is not None else None, 'setter' : self._translate_method(property_.setter) if property_.setter is not None else None } propertyAttr['title'] = RstTools.make_subsubsection(propertyAttr['name']) translatedProperties.append(propertyAttr) return translatedProperties def _translate_methods(self, methods): translatedMethods = [] for method in methods: translatedMethods.append(self._translate_method(method)) return translatedMethods def _translate_method(self, method): prototypeParams = {} if self.lang.langCode == 'Cpp': prototypeParams['showStdNs'] = True methAttr = { 'prototype' : method.translate_as_prototype(self.lang.langTranslator, **prototypeParams), 'briefDoc' : method.briefDescription.translate(self.docTranslator), 'detailedDoc' : method.detailedDescription.translate(self.docTranslator), 'selector' : self._make_selector(method) } reference = metadoc.FunctionReference(None) reference.relatedObject = method methAttr['link'] = reference.translate(self.lang.docTranslator) return methAttr @property def propertiesSummary(self): table = RstTools.Table() for property_ in self.properties: reference = ':ref:`{0}`'.format(property_['ref_label']) briefDoc = property_['getter']['briefDoc'] if property_['getter'] is not None else property_['setter']['briefDoc'] briefDoc = '\n'.join([line['line'] for line in briefDoc['lines']]) table.addrow([reference, briefDoc]) return table @property def instanceMethodsSummary(self): table = RstTools.Table() for method in self.methods: briefDoc = '\n'.join([line['line'] for line in method['briefDoc']['lines']]) table.addrow([method['link'], briefDoc]) return table @property def classMethodsSummary(self): table = RstTools.Table() for method in self.classMethods: briefDoc = '\n'.join([line['line'] for line in method['briefDoc']['lines']]) table.addrow([method['link'], briefDoc]) return table @property def isJava(self): return self.lang.langCode == 'Java' @property def isNotJava(self): return not self.isJava class DocGenerator: def __init__(self, api): self.api = api self.languages = [ LangInfo('C'), LangInfo('Cpp'), LangInfo('Java'), LangInfo('CSharp') ] def generate(self, outputdir): for lang in self.languages: subdirectory = lang.langCode.lower() directory = os.path.join(args.outputdir, subdirectory) if not os.path.exists(directory): os.mkdir(directory) enumsPage = EnumsPage(lang, self.languages, self.api.namespace.enums) enumsPage.write(directory) indexPage = IndexPage(lang, self.languages) for _class in self.api.namespace.classes: page = ClassPage(_class, lang, self.languages) page.write(directory) indexPage.add_class_entry(_class) indexPage.write(directory) if __name__ == '__main__': argparser = argparse.ArgumentParser(description='Generate a sphinx project to generate the documentation of Linphone Core API.') argparser.add_argument('xmldir', type=str, help='directory holding the XML documentation of the C API generated by Doxygen') argparser.add_argument('-o --output', type=str, help='directory into where Sphinx source files will be written', dest='outputdir', default='.') argparser.add_argument('-v --verbose', action='store_true', default=False, dest='verbose_mode', help='Show warning and info messages') args = argparser.parse_args() loglevel = logging.INFO if args.verbose_mode else logging.ERROR logging.basicConfig(format='%(levelname)s[%(name)s]: %(message)s', level=loglevel) cProject = capi.Project() cProject.initFromDir(args.xmldir) cProject.check() absApiParser = abstractapi.CParser(cProject) absApiParser.parse_all() docGenerator = DocGenerator(absApiParser) docGenerator.generate(args.outputdir)