Merged the trunk r8467:8507 (inclusive) (big bunch of documentation fixes)

This commit is contained in:
Andrey Kamaev
2012-05-30 11:13:07 +00:00
parent 052d2dc23a
commit 81a5988015
120 changed files with 5407 additions and 4695 deletions

497
doc/check_docs2.py Normal file
View File

@@ -0,0 +1,497 @@
import os, sys, glob, re
sys.path.append("../modules/python/src2/")
sys.path.append("../modules/java/")
import hdr_parser as hp
import rst_parser as rp
rp.show_warnings = False
rp.show_errors = False
allmodules = rp.allmodules
DOCUMENTED_MARKER = "verified"
ERROR_001_NOTACLASS = 1
ERROR_002_NOTASTRUCT = 2
ERROR_003_INCORRECTBASE = 3
ERROR_004_MISSEDNAMESPACE = 4
ERROR_005_MISSINGPYFUNC = 5
ERROR_006_INVALIDPYOLDDOC = 6
ERROR_007_INVALIDPYDOC = 7
ERROR_008_CFUNCISNOTGLOBAL = 8
ERROR_009_OVERLOADNOTFOUND = 9
ERROR_010_UNKNOWNCLASS = 10
ERROR_011_UNKNOWNFUNC = 11
do_python_crosscheck = True
errors_disabled = [ERROR_004_MISSEDNAMESPACE]
doc_signatures_whitelist = [
# templates
"Matx", "Vec", "SparseMat_", "Scalar_", "Mat_", "Ptr", "Size_", "Point_", "Rect_", "Point3_",
"DataType", "detail::RotationWarperBase", "flann::Index_", "CalonderDescriptorExtractor",
"gpu::DevMem2D_", "gpu::PtrStep_", "gpu::PtrElemStep_",
# black boxes
"CvArr", "CvFileStorage",
# other
"InputArray", "OutputArray",
]
defines = ["cvGraphEdgeIdx", "cvFree", "CV_Assert", "cvSqrt", "cvGetGraphVtx", "cvGraphVtxIdx",
"cvCaptureFromFile", "cvCaptureFromCAM", "cvCalcBackProjectPatch", "cvCalcBackProject",
"cvGetHistValue_1D", "cvGetHistValue_2D", "cvGetHistValue_3D", "cvGetHistValue_nD",
"cvQueryHistValue_1D", "cvQueryHistValue_2D", "cvQueryHistValue_3D", "cvQueryHistValue_nD",
# not a real function but behaves as function
"Mat::size",
# ugly "virtual" functions from ml module
"CvStatModel::train", "CvStatModel::predict",
# TODO:
"cvExtractSURF"
]
synonims = {
"StarDetector" : ["StarFeatureDetector"],
"MSER" : ["MserFeatureDetector"],
"GFTTDetector" : ["GoodFeaturesToTrackDetector"],
"cvCaptureFromFile" : ["cvCreateFileCapture"],
"cvCaptureFromCAM" : ["cvCreateCameraCapture"],
"cvCalcArrBackProjectPatch" : ["cvCalcBackProjectPatch"],
"cvCalcArrBackProject" : ["cvCalcBackProject"],
"InputArray" : ["_InputArray"],
"OutputArray" : ["_OutputArray"],
}
if do_python_crosscheck:
try:
import cv2
except ImportError:
print "Could not load cv2"
do_python_crosscheck = False
def get_cv2_object(name):
if name.startswith("cv2."):
name = name[4:]
if name.startswith("cv."):
name = name[3:]
if name == "Algorithm":
return cv2.Algorithm__create("Feature2D.ORB"), name
elif name == "FeatureDetector":
return cv2.FeatureDetector_create("ORB"), name
elif name == "DescriptorExtractor":
return cv2.DescriptorExtractor_create("ORB"), name
elif name == "BackgroundSubtractor":
return cv2.BackgroundSubtractorMOG(), name
elif name == "StatModel":
return cv2.KNearest(), name
else:
return getattr(cv2, name)(), name
def compareSignatures(f, s):
# function names
if f[0] != s[0]:
return False, "name mismatch"
# return type
stype = (s[1] or "void")
ftype = f[1]
stype = re.sub(r"\b(cv|std)::", "", stype)
if ftype:
ftype = re.sub(r"\b(cv|std)::", "", ftype)
if ftype and ftype != stype:
return False, "return type mismatch"
if ("\C" in f[2]) ^ ("\C" in s[2]):
return False, "const qualifier mismatch"
if ("\S" in f[2]) ^ ("\S" in s[2]):
return False, "static qualifier mismatch"
if ("\V" in f[2]) ^ ("\V" in s[2]):
return False, "virtual qualifier mismatch"
if ("\A" in f[2]) ^ ("\A" in s[2]):
return False, "abstract qualifier mismatch"
if len(f[3]) != len(s[3]):
return False, "different number of arguments"
for idx, arg in enumerate(zip(f[3], s[3])):
farg = arg[0]
sarg = arg[1]
ftype = re.sub(r"\b(cv|std)::", "", (farg[0] or ""))
stype = re.sub(r"\b(cv|std)::", "", (sarg[0] or ""))
if ftype != stype:
return False, "type of argument #" + str(idx+1) + " mismatch"
fname = farg[1] or "arg" + str(idx)
sname = sarg[1] or "arg" + str(idx)
if fname != sname:
return False, "name of argument #" + str(idx+1) + " mismatch"
fdef = re.sub(r"\b(cv|std)::", "", (farg[2] or ""))
sdef = re.sub(r"\b(cv|std)::", "", (sarg[2] or ""))
if fdef != sdef:
return False, "default value of argument #" + str(idx+1) + " mismatch"
return True, "match"
def formatSignature(s):
_str = ""
if "/V" in s[2]:
_str += "virtual "
if "/S" in s[2]:
_str += "static "
if s[1]:
_str += s[1] + " "
else:
if not bool(re.match(r"(\w+\.)*(?P<cls>\w+)\.(?P=cls)", s[0])):
_str += "void "
if s[0].startswith("cv."):
_str += s[0][3:].replace(".", "::")
else:
_str += s[0].replace(".", "::")
if len(s[3]) == 0:
_str += "()"
else:
_str += "( "
for idx, arg in enumerate(s[3]):
if idx > 0:
_str += ", "
argtype = re.sub(r"\bcv::", "", arg[0])
bidx = argtype.find('[')
if bidx < 0:
_str += argtype + " "
else:
_srt += argtype[:bidx]
if arg[1]:
_str += arg[1]
else:
_str += "arg" + str(idx)
if bidx >= 0:
_str += argtype[bidx:]
if arg[2]:
_str += "=" + re.sub(r"\bcv::", "", arg[2])
_str += " )"
if "/C" in s[2]:
_str += " const"
if "/A" in s[2]:
_str += " = 0"
return _str
def logerror(code, message, doc = None):
if code in errors_disabled:
return
if doc:
print doc["file"] + ":" + str(doc["line"]),
print "error %03d: %s" % (code, message)
#print
def process_module(module, path):
hppparser = hp.CppHeaderParser()
rstparser = rp.RstParser(hppparser)
rstparser.parse(module, path)
rst = rstparser.definitions
hdrlist = glob.glob(os.path.join(path, "include", "opencv2", module, "*.h*"))
hdrlist.extend(glob.glob(os.path.join(path, "include", "opencv2", module, "detail", "*.h*")))
if module == "gpu":
hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "devmem2d.hpp"))
hdrlist.append(os.path.join(path, "..", "core", "include", "opencv2", "core", "gpumat.hpp"))
decls = []
for hname in hdrlist:
if not "ts_gtest.h" in hname:
decls += hppparser.parse(hname, wmode=False)
funcs = []
# not really needed to hardcode all the namespaces. Normally all they are collected automatically
namespaces = ['cv', 'cv.gpu', 'cvflann', 'cvflann.anyimpl', 'cvflann.lsh', 'cv.flann', 'cv.linemod', 'cv.detail', 'cvtest', 'perf', 'cv.videostab']
classes = []
structs = []
# collect namespaces and classes/structs
for decl in decls:
if decl[0].startswith("const"):
pass
elif decl[0].startswith("class") or decl[0].startswith("struct"):
if decl[0][0] == 'c':
classes.append(decl)
else:
structs.append(decl)
dotIdx = decl[0].rfind('.')
if dotIdx > 0:
namespace = decl[0][decl[0].find(' ')+1:dotIdx]
if not [c for c in classes if c[0].endswith(namespace)] and not [s for s in structs if s[0].endswith(namespace)]:
if namespace not in namespaces:
namespaces.append(namespace)
else:
funcs.append(decl)
clsnamespaces = []
# process classes
for cl in classes:
name = cl[0][cl[0].find(' ')+1:]
if name.find('.') < 0 and not name.startswith("Cv"):
logerror(ERROR_004_MISSEDNAMESPACE, "class " + name + " from opencv_" + module + " is placed in global namespace but violates C-style naming convention")
clsnamespaces.append(name)
if do_python_crosscheck and not name.startswith("cv.") and name.startswith("Cv"):
clsnamespaces.append("cv." + name[2:])
if name.startswith("cv."):
name = name[3:]
name = name.replace(".", "::")
sns = synonims.get(name, [])
sns.append(name)
for name in sns:
doc = rst.get(name)
if not doc:
#TODO: class is not documented
continue
doc[DOCUMENTED_MARKER] = True
# verify class marker
if not doc.get("isclass"):
logerror(ERROR_001_NOTACLASS, "class " + name + " is not marked as \"class\" in documentation", doc)
else:
# verify base
signature = doc.get("class", "")
signature = signature.replace(" public ", " ")
namespaceIdx = signature.rfind("::")
signature = ("class " + signature).strip()
hdrsignature = ("class " + name + " " + cl[1]).replace(".", "::").replace("cv::","").strip()
if signature != hdrsignature:
logerror(ERROR_003_INCORRECTBASE, "invalid base class documentation\ndocumented: " + signature + "\nactual: " + hdrsignature, doc)
# process structs
for st in structs:
name = st[0][st[0].find(' ')+1:]
if name.find('.') < 0 and not name.startswith("Cv"):
logerror(ERROR_004_MISSEDNAMESPACE, "struct " + name + " from opencv_" + module + " is placed in global namespace but violates C-style naming convention")
clsnamespaces.append(name)
if name.startswith("cv."):
name = name[3:]
name = name.replace(".", "::")
doc = rst.get(name)
if not doc:
#TODO: struct is not documented
continue
doc[DOCUMENTED_MARKER] = True
# verify struct marker
if not doc.get("isstruct"):
logerror(ERROR_002_NOTASTRUCT, "struct " + name + " is not marked as \"struct\" in documentation", doc)
else:
# verify base
signature = doc.get("class", "")
signature = signature.replace(", public ", " ").replace(" public ", " ")
signature = signature.replace(", protected ", " ").replace(" protected ", " ")
signature = signature.replace(", private ", " ").replace(" private ", " ")
signature = ("struct " + signature).strip()
hdrsignature = (st[0] + " " + st[1]).replace("struct cv.", "struct ").replace(".", "::").strip()
if signature != hdrsignature:
logerror(ERROR_003_INCORRECTBASE, "invalid base struct documentation\ndocumented: " + signature + "\nactual: " + hdrsignature, doc)
print st, doc
# process functions and methods
flookup = {}
for fn in funcs:
name = fn[0]
parent = None
namespace = None
for cl in clsnamespaces:
if name.startswith(cl + "."):
if cl.startswith(parent or ""):
parent = cl
if parent:
name = name[len(parent) + 1:]
for nm in namespaces:
if parent.startswith(nm + "."):
if nm.startswith(namespace or ""):
namespace = nm
if namespace:
parent = parent[len(namespace) + 1:]
else:
for nm in namespaces:
if name.startswith(nm + "."):
if nm.startswith(namespace or ""):
namespace = nm
if namespace:
name = name[len(namespace) + 1:]
#print namespace, parent, name, fn[0]
if not namespace and not parent and not name.startswith("cv") and not name.startswith("CV_"):
logerror(ERROR_004_MISSEDNAMESPACE, "function " + name + " from opencv_" + module + " is placed in global namespace but violates C-style naming convention")
else:
fdescr = (namespace, parent, name, fn)
flookup_entry = flookup.get(fn[0], [])
flookup_entry.append(fdescr)
flookup[fn[0]] = flookup_entry
if do_python_crosscheck:
for name, doc in rst.iteritems():
decls = doc.get("decls")
if not decls:
continue
for signature in decls:
if signature[0] == "Python1":
pname = signature[1][:signature[1].find('(')]
try:
fn = getattr(cv2.cv, pname[3:])
docstr = "cv." + fn.__doc__
except AttributeError:
logerror(ERROR_005_MISSINGPYFUNC, "could not load documented function: cv2." + pname, doc)
continue
docstring = docstr
sign = signature[1]
signature.append(DOCUMENTED_MARKER)
# convert old signature to pydoc style
if docstring.endswith("*"):
docstring = docstring[:-1]
s = None
while s != sign:
s = sign
sign = re.sub(r"^(.*\(.*)\(.*?\)(.*\) *->)", "\\1_\\2", sign)
s = None
while s != sign:
s = sign
sign = re.sub(r"\s*,\s*([^,]+)\s*=\s*[^,]+\s*(( \[.*\])?)\)", " [, \\1\\2])", sign)
sign = re.sub(r"\(\s*([^,]+)\s*=\s*[^,]+\s*(( \[.*\])?)\)", "([\\1\\2])", sign)
sign = re.sub(r"\)\s*->\s*", ") -> ", sign)
sign = sign.replace("-> convexHull", "-> CvSeq")
sign = sign.replace("-> lines", "-> CvSeq")
sign = sign.replace("-> boundingRects", "-> CvSeq")
sign = sign.replace("-> contours", "-> CvSeq")
sign = sign.replace("-> retval", "-> int")
sign = sign.replace("-> detectedObjects", "-> CvSeqOfCvAvgComp")
def retvalRplace(match):
m = match.group(1)
m = m.replace("CvScalar", "scalar")
m = m.replace("CvMemStorage", "memstorage")
m = m.replace("ROIplImage", "image")
m = m.replace("IplImage", "image")
m = m.replace("ROCvMat", "mat")
m = m.replace("CvMat", "mat")
m = m.replace("double", "float")
m = m.replace("CvSubdiv2DPoint", "point")
m = m.replace("CvBox2D", "Box2D")
m = m.replace("IplConvKernel", "kernel")
m = m.replace("CvHistogram", "hist")
m = m.replace("CvSize", "width,height")
m = m.replace("cvmatnd", "matND")
m = m.replace("CvSeqOfCvConvexityDefect", "convexityDefects")
mm = m.split(',')
if len(mm) > 1:
return "(" + ", ".join(mm) + ")"
else:
return m
docstring = re.sub(r"(?<=-> )(.*)$", retvalRplace, docstring)
docstring = docstring.replace("( [, ", "([")
if sign != docstring:
logerror(ERROR_006_INVALIDPYOLDDOC, "old-style documentation differs from pydoc\npydoc: " + docstring + "\nfixup: " + sign + "\ncvdoc: " + signature[1], doc)
elif signature[0] == "Python2":
pname = signature[1][4:signature[1].find('(')]
cvname = "cv." + pname
parent = None
for cl in clsnamespaces:
if cvname.startswith(cl + "."):
if cl.startswith(parent or ""):
parent = cl
try:
if parent:
instance, clsname = get_cv2_object(parent)
fn = getattr(instance, cvname[len(parent)+1:])
docstr = fn.__doc__
docprefix = "cv2." + clsname + "."
else:
fn = getattr(cv2, pname)
docstr = fn.__doc__
docprefix = "cv2."
except AttributeError:
if parent:
logerror(ERROR_005_MISSINGPYFUNC, "could not load documented member of " + parent + " class: cv2." + pname, doc)
else:
logerror(ERROR_005_MISSINGPYFUNC, "could not load documented function cv2." + pname, doc)
signature.append(DOCUMENTED_MARKER) # stop subsequent errors
continue
docstrings = [docprefix + s.replace("([, ", "([") for s in docstr.split(" or ")]
if not signature[1] in docstrings:
pydocs = "\npydoc: ".join(docstrings)
logerror(ERROR_007_INVALIDPYDOC, "documentation differs from pydoc\npydoc: " + pydocs + "\ncvdoc: " + signature[1], doc)
signature.append(DOCUMENTED_MARKER)
# verify C/C++ signatures
for name, doc in rst.iteritems():
decls = doc.get("decls")
if not decls:
continue
for signature in decls:
if signature[0] == "C" or signature[0] == "C++":
if "template" in (signature[2][1] or ""):
# TODO find a way to validate templates
signature.append(DOCUMENTED_MARKER)
continue
fd = flookup.get(signature[2][0])
if not fd:
if signature[2][0].startswith("cv."):
fd = flookup.get(signature[2][0][3:])
if not fd:
continue
else:
signature[2][0] = signature[2][0][3:]
if signature[0] == "C":
ffd = [f for f in fd if not f[0] and not f[1]] # filter out C++ stuff
if not ffd:
if fd[0][1]:
logerror(ERROR_008_CFUNCISNOTGLOBAL, "function " + fd[0][2] + " is documented as C function but is actually member of " + fd[0][1] + " class", doc)
elif fd[0][0]:
logerror(ERROR_008_CFUNCISNOTGLOBAL, "function " + fd[0][2] + " is documented as C function but is actually placed in " + fd[0][0] + " namespace", doc)
fd = ffd
error = None
for f in fd:
match, error = compareSignatures(signature[2], f[3])
if match:
signature.append(DOCUMENTED_MARKER)
break
if signature[-1] != DOCUMENTED_MARKER:
candidates = "\n\t".join([formatSignature(f[3]) for f in fd])
logerror(ERROR_009_OVERLOADNOTFOUND, signature[0] + " function " + signature[2][0].replace(".","::") + " is documented but misses in headers (" + error + ").\nDocumented as:\n\t" + signature[1] + "\nCandidates are:\n\t" + candidates, doc)
signature.append(DOCUMENTED_MARKER) # to stop subsequent error on this function
# verify that all signatures was found in the library headers
for name, doc in rst.iteritems():
# if doc.get(DOCUMENTED_MARKER, False):
# continue # this class/struct was found
if not doc.get(DOCUMENTED_MARKER, False) and (doc.get("isclass", False) or doc.get("isstruct", False)):
if name in doc_signatures_whitelist:
continue
logerror(ERROR_010_UNKNOWNCLASS, "class/struct " + name + " is mentioned in documentation but is not found in OpenCV headers", doc)
for d in doc.get("decls", []):
if d[-1] != DOCUMENTED_MARKER:
if d[0] == "C" or d[0] =="C++" or (do_python_crosscheck and d[0].startswith("Python")):
if d[0][0] == 'C':
sname = d[2][0][3:].replace(".", "::")
if sname in defines:
#TODO: need to find a way to verify #define's
continue
else:
sname = d[1][:d[1].find("(")]
prefixes = [x for x in doc_signatures_whitelist if sname.startswith(x)]
if prefixes:
# TODO: member of template class
continue
logerror(ERROR_011_UNKNOWNFUNC, d[0] + " function " + sname + " is documented but is not found in OpenCV headers. It is documented as:\n\t" + d[1], doc)
# end of process_module
if __name__ == "__main__":
if len(sys.argv) < 2:
print "Usage:\n", os.path.basename(sys.argv[0]), " <module path>"
exit(0)
modules = sys.argv[1:]
if modules[0] == "all":
modules = allmodules
for module in modules:
selfpath = os.path.dirname(os.path.abspath(sys.argv[0]))
module_path = os.path.join(selfpath, "..", "modules", module)
if not os.path.isdir(module_path):
print "Module \"" + module + "\" could not be found."
exit(1)
process_module(module, module_path)

