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