mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2026-09-03 20:52:55 -05:00
Merge pull request #7882 from jakobandersen/c_alias
C, add c:alias directive
This commit is contained in:
@@ -15,6 +15,8 @@ Features added
|
|||||||
|
|
||||||
* #7853: C and C++, support parameterized GNU style attributes.
|
* #7853: C and C++, support parameterized GNU style attributes.
|
||||||
* #7888: napoleon: Add aliases Warn and Raise.
|
* #7888: napoleon: Add aliases Warn and Raise.
|
||||||
|
* C, added :rst:dir:`c:alias` directive for inserting copies
|
||||||
|
of existing declarations.
|
||||||
|
|
||||||
Bugs fixed
|
Bugs fixed
|
||||||
----------
|
----------
|
||||||
|
|||||||
@@ -699,6 +699,41 @@ Explicit ref: :c:var:`Data.@data.a`. Short-hand ref: :c:var:`Data.a`.
|
|||||||
.. versionadded:: 3.0
|
.. versionadded:: 3.0
|
||||||
|
|
||||||
|
|
||||||
|
Aliasing Declarations
|
||||||
|
~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
.. c:namespace-push:: @alias
|
||||||
|
|
||||||
|
Sometimes it may be helpful list declarations elsewhere than their main
|
||||||
|
documentation, e.g., when creating a synopsis of an interface.
|
||||||
|
The following directive can be used for this purpose.
|
||||||
|
|
||||||
|
.. rst:directive:: .. c:alias:: name
|
||||||
|
|
||||||
|
Insert one or more alias declarations. Each entity can be specified
|
||||||
|
as they can in the :rst:role:`c:any` role.
|
||||||
|
|
||||||
|
For example::
|
||||||
|
|
||||||
|
.. c:var:: int data
|
||||||
|
.. c:function:: int f(double k)
|
||||||
|
|
||||||
|
.. c:alias:: data
|
||||||
|
f
|
||||||
|
|
||||||
|
becomes
|
||||||
|
|
||||||
|
.. c:var:: int data
|
||||||
|
.. c:function:: int f(double k)
|
||||||
|
|
||||||
|
.. c:alias:: data
|
||||||
|
f
|
||||||
|
|
||||||
|
.. versionadded:: 3.2
|
||||||
|
|
||||||
|
.. c:namespace-pop::
|
||||||
|
|
||||||
|
|
||||||
Inline Expressions and Types
|
Inline Expressions and Types
|
||||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||||
|
|
||||||
|
|||||||
+107
-1
@@ -10,7 +10,7 @@
|
|||||||
|
|
||||||
import re
|
import re
|
||||||
from typing import (
|
from typing import (
|
||||||
Any, Callable, Dict, Generator, Iterator, List, Type, Tuple, Union
|
Any, Callable, Dict, Generator, Iterator, List, Type, TypeVar, Tuple, Union
|
||||||
)
|
)
|
||||||
from typing import cast
|
from typing import cast
|
||||||
|
|
||||||
@@ -26,6 +26,8 @@ from sphinx.domains import Domain, ObjType
|
|||||||
from sphinx.environment import BuildEnvironment
|
from sphinx.environment import BuildEnvironment
|
||||||
from sphinx.locale import _, __
|
from sphinx.locale import _, __
|
||||||
from sphinx.roles import SphinxRole, XRefRole
|
from sphinx.roles import SphinxRole, XRefRole
|
||||||
|
from sphinx.transforms import SphinxTransform
|
||||||
|
from sphinx.transforms.post_transforms import ReferencesResolver
|
||||||
from sphinx.util import logging
|
from sphinx.util import logging
|
||||||
from sphinx.util.cfamily import (
|
from sphinx.util.cfamily import (
|
||||||
NoOldIdError, ASTBaseBase, ASTBaseParenExprList,
|
NoOldIdError, ASTBaseBase, ASTBaseParenExprList,
|
||||||
@@ -41,6 +43,7 @@ from sphinx.util.docutils import SphinxDirective
|
|||||||
from sphinx.util.nodes import make_refnode
|
from sphinx.util.nodes import make_refnode
|
||||||
|
|
||||||
logger = logging.getLogger(__name__)
|
logger = logging.getLogger(__name__)
|
||||||
|
T = TypeVar('T')
|
||||||
|
|
||||||
# https://en.cppreference.com/w/c/keyword
|
# https://en.cppreference.com/w/c/keyword
|
||||||
_keywords = [
|
_keywords = [
|
||||||
@@ -3311,6 +3314,106 @@ class CNamespacePopObject(SphinxDirective):
|
|||||||
return []
|
return []
|
||||||
|
|
||||||
|
|
||||||
|
class AliasNode(nodes.Element):
|
||||||
|
def __init__(self, sig: str, env: "BuildEnvironment" = None,
|
||||||
|
parentKey: LookupKey = None) -> None:
|
||||||
|
super().__init__()
|
||||||
|
self.sig = sig
|
||||||
|
if env is not None:
|
||||||
|
if 'c:parent_symbol' not in env.temp_data:
|
||||||
|
root = env.domaindata['c']['root_symbol']
|
||||||
|
env.temp_data['c:parent_symbol'] = root
|
||||||
|
self.parentKey = env.temp_data['c:parent_symbol'].get_lookup_key()
|
||||||
|
else:
|
||||||
|
assert parentKey is not None
|
||||||
|
self.parentKey = parentKey
|
||||||
|
|
||||||
|
def copy(self: T) -> T:
|
||||||
|
return self.__class__(self.sig, env=None, parentKey=self.parentKey) # type: ignore
|
||||||
|
|
||||||
|
|
||||||
|
class AliasTransform(SphinxTransform):
|
||||||
|
default_priority = ReferencesResolver.default_priority - 1
|
||||||
|
|
||||||
|
def apply(self, **kwargs: Any) -> None:
|
||||||
|
for node in self.document.traverse(AliasNode):
|
||||||
|
sig = node.sig
|
||||||
|
parentKey = node.parentKey
|
||||||
|
try:
|
||||||
|
parser = DefinitionParser(sig, location=node,
|
||||||
|
config=self.env.config)
|
||||||
|
name = parser.parse_xref_object()
|
||||||
|
except DefinitionError as e:
|
||||||
|
logger.warning(e, location=node)
|
||||||
|
name = None
|
||||||
|
|
||||||
|
if name is None:
|
||||||
|
# could not be parsed, so stop here
|
||||||
|
signode = addnodes.desc_signature(sig, '')
|
||||||
|
signode.clear()
|
||||||
|
signode += addnodes.desc_name(sig, sig)
|
||||||
|
node.replace_self(signode)
|
||||||
|
continue
|
||||||
|
|
||||||
|
rootSymbol = self.env.domains['c'].data['root_symbol'] # type: Symbol
|
||||||
|
parentSymbol = rootSymbol.direct_lookup(parentKey) # type: Symbol
|
||||||
|
if not parentSymbol:
|
||||||
|
print("Target: ", sig)
|
||||||
|
print("ParentKey: ", parentKey)
|
||||||
|
print(rootSymbol.dump(1))
|
||||||
|
assert parentSymbol # should be there
|
||||||
|
|
||||||
|
s = parentSymbol.find_declaration(
|
||||||
|
name, 'any',
|
||||||
|
matchSelf=True, recurseInAnon=True)
|
||||||
|
if s is None:
|
||||||
|
signode = addnodes.desc_signature(sig, '')
|
||||||
|
node.append(signode)
|
||||||
|
signode.clear()
|
||||||
|
signode += addnodes.desc_name(sig, sig)
|
||||||
|
|
||||||
|
logger.warning("Could not find C declaration for alias '%s'." % name,
|
||||||
|
location=node)
|
||||||
|
node.replace_self(signode)
|
||||||
|
else:
|
||||||
|
nodes = []
|
||||||
|
options = dict() # type: ignore
|
||||||
|
signode = addnodes.desc_signature(sig, '')
|
||||||
|
nodes.append(signode)
|
||||||
|
s.declaration.describe_signature(signode, 'markName', self.env, options)
|
||||||
|
node.replace_self(nodes)
|
||||||
|
|
||||||
|
|
||||||
|
class CAliasObject(ObjectDescription):
|
||||||
|
option_spec = {} # type: Dict
|
||||||
|
|
||||||
|
def run(self) -> List[Node]:
|
||||||
|
if ':' in self.name:
|
||||||
|
self.domain, self.objtype = self.name.split(':', 1)
|
||||||
|
else:
|
||||||
|
self.domain, self.objtype = '', self.name
|
||||||
|
|
||||||
|
node = addnodes.desc()
|
||||||
|
node.document = self.state.document
|
||||||
|
node['domain'] = self.domain
|
||||||
|
# 'desctype' is a backwards compatible attribute
|
||||||
|
node['objtype'] = node['desctype'] = self.objtype
|
||||||
|
node['noindex'] = True
|
||||||
|
|
||||||
|
self.names = [] # type: List[str]
|
||||||
|
signatures = self.get_signatures()
|
||||||
|
for i, sig in enumerate(signatures):
|
||||||
|
node.append(AliasNode(sig, env=self.env))
|
||||||
|
|
||||||
|
contentnode = addnodes.desc_content()
|
||||||
|
node.append(contentnode)
|
||||||
|
self.before_content()
|
||||||
|
self.state.nested_parse(self.content, self.content_offset, contentnode)
|
||||||
|
self.env.temp_data['object'] = None
|
||||||
|
self.after_content()
|
||||||
|
return [node]
|
||||||
|
|
||||||
|
|
||||||
class CXRefRole(XRefRole):
|
class CXRefRole(XRefRole):
|
||||||
def process_link(self, env: BuildEnvironment, refnode: Element,
|
def process_link(self, env: BuildEnvironment, refnode: Element,
|
||||||
has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
has_explicit_title: bool, title: str, target: str) -> Tuple[str, str]:
|
||||||
@@ -3394,6 +3497,8 @@ class CDomain(Domain):
|
|||||||
'namespace': CNamespaceObject,
|
'namespace': CNamespaceObject,
|
||||||
'namespace-push': CNamespacePushObject,
|
'namespace-push': CNamespacePushObject,
|
||||||
'namespace-pop': CNamespacePopObject,
|
'namespace-pop': CNamespacePopObject,
|
||||||
|
# other
|
||||||
|
'alias': CAliasObject
|
||||||
}
|
}
|
||||||
roles = {
|
roles = {
|
||||||
'member': CXRefRole(),
|
'member': CXRefRole(),
|
||||||
@@ -3541,6 +3646,7 @@ def setup(app: Sphinx) -> Dict[str, Any]:
|
|||||||
app.add_domain(CDomain)
|
app.add_domain(CDomain)
|
||||||
app.add_config_value("c_id_attributes", [], 'env')
|
app.add_config_value("c_id_attributes", [], 'env')
|
||||||
app.add_config_value("c_paren_attributes", [], 'env')
|
app.add_config_value("c_paren_attributes", [], 'env')
|
||||||
|
app.add_post_transform(AliasTransform)
|
||||||
|
|
||||||
return {
|
return {
|
||||||
'version': 'builtin',
|
'version': 'builtin',
|
||||||
|
|||||||
Reference in New Issue
Block a user