added example of vec-file
[profile/ivi/opencv.git] / doc / ocv.py
1 # -*- coding: utf-8 -*-
2 """
3     ocv domain, a modified copy of sphinx.domains.cpp + shpinx.domains.python.
4                             The original copyright is below
5     ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6
7     The OpenCV C/C++/Python/Java/... language domain.
8
9     :copyright: Copyright 2007-2011 by the Sphinx team, see AUTHORS.
10     :license: BSD, see LICENSE for details.
11 """
12
13 import re
14 from copy import deepcopy
15
16 from docutils import nodes
17 from docutils.parsers.rst import directives
18
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
27
28 ########################### Python Part ########################### 
29
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
37           ''', re.VERBOSE)
38
39
40 def _pseudo_parse_arglist(signode, arglist):
41     """"Parse" a list of arguments separated by commas.
42
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).
46     """
47     paramlist = addnodes.desc_parameterlist()
48     stack = [paramlist]
49     try:
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(']'):
58                 stack.pop()
59                 argument = argument[1:].strip()
60             while argument.endswith(']'):
61                 ends_close += 1
62                 argument = argument[:-1].strip()
63             while argument.endswith('['):
64                 ends_open += 1
65                 argument = argument[:-1].strip()
66             if argument:
67                 stack[-1] += addnodes.desc_parameter(argument, argument, noemph=True)
68             while ends_open:
69                 stack.append(addnodes.desc_optional())
70                 stack[-2] += stack[-1]
71                 ends_open -= 1
72             while ends_close:
73                 stack.pop()
74                 ends_close -= 1
75         if len(stack) != 1:
76             raise IndexError
77     except IndexError:
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)
83     else:
84         signode += paramlist
85
86
87 class OCVPyObject(ObjectDescription):
88     """
89     Description of a general Python object.
90     """
91     option_spec = {
92         'noindex': directives.flag,
93         'module': directives.unchanged,
94     }
95
96     doc_field_types = [
97         TypedField('parameter', label=l_('Parameters'),
98                    names=('param', 'parameter', 'arg', 'argument',
99                           'keyword', 'kwarg', 'kwparam'),
100                    typerolename='obj', typenames=('paramtype', 'type'),
101                    can_collapse=True),
102         TypedField('variable', label=l_('Variables'), rolename='obj',
103                    names=('var', 'ivar', 'cvar'),
104                    typerolename='obj', typenames=('vartype',),
105                    can_collapse=True),
106         GroupedField('exceptions', label=l_('Raises'), rolename='exc',
107                      names=('raises', 'raise', 'exception', 'except'),
108                      can_collapse=True),
109         Field('returnvalue', label=l_('Returns'), has_arg=False,
110               names=('returns', 'return')),
111         Field('returntype', label=l_('Return type'), has_arg=False,
112               names=('rtype',)),
113     ]
114
115     def get_signature_prefix(self, sig):
116         """
117         May return a prefix to put before the object name in the signature.
118         """
119         return ''
120
121     def needs_arglist(self):
122         """
123         May return true if an empty argument list is to be generated even if
124         the document contains none.
125         """
126         return False
127
128     def handle_signature(self, sig, signode):
129         """
130         Transform a Python signature into RST nodes.
131         Returns (fully qualified name of the thing, classname if any).
132
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
136         """
137         signode += nodes.strong("Python:", "Python:")
138         signode += addnodes.desc_name(" ", " ")
139         m = py_sig_re.match(sig)
140         if m is None:
141             raise ValueError
142         name_prefix, name, arglist, retann = m.groups()
143
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')
148         if classname:
149             add_module = False
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('.')
154             elif name_prefix:
155                 # class name is given in the signature, but different
156                 # (shouldn't happen)
157                 fullname = classname + '.' + name_prefix + name
158             else:
159                 # class name is not given in the signature
160                 fullname = classname + '.' + name
161         else:
162             add_module = True
163             if name_prefix:
164                 classname = name_prefix.rstrip('.')
165                 fullname = name_prefix + name
166             else:
167                 classname = ''
168                 fullname = name
169
170         signode['module'] = modname
171         signode['class'] = classname
172         signode['fullname'] = fullname
173
174         sig_prefix = self.get_signature_prefix(sig)
175         if sig_prefix:
176             signode += addnodes.desc_annotation(sig_prefix, sig_prefix)
177
178         if name_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)
188
189         signode += addnodes.desc_name(name, name)
190         if not arglist:
191             if self.needs_arglist():
192                 # for callables, add an empty parameter list
193                 signode += addnodes.desc_parameterlist()
194             if retann:
195                 signode += addnodes.desc_returns(retann, retann)
196             return fullname, name_prefix
197         _pseudo_parse_arglist(signode, arglist)
198         if retann:
199             signode += addnodes.desc_returns(retann, retann)
200         return fullname, name_prefix
201
202     def get_index_text(self, modname, name):
203         """
204         Return the text for the index entry of the object.
205         """
206         raise NotImplementedError('must be implemented in subclasses')
207
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]
212         # note target
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:
220                 self.env.warn(
221                     self.env.docname,
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',
226                     self.lineno)
227             objects.setdefault(fullname, (self.env.docname, self.objtype, name_cls[0]))
228
229         indextext = self.get_index_text(modname, name_cls)
230         if indextext:
231             self.indexnode['entries'].append(('single', indextext,
232                                               fullname, fullname))
233
234     def before_content(self):
235         # needed for automatic qualification of members (reset in subclasses)
236         self.clsname_set = False
237
238     def after_content(self):
239         if self.clsname_set:
240             self.env.temp_data['py:class'] = None
241
242 class OCVPyModulelevel(OCVPyObject):
243     """
244     Description of an object on module level (functions, data).
245     """
246     directive_prefix = 'py'
247
248     def needs_arglist(self):
249         return self.objtype == self.__class__.directive_prefix + 'function'
250
251     def get_index_text(self, modname, name_cls):
252         if self.objtype == self.__class__.directive_prefix + 'function':
253             if not modname:
254                 fname = name_cls[0]
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':
263             if not modname:
264                 return _('%s (Python variable)') % name_cls[0]
265             return _('%s (in module %s)') % (name_cls[0], modname)
266         else:
267             return ''
268
269 class OCVPyOldModulelevel(OCVPyModulelevel):
270     directive_prefix = 'pyold'
271     pass
272
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] == '~':
283                 title = title[1:]
284                 dot = title.rfind('.')
285                 if dot != -1:
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] == '.':
290             target = target[1:]
291             refnode['refspecific'] = True
292         return title, target
293
294
295 ########################### C/C++/Java Part ########################### 
296
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)
303         \[\s*\]
304     |   \(\s*\)
305     |   (<<|>>)=?
306     |   [!<>=/*%+|&^-]=?
307     |   \+\+ | --
308     |   ~ | && | \| | \|\|
309     |   ->\*? | \,
310 ''')
311
312 _id_shortwords = {
313     'char':                 'c',
314     'signed char':          'c',
315     'unsigned char':        'C',
316     'int':                  'i',
317     'signed int':           'i',
318     'unsigned int':         'U',
319     'long':                 'l',
320     'signed long':          'l',
321     'unsigned long':        'L',
322     'bool':                 'b',
323     'size_t':               's',
324     'std::string':          'ss',
325     'std::ostream':         'os',
326     'std::istream':         'is',
327     'std::iostream':        'ios',
328     'std::vector':          'v',
329     'std::map':             'm',
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'
372 }
373
374
375 class DefinitionError(Exception):
376
377     def __init__(self, description):
378         self.description = description
379
380     def __unicode__(self):
381         return self.description
382
383     def __str__(self):
384         return unicode(self.encode('utf-8'))
385
386
387 class DefExpr(object):
388
389     def __unicode__(self):
390         raise NotImplementedError()
391
392     def __eq__(self, other):
393         if type(self) is not type(other):
394             return False
395         try:
396             for key, value in self.__dict__.iteritems():
397                 if value != getattr(other, value):
398                     return False
399         except AttributeError:
400             return False
401         return True
402
403     def __ne__(self, other):
404         return not self.__eq__(other)
405
406     def clone(self):
407         """Close a definition expression node"""
408         return deepcopy(self)
409
410     def get_id(self):
411         """Returns the id for the node"""
412         return u''
413
414     def get_name(self):
415         """Returns the name.  Returns either `None` or a node with
416         a name you might call :meth:`split_owner` on.
417         """
418         return None
419
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.
425         """
426         return None, self
427
428     def prefix(self, prefix):
429         """Prefixes a name node (a node returned by :meth:`get_name`)."""
430         raise NotImplementedError()
431
432     def __str__(self):
433         return unicode(self).encode('utf-8')
434
435     def __repr__(self):
436         return '<%s %s>' % (self.__class__.__name__, self)
437
438
439 class PrimaryDefExpr(DefExpr):
440
441     def get_name(self):
442         return self
443
444     def prefix(self, prefix):
445         if isinstance(prefix, PathDefExpr):
446             prefix = prefix.clone()
447             prefix.path.append(self)
448             return prefix
449         return PathDefExpr([prefix, self])
450
451
452 class NameDefExpr(PrimaryDefExpr):
453
454     def __init__(self, name):
455         self.name = name
456
457     def get_id(self):
458         name = _id_shortwords.get(self.name)
459         if name is not None:
460             return name
461         return self.name.replace(u' ', u'-')
462
463     def __unicode__(self):
464         return unicode(self.name)
465
466
467 class PathDefExpr(PrimaryDefExpr):
468
469     def __init__(self, parts):
470         self.path = parts
471
472     def get_id(self):
473         rv = u'::'.join(x.get_id() for x in self.path)
474         return _id_shortwords.get(rv, rv)
475
476     def split_owner(self):
477         if len(self.path) > 1:
478             return PathDefExpr(self.path[:-1]), self.path[-1]
479         return None, self
480
481     def prefix(self, prefix):
482         if isinstance(prefix, PathDefExpr):
483             prefix = prefix.clone()
484             prefix.path.extend(self.path)
485             return prefix
486         return PathDefExpr([prefix] + self.path)
487
488     def __unicode__(self):
489         return u'::'.join(map(unicode, self.path))
490
491
492 class TemplateDefExpr(PrimaryDefExpr):
493
494     def __init__(self, typename, args):
495         self.typename = typename
496         self.args = args
497
498     def split_owner(self):
499         owner, typename = self.typename.split_owner()
500         return owner, TemplateDefExpr(typename, self.args)
501
502     def get_id(self):
503         return u'%s:%s:' % (self.typename.get_id(),
504                             u'.'.join(x.get_id() for x in self.args))
505
506     def __unicode__(self):
507         return u'%s<%s>' % (self.typename, u', '.join(map(unicode, self.args)))
508
509
510 class WrappingDefExpr(DefExpr):
511
512     def __init__(self, typename):
513         self.typename = typename
514
515     def get_name(self):
516         return self.typename.get_name()
517
518
519 class ModifierDefExpr(WrappingDefExpr):
520
521     def __init__(self, typename, modifiers):
522         WrappingDefExpr.__init__(self, typename)
523         self.modifiers = modifiers
524
525     def get_id(self):
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)
530
531     def __unicode__(self):
532         return u' '.join(map(unicode, list(self.modifiers) + [self.typename]))
533
534
535 class PtrDefExpr(WrappingDefExpr):
536
537     def get_id(self):
538         return self.typename.get_id() + u'P'
539
540     def __unicode__(self):
541         return u'%s*' % self.typename
542
543
544 class RefDefExpr(WrappingDefExpr):
545
546     def get_id(self):
547         return self.typename.get_id() + u'R'
548
549     def __unicode__(self):
550         return u'%s&' % self.typename
551
552
553 class ConstDefExpr(WrappingDefExpr):
554
555     def __init__(self, typename, prefix=False):
556         WrappingDefExpr.__init__(self, typename)
557         self.prefix = prefix
558
559     def get_id(self):
560         return self.typename.get_id() + u'C'
561
562     def __unicode__(self):
563         return (self.prefix and u'const %s' or u'%s const') % self.typename
564         
565 class ConstTemplateDefExpr(WrappingDefExpr):
566
567     def __init__(self, typename, prefix=False):
568         WrappingDefExpr.__init__(self, typename)
569         self.prefix = prefix
570
571     def get_id(self):
572         return self.typename.get_id() + u'C'
573
574     def __unicode__(self):
575         return (self.prefix and u'const %s' or u'%s const') % self.typename
576
577
578 class CastOpDefExpr(PrimaryDefExpr):
579
580     def __init__(self, typename):
581         self.typename = typename
582
583     def get_id(self):
584         return u'castto-%s-operator' % self.typename.get_id()
585
586     def __unicode__(self):
587         return u'operator %s' % self.typename
588
589
590 class ArgumentDefExpr(DefExpr):
591
592     def __init__(self, type, name, default=None):
593         self.name = name
594         self.type = type
595         self.default = default
596
597     def get_name(self):
598         return self.name.get_name()
599
600     def get_id(self):
601         if self.type is None:
602             return 'X'
603         return self.type.get_id()
604
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'')
608
609
610 class NamedDefExpr(DefExpr):
611
612     def __init__(self, name, visibility, static):
613         self.name = name
614         self.visibility = visibility
615         self.static = static
616
617     def get_name(self):
618         return self.name.get_name()
619
620     def get_modifiers(self):
621         rv = []
622         if self.visibility != 'public':
623             rv.append(self.visibility)
624         if self.static:
625             rv.append(u'static')
626         return rv
627
628
629 class TypeObjDefExpr(NamedDefExpr):
630
631     def __init__(self, name, visibility, static, typename):
632         NamedDefExpr.__init__(self, name, visibility, static)
633         self.typename = typename
634
635     def get_id(self):
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())
639
640     def __unicode__(self):
641         buf = self.get_modifiers()
642         if self.typename is None:
643             buf.append(unicode(self.name))
644         else:
645             buf.extend(map(unicode, (self.typename, self.name)))
646         return u' '.join(buf)
647
648
649 class MemberObjDefExpr(NamedDefExpr):
650
651     def __init__(self, name, visibility, static, typename, value):
652         NamedDefExpr.__init__(self, name, visibility, static)
653         self.typename = typename
654         self.value = value
655
656     def get_id(self):
657         return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
658
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)
665
666
667 class FuncDefExpr(NamedDefExpr):
668
669     def __init__(self, name, visibility, static, explicit, rv,
670                  signature, const, pure_virtual):
671         NamedDefExpr.__init__(self, name, visibility, static)
672         self.rv = rv
673         self.signature = signature
674         self.explicit = explicit
675         self.const = const
676         self.pure_virtual = pure_virtual
677
678     def get_id(self):
679         return u'%s%s%s' % (
680             self.name.get_id(),
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''
684         )
685     
686     def __unicode__(self):
687         buf = self.get_modifiers()
688         if self.explicit:
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))))
694         if self.const:
695             buf.append(u'const')
696         if self.pure_virtual:
697             buf.append(u'= 0')
698         return u' '.join(buf)
699
700
701 class ClassDefExpr(NamedDefExpr):
702
703     def __init__(self, name, visibility, static):
704         NamedDefExpr.__init__(self, name, visibility, static)
705
706     def get_id(self):
707         return self.name.get_id()
708
709     def __unicode__(self):
710         buf = self.get_modifiers()
711         buf.append(unicode(self.name))
712         return u' '.join(buf)
713
714
715 class DefinitionParser(object):
716
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.
721     _modifiers = {
722         'volatile':     None,
723         'register':     None,
724         'mutable':      None,
725         'const':        None,
726         'typename':     None,
727         'unsigned':     set(('char', 'short', 'int', 'long')),
728         'signed':       set(('char', 'short', 'int', 'long')),
729         'short':        set(('int',)),
730         'long':         set(('int', 'long', 'double'))
731     }
732
733     def __init__(self, definition):
734         self.definition = definition.strip()
735         self.pos = 0
736         self.end = len(self.definition)
737         self.last_match = None
738         self._previous_state = (0, None)
739
740     def fail(self, msg):
741         raise DefinitionError('Invalid definition: %s [error at %d]\n  %s' %
742             (msg, self.pos, self.definition))
743
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
750             return True
751         return False
752
753     def backout(self):
754         self.pos, self.last_match = self._previous_state
755
756     def skip_string(self, string):
757         strlen = len(string)
758         if self.definition[self.pos:self.pos + strlen] == string:
759             self.pos += strlen
760             return True
761         return False
762
763     def skip_word(self, word):
764         return self.match(re.compile(r'\b%s\b' % re.escape(word)))
765
766     def skip_ws(self):
767         return self.match(_whitespace_re)
768
769     @property
770     def eof(self):
771         return self.pos >= self.end
772
773     @property
774     def current_char(self):
775         try:
776             return self.definition[self.pos]
777         except IndexError:
778             return 'EOF'
779
780     @property
781     def matched_text(self):
782         if self.last_match is not None:
783             return self.last_match.group()
784
785     def _parse_operator(self):
786         self.skip_ws()
787         # thank god, a regular operator definition
788         if self.match(_operator_re):
789             return NameDefExpr('operator' +
790                                 _whitespace_re.sub('', self.matched_text))
791
792         # new/delete operator?
793         for allocop in 'new', 'delete':
794             if not self.skip_word(allocop):
795                 continue
796             self.skip_ws()
797             if self.skip_string('['):
798                 self.skip_ws()
799                 if not self.skip_string(']'):
800                     self.fail('expected "]" for ' + allocop)
801                 allocop += '[]'
802             return NameDefExpr('operator ' + allocop)
803
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)
808
809     def _parse_name(self):
810         if not self.match(_identifier_re):
811             self.fail('expected name')
812         identifier = self.matched_text
813
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()
820
821         return NameDefExpr(identifier)
822
823     def _guess_typename(self, path):
824         if not path:
825             return [], 'int'
826         # for the long type, we don't want the int in there
827         if 'long' in path:
828             path = [x for x in path if x != 'int']
829             # remove one long
830             path.remove('long')
831             return path, 'long'
832         if path[-1] in ('int', 'char'):
833             return path[:-1], path[-1]
834         return path, 'int'
835
836     def _attach_crefptr(self, expr, is_const=False):
837         if is_const:
838             expr = ConstDefExpr(expr, prefix=True)
839         while 1:
840             self.skip_ws()
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)
847             else:
848                 return expr
849
850     def _peek_const(self, path):
851         try:
852             path.remove('const')
853             return True
854         except ValueError:
855             return False
856
857     def _parse_builtin(self, modifier):
858         path = [modifier]
859         following = self._modifiers[modifier]
860         while 1:
861             self.skip_ws()
862             if not self.match(_identifier_re):
863                 break
864             identifier = self.matched_text
865             if identifier in following:
866                 path.append(identifier)
867                 following = self._modifiers[modifier]
868                 assert following
869             else:
870                 self.backout()
871                 break
872
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)
877
878     def _parse_type_expr(self):
879         typename = self._parse_name()
880         if typename and self.skip_string('['):
881             typename.name += '['
882             if self.match(re.compile(r'\d*')):
883                 typename.name += self.last_match.group(0)
884             typename.name += ']'
885             if not self.skip_string(']'):
886                 self.fail('expected type')
887         self.skip_ws()
888         if not self.skip_string('<'):
889             return typename
890
891         args = []
892         while 1:
893             self.skip_ws()
894             if self.skip_string('>'):
895                 break
896             if args:
897                 if not self.skip_string(','):
898                     self.fail('"," or ">" in template expected')
899                 self.skip_ws()
900             args.append(self._parse_type(True))
901         return TemplateDefExpr(typename, args)
902
903     def _parse_type(self, in_template=False):
904         self.skip_ws()
905         result = []
906         modifiers = []
907
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))
912
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('::'):
917             self.skip_ws()
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
926                     # eats types
927                     if following is not None:
928                         return self._parse_builtin(modifier)
929                     modifiers.append(modifier)
930                 else:
931                     self.backout()
932                     break
933
934         while 1:
935             self.skip_ws()
936             if (in_template and self.current_char in ',>') or \
937                (result and not self.skip_string('::')) or \
938                self.eof:
939                 break
940             result.append(self._parse_type_expr())
941
942         if not result:
943             self.fail('expected type')
944         if len(result) == 1:
945             rv = result[0]
946         else:
947             rv = PathDefExpr(result)
948         is_const = self._peek_const(modifiers)
949         if is_const:
950             rv = ConstDefExpr(rv, prefix=True)
951         if modifiers:
952             rv = ModifierDefExpr(rv, modifiers)
953         return self._attach_crefptr(rv, False)
954
955     def _parse_default_expr(self):
956         self.skip_ws()
957         if self.match(_string_re):
958             return self.matched_text
959         paren_stack_depth = 0
960         max_pos = len(self.definition)
961         rv_start = self.pos
962         while 1:
963             idx0 = self.definition.find('(', self.pos)
964             idx1 = self.definition.find(',', self.pos)
965             idx2 = self.definition.find(')', self.pos)
966             if idx0 < 0:
967                 idx0 = max_pos
968             if idx1 < 0:
969                 idx1 = max_pos
970             if idx2 < 0:
971                 idx2 = max_pos
972             idx = min(idx0, idx1, idx2)
973             if idx >= max_pos:
974                 self.fail('unexpected end in default expression')
975             if idx == idx0:
976                 paren_stack_depth += 1
977             elif idx == idx2:
978                 paren_stack_depth -= 1
979                 if paren_stack_depth < 0:
980                     break
981             elif paren_stack_depth == 0:
982                 break
983             self.pos = idx+1
984             
985         rv = self.definition[rv_start:idx]
986         self.pos = idx
987         return rv
988
989     def _parse_signature(self):
990         self.skip_ws()
991         if not self.skip_string('('):
992             self.fail('expected parentheses for function')
993
994         args = []
995         while 1:
996             self.skip_ws()
997             if self.eof:
998                 self.fail('missing closing parentheses')
999             if self.skip_string(')'):
1000                 break
1001             if args:
1002                 if not self.skip_string(','):
1003                     self.fail('expected comma between arguments')
1004                 self.skip_ws()
1005
1006             argtype = self._parse_type()
1007             argname = default = None
1008             self.skip_ws()
1009             if self.skip_string('='):
1010                 self.pos += 1
1011                 default = self._parse_default_expr()
1012             elif self.current_char not in ',)':
1013                 argname = self._parse_name()
1014                 self.skip_ws()
1015                 if self.skip_string('='):
1016                     default = self._parse_default_expr()
1017
1018             args.append(ArgumentDefExpr(argtype, argname, default))
1019         self.skip_ws()
1020         const = self.skip_word('const')
1021         if const:
1022             self.skip_ws()
1023         if self.skip_string('='):
1024             self.skip_ws()
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 '
1030                           'not allowed')
1031             pure_virtual = True
1032         else:
1033             pure_virtual = False
1034         return args, const, pure_virtual
1035
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
1042
1043     def parse_type(self):
1044         return self._parse_type()
1045
1046     def parse_type_object(self):
1047         visibility, static = self._parse_visibility_static()
1048         typename = self._parse_type()
1049         self.skip_ws()
1050         if not self.eof:
1051             name = self._parse_type()
1052         else:
1053             name = typename
1054             typename = None
1055         return TypeObjDefExpr(name, visibility, static, typename)
1056
1057     def parse_member_object(self):
1058         visibility, static = self._parse_visibility_static()
1059         typename = self._parse_type()
1060         name = self._parse_type()
1061         self.skip_ws()
1062         if self.skip_string('='):
1063             value = self.read_rest().strip()
1064         else:
1065             value = None
1066         return MemberObjDefExpr(name, visibility, static, typename, value)
1067
1068     def parse_function(self):
1069         visibility, static = self._parse_visibility_static()
1070         if self.skip_word('explicit'):
1071             explicit = True
1072             self.skip_ws()
1073         else:
1074             explicit = False
1075         rv = self._parse_type()
1076         self.skip_ws()
1077         # some things just don't have return values
1078         if self.current_char == '(':
1079             name = rv
1080             rv = None
1081         else:
1082             name = self._parse_type()
1083         return FuncDefExpr(name, visibility, static, explicit, rv,
1084                            *self._parse_signature())
1085
1086     def parse_class(self):
1087         visibility, static = self._parse_visibility_static()
1088         return ClassDefExpr(self._parse_type(), visibility, static)
1089
1090     def read_rest(self):
1091         rv = self.definition[self.pos:]
1092         self.pos = self.end
1093         return rv
1094
1095     def assert_end(self):
1096         self.skip_ws()
1097         if not self.eof:
1098             self.fail('expected end of definition, got %r' %
1099                       self.definition[self.pos:])
1100
1101
1102 class OCVObject(ObjectDescription):
1103     """Description of a C++ language object."""
1104
1105     langname = "C++"
1106     ismember = False
1107
1108     doc_field_types = [
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,
1115               names=('rtype',)),
1116     ]
1117
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)
1125
1126     def attach_type(self, node, type):
1127         # XXX: link to c?
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)
1134         node += pnode
1135
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(" ", " ")
1141             
1142         if obj.visibility != 'public':
1143             node += addnodes.desc_annotation(obj.visibility,
1144                                              obj.visibility)
1145             node += nodes.Text(' ')
1146         if obj.static:
1147             node += addnodes.desc_annotation('static', 'static')
1148             node += nodes.Text(' ')
1149
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)
1162
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))
1169
1170         indextext = self.get_index_text(name)
1171         if indextext:
1172             self.indexnode['entries'].append(('single', indextext, theid, name))
1173
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
1180         else:
1181             self.parentname_set = False
1182
1183     def after_content(self):
1184         if self.parentname_set:
1185             self.env.temp_data['ocv:parent'] = None
1186
1187     def parse_definition(self, parser):
1188         raise NotImplementedError()
1189
1190     def describe_signature(self, signode, arg):
1191         raise NotImplementedError()
1192
1193     def handle_signature(self, sig, signode):
1194         parser = DefinitionParser(sig)
1195         try:
1196             rv = self.parse_definition(parser)
1197             parser.assert_end()
1198         except DefinitionError, e:
1199             self.env.warn(self.env.docname,
1200                           e.description, self.lineno)
1201             raise ValueError
1202         self.describe_signature(signode, rv)
1203
1204         parent = self.env.temp_data.get('ocv:parent')
1205         if parent is not None:
1206             rv = rv.clone()
1207             rv.name = rv.name.prefix(parent)
1208         return rv
1209
1210
1211 class OCVClassObject(OCVObject):
1212     object_annotation = "class "
1213     object_long_name = "class"
1214
1215     def attach_modifiers(self, node, obj):
1216         if obj.visibility != 'public':
1217             node += addnodes.desc_annotation(obj.visibility,
1218                                              obj.visibility)
1219             node += nodes.Text(' ')
1220         if obj.static:
1221             node += addnodes.desc_annotation('static', 'static')
1222             node += nodes.Text(' ')
1223
1224     def get_index_text(self, name):
1225         return _('%s (C++ %s)') % (name, self.__class__.object_long_name)
1226
1227     def parse_definition(self, parser):
1228         return parser.parse_class()
1229
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)
1234
1235 class OCVStructObject(OCVClassObject):
1236     object_annotation = "struct "
1237     object_long_name = "structure"
1238
1239 class OCVTypeObject(OCVObject):
1240
1241     def get_index_text(self, name):
1242         if self.objtype == 'type':
1243             return _('%s (C++ type)') % name
1244         return ''
1245
1246     def parse_definition(self, parser):
1247         return parser.parse_type_object()
1248
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)
1256
1257 class OCVMemberObject(OCVObject):
1258     ismember = True
1259
1260     def get_index_text(self, name):
1261         if self.objtype == 'member':
1262             return _('%s (C++ member)') % name
1263         return ''
1264
1265     def parse_definition(self, parser):
1266         return parser.parse_member_object()
1267
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)
1275
1276 class OCVFunctionObject(OCVObject):
1277
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)
1283
1284         # cast operator is special.  in this case the return value
1285         # is reversed.
1286         if isinstance(name, CastOpDefExpr):
1287             node += addnodes.desc_name('operator', 'operator')
1288             node += nodes.Text(u' ')
1289             self.attach_type(node, name.typename)
1290         else:
1291             funcname = unicode(name)
1292             node += addnodes.desc_name(funcname, funcname)
1293
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_)
1306             paramlist += param
1307
1308         node += paramlist
1309         if func.const:
1310             node += addnodes.desc_addname(' const', ' const')
1311         if func.pure_virtual:
1312             node += addnodes.desc_addname(' = 0', ' = 0')
1313
1314     def get_index_text(self, name):
1315         lname = self.__class__.langname
1316         if lname == "C" and name.startswith("cv"):
1317             name = name[2:]
1318         return _('%s (%s function)') % (name, lname)
1319
1320     def parse_definition(self, parser):
1321         return parser.parse_function()
1322
1323     def describe_signature(self, signode, func):
1324         self.attach_modifiers(signode, func)
1325         if func.explicit:
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
1330         # and destructors.
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)
1335
1336
1337 class OCVCurrentNamespace(Directive):
1338     """This directive is just to tell Sphinx that we're documenting
1339     stuff in namespace foo.
1340     """
1341
1342     has_content = False
1343     required_arguments = 1
1344     optional_arguments = 0
1345     final_argument_whitespace = True
1346     option_spec = {}
1347
1348     def run(self):
1349         env = self.state.document.settings.env
1350         if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
1351             env.temp_data['ocv:prefix'] = None
1352         else:
1353             parser = DefinitionParser(self.arguments[0])
1354             try:
1355                 prefix = parser.parse_type()
1356                 parser.assert_end()
1357             except DefinitionError, e:
1358                 self.env.warn(self.env.docname,
1359                               e.description, self.lineno)
1360             else:
1361                 env.temp_data['ocv:prefix'] = prefix
1362         return []
1363
1364
1365 class OCVXRefRole(XRefRole):
1366
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] == '~':
1374                 title = title[1:]
1375                 dcolon = title.rfind('::')
1376                 if dcolon != -1:
1377                     title = title[dcolon + 2:]
1378         return title, target
1379
1380
1381 class OCVCFunctionObject(OCVFunctionObject):
1382     langname = "C"
1383     
1384 class OCVJavaFunctionObject(OCVFunctionObject):
1385     langname = "Java"
1386
1387
1388 class OCVDomain(Domain):
1389     """OpenCV C++ language domain."""
1390     name = 'ocv'
1391     label = 'C++'
1392     object_types = {
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')
1402     }
1403
1404     directives = {
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
1415     }
1416     roles = {
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()
1429     }
1430     initial_data = {
1431         'objects': {},  # fullname -> docname, objtype
1432     }
1433     
1434     def __init__(self, env):
1435         Domain.__init__(self, env)
1436         self.data['objects2'] = {}
1437
1438     def clear_doc(self, docname):
1439         for fullname, (fn, _, _) in self.data['objects'].items():
1440             if fn == docname:
1441                 del self.data['objects'][fullname]
1442
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):
1448                 return None
1449             if "cfunction" in self.objtypes_for_role(typ):
1450                 if not name.startswith(u'cv'):
1451                     name = u'cv' + name
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)
1458                 return None
1459             obj = dict[name]
1460             if obj[1] not in self.objtypes_for_role(typ):
1461                 return None
1462             title = obj[2]
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],
1468                                 contnode, title)
1469
1470         parser = DefinitionParser(target)
1471         try:
1472             expr = parser.parse_type().get_name()
1473             parser.skip_ws()
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,
1479                      node.line)
1480             return None
1481
1482         parent = node['ocv:parent']
1483
1484         rv = _create_refnode(expr)
1485         if rv is not None or parent is None:
1486             return rv
1487         parent = parent.get_name()
1488
1489         rv = _create_refnode(expr.prefix(parent))
1490         if rv is not None:
1491             return rv
1492
1493         parent, name = parent.split_owner()
1494         return _create_refnode(expr.prefix(parent))
1495
1496     def get_objects(self):
1497         for refname, (docname, type, theid) in self.data['objects'].iteritems():
1498             yield (refname, refname, type, docname, refname, 1)
1499             
1500     def get_type_name(self, type, primary=False):
1501         """
1502         Return full name for given ObjType.
1503         """
1504         if primary:
1505             return type.lname
1506             
1507         return {
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))
1519         
1520 def setup(app):
1521     app.add_domain(OCVDomain)