Skip to content

Commit 87d9d3a

Browse files
committed
C, warn on tag mismatch
1 parent 0b526ed commit 87d9d3a

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

sphinx/domains/c.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3784,6 +3784,22 @@ def _resolve_xref_inner(self, env: BuildEnvironment, fromdocname: str, builder:
37843784
return None, None
37853785
# TODO: conditionally warn about xrefs with incorrect tagging?
37863786

3787+
# check if tags are used correctly
3788+
sName = s.get_full_nested_name()
3789+
assert len(name.names) <= len(sName.names)
3790+
for n, ns in zip(reversed(name.names), reversed(sName.names)):
3791+
if n.tag is None:
3792+
continue
3793+
assert ns.tag is not None
3794+
assert (n.tag == '') == (ns.tag == '')
3795+
if n.tag != ns.tag:
3796+
logger.warning(
3797+
"C '%s' cross-reference uses wrong tag:"
3798+
" reference name is '%s' but found name is '%s'."
3799+
" Full reference name is '%s'."
3800+
" Full found name is '%s'.",
3801+
typ, n, ns, name, sName, location=node)
3802+
37873803
# TODO: check role type vs. object type
37883804

37893805
declaration = s.declaration
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
.. c:namespace:: @wrong_tag
2+
3+
.. c:struct:: A
4+
5+
.. c:var:: int i
6+
7+
- :c:var:`A.i`
8+
- :c:var:`union A.i`
9+
- :c:var:`enum A.i`
10+
11+
.. c:function:: void f1(union A a)
12+
.. c:function:: void f2(enum A a)
13+
14+
.. c:var:: int union A.j

tests/test_domain_c.py

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -688,6 +688,26 @@ def test_duplicate_tags(app, warning):
688688
assert "Declaration is '.. c:enum:: A'." in ws[3]
689689

690690

691+
@pytest.mark.sphinx(testroot='domain-c', confoverrides={'nitpicky': True})
692+
def test_build_domain_c_wrong_tags(app, warning):
693+
app.builder.build_all()
694+
ws = filter_warnings(warning, "wrong-tags")
695+
template = ".rst:%d: WARNING: C '%s' cross-reference uses wrong tag:"\
696+
" reference name is '%s' but found name is '%s'."\
697+
" Full reference name is '%s'."\
698+
" Full found name is '%s'."
699+
expected = [
700+
template % (8, 'var', 'union A', 'struct A', 'union A.i', '@wrong_tag.struct A.i'),
701+
template % (9, 'var', 'enum A', 'struct A', 'enum A.i', '@wrong_tag.struct A.i'),
702+
template % (11, 'identifier', 'union A', 'struct A', 'union A', '@wrong_tag.struct A'),
703+
template % (13, 'identifier', 'enum A', 'struct A', 'enum A', '@wrong_tag.struct A'),
704+
template % (14, 'identifier', 'union A', 'struct A', 'union A', '@wrong_tag.struct A'),
705+
]
706+
for i in range(len(expected)):
707+
assert expected[i] in ws[i]
708+
assert len(ws) == len(expected)
709+
710+
691711
def test_build_domain_c_semicolon(app, warning):
692712
text = """
693713
.. c:member:: int member;

0 commit comments

Comments
 (0)