diff --git a/sphinx/directives/__init__.py b/sphinx/directives/__init__.py index 2656cc99b79..e3829001602 100644 --- a/sphinx/directives/__init__.py +++ b/sphinx/directives/__init__.py @@ -157,6 +157,17 @@ def run(self) -> List[Node]: node = addnodes.desc() node.document = self.state.document + source, line = self.get_source_info() + # If any options were specified to the directive, + # self.state.document.current_line will at this point be set to + # None. To ensure nodes created as part of the signature have a line + # number set, set the document's line number correctly. + # + # Note that we need to subtract one from the line number since + # note_source uses 0-based line numbers. + if line is not None: + line -= 1 + self.state.document.note_source(source, line) node['domain'] = self.domain # 'desctype' is a backwards compatible attribute node['objtype'] = node['desctype'] = self.objtype diff --git a/tests/test_domain_py.py b/tests/test_domain_py.py index ce1636eb28e..26f12e48ceb 100644 --- a/tests/test_domain_py.py +++ b/tests/test_domain_py.py @@ -4,6 +4,7 @@ import sys from unittest.mock import Mock +import docutils.utils import pytest from docutils import nodes @@ -1372,3 +1373,16 @@ def test_warn_missing_reference(app, status, warning): assert "index.rst:6: WARNING: undefined label: 'no-label'" in warning.getvalue() assert ("index.rst:6: WARNING: Failed to create a cross reference. " "A title or caption not found: 'existing-label'") in warning.getvalue() + + +@pytest.mark.sphinx(confoverrides={'nitpicky': True}) +@pytest.mark.parametrize('include_options', (True, False)) +def test_signature_line_number(app, include_options): + text = (".. py:function:: foo(bar : string)\n" + + (" :noindexentry:\n" if include_options else "")) + doc = restructuredtext.parse(app, text) + xrefs = list(doc.findall(condition=addnodes.pending_xref)) + assert len(xrefs) == 1 + source, line = docutils.utils.get_source_line(xrefs[0]) + assert 'index.rst' in source + assert line == 1