xref: /aosp_15_r20/external/ComputeLibrary/scripts/format_doxygen.py (revision c217d954acce2dbc11938adb493fc0abd69584f3)
1*c217d954SCole Faust#!/usr/bin/env python3
2*c217d954SCole Faustimport os.path
3*c217d954SCole Faustimport re
4*c217d954SCole Faustimport sys
5*c217d954SCole Faust
6*c217d954SCole Faustdef process_comment(fd, comment, first_param, last_param):
7*c217d954SCole Faust    if first_param < 0:
8*c217d954SCole Faust        # Nothing to do: just copy the comment
9*c217d954SCole Faust        fd.write("".join(comment))
10*c217d954SCole Faust    else:
11*c217d954SCole Faust        params = list()
12*c217d954SCole Faust
13*c217d954SCole Faust        # Measure the indentation of the first param and use that to create an empty comment line string:
14*c217d954SCole Faust        m = re.match(r" */", comment[0])
15*c217d954SCole Faust
16*c217d954SCole Faust        if not m:
17*c217d954SCole Faust            raise Exception("{}: Not a comment ? '{}'".format(path,comment[first_param]))
18*c217d954SCole Faust
19*c217d954SCole Faust        line_prefix = " " * len(m.group(0)) + "*"
20*c217d954SCole Faust        empty_line =  line_prefix +"\n"
21*c217d954SCole Faust
22*c217d954SCole Faust        fd.write(comment[0])
23*c217d954SCole Faust        # Copy the non param lines with the correct indentation:
24*c217d954SCole Faust        for comment_line in range(1,first_param):
25*c217d954SCole Faust            line = comment[comment_line]
26*c217d954SCole Faust            m = re.match(" *\*(.*)", line)
27*c217d954SCole Faust            if not m:
28*c217d954SCole Faust                raise Exception("{}:{}: Not a comment line ? ".format(path, n_line - len(comment) + comment_line + 1))
29*c217d954SCole Faust            fd.write(line_prefix+ m.group(1)+"\n")
30*c217d954SCole Faust
31*c217d954SCole Faust        # For each param split the line into 3 columns: param, param_name, description
32*c217d954SCole Faust        for param in range(first_param, last_param):
33*c217d954SCole Faust            m = re.match(r"[^@]+(@param\[[^\]]+\]) +(\S+) +(.+)", comment[param])
34*c217d954SCole Faust
35*c217d954SCole Faust            if m:
36*c217d954SCole Faust                params.append( (" "+m.group(1), m.group(2), m.group(3)) )
37*c217d954SCole Faust            else:
38*c217d954SCole Faust                # If it's not a match then it must be a multi-line param description:
39*c217d954SCole Faust
40*c217d954SCole Faust                m = re.match(" *\* +(.*)", comment[param])
41*c217d954SCole Faust                if not m:
42*c217d954SCole Faust                    raise Exception("{}:{}: Not a comment line ? ".format(path, n_line - len(comment) + param + 1))
43*c217d954SCole Faust
44*c217d954SCole Faust                params.append( ("", "", m.group(1)) )
45*c217d954SCole Faust
46*c217d954SCole Faust        # Now that we've got a list of params, find what is the longest string for each column:
47*c217d954SCole Faust        max_len = [0, 0]
48*c217d954SCole Faust
49*c217d954SCole Faust        for p in params:
50*c217d954SCole Faust            for l in range(len(max_len)):
51*c217d954SCole Faust                max_len[l] = max(max_len[l], len(p[l]))
52*c217d954SCole Faust
53*c217d954SCole Faust        # Insert an empty line if needed before the first param to make it easier to read:
54*c217d954SCole Faust        m = re.match(r" *\* *$", comment[first_param - 1])
55*c217d954SCole Faust
56*c217d954SCole Faust        if not m:
57*c217d954SCole Faust            # insert empty line
58*c217d954SCole Faust            fd.write(empty_line)
59*c217d954SCole Faust
60*c217d954SCole Faust        # Write out the formatted list of params:
61*c217d954SCole Faust        for p in params:
62*c217d954SCole Faust            fd.write("{}{}{} {}{} {}\n".format( line_prefix,
63*c217d954SCole Faust                    p[0], " " * (max_len[0] - len(p[0])),
64*c217d954SCole Faust                    p[1], " " * (max_len[1] - len(p[1])),
65*c217d954SCole Faust                    p[2]))
66*c217d954SCole Faust
67*c217d954SCole Faust        # If the next line after the list of params is a command (@return, @note, @warning, etc), insert an empty line to separate it from the list of params
68*c217d954SCole Faust        if last_param < len(comment) - 1:
69*c217d954SCole Faust            if re.match(r" *\* *@\w+", comment[last_param]):
70*c217d954SCole Faust                # insert empty line
71*c217d954SCole Faust                fd.write(empty_line)
72*c217d954SCole Faust
73*c217d954SCole Faust        # Copy the remaining of the comment with the correct indentation:
74*c217d954SCole Faust        for comment_line in range(last_param,len(comment)):
75*c217d954SCole Faust            line = comment[comment_line]
76*c217d954SCole Faust            m = re.match(" *\*(.*)", line)
77*c217d954SCole Faust            if not m:
78*c217d954SCole Faust                raise Exception("{}:{}: Not a comment line ? ".format(path, n_line - len(comment) + comment_line + 1))
79*c217d954SCole Faust            fd.write(line_prefix+ m.group(1)+"\n")
80*c217d954SCole Faust
81*c217d954SCole Faustif __name__ == "__main__":
82*c217d954SCole Faust    n_file=0
83*c217d954SCole Faust
84*c217d954SCole Faust    if len(sys.argv) == 1:
85*c217d954SCole Faust        paths = []
86*c217d954SCole Faust
87*c217d954SCole Faust        for top_level in ["./arm_compute", "./src", "./examples", "./tests", "./utils", "./framework", "./support"]:
88*c217d954SCole Faust            for root, _, files in os.walk(top_level):
89*c217d954SCole Faust                paths.extend([os.path.join(root, f) for f in files])
90*c217d954SCole Faust    else:
91*c217d954SCole Faust        paths = sys.argv[1:]
92*c217d954SCole Faust
93*c217d954SCole Faust    for path in paths:
94*c217d954SCole Faust        if (path[-3:] not in ("cpp", "inl") and
95*c217d954SCole Faust            path[-2:] not in ("cl") and
96*c217d954SCole Faust            path[-2:] not in ("cs") and
97*c217d954SCole Faust            path[-1] not in ("h")):
98*c217d954SCole Faust            continue
99*c217d954SCole Faust
100*c217d954SCole Faust        print("[{}] {}".format(n_file, path))
101*c217d954SCole Faust
102*c217d954SCole Faust        n_file += 1
103*c217d954SCole Faust
104*c217d954SCole Faust        with open(path,'r+', encoding="utf-8") as fd:
105*c217d954SCole Faust            comment = list()
106*c217d954SCole Faust            first_param = -1
107*c217d954SCole Faust            last_param = -1
108*c217d954SCole Faust            n_line = 0
109*c217d954SCole Faust
110*c217d954SCole Faust            lines = fd.readlines()
111*c217d954SCole Faust            fd.seek(0)
112*c217d954SCole Faust            fd.truncate()
113*c217d954SCole Faust
114*c217d954SCole Faust            for line in lines:
115*c217d954SCole Faust                n_line += 1
116*c217d954SCole Faust
117*c217d954SCole Faust                # Start comment
118*c217d954SCole Faust                # Match C-style comment /* anywhere in the line
119*c217d954SCole Faust                if re.search(r"/\*", line):
120*c217d954SCole Faust                    #print("Start comment {}".format(n_line))
121*c217d954SCole Faust
122*c217d954SCole Faust                    if len(comment) > 0:
123*c217d954SCole Faust                        raise Exception("{}:{}: Already in a comment!".format(path,n_line))
124*c217d954SCole Faust
125*c217d954SCole Faust                    comment.append(line)
126*c217d954SCole Faust
127*c217d954SCole Faust                # Comment already started
128*c217d954SCole Faust                elif len(comment) > 0:
129*c217d954SCole Faust                    #print("Add line to comment {}".format(n_line))
130*c217d954SCole Faust
131*c217d954SCole Faust                    comment.append(line)
132*c217d954SCole Faust
133*c217d954SCole Faust                # Non-comment line
134*c217d954SCole Faust                else:
135*c217d954SCole Faust                    #print("Normal line {}".format(n_line))
136*c217d954SCole Faust
137*c217d954SCole Faust                    fd.write(line)
138*c217d954SCole Faust
139*c217d954SCole Faust                # Match param declaration in Doxygen comment
140*c217d954SCole Faust                # @param[in] name description
141*c217d954SCole Faust                if re.search(r"@param\[[^\]]+\] +\S+ +\S", line):
142*c217d954SCole Faust                    #print("Param {}".format(n_line))
143*c217d954SCole Faust
144*c217d954SCole Faust                    if first_param < 0:
145*c217d954SCole Faust                        first_param = len(comment) - 1
146*c217d954SCole Faust
147*c217d954SCole Faust                    last_param = len(comment)
148*c217d954SCole Faust
149*c217d954SCole Faust                # Match end of C-style comment */
150*c217d954SCole Faust                if re.search(r"\*/", line):
151*c217d954SCole Faust                    if re.search('"[^"]*\*/[^"]*"', line):
152*c217d954SCole Faust                        #print("End of comment inside a string: ignoring")
153*c217d954SCole Faust                        pass
154*c217d954SCole Faust                    else:
155*c217d954SCole Faust                        #print("End comment {}".format(n_line))
156*c217d954SCole Faust
157*c217d954SCole Faust                        if len(comment) < 1:
158*c217d954SCole Faust                            raise Exception("{}:{}: Was not in a comment! ".format(path, n_line))
159*c217d954SCole Faust
160*c217d954SCole Faust                        #print("Process comment {} {}".format(first_param, last_param))
161*c217d954SCole Faust
162*c217d954SCole Faust                        process_comment(fd, comment, first_param, last_param)
163*c217d954SCole Faust
164*c217d954SCole Faust                        comment = list()
165*c217d954SCole Faust                        first_param = -1
166*c217d954SCole Faust                        last_param = -1
167