Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add :noindexentry: option #7906

Merged
merged 2 commits into from Jul 5, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
3 changes: 3 additions & 0 deletions CHANGES
Expand Up @@ -17,6 +17,9 @@ Features added
* #7888: napoleon: Add aliases Warn and Raise.
* C, added :rst:dir:`c:alias` directive for inserting copies
of existing declarations.
* #7052: add ``:noindexentry:`` to the Python, C, C++, and Javascript domains.
Update the documentation to better reflect the relationship between this option
and the ``:noindex:`` option.

Bugs fixed
----------
Expand Down
20 changes: 17 additions & 3 deletions doc/usage/restructuredtext/domains.rst
Expand Up @@ -42,9 +42,22 @@ Basic Markup
Most domains provide a number of :dfn:`object description directives`, used to
describe specific objects provided by modules. Each directive requires one or
more signatures to provide basic information about what is being described, and
the content should be the description. The basic version makes entries in the
general index; if no index entry is desired, you can give the directive option
flag ``:noindex:``. An example using a Python domain directive::
the content should be the description. A domain will typically keep an
internal index of all entites to aid cross-referencing. Typically it will
also add entries in the shown general index.
If you want to suppress the addition of an entry in the shown index, you can
give the directive option flag ``:noindexentry:``.
If you want to typeset an object description, without even making it available
for cross-referencing, you can give the directive option flag ``:noindex:``
(which implies ``:noindexentry:``).
Though, note that not every directive en every domain may support these
options.

.. versionadded:: 3.2
The directive option ``noindexentry`` in the Python, C, C++, and Javascript
domains.

An example using a Python domain directive::

.. py:function:: spam(eggs)
ham(eggs)
Expand Down Expand Up @@ -1073,6 +1086,7 @@ Options

Some directives support options:

- ``:noindexentry:``, see :ref:`basic-domain-markup`.
- ``:tparam-line-spec:``, for templated declarations.
If specified, each template parameter will be rendered on a separate line.

Expand Down
11 changes: 5 additions & 6 deletions sphinx/domains/c.py
Expand Up @@ -16,6 +16,7 @@

from docutils import nodes
from docutils.nodes import Element, Node, TextElement, system_message
from docutils.parsers.rst import directives

from sphinx import addnodes
from sphinx.addnodes import pending_xref
Expand Down Expand Up @@ -3023,10 +3024,7 @@ class CObject(ObjectDescription):
]

option_spec = {
# have a dummy option to ensure proper errors on options,
# otherwise the option is taken as a continuation of the
# argument
'dummy': None
'noindexentry': directives.flag,
}

def _add_enumerator_to_parent(self, ast: ASTDeclaration) -> None:
Expand Down Expand Up @@ -3098,8 +3096,9 @@ def add_target_and_index(self, ast: ASTDeclaration, sig: str,
if name not in domain.objects:
domain.objects[name] = (domain.env.docname, newestId, self.objtype)

indexText = self.get_index_text(name)
self.indexnode['entries'].append(('single', indexText, newestId, '', None))
if 'noindexentry' not in self.options:
indexText = self.get_index_text(name)
self.indexnode['entries'].append(('single', indexText, newestId, '', None))

@property
def object_type(self) -> str:
Expand Down
3 changes: 2 additions & 1 deletion sphinx/domains/cpp.py
Expand Up @@ -6625,6 +6625,7 @@ class CPPObject(ObjectDescription):
]

option_spec = {
'noindexentry': directives.flag,
'tparam-line-spec': directives.flag,
}

