locatemissingdoxygen.py 2.1 KB

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