C++, fix refs to operator() functions.

Fixes sphinx-doc/sphinx#2952.
This commit is contained in:
Jakob Lykke Andersen
2017-01-15 14:36:29 +09:00
parent 00fcbfb35d
commit ccd6bf4a0c
6 changed files with 49 additions and 11 deletions

View File

@@ -35,6 +35,7 @@ Bugs fixed
* #3329: emit warnings if po file is invalid and can't read it. Also writing mo too * #3329: emit warnings if po file is invalid and can't read it. Also writing mo too
* #3337: Ugly rendering of definition list term's classifier * #3337: Ugly rendering of definition list term's classifier
* #3335: gettext does not extract field_name of a field in a field_list * #3335: gettext does not extract field_name of a field in a field_list
* #2952: C++, fix refs to operator() functions.
Release 1.5.1 (released Dec 13, 2016) Release 1.5.1 (released Dec 13, 2016)

View File

@@ -4032,6 +4032,9 @@ class DefinitionParser(object):
def parse_xref_object(self): def parse_xref_object(self):
templatePrefix = self._parse_template_declaration_prefix(objectType="xref") templatePrefix = self._parse_template_declaration_prefix(objectType="xref")
name = self._parse_nested_name() name = self._parse_nested_name()
# if there are '()' left, just skip them
self.skip_ws()
self.skip_string('()')
templatePrefix = self._check_template_consistency(name, templatePrefix, templatePrefix = self._check_template_consistency(name, templatePrefix,
fullSpecShorthand=True) fullSpecShorthand=True)
res = ASTNamespace(name, templatePrefix) res = ASTNamespace(name, templatePrefix)
@@ -4488,10 +4491,12 @@ class CPPDomain(Domain):
if emitWarnings: if emitWarnings:
env.warn_node(msg, node) env.warn_node(msg, node)
warner = Warner() warner = Warner()
# add parens again for those that could be functions
if typ == 'any' or typ == 'func':
target += '()'
parser = DefinitionParser(target, warner, env.config) parser = DefinitionParser(target, warner, env.config)
try: try:
ast = parser.parse_xref_object() ast = parser.parse_xref_object()
parser.skip_ws()
parser.assert_end() parser.assert_end()
except DefinitionError as e: except DefinitionError as e:
warner.warn('Unparseable C++ cross-reference: %r\n%s' warner.warn('Unparseable C++ cross-reference: %r\n%s'
@@ -4551,11 +4556,26 @@ class CPPDomain(Domain):
name = text_type(fullNestedName).lstrip(':') name = text_type(fullNestedName).lstrip(':')
docname = s.docname docname = s.docname
assert docname assert docname
if typ == 'any' and declaration.objectType == 'function': # If it's operator(), we need to add '()' if explicit function parens
if env.config.add_function_parentheses: # are requested. Then the Sphinx machinery will add another pair.
if not node['refexplicit']: # Also, if it's an 'any' ref that resolves to a function, we need to add
title = contnode.pop(0).astext() # parens as well.
contnode += nodes.Text(title + '()') addParen = 0
if not node['refexplicit'] and declaration.objectType == 'function':
# this is just the normal haxing for 'any' roles
if env.config.add_function_parentheses and typ == 'any':
addParen += 1
# and now this stuff for operator()
if (env.config.add_function_parentheses and typ == 'function' and
contnode[-1].astext().endswith('operator()')):
addParen += 1
if ((typ == 'any' or typ == 'function') and
contnode[-1].astext().endswith('operator') and
name.endswith('operator()')):
addParen += 1
if addParen > 0:
title = contnode.pop(0).astext()
contnode += nodes.Text(title + '()' * addParen)
return make_refnode(builder, fromdocname, docname, return make_refnode(builder, fromdocname, docname,
declaration.get_newest_id(), contnode, name declaration.get_newest_id(), contnode, name
), declaration.objectType ), declaration.objectType

View File

@@ -11,3 +11,7 @@ any role
* ref function with parens :cpp:any:`paren_2()` * ref function with parens :cpp:any:`paren_2()`
* ref function without parens, explicit title :cpp:any:`paren_3_title <paren_3>` * ref function without parens, explicit title :cpp:any:`paren_3_title <paren_3>`
* ref function with parens, explicit title :cpp:any:`paren_4_title <paren_4()>` * ref function with parens, explicit title :cpp:any:`paren_4_title <paren_4()>`
* ref op call without parens :cpp:any:`paren_5::operator()`
* ref op call with parens :cpp:any:`paren_6::operator()()`
* ref op call without parens, explicit title :cpp:any:`paren_7_title <paren_7::operator()>`
* ref op call with parens, explicit title :cpp:any:`paren_8_title <paren_8::operator()()>`

View File

@@ -38,9 +38,10 @@ directives
.. cpp:function:: void paren_1(int, float) .. cpp:function:: void paren_1(int, float)
.. cpp:function:: void paren_2(int, float) .. cpp:function:: void paren_2(int, float)
.. cpp:function:: void paren_3(int, float) .. cpp:function:: void paren_3(int, float)
.. cpp:function:: void paren_4(int, float) .. cpp:function:: void paren_4(int, float)
.. cpp:function:: void paren_5::operator()(int)
.. cpp:function:: void paren_6::operator()(int)
.. cpp:function:: void paren_7::operator()(int)
.. cpp:function:: void paren_8::operator()(int)

View File

@@ -11,3 +11,7 @@ roles
* ref function with parens :cpp:func:`paren_2()` * ref function with parens :cpp:func:`paren_2()`
* ref function without parens, explicit title :cpp:func:`paren_3_title <paren_3>` * ref function without parens, explicit title :cpp:func:`paren_3_title <paren_3>`
* ref function with parens, explicit title :cpp:func:`paren_4_title <paren_4()>` * ref function with parens, explicit title :cpp:func:`paren_4_title <paren_4()>`
* ref op call without parens :cpp:func:`paren_5::operator()`
* ref op call with parens :cpp:func:`paren_6::operator()()`
* ref op call without parens, explicit title :cpp:func:`paren_7_title <paren_7::operator()>`
* ref op call with parens, explicit title :cpp:func:`paren_8_title <paren_8::operator()()>`

View File

@@ -524,7 +524,11 @@ def test_build_domain_cpp_with_add_function_parentheses_is_True(app, status, war
('ref function without parens ', 'paren_1\(\)'), ('ref function without parens ', 'paren_1\(\)'),
('ref function with parens ', 'paren_2\(\)'), ('ref function with parens ', 'paren_2\(\)'),
('ref function without parens, explicit title ', 'paren_3_title'), ('ref function without parens, explicit title ', 'paren_3_title'),
('ref function with parens, explicit title ', 'paren_4_title') ('ref function with parens, explicit title ', 'paren_4_title'),
('ref op call without parens ', 'paren_5::operator\(\)\(\)'),
('ref op call with parens ', 'paren_6::operator\(\)\(\)'),
('ref op call without parens, explicit title ', 'paren_7_title'),
('ref op call with parens, explicit title ', 'paren_8_title')
] ]
f = 'roles.html' f = 'roles.html'
@@ -562,7 +566,11 @@ def test_build_domain_cpp_with_add_function_parentheses_is_False(app, status, wa
('ref function without parens ', 'paren_1'), ('ref function without parens ', 'paren_1'),
('ref function with parens ', 'paren_2'), ('ref function with parens ', 'paren_2'),
('ref function without parens, explicit title ', 'paren_3_title'), ('ref function without parens, explicit title ', 'paren_3_title'),
('ref function with parens, explicit title ', 'paren_4_title') ('ref function with parens, explicit title ', 'paren_4_title'),
('ref op call without parens ', 'paren_5::operator\(\)'),
('ref op call with parens ', 'paren_6::operator\(\)'),
('ref op call without parens, explicit title ', 'paren_7_title'),
('ref op call with parens, explicit title ', 'paren_8_title')
] ]
f = 'roles.html' f = 'roles.html'