locatemissingdoxygen.py (2108B)
1 #!/usr/bin/env python 2 3 """ 4 This script parses the stderr output of doxygen and looks for undocumented 5 stuff. By default, it just counts the undocumented things per file. But with 6 the -A option, it rewrites the files to stick in /*DOCDOC*/ comments 7 to highlight the undocumented stuff. 8 """ 9 10 # Future imports for Python 2.7, mandatory in 3.0 11 from __future__ import division 12 from __future__ import print_function 13 from __future__ import unicode_literals 14 15 import os 16 import re 17 import shutil 18 import sys 19 20 warning_pattern = re.compile(r'^([^:]+):(\d+): warning: (.*) is not documented') 21 22 def readDoxygenOutput(f): 23 " yields (cfilename, lineno, thingname) " 24 for line in f: 25 m = warning_pattern.match(line) 26 if m: 27 yield m.groups() 28 29 warnings = {} 30 31 def buildWarnings(): 32 for fn, lineno, what in list(readDoxygenOutput(sys.stdin)): 33 warnings.setdefault(fn, []).append( (int(lineno), what) ) 34 35 def count(fn): 36 if os.path.abspath(fn) not in warnings: 37 print("0\t%s"%fn) 38 else: 39 n = len(warnings[os.path.abspath(fn)]) 40 print("%d\t%s"%(n,fn)) 41 42 def getIndentation(line): 43 s = line.lstrip() 44 return line[:len(line)-len(s)] 45 46 def annotate(filename): 47 if os.path.abspath(filename) not in warnings: 48 return 49 with open(filename) as f: 50 lines = f.readlines() 51 w = warnings[os.path.abspath(filename)][:] 52 w.sort() 53 w.reverse() 54 55 for lineno, what in w: 56 lineno -= 1 # list is 0-indexed. 57 if 'DOCDOC' in lines[lineno]: 58 continue 59 ind = getIndentation(lines[lineno]) 60 lines.insert(lineno, "%s/* DOCDOC %s */\n"%(ind,what)) 61 62 shutil.copy(filename, filename+".orig") 63 with open(filename, 'w') as f: 64 for l in lines: 65 f.write(l) 66 67 68 if __name__ == '__main__': 69 if len(sys.argv) == 1: 70 print("Usage: locatemissingdoxygen.py [-A] filename... <doxygen_log") 71 sys.exit(1) 72 buildWarnings() 73 if sys.argv[1] == '-A': 74 del sys.argv[1] 75 func = annotate 76 else: 77 func = count 78 for fname in sys.argv[1:]: 79 func(fname)