File: checkdoxygen.py

package info (click to toggle)
deal.ii 9.2.0-3
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 236,560 kB
  • sloc: cpp: 334,965; ansic: 72,687; python: 2,374; sh: 841; perl: 761; xml: 437; makefile: 82; javascript: 14
file content (140 lines) | stat: -rwxr-xr-x 5,084 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
#!/usr/bin/env python3

# run this script on all headers of deal.II to check various doxygen related problems

# for example:
# find doc examples include \( -name "*.h" -o -name "*.dox" \) -print | xargs -n 1 contrib/utilities/checkdoxygen.py


import sys

# have matching @{ @} pairs? (doxygen groups)
def check_doxygen_groups(lines):
    count = 0
    lineno = 1
    for l in lines:
        if "@{" in l:
            count = count + 1
        elif "@}" in l:
            count = count -1
        if count < 0:
            sys.exit("Error in file '%s' in line %d"%(filename, lineno))
        lineno = lineno + 1

    if count != 0:
        sys.exit("Error: missing closing braces in file '%s'"%(filename))

    return

# have empty lines in html tables?
def check_empty_lines_in_tables(lines):
    count = 0
    lineno = 1
    for l in lines:
        if "<table" in l:
            count = count + 1
        elif "</table>" in l:
            count = count -1
        if count < 0:
            sys.exit("Error in file '%s' in line %d"%(filename, lineno))

        if count == 1:
            if l.strip() == "":
                sys.exit("Error: empty line inside html table in file '%s' in line %d"%(filename, lineno))

        lineno = lineno + 1

    if count != 0:
        sys.exit("Error: mismatched html table tags in file '%s'"%(filename))

    return

# have more than one header with the same name in a tutorial?
def check_multiple_defined_headers(lines):
    headers = []
    for l in lines:
        # this may break if a header splits across a line
        if "<h" in l:
            # convert thisheader to the doxygen header name equivalent
            thisheader = l                             # take this line
            thisheader = thisheader.replace(' ', '')   # remove all whitespace
            thisheader = thisheader.split('<h')[1]     # remove header tag '<h'

            if thisheader[0] == '2':
                # We do not use <h2> headers in tutorials because our script
                # does not put them in the table of contents (for historical
                # reasons). Instead, please use <h3>, <h4>, etc..
                sys.exit("Error: Header <h2> detected in file '%s'. This is"
                         " not allowed in tutorial programs. Please use <h3>"
                         " instead." % (filename))

            if thisheader[0] in ['1', '2', '3', '4', '5']:  # make sure the next character is 1-5
                thisheader = thisheader[2:]            # remove '*>'
                if len(thisheader.split('</h'))==2:    # check for close header on the same line
                    thisheader = thisheader.split('</h')[0]    # remove close header tag
                    thisheader = ''.join(ch for ch in thisheader if ch.isalnum()) # remove nonalphanumeric
                    if thisheader in headers:
                        sys.exit("Error: repeated header title '%s' in file group '%s'"%(thisheader,filename))
                    else:
                        headers.append(thisheader)
                else:
                    sys.exit("Error: mismatched html header flags in file group '%s'"%(filename))
            # do not check else here because it may match with template arguments like '<hsize_t>'
        
        # detect @sect[1-5]{ ... }
        if "@sect" in l:
            thisheader = l                             # take this line
            thisheader = thisheader.replace(' ', '')   # remove all whitespace
            thisheader = thisheader.split('@sect')[1]  # remove '@sect'
            if thisheader[0] in ['1', '2', '3', '4', '5']:  # make sure the next character is 1-5
                thisheader = thisheader[2:]          # remove the number
                thisheader = ''.join(ch for ch in thisheader if ch.isalnum()) # remove nonalphanumeric

                if thisheader in headers:
                    sys.exit("Error: repeated header title '%s' in file group '%s'"%(thisheader,filename))
                else:
                    headers.append(thisheader)

    return


args = sys.argv
if len(args)!=2:
    print("Usage: %s <filename>"%(sys.argv[0]))
    sys.exit("Error: please pass exactly one filename to this script")

filename = args[1]

f = open(filename)
lines = f.readlines()
f.close()

check_doxygen_groups(lines)
check_empty_lines_in_tables(lines)

# if it's intro.dox, combine it with step-**.cc and results.dox and check headers
if 'intro.dox' in filename:
    # get stepname.cc
    stepname = filename.split('/doc',1)[0]
    stepname = stepname + '/' + stepname.split('/',1)[1] + '.cc'

    # get results.dox
    resultsname = filename.split('intro.dox',1)[0] + 'results.dox'
    
    # try to open the '.cc' file, otherwise try to open a '.cu' file
    try:
        fstep = open(stepname)
    except IOError:
        stepname = stepname[:-2] + 'cu'
        fstep = open(stepname)

    lines += fstep.readlines()
    fstep.close()

    fres = open(resultsname)
    lines += fres.readlines()
    fres.close()
    
    # check the file group
    check_multiple_defined_headers(lines)