doxygen_postprocessing.py 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. # Copyright Hans Dembinski 2018 - 2019.
  2. # Distributed under the Boost Software License, Version 1.0.
  3. # (See accompanying file LICENSE_1_0.txt or copy at
  4. # https://www.boost.org/LICENSE_1_0.txt)
  5. from __future__ import print_function
  6. import sys
  7. import xml.etree.ElementTree as ET
  8. import re
  9. def log(*args):
  10. print("post-processing:", *args)
  11. def select(condition, *tags):
  12. result = []
  13. for tag in tags:
  14. for item in root.iter(tag):
  15. if condition(item):
  16. result.append(item)
  17. return result
  18. def is_detail(x):
  19. if x.text is not None:
  20. if "detail" in x.text:
  21. return True
  22. m = re.match("(?:typename)? *([A-Za-z0-9_\:]+)", x.text)
  23. if m is not None:
  24. s = m.group(1)
  25. if s.startswith("detail") or s.endswith("_impl"):
  26. x.text = s
  27. return True
  28. p = x.find("purpose")
  29. if p is not None:
  30. return p.text.lower().lstrip().startswith("implementation detail")
  31. return False
  32. def is_deprecated(x):
  33. p = x.find("purpose")
  34. if p is not None:
  35. return p.text.lower().lstrip().startswith("deprecated")
  36. return False
  37. tree = ET.parse(sys.argv[1])
  38. root = tree.getroot()
  39. parent_map = {c:p for p in tree.iter() for c in p}
  40. unspecified = ET.Element("emphasis")
  41. unspecified.text = "unspecified"
  42. # hide all unnamed template parameters, these are used for SFINAE
  43. for item in select(lambda x: x.get("name") == "", "template-type-parameter"):
  44. parent = parent_map[item]
  45. assert parent.tag == "template"
  46. parent.remove(item)
  47. parent = parent_map[parent]
  48. name = parent.get("name")
  49. if name is None:
  50. log("removing unnamed template parameter from", parent.tag)
  51. else:
  52. log("removing unnamed template parameter from", parent.tag, name)
  53. # replace any type with "detail" in its name with "unspecified"
  54. for item in select(is_detail, "type"):
  55. log("replacing", '"%s"' % item.text, 'with "unspecified"')
  56. item.clear()
  57. item.append(unspecified)
  58. # hide everything that's deprecated
  59. for item in select(is_deprecated, "typedef"):
  60. parent = parent_map[item]
  61. log("removing deprecated", item.tag, item.get("name"), "from", parent.tag, parent.get("name"))
  62. parent.remove(item)
  63. # hide private member functions
  64. for item in select(lambda x: x.get("name") == "private member functions", "method-group"):
  65. parent = parent_map[item]
  66. log("removing private member functions from", parent.tag, parent.get("name"))
  67. parent.remove(item)
  68. # hide undocumented classes, structs, functions and replace those declared
  69. # "implementation detail" with typedef to implementation_defined
  70. for item in select(lambda x:True, "class", "struct", "function"):
  71. purpose = item.find("purpose")
  72. if purpose is None:
  73. parent = parent_map[item]
  74. log("removing undocumented", item.tag, item.get("name"), "from",
  75. parent.tag, parent.get("name"))
  76. if item in parent_map[item]:
  77. parent_map[item].remove(item)
  78. elif purpose.text.strip().lower() == "implementation detail":
  79. log("replacing", item.tag, item.get("name"), "with unspecified typedef")
  80. name = item.get("name")
  81. item.clear()
  82. item.tag = "typedef"
  83. item.set("name", name)
  84. type = ET.Element("type")
  85. type.append(unspecified)
  86. item.append(type)
  87. parent_map = {c:p for p in tree.iter() for c in p}
  88. # hide methods and constructors explicitly declared as "implementation detail"
  89. for item in select(is_detail, "constructor", "method"):
  90. name = item.get("name")
  91. log("removing", (item.tag + " " + name) if name is not None else item.tag,
  92. "declared as implementation detail")
  93. parent_map[item].remove(item)
  94. tree.write(sys.argv[2])