Merge pull request #8682 from jakobandersen/c_intersphinx_8341

C, C++, fix intersphinx and role lookup types
This commit is contained in:
Jakob Lykke Andersen
2021-01-11 21:22:04 +01:00
committed by GitHub
11 changed files with 359 additions and 59 deletions

View File

@@ -48,6 +48,8 @@ Bugs fixed
* #8094: texinfo: image files on the different directory with document are not
copied
* #8671: :confval:`highlight_options` is not working
* #8341: C, fix intersphinx lookup types for names in declarations.
* C, C++: in general fix intersphinx and role lookup types.
Testing
--------

View File

@@ -3657,15 +3657,18 @@ class CDomain(Domain):
name = 'c'
label = 'C'
object_types = {
'function': ObjType(_('function'), 'func'),
'member': ObjType(_('member'), 'member'),
'macro': ObjType(_('macro'), 'macro'),
'type': ObjType(_('type'), 'type'),
'var': ObjType(_('variable'), 'data'),
'enum': ObjType(_('enum'), 'enum'),
'enumerator': ObjType(_('enumerator'), 'enumerator'),
'struct': ObjType(_('struct'), 'struct'),
'union': ObjType(_('union'), 'union'),
# 'identifier' is the one used for xrefs generated in signatures, not in roles
'member': ObjType(_('member'), 'var', 'member', 'data', 'identifier'),
'var': ObjType(_('variable'), 'var', 'member', 'data', 'identifier'),
'function': ObjType(_('function'), 'func', 'identifier', 'type'),
'macro': ObjType(_('macro'), 'macro', 'identifier'),
'struct': ObjType(_('struct'), 'struct', 'identifier', 'type'),
'union': ObjType(_('union'), 'union', 'identifier', 'type'),
'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'),
'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'),
'type': ObjType(_('type'), 'identifier', 'type'),
# generated object types
'functionParam': ObjType(_('function parameter'), 'identifier', 'var', 'member', 'data'), # noqa
}
directives = {

View File

@@ -7251,14 +7251,18 @@ class CPPDomain(Domain):
name = 'cpp'
label = 'C++'
object_types = {
'class': ObjType(_('class'), 'class', 'type', 'identifier'),
'union': ObjType(_('union'), 'union', 'type', 'identifier'),
'function': ObjType(_('function'), 'function', 'func', 'type', 'identifier'),
'member': ObjType(_('member'), 'member', 'var'),
'type': ObjType(_('type'), 'type', 'identifier'),
'concept': ObjType(_('concept'), 'concept', 'identifier'),
'enum': ObjType(_('enum'), 'enum', 'type', 'identifier'),
'enumerator': ObjType(_('enumerator'), 'enumerator')
'class': ObjType(_('class'), 'class', 'struct', 'identifier', 'type'),
'union': ObjType(_('union'), 'union', 'identifier', 'type'),
'function': ObjType(_('function'), 'func', 'identifier', 'type'),
'member': ObjType(_('member'), 'member', 'var', 'identifier'),
'type': ObjType(_('type'), 'identifier', 'type'),
'concept': ObjType(_('concept'), 'concept', 'identifier'),
'enum': ObjType(_('enum'), 'enum', 'identifier', 'type'),
'enumerator': ObjType(_('enumerator'), 'enumerator', 'identifier'),
# generated object types
'functionParam': ObjType(_('function parameter'), 'identifier', 'member', 'var'), # noqa
'templateParam': ObjType(_('template parameter'),
'identifier', 'class', 'struct', 'union', 'member', 'var', 'type'), # noqa
}
directives = {
@@ -7435,30 +7439,19 @@ class CPPDomain(Domain):
if typ.startswith('cpp:'):
typ = typ[4:]
origTyp = typ
if typ == 'func':
typ = 'function'
if typ == 'struct':
typ = 'class'
declTyp = s.declaration.objectType
def checkType() -> bool:
if typ == 'any' or typ == 'identifier':
if typ == 'any':
return True
if declTyp == 'templateParam':
# TODO: perhaps this should be strengthened one day
return True
if declTyp == 'functionParam':
if typ == 'var' or typ == 'member':
return True
objtypes = self.objtypes_for_role(typ)
if objtypes:
return declTyp in objtypes
print("Type is %s (originally: %s), declType is %s" % (typ, origTyp, declTyp))
print("Type is %s, declaration type is %s" % (typ, declTyp))
assert False
if not checkType():
logger.warning("cpp:%s targets a %s (%s).",
origTyp, s.declaration.objectType,
typ, s.declaration.objectType,
s.get_full_nested_name(),
location=node)
@@ -7488,10 +7481,10 @@ class CPPDomain(Domain):
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
if (env.config.add_function_parentheses and typ == 'func' and
title.endswith('operator()')):
addParen += 1
if ((typ == 'any' or typ == 'function') and
if ((typ == 'any' or typ == 'func') and
title.endswith('operator') and
displayName.endswith('operator()')):
addParen += 1
@@ -7500,7 +7493,7 @@ class CPPDomain(Domain):
if env.config.add_function_parentheses:
if typ == 'any' and displayName.endswith('()'):
addParen += 1
elif typ == 'function':
elif typ == 'func':
if title.endswith('()') and not displayName.endswith('()'):
title = title[:-2]
else:

View File

@@ -0,0 +1,4 @@
exclude_patterns = ['_build']
extensions = [
'sphinx.ext.intersphinx',
]

View File

@@ -0,0 +1,62 @@
.. c:member:: void __member = _member
- :any:`_member`
- :c:member:`_member`
- :c:var:`_member`
- :c:data:`_member`
.. c:member:: void __var = _var
- :any:`_var`
- :c:member:`_var`
- :c:var:`_var`
- :c:data:`_var`
.. c:member:: void __function = _function
- :any:`_function`
- :c:func:`_function`
- :c:type:`_function`
.. c:member:: void __macro = _macro
- :any:`_macro`
- :c:macro:`_macro`
.. c:type:: _struct __struct
struct _struct __structTagged
- :any:`_struct`
- :c:struct:`_struct`
- :c:type:`_struct`
.. c:type:: _union __union
union _union __unionTagged
- :any:`_union`
- :c:union:`_union`
- :c:type:`_union`
.. c:type:: _enum __enum
enum _enum __enumTagged
- :any:`_enum`
- :c:enum:`_enum`
- :c:type:`_enum`
.. c:member:: void __enumerator = _enumerator
- :any:`_enumerator`
- :c:enumerator:`_enumerator`
.. c:type:: _type __type
- :any:`_type`
- :c:type:`_type`
.. c:member:: void __functionParam = _functionParam.param
- :any:`_functionParam.param`
- :c:member:`_functionParam.param`
- :c:var:`_functionParam.param`
- :c:data:`_functionParam.param`

View File

@@ -0,0 +1,4 @@
exclude_patterns = ['_build']
extensions = [
'sphinx.ext.intersphinx',
]

View File

@@ -0,0 +1,112 @@
.. cpp:type:: _class __class
- :any:`_class`
- :cpp:any:`_class`
- :cpp:class:`_class`
- :cpp:struct:`_class`
- :cpp:type:`_class`
.. cpp:type:: _struct __struct
- :any:`_struct`
- :cpp:any:`_struct`
- :cpp:class:`_struct`
- :cpp:struct:`_struct`
- :cpp:type:`_struct`
.. cpp:type:: _union __union
- :any:`_union`
- :cpp:any:`_union`
- :cpp:union:`_union`
- :cpp:type:`_union`
.. cpp:member:: void __function = _function
- :any:`_function`
- :cpp:any:`_function`
- :cpp:func:`_function`
- :cpp:type:`_function`
.. cpp:member:: void __member = _member
- :any:`_member`
- :cpp:any:`_member`
- :cpp:member:`_member`
- :cpp:var:`_member`
.. cpp:member:: void __var = _var
- :any:`_var`
- :cpp:any:`_var`
- :cpp:member:`_var`
- :cpp:var:`_var`
.. cpp:type:: _type __type
- :any:`_type`
- :cpp:any:`_type`
- :cpp:type:`_type`
.. cpp:function:: template<_concept T> void __concept()
- :any:`_concept`
- :cpp:any:`_concept`
- :cpp:concept:`_concept`
.. cpp:type:: _enum __enum
- :any:`_enum`
- :cpp:any:`_enum`
- :cpp:enum:`_enum`
- :cpp:type:`_enum`
.. cpp:type:: _enumStruct __enumStruct
- :any:`_enumStruct`
- :cpp:any:`_enumStruct`
- :cpp:enum:`_enumStruct`
- :cpp:type:`_enumStruct`
.. cpp:type:: _enumClass __enumClass
- :any:`_enumClass`
- :cpp:any:`_enumClass`
- :cpp:enum:`_enumClass`
- :cpp:type:`_enumClass`
.. cpp:member:: void __enumerator = _enumerator
- :any:`_enumerator`
- :cpp:any:`_enumerator`
- :cpp:enumerator:`_enumerator`
.. cpp:member:: void __scopedEnumerator = _enumStruct::_scopedEnumerator
- :any:`_enumStruct::_scopedEnumerator`
- :cpp:any:`_enumStruct::_scopedEnumerator`
- :cpp:enumerator:`_enumStruct::_scopedEnumerator`
.. cpp:member:: void __enumerator2 = _enum::_enumerator
- :any:`_enum::_enumerator`
- :cpp:any:`_enum::_enumerator`
- :cpp:enumerator:`_enum::_enumerator`
.. cpp:member:: void __functionParam = _functionParam::param
- :any:`_functionParam::param`
- :cpp:any:`_functionParam::param`
- :cpp:member:`_functionParam::param`
- :cpp:var:`_functionParam::param`
.. cpp:type:: _templateParam::TParam __templateParam
- :any:`_templateParam::TParam`
- :cpp:any:`_templateParam::TParam`
- :cpp:type:`_templateParam::TParam`
- :cpp:member:`_templateParam::TParam`
- :cpp:var:`_templateParam::TParam`
- :cpp:class:`_templateParam::TParam`
- :cpp:struct:`_templateParam::TParam`
- :cpp:union:`_templateParam::TParam`

View File

@@ -123,37 +123,37 @@
:class:`TParamType`
:struct:`TParamType`
:union:`TParamType`
:func:`TParamType`
function
:member:`TParamType`
:var:`TParamType`
:type:`TParamType`
:concept:`TParamType`
:enum:`TParamType`
:enumerator:`TParamType`
concept
enum
enumerator
:cpp:any:`TParamVar`
:class:`TParamVar`
:struct:`TParamVar`
:union:`TParamVar`
:func:`TParamVar`
function
:member:`TParamVar`
:var:`TParamVar`
:type:`TParamVar`
:concept:`TParamVar`
:enum:`TParamVar`
:enumerator:`TParamVar`
concept
enum
enumerator
:cpp:any:`TParamTemplate`
:class:`TParamTemplate`
:struct:`TParamTemplate`
:union:`TParamTemplate`
:func:`TParamTemplate`
function
:member:`TParamTemplate`
:var:`TParamTemplate`
:type:`TParamTemplate`
:concept:`TParamTemplate`
:enum:`TParamTemplate`
:enumerator:`TParamTemplate`
concept
enum
enumerator
.. function:: void FunctionParams(int FunctionParam)

View File

@@ -114,35 +114,35 @@
class
struct
union
func
:func:`TParamType`
member
var
type
concept
enum
enumerator
:concept:`TParamType`
:enum:`TParamType`
:enumerator:`TParamType`
class
struct
union
func
:func:`TParamVar`
member
var
type
concept
enum
enumerator
:concept:`TParamVar`
:enum:`TParamVar`
:enumerator:`TParamVar`
class
struct
union
func
:func:`TParamTemplate`
member
var
type
concept
enum
enumerator
:concept:`TParamTemplate`
:enum:`TParamTemplate`
:enumerator:`TParamTemplate`
.. function:: void FunctionParams(int FunctionParam)

View File

@@ -7,6 +7,8 @@
:copyright: Copyright 2007-2021 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
"""
import zlib
from xml.etree import ElementTree
import pytest
@@ -14,6 +16,7 @@ import pytest
from sphinx import addnodes
from sphinx.addnodes import desc
from sphinx.domains.c import DefinitionError, DefinitionParser, Symbol, _id_prefix, _max_id
from sphinx.ext.intersphinx import load_mappings, normalize_intersphinx_mapping
from sphinx.testing import restructuredtext
from sphinx.testing.util import assert_node
@@ -642,3 +645,52 @@ def test_noindexentry(app):
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('single', 'f (C function)', 'c.f', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])
@pytest.mark.sphinx(testroot='domain-c-intersphinx', confoverrides={'nitpicky': True})
def test_intersphinx(tempdir, app, status, warning):
origSource = """\
.. c:member:: int _member
.. c:var:: int _var
.. c:function:: void _function()
.. c:macro:: _macro
.. c:struct:: _struct
.. c:union:: _union
.. c:enum:: _enum
.. c:enumerator:: _enumerator
.. c:type:: _type
.. c:function:: void _functionParam(int param)
""" # noqa
inv_file = tempdir / 'inventory'
inv_file.write_bytes(b'''\
# Sphinx inventory version 2
# Project: C Intersphinx Test
# Version:
# The remainder of this file is compressed using zlib.
''' + zlib.compress(b'''\
_enum c:enum 1 index.html#c.$ -
_enum._enumerator c:enumerator 1 index.html#c.$ -
_enumerator c:enumerator 1 index.html#c._enum.$ -
_function c:function 1 index.html#c.$ -
_functionParam c:function 1 index.html#c.$ -
_functionParam.param c:functionParam 1 index.html#c._functionParam -
_macro c:macro 1 index.html#c.$ -
_member c:member 1 index.html#c.$ -
_struct c:struct 1 index.html#c.$ -
_type c:type 1 index.html#c.$ -
_union c:union 1 index.html#c.$ -
_var c:member 1 index.html#c.$ -
''')) # noqa
app.config.intersphinx_mapping = {
'https://localhost/intersphinx/c/': inv_file,
}
app.config.intersphinx_cache_limit = 0
# load the inventory and check if it's done correctly
normalize_intersphinx_mapping(app, app.config)
load_mappings(app)
app.builder.build_all()
ws = filter_warnings(warning, "index")
assert len(ws) == 0

View File

@@ -9,6 +9,7 @@
"""
import re
import zlib
import pytest
@@ -17,6 +18,7 @@ from sphinx import addnodes
from sphinx.addnodes import desc
from sphinx.domains.cpp import (DefinitionError, DefinitionParser, NoOldIdError, Symbol,
_id_prefix, _max_id)
from sphinx.ext.intersphinx import load_mappings, normalize_intersphinx_mapping
from sphinx.testing import restructuredtext
from sphinx.testing.util import assert_node
from sphinx.util import docutils
@@ -1049,8 +1051,8 @@ def test_build_domain_cpp_misuse_of_roles(app, status, warning):
('concept', ['concept']),
('enum', ['type', 'enum']),
('enumerator', ['enumerator']),
('tParam', ['class', 'struct', 'union', 'func', 'member', 'var', 'type', 'concept', 'enum', 'enumerator', 'functionParam']),
('functionParam', ['member', 'var']),
('templateParam', ['class', 'struct', 'union', 'member', 'var', 'type']),
]
warn = []
for targetType, roles in ok:
@@ -1058,6 +1060,9 @@ def test_build_domain_cpp_misuse_of_roles(app, status, warning):
for r in allRoles:
if r not in roles:
warn.append("WARNING: cpp:{} targets a {} (".format(r, txtTargetType))
if targetType == 'templateParam':
warn.append("WARNING: cpp:{} targets a {} (".format(r, txtTargetType))
warn.append("WARNING: cpp:{} targets a {} (".format(r, txtTargetType))
warn = list(sorted(warn))
for w in ws:
assert "targets a" in w
@@ -1250,3 +1255,66 @@ def test_mix_decl_duplicate(app, warning):
assert "index.rst:3: WARNING: Duplicate C++ declaration, also defined at index:1." in ws[2]
assert "Declaration is '.. cpp:struct:: A'." in ws[3]
assert ws[4] == ""
@pytest.mark.sphinx(testroot='domain-cpp-intersphinx', confoverrides={'nitpicky': True})
def test_intersphinx(tempdir, app, status, warning):
origSource = """\
.. cpp:class:: _class
.. cpp:struct:: _struct
.. cpp:union:: _union
.. cpp:function:: void _function()
.. cpp:member:: int _member
.. cpp:var:: int _var
.. cpp:type:: _type
.. cpp:concept:: template<typename T> _concept
.. cpp:enum:: _enum
.. cpp:enumerator:: _enumerator
.. cpp:enum-struct:: _enumStruct
.. cpp:enumerator:: _scopedEnumerator
.. cpp:enum-class:: _enumClass
.. cpp:function:: void _functionParam(int param)
.. cpp:function:: template<typename TParam> void _templateParam()
""" # noqa
inv_file = tempdir / 'inventory'
inv_file.write_bytes(b'''\
# Sphinx inventory version 2
# Project: C Intersphinx Test
# Version:
# The remainder of this file is compressed using zlib.
''' + zlib.compress(b'''\
_class cpp:class 1 index.html#_CPPv46$ -
_concept cpp:concept 1 index.html#_CPPv4I0E8$ -
_concept::T cpp:templateParam 1 index.html#_CPPv4I0E8_concept -
_enum cpp:enum 1 index.html#_CPPv45$ -
_enum::_enumerator cpp:enumerator 1 index.html#_CPPv4N5_enum11_enumeratorE -
_enumClass cpp:enum 1 index.html#_CPPv410$ -
_enumStruct cpp:enum 1 index.html#_CPPv411$ -
_enumStruct::_scopedEnumerator cpp:enumerator 1 index.html#_CPPv4N11_enumStruct17_scopedEnumeratorE -
_enumerator cpp:enumerator 1 index.html#_CPPv4N5_enum11_enumeratorE -
_function cpp:function 1 index.html#_CPPv49_functionv -
_functionParam cpp:function 1 index.html#_CPPv414_functionParami -
_functionParam::param cpp:functionParam 1 index.html#_CPPv414_functionParami -
_member cpp:member 1 index.html#_CPPv47$ -
_struct cpp:class 1 index.html#_CPPv47$ -
_templateParam cpp:function 1 index.html#_CPPv4I0E14_templateParamvv -
_templateParam::TParam cpp:templateParam 1 index.html#_CPPv4I0E14_templateParamvv -
_type cpp:type 1 index.html#_CPPv45$ -
_union cpp:union 1 index.html#_CPPv46$ -
_var cpp:member 1 index.html#_CPPv44$ -
''')) # noqa
app.config.intersphinx_mapping = {
'https://localhost/intersphinx/cpp/': inv_file,
}
app.config.intersphinx_cache_limit = 0
# load the inventory and check if it's done correctly
normalize_intersphinx_mapping(app, app.config)
load_mappings(app)
app.builder.build_all()
ws = filter_warnings(warning, "index")
assert len(ws) == 0