2 # -*- coding: utf-8 -*-
4 ocv domain, a modified copy of sphinx.domains.cpp + shpinx.domains.python.
5 The original copyright is below
6 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
8 The OpenCV C/C++/Python/Java/... language domain.
10 :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
11 :license: BSD, see LICENSE for details.
15 from copy import deepcopy
17 from docutils import nodes
18 from docutils.parsers.rst import directives
20 from sphinx import addnodes
21 from sphinx.roles import XRefRole
22 from sphinx.locale import l_, _
23 from sphinx.domains import Domain, ObjType
24 from sphinx.directives import ObjectDescription
25 from sphinx.util.nodes import make_refnode
26 from sphinx.util.compat import Directive
27 from sphinx.util.docfields import Field, GroupedField, TypedField
29 ########################### Python Part ###########################
31 # REs for Python signatures
32 py_sig_re = re.compile(
33 r'''^ ([\w.]*\.)? # class name(s)
34 (\w+) \s* # thing name
35 (?: \((.*)\) # optional: arguments
36 (?:\s* -> \s* (.*))? # return annotation
37 )? $ # and nothing more
41 def _pseudo_parse_arglist(signode, arglist):
42 """"Parse" a list of arguments separated by commas.
44 Arguments can have "optional" annotations given by enclosing them in
45 brackets. Currently, this will split at any comma, even if it's inside a
46 string literal (e.g. default argument value).
48 paramlist = addnodes.desc_parameterlist()
51 for argument in arglist.split(','):
52 argument = argument.strip()
53 ends_open = ends_close = 0
54 while argument.startswith('['):
55 stack.append(addnodes.desc_optional())
56 stack[-2] += stack[-1]
57 argument = argument[1:].strip()
58 while argument.startswith(']'):
60 argument = argument[1:].strip()
61 while argument.endswith(']'):
63 argument = argument[:-1].strip()
64 while argument.endswith('['):
66 argument = argument[:-1].strip()
68 stack[-1] += addnodes.desc_parameter(argument, argument, noemph=True)
70 stack.append(addnodes.desc_optional())
71 stack[-2] += stack[-1]
79 # if there are too few or too many elements on the stack, just give up
80 # and treat the whole argument list as one argument, discarding the
81 # already partially populated paramlist node
82 signode += addnodes.desc_parameterlist()
83 signode[-1] += addnodes.desc_parameter(arglist, arglist)
88 class OCVPyObject(ObjectDescription):
90 Description of a general Python object.
93 'noindex': directives.flag,
94 'module': directives.unchanged,
98 TypedField('parameter', label=l_('Parameters'),
99 names=('param', 'parameter', 'arg', 'argument',
100 'keyword', 'kwarg', 'kwparam'),
101 typerolename='obj', typenames=('paramtype', 'type'),
103 TypedField('variable', label=l_('Variables'), rolename='obj',
104 names=('var', 'ivar', 'cvar'),
105 typerolename='obj', typenames=('vartype',),
107 GroupedField('exceptions', label=l_('Raises'), rolename='exc',
108 names=('raises', 'raise', 'exception', 'except'),
110 Field('returnvalue', label=l_('Returns'), has_arg=False,
111 names=('returns', 'return')),
112 Field('returntype', label=l_('Return type'), has_arg=False,
116 def get_signature_prefix(self, sig):
118 May return a prefix to put before the object name in the signature.
122 def needs_arglist(self):
124 May return true if an empty argument list is to be generated even if
125 the document contains none.
129 def handle_signature(self, sig, signode):
131 Transform a Python signature into RST nodes.
132 Returns (fully qualified name of the thing, classname if any).
134 If inside a class, the current class name is handled intelligently:
135 * it is stripped from the displayed name if present
136 * it is added to the full name (return value) if not present
138 signode += nodes.strong("Python:", "Python:")
139 signode += addnodes.desc_name(" ", " ")
140 m = py_sig_re.match(sig)
143 name_prefix, name, arglist, retann = m.groups()
145 # determine module and class name (if applicable), as well as full name
146 modname = self.options.get(
147 'module', self.env.temp_data.get('py:module'))
148 classname = self.env.temp_data.get('py:class')
151 if name_prefix and name_prefix.startswith(classname):
152 fullname = name_prefix + name
153 # class name is given again in the signature
154 name_prefix = name_prefix[len(classname):].lstrip('.')
156 # class name is given in the signature, but different
158 fullname = classname + '.' + name_prefix + name
160 # class name is not given in the signature
161 fullname = classname + '.' + name
165 classname = name_prefix.rstrip('.')
166 fullname = name_prefix + name
171 signode['module'] = modname
172 signode['class'] = classname
173 signode['fullname'] = fullname
175 sig_prefix = self.get_signature_prefix(sig)
177 signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
180 signode += addnodes.desc_addname(name_prefix, name_prefix)
181 # exceptions are a special case, since they are documented in the
182 # 'exceptions' module.
183 elif add_module and self.env.config.add_module_names:
184 modname = self.options.get(
185 'module', self.env.temp_data.get('py:module'))
186 if modname and modname != 'exceptions':
187 nodetext = modname + '.'
188 signode += addnodes.desc_addname(nodetext, nodetext)
190 signode += addnodes.desc_name(name, name)
192 if self.needs_arglist():
193 # for callables, add an empty parameter list
194 signode += addnodes.desc_parameterlist()
196 signode += addnodes.desc_returns(retann, retann)
197 return fullname, name_prefix
198 _pseudo_parse_arglist(signode, arglist)
200 signode += addnodes.desc_returns(retann, retann)
201 return fullname, name_prefix
203 def get_index_text(self, modname, name):
205 Return the text for the index entry of the object.
207 raise NotImplementedError('must be implemented in subclasses')
209 def add_target_and_index(self, name_cls, sig, signode):
210 modname = self.options.get(
211 'module', self.env.temp_data.get('py:module'))
212 fullname = (modname and modname + '.' or '') + name_cls[0]
214 if fullname not in self.state.document.ids:
215 signode['names'].append(fullname)
216 signode['ids'].append(fullname)
217 signode['first'] = (not self.names)
218 self.state.document.note_explicit_target(signode)
219 objects = self.env.domaindata['ocv']['objects']
220 if fullname in objects:
223 'duplicate object description of %s, ' % fullname +
224 'other instance in ' +
225 self.env.doc2path(objects[fullname][0]) +
226 ', use :noindex: for one of them',
228 objects.setdefault(fullname, (self.env.docname, self.objtype, name_cls[0]))
230 indextext = self.get_index_text(modname, name_cls)
232 self.indexnode['entries'].append(('single', indextext,
235 def before_content(self):
236 # needed for automatic qualification of members (reset in subclasses)
237 self.clsname_set = False
239 def after_content(self):
241 self.env.temp_data['py:class'] = None
243 class OCVPyModulelevel(OCVPyObject):
245 Description of an object on module level (functions, data).
247 directive_prefix = 'py'
249 def needs_arglist(self):
250 return self.objtype == self.__class__.directive_prefix + 'function'
252 def get_index_text(self, modname, name_cls):
253 if self.objtype == self.__class__.directive_prefix + 'function':
256 if not fname.startswith("cv") and not fname.startswith("cv2"):
257 return _('%s() (Python function)') % fname
258 pos = fname.find(".")
259 modname = fname[:pos]
260 fname = fname[pos+1:]
261 return _('%s() (Python function in %s)') % (fname, modname)
262 return _('%s() (Python function in %s)') % (name_cls[0], modname)
263 elif self.objtype == 'pydata':
265 return _('%s (Python variable)') % name_cls[0]
266 return _('%s (in module %s)') % (name_cls[0], modname)
270 class OCVPyXRefRole(XRefRole):
271 def process_link(self, env, refnode, has_explicit_title, title, target):
272 refnode['ocv:module'] = env.temp_data.get('ocv:module')
273 refnode['ocv:class'] = env.temp_data.get('ocv:class')
274 if not has_explicit_title:
275 title = title.lstrip('.') # only has a meaning for the target
276 target = target.lstrip('~') # only has a meaning for the title
277 # if the first character is a tilde, don't display the module/class
278 # parts of the contents
279 if title[0:1] == '~':
281 dot = title.rfind('.')
283 title = title[dot+1:]
284 # if the first character is a dot, search more specific namespaces first
285 # else search builtins first
286 if target[0:1] == '.':
288 refnode['refspecific'] = True
292 ########################### C/C++/Java Part ###########################
294 _identifier_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b)')
295 _argument_name_re = re.compile(r'(~?\b[a-zA-Z_][a-zA-Z0-9_]*\b(?:\[\d*\])?|\.\.\.)')
296 _whitespace_re = re.compile(r'\s+(?u)')
297 _string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
298 r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
299 _visibility_re = re.compile(r'\b(public|private|protected)\b')
300 _operator_re = re.compile(r'''(?x)
313 'unsigned char': 'C',
319 'unsigned long': 'L',
323 'std::ostream': 'os',
324 'std::istream': 'is',
325 'std::iostream': 'ios',
328 'operator[]': 'subscript-operator',
329 'operator()': 'call-operator',
330 'operator!': 'not-operator',
331 'operator<': 'lt-operator',
332 'operator<=': 'lte-operator',
333 'operator>': 'gt-operator',
334 'operator>=': 'gte-operator',
335 'operator=': 'assign-operator',
336 'operator/': 'div-operator',
337 'operator*': 'mul-operator',
338 'operator%': 'mod-operator',
339 'operator+': 'add-operator',
340 'operator-': 'sub-operator',
341 'operator|': 'or-operator',
342 'operator&': 'and-operator',
343 'operator^': 'xor-operator',
344 'operator&&': 'sand-operator',
345 'operator||': 'sor-operator',
346 'operator==': 'eq-operator',
347 'operator!=': 'neq-operator',
348 'operator<<': 'lshift-operator',
349 'operator>>': 'rshift-operator',
350 'operator-=': 'sub-assign-operator',
351 'operator+=': 'add-assign-operator',
352 'operator*-': 'mul-assign-operator',
353 'operator/=': 'div-assign-operator',
354 'operator%=': 'mod-assign-operator',
355 'operator&=': 'and-assign-operator',
356 'operator|=': 'or-assign-operator',
357 'operator<<=': 'lshift-assign-operator',
358 'operator>>=': 'rshift-assign-operator',
359 'operator^=': 'xor-assign-operator',
360 'operator,': 'comma-operator',
361 'operator->': 'pointer-operator',
362 'operator->*': 'pointer-by-pointer-operator',
363 'operator~': 'inv-operator',
364 'operator++': 'inc-operator',
365 'operator--': 'dec-operator',
366 'operator new': 'new-operator',
367 'operator new[]': 'new-array-operator',
368 'operator delete': 'delete-operator',
369 'operator delete[]': 'delete-array-operator'
373 class DefinitionError(Exception):
375 def __init__(self, description):
376 self.description = description
378 def __unicode__(self):
379 return self.description
382 return unicode(self.encode('utf-8'))
385 class DefExpr(object):
387 def __unicode__(self):
388 raise NotImplementedError()
390 def __eq__(self, other):
391 if type(self) is not type(other):
394 for key, value in self.__dict__.iteritems():
395 if value != getattr(other, value):
397 except AttributeError:
401 def __ne__(self, other):
402 return not self.__eq__(other)
405 """Close a definition expression node"""
406 return deepcopy(self)
409 """Returns the id for the node"""
413 """Returns the name. Returns either `None` or a node with
414 a name you might call :meth:`split_owner` on.
418 def split_owner(self):
419 """Nodes returned by :meth:`get_name` can split off their
420 owning parent. This function returns the owner and the
421 name as a tuple of two items. If a node does not support
422 it, it returns None as owner and self as name.
426 def prefix(self, prefix):
427 """Prefixes a name node (a node returned by :meth:`get_name`)."""
428 raise NotImplementedError()
431 return unicode(self).encode('utf-8')
434 return '<%s %s>' % (self.__class__.__name__, self)
437 class PrimaryDefExpr(DefExpr):
442 def prefix(self, prefix):
443 if isinstance(prefix, PathDefExpr):
444 prefix = prefix.clone()
445 prefix.path.append(self)
447 return PathDefExpr([prefix, self])
450 class NameDefExpr(PrimaryDefExpr):
452 def __init__(self, name):
456 name = _id_shortwords.get(self.name)
459 return self.name.replace(u' ', u'-')
461 def __unicode__(self):
462 return unicode(self.name)
465 class PathDefExpr(PrimaryDefExpr):
467 def __init__(self, parts):
471 rv = u'::'.join(x.get_id() for x in self.path)
472 return _id_shortwords.get(rv, rv)
474 def split_owner(self):
475 if len(self.path) > 1:
476 return PathDefExpr(self.path[:-1]), self.path[-1]
479 def prefix(self, prefix):
480 if isinstance(prefix, PathDefExpr):
481 prefix = prefix.clone()
482 prefix.path.extend(self.path)
484 return PathDefExpr([prefix] + self.path)
486 def __unicode__(self):
487 return u'::'.join(map(unicode, self.path))
490 class TemplateDefExpr(PrimaryDefExpr):
492 def __init__(self, typename, args):
493 self.typename = typename
496 def split_owner(self):
497 owner, typename = self.typename.split_owner()
498 return owner, TemplateDefExpr(typename, self.args)
501 return u'%s:%s:' % (self.typename.get_id(),
502 u'.'.join(x.get_id() for x in self.args))
504 def __unicode__(self):
505 return u'%s<%s>' % (self.typename, u', '.join(map(unicode, self.args)))
508 class WrappingDefExpr(DefExpr):
510 def __init__(self, typename):
511 self.typename = typename
514 return self.typename.get_name()
517 class ModifierDefExpr(WrappingDefExpr):
519 def __init__(self, typename, modifiers):
520 WrappingDefExpr.__init__(self, typename)
521 self.modifiers = modifiers
524 pieces = [_id_shortwords.get(unicode(x), unicode(x))
525 for x in self.modifiers]
526 pieces.append(self.typename.get_id())
527 return u'-'.join(pieces)
529 def __unicode__(self):
530 return u' '.join(map(unicode, list(self.modifiers) + [self.typename]))
533 class PtrDefExpr(WrappingDefExpr):
536 return self.typename.get_id() + u'P'
538 def __unicode__(self):
539 return u'%s*' % self.typename
542 class RefDefExpr(WrappingDefExpr):
545 return self.typename.get_id() + u'R'
547 def __unicode__(self):
548 return u'%s&' % self.typename
551 class ConstDefExpr(WrappingDefExpr):
553 def __init__(self, typename, prefix=False):
554 WrappingDefExpr.__init__(self, typename)
558 return self.typename.get_id() + u'C'
560 def __unicode__(self):
561 return (self.prefix and u'const %s' or u'%s const') % self.typename
563 class ConstTemplateDefExpr(WrappingDefExpr):
565 def __init__(self, typename, prefix=False):
566 WrappingDefExpr.__init__(self, typename)
570 return self.typename.get_id() + u'C'
572 def __unicode__(self):
573 return (self.prefix and u'const %s' or u'%s const') % self.typename
576 class CastOpDefExpr(PrimaryDefExpr):
578 def __init__(self, typename):
579 self.typename = typename
582 return u'castto-%s-operator' % self.typename.get_id()
584 def __unicode__(self):
585 return u'operator %s' % self.typename
588 class ArgumentDefExpr(DefExpr):
590 def __init__(self, type, name, default=None):
593 self.default = default
596 return self.name.get_name()
599 if self.type is None:
601 return self.type.get_id()
603 def __unicode__(self):
604 return (u'%s %s' % (self.type or u'', self.name or u'')).strip() + \
605 (self.default is not None and u'=%s' % self.default or u'')
608 class NamedDefExpr(DefExpr):
610 def __init__(self, name, visibility, static):
612 self.visibility = visibility
616 return self.name.get_name()
618 def get_modifiers(self):
620 if self.visibility != 'public':
621 rv.append(self.visibility)
627 class TypeObjDefExpr(NamedDefExpr):
629 def __init__(self, name, visibility, static, typename):
630 NamedDefExpr.__init__(self, name, visibility, static)
631 self.typename = typename
634 if self.typename is None:
635 return self.name.get_id()
636 return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
638 def __unicode__(self):
639 buf = self.get_modifiers()
640 if self.typename is None:
641 buf.append(unicode(self.name))
643 buf.extend(map(unicode, (self.typename, self.name)))
644 return u' '.join(buf)
647 class MemberObjDefExpr(NamedDefExpr):
649 def __init__(self, name, visibility, static, typename, value):
650 NamedDefExpr.__init__(self, name, visibility, static)
651 self.typename = typename
655 return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
657 def __unicode__(self):
658 buf = self.get_modifiers()
659 buf.append(u'%s %s' % (self.typename, self.name))
660 if self.value is not None:
661 buf.append(u'= %s' % self.value)
662 return u' '.join(buf)
665 class FuncDefExpr(NamedDefExpr):
667 def __init__(self, name, visibility, static, explicit, rv,
668 signature, const, pure_virtual, virtual):
669 NamedDefExpr.__init__(self, name, visibility, static)
671 self.signature = signature
672 self.explicit = explicit
674 self.pure_virtual = pure_virtual
675 self.virtual = virtual
680 self.signature and u'__' +
681 u'.'.join(x.get_id() for x in self.signature) or u'',
682 self.const and u'C' or u''
685 def __unicode__(self):
686 buf = self.get_modifiers()
688 buf.append(u'explicit')
690 buf.append(u'virtual')
691 if self.rv is not None:
692 buf.append(unicode(self.rv))
693 buf.append(u'%s(%s)' % (self.name, u', '.join(
694 map(unicode, self.signature))))
697 if self.pure_virtual:
699 return u' '.join(buf)
702 class ClassDefExpr(NamedDefExpr):
704 def __init__(self, name, visibility, static, parents = None):
705 NamedDefExpr.__init__(self, name, visibility, static)
706 self.parents = parents
709 return self.name.get_id()
711 def __unicode__(self):
712 buf = self.get_modifiers()
713 buf.append(unicode(self.name))
714 return u' '.join(buf)
717 class DefinitionParser(object):
719 # mapping of valid type modifiers. if the set is None it means
720 # the modifier can prefix all types, otherwise only the types
721 # (actually more keywords) in the set. Also check
722 # _guess_typename when changing this.
729 'unsigned': set(('char', 'short', 'int', 'long')),
730 'signed': set(('char', 'short', 'int', 'long')),
731 'short': set(('int',)),
732 'long': set(('int', 'long', 'double'))
735 def __init__(self, definition):
736 self.definition = definition.strip()
738 self.end = len(self.definition)
739 self.last_match = None
740 self._previous_state = (0, None)
743 raise DefinitionError('Invalid definition: %s [error at %d]\n %s' %
744 (msg, self.pos, self.definition))
746 def match(self, regex):
747 match = regex.match(self.definition, self.pos)
748 if match is not None:
749 self._previous_state = (self.pos, self.last_match)
750 self.pos = match.end()
751 self.last_match = match
756 self.pos, self.last_match = self._previous_state
758 def skip_string(self, string):
760 if self.definition[self.pos:self.pos + strlen] == string:
765 def skip_word(self, word):
766 return self.match(re.compile(r'\b%s\b' % re.escape(word)))
769 return self.match(_whitespace_re)
773 return self.pos >= self.end
776 def current_char(self):
778 return self.definition[self.pos]
783 def matched_text(self):
784 if self.last_match is not None:
785 return self.last_match.group()
787 def _parse_operator(self):
789 # thank god, a regular operator definition
790 if self.match(_operator_re):
791 return NameDefExpr('operator' +
792 _whitespace_re.sub('', self.matched_text))
793 # new/delete operator?
794 for allocop in 'new', 'delete':
795 if not self.skip_word(allocop):
798 if self.skip_string('['):
800 if not self.skip_string(']'):
801 self.fail('expected "]" for ' + allocop)
803 return NameDefExpr('operator ' + allocop)
805 # oh well, looks like a cast operator definition.
806 # In that case, eat another type.
807 type = self._parse_type()
808 return CastOpDefExpr(type)
810 def _parse_name(self):
811 if not self.match(_argument_name_re):
812 self.fail('expected name')
813 identifier = self.matched_text
815 # strictly speaking, operators are not regular identifiers
816 # but because operator is a keyword, it might not be used
817 # for variable names anyways, so we can safely parse the
818 # operator here as identifier
819 if identifier == 'operator':
820 return self._parse_operator()
822 return NameDefExpr(identifier)
824 def _guess_typename(self, path):
827 # for the long type, we don't want the int in there
829 path = [x for x in path if x != 'int']
833 if path[-1] in ('int', 'char'):
834 return path[:-1], path[-1]
837 def _attach_crefptr(self, expr, is_const=False):
839 expr = ConstDefExpr(expr, prefix=True)
842 if self.skip_word('const'):
843 expr = ConstDefExpr(expr)
844 elif self.skip_string('*'):
845 expr = PtrDefExpr(expr)
846 elif self.skip_string('&'):
847 expr = RefDefExpr(expr)
851 def _peek_const(self, path):
858 def _parse_builtin(self, modifier):
860 following = self._modifiers[modifier]
863 if not self.match(_identifier_re):
865 identifier = self.matched_text
866 if identifier in following:
867 path.append(identifier)
868 following = self._modifiers[modifier]
874 is_const = self._peek_const(path)
875 modifiers, typename = self._guess_typename(path)
876 rv = ModifierDefExpr(NameDefExpr(typename), modifiers)
877 return self._attach_crefptr(rv, is_const)
879 def _parse_type_expr(self):
880 typename = self._parse_name()
881 if typename and self.skip_string('['):
883 if self.match(re.compile(r'\d*')):
884 typename.name += self.last_match.group(0)
886 if not self.skip_string(']'):
887 self.fail('expected type')
889 if not self.skip_string('<'):
895 if self.skip_string('>'):
898 if not self.skip_string(','):
899 self.fail('"," or ">" in template expected')
901 args.append(self._parse_type(True))
902 return TemplateDefExpr(typename, args)
904 def _parse_type(self, in_template=False):
909 if self.match(re.compile(r'template\w*<([^>]*)>')):
910 args = self.last_match.group(1).split(',')
911 args = [a.strip() for a in args]
912 modifiers.append(TemplateDefExpr('template', args))
914 # if there is a leading :: or not, we don't care because we
915 # treat them exactly the same. Buf *if* there is one, we
916 # don't have to check for type modifiers
917 if not self.skip_string('::'):
919 while self.match(_identifier_re):
920 modifier = self.matched_text
921 if modifier in self._modifiers:
922 following = self._modifiers[modifier]
923 # if the set is not none, there is a limited set
924 # of types that might follow. It is technically
925 # impossible for a template to follow, so what
926 # we do is go to a different function that just
928 if following is not None:
929 return self._parse_builtin(modifier)
930 modifiers.append(modifier)
937 if (in_template and self.current_char in ',>') or \
938 (result and not self.skip_string('::')) or \
941 result.append(self._parse_type_expr())
944 self.fail('expected type')
948 rv = PathDefExpr(result)
949 is_const = self._peek_const(modifiers)
951 rv = ConstDefExpr(rv, prefix=True)
953 rv = ModifierDefExpr(rv, modifiers)
954 return self._attach_crefptr(rv, False)
956 def _parse_default_expr(self):
958 if self.match(_string_re):
959 return self.matched_text
960 paren_stack_depth = 0
961 max_pos = len(self.definition)
964 idx0 = self.definition.find('(', self.pos)
965 idx1 = self.definition.find(',', self.pos)
966 idx2 = self.definition.find(')', self.pos)
973 idx = min(idx0, idx1, idx2)
975 self.fail('unexpected end in default expression')
977 paren_stack_depth += 1
979 paren_stack_depth -= 1
980 if paren_stack_depth < 0:
982 elif paren_stack_depth == 0:
986 rv = self.definition[rv_start:idx]
990 def _parse_signature(self):
991 if r'CvStatModel::train' in self.definition:
992 # hack to skip parsing of problematic definition
994 return [ArgumentDefExpr("const Mat&", "train_data", None), ArgumentDefExpr(None, self.definition[self.definition.find("["):-1], None)], False, True
997 if not self.skip_string('('):
998 self.fail('expected parentheses for function')
1004 self.fail('missing closing parentheses')
1005 if self.skip_string(')'):
1008 if not self.skip_string(','):
1009 self.fail('expected comma between arguments')
1012 argtype = self._parse_type()
1014 if unicode(argtype) == u"...":
1015 if not self.skip_string(')'):
1016 self.fail("var arg must be the last argument")
1017 args.append(ArgumentDefExpr(None, argtype, None))
1019 argname = default = None
1020 if self.skip_string('='):
1022 default = self._parse_default_expr()
1023 elif self.current_char not in ',)':
1024 argname = self._parse_name()
1026 if self.skip_string('='):
1027 default = self._parse_default_expr()
1029 args.append(ArgumentDefExpr(argtype, argname, default))
1031 const = self.skip_word('const')
1034 if self.skip_string('='):
1036 if not (self.skip_string('0') or \
1037 self.skip_word('NULL') or \
1038 self.skip_word('nullptr')):
1039 self.fail('pure virtual functions must be defined with '
1040 'either 0, NULL or nullptr, other macros are '
1044 pure_virtual = False
1045 return args, const, pure_virtual
1047 def _parse_visibility_static(self):
1048 visibility = 'public'
1049 if self.match(_visibility_re):
1050 visibility = self.matched_text
1051 static = self.skip_word('static')
1052 return visibility, static
1054 def parse_type(self):
1055 return self._parse_type()
1057 def parse_type_object(self):
1058 visibility, static = self._parse_visibility_static()
1059 typename = self._parse_type()
1062 name = self._parse_type()
1066 return TypeObjDefExpr(name, visibility, static, typename)
1068 def parse_member_object(self):
1069 visibility, static = self._parse_visibility_static()
1070 typename = self._parse_type()
1071 name = self._parse_type()
1073 if self.skip_string('='):
1074 value = self.read_rest().strip()
1077 return MemberObjDefExpr(name, visibility, static, typename, value)
1079 def parse_enum_member_object(self):
1080 visibility, static = self._parse_visibility_static()
1082 name = self._parse_type()
1084 if self.skip_string('='):
1085 value = self.read_rest().strip()
1088 return MemberObjDefExpr(name, visibility, static, typename, value)
1090 def parse_function(self):
1091 visibility, static = self._parse_visibility_static()
1092 if self.skip_word('explicit'):
1097 if self.skip_word('virtual'):
1102 rv = self._parse_type()
1104 # some things just don't have return values
1105 if self.current_char == '(':
1109 name = self._parse_type()
1110 return FuncDefExpr(name, visibility, static, explicit, rv,
1111 *self._parse_signature(), virtual = virtual)
1113 def parse_class(self):
1114 visibility, static = self._parse_visibility_static()
1115 typename = self._parse_type()
1119 if self.skip_string(':'):
1122 classname_pos = self.pos
1123 pvisibility, pstatic = self._parse_visibility_static()
1125 self.fail('unsepected static keyword, got %r' %
1126 self.definition[self.classname_pos:])
1127 parents.append(ClassDefExpr(self._parse_type(), pvisibility, pstatic))
1128 if not self.skip_string(','):
1130 return ClassDefExpr(typename, visibility, static, parents)
1132 def read_rest(self):
1133 rv = self.definition[self.pos:]
1137 def assert_end(self):
1140 self.fail('expected end of definition, got %r' %
1141 self.definition[self.pos:])
1144 class OCVObject(ObjectDescription):
1145 """Description of a C++ language object."""
1151 TypedField('parameter', label=l_('Parameters'),
1152 names=('param', 'parameter', 'arg', 'argument'),
1153 typerolename='type', typenames=('type',)),
1154 Field('returnvalue', label=l_('Returns'), has_arg=False,
1155 names=('returns', 'return')),
1156 Field('returntype', label=l_('Return type'), has_arg=False,
1160 def attach_name(self, node, name):
1161 owner, name = name.split_owner()
1162 varname = unicode(name)
1163 if owner is not None:
1164 owner = unicode(owner) + '::'
1165 node += addnodes.desc_addname(owner, owner)
1166 node += addnodes.desc_name(varname, varname)
1168 def attach_type(self, node, type):
1170 text = unicode(type)
1171 pnode = addnodes.pending_xref(
1172 '', refdomain='ocv', reftype='type',
1173 reftarget=text, modname=None, classname=None)
1174 pnode['ocv:parent'] = self.env.temp_data.get('ocv:parent')
1175 pnode += nodes.Text(text)
1178 def attach_modifiers(self, node, obj):
1179 if not self.__class__.ismember:
1180 lname = self.__class__.langname
1181 node += nodes.strong(lname + ":", lname + ":")
1182 node += addnodes.desc_name(" ", " ")
1184 if obj.visibility != 'public':
1185 node += addnodes.desc_annotation(obj.visibility,
1187 node += nodes.Text(' ')
1189 node += addnodes.desc_annotation('static', 'static')
1190 node += nodes.Text(' ')
1192 def add_target_and_index(self, sigobj, sig, signode):
1193 theid = sig#obj.get_id()
1194 theid = re.sub(r" +", " ", theid)
1195 if self.objtype == 'emember':
1196 theid = re.sub(r" ?=.*", "", theid)
1197 theid = re.sub(r"=[^,()]+\([^)]*?\)[^,)]*(,|\))", "\\1", theid)
1198 theid = re.sub(r"=\w*[^,)(]+(,|\))", "\\1", theid)
1199 theid = theid.replace("( ", "(").replace(" )", ")")
1200 name = unicode(sigobj.name)
1201 if theid not in self.state.document.ids:
1202 signode['names'].append(theid)
1203 signode['ids'].append(theid)
1204 signode['first'] = (not self.names)
1205 self.state.document.note_explicit_target(signode)
1207 #self.env.domaindata['ocv']['objects'].setdefault(name,
1208 #(self.env.docname, self.objtype, theid))
1209 self.env.domaindata['ocv']['objects'].setdefault(theid,
1210 (self.env.docname, self.objtype, theid))
1211 self.env.domaindata['ocv']['objects2'].setdefault(name,
1212 (self.env.docname, self.objtype, theid))
1214 indextext = self.get_index_text(name)
1216 self.indexnode['entries'].append(('single', indextext, theid, name))
1218 def before_content(self):
1219 lastname = self.names and self.names[-1]
1220 if lastname and not self.env.temp_data.get('ocv:parent'):
1221 assert isinstance(lastname, NamedDefExpr)
1222 self.env.temp_data['ocv:parent'] = lastname.name
1223 self.parentname_set = True
1225 self.parentname_set = False
1227 def after_content(self):
1228 if self.parentname_set:
1229 self.env.temp_data['ocv:parent'] = None
1231 def parse_definition(self, parser):
1232 raise NotImplementedError()
1234 def describe_signature(self, signode, arg):
1235 raise NotImplementedError()
1237 def handle_signature(self, sig, signode):
1238 parser = DefinitionParser(sig)
1240 rv = self.parse_definition(parser)
1242 except DefinitionError, e:
1243 self.env.warn(self.env.docname,
1244 e.description, self.lineno)
1246 self.describe_signature(signode, rv)
1248 parent = self.env.temp_data.get('ocv:parent')
1249 if parent is not None:
1251 rv.name = rv.name.prefix(parent)
1255 class OCVClassObject(OCVObject):
1256 object_annotation = "class "
1257 object_long_name = "class"
1259 def attach_modifiers(self, node, obj, skip_visibility = 'public'):
1260 if obj.visibility != skip_visibility:
1261 node += addnodes.desc_annotation(obj.visibility,
1263 node += nodes.Text(' ')
1265 node += addnodes.desc_annotation('static', 'static')
1266 node += nodes.Text(' ')
1268 def get_index_text(self, name):
1269 return _('%s (C++ %s)') % (name, self.__class__.object_long_name)
1271 def parse_definition(self, parser):
1272 return parser.parse_class()
1274 def describe_signature(self, signode, cls):
1275 self.attach_modifiers(signode, cls)
1276 signode += addnodes.desc_annotation(self.__class__.object_annotation, self.__class__.object_annotation)
1277 self.attach_name(signode, cls.name)
1279 for p in cls.parents:
1281 signode += nodes.Text(' : ')
1282 first_parent = False
1284 signode += nodes.Text(', ')
1285 self.attach_modifiers(signode, p, None)
1286 self.attach_name(signode, p.name)
1288 class OCVStructObject(OCVClassObject):
1289 object_annotation = "struct "
1290 object_long_name = "structure"
1292 class OCVTypeObject(OCVObject):
1294 def get_index_text(self, name):
1295 if self.objtype == 'type':
1296 return _('%s (C++ type)') % name
1299 def parse_definition(self, parser):
1300 return parser.parse_type_object()
1302 def describe_signature(self, signode, obj):
1303 self.attach_modifiers(signode, obj)
1304 signode += addnodes.desc_annotation('type ', 'type ')
1305 if obj.typename is not None:
1306 self.attach_type(signode, obj.typename)
1307 signode += nodes.Text(' ')
1308 self.attach_name(signode, obj.name)
1310 class OCVEnumObject(OCVObject):
1312 def get_index_text(self, name):
1313 if self.objtype == 'enum':
1314 return _('%s (enum)') % name
1317 def parse_definition(self, parser):
1318 return parser.parse_type_object()
1320 def describe_signature(self, signode, obj):
1321 self.attach_modifiers(signode, obj)
1322 signode += addnodes.desc_annotation('enum ', 'enum ')
1323 if obj.typename is not None:
1324 self.attach_type(signode, obj.typename)
1325 signode += nodes.Text(' ')
1326 self.attach_name(signode, obj.name)
1329 class OCVMemberObject(OCVObject):
1332 def get_index_text(self, name):
1333 if self.objtype == 'member':
1334 return _('%s (C++ member)') % name
1337 def parse_definition(self, parser):
1338 parent_class = self.env.temp_data.get('ocv:parent')
1339 if parent_class is None:
1340 parser.fail("missing parent structure/class")
1341 return parser.parse_member_object()
1343 def describe_signature(self, signode, obj):
1344 self.attach_modifiers(signode, obj)
1346 self.attach_type(signode, obj.typename)
1347 signode += nodes.Text(' ')
1348 self.attach_name(signode, obj.name)
1349 if obj.value is not None:
1350 signode += nodes.Text(u' = ' + obj.value)
1352 class OCVEnumMemberObject(OCVMemberObject):
1353 def parse_definition(self, parser):
1354 # parent_class = self.env.temp_data.get('ocv:parent')
1355 # if parent_class is None:
1356 # parser.fail("missing parent structure/class")
1357 return parser.parse_enum_member_object()
1359 class OCVFunctionObject(OCVObject):
1361 def attach_function(self, node, func):
1362 owner, name = func.name.split_owner()
1363 if owner is not None:
1364 owner = unicode(owner) + '::'
1365 node += addnodes.desc_addname(owner, owner)
1367 # cast operator is special. in this case the return value
1369 if isinstance(name, CastOpDefExpr):
1370 node += addnodes.desc_name('operator', 'operator')
1371 node += nodes.Text(u' ')
1372 self.attach_type(node, name.typename)
1374 funcname = unicode(name)
1375 node += addnodes.desc_name(funcname, funcname)
1377 paramlist = addnodes.desc_parameterlist()
1378 for arg in func.signature:
1379 param = addnodes.desc_parameter('', '', noemph=True)
1380 if arg.type is not None:
1381 self.attach_type(param, arg.type)
1382 param += nodes.Text(u' ')
1383 #param += nodes.emphasis(unicode(arg.name), unicode(arg.name))
1384 sbrIdx = unicode(arg.name).find("[")
1386 param += nodes.strong(unicode(arg.name), unicode(arg.name))
1388 param += nodes.strong(unicode(arg.name)[:sbrIdx], unicode(arg.name)[:sbrIdx])
1389 param += nodes.Text(unicode(arg.name)[sbrIdx:])
1390 if arg.default is not None:
1391 def_ = u'=' + unicode(arg.default)
1392 #param += nodes.emphasis(def_, def_)
1393 param += nodes.Text(def_)
1398 node += addnodes.desc_addname(' const', ' const')
1399 if func.pure_virtual:
1400 node += addnodes.desc_addname(' = 0', ' = 0')
1402 def get_index_text(self, name):
1403 lname = self.__class__.langname
1404 if lname == "C" and name.startswith("cv"):
1406 return _('%s (%s function)') % (name, lname)
1408 def parse_definition(self, parser):
1409 return parser.parse_function()
1411 def describe_signature(self, signode, func):
1412 self.attach_modifiers(signode, func)
1414 signode += addnodes.desc_annotation('explicit', 'explicit')
1415 signode += nodes.Text(' ')
1417 signode += addnodes.desc_annotation('virtual', 'virtual')
1418 signode += nodes.Text(' ')
1419 # return value is None for things with a reverse return value
1420 # such as casting operator definitions or constructors
1422 if func.rv is not None:
1423 self.attach_type(signode, func.rv)
1424 signode += nodes.Text(u' ')
1425 self.attach_function(signode, func)
1428 class OCVCurrentNamespace(Directive):
1429 """This directive is just to tell Sphinx that we're documenting
1430 stuff in namespace foo.
1434 required_arguments = 1
1435 optional_arguments = 0
1436 final_argument_whitespace = True
1440 env = self.state.document.settings.env
1441 if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
1442 env.temp_data['ocv:prefix'] = None
1444 parser = DefinitionParser(self.arguments[0])
1446 prefix = parser.parse_type()
1448 except DefinitionError, e:
1449 self.env.warn(self.env.docname,
1450 e.description, self.lineno)
1452 env.temp_data['ocv:prefix'] = prefix
1456 class OCVXRefRole(XRefRole):
1458 def process_link(self, env, refnode, has_explicit_title, title, target):
1459 refnode['ocv:parent'] = env.temp_data.get('ocv:parent')
1460 if not has_explicit_title:
1461 target = target.lstrip('~') # only has a meaning for the title
1462 # if the first character is a tilde, don't display the module/class
1463 # parts of the contents
1464 if title[:1] == '~':
1466 dcolon = title.rfind('::')
1468 title = title[dcolon + 2:]
1469 return title, target
1472 class OCVCFunctionObject(OCVFunctionObject):
1475 class OCVJavaFunctionObject(OCVFunctionObject):
1479 class OCVDomain(Domain):
1480 """OpenCV C++ language domain."""
1484 'class': ObjType(l_('class'), 'class'),
1485 'struct': ObjType(l_('struct'), 'struct'),
1486 'function': ObjType(l_('function'), 'func', 'funcx'),
1487 'cfunction': ObjType(l_('cfunction'), 'cfunc', 'cfuncx'),
1488 'jfunction': ObjType(l_('jfunction'), 'jfunc', 'jfuncx'),
1489 'pyfunction': ObjType(l_('pyfunction'), 'pyfunc'),
1490 'member': ObjType(l_('member'), 'member'),
1491 'emember': ObjType(l_('emember'), 'emember'),
1492 'type': ObjType(l_('type'), 'type'),
1493 'enum': ObjType(l_('enum'), 'enum')
1497 'class': OCVClassObject,
1498 'struct': OCVStructObject,
1499 'function': OCVFunctionObject,
1500 'cfunction': OCVCFunctionObject,
1501 'jfunction': OCVJavaFunctionObject,
1502 'pyfunction': OCVPyModulelevel,
1503 'member': OCVMemberObject,
1504 'emember': OCVEnumMemberObject,
1505 'type': OCVTypeObject,
1506 'enum': OCVEnumObject,
1507 'namespace': OCVCurrentNamespace
1510 'class': OCVXRefRole(),
1511 'struct': OCVXRefRole(),
1512 'func' : OCVXRefRole(fix_parens=True),
1513 'funcx' : OCVXRefRole(),
1514 'cfunc' : OCVXRefRole(fix_parens=True),
1515 'cfuncx' : OCVXRefRole(),
1516 'jfunc' : OCVXRefRole(fix_parens=True),
1517 'jfuncx' : OCVXRefRole(),
1518 'pyfunc' : OCVPyXRefRole(),
1519 'member': OCVXRefRole(),
1520 'emember': OCVXRefRole(),
1521 'type': OCVXRefRole(),
1522 'enum': OCVXRefRole()
1525 'objects': {}, # fullname -> docname, objtype
1528 def __init__(self, env):
1529 Domain.__init__(self, env)
1530 self.data['objects2'] = {}
1532 def clear_doc(self, docname):
1533 for fullname, (fn, _, _) in self.data['objects'].items():
1535 del self.data['objects'][fullname]
1537 def resolve_xref(self, env, fromdocname, builder,
1538 typ, target, node, contnode):
1539 def _create_refnode(expr):
1540 name = unicode(expr)
1541 if "type" in self.objtypes_for_role(typ):
1543 if "cfunction" in self.objtypes_for_role(typ):
1544 if not name.startswith(u'cv'):
1546 dict = self.data['objects']
1547 if name not in dict:
1548 dict = self.data['objects2']
1549 if name not in dict:
1550 refdoc = node.get('refdoc', fromdocname)
1551 env.warn(refdoc, 'unresolved reference: %r - %r' % (target, typ), node.line)
1554 if obj[1] not in self.objtypes_for_role(typ):
1557 if "class" in self.objtypes_for_role(typ):
1558 title = u"class " + title
1559 elif "struct" in self.objtypes_for_role(typ):
1560 title = u"struct " + title
1561 return make_refnode(builder, fromdocname, obj[0], obj[2],
1564 parser = DefinitionParser(target)
1566 expr = parser.parse_type().get_name()
1568 if not parser.eof or expr is None:
1569 raise DefinitionError('')
1570 except DefinitionError:
1571 refdoc = node.get('refdoc', fromdocname)
1572 env.warn(refdoc, 'unparseable C++ definition: %r' % target,
1576 parent = node['ocv:parent']
1578 rv = _create_refnode(expr)
1579 if rv is not None or parent is None:
1581 parent = parent.get_name()
1583 rv = _create_refnode(expr.prefix(parent))
1587 parent, name = parent.split_owner()
1588 return _create_refnode(expr.prefix(parent))
1590 def get_objects(self):
1591 for refname, (docname, type, theid) in self.data['objects'].iteritems():
1592 yield (refname, refname, type, docname, refname, 1)
1594 def get_type_name(self, type, primary=False):
1596 Return full name for given ObjType.
1602 'class': _('C++ class'),
1603 'struct': _('C/C++ struct'),
1604 'function': _('C++ function'),
1605 'cfunction': _('C function'),
1606 'jfunction': _('Java method'),
1607 'pyfunction': _('Python function'),
1608 'member': _('C++ member'),
1609 'emember': _('enum member'),
1610 'type': _('C/C++ type'),
1611 'enum': _('C/C++ enum'),
1612 'namespace': _('C++ namespace'),
1613 }.get(type.lname, _('%s %s') % (self.label, type.lname))
1616 app.add_domain(OCVDomain)