Merge pull request #7038 from jakobandersen/cpp_role_target_checking

C++, test role target checks and fix two cases
This commit is contained in:
Jakob Lykke Andersen 2020-01-20 20:05:16 +01:00 committed by GitHub
commit 204564549c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 390 additions and 3 deletions

View File

@ -122,6 +122,10 @@ Features added
Bugs fixed
----------
* C++, don't crash when using the ``struct`` role in some cases.
* C++, don't warn when using the ``var``/``member`` role for function
parameters.
Testing
--------

View File

@ -6862,23 +6862,30 @@ 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():
if typ == 'any' or typ == 'identifier':
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, declType is %s" % (typ, declTyp))
print("Type is %s (originally: %s), declType is %s" % (typ, origTyp, declTyp))
assert False
if not checkType():
warner.warn("cpp:%s targets a %s (%s)."
% (typ, s.declaration.objectType,
% (origTyp, s.declaration.objectType,
s.get_full_nested_name()))
declaration = s.declaration

View File

@ -0,0 +1,170 @@
.. default-domain:: cpp
.. namespace:: RolesTargetsOk
.. class:: Class
:cpp:any:`Class`
:class:`Class`
:struct:`Class`
union
func
member
var
:type:`Class`
concept
enum
enumerator
.. union:: Union
:cpp:any:`Union`
class
struct
:union:`Union`
func
member
var
:type:`Union`
concept
enum
enumerator
.. function:: void Function()
:cpp:any:`Function`
class
struct
union
:func:`Function`
member
var
:type:`Function`
concept
enum
enumerator
.. var:: int Variable
:cpp:any:`Variable`
class
struct
union
function
:member:`Variable`
:var:`Variables`
type
concept
enum
enumerator
.. type:: Type = void
:cpp:any:`Type`
class
struct
union
function
member
var
:type:`Type`
concept
enum
enumerator
.. concept:: template<typename T> Concept
:cpp:any:`Concept`
class
struct
union
function
member
var
type
:concept:`Concept`
enum
enumerator
.. enum-struct:: Enum
:cpp:any:`Enum`
class
struct
union
function
member
var
:type:`Enum`
concept
:enum:`Enum`
enumerator
.. enumerator:: Enumerator
:cpp:any:`Enumerator`
class
struct
union
function
member
var
type
concept
enum
:enumerator:`Enumerator`
.. class:: template<typename TParamType, \
int TParamVar, \
template<typename> typename TParamTemplate \
> ClassTemplate
:cpp:any:`TParamType`
:class:`TParamType`
:struct:`TParamType`
:union:`TParamType`
:func:`TParamType`
:member:`TParamType`
:var:`TParamType`
:type:`TParamType`
:concept:`TParamType`
:enum:`TParamType`
:enumerator:`TParamType`
:cpp:any:`TParamVar`
:class:`TParamVar`
:struct:`TParamVar`
:union:`TParamVar`
:func:`TParamVar`
:member:`TParamVar`
:var:`TParamVar`
:type:`TParamVar`
:concept:`TParamVar`
:enum:`TParamVar`
:enumerator:`TParamVar`
:cpp:any:`TParamTemplate`
:class:`TParamTemplate`
:struct:`TParamTemplate`
:union:`TParamTemplate`
:func:`TParamTemplate`
:member:`TParamTemplate`
:var:`TParamTemplate`
:type:`TParamTemplate`
:concept:`TParamTemplate`
:enum:`TParamTemplate`
:enumerator:`TParamTemplate`
.. function:: void FunctionParams(int FunctionParam)
:cpp:any:`FunctionParam`
class
struct
union
function
:member:`FunctionParam`
:var:`FunctionParam`
type
concept
enum
enumerator

View File

@ -0,0 +1,158 @@
.. default-domain:: cpp
.. namespace:: RolesTargetsWarn
.. class:: Class
class
struct
:union:`Class`
:func:`Class`
:member:`Class`
:var:`Class`
type
:concept:`Class`
:enum:`Class`
:enumerator:`Class`
.. union:: Union
:class:`Union`
:struct:`Union`
union
:func:`Union`
:member:`Union`
:var:`Union`
type
:concept:`Union`
:enum:`Union`
:enumerator:`Union`
.. function:: void Function()
:class:`Function`
:struct:`Function`
:union:`Function`
func
:member:`Function`
:var:`Function`
type
:concept:`Function`
:enum:`Function`
:enumerator:`Function`
.. var:: int Variable
:class:`Variable`
:struct:`Variable`
:union:`Variable`
:func:`Variable`
member
var
:type:`Variable`
:concept:`Variable`
:enum:`Variable`
:enumerator:`Variable`
.. type:: Type = void
:class:`Type`
:struct:`Type`
:union:`Type`
:func:`Type`
:member:`Type`
:var:`Type`
type
:concept:`Type`
:enum:`Type`
:enumerator:`Type`
.. concept:: template<typename T> Concept
:class:`Concept`
:struct:`Concept`
:union:`Concept`
:func:`Concept`
:member:`Concept`
:var:`Concept`
:type:`Concept`
concept
:enum:`Concept`
:enumerator:`Concept`
.. enum-struct:: Enum
:class:`Enum`
:struct:`Enum`
:union:`Enum`
:func:`Enum`
:member:`Enum`
:var:`Enum`
type
:concept:`Enum`
enum
:enumerator:`Enum`
.. enumerator:: Enumerator
:class:`Enumerator`
:struct:`Enumerator`
:union:`Enumerator`
:func:`Enumerator`
:member:`Enumerator`
:var:`Enumerator`
:type:`Enumerator`
:concept:`Enumerator`
:enum:`Enumerator`
enumerator
.. class:: template<typename TParamType, \
int TParamVar, \
template<typename> typename TParamTemplate \
> ClassTemplate
class
struct
union
func
member
var
type
concept
enum
enumerator
class
struct
union
func
member
var
type
concept
enum
enumerator
class
struct
union
func
member
var
type
concept
enum
enumerator
.. function:: void FunctionParams(int FunctionParam)
:class:`FunctionParam`
:struct:`FunctionParam`
:union:`FunctionParam`
:func:`FunctionParam`
member
var
:type:`FunctionParam`
:concept:`FunctionParam`
:enum:`FunctionParam`
:enumerator:`FunctionParam`

View File

@ -786,11 +786,59 @@ def test_xref_parsing():
# raise DefinitionError("")
def filter_warnings(warning, file):
lines = warning.getvalue().split("\n");
res = [l for l in lines if "domain-cpp" in l and "{}.rst".format(file) in l and
"WARNING: document isn't included in any toctree" not in l]
print("Filtered warnings for file '{}':".format(file))
for w in res:
print(w)
return res
@pytest.mark.sphinx(testroot='domain-cpp')
def test_build_domain_cpp_misuse_of_roles(app, status, warning):
app.builder.build_all()
ws = filter_warnings(warning, "roles-targets-ok")
assert len(ws) == 0
# TODO: properly check for the warnings we expect
ws = filter_warnings(warning, "roles-targets-warn")
# the roles that should be able to generate warnings:
allRoles = ['class', 'struct', 'union', 'func', 'member', 'var', 'type', 'concept', 'enum', 'enumerator']
ok = [ # targetType, okRoles
('class', ['class', 'struct', 'type']),
('union', ['union', 'type']),
('func', ['func', 'type']),
('member', ['member', 'var']),
('type', ['type']),
('concept', ['concept']),
('enum', ['type', 'enum']),
('enumerator', ['enumerator']),
('tParam', ['class', 'struct', 'union', 'func', 'member', 'var', 'type', 'concept', 'enum', 'enumerator', 'functionParam']),
('functionParam', ['member', 'var']),
]
warn = []
for targetType, roles in ok:
txtTargetType = "function" if targetType == "func" else targetType
for r in allRoles:
if r not in roles:
warn.append("WARNING: cpp:{} targets a {} (".format(r, txtTargetType))
warn = list(sorted(warn))
for w in ws:
assert "targets a" in w
ws = [w[w.index("WARNING:"):] for w in ws]
ws = list(sorted(ws))
print("Expected warnings:")
for w in warn:
print(w)
print("Actual warnings:")
for w in ws:
print(w)
for i in range(min(len(warn), len(ws))):
assert ws[i].startswith(warn[i])
assert len(ws) == len(warn)
@pytest.mark.skipif(docutils.__version_info__ < (0, 13),