mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
intersphinx role: new inventory parsing from role name
This commit is contained in:
parent
ce5512e3af
commit
029d0e5b18
@ -489,9 +489,15 @@ class IntersphinxDispatcher(CustomReSTDispatcher):
|
||||
|
||||
class IntersphinxRole(SphinxRole):
|
||||
def run(self) -> Tuple[List[Node], List[system_message]]:
|
||||
role_name = self.get_role_name(self.name)
|
||||
inventory, name_suffix = self.get_inventory_and_name_suffix(self.name)
|
||||
if inventory and not inventory_exists(self.env, inventory):
|
||||
logger.warning(__('inventory for external cross-reference not found: %s'), inventory,
|
||||
location=(self.env.docname, self.lineno))
|
||||
return [], []
|
||||
|
||||
role_name = self.get_role_name(name_suffix)
|
||||
if role_name is None:
|
||||
logger.warning(__('role not found: %s'), self.name,
|
||||
logger.warning(__('role for external cross-reference not found: %s'), name_suffix,
|
||||
location=(self.env.docname, self.lineno))
|
||||
return [], []
|
||||
|
||||
@ -499,20 +505,33 @@ class IntersphinxRole(SphinxRole):
|
||||
for node in result:
|
||||
if isinstance(node, pending_xref):
|
||||
node['intersphinx'] = True
|
||||
node['inventory'] = None
|
||||
node['inventory'] = inventory
|
||||
|
||||
return result, messages
|
||||
|
||||
def get_inventory_and_name_suffix(self, name: str) -> Tuple[Optional[str], Optional[str]]:
|
||||
assert name.startswith('external:'), name
|
||||
name = name[9:]
|
||||
inv_names = name.split('+')
|
||||
inventory = None
|
||||
if len(inv_names) > 1:
|
||||
# inv+role
|
||||
# inv+domain:role
|
||||
inventory = inv_names[0]
|
||||
name = name[len(inventory)+1:]
|
||||
return inventory, name
|
||||
|
||||
def get_role_name(self, name: str) -> Optional[Tuple[str, str]]:
|
||||
names = name.split(':')
|
||||
if len(names) == 2:
|
||||
# :external:role:
|
||||
domain = self.env.temp_data.get('default_domain')
|
||||
if len(names) == 1:
|
||||
# role
|
||||
default_domain = self.env.temp_data.get('default_domain')
|
||||
domain = default_domain.name if default_domain else None
|
||||
role = names[0]
|
||||
elif len(names) == 2:
|
||||
# domain:role:
|
||||
domain = names[0]
|
||||
role = names[1]
|
||||
elif len(names) == 3:
|
||||
# :external:domain:role:
|
||||
domain = names[1]
|
||||
role = names[2]
|
||||
else:
|
||||
return None
|
||||
|
||||
@ -559,8 +578,7 @@ class IntersphinxRoleResolver(ReferencesResolver):
|
||||
contnode = cast(nodes.TextElement, node[0].deepcopy())
|
||||
inv_name = node['inventory']
|
||||
if inv_name is not None:
|
||||
if not inventory_exists(self.env, inv_name):
|
||||
continue
|
||||
assert inventory_exists(self.env, inv_name)
|
||||
newnode = resolve_reference_in_inventory(self.env, inv_name, node, contnode)
|
||||
else:
|
||||
newnode = resolve_reference_any_inventory(self.env, False, node, contnode)
|
||||
|
@ -14,8 +14,31 @@
|
||||
- ``module10`` is only defined here, but should still not be resolved to:
|
||||
:external:py:mod:`module10`
|
||||
|
||||
|
||||
- a function in inv:
|
||||
:external:py:func:`module1.func`
|
||||
- a method, but with old style inventory prefix, which shouldn't work:
|
||||
:external:py:meth:`inv:Foo.bar`
|
||||
- a non-existing role:
|
||||
:external:py:nope:`something`
|
||||
|
||||
.. default-domain:: cpp
|
||||
|
||||
- a type where the default domain is used to find the role:
|
||||
:external:type:`std::uint8_t`
|
||||
- a non-existing role in default domain:
|
||||
:external:nope:`somethingElse`
|
||||
|
||||
- two roles in ``std`` which can be found without a default domain:
|
||||
|
||||
- :external:doc:`docname`
|
||||
- :external:option:`ls -l`
|
||||
|
||||
|
||||
- a function with explicit inventory:
|
||||
:external:inv+c:func:`CFunc`
|
||||
- a class with explicit non-existing inventory, which also has upper-case in name:
|
||||
:external:invNope+cpp:class:`foo::Bar`
|
||||
|
||||
|
||||
- explicit title:
|
||||
:external:cpp:type:`FoonsTitle <foons>`
|
||||
|
@ -552,3 +552,20 @@ def test_intersphinx_role(app, warning):
|
||||
|
||||
assert html.format('sub/foo.html#module1.func') in content
|
||||
assert "WARNING: external py:meth reference target not found: inv:Foo.bar" in wStr
|
||||
|
||||
assert "WARNING: role for external cross-reference not found: py:nope" in wStr
|
||||
|
||||
# default domain
|
||||
assert html.format('index.html#std_uint8_t') in content
|
||||
assert "WARNING: role for external cross-reference not found: nope" in wStr
|
||||
|
||||
# std roles without domain prefix
|
||||
assert html.format('docname.html') in content
|
||||
assert html.format('index.html#cmdoption-ls-l') in content
|
||||
|
||||
# explicit inventory
|
||||
assert html.format('cfunc.html#CFunc') in content
|
||||
#assert "WARNING: inventory for external cross-reference not found: invNope" in wStr
|
||||
|
||||
# explicit title
|
||||
assert html.format('index.html#foons') in content
|
||||
|
Loading…
Reference in New Issue
Block a user