xref: /aosp_15_r20/external/fbjni/docs/build_quickref.py (revision 65c59e023c5336bbd4a23be7af78407e3d80e7e7)
1*65c59e02SInna Palant#!/usr/bin/env python3
2*65c59e02SInna Palant# Copyright (c) Facebook, Inc. and its affiliates.
3*65c59e02SInna Palantimport collections
4*65c59e02SInna Palantimport itertools
5*65c59e02SInna Palantimport re
6*65c59e02SInna Palantimport sys
7*65c59e02SInna Palant
8*65c59e02SInna Palant
9*65c59e02SInna Palantdef main(argv):
10*65c59e02SInna Palant    sections = collections.defaultdict(list)
11*65c59e02SInna Palant    toc = read_toc("docs/quickref_toc.txt")
12*65c59e02SInna Palant    grab_sections("test/DocTests.java", sections)
13*65c59e02SInna Palant    grab_sections("test/jni/doc_tests.cpp", sections)
14*65c59e02SInna Palant
15*65c59e02SInna Palant    missing_code = toc.keys() - sections.keys()
16*65c59e02SInna Palant    if missing_code:
17*65c59e02SInna Palant        raise Exception(f"Missing code for sections: {' '.join(missing_code)}")
18*65c59e02SInna Palant    missing_toc = sections.keys() - toc.keys()
19*65c59e02SInna Palant    if missing_toc:
20*65c59e02SInna Palant        raise Exception(f"Missing toc for sections: {' '.join(missing_toc)}")
21*65c59e02SInna Palant
22*65c59e02SInna Palant    with open("docs/quickref.md", "w") as handle:
23*65c59e02SInna Palant        handle.write("# Quick Reference\n")
24*65c59e02SInna Palant        for section in toc:
25*65c59e02SInna Palant            name = toc[section].strip()
26*65c59e02SInna Palant            handle.write(f"- [{name}](#{anchor(name)})\n")
27*65c59e02SInna Palant        for section in toc:
28*65c59e02SInna Palant            render_section(handle, section, toc[section], sections[section])
29*65c59e02SInna Palant
30*65c59e02SInna Palant
31*65c59e02SInna Palantdef anchor(title):
32*65c59e02SInna Palant    anchor = title.lower()
33*65c59e02SInna Palant    anchor = re.sub(" ", "-", anchor)
34*65c59e02SInna Palant    anchor = re.sub(r"[^-\w]", "", anchor)
35*65c59e02SInna Palant    return anchor
36*65c59e02SInna Palant
37*65c59e02SInna Palant
38*65c59e02SInna Palantdef read_toc(fname):
39*65c59e02SInna Palant    with open(fname) as handle:
40*65c59e02SInna Palant        return collections.OrderedDict(line.split(" ", 1) for line in handle)
41*65c59e02SInna Palant
42*65c59e02SInna Palant
43*65c59e02SInna Palantdef grab_sections(fname, sections):
44*65c59e02SInna Palant    extension = fname.split(".")[1]
45*65c59e02SInna Palant    active_block = None
46*65c59e02SInna Palant
47*65c59e02SInna Palant    with open(fname) as handle:
48*65c59e02SInna Palant        for lnum, line in enumerate(handle):
49*65c59e02SInna Palant            lnum += 1
50*65c59e02SInna Palant            if line.strip().endswith("// END"):
51*65c59e02SInna Palant                active_block = None
52*65c59e02SInna Palant                continue
53*65c59e02SInna Palant            m = re.search(r"// SECTION (\w+)$", line)
54*65c59e02SInna Palant            if m:
55*65c59e02SInna Palant                if active_block is not None:
56*65c59e02SInna Palant                    raise Exception(f"Nested section at {fname}:{lnum}")
57*65c59e02SInna Palant                active_group = m.group(1)
58*65c59e02SInna Palant                active_block = []
59*65c59e02SInna Palant                sections[active_group].append((extension, active_block))
60*65c59e02SInna Palant                continue
61*65c59e02SInna Palant            if line.strip().endswith(" MARKDOWN"):
62*65c59e02SInna Palant                if active_block is None:
63*65c59e02SInna Palant                    raise Exception(f"Orphaned markdown at {fname}:{lnum}")
64*65c59e02SInna Palant                active_block = []
65*65c59e02SInna Palant                sections[active_group].append(("md", active_block))
66*65c59e02SInna Palant                continue
67*65c59e02SInna Palant            if active_block is not None:
68*65c59e02SInna Palant                active_block.append(line)
69*65c59e02SInna Palant
70*65c59e02SInna Palant
71*65c59e02SInna Palantdef render_section(out, name, title, blocks):
72*65c59e02SInna Palant    out.write(f"## {title}")
73*65c59e02SInna Palant    for syntax, lines in blocks:
74*65c59e02SInna Palant        if not lines:
75*65c59e02SInna Palant            # This happens with Markdown-first sections
76*65c59e02SInna Palant            continue
77*65c59e02SInna Palant        if syntax != "md":
78*65c59e02SInna Palant            lines = itertools.chain(
79*65c59e02SInna Palant                [f"```{syntax}\n"],
80*65c59e02SInna Palant                lines,
81*65c59e02SInna Palant                ["```\n"],
82*65c59e02SInna Palant            )
83*65c59e02SInna Palant        for line in lines:
84*65c59e02SInna Palant            out.write(line)
85*65c59e02SInna Palant    out.write("\n\n")
86*65c59e02SInna Palant
87*65c59e02SInna Palant
88*65c59e02SInna Palantif __name__ == "__main__":
89*65c59e02SInna Palant    sys.exit(main(sys.argv))
90