3 Usage: check_doc.py > log.txt
4 The script parses different opencv modules
5 (that are described by instances of class Comp below) and
6 checks for typical errors in headers and docs, for consistence and for completeness.
7 Due to its simplicity, it falsely reports some bugs, that should be
11 import sys, os, re, glob
16 def __init__(self,comp_name):
19 cxcore = Comp('cxcore')
20 cxcore.header_path = '../cxcore/include'
21 cxcore.headers = ['cxcore.h','cxtypes.h']
22 cxcore.ext_macro = 'CVAPI'
23 cxcore.inline_macro = 'CV_INLINE'
24 cxcore.func_prefix = 'cv'
25 cxcore.doc_path = '../docs/ref'
26 cxcore.docs = ['opencvref_cxcore.htm']
30 cv.header_path = '../cv/include'
31 cv.headers = ['cv.h','cvtypes.h']
32 cv.ext_macro = 'CVAPI'
33 cv.inline_macro = 'CV_INLINE'
35 cv.doc_path = '../docs/ref'
36 cv.docs = ['opencvref_cv.htm']
40 highgui = Comp('highgui')
41 highgui.header_path = '../otherlibs/highgui'
42 highgui.headers = ['highgui.h']
43 highgui.ext_macro = 'CVAPI'
44 highgui.inline_macro = 'CV_INLINE'
45 highgui.func_prefix = 'cv'
46 highgui.doc_path = '../docs/ref'
47 highgui.docs = ['opencvref_highgui.htm']
51 def normalize_decl(decl):
52 decl = re.sub( r'^\((.+?)\)', r'\1', decl)
53 decl = re.sub( r' CV_DEFAULT\((.+?)\)(,|( *\);))', r'=\1\2', decl)
54 decl = re.sub( r'\);', r' );', decl )
55 decl = re.sub( r'\(', r'( ', decl )
56 decl = re.sub( r'/\*.+?\*/', r'', decl )
57 decl = re.sub( r'\binline\b', r'', decl )
58 decl = re.sub( r' +', r' ', decl )
59 decl = re.sub( r' ?= ?', r'=', decl )
62 def print_report(filename, line_no, msg):
63 print '%s(%d): %s' % (filename,line_no,msg)
66 print "==================================================="
67 print 'Checking %s...' % (comp.name,)
68 header_path = comp.header_path
71 if not header_path.endswith('/') and not header_path.endswith('\\'):
73 for header_glob in comp.headers:
74 glob_expr = header_path + header_glob
75 for header in glob.glob(glob_expr):
78 mode = line_no = 0 # mode - outside func declaration (0) or inside (1)
79 for l in f.xreadlines():
83 #if re.findall(r'\b([abd-z]|([c][a-uw-z]))[a-z]*[A-Z]', l):
84 # print_report(header,line_no,"Bad-style identifier:\n\t"+l)
87 if l.startswith(comp.ext_macro):
88 ll = l[len(comp.ext_macro):]
91 elif l.startswith(comp.inline_macro):
92 temp_func_name = re.findall( r'^.+?\b(' + comp.func_prefix + '\w+)', l )
93 if temp_func_name and temp_func_name[0] != func_name:
94 ll = l[len(comp.inline_macro):]
101 decl += ll.rstrip('\n') + ' '
102 if ll.find(';') >= 0:
104 decl = normalize_decl(decl)
105 func_name = re.findall( r'^.+?\b(' + comp.func_prefix + '\w+)', decl )[0]
106 if func_list.get(func_name,[]):
107 print_report(header,line_no,"Duplicated declaration of " + \
108 func_name + "... ignored")
110 func_list[func_name] = [decl,header,line_no,0]
115 doc_path = comp.doc_path
116 if not doc_path.endswith('/') and not doc_path.endswith('\\'):
119 blurb_re = re.compile( r'^<p class="Blurb"' )
121 for doc_glob in comp.docs:
122 glob_expr = doc_path + doc_glob
123 for doc in glob.glob(glob_expr):
125 mode = line_no = 0 # mode - 0 outside function declaration, 2 - inside,
126 # 1 transitional state ('cause <pre> is used not only
127 # for declaring functions)
128 for l in f.xreadlines():
130 #if re.findall(r'\b([abd-z]|([c][a-uw-z]))[a-z]*[A-Z]', l):
131 # print_report(doc,line_no,"Bad-style identifier:\n\t" + l)
133 if blurb_re.match(l):
136 if l.endswith('<pre>\n'):
140 if l.startswith('</pre>'):
142 if decl.find('CV_DEFAULT') >= 0:
143 print_report(doc,line_no,'CV_DEFAULT is used in documentation')
144 decl = normalize_decl(decl)
145 decl_list = decl.split(';')
146 for decl in decl_list:
152 func_name = re.findall( r'^.+?\b(' + comp.func_prefix + '\w+)\(', decl )
153 if not func_name: continue
155 func_name = func_name[0]
156 decl_info = func_list.get(func_name,[])
158 if decl_info[3] == 0:
159 if decl_info[0] != decl:
160 print_report(doc,line_no,'Incorrect documentation on ' + func_name + ':')
161 print ' hdr: ' + decl_info[0]
162 print ' doc: ' + decl
165 print_report(doc,line_no,'Duplicated documentation on ' + func_name)
167 print_report(doc,line_no,'The function '+func_name+' is not declared')
168 elif not l.startswith('#define'):
169 decl += l.rstrip('\n')
172 print "---------------------------------------------------"
173 keys = func_list.keys()
174 undocumented_funcs = []
176 decl_info = func_list[k]
177 if decl_info[3] == 0:
178 undocumented_funcs.append((decl_info[1],decl_info[2],k))
180 undocumented_funcs.sort()
182 for decl_info in undocumented_funcs:
183 print_report(decl_info[0],decl_info[1],'Undocumented function '+decl_info[2])