mirror of https://github.com/opencv/opencv.git
Open Source Computer Vision Library
https://opencv.org/
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
184 lines
7.0 KiB
184 lines
7.0 KiB
#!/usr/bin/env python |
|
""" |
|
Usage: check_doc.py > log.txt |
|
The script parses different opencv modules |
|
(that are described by instances of class Comp below) and |
|
checks for typical errors in headers and docs, for consistence and for completeness. |
|
Due to its simplicity, it falsely reports some bugs, that should be |
|
just ignored. |
|
""" |
|
|
|
import sys, os, re, glob |
|
|
|
comps = [] |
|
|
|
class Comp: |
|
def __init__(self,comp_name): |
|
self.name = comp_name |
|
|
|
cxcore = Comp('cxcore') |
|
cxcore.header_path = '../cxcore/include' |
|
cxcore.headers = ['cxcore.h','cxtypes.h'] |
|
cxcore.ext_macro = 'CVAPI' |
|
cxcore.inline_macro = 'CV_INLINE' |
|
cxcore.func_prefix = 'cv' |
|
cxcore.doc_path = '../docs/ref' |
|
cxcore.docs = ['opencvref_cxcore.htm'] |
|
comps.append(cxcore) |
|
|
|
cv = Comp('cv') |
|
cv.header_path = '../cv/include' |
|
cv.headers = ['cv.h','cvtypes.h'] |
|
cv.ext_macro = 'CVAPI' |
|
cv.inline_macro = 'CV_INLINE' |
|
cv.func_prefix = 'cv' |
|
cv.doc_path = '../docs/ref' |
|
cv.docs = ['opencvref_cv.htm'] |
|
comps.append(cv) |
|
|
|
|
|
highgui = Comp('highgui') |
|
highgui.header_path = '../otherlibs/highgui' |
|
highgui.headers = ['highgui.h'] |
|
highgui.ext_macro = 'CVAPI' |
|
highgui.inline_macro = 'CV_INLINE' |
|
highgui.func_prefix = 'cv' |
|
highgui.doc_path = '../docs/ref' |
|
highgui.docs = ['opencvref_highgui.htm'] |
|
comps.append(highgui) |
|
|
|
|
|
def normalize_decl(decl): |
|
decl = re.sub( r'^\((.+?)\)', r'\1', decl) |
|
decl = re.sub( r' CV_DEFAULT\((.+?)\)(,|( *\);))', r'=\1\2', decl) |
|
decl = re.sub( r'\);', r' );', decl ) |
|
decl = re.sub( r'\(', r'( ', decl ) |
|
decl = re.sub( r'/\*.+?\*/', r'', decl ) |
|
decl = re.sub( r'\binline\b', r'', decl ) |
|
decl = re.sub( r' +', r' ', decl ) |
|
decl = re.sub( r' ?= ?', r'=', decl ) |
|
return decl.strip() |
|
|
|
def print_report(filename, line_no, msg): |
|
print '%s(%d): %s' % (filename,line_no,msg) |
|
|
|
for comp in comps: |
|
print "===================================================" |
|
print 'Checking %s...' % (comp.name,) |
|
header_path = comp.header_path |
|
func_list = {} |
|
|
|
if not header_path.endswith('/') and not header_path.endswith('\\'): |
|
header_path += '/' |
|
for header_glob in comp.headers: |
|
glob_expr = header_path + header_glob |
|
for header in glob.glob(glob_expr): |
|
f = open(header,'r') |
|
func_name = "" |
|
mode = line_no = 0 # mode - outside func declaration (0) or inside (1) |
|
for l in f.xreadlines(): |
|
line_no += 1 |
|
ll = "" |
|
|
|
#if re.findall(r'\b([abd-z]|([c][a-uw-z]))[a-z]*[A-Z]', l): |
|
# print_report(header,line_no,"Bad-style identifier:\n\t"+l) |
|
|
|
if mode == 0: |
|
if l.startswith(comp.ext_macro): |
|
ll = l[len(comp.ext_macro):] |
|
decl = "" |
|
mode = 1 |
|
elif l.startswith(comp.inline_macro): |
|
temp_func_name = re.findall( r'^.+?\b(' + comp.func_prefix + '\w+)', l ) |
|
if temp_func_name and temp_func_name[0] != func_name: |
|
ll = l[len(comp.inline_macro):] |
|
decl = "" |
|
mode = 1 |
|
else: |
|
ll = l |
|
|
|
if ll: |
|
decl += ll.rstrip('\n') + ' ' |
|
if ll.find(';') >= 0: |
|
mode = 0 |
|
decl = normalize_decl(decl) |
|
func_name = re.findall( r'^.+?\b(' + comp.func_prefix + '\w+)', decl )[0] |
|
if func_list.get(func_name,[]): |
|
print_report(header,line_no,"Duplicated declaration of " + \ |
|
func_name + "... ignored") |
|
else: |
|
func_list[func_name] = [decl,header,line_no,0] |
|
else: |
|
mode = 1 |
|
f.close() |
|
|
|
doc_path = comp.doc_path |
|
if not doc_path.endswith('/') and not doc_path.endswith('\\'): |
|
doc_path += '/' |
|
|
|
blurb_re = re.compile( r'^<p class="Blurb"' ) |
|
|
|
for doc_glob in comp.docs: |
|
glob_expr = doc_path + doc_glob |
|
for doc in glob.glob(glob_expr): |
|
f = open(doc, 'r') |
|
mode = line_no = 0 # mode - 0 outside function declaration, 2 - inside, |
|
# 1 transitional state ('cause <pre> is used not only |
|
# for declaring functions) |
|
for l in f.xreadlines(): |
|
line_no += 1 |
|
#if re.findall(r'\b([abd-z]|([c][a-uw-z]))[a-z]*[A-Z]', l): |
|
# print_report(doc,line_no,"Bad-style identifier:\n\t" + l) |
|
if mode == 0: |
|
if blurb_re.match(l): |
|
mode = 1 |
|
elif mode == 1: |
|
if l.endswith('<pre>\n'): |
|
mode = 2 |
|
decl = "" |
|
elif mode == 2: |
|
if l.startswith('</pre>'): |
|
mode = 0 |
|
if decl.find('CV_DEFAULT') >= 0: |
|
print_report(doc,line_no,'CV_DEFAULT is used in documentation') |
|
decl = normalize_decl(decl) |
|
decl_list = decl.split(';') |
|
for decl in decl_list: |
|
decl = decl.strip() |
|
if decl: |
|
decl = decl + ';' |
|
|
|
#print '***', decl |
|
func_name = re.findall( r'^.+?\b(' + comp.func_prefix + '\w+)\(', decl ) |
|
if not func_name: continue |
|
|
|
func_name = func_name[0] |
|
decl_info = func_list.get(func_name,[]) |
|
if decl_info: |
|
if decl_info[3] == 0: |
|
if decl_info[0] != decl: |
|
print_report(doc,line_no,'Incorrect documentation on ' + func_name + ':') |
|
print ' hdr: ' + decl_info[0] |
|
print ' doc: ' + decl |
|
decl_info[3] = 1 |
|
else: |
|
print_report(doc,line_no,'Duplicated documentation on ' + func_name) |
|
else: |
|
print_report(doc,line_no,'The function '+func_name+' is not declared') |
|
elif not l.startswith('#define'): |
|
decl += l.rstrip('\n') |
|
f.close() |
|
|
|
print "---------------------------------------------------" |
|
keys = func_list.keys() |
|
undocumented_funcs = [] |
|
for k in keys: |
|
decl_info = func_list[k] |
|
if decl_info[3] == 0: |
|
undocumented_funcs.append((decl_info[1],decl_info[2],k)) |
|
|
|
undocumented_funcs.sort() |
|
|
|
for decl_info in undocumented_funcs: |
|
print_report(decl_info[0],decl_info[1],'Undocumented function '+decl_info[2]) |
|
|
|
|