summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArmin Ronacher <armin.ronacher@active-4.com>2011-09-23 00:49:08 +0200
committerArmin Ronacher <armin.ronacher@active-4.com>2011-09-23 00:49:08 +0200
commitd0922a3c2de845bdede021a7c1c51e9a91fb4bb0 (patch)
treecebc38c92c465a8c62f31eb7dcdc7126355c8d4a
parent033e429bcb75fa7047e510df57a2f24be6c5ba03 (diff)
parentcb3a2ab539aa403af69c3650210fd1325f143291 (diff)
downloadsphinx-d0922a3c2de845bdede021a7c1c51e9a91fb4bb0.tar.gz
merged
-rw-r--r--doc/domains.rst12
-rw-r--r--sphinx/domains/cpp.py176
-rw-r--r--tests/test_cpp_domain.py12
3 files changed, 146 insertions, 54 deletions
diff --git a/doc/domains.rst b/doc/domains.rst
index a1e7b98e..9894caab 100644
--- a/doc/domains.rst
+++ b/doc/domains.rst
@@ -535,8 +535,14 @@ The following directives are available:
Describe a casting operator here.
+ .. cpp:function:: constexpr void foo(std::string &bar[2]) noexcept
+
+ Describe a constexpr function here.
+
.. cpp:member:: std::string theclass::name
+ .. cpp:member:: std::string theclass::name[N][M]
+
.. cpp:type:: theclass::const_iterator
Will be rendered like this:
@@ -557,8 +563,14 @@ The following directives are available:
Describe a casting operator here.
+ .. cpp:function:: constexpr void foo(std::string &bar[2]) noexcept
+
+ Describe a constexpr function here.
+
.. cpp:member:: std::string theclass::name
+ .. cpp:member:: std::string theclass::name[N][M]
+
.. cpp:type:: theclass::const_iterator
.. rst:directive:: .. cpp:namespace:: namespace
diff --git a/sphinx/domains/cpp.py b/sphinx/domains/cpp.py
index 0d33f59d..1fa428e1 100644
--- a/sphinx/domains/cpp.py
+++ b/sphinx/domains/cpp.py
@@ -29,8 +29,8 @@ _whitespace_re = re.compile(r'\s+(?u)')
_string_re = re.compile(r"[LuU8]?('([^'\\]*(?:\\.[^'\\]*)*)'"
r'|"([^"\\]*(?:\\.[^"\\]*)*)")', re.S)
_visibility_re = re.compile(r'\b(public|private|protected)\b')
-_array_def_re = re.compile(r'\[\s*(.+?)?\s*\]')
-_template_arg_re = re.compile(r'[^,>]+')
+_array_def_re = re.compile(r'\[\s*([^\]]+?)?\s*\]')
+_template_arg_re = re.compile(r'(%s)|([^,>]+)' % _string_re.pattern, re.S)
_operator_re = re.compile(r'''(?x)
\[\s*\]
| \(\s*\)
@@ -224,6 +224,20 @@ class PathDefExpr(PrimaryDefExpr):
return u'::'.join(map(unicode, self.path))
+class ArrayTypeSuffixDefExpr(object):
+
+ def __init__(self, size_hint=None):
+ self.size_hint = size_hint
+
+ def get_id_suffix(self):
+ return 'A'
+
+ def __unicode__(self):
+ return u'[%s]' % (
+ self.size_hint is not None and unicode(self.size_hint) or u'',
+ )
+
+
class TemplateDefExpr(PrimaryDefExpr):
def __init__(self, typename, args):
@@ -288,29 +302,22 @@ class PtrDefExpr(WrappingDefExpr):
return u'%s*' % self.typename
-class ArrayDefExpr(WrappingDefExpr):
-
- def __init__(self, typename, size_hint=None):
- WrappingDefExpr.__init__(self, typename)
- self.size_hint = size_hint
+class LValRefDefExpr(WrappingDefExpr):
def get_id(self):
- return self.typename.get_id() + u'A'
+ return self.typename.get_id() + u'R'
def __unicode__(self):
- return u'%s[%s]' % (
- self.typename,
- self.size_hint is not None and unicode(self.size_hint) or u''
- )
+ return u'%s&' % self.typename
-class RefDefExpr(WrappingDefExpr):
+class RValRefDefExpr(WrappingDefExpr):
def get_id(self):
- return self.typename.get_id() + u'R'
+ return self.typename.get_id() + u'RR'
def __unicode__(self):
- return u'%s&' % self.typename
+ return u'%s&&' % self.typename
class ConstDefExpr(WrappingDefExpr):
@@ -340,22 +347,29 @@ class CastOpDefExpr(PrimaryDefExpr):
class ArgumentDefExpr(DefExpr):
- def __init__(self, type, name, default=None):
+ def __init__(self, type, name, type_suffixes, default=None):
self.name = name
self.type = type
+ self.type_suffixes = type_suffixes
self.default = default
def get_name(self):
return self.name.get_name()
def get_id(self):
- if self.type is None:
- return 'X'
- return self.type.get_id()
+ buf = []
+ buf.append(self.type and self.type.get_id() or 'X')
+ for suffix in self.type_suffixes:
+ buf.append(suffix.get_id_suffix())
+ return u''.join(buf)
def __unicode__(self):
- return (u'%s %s' % (self.type or u'', self.name or u'')).strip() + \
- (self.default is not None and u'=%s' % self.default or u'')
+ buf = [(u'%s %s' % (self.type or u'', self.name or u'')).strip()]
+ if self.default is not None:
+ buf.append('=%s' % self.default)
+ for suffix in self.type_suffixes:
+ buf.append(unicode(suffix))
+ return u''.join(buf)
class NamedDefExpr(DefExpr):
@@ -379,14 +393,19 @@ class NamedDefExpr(DefExpr):
class TypeObjDefExpr(NamedDefExpr):
- def __init__(self, name, visibility, static, typename):
+ def __init__(self, name, visibility, static, typename, type_suffixes):
NamedDefExpr.__init__(self, name, visibility, static)
self.typename = typename
+ self.type_suffixes = type_suffixes
def get_id(self):
if self.typename is None:
- return self.name.get_id()
- return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
+ buf = [self.name.get_id()]
+ else:
+ buf = [u'%s__%s' % (self.name.get_id(), self.typename.get_id())]
+ for suffix in self.type_suffixes:
+ buf.append(suffix.get_id_suffix())
+ return u''.join(buf)
def __unicode__(self):
buf = self.get_modifiers()
@@ -394,56 +413,74 @@ class TypeObjDefExpr(NamedDefExpr):
buf.append(unicode(self.name))
else:
buf.extend(map(unicode, (self.typename, self.name)))
- return u' '.join(buf)
+ buf = [u' '.join(buf)]
+ for suffix in self.type_suffixes:
+ buf.append(unicode(suffix))
+ return u''.join(buf)
class MemberObjDefExpr(NamedDefExpr):
- def __init__(self, name, visibility, static, typename, value):
+ def __init__(self, name, visibility, static, typename, type_suffixes,
+ value):
NamedDefExpr.__init__(self, name, visibility, static)
self.typename = typename
+ self.type_suffixes = type_suffixes
self.value = value
def get_id(self):
- return u'%s__%s' % (self.name.get_id(), self.typename.get_id())
+ buf = [u'%s__%s' % (self.name.get_id(), self.typename.get_id())]
+ for suffix in self.type_suffixes:
+ buf.append(suffix.get_id_suffix())
+ return u''.join(buf)
def __unicode__(self):
buf = self.get_modifiers()
- buf.append(u'%s %s' % (self.typename, self.name))
+ buf.extend((unicode(self.typename), unicode(self.name)))
+ buf = [u' '.join(buf)]
+ for suffix in self.type_suffixes:
+ buf.append(unicode(suffix))
if self.value is not None:
- buf.append(u'= %s' % self.value)
- return u' '.join(buf)
+ buf.append(u' = %s' % self.value)
+ return u''.join(buf)
class FuncDefExpr(NamedDefExpr):
- def __init__(self, name, visibility, static, explicit, rv,
- signature, const, pure_virtual):
+ def __init__(self, name, visibility, static, explicit, constexpr, rv,
+ signature, const, noexcept, pure_virtual):
NamedDefExpr.__init__(self, name, visibility, static)
self.rv = rv
self.signature = signature
self.explicit = explicit
+ self.constexpr = constexpr
self.const = const
+ self.noexcept = noexcept
self.pure_virtual = pure_virtual
def get_id(self):
- return u'%s%s%s' % (
+ return u'%s%s%s%s' % (
self.name.get_id(),
self.signature and u'__' +
u'.'.join(x.get_id() for x in self.signature) or u'',
- self.const and u'C' or u''
+ self.const and u'C' or u'',
+ self.constexpr and 'CE' or ''
)
def __unicode__(self):
buf = self.get_modifiers()
if self.explicit:
buf.append(u'explicit')
+ if self.constexpr:
+ buf.append(u'constexpr')
if self.rv is not None:
buf.append(unicode(self.rv))
buf.append(u'%s(%s)' % (self.name, u', '.join(
map(unicode, self.signature))))
if self.const:
buf.append(u'const')
+ if self.noexcept:
+ buf.append(u'noexcept')
if self.pure_virtual:
buf.append(u'= 0')
return u' '.join(buf)
@@ -517,6 +554,12 @@ class DefinitionParser(object):
def skip_ws(self):
return self.match(_whitespace_re)
+ def skip_word_and_ws(self, word):
+ if self.skip_word(word):
+ self.skip_ws()
+ return True
+ return False
+
@property
def eof(self):
return self.pos >= self.end
@@ -600,13 +643,21 @@ class DefinitionParser(object):
expr = ConstDefExpr(expr)
elif self.skip_string('*'):
expr = PtrDefExpr(expr)
- elif self.match(_array_def_re):
- expr = ArrayDefExpr(expr, self.last_match.group(1))
elif self.skip_string('&'):
- expr = RefDefExpr(expr)
+ if self.skip_string('&'):
+ expr = RValRefDefExpr(expr)
+ else:
+ expr = LValRefDefExpr(expr)
else:
return expr
+ def _try_parse_type_suffixes(self):
+ rv = []
+ while self.match(_array_def_re):
+ rv.append(ArrayTypeSuffixDefExpr(self.last_match.group(1)))
+ self.skip_ws()
+ return rv
+
def _peek_const(self, path):
try:
path.remove('const')
@@ -734,29 +785,32 @@ class DefinitionParser(object):
self.skip_ws()
if self.skip_string('...'):
- args.append(ArgumentDefExpr(None, '...', None))
+ args.append(ArgumentDefExpr(None, '...', [], None))
if self.skip_string(')'):
break
else:
self.fail('expected closing parenthesis after ellipses')
- argtype = self._parse_type()
argname = default = None
+ argtype = self._parse_type()
self.skip_ws()
+ type_suffixes = self._try_parse_type_suffixes()
if self.skip_string('='):
- self.pos += 1
default = self._parse_default_expr()
elif self.current_char not in ',)':
argname = self._parse_name()
self.skip_ws()
+ type_suffixes.extend(self._try_parse_type_suffixes())
if self.skip_string('='):
default = self._parse_default_expr()
+ if argname is None:
+ argname = argtype
+ argtype = None
- args.append(ArgumentDefExpr(argtype, argname, default))
+ args.append(ArgumentDefExpr(argtype, argname, type_suffixes, default))
self.skip_ws()
- const = self.skip_word('const')
- if const:
- self.skip_ws()
+ const = self.skip_word_and_ws('const')
+ noexcept = self.skip_word_and_ws('noexcept')
if self.skip_string('='):
self.skip_ws()
if not (self.skip_string('0') or \
@@ -768,10 +822,10 @@ class DefinitionParser(object):
pure_virtual = True
else:
pure_virtual = False
- return args, const, pure_virtual
+ return args, const, noexcept, pure_virtual
def _parse_visibility_static(self):
- visibility = 'public'
+ visibility = 'public'
if self.match(_visibility_re):
visibility = self.matched_text
static = self.skip_word('static')
@@ -786,29 +840,31 @@ class DefinitionParser(object):
self.skip_ws()
if not self.eof:
name = self._parse_type()
+ type_suffixes = self._try_parse_type_suffixes()
else:
name = typename
typename = None
- return TypeObjDefExpr(name, visibility, static, typename)
+ type_suffixes = []
+ return TypeObjDefExpr(name, visibility, static, typename, type_suffixes)
def parse_member_object(self):
visibility, static = self._parse_visibility_static()
typename = self._parse_type()
name = self._parse_type()
+ type_suffixes = self._try_parse_type_suffixes()
self.skip_ws()
if self.skip_string('='):
value = self.read_rest().strip()
else:
value = None
- return MemberObjDefExpr(name, visibility, static, typename, value)
+ return MemberObjDefExpr(name, visibility, static, typename,
+ type_suffixes, value)
def parse_function(self):
visibility, static = self._parse_visibility_static()
- if self.skip_word('explicit'):
- explicit = True
- self.skip_ws()
- else:
- explicit = False
+ explicit = self.skip_word_and_ws('explicit')
+ constexpr = self.skip_word_and_ws('constexpr')
+
rv = self._parse_type()
self.skip_ws()
# some things just don't have return values
@@ -817,7 +873,7 @@ class DefinitionParser(object):
rv = None
else:
name = self._parse_type()
- return FuncDefExpr(name, visibility, static, explicit, rv,
+ return FuncDefExpr(name, visibility, static, explicit, constexpr, rv,
*self._parse_signature())
def parse_class(self):
@@ -858,6 +914,10 @@ class CPPObject(ObjectDescription):
node += addnodes.desc_addname(owner, owner)
node += addnodes.desc_name(varname, varname)
+ def attach_type_suffixes(self, node, suffixes):
+ for suffix in suffixes:
+ node += nodes.Text(unicode(suffix))
+
def attach_type(self, node, type):
# XXX: link to c?
text = unicode(type)
@@ -876,6 +936,9 @@ class CPPObject(ObjectDescription):
if obj.static:
node += addnodes.desc_annotation('static', 'static')
node += nodes.Text(' ')
+ if getattr(obj, 'constexpr', False):
+ node += addnodes.desc_annotation('constexpr', 'constexpr')
+ node += nodes.Text(' ')
def add_target_and_index(self, sigobj, sig, signode):
theid = sigobj.get_id()
@@ -961,6 +1024,7 @@ class CPPTypeObject(CPPObject):
self.attach_type(signode, obj.typename)
signode += nodes.Text(' ')
self.attach_name(signode, obj.name)
+ self.attach_type_suffixes(signode, obj.type_suffixes)
class CPPMemberObject(CPPObject):
@@ -978,6 +1042,7 @@ class CPPMemberObject(CPPObject):
self.attach_type(signode, obj.typename)
signode += nodes.Text(' ')
self.attach_name(signode, obj.name)
+ self.attach_type_suffixes(signode, obj.type_suffixes)
if obj.value is not None:
signode += nodes.Text(u' = ' + obj.value)
@@ -1007,6 +1072,7 @@ class CPPFunctionObject(CPPObject):
self.attach_type(param, arg.type)
param += nodes.Text(u' ')
param += nodes.emphasis(unicode(arg.name), unicode(arg.name))
+ self.attach_type_suffixes(param, arg.type_suffixes)
if arg.default is not None:
def_ = u'=' + unicode(arg.default)
param += nodes.emphasis(def_, def_)
@@ -1015,6 +1081,8 @@ class CPPFunctionObject(CPPObject):
node += paramlist
if func.const:
node += addnodes.desc_addname(' const', ' const')
+ if func.noexcept:
+ node += addnodes.desc_addname(' noexcept', ' noexcept')
if func.pure_virtual:
node += addnodes.desc_addname(' = 0', ' = 0')
diff --git a/tests/test_cpp_domain.py b/tests/test_cpp_domain.py
index 3ca29b4e..30cdb69e 100644
--- a/tests/test_cpp_domain.py
+++ b/tests/test_cpp_domain.py
@@ -28,6 +28,9 @@ def test_type_definitions():
x = 'void operator()(const boost::array<VertexID, 2>& v) const'
assert unicode(parse('function', x)) == x
+ x = 'void operator()(const boost::array<VertexID, 2, "foo, bar">& v) const'
+ assert unicode(parse('function', x)) == x
+
rv = parse('member_object', 'const std::vector< unsigned int, long> &name')
assert unicode(rv) == 'const std::vector<unsigned int, long>& name'
@@ -48,6 +51,15 @@ def test_type_definitions():
assert unicode(parse('type_object', 'long long int foo')) == 'long long foo'
+ x = 'MyClass::MyClass(MyClass::MyClass&&)'
+ assert unicode(parse('function', x)) == x
+
+ x = 'constexpr int get_value()'
+ assert unicode(parse('function', x)) == x
+
+ x = 'int get_value() const noexcept'
+ assert unicode(parse('function', x)) == x
+
def test_operators():
x = parse('function', 'void operator new [ ] ()')