diff options
author | Dimitri van Heesch <doxygen@gmail.com> | 2021-04-29 17:26:11 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2021-04-29 17:26:11 (GMT) |
commit | b8a3ff6c33264c43cdf30c04baa9793e7e8d51a2 (patch) | |
tree | 9d60ced4b8fceb00c068b56d699c1ba57540d415 /addon/doxmlparser/examples/metrics/metrics.py | |
parent | 4dba9fbdda10889d2285b85b7e9ff6282b34fccf (diff) | |
parent | c6d77227efaf332a5d24bc12d32f4b1fec6b13b9 (diff) | |
download | Doxygen-b8a3ff6c33264c43cdf30c04baa9793e7e8d51a2.zip Doxygen-b8a3ff6c33264c43cdf30c04baa9793e7e8d51a2.tar.gz Doxygen-b8a3ff6c33264c43cdf30c04baa9793e7e8d51a2.tar.bz2 |
Merge branch 'master' into feature/bug_305773
Diffstat (limited to 'addon/doxmlparser/examples/metrics/metrics.py')
-rw-r--r-- | addon/doxmlparser/examples/metrics/metrics.py | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/addon/doxmlparser/examples/metrics/metrics.py b/addon/doxmlparser/examples/metrics/metrics.py new file mode 100644 index 0000000..a83e16f --- /dev/null +++ b/addon/doxmlparser/examples/metrics/metrics.py @@ -0,0 +1,225 @@ +# An example showing how to use the python doxmlparser module to extract some metrics from +# the XML output generated by doxygen for a project. + +import sys + +import doxmlparser + +from doxmlparser.compound import DoxCompoundKind, DoxMemberKind, DoxSectionKind, MixedContainer + +class Metrics: + def __init__(self): + self.numClasses = 0 + self.numDocClasses = 0 + self.numStructs = 0 + self.numUnions = 0 + self.numInterfaces = 0 + self.numExceptions = 0 + self.numNamespaces = 0 + self.numFiles = 0 + self.numDocFiles = 0 + self.numGroups = 0 + self.numPages = 0 + self.numPubMethods = 0 + self.numDocPubMethods = 0 + self.numProMethods = 0 + self.numDocProMethods = 0 + self.numPriMethods = 0 + self.numDocPriMethods = 0 + self.numAttributes = 0 + self.numDocAttributes = 0 + self.numFunctions = 0 + self.numDocFunctions = 0 + self.numVariables = 0 + self.numDocVariables = 0 + self.numParams = 0 + def print(self): + numMethods = self.numPubMethods + self.numProMethods + self.numPriMethods + numDocMethods = self.numDocPubMethods + self.numDocProMethods + self.numDocPriMethods + print("Metrics:"); + print("-----------------------------------"); + if self.numClasses>0: + print("Classes: {:=10} ({} documented)".format(self.numClasses,self.numDocClasses)) + if self.numStructs>0: + print("Structs: {:=10}".format(self.numStructs)) + if self.numUnions>0: + print("Unions: {:=10}".format(self.numUnions)) + if self.numExceptions>0: + print("Exceptions: {:=10}".format(self.numExceptions)) + if self.numNamespaces>0: + print("Namespaces: {:=10}".format(self.numNamespaces)) + if self.numFiles>0: + print("Files: {:=10} ({} documented)".format(self.numFiles,self.numDocFiles)) + if self.numGroups>0: + print("Groups: {:=10}".format(self.numGroups)) + if self.numPages>0: + print("Pages: {:=10}".format(self.numPages)) + if numMethods>0: + print("Methods: {:=10} ({} documented)".format(numMethods,numDocMethods)) + if self.numPubMethods>0: + print(" Public: {:=10} ({} documented)".format(self.numPubMethods,self.numDocPubMethods)) + if self.numProMethods>0: + print(" Protected: {:=10} ({} documented)".format(self.numProMethods,self.numDocProMethods)) + if self.numPriMethods>0: + print(" Private: {:=10} ({} documented)".format(self.numPriMethods,self.numDocPriMethods)) + if self.numFunctions>0: + print("Functions: {:=10} ({} documented)".format(self.numFunctions,self.numDocFunctions)) + if self.numAttributes>0: + print("Attributes: {:=10} ({} documented)".format(self.numAttributes,self.numDocAttributes)) + if self.numVariables>0: + print("Variables: {:=10} ({} documented)".format(self.numVariables,self.numDocVariables)) + if self.numParams>0: + print("Params: {:=10}".format(self.numParams)) + print("-----------------------------------"); + if self.numClasses>0: + print("Avg. #methods/compound: {:=10}".format(float(numMethods)/float(self.numClasses))) + if numMethods>0: + print("Avg. #params/method: {:=10}".format(float(self.numParams)/float(numMethods))) + print("-----------------------------------"); + + +def description_is_empty(description): + for content in description.content_: + if content.getCategory()==MixedContainer.CategoryText: + if not content.getValue().isspace(): + return False # non space-only text + elif not content.getCategory()==MixedContainer.CategoryNone: + return False # some internal object like a paragraph + return True + +def is_documented(definition): + return not description_is_empty(definition.get_briefdescription()) or \ + not description_is_empty(definition.get_detaileddescription()) + +def section_is_protected(sectionkind): + return sectionkind in [DoxSectionKind.PROTECTEDTYPE, + DoxSectionKind.PROTECTEDFUNC, + DoxSectionKind.PROTECTEDATTRIB, + DoxSectionKind.PROTECTEDSLOT, + DoxSectionKind.PROTECTEDSTATICFUNC, + DoxSectionKind.PROTECTEDSTATICATTRIB] + +def section_is_private(sectionkind): + return sectionkind in [DoxSectionKind.PRIVATETYPE, + DoxSectionKind.PRIVATEFUNC, + DoxSectionKind.PRIVATEATTRIB, + DoxSectionKind.PRIVATESLOT, + DoxSectionKind.PRIVATESTATICFUNC, + DoxSectionKind.PRIVATESTATICATTRIB] + +def section_is_public(sectionkind): + return not section_is_protected(sectionkind) and not section_is_private(sectionkind) + +def linked_text_to_string(linkedtext): + str='' + if linkedtext: + for text_or_ref in linkedtext.content_: + if text_or_ref.getCategory()==MixedContainer.CategoryText: + str+=text_or_ref.getValue() + else: + str+=text_or_ref.getValue().get_valueOf_() + return str + +def parse_members(compounddef,sectiondef,metrics): + functionLikeKind = [DoxMemberKind.FUNCTION, + DoxMemberKind.PROTOTYPE, + DoxMemberKind.SIGNAL, + DoxMemberKind.SLOT, + DoxMemberKind.DCOP] + variableLikeKind = [DoxMemberKind.VARIABLE, DoxMemberKind.PROPERTY] + for memberdef in sectiondef.get_memberdef(): + if compounddef.get_kind() in [DoxCompoundKind.CLASS, DoxCompoundKind.STRUCT, DoxCompoundKind.INTERFACE]: + if memberdef.get_kind() in functionLikeKind: + if section_is_public(sectiondef.get_kind()): + metrics.numPubMethods+=1 + if is_documented(memberdef): + metrics.numDocPubMethods+=1 + elif section_is_protected(sectiondef.get_kind()): + metrics.numProMethods+=1 + if is_documented(memberdef): + metrics.numDocProMethods+=1 + elif section_is_private(sectiondef.get_kind()): + metrics.numPriMethods+=1 + if is_documented(memberdef): + metrics.numDocPriMethods+=1 + elif memberdef.get_kind() in variableLikeKind: + metrics.numAttributes+=1 + if is_documented(memberdef): + metrics.numDocAttributes+=1 + elif compounddef.get_kind() in [DoxCompoundKind.FILE, DoxCompoundKind.NAMESPACE]: + if memberdef.get_kind() in functionLikeKind: + metrics.numFunctions+=1 + if is_documented(memberdef): + metrics.numDocFunctions+=1 + elif memberdef.get_kind() in variableLikeKind: + metrics.numVariables+=1 + if is_documented(memberdef): + metrics.numDocVariables+=1 + #for param in memberdef.get_param(): + # name = '' + # if param.get_defname(): + # name = param.get_defname() + # if param.get_declname(): + # name = param.get_declname() + # print("param '{}':'{}'".format(linked_text_to_string(param.get_type()),name)) + metrics.numParams+=len(memberdef.get_param()) + if memberdef.get_type() and memberdef.get_type()!="void" and linked_text_to_string(memberdef.get_type()): + metrics.numParams+=1 # count non-void return types as well + #print("returns '{}'".format(linked_text_to_string(memberdef.get_type()))) + +def parse_sections(compounddef,metrics): + for sectiondef in compounddef.get_sectiondef(): + parse_members(compounddef,sectiondef,metrics) + +def parse_compound(inDirName,baseName,metrics): + rootObj = doxmlparser.compound.parse(inDirName+"/"+baseName+".xml",True) + for compounddef in rootObj.get_compounddef(): + kind = compounddef.get_kind() + if kind==DoxCompoundKind.CLASS: + metrics.numClasses+=1 + if is_documented(compounddef): + metrics.numDocClasses+=1 + elif kind==DoxCompoundKind.STRUCT: + metrics.numStructs+=1 + elif kind==DoxCompoundKind.UNION: + metrics.numUnions+=1 + elif kind==DoxCompoundKind.INTERFACE: + metrics.numInterfaces+=1 + elif kind==DoxCompoundKind.EXCEPTION: + metrics.numExceptions+=1 + elif kind==DoxCompoundKind.NAMESPACE: + metrics.numNamespaces+=1 + elif kind==DoxCompoundKind.FILE: + metrics.numFiles+=1 + if is_documented(compounddef): + metrics.numDocFiles+=1 + elif kind==DoxCompoundKind.GROUP: + metrics.numGroups+=1 + elif kind==DoxCompoundKind.PAGE: + metrics.numPages+=1 + else: + continue + parse_sections(compounddef,metrics) + +def parse_index(inDirName): + metrics = Metrics() + rootObj = doxmlparser.index.parse(inDirName+"/index.xml",True) + for compound in rootObj.get_compound(): # for each compound defined in the index + print("Processing {0}...".format(compound.get_name())) + parse_compound(inDirName,compound.get_refid(),metrics) + metrics.print() + +def usage(): + print("Usage {0} <xml_output_dir>".format(sys.argv[0])) + sys.exit(1) + +def main(): + args = sys.argv[1:] + if len(args)==1: + parse_index(args[0]) + else: + usage() + +if __name__ == '__main__': + main() + |