View File

@@ -231,9 +231,9 @@ latex_documents = [
('modules/refman', 'opencv2refman.tex', u'The OpenCV Reference Manual',
u'', 'manual'),
('doc/user_guide/user_guide', 'opencv_user.tex', u'The OpenCV User Guide',
u'', 'manual'),
u'', 'manual'),
('doc/tutorials/tutorials', 'opencv_tutorials.tex', u'The OpenCV Tutorials',
u'', 'manual'),
u'', 'manual'),
]
preamble ="""
@@ -303,7 +303,7 @@ extlinks = {
'calib3d' : ('http://opencv.itseez.com/trunk/modules/calib3d/doc/camera_calibration_and_3d_reconstruction.html#%s', None ),
'feature2d' : ('http://opencv.itseez.com/trunk/modules/imgproc/doc/feature_detection.html#%s', None ),
'imgproc_geometric' : ('http://opencv.itseez.com/trunk/modules/imgproc/doc/geometric_transformations.html#%s', None ),
'opencv_group' : ('http://tech.groups.yahoo.com/group/OpenCV/%s', None),
'cvt_color': ('http://opencv.itseez.com/modules/imgproc/doc/miscellaneous_transformations.html?highlight=cvtcolor#cvtcolor%s', None),

View File

@@ -25,7 +25,7 @@ from sphinx.util.nodes import make_refnode
from sphinx.util.compat import Directive
from sphinx.util.docfields import Field, GroupedField, TypedField
########################### Python Part ###########################
########################### Python Part ###########################
# REs for Python signatures
py_sig_re = re.compile(
@@ -292,9 +292,10 @@ class OCVPyXRefRole(XRefRole):
return title, target
########################### C/C++/Java Part ###########################
########################### C/C++/Java Part ###########################
_identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*)\b')
_identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b)')
_argument_name_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b(?:\[\d*\])?|\.\.\.)')
_whitespace_re = re.compile(r'\s+(?u)')
_string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
@@ -303,10 +304,10 @@ _operator_re = re.compile(r'''(?x)
\[\s*\]
| \(\s*\)
| (<<|>>)=?
| \+\+ | -- | ->\*?
| [!<>=/*%+|&^-]=?
| \+\+ | --
| ~ | && | \| | \|\|
| ->\*? | \,
| \,
''')
_id_shortwords = {
@@ -561,7 +562,7 @@ class ConstDefExpr(WrappingDefExpr):
def __unicode__(self):
return (self.prefix and u'const %s' or u'%s const') % self.typename
class ConstTemplateDefExpr(WrappingDefExpr):
def __init__(self, typename, prefix=False):
@@ -667,13 +668,14 @@ class MemberObjDefExpr(NamedDefExpr):
class FuncDefExpr(NamedDefExpr):
def __init__(self, name, visibility, static, explicit, rv,
signature, const, pure_virtual):
signature, const, pure_virtual, virtual):
NamedDefExpr.__init__(self, name, visibility, static)
self.rv = rv
self.signature = signature
self.explicit = explicit
self.const = const
self.pure_virtual = pure_virtual
self.virtual = virtual
def get_id(self):
return u'%s%s%s' % (
@@ -682,11 +684,13 @@ class FuncDefExpr(NamedDefExpr):
u'.'.join(x.get_id() for x in self.signature) or u'',
self.const and u'C' or u''
)
def __unicode__(self):
buf = self.get_modifiers()
if self.explicit:
buf.append(u'explicit')
if self.virtual:
buf.append(u'virtual')
if self.rv is not None:
buf.append(unicode(self.rv))
buf.append(u'%s(%s)' % (self.name, u', '.join(
@@ -700,8 +704,9 @@ class FuncDefExpr(NamedDefExpr):
class ClassDefExpr(NamedDefExpr):
def __init__(self, name, visibility, static):
def __init__(self, name, visibility, static, parents = None):
NamedDefExpr.__init__(self, name, visibility, static)
self.parents = parents
def get_id(self):
return self.name.get_id()
@@ -788,7 +793,6 @@ class DefinitionParser(object):
if self.match(_operator_re):
return NameDefExpr('operator' +
_whitespace_re.sub('', self.matched_text))
# new/delete operator?
for allocop in 'new', 'delete':
if not self.skip_word(allocop):
@@ -807,7 +811,7 @@ class DefinitionParser(object):
return CastOpDefExpr(type)
def _parse_name(self):
if not self.match(_identifier_re):
if not self.match(_argument_name_re):
self.fail('expected name')
identifier = self.matched_text
@@ -981,7 +985,7 @@ class DefinitionParser(object):
elif paren_stack_depth == 0:
break
self.pos = idx+1
rv = self.definition[rv_start:idx]
self.pos = idx
return rv
@@ -1004,8 +1008,13 @@ class DefinitionParser(object):
self.skip_ws()
argtype = self._parse_type()
argname = default = None
self.skip_ws()
if unicode(argtype) == u"...":
if not self.skip_string(')'):
self.fail("var arg must be the last argument")
args.append(ArgumentDefExpr(None, argtype, None))
break
argname = default = None
if self.skip_string('='):
self.pos += 1
default = self._parse_default_expr()
@@ -1072,6 +1081,11 @@ class DefinitionParser(object):
self.skip_ws()
else:
explicit = False
if self.skip_word('virtual'):
virtual = True
self.skip_ws()
else:
virtual = False
rv = self._parse_type()
self.skip_ws()
# some things just don't have return values
@@ -1080,12 +1094,27 @@ class DefinitionParser(object):
rv = None
else:
name = self._parse_type()
return FuncDefExpr(name, visibility, static, explicit, rv,
*self._parse_signature())
return FuncDefExpr(name, visibility, static, explicit, rv,
*self._parse_signature(), virtual = virtual)
def parse_class(self):
visibility, static = self._parse_visibility_static()
return ClassDefExpr(self._parse_type(), visibility, static)
typename = self._parse_type()
parent = None
self.skip_ws()
parents = []
if self.skip_string(':'):
while not self.eof:
self.skip_ws()
classname_pos = self.pos
pvisibility, pstatic = self._parse_visibility_static()
if pstatic:
self.fail('unsepected static keyword, got %r' %
self.definition[self.classname_pos:])
parents.append(ClassDefExpr(self._parse_type(), pvisibility, pstatic))
if not self.skip_string(','):
break
return ClassDefExpr(typename, visibility, static, parents)
def read_rest(self):
rv = self.definition[self.pos:]
@@ -1138,7 +1167,7 @@ class OCVObject(ObjectDescription):
lname = self.__class__.langname
node += nodes.strong(lname + ":", lname + ":")
node += addnodes.desc_name(" ", " ")
if obj.visibility != 'public':
node += addnodes.desc_annotation(obj.visibility,
obj.visibility)
@@ -1212,8 +1241,8 @@ class OCVClassObject(OCVObject):
object_annotation = "class "
object_long_name = "class"
def attach_modifiers(self, node, obj):
if obj.visibility != 'public':
def attach_modifiers(self, node, obj, skip_visibility = 'public'):
if obj.visibility != skip_visibility:
node += addnodes.desc_annotation(obj.visibility,
obj.visibility)
node += nodes.Text(' ')
@@ -1231,6 +1260,15 @@ class OCVClassObject(OCVObject):
self.attach_modifiers(signode, cls)
signode += addnodes.desc_annotation(self.__class__.object_annotation, self.__class__.object_annotation)
self.attach_name(signode, cls.name)
first_parent = True
for p in cls.parents:
if first_parent:
signode += nodes.Text(' : ')
first_parent = False
else:
signode += nodes.Text(', ')
self.attach_modifiers(signode, p, None)
self.attach_name(signode, p.name)
class OCVStructObject(OCVClassObject):
object_annotation = "struct "
@@ -1263,6 +1301,9 @@ class OCVMemberObject(OCVObject):
return ''
def parse_definition(self, parser):
parent_class = self.env.temp_data.get('ocv:parent')
if parent_class is None:
parser.fail("missing parent structure/class")
return parser.parse_member_object()
def describe_signature(self, signode, obj):
@@ -1298,7 +1339,12 @@ class OCVFunctionObject(OCVObject):
self.attach_type(param, arg.type)
param += nodes.Text(u' ')
#param += nodes.emphasis(unicode(arg.name), unicode(arg.name))
param += nodes.strong(unicode(arg.name), unicode(arg.name))
sbrIdx = unicode(arg.name).find("[")
if sbrIdx < 0:
param += nodes.strong(unicode(arg.name), unicode(arg.name))
else:
param += nodes.strong(unicode(arg.name)[:sbrIdx], unicode(arg.name)[:sbrIdx])
param += nodes.Text(unicode(arg.name)[sbrIdx:])
if arg.default is not None:
def_ = u'=' + unicode(arg.default)
#param += nodes.emphasis(def_, def_)
@@ -1325,6 +1371,9 @@ class OCVFunctionObject(OCVObject):
if func.explicit:
signode += addnodes.desc_annotation('explicit', 'explicit')
signode += nodes.Text(' ')
if func.virtual:
signode += addnodes.desc_annotation('virtual', 'virtual')
signode += nodes.Text(' ')
# return value is None for things with a reverse return value
# such as casting operator definitions or constructors
# and destructors.
@@ -1380,7 +1429,7 @@ class OCVXRefRole(XRefRole):
class OCVCFunctionObject(OCVFunctionObject):
langname = "C"
class OCVJavaFunctionObject(OCVFunctionObject):
langname = "Java"
@@ -1430,7 +1479,7 @@ class OCVDomain(Domain):
initial_data = {
'objects': {}, # fullname -> docname, objtype
}
def __init__(self, env):
Domain.__init__(self, env)
self.data['objects2'] = {}
@@ -1496,14 +1545,14 @@ class OCVDomain(Domain):
def get_objects(self):
for refname, (docname, type, theid) in self.data['objects'].iteritems():
yield (refname, refname, type, docname, refname, 1)
def get_type_name(self, type, primary=False):
"""
Return full name for given ObjType.
"""
if primary:
return type.lname
return {
'class': _('C++ class'),
'struct': _('C/C++ struct'),
@@ -1516,6 +1565,6 @@ class OCVDomain(Domain):
'type': _('C/C++ type'),
'namespace': _('C++ namespace'),
}.get(type.lname, _('%s %s') % (self.label, type.lname))
def setup(app):
app.add_domain(OCVDomain)