1 # -*- coding: utf-8 -*-
3 ocv domain, a modified copy of sphinx.domains.cpp + shpinx.domains.python.
4 The original copyright is below
5 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
7 The OpenCV C/C++/Python/Java/... language domain.
9 :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
10 :license: BSD, see LICENSE for details.
14 from copy import deepcopy
16 from docutils import nodes
17 from docutils.parsers.rst import directives
19 from sphinx import addnodes
20 from sphinx.roles import XRefRole
21 from sphinx.locale import l_, _
22 from sphinx.domains import Domain, ObjType
23 from sphinx.directives import ObjectDescription
24 from sphinx.util.nodes import make_refnode
25 from sphinx.util.compat import Directive
26 from sphinx.util.docfields import Field, GroupedField, TypedField
28 ########################### Python Part ###########################
30 # REs for Python signatures
31 py_sig_re = re.compile(
32 r'''^ ([\w.]*\.)? # class name(s)
33 (\w+) \s* # thing name
34 (?: \((.*)\) # optional: arguments
35 (?:\s* -> \s* (.*))? # return annotation
36 )? $ # and nothing more
40 def _pseudo_parse_arglist(signode, arglist):
41 """"Parse" a list of arguments separated by commas.
43 Arguments can have "optional" annotations given by enclosing them in
44 brackets. Currently, this will split at any comma, even if it's inside a
45 string literal (e.g. default argument value).
47 paramlist = addnodes.desc_parameterlist()
50 for argument in arglist.split(','):
51 argument = argument.strip()
52 ends_open = ends_close = 0
53 while argument.startswith('['):
54 stack.append(addnodes.desc_optional())
55 stack[-2] += stack[-1]
56 argument = argument[1:].strip()
57 while argument.startswith(']'):
59 argument = argument[1:].strip()
60 while argument.endswith(']'):
62 argument = argument[:-1].strip()
63 while argument.endswith('['):
65 argument = argument[:-1].strip()
67 stack[-1] += addnodes.desc_parameter(argument, argument, noemph=True)
69 stack.append(addnodes.desc_optional())
70 stack[-2] += stack[-1]
78 # if there are too few or too many elements on the stack, just give up
79 # and treat the whole argument list as one argument, discarding the
80 # already partially populated paramlist node
81 signode += addnodes.desc_parameterlist()
82 signode[-1] += addnodes.desc_parameter(arglist, arglist)
87 class OCVPyObject(ObjectDescription):
89 Description of a general Python object.
92 'noindex': directives.flag,
93 'module': directives.unchanged,
97 TypedField('parameter', label=l_('Parameters'),
98 names=('param', 'parameter', 'arg', 'argument',
99 'keyword', 'kwarg', 'kwparam'),
100 typerolename='obj', typenames=('paramtype', 'type'),
102 TypedField('variable', label=l_('Variables'), rolename='obj',
103 names=('var', 'ivar', 'cvar'),
104 typerolename='obj', typenames=('vartype',),
106 GroupedField('exceptions', label=l_('Raises'), rolename='exc',
107 names=('raises', 'raise', 'exception', 'except'),
109 Field('returnvalue', label=l_('Returns'), has_arg=False,
110 names=('returns', 'return')),
111 Field('returntype', label=l_('Return type'), has_arg=False,
115 def get_signature_prefix(self, sig):
117 May return a prefix to put before the object name in the signature.
121 def needs_arglist(self):
123 May return true if an empty argument list is to be generated even if
124 the document contains none.
128 def handle_signature(self, sig, signode):
130 Transform a Python signature into RST nodes.
131 Returns (fully qualified name of the thing, classname if any).
133 If inside a class, the current class name is handled intelligently:
134 * it is stripped from the displayed name if present
135 * it is added to the full name (return value) if not present
137 signode += nodes.strong("Python:", "Python:")
138 signode += addnodes.desc_name(" ", " ")
139 m = py_sig_re.match(sig)
142 name_prefix, name, arglist, retann = m.groups()
144 # determine module and class name (if applicable), as well as full name
145 modname = self.options.get(
146 'module', self.env.temp_data.get('py:module'))
147 classname = self.env.temp_data.get('py:class')
150 if name_prefix and name_prefix.startswith(classname):
151 fullname = name_prefix + name
152 # class name is given again in the signature
153 name_prefix = name_prefix[len(classname):].lstrip('.')
155 # class name is given in the signature, but different
157 fullname = classname + '.' + name_prefix + name
159 # class name is not given in the signature
160 fullname = classname + '.' + name
164 classname = name_prefix.rstrip('.')
165 fullname = name_prefix + name
170 signode['module'] = modname
171 signode['class'] = classname
172 signode['fullname'] = fullname
174 sig_prefix = self.get_signature_prefix(sig)
176 signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
179 signode += addnodes.desc_addname(name_prefix, name_prefix)
180 # exceptions are a special case, since they are documented in the
181 # 'exceptions' module.
182 elif add_module and self.env.config.add_module_names:
183 modname = self.options.get(
184 'module', self.env.temp_data.get('py:module'))
185 if modname and modname != 'exceptions':
186 nodetext = modname + '.'
187 signode += addnodes.desc_addname(nodetext, nodetext)
189 signode += addnodes.desc_name(name, name)
191 if self.needs_arglist():
192 # for callables, add an empty parameter list
193 signode += addnodes.desc_parameterlist()
195 signode += addnodes.desc_returns(retann, retann)
196 return fullname, name_prefix
197 _pseudo_parse_arglist(signode, arglist)
199 signode += addnodes.desc_returns(retann, retann)
200 return fullname, name_prefix
202 def get_index_text(self, modname, name):
204 Return the text for the index entry of the object.
206 raise NotImplementedError('must be implemented in subclasses')
208 def add_target_and_index(self, name_cls, sig, signode):
209 modname = self.options.get(
210 'module', self.env.temp_data.get('py:module'))
211 fullname = (modname and modname + '.' or '') + name_cls[0]
213 if fullname not in self.state.document.ids:
214 signode['names'].append(fullname)
215 signode['ids'].append(fullname)
216 signode['first'] = (not self.names)
217 self.state.document.note_explicit_target(signode)
218 objects = self.env.domaindata['ocv']['objects']
219 if fullname in objects:
222 'duplicate object description of %s, ' % fullname +
223 'other instance in ' +
224 self.env.doc2path(objects[fullname][0]) +
225 ', use :noindex: for one of them',
227 objects.setdefault(fullname, (self.env.docname, self.objtype, name_cls[0]))
229 indextext = self.get_index_text(modname, name_cls)
231 self.indexnode['entries'].append(('single', indextext,
234 def before_content(self):
235 # needed for automatic qualification of members (reset in subclasses)
236 self.clsname_set = False
238 def after_content(self):
240 self.env.temp_data['py:class'] = None
242 class OCVPyModulelevel(OCVPyObject):
244 Description of an object on module level (functions, data).
246 directive_prefix = 'py'
248 def needs_arglist(self):
249 return self.objtype == self.__class__.directive_prefix + 'function'
251 def get_index_text(self, modname, name_cls):
252 if self.objtype == self.__class__.directive_prefix + 'function':
255 if not fname.startswith("cv") and not fname.startswith("cv2"):
256 return _('%s() (Python function)') % fname
257 pos = fname.find(".")
258 modname = fname[:pos]
259 fname = fname[pos+1:]
260 return _('%s() (Python function in %s)') % (fname, modname)
261 return _('%s() (Python function in %s)') % (name_cls[0], modname)
262 elif self.objtype == 'pydata':
264 return _('%s (Python variable)') % name_cls[0]
265 return _('%s (in module %s)') % (name_cls[0], modname)
269 class OCVPyOldModulelevel(OCVPyModulelevel):
270 directive_prefix = 'pyold'
273 class OCVPyXRefRole(XRefRole):
274 def process_link(self, env, refnode, has_explicit_title, title, target):
275 refnode['ocv:module'] = env.temp_data.get('ocv:module')
276 refnode['ocv:class'] = env.temp_data.get('ocv:class')
277 if not has_explicit_title:
278 title = title.lstrip('.') # only has a meaning for the target
279 target = target.lstrip('~') # only has a meaning for the title
280 # if the first character is a tilde, don't display the module/class
281 # parts of the contents
282 if title[0:1] == '~':
284 dot = title.rfind('.')
286 title = title[dot+1:]
287 # if the first character is a dot, search more specific namespaces first
288 # else search builtins first
289 if target[0:1] == '.':
291 refnode['refspecific'] = True
295 ########################### C/C++/Java Part ###########################
297 _identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*)\b')
298 _whitespace_re = re.compile(r'\s+(?u)')
299 _string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
300 r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
301 _visibility_re = re.compile(r'\b(public|private|protected)\b')
302 _operator_re = re.compile(r'''(?x)
315 'unsigned char': 'C',
321 'unsigned long': 'L',
325 'std::ostream': 'os',
326 'std::istream': 'is',
327 'std::iostream': 'ios',
330 'operator[]': 'subscript-operator',
331 'operator()': 'call-operator',
332 'operator!': 'not-operator',
333 'operator<': 'lt-operator',
334 'operator<=': 'lte-operator',
335 'operator>': 'gt-operator',
336 'operator>=': 'gte-operator',
337 'operator=': 'assign-operator',
338 'operator/': 'div-operator',
339 'operator*': 'mul-operator',
340 'operator%': 'mod-operator',
341 'operator+': 'add-operator',
342 'operator-': 'sub-operator',
343 'operator|': 'or-operator',
344 'operator&': 'and-operator',
345 'operator^': 'xor-operator',
346 'operator&&': 'sand-operator',
347 'operator||': 'sor-operator',
348 'operator==': 'eq-operator',
349 'operator!=': 'neq-operator',
350 'operator<<': 'lshift-operator',
351 'operator>>': 'rshift-operator',
352 'operator-=': 'sub-assign-operator',
353 'operator+=': 'add-assign-operator',
354 'operator*-': 'mul-assign-operator',
355 'operator/=': 'div-assign-operator',
356 'operator%=': 'mod-assign-operator',
357 'operator&=': 'and-assign-operator',
358 'operator|=': 'or-assign-operator',
359 'operator<<=': 'lshift-assign-operator',
360 'operator>>=': 'rshift-assign-operator',
361 'operator^=': 'xor-assign-operator',
362 'operator,': 'comma-operator',
363 'operator->': 'pointer-operator',
364 'operator->*': 'pointer-by-pointer-operator',
365 'operator~': 'inv-operator',
366 'operator++': 'inc-operator',
367 'operator--': 'dec-operator',
368 'operator new': 'new-operator',
369 'operator new[]': 'new-array-operator',
370 'operator delete': 'delete-operator',
371 'operator delete[]': 'delete-array-operator'
375 class DefinitionError(Exception):
377 def __init__(self, description):
378 self.description = description
380 def __unicode__(self):
381 return self.description
384 return unicode(self.encode('utf-8'))
387 class DefExpr(object):
389 def __unicode__(self):
390 raise NotImplementedError()
392 def __eq__(self, other):
393 if type(self) is not type(other):
396 for key, value in self.__dict__.iteritems():
397 if value != getattr(other, value):
399 except AttributeError:
403 def __ne__(self, other):
404 return not self.__eq__(other)
407 """Close a definition expression node"""
408 return deepcopy(self)
411 """Returns the id for the node"""
415 """Returns the name. Returns either `None` or a node with
416 a name you might call :meth:`split_owner` on.
420 def split_owner(self):
421 """Nodes returned by :meth:`get_name` can split off their
422 owning parent. This function returns the owner and the
423 name as a tuple of two items. If a node does not support
424 it, it returns None as owner and self as name.
428 def prefix(self, prefix):
429 """Prefixes a name node (a node returned by :meth:`get_name`)."""
430 raise NotImplementedError()
433 return unicode(self).encode('utf-8')
436 return '<%s %s>' % (self.__class__.__name__, self)
439 class PrimaryDefExpr(DefExpr):
444 def prefix(self, prefix):
445 if isinstance(prefix, PathDefExpr):
446 prefix = prefix.clone()
447 prefix.path.append(self)
449 return PathDefExpr([prefix, self])
452 class NameDefExpr(PrimaryDefExpr):
454 def __init__(self, name):
458 name = _id_shortwords.get(self.name)
461 return self.name.replace(u' ', u'-')
463 def __unicode__(self):
464 return unicode(self.name)
467 class PathDefExpr(PrimaryDefExpr):
469 def __init__(self, parts):
473 rv = u'::'.join(x.get_id() for x in self.path)
474 return _id_shortwords.get(rv, rv)
476 def split_owner(self):
477 if len(self.path) > 1:
478 return PathDefExpr(self.path[:-1]), self.path[-1]
481 def prefix(self, prefix):
482 if isinstance(prefix, PathDefExpr):
483 prefix = prefix.clone()
484 prefix.path.extend(self.path)
486 return PathDefExpr([prefix] + self.path)
488 def __unicode__(self):
489 return u'::'.join(map(unicode, self.path))
492 class TemplateDefExpr(PrimaryDefExpr):
494 def __init__(self, typename, args):
495 self.typename = typename
498 def split_owner(self):
499 owner, typename = self.typename.split_owner()
500 return owner, TemplateDefExpr(typename, self.args)
503 return u'%s:%s:' % (self.typename.get_id(),
504 u'.'.join(x.get_id() for x in self.args))
506 def __unicode__(self):
507 return u'%s<%s>' % (self.typename, u', '.join(map(unicode, self.args)))
510 class WrappingDefExpr(DefExpr):
512 def __init__(self, typename):
513 self.typename = typename
516 return self.typename.get_name()
519 class ModifierDefExpr(WrappingDefExpr):
521 def __init__(self, typename, modifiers):
522 WrappingDefExpr.__init__(self, typename)
523 self.modifiers = modifiers
526 pieces = [_id_shortwords.get(unicode(x), unicode(x))
527 for x in self.modifiers]
528 pieces.append(self.typename.get_id())
529 return u'-'.join(pieces)
531 def __unicode__(self):
532 return u' '.join(map(unicode, list(self.modifiers) + [self.typename]))
535 class PtrDefExpr(WrappingDefExpr):
538 return self.typename.get_id() + u'P'
540 def __unicode__(self):
541 return u'%s*' % self.typename
544 class RefDefExpr(WrappingDefExpr):
547 return self.typename.get_id() + u'R'
549 def __unicode__(self):
550 return u'%s&' % self.typename
553 class ConstDefExpr(WrappingDefExpr):
555 def __init__(self, typename, prefix=False):
556 WrappingDefExpr.__init__(self, typename)
560 return self.typename.get_id() + u'C'
562 def __unicode__(self):
563 return (self.prefix and u'const %s' or u'%s const') % self.typename
565 class ConstTemplateDefExpr(WrappingDefExpr):
567 def __init__(self, typename, prefix=False):
568 WrappingDefExpr.__init__(self, typename)
572 return self.typename.get_id() + u'C'
574 def __unicode__(self):
575 return (self.prefix and u'const %s' or u'%s const') % self.typename
578 class CastOpDefExpr(PrimaryDefExpr):
580 def __init__(self, typename):
581 self.typename = typename
584 return u'castto-%s-operator' % self.typename.get_id()
586 def __unicode__(self):
587 return u'operator %s' % self.typename
590 class ArgumentDefExpr(DefExpr):
592 def __init__(self, type, name, default=None):
595 self.default = default
598 return self.name.get_name()
601 if self.type is None:
603 return self.type.get_id()
605 def __unicode__(self):
606 return (u'%s %s' % (self.type or u'', self.name or u'')).strip() + \
607 (self.default is not None and u'=%s' % self.default or u'')
610 class NamedDefExpr(DefExpr):
612 def __init__(self, name, visibility, static):
614 self.visibility = visibility
618 return self.name.get_name()
620 def get_modifiers(self):
622 if self.visibility != 'public':
623 rv.append(self.visibility)
629 class TypeObjDefExpr(NamedDefExpr):
631 def __init__(self, name, visibility, static, typename):
632 NamedDefExpr.__init__(self, name, visibility, static)
633 self.typename = typename
636 if self.typename is None:
637 return self.name.get_id()
638 return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
640 def __unicode__(self):
641 buf = self.get_modifiers()
642 if self.typename is None:
643 buf.append(unicode(self.name))
645 buf.extend(map(unicode, (self.typename, self.name)))
646 return u' '.join(buf)
649 class MemberObjDefExpr(NamedDefExpr):
651 def __init__(self, name, visibility, static, typename, value):
652 NamedDefExpr.__init__(self, name, visibility, static)
653 self.typename = typename
657 return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
659 def __unicode__(self):
660 buf = self.get_modifiers()
661 buf.append(u'%s %s' % (self.typename, self.name))
662 if self.value is not None:
663 buf.append(u'= %s' % self.value)
664 return u' '.join(buf)
667 class FuncDefExpr(NamedDefExpr):
669 def __init__(self, name, visibility, static, explicit, rv,
670 signature, const, pure_virtual):
671 NamedDefExpr.__init__(self, name, visibility, static)
673 self.signature = signature
674 self.explicit = explicit
676 self.pure_virtual = pure_virtual
681 self.signature and u'__' +
682 u'.'.join(x.get_id() for x in self.signature) or u'',
683 self.const and u'C' or u''
686 def __unicode__(self):
687 buf = self.get_modifiers()
689 buf.append(u'explicit')
690 if self.rv is not None:
691 buf.append(unicode(self.rv))
692 buf.append(u'%s(%s)' % (self.name, u', '.join(
693 map(unicode, self.signature))))
696 if self.pure_virtual:
698 return u' '.join(buf)
701 class ClassDefExpr(NamedDefExpr):
703 def __init__(self, name, visibility, static):
704 NamedDefExpr.__init__(self, name, visibility, static)
707 return self.name.get_id()
709 def __unicode__(self):
710 buf = self.get_modifiers()
711 buf.append(unicode(self.name))
712 return u' '.join(buf)
715 class DefinitionParser(object):
717 # mapping of valid type modifiers. if the set is None it means
718 # the modifier can prefix all types, otherwise only the types
719 # (actually more keywords) in the set. Also check
720 # _guess_typename when changing this.
727 'unsigned': set(('char', 'short', 'int', 'long')),
728 'signed': set(('char', 'short', 'int', 'long')),
729 'short': set(('int',)),
730 'long': set(('int', 'long', 'double'))
733 def __init__(self, definition):
734 self.definition = definition.strip()
736 self.end = len(self.definition)
737 self.last_match = None
738 self._previous_state = (0, None)
741 raise DefinitionError('Invalid definition: %s [error at %d]\n %s' %
742 (msg, self.pos, self.definition))
744 def match(self, regex):
745 match = regex.match(self.definition, self.pos)
746 if match is not None:
747 self._previous_state = (self.pos, self.last_match)
748 self.pos = match.end()
749 self.last_match = match
754 self.pos, self.last_match = self._previous_state
756 def skip_string(self, string):
758 if self.definition[self.pos:self.pos + strlen] == string:
763 def skip_word(self, word):
764 return self.match(re.compile(r'\b%s\b' % re.escape(word)))
767 return self.match(_whitespace_re)
771 return self.pos >= self.end
774 def current_char(self):
776 return self.definition[self.pos]
781 def matched_text(self):
782 if self.last_match is not None:
783 return self.last_match.group()
785 def _parse_operator(self):
787 # thank god, a regular operator definition
788 if self.match(_operator_re):
789 return NameDefExpr('operator' +
790 _whitespace_re.sub('', self.matched_text))
792 # new/delete operator?
793 for allocop in 'new', 'delete':
794 if not self.skip_word(allocop):
797 if self.skip_string('['):
799 if not self.skip_string(']'):
800 self.fail('expected "]" for ' + allocop)
802 return NameDefExpr('operator ' + allocop)
804 # oh well, looks like a cast operator definition.
805 # In that case, eat another type.
806 type = self._parse_type()
807 return CastOpDefExpr(type)
809 def _parse_name(self):
810 if not self.match(_identifier_re):
811 self.fail('expected name')
812 identifier = self.matched_text
814 # strictly speaking, operators are not regular identifiers
815 # but because operator is a keyword, it might not be used
816 # for variable names anyways, so we can safely parse the
817 # operator here as identifier
818 if identifier == 'operator':
819 return self._parse_operator()
821 return NameDefExpr(identifier)
823 def _guess_typename(self, path):
826 # for the long type, we don't want the int in there
828 path = [x for x in path if x != 'int']
832 if path[-1] in ('int', 'char'):
833 return path[:-1], path[-1]
836 def _attach_crefptr(self, expr, is_const=False):
838 expr = ConstDefExpr(expr, prefix=True)
841 if self.skip_word('const'):
842 expr = ConstDefExpr(expr)
843 elif self.skip_string('*'):
844 expr = PtrDefExpr(expr)
845 elif self.skip_string('&'):
846 expr = RefDefExpr(expr)
850 def _peek_const(self, path):
857 def _parse_builtin(self, modifier):
859 following = self._modifiers[modifier]
862 if not self.match(_identifier_re):
864 identifier = self.matched_text
865 if identifier in following:
866 path.append(identifier)
867 following = self._modifiers[modifier]
873 is_const = self._peek_const(path)
874 modifiers, typename = self._guess_typename(path)
875 rv = ModifierDefExpr(NameDefExpr(typename), modifiers)
876 return self._attach_crefptr(rv, is_const)
878 def _parse_type_expr(self):
879 typename = self._parse_name()
880 if typename and self.skip_string('['):
882 if self.match(re.compile(r'\d*')):
883 typename.name += self.last_match.group(0)
885 if not self.skip_string(']'):
886 self.fail('expected type')
888 if not self.skip_string('<'):
894 if self.skip_string('>'):
897 if not self.skip_string(','):
898 self.fail('"," or ">" in template expected')
900 args.append(self._parse_type(True))
901 return TemplateDefExpr(typename, args)
903 def _parse_type(self, in_template=False):
908 if self.match(re.compile(r'template\w*<([^>]*)>')):
909 args = self.last_match.group(1).split(',')
910 args = [a.strip() for a in args]
911 modifiers.append(TemplateDefExpr('template', args))
913 # if there is a leading :: or not, we don't care because we
914 # treat them exactly the same. Buf *if* there is one, we
915 # don't have to check for type modifiers
916 if not self.skip_string('::'):
918 while self.match(_identifier_re):
919 modifier = self.matched_text
920 if modifier in self._modifiers:
921 following = self._modifiers[modifier]
922 # if the set is not none, there is a limited set
923 # of types that might follow. It is technically
924 # impossible for a template to follow, so what
925 # we do is go to a different function that just
927 if following is not None:
928 return self._parse_builtin(modifier)
929 modifiers.append(modifier)
936 if (in_template and self.current_char in ',>') or \
937 (result and not self.skip_string('::')) or \
940 result.append(self._parse_type_expr())
943 self.fail('expected type')
947 rv = PathDefExpr(result)
948 is_const = self._peek_const(modifiers)
950 rv = ConstDefExpr(rv, prefix=True)
952 rv = ModifierDefExpr(rv, modifiers)
953 return self._attach_crefptr(rv, False)
955 def _parse_default_expr(self):
957 if self.match(_string_re):
958 return self.matched_text
959 paren_stack_depth = 0
960 max_pos = len(self.definition)
963 idx0 = self.definition.find('(', self.pos)
964 idx1 = self.definition.find(',', self.pos)
965 idx2 = self.definition.find(')', self.pos)
972 idx = min(idx0, idx1, idx2)
974 self.fail('unexpected end in default expression')
976 paren_stack_depth += 1
978 paren_stack_depth -= 1
979 if paren_stack_depth < 0:
981 elif paren_stack_depth == 0:
985 rv = self.definition[rv_start:idx]
989 def _parse_signature(self):
991 if not self.skip_string('('):
992 self.fail('expected parentheses for function')
998 self.fail('missing closing parentheses')
999 if self.skip_string(')'):
1002 if not self.skip_string(','):
1003 self.fail('expected comma between arguments')
1006 argtype = self._parse_type()
1007 argname = default = None
1009 if self.skip_string('='):
1011 default = self._parse_default_expr()
1012 elif self.current_char not in ',)':
1013 argname = self._parse_name()
1015 if self.skip_string('='):
1016 default = self._parse_default_expr()
1018 args.append(ArgumentDefExpr(argtype, argname, default))
1020 const = self.skip_word('const')
1023 if self.skip_string('='):
1025 if not (self.skip_string('0') or \
1026 self.skip_word('NULL') or \
1027 self.skip_word('nullptr')):
1028 self.fail('pure virtual functions must be defined with '
1029 'either 0, NULL or nullptr, other macros are '
1033 pure_virtual = False
1034 return args, const, pure_virtual
1036 def _parse_visibility_static(self):
1037 visibility = 'public'
1038 if self.match(_visibility_re):
1039 visibility = self.matched_text
1040 static = self.skip_word('static')
1041 return visibility, static
1043 def parse_type(self):
1044 return self._parse_type()
1046 def parse_type_object(self):
1047 visibility, static = self._parse_visibility_static()
1048 typename = self._parse_type()
1051 name = self._parse_type()
1055 return TypeObjDefExpr(name, visibility, static, typename)
1057 def parse_member_object(self):
1058 visibility, static = self._parse_visibility_static()
1059 typename = self._parse_type()
1060 name = self._parse_type()
1062 if self.skip_string('='):
1063 value = self.read_rest().strip()
1066 return MemberObjDefExpr(name, visibility, static, typename, value)
1068 def parse_function(self):
1069 visibility, static = self._parse_visibility_static()
1070 if self.skip_word('explicit'):
1075 rv = self._parse_type()
1077 # some things just don't have return values
1078 if self.current_char == '(':
1082 name = self._parse_type()
1083 return FuncDefExpr(name, visibility, static, explicit, rv,
1084 *self._parse_signature())
1086 def parse_class(self):
1087 visibility, static = self._parse_visibility_static()
1088 return ClassDefExpr(self._parse_type(), visibility, static)
1090 def read_rest(self):
1091 rv = self.definition[self.pos:]
1095 def assert_end(self):
1098 self.fail('expected end of definition, got %r' %
1099 self.definition[self.pos:])
1102 class OCVObject(ObjectDescription):
1103 """Description of a C++ language object."""
1109 TypedField('parameter', label=l_('Parameters'),
1110 names=('param', 'parameter', 'arg', 'argument'),
1111 typerolename='type', typenames=('type',)),
1112 Field('returnvalue', label=l_('Returns'), has_arg=False,
1113 names=('returns', 'return')),
1114 Field('returntype', label=l_('Return type'), has_arg=False,
1118 def attach_name(self, node, name):
1119 owner, name = name.split_owner()
1120 varname = unicode(name)
1121 if owner is not None:
1122 owner = unicode(owner) + '::'
1123 node += addnodes.desc_addname(owner, owner)
1124 node += addnodes.desc_name(varname, varname)
1126 def attach_type(self, node, type):
1128 text = unicode(type)
1129 pnode = addnodes.pending_xref(
1130 '', refdomain='ocv', reftype='type',
1131 reftarget=text, modname=None, classname=None)
1132 pnode['ocv:parent'] = self.env.temp_data.get('ocv:parent')
1133 pnode += nodes.Text(text)
1136 def attach_modifiers(self, node, obj):
1137 if not self.__class__.ismember:
1138 lname = self.__class__.langname
1139 node += nodes.strong(lname + ":", lname + ":")
1140 node += addnodes.desc_name(" ", " ")
1142 if obj.visibility != 'public':
1143 node += addnodes.desc_annotation(obj.visibility,
1145 node += nodes.Text(' ')
1147 node += addnodes.desc_annotation('static', 'static')
1148 node += nodes.Text(' ')
1150 def add_target_and_index(self, sigobj, sig, signode):
1151 theid = sig#obj.get_id()
1152 theid = re.sub(r" +", " ", theid)
1153 theid = re.sub(r"=[^,()]+\([^)]*?\)[^,)]*(,|\))", "\\1", theid)
1154 theid = re.sub(r"=\w*[^,)(]+(,|\))", "\\1", theid)
1155 theid = theid.replace("( ", "(").replace(" )", ")")
1156 name = unicode(sigobj.name)
1157 if theid not in self.state.document.ids:
1158 signode['names'].append(theid)
1159 signode['ids'].append(theid)
1160 signode['first'] = (not self.names)
1161 self.state.document.note_explicit_target(signode)
1163 #self.env.domaindata['ocv']['objects'].setdefault(name,
1164 #(self.env.docname, self.objtype, theid))
1165 self.env.domaindata['ocv']['objects'].setdefault(theid,
1166 (self.env.docname, self.objtype, theid))
1167 self.env.domaindata['ocv']['objects2'].setdefault(name,
1168 (self.env.docname, self.objtype, theid))
1170 indextext = self.get_index_text(name)
1172 self.indexnode['entries'].append(('single', indextext, theid, name))
1174 def before_content(self):
1175 lastname = self.names and self.names[-1]
1176 if lastname and not self.env.temp_data.get('ocv:parent'):
1177 assert isinstance(lastname, NamedDefExpr)
1178 self.env.temp_data['ocv:parent'] = lastname.name
1179 self.parentname_set = True
1181 self.parentname_set = False
1183 def after_content(self):
1184 if self.parentname_set:
1185 self.env.temp_data['ocv:parent'] = None
1187 def parse_definition(self, parser):
1188 raise NotImplementedError()
1190 def describe_signature(self, signode, arg):
1191 raise NotImplementedError()
1193 def handle_signature(self, sig, signode):
1194 parser = DefinitionParser(sig)
1196 rv = self.parse_definition(parser)
1198 except DefinitionError, e:
1199 self.env.warn(self.env.docname,
1200 e.description, self.lineno)
1202 self.describe_signature(signode, rv)
1204 parent = self.env.temp_data.get('ocv:parent')
1205 if parent is not None:
1207 rv.name = rv.name.prefix(parent)
1211 class OCVClassObject(OCVObject):
1212 object_annotation = "class "
1213 object_long_name = "class"
1215 def attach_modifiers(self, node, obj):
1216 if obj.visibility != 'public':
1217 node += addnodes.desc_annotation(obj.visibility,
1219 node += nodes.Text(' ')
1221 node += addnodes.desc_annotation('static', 'static')
1222 node += nodes.Text(' ')
1224 def get_index_text(self, name):
1225 return _('%s (C++ %s)') % (name, self.__class__.object_long_name)
1227 def parse_definition(self, parser):
1228 return parser.parse_class()
1230 def describe_signature(self, signode, cls):
1231 self.attach_modifiers(signode, cls)
1232 signode += addnodes.desc_annotation(self.__class__.object_annotation, self.__class__.object_annotation)
1233 self.attach_name(signode, cls.name)
1235 class OCVStructObject(OCVClassObject):
1236 object_annotation = "struct "
1237 object_long_name = "structure"
1239 class OCVTypeObject(OCVObject):
1241 def get_index_text(self, name):
1242 if self.objtype == 'type':
1243 return _('%s (C++ type)') % name
1246 def parse_definition(self, parser):
1247 return parser.parse_type_object()
1249 def describe_signature(self, signode, obj):
1250 self.attach_modifiers(signode, obj)
1251 signode += addnodes.desc_annotation('type ', 'type ')
1252 if obj.typename is not None:
1253 self.attach_type(signode, obj.typename)
1254 signode += nodes.Text(' ')
1255 self.attach_name(signode, obj.name)
1257 class OCVMemberObject(OCVObject):
1260 def get_index_text(self, name):
1261 if self.objtype == 'member':
1262 return _('%s (C++ member)') % name
1265 def parse_definition(self, parser):
1266 return parser.parse_member_object()
1268 def describe_signature(self, signode, obj):
1269 self.attach_modifiers(signode, obj)
1270 self.attach_type(signode, obj.typename)
1271 signode += nodes.Text(' ')
1272 self.attach_name(signode, obj.name)
1273 if obj.value is not None:
1274 signode += nodes.Text(u' = ' + obj.value)
1276 class OCVFunctionObject(OCVObject):
1278 def attach_function(self, node, func):
1279 owner, name = func.name.split_owner()
1280 if owner is not None:
1281 owner = unicode(owner) + '::'
1282 node += addnodes.desc_addname(owner, owner)
1284 # cast operator is special. in this case the return value
1286 if isinstance(name, CastOpDefExpr):
1287 node += addnodes.desc_name('operator', 'operator')
1288 node += nodes.Text(u' ')
1289 self.attach_type(node, name.typename)
1291 funcname = unicode(name)
1292 node += addnodes.desc_name(funcname, funcname)
1294 paramlist = addnodes.desc_parameterlist()
1295 for arg in func.signature:
1296 param = addnodes.desc_parameter('', '', noemph=True)
1297 if arg.type is not None:
1298 self.attach_type(param, arg.type)
1299 param += nodes.Text(u' ')
1300 #param += nodes.emphasis(unicode(arg.name), unicode(arg.name))
1301 param += nodes.strong(unicode(arg.name), unicode(arg.name))
1302 if arg.default is not None:
1303 def_ = u'=' + unicode(arg.default)
1304 #param += nodes.emphasis(def_, def_)
1305 param += nodes.Text(def_)
1310 node += addnodes.desc_addname(' const', ' const')
1311 if func.pure_virtual:
1312 node += addnodes.desc_addname(' = 0', ' = 0')
1314 def get_index_text(self, name):
1315 lname = self.__class__.langname
1316 if lname == "C" and name.startswith("cv"):
1318 return _('%s (%s function)') % (name, lname)
1320 def parse_definition(self, parser):
1321 return parser.parse_function()
1323 def describe_signature(self, signode, func):
1324 self.attach_modifiers(signode, func)
1326 signode += addnodes.desc_annotation('explicit', 'explicit')
1327 signode += nodes.Text(' ')
1328 # return value is None for things with a reverse return value
1329 # such as casting operator definitions or constructors
1331 if func.rv is not None:
1332 self.attach_type(signode, func.rv)
1333 signode += nodes.Text(u' ')
1334 self.attach_function(signode, func)
1337 class OCVCurrentNamespace(Directive):
1338 """This directive is just to tell Sphinx that we're documenting
1339 stuff in namespace foo.
1343 required_arguments = 1
1344 optional_arguments = 0
1345 final_argument_whitespace = True
1349 env = self.state.document.settings.env
1350 if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
1351 env.temp_data['ocv:prefix'] = None
1353 parser = DefinitionParser(self.arguments[0])
1355 prefix = parser.parse_type()
1357 except DefinitionError, e:
1358 self.env.warn(self.env.docname,
1359 e.description, self.lineno)
1361 env.temp_data['ocv:prefix'] = prefix
1365 class OCVXRefRole(XRefRole):
1367 def process_link(self, env, refnode, has_explicit_title, title, target):
1368 refnode['ocv:parent'] = env.temp_data.get('ocv:parent')
1369 if not has_explicit_title:
1370 target = target.lstrip('~') # only has a meaning for the title
1371 # if the first character is a tilde, don't display the module/class
1372 # parts of the contents
1373 if title[:1] == '~':
1375 dcolon = title.rfind('::')
1377 title = title[dcolon + 2:]
1378 return title, target
1381 class OCVCFunctionObject(OCVFunctionObject):
1384 class OCVJavaFunctionObject(OCVFunctionObject):
1388 class OCVDomain(Domain):
1389 """OpenCV C++ language domain."""
1393 'class': ObjType(l_('class'), 'class'),
1394 'struct': ObjType(l_('struct'), 'struct'),
1395 'function': ObjType(l_('function'), 'func', 'funcx'),
1396 'cfunction': ObjType(l_('cfunction'), 'cfunc', 'cfuncx'),
1397 'jfunction': ObjType(l_('jfunction'), 'jfunc', 'jfuncx'),
1398 'pyfunction': ObjType(l_('pyfunction'), 'pyfunc'),
1399 'pyoldfunction': ObjType(l_('pyoldfunction'), 'pyoldfunc'),
1400 'member': ObjType(l_('member'), 'member'),
1401 'type': ObjType(l_('type'), 'type')
1405 'class': OCVClassObject,
1406 'struct': OCVStructObject,
1407 'function': OCVFunctionObject,
1408 'cfunction': OCVCFunctionObject,
1409 'jfunction': OCVJavaFunctionObject,
1410 'pyfunction': OCVPyModulelevel,
1411 'pyoldfunction': OCVPyOldModulelevel,
1412 'member': OCVMemberObject,
1413 'type': OCVTypeObject,
1414 'namespace': OCVCurrentNamespace
1417 'class': OCVXRefRole(),
1418 'struct': OCVXRefRole(),
1419 'func' : OCVXRefRole(fix_parens=True),
1420 'funcx' : OCVXRefRole(),
1421 'cfunc' : OCVXRefRole(fix_parens=True),
1422 'cfuncx' : OCVXRefRole(),
1423 'jfunc' : OCVXRefRole(fix_parens=True),
1424 'jfuncx' : OCVXRefRole(),
1425 'pyfunc' : OCVPyXRefRole(),
1426 'pyoldfunc' : OCVPyXRefRole(),
1427 'member': OCVXRefRole(),
1428 'type': OCVXRefRole()
1431 'objects': {}, # fullname -> docname, objtype
1434 def __init__(self, env):
1435 Domain.__init__(self, env)
1436 self.data['objects2'] = {}
1438 def clear_doc(self, docname):
1439 for fullname, (fn, _, _) in self.data['objects'].items():
1441 del self.data['objects'][fullname]
1443 def resolve_xref(self, env, fromdocname, builder,
1444 typ, target, node, contnode):
1445 def _create_refnode(expr):
1446 name = unicode(expr)
1447 if "type" in self.objtypes_for_role(typ):
1449 if "cfunction" in self.objtypes_for_role(typ):
1450 if not name.startswith(u'cv'):
1452 dict = self.data['objects']
1453 if name not in dict:
1454 dict = self.data['objects2']
1455 if name not in dict:
1456 refdoc = node.get('refdoc', fromdocname)
1457 env.warn(refdoc, 'unresolved reference: %r - %r' % (target, typ), node.line)
1460 if obj[1] not in self.objtypes_for_role(typ):
1463 if "class" in self.objtypes_for_role(typ):
1464 title = u"class " + title
1465 elif "struct" in self.objtypes_for_role(typ):
1466 title = u"struct " + title
1467 return make_refnode(builder, fromdocname, obj[0], obj[2],
1470 parser = DefinitionParser(target)
1472 expr = parser.parse_type().get_name()
1474 if not parser.eof or expr is None:
1475 raise DefinitionError('')
1476 except DefinitionError:
1477 refdoc = node.get('refdoc', fromdocname)
1478 env.warn(refdoc, 'unparseable C++ definition: %r' % target,
1482 parent = node['ocv:parent']
1484 rv = _create_refnode(expr)
1485 if rv is not None or parent is None:
1487 parent = parent.get_name()
1489 rv = _create_refnode(expr.prefix(parent))
1493 parent, name = parent.split_owner()
1494 return _create_refnode(expr.prefix(parent))
1496 def get_objects(self):
1497 for refname, (docname, type, theid) in self.data['objects'].iteritems():
1498 yield (refname, refname, type, docname, refname, 1)
1500 def get_type_name(self, type, primary=False):
1502 Return full name for given ObjType.
1508 'class': _('C++ class'),
1509 'struct': _('C/C++ struct'),
1510 'function': _('C++ function'),
1511 'cfunction': _('C function'),
1512 'jfunction': _('Java method'),
1513 'pyfunction': _('Python function'),
1514 'pyoldfunction': _('Legacy Python function'),
1515 'member': _('C++ member'),
1516 'type': _('C/C++ type'),
1517 'namespace': _('C++ namespace'),
1518 }.get(type.lname, _('%s %s') % (self.label, type.lname))
1521 app.add_domain(OCVDomain)