mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
C++, fix namespacing of elements and xrefs.
This commit is contained in:
parent
967ca06545
commit
caad958de4
@ -257,15 +257,7 @@ class ASTBase(UnicodeMixin):
|
|||||||
"""
|
"""
|
||||||
raise NotImplementedError(repr(self))
|
raise NotImplementedError(repr(self))
|
||||||
|
|
||||||
def split_owner(self):
|
def prefix_nested_name(self, prefix):
|
||||||
"""Nodes returned by :meth:`get_name` can split off their
|
|
||||||
owning parent. This function returns the owner and the
|
|
||||||
name as a tuple of two items. If a node does not support
|
|
||||||
it, it returns None as owner and self as name.
|
|
||||||
"""
|
|
||||||
raise NotImplementedError(repr(self))
|
|
||||||
|
|
||||||
def prefix(self, prefix):
|
|
||||||
"""Prefix a name node (a node returned by :meth:`get_name`)."""
|
"""Prefix a name node (a node returned by :meth:`get_name`)."""
|
||||||
raise NotImplementedError(repr(self))
|
raise NotImplementedError(repr(self))
|
||||||
|
|
||||||
@ -276,10 +268,12 @@ class ASTBase(UnicodeMixin):
|
|||||||
return '<%s %s>' % (self.__class__.__name__, self)
|
return '<%s %s>' % (self.__class__.__name__, self)
|
||||||
|
|
||||||
def _verify_parsing_context(context):
|
def _verify_parsing_context(context):
|
||||||
assert context in {'typeObject', 'functionObject', 'memberObject', 'classObject', 'namespaceObject', 'xrefObject', 'abstractDecl', 'functionObjectArgument', 'baseClass'}
|
if not context in {'typeObject', 'functionObject', 'memberObject', 'classObject', 'namespaceObject', 'xrefObject', 'abstractDecl', 'functionObjectArgument', 'baseClass'}:
|
||||||
|
raise Exception("Parsing context '%s' is invalid." % context)
|
||||||
|
|
||||||
def _verify_description_mod(mode):
|
def _verify_description_mod(mode):
|
||||||
assert mode in {'lastIsName', 'allIsName', 'noneIsName', 'markType'}
|
if not mode in {'lastIsName', 'allIsName', 'noneIsName', 'markType'}:
|
||||||
|
raise Exception("Description mode '%s' is invalid." % mode)
|
||||||
|
|
||||||
class ASTOperatorBuildIn(ASTBase):
|
class ASTOperatorBuildIn(ASTBase):
|
||||||
|
|
||||||
@ -371,10 +365,11 @@ class ASTNestedName(ASTBase):
|
|||||||
def name(self):
|
def name(self):
|
||||||
return self
|
return self
|
||||||
|
|
||||||
def prefix(self, prefix):
|
def prefix_nested_name(self, prefix):
|
||||||
if self.names[0] == '':
|
if self.names[0] == '':
|
||||||
raise DefinitionError('Can not prefix nested name rooted in outer-most namespace.')
|
return self # it's defined at global namespace, don't tuch it
|
||||||
names = [prefix]
|
assert isinstance(prefix, ASTNestedName)
|
||||||
|
names = prefix.names[:]
|
||||||
names.extend(self.names)
|
names.extend(self.names)
|
||||||
return ASTNestedName(names)
|
return ASTNestedName(names)
|
||||||
|
|
||||||
@ -669,10 +664,12 @@ class ASTType(ASTBase):
|
|||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
res = ['___']
|
res = ['___']
|
||||||
res.append(text_type(self.name))
|
res.append(text_type(self.prefixedName))
|
||||||
if self.objectType == 'function':
|
if self.objectType == 'function':
|
||||||
res.append('___')
|
res.append('___')
|
||||||
res.append(self.decl.get_param_id())
|
res.append(self.decl.get_param_id())
|
||||||
|
elif self.objectType == 'type':
|
||||||
|
pass
|
||||||
else:
|
else:
|
||||||
print(self.objectType)
|
print(self.objectType)
|
||||||
assert False
|
assert False
|
||||||
@ -711,7 +708,7 @@ class ASTTypeWithInit(ASTBase):
|
|||||||
|
|
||||||
def get_id(self):
|
def get_id(self):
|
||||||
if self.objectType == 'member':
|
if self.objectType == 'member':
|
||||||
return text_type(self.name)
|
return "___" + text_type(self.prefixedName)
|
||||||
else:
|
else:
|
||||||
raise NotImplementedError("Should this happen? %s, %s" % (self.objectType, text_type(self.name)))
|
raise NotImplementedError("Should this happen? %s, %s" % (self.objectType, text_type(self.name)))
|
||||||
|
|
||||||
@ -1133,12 +1130,12 @@ class DefinitionParser(object):
|
|||||||
|
|
||||||
if context == 'abstractDecl':
|
if context == 'abstractDecl':
|
||||||
declId = None
|
declId = None
|
||||||
elif context == 'functionObjectArgument' \
|
elif context in {'functionObjectArgument', 'functionObject', 'typeObject'}:
|
||||||
or context == 'functionObject':
|
|
||||||
# Function arguments don't need to have a name.
|
# Function arguments don't need to have a name.
|
||||||
# Some functions (constructors/destructors) don't ahve return type,
|
# Some functions (constructors/destructors) don't ahve return type,
|
||||||
# so the name has been parsed in the declSpecs.
|
# so the name has been parsed in the declSpecs.
|
||||||
# Also conversion operators (e.g., "A::operator std::string()" will have no declId at this point
|
# Also conversion operators (e.g., "A::operator std::string()" will have no declId at this point
|
||||||
|
# For types we want to allow the plain declaration that there is a type, i.e., "MyContainer::const_iterator"
|
||||||
pos = self.pos
|
pos = self.pos
|
||||||
try:
|
try:
|
||||||
declId = self._parse_nested_name(context)
|
declId = self._parse_nested_name(context)
|
||||||
@ -1291,23 +1288,12 @@ class CPPObject(ObjectDescription):
|
|||||||
self.state.document.note_explicit_target(signode)
|
self.state.document.note_explicit_target(signode)
|
||||||
if not name in objects:
|
if not name in objects:
|
||||||
objects.setdefault(name, (self.env.docname, ast.objectType, theid))
|
objects.setdefault(name, (self.env.docname, ast.objectType, theid))
|
||||||
|
self.env.temp_data['cpp:lastname'] = ast.prefixedName
|
||||||
|
|
||||||
indextext = self.get_index_text(name)
|
indextext = self.get_index_text(name)
|
||||||
if indextext:
|
if indextext:
|
||||||
self.indexnode['entries'].append(('single', indextext, theid, ''))
|
self.indexnode['entries'].append(('single', indextext, theid, ''))
|
||||||
|
|
||||||
def before_content(self):
|
|
||||||
lastname = self.names and self.names[-1]
|
|
||||||
if lastname and not self.env.temp_data.get('cpp:parent'):
|
|
||||||
self.env.temp_data['cpp:parent'] = lastname.name
|
|
||||||
self.parentname_set = True
|
|
||||||
else:
|
|
||||||
self.parentname_set = False
|
|
||||||
|
|
||||||
def after_content(self):
|
|
||||||
if self.parentname_set:
|
|
||||||
self.env.temp_data['cpp:parent'] = None
|
|
||||||
|
|
||||||
def parse_definition(self, parser):
|
def parse_definition(self, parser):
|
||||||
raise NotImplementedError()
|
raise NotImplementedError()
|
||||||
|
|
||||||
@ -1325,9 +1311,9 @@ class CPPObject(ObjectDescription):
|
|||||||
self.describe_signature(signode, ast)
|
self.describe_signature(signode, ast)
|
||||||
|
|
||||||
parent = self.env.temp_data.get('cpp:parent')
|
parent = self.env.temp_data.get('cpp:parent')
|
||||||
if parent is not None:
|
if parent and len(parent) > 0:
|
||||||
ast = ast.clone()
|
ast = ast.clone()
|
||||||
ast.prefixedName = ast.name.prefix(parent)
|
ast.prefixedName = ast.name.prefix_nested_name(parent[-1])
|
||||||
else:
|
else:
|
||||||
ast.prefixedName = ast.name
|
ast.prefixedName = ast.name
|
||||||
return ast
|
return ast
|
||||||
@ -1342,7 +1328,7 @@ class CPPTypeObject(CPPObject):
|
|||||||
|
|
||||||
def describe_signature(self, signode, ast):
|
def describe_signature(self, signode, ast):
|
||||||
signode += addnodes.desc_annotation('type ', 'type ')
|
signode += addnodes.desc_annotation('type ', 'type ')
|
||||||
ast.describe_signature(signode, 'typeObject', self.env)
|
ast.describe_signature(signode, 'lastIsName', self.env)
|
||||||
|
|
||||||
class CPPMemberObject(CPPObject):
|
class CPPMemberObject(CPPObject):
|
||||||
|
|
||||||
@ -1371,6 +1357,14 @@ class CPPClassObject(CPPObject):
|
|||||||
def get_index_text(self, name):
|
def get_index_text(self, name):
|
||||||
return _('%s (C++ class)') % name
|
return _('%s (C++ class)') % name
|
||||||
|
|
||||||
|
def before_content(self):
|
||||||
|
lastname = self.env.temp_data['cpp:lastname']
|
||||||
|
assert lastname
|
||||||
|
self.env.temp_data['cpp:parent'].append(lastname)
|
||||||
|
|
||||||
|
def after_content(self):
|
||||||
|
self.env.temp_data['cpp:parent'].pop()
|
||||||
|
|
||||||
def parse_definition(self, parser):
|
def parse_definition(self, parser):
|
||||||
return parser.parse_class_object()
|
return parser.parse_class_object()
|
||||||
|
|
||||||
@ -1393,7 +1387,7 @@ class CPPNamespaceObject(Directive):
|
|||||||
def run(self):
|
def run(self):
|
||||||
env = self.state.document.settings.env
|
env = self.state.document.settings.env
|
||||||
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
|
if self.arguments[0].strip() in ('NULL', '0', 'nullptr'):
|
||||||
env.temp_data['cpp:parent'] = None
|
env.temp_data['cpp:parent'] = []
|
||||||
else:
|
else:
|
||||||
parser = DefinitionParser(self.arguments[0])
|
parser = DefinitionParser(self.arguments[0])
|
||||||
try:
|
try:
|
||||||
@ -1402,13 +1396,15 @@ class CPPNamespaceObject(Directive):
|
|||||||
except DefinitionError as e:
|
except DefinitionError as e:
|
||||||
self.state_machine.reporter.warning(e.description,line=self.lineno)
|
self.state_machine.reporter.warning(e.description,line=self.lineno)
|
||||||
else:
|
else:
|
||||||
env.temp_data['cpp:parent'] = prefix
|
env.temp_data['cpp:parent'] = [prefix]
|
||||||
return []
|
return []
|
||||||
|
|
||||||
class CPPXRefRole(XRefRole):
|
class CPPXRefRole(XRefRole):
|
||||||
|
|
||||||
def process_link(self, env, refnode, has_explicit_title, title, target):
|
def process_link(self, env, refnode, has_explicit_title, title, target):
|
||||||
refnode['cpp:parent'] = env.temp_data.get('cpp:parent')
|
parent = env.temp_data.get('cpp:parent')
|
||||||
|
if parent:
|
||||||
|
refnode['cpp:parent'] = parent[:]
|
||||||
if not has_explicit_title:
|
if not has_explicit_title:
|
||||||
target = target.lstrip('~') # only has a meaning for the title
|
target = target.lstrip('~') # only has a meaning for the title
|
||||||
# if the first character is a tilde, don't display the module/class
|
# if the first character is a tilde, don't display the module/class
|
||||||
@ -1477,8 +1473,9 @@ class CPPDomain(Domain):
|
|||||||
|
|
||||||
# try qualifying it with the parent
|
# try qualifying it with the parent
|
||||||
parent = node.get('cpp:parent', None)
|
parent = node.get('cpp:parent', None)
|
||||||
if not parent: return None
|
if parent and len(parent) > 0:
|
||||||
else: return _create_refnode(nameAst.prefix(parent))
|
return _create_refnode(nameAst.prefix_nested_name(parent[-1]))
|
||||||
|
else: return None
|
||||||
|
|
||||||
def get_objects(self):
|
def get_objects(self):
|
||||||
for refname, (docname, type, theid) in iteritems(self.data['objects']):
|
for refname, (docname, type, theid) in iteritems(self.data['objects']):
|
||||||
|
@ -53,6 +53,7 @@ def test_type_definitions():
|
|||||||
check("type", "std::function<void()> F")
|
check("type", "std::function<void()> F")
|
||||||
check("type", "std::function<R(A1, A2, A3)> F")
|
check("type", "std::function<R(A1, A2, A3)> F")
|
||||||
check("type", "std::function<R(A1, A2, A3, As...)> F")
|
check("type", "std::function<R(A1, A2, A3, As...)> F")
|
||||||
|
check("type", "MyContainer::const_iterator")
|
||||||
|
|
||||||
check('member', ' const std::string & name = 42', 'const std::string &name = 42')
|
check('member', ' const std::string & name = 42', 'const std::string &name = 42')
|
||||||
check('member', ' const std::string & name', 'const std::string &name')
|
check('member', ' const std::string & name', 'const std::string &name')
|
||||||
|
Loading…
Reference in New Issue
Block a user