Logo AND Algorithmique Numérique Distribuée

Public GIT Repository
Update copyright lines with new year.
[simgrid.git] / docs / find-missing.py
index c944e85..4546b37 100755 (executable)
@@ -1,8 +1,7 @@
 #! /usr/bin/env python3
 # -*- coding: utf-8 -*-
 
-# Copyright (c) 2019. The SimGrid Team.
-# All rights reserved.
+# Copyright (c) 2019-2020. The SimGrid Team. All rights reserved.
 
 # This program is free software; you can redistribute it and/or modify it
 # under the terms of the license (GNU LGPL) which comes with this package.
@@ -12,6 +11,8 @@ Search for symbols documented in both the XML files produced by Doxygen and the
 but not documented with autodoxy in the RST files.
 
 This script is tailored to SimGrid own needs and should be made more generic for autodoxy.
+
+If you are missing some dependencies, try:  pip3 install --requirement docs/requirements.txt
 """
 
 import fnmatch
@@ -22,7 +23,7 @@ import xml.etree.ElementTree as ET
 import inspect
 
 xml_files = [
-#    'build/xml/classsimgrid_1_1s4u_1_1Activity.xml',
+    'build/xml/classsimgrid_1_1s4u_1_1Activity.xml',
     'build/xml/classsimgrid_1_1s4u_1_1Actor.xml',
     'build/xml/classsimgrid_1_1s4u_1_1Barrier.xml',
     'build/xml/classsimgrid_1_1s4u_1_1Comm.xml',
@@ -39,7 +40,10 @@ xml_files = [
     'build/xml/classsimgrid_1_1s4u_1_1Mutex.xml',
     'build/xml/classsimgrid_1_1s4u_1_1NetZone.xml',
     'build/xml/classsimgrid_1_1s4u_1_1Semaphore.xml',
-    'build/xml/classsimgrid_1_1s4u_1_1VirtualMachine.xml'
+    'build/xml/classsimgrid_1_1s4u_1_1VirtualMachine.xml',
+    'build/xml/actor_8h.xml',
+    'build/xml/engine_8h.xml',
+    'build/xml/vm_8h.xml'
 ]
 
 python_modules = [
@@ -61,7 +65,8 @@ def handle_python_module(fullname, englobing, elm):
 
     def found_decl(kind, obj):
         """Helper function that add an object in the python_decl data structure"""
-        if not kind in python_decl: python_decl[kind] = []
+        if kind not in python_decl:
+            python_decl[kind] = []
         python_decl[kind].append(obj)
 
 
@@ -92,7 +97,11 @@ def handle_python_module(fullname, englobing, elm):
 
 # Start the recursion on the provided Python modules
 for name in python_modules:
-    module = __import__(name)
+    try:
+        module = __import__(name)
+    except Exception:
+        print("Cannot import {}. Did you set PYTHONPATH=../lib accordingly?".format(name))
+        sys.exit(1)
     for sub in dir(module):
         if sub[0] == '_':
             continue
@@ -102,14 +111,14 @@ for name in python_modules:
 for kind in python_decl:
     with os.popen('grep \'[[:blank:]]*auto{}::\' source/*rst|sed \'s/^.*auto{}:: //\''.format(kind, kind)) as pse:
         for fullname in (l.strip() for l in pse):
-            if not fullname in python_decl[kind]:
+            if fullname not in python_decl[kind]:
                 print("Warning: {} documented but declaration not found in python.".format(fullname))
             else:
                 python_decl[kind].remove(fullname)
 # Dump the missing ones
 for kind in python_decl:
     for fullname in python_decl[kind]:
-        print("Missing decl: .. auto{}:: {}".format(kind, fullname))
+        print(" .. auto{}:: {}".format(kind, fullname))
 
 ################ And now deal with Doxygen declarations
 ################
@@ -118,34 +127,46 @@ doxy_funs = {} # {classname: {func_name: [args]} }
 doxy_vars = {} # {classname: [names]}
 
 # find the declarations in the XML files
-for arg in xml_files[:1]:
+for arg in xml_files:
     if arg[-4:] != '.xml':
         print ("Argument '{}' does not end with '.xml'".format(arg))
         continue
-    print("Parse file {}".format(arg))
+    #print("Parse file {}".format(arg))
     tree = ET.parse(arg)
     for elem in tree.findall(".//compounddef"):
-        if elem.attrib["prot"] != "public":
-            continue
-        if "compoundname" in elem:
-            raise Exception("Compound {} has no 'compoundname' child tag.".format(elem))
-        compoundname = elem.find("compoundname").text
-        #print ("compoundname {}".format(compoundname))
+        if elem.attrib["kind"] == "class":
+            if elem.attrib["prot"] != "public":
+                continue
+            if "compoundname" in elem:
+                raise Exception("Compound {} has no 'compoundname' child tag.".format(elem))
+            compoundname = elem.find("compoundname").text
+            #print ("compoundname {}".format(compoundname))
+        elif elem.attrib["kind"] == "file":
+            compoundname = ""
+        else:
+            print("Element {} is of kind {}".format(elem.attrib["id"], elem.attrib["kind"]))
+
         for member in elem.findall('.//memberdef'):
             if member.attrib["prot"] != "public":
                 continue
             kind = member.attrib["kind"]
             name = member.find("name").text
+            #print("kind:{} compoundname:{} name:{}".format( kind,compoundname, name))
             if kind == "variable":
-                if not compoundname in doxy_vars: doxy_vars[compoundname] = []
+                if compoundname not in doxy_vars:
+                    doxy_vars[compoundname] = []
                 doxy_vars[compoundname].append(name)
             elif kind == "function":
                 args = member.find('argsstring').text
                 args = re.sub('\)[^)]*$', ')', args) # ignore what's after the parameters (eg, '=0' or ' const')
 
-                if not compoundname in doxy_funs: doxy_funs[compoundname] = {}
-                if not name in doxy_funs[compoundname]: doxy_funs[compoundname][name] = []
+                if compoundname not in doxy_funs:
+                    doxy_funs[compoundname] = {}
+                if name not in doxy_funs[compoundname]:
+                    doxy_funs[compoundname][name] = []
                 doxy_funs[compoundname][name].append(args)
+            elif kind == "friend":
+                pass # Ignore friendship
             else:
                 print ("member {}::{} is of kind {}".format(compoundname, name, kind))
 
@@ -156,30 +177,48 @@ with os.popen('grep autodoxymethod:: source/*rst|sed \'s/^.*autodoxymethod:: //\
         if "(" in line:
             (line, args) = line.split('(', 1)
             args = "({}".format(args)
-        (klass, obj) = line.rsplit('::', 1)
+        if '::' in line:
+            (klass, obj) = line.rsplit('::', 1)
+        else:
+            (klass, obj) = ("", line)
 
-        if not klass in doxy_funs:
+        if klass not in doxy_funs:
             print("Warning: {} documented, but class {} not found in doxygen.".format(line, klass))
             continue
-        if not obj in doxy_funs[klass]:
-            print("Warning: Object {} documented but not found in {}".format(line, klass))
+        if obj not in doxy_funs[klass]:
+            print("Warning: Object '{}' documented but not found in '{}'".format(line, klass))
+#            for obj in doxy_funs[klass]:
+#                print("  found: {}::{}".format(klass, obj))
         elif len(doxy_funs[klass][obj])==1:
             del doxy_funs[klass][obj]
-        elif not args in doxy_funs[klass][obj]:
+        elif args not in doxy_funs[klass][obj]:
             print("Warning: Function {}{} not found in {}".format(obj, args, klass))
         else:
-#            print("Found {} in {}".format(line, klass))
+            #print("Found {} in {}".format(line, klass))
             doxy_funs[klass][obj].remove(args)
             if len(doxy_funs[klass][obj]) == 0:
                 del doxy_funs[klass][obj]
+with os.popen('grep autodoxyvar:: source/*rst|sed \'s/^.*autodoxyvar:: //\'') as pse:
+    for line in (l.strip() for l in pse):
+        (klass, var) = line.rsplit('::', 1)
+
+        if klass not in doxy_vars:
+            print("Warning: {} documented, but class {} not found in doxygen.".format(line, klass))
+            continue
+        if var not in doxy_vars[klass]:
+            print("Warning: Object {} documented but not found in {}".format(line, klass))
+        else:
+#            print("Found {} in {}".format(line, klass))
+            doxy_vars[klass].remove(var)
+            if len(doxy_vars[klass]) == 0:
+                del doxy_vars[klass]
 
 # Dump the undocumented Doxygen declarations 
-for obj in doxy_funs:
-    for meth in doxy_funs[obj]:
-        for args in doxy_funs[obj][meth]:
-            print("Missing decl: .. autodoxymethod:: {}::{}{}".format(obj, meth, args))
+for obj in sorted(doxy_funs):
+    for meth in sorted(doxy_funs[obj]):
+        for args in sorted(doxy_funs[obj][meth]):
+            print(".. autodoxymethod:: {}::{}{}".format(obj, meth, args))
 
 for obj in doxy_vars:
-    for meth in doxy_vars[obj]:
-        print("Missing decl: .. autodoxyfield:: {}::{}".format(obj, meth))
-
+    for meth in sorted(doxy_vars[obj]):
+        print(".. autodoxyvar:: {}::{}".format(obj, meth))