Expand Down Expand Up @@ -6701,7 +6702,7 @@ def add_target_and_index(self, ast: ASTDeclaration, sig: str,
if decl.objectType == 'concept':
isInConcept = True
break
if not isInConcept:
if not isInConcept and 'noindexentry' not in self.options:
strippedName = name
for prefix in self.env.config.cpp_index_common_prefix:
if name.startswith(prefix):
Expand Down
12 changes: 9 additions & 3 deletions sphinx/domains/javascript.py
Expand Up @@ -49,6 +49,11 @@ class JSObject(ObjectDescription):
#: based on directive nesting
allow_nesting = False

option_spec = {
'noindex': directives.flag,
'noindexentry': directives.flag,
}

def handle_signature(self, sig: str, signode: desc_signature) -> Tuple[str, str]:
"""Breaks down construct signatures

Expand Down Expand Up @@ -120,9 +125,10 @@ def add_target_and_index(self, name_obj: Tuple[str, str], sig: str,
domain = cast(JavaScriptDomain, self.env.get_domain('js'))
domain.note_object(fullname, self.objtype, node_id, location=signode)

indextext = self.get_index_text(mod_name, name_obj)
if indextext:
self.indexnode['entries'].append(('single', indextext, node_id, '', None))
if 'noindexentry' not in self.options:
indextext = self.get_index_text(mod_name, name_obj)
if indextext:
self.indexnode['entries'].append(('single', indextext, node_id, '', None))

def get_index_text(self, objectname: str, name_obj: Tuple[str, str]) -> str:
name, obj = name_obj
Expand Down
27 changes: 15 additions & 12 deletions sphinx/domains/python.py
Expand Up @@ -317,6 +317,7 @@ class PyObject(ObjectDescription):
"""
option_spec = {
'noindex': directives.flag,
'noindexentry': directives.flag,
'module': directives.unchanged,
'annotation': directives.unchanged,
}
Expand Down Expand Up @@ -459,9 +460,10 @@ def add_target_and_index(self, name_cls: Tuple[str, str], sig: str,
domain = cast(PythonDomain, self.env.get_domain('py'))
domain.note_object(fullname, self.objtype, node_id, location=signode)

indextext = self.get_index_text(modname, name_cls)
if indextext:
self.indexnode['entries'].append(('single', indextext, node_id, '', None))
if 'noindexentry' not in self.options:
indextext = self.get_index_text(modname, name_cls)
if indextext:
self.indexnode['entries'].append(('single', indextext, node_id, '', None))

def before_content(self) -> None:
"""Handle object nesting before content
Expand Down Expand Up @@ -576,16 +578,17 @@ def needs_arglist(self) -> bool:
def add_target_and_index(self, name_cls: Tuple[str, str], sig: str,
signode: desc_signature) -> None:
super().add_target_and_index(name_cls, sig, signode)
modname = self.options.get('module', self.env.ref_context.get('py:module'))
node_id = signode['ids'][0]
if 'noindexentry' not in self.options:
modname = self.options.get('module', self.env.ref_context.get('py:module'))
node_id = signode['ids'][0]

name, cls = name_cls
if modname:
text = _('%s() (in module %s)') % (name, modname)
self.indexnode['entries'].append(('single', text, node_id, '', None))
else:
text = '%s; %s()' % (pairindextypes['builtin'], name)
self.indexnode['entries'].append(('pair', text, node_id, '', None))
name, cls = name_cls
if modname:
text = _('%s() (in module %s)') % (name, modname)
self.indexnode['entries'].append(('single', text, node_id, '', None))
else:
text = '%s; %s()' % (pairindextypes['builtin'], name)
self.indexnode['entries'].append(('pair', text, node_id, '', None))

def get_index_text(self, modname: str, name_cls: Tuple[str, str]) -> str:
# add index in own add_target_and_index() instead.
Expand Down
11 changes: 11 additions & 0 deletions tests/test_domain_c.py
Expand Up @@ -10,6 +10,7 @@
import pytest

from sphinx import addnodes
from sphinx.addnodes import desc
from sphinx.domains.c import DefinitionParser, DefinitionError
from sphinx.domains.c import _max_id, _id_prefix, Symbol
from sphinx.testing import restructuredtext
Expand Down Expand Up @@ -590,3 +591,13 @@ def test_cvar(app):
domain = app.env.get_domain('c')
entry = domain.objects.get('PyClass_Type')
assert entry == ('index', 'c.PyClass_Type', 'var')


def test_noindexentry(app):
text = (".. c:function:: void f()\n"
".. c:function:: void g()\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
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=[])
13 changes: 13 additions & 0 deletions tests/test_domain_cpp.py
Expand Up @@ -14,8 +14,11 @@

import sphinx.domains.cpp as cppDomain
from sphinx import addnodes
from sphinx.addnodes import desc
from sphinx.domains.cpp import DefinitionParser, DefinitionError, NoOldIdError
from sphinx.domains.cpp import Symbol, _max_id, _id_prefix
from sphinx.testing import restructuredtext
from sphinx.testing.util import assert_node
from sphinx.util import docutils


Expand Down Expand Up @@ -1211,3 +1214,13 @@ def __init__(self, role, root, contents):
assert any_role.classes == cpp_any_role.classes, expect
assert any_role.classes == expr_role.content_classes['a'], expect
assert any_role.classes == texpr_role.content_classes['a'], expect


def test_noindexentry(app):
text = (".. cpp:function:: void f()\n"
".. cpp:function:: void g()\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('single', 'f (C++ function)', '_CPPv41fv', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])
10 changes: 10 additions & 0 deletions tests/test_domain_js.py
Expand Up @@ -218,3 +218,13 @@ def test_js_data(app):
assert_node(doctree[0], addnodes.index,
entries=[("single", "name (global variable or constant)", "name", "", None)])
assert_node(doctree[1], addnodes.desc, domain="js", objtype="data", noindex=False)


def test_noindexentry(app):
text = (".. js:function:: f()\n"
".. js:function:: g()\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('single', 'f() (built-in function)', 'f', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])
16 changes: 16 additions & 0 deletions tests/test_domain_py.py
Expand Up @@ -799,3 +799,19 @@ def test_modindex_common_prefix(app):
)


def test_noindexentry(app):
text = (".. py:function:: f()\n"
".. py:function:: g()\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('pair', 'built-in function; f()', 'f', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])

text = (".. py:class:: f\n"
".. py:class:: g\n"
" :noindexentry:\n")
doctree = restructuredtext.parse(app, text)
assert_node(doctree, (addnodes.index, desc, addnodes.index, desc))
assert_node(doctree[0], addnodes.index, entries=[('single', 'f (built-in class)', 'f', '', None)])
assert_node(doctree[2], addnodes.index, entries=[])