histogram/doc/doxygen_postprocessing.py
Hans Dembinski df647cf959
update copyright (#55)
* add missing copyright notices
* workaround for xml_iarchive bug to handle XML with comments
* fixing min/max according to boost guidelines
2019-08-19 16:53:27 +02:00

117 lines
3.7 KiB
Python

# Copyright Hans Dembinski 2018 - 2019.
# Distributed under the Boost Software License, Version 1.0.
# (See accompanying file LICENSE_1_0.txt or copy at
# https://www.boost.org/LICENSE_1_0.txt)
from __future__ import print_function
import sys
import xml.etree.ElementTree as ET
import re
def log(*args):
print("post-processing:", *args)
def select(condition, *tags):
result = []
for tag in tags:
for item in root.iter(tag):
if condition(item):
result.append(item)
return result
def is_detail(x):
if x.text is not None:
if "detail" in x.text:
return True
m = re.match("(?:typename)? *([A-Za-z0-9_\:]+)", x.text)
if m is not None:
s = m.group(1)
if s.startswith("detail") or s.endswith("_impl"):
x.text = s
return True
p = x.find("purpose")
if p is not None:
return p.text.lower().lstrip().startswith("implementation detail")
return False
def is_deprecated(x):
p = x.find("purpose")
if p is not None:
return p.text.lower().lstrip().startswith("deprecated")
return False
tree = ET.parse(sys.argv[1])
root = tree.getroot()
parent_map = {c:p for p in tree.iter() for c in p}
unspecified = ET.Element("emphasis")
unspecified.text = "unspecified"
# hide all unnamed template parameters, these are used for SFINAE
for item in select(lambda x: x.get("name") == "", "template-type-parameter"):
parent = parent_map[item]
assert parent.tag == "template"
parent.remove(item)
parent = parent_map[parent]
name = parent.get("name")
if name is None:
log("removing unnamed template parameter from", parent.tag)
else:
log("removing unnamed template parameter from", parent.tag, name)
# replace any type with "detail" in its name with "unspecified"
for item in select(is_detail, "type"):
log("replacing", '"%s"' % item.text, 'with "unspecified"')
item.clear()
item.append(unspecified)
# hide everything that's deprecated
for item in select(is_deprecated, "typedef"):
parent = parent_map[item]
log("removing deprecated", item.tag, item.get("name"), "from", parent.tag, parent.get("name"))
parent.remove(item)
# hide private member functions
for item in select(lambda x: x.get("name") == "private member functions", "method-group"):
parent = parent_map[item]
log("removing private member functions from", parent.tag, parent.get("name"))
parent.remove(item)
# hide undocumented classes, structs, functions and replace those declared
# "implementation detail" with typedef to implementation_defined
for item in select(lambda x:True, "class", "struct", "function"):
purpose = item.find("purpose")
if purpose is None:
parent = parent_map[item]
log("removing undocumented", item.tag, item.get("name"), "from",
parent.tag, parent.get("name"))
if item in parent_map[item]:
parent_map[item].remove(item)
elif purpose.text.strip().lower() == "implementation detail":
log("replacing", item.tag, item.get("name"), "with unspecified typedef")
name = item.get("name")
item.clear()
item.tag = "typedef"
item.set("name", name)
type = ET.Element("type")
type.append(unspecified)
item.append(type)
parent_map = {c:p for p in tree.iter() for c in p}
# hide methods and constructors explicitly declared as "implementation detail"
for item in select(is_detail, "constructor", "method"):
name = item.get("name")
log("removing", (item.tag + " " + name) if name is not None else item.tag,
"declared as implementation detail")
parent_map[item].remove(item)
tree.write(sys.argv[2])