diff options
author | Armin Ronacher <armin.ronacher@active-4.com> | 2011-09-23 00:49:08 +0200 |
---|---|---|
committer | Armin Ronacher <armin.ronacher@active-4.com> | 2011-09-23 00:49:08 +0200 |
commit | d0922a3c2de845bdede021a7c1c51e9a91fb4bb0 (patch) | |
tree | cebc38c92c465a8c62f31eb7dcdc7126355c8d4a | |
parent | 033e429bcb75fa7047e510df57a2f24be6c5ba03 (diff) | |
parent | cb3a2ab539aa403af69c3650210fd1325f143291 (diff) | |
download | sphinx-d0922a3c2de845bdede021a7c1c51e9a91fb4bb0.tar.gz |
merged
-rw-r--r-- | doc/domains.rst | 12 | ||||
-rw-r--r-- | sphinx/domains/cpp.py | 176 | ||||
-rw-r--r-- | tests/test_cpp_domain.py | 12 |
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 [ ] ()') |