mirror of
https://github.com/sphinx-doc/sphinx.git
synced 2025-02-25 18:55:22 -06:00
Add nesting, module directive, and method directive to JavaScript domain
* Adds nesting to the JavaScript domain, to allow for nesting of elements * Adds the ``js:module`` directive, which behaves similarly to the Python directive * Adds the ``js:method`` directive, an alias to ``js:function`` * Adds roles for ``js:mod`` and ``js:meth`` * Updates tests to passing cases * Adds docs for new features
This commit is contained in:
parent
b7cada236f
commit
3ba60ffd5d
@ -1103,6 +1103,22 @@ The JavaScript Domain
|
||||
|
||||
The JavaScript domain (name **js**) provides the following directives:
|
||||
|
||||
.. rst:directive:: .. js:module:: name
|
||||
|
||||
This directive sets the module name for object declarations that follow
|
||||
after. The module name is used in the global module index and in cross
|
||||
references. This directive does not create an object heading like
|
||||
:rst:dir:`py:class` would, for example.
|
||||
|
||||
By default, this directive will create a linkable entity and will cause an
|
||||
entry in the global module index, unless the ``noindex`` option is specified.
|
||||
If this option is specified, the directive will only update the current
|
||||
module name.
|
||||
|
||||
To clear the current module, set the module name to ``null`` or ``None``
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
.. rst:directive:: .. js:function:: name(signature)
|
||||
|
||||
Describes a JavaScript function or method. If you want to describe
|
||||
@ -1135,6 +1151,13 @@ The JavaScript domain (name **js**) provides the following directives:
|
||||
:throws SomeError: For whatever reason in that case.
|
||||
:returns: Something.
|
||||
|
||||
.. rst:directive:: .. js:method:: name(signature)
|
||||
|
||||
This directive is an alias for :rst:dir:`js:function`, however it describes a
|
||||
function that is implemented as a method on a class object.
|
||||
|
||||
.. versionadded:: 1.6
|
||||
|
||||
.. rst:directive:: .. js:class:: name
|
||||
|
||||
Describes a constructor that creates an object. This is basically like
|
||||
@ -1164,7 +1187,9 @@ The JavaScript domain (name **js**) provides the following directives:
|
||||
|
||||
These roles are provided to refer to the described objects:
|
||||
|
||||
.. rst:role:: js:func
|
||||
.. rst:role:: js:mod
|
||||
js:func
|
||||
js:meth
|
||||
js:class
|
||||
js:data
|
||||
js:attr
|
||||
|
@ -9,6 +9,9 @@
|
||||
:license: BSD, see LICENSE for details.
|
||||
"""
|
||||
|
||||
from docutils import nodes
|
||||
from docutils.parsers.rst import Directive, directives
|
||||
|
||||
from sphinx import addnodes
|
||||
from sphinx.domains import Domain, ObjType
|
||||
from sphinx.locale import l_, _
|
||||
@ -38,57 +41,68 @@ class JSObject(ObjectDescription):
|
||||
#: what is displayed right before the documentation entry
|
||||
display_prefix = None # type: unicode
|
||||
|
||||
#: If ``allow_nesting`` is ``True``, the object prefixes will be accumulated
|
||||
#: based on directive nesting
|
||||
allow_nesting = False
|
||||
|
||||
def handle_signature(self, sig, signode):
|
||||
# type: (unicode, addnodes.desc_signature) -> Tuple[unicode, unicode]
|
||||
"""Breaks down construct signatures
|
||||
|
||||
Parses out prefix and argument list from construct definition. The
|
||||
namespace and class will be determined by the nesting of domain
|
||||
directives.
|
||||
"""
|
||||
sig = sig.strip()
|
||||
if '(' in sig and sig[-1:] == ')':
|
||||
prefix, arglist = sig.split('(', 1)
|
||||
prefix = prefix.strip()
|
||||
member, arglist = sig.split('(', 1)
|
||||
member = member.strip()
|
||||
arglist = arglist[:-1].strip()
|
||||
else:
|
||||
prefix = sig
|
||||
member = sig
|
||||
arglist = None
|
||||
if '.' in prefix:
|
||||
nameprefix, name = prefix.rsplit('.', 1)
|
||||
else:
|
||||
nameprefix = None
|
||||
name = prefix
|
||||
# If construct is nested, prefix the current prefix
|
||||
prefix = self.env.ref_context.get('js:object', None)
|
||||
mod_name = self.env.ref_context.get('js:module')
|
||||
name = member
|
||||
try:
|
||||
member_prefix, member_name = member.rsplit('.', 1)
|
||||
except ValueError:
|
||||
member_name = name
|
||||
member_prefix = ''
|
||||
finally:
|
||||
name = member_name
|
||||
if prefix and member_prefix:
|
||||
prefix = '.'.join([prefix, member_prefix])
|
||||
elif prefix is None and member_prefix:
|
||||
prefix = member_prefix
|
||||
fullname = name
|
||||
if prefix:
|
||||
fullname = '.'.join([prefix, name])
|
||||
|
||||
objectname = self.env.ref_context.get('js:object')
|
||||
if nameprefix:
|
||||
if objectname:
|
||||
# someone documenting the method of an attribute of the current
|
||||
# object? shouldn't happen but who knows...
|
||||
nameprefix = objectname + '.' + nameprefix
|
||||
fullname = nameprefix + '.' + name
|
||||
elif objectname:
|
||||
fullname = objectname + '.' + name
|
||||
else:
|
||||
# just a function or constructor
|
||||
objectname = ''
|
||||
fullname = name
|
||||
|
||||
signode['object'] = objectname
|
||||
signode['module'] = mod_name
|
||||
signode['object'] = prefix
|
||||
signode['fullname'] = fullname
|
||||
|
||||
if self.display_prefix:
|
||||
signode += addnodes.desc_annotation(self.display_prefix,
|
||||
self.display_prefix)
|
||||
if nameprefix:
|
||||
signode += addnodes.desc_addname(nameprefix + '.', nameprefix + '.')
|
||||
if prefix:
|
||||
signode += addnodes.desc_addname(prefix + '.', prefix + '.')
|
||||
elif mod_name:
|
||||
signode += addnodes.desc_addname(mod_name + '.', mod_name + '.')
|
||||
signode += addnodes.desc_name(name, name)
|
||||
if self.has_arguments:
|
||||
if not arglist:
|
||||
signode += addnodes.desc_parameterlist()
|
||||
else:
|
||||
_pseudo_parse_arglist(signode, arglist)
|
||||
return fullname, nameprefix
|
||||
return fullname, prefix
|
||||
|
||||
def add_target_and_index(self, name_obj, sig, signode):
|
||||
# type: (Tuple[unicode, unicode], unicode, addnodes.desc_signature) -> None
|
||||
objectname = self.options.get(
|
||||
'object', self.env.ref_context.get('js:object'))
|
||||
fullname = name_obj[0]
|
||||
mod_name = self.env.ref_context.get('js:module')
|
||||
fullname = (mod_name and mod_name + '.' or '') + name_obj[0]
|
||||
if fullname not in self.state.document.ids:
|
||||
signode['names'].append(fullname)
|
||||
signode['ids'].append(fullname.replace('$', '_S_'))
|
||||
@ -103,7 +117,7 @@ class JSObject(ObjectDescription):
|
||||
line=self.lineno)
|
||||
objects[fullname] = self.env.docname, self.objtype
|
||||
|
||||
indextext = self.get_index_text(objectname, name_obj)
|
||||
indextext = self.get_index_text(mod_name, name_obj)
|
||||
if indextext:
|
||||
self.indexnode['entries'].append(('single', indextext,
|
||||
fullname.replace('$', '_S_'),
|
||||
@ -124,6 +138,68 @@ class JSObject(ObjectDescription):
|
||||
return _('%s (%s attribute)') % (name, obj)
|
||||
return ''
|
||||
|
||||
def before_content(self):
|
||||
# type: () -> None
|
||||
"""Handle object nesting before content
|
||||
|
||||
If this class is a nestable object, such as a class object, build up a
|
||||
representation of the nesting heirarchy so that de-nesting multiple
|
||||
levels works correctly.
|
||||
|
||||
If this class isn't a nestable object, just set the current object
|
||||
prefix using the object name. This prefix will be removed with
|
||||
:py:meth:`after_content`, and is not added to the list of nested
|
||||
object prefixes.
|
||||
|
||||
The following keys are used in ``self.env.ref_context``:
|
||||
|
||||
js:objects
|
||||
Stores the object prefix history. With each nested element, we
|
||||
add the object prefix to this list. When we exit that object's
|
||||
nesting level, :py:meth:`after_content` is triggered and the
|
||||
prefix is removed from the end of the list.
|
||||
|
||||
js:object
|
||||
Current object prefix. This should generally reflect the last
|
||||
element in the prefix history
|
||||
"""
|
||||
prefix = None
|
||||
if self.names:
|
||||
(obj_name, obj_name_prefix) = self.names.pop()
|
||||
prefix = obj_name_prefix.strip('.') if obj_name_prefix else None
|
||||
if self.allow_nesting:
|
||||
prefix = obj_name
|
||||
if prefix:
|
||||
self.env.ref_context['js:object'] = prefix
|
||||
if self.allow_nesting:
|
||||
try:
|
||||
self.env.ref_context['js:objects'].append(prefix)
|
||||
except (AttributeError, KeyError):
|
||||
self.env.ref_context['js:objects'] = [prefix]
|
||||
|
||||
def after_content(self):
|
||||
# type: () -> None
|
||||
"""Handle object de-nesting after content
|
||||
|
||||
If this class is a nestable object, removing the last nested class prefix
|
||||
ends further nesting in the object.
|
||||
|
||||
If this class is not a nestable object, the list of classes should not
|
||||
be altered as we didn't affect the nesting levels in
|
||||
:py:meth:`before_content`.
|
||||
"""
|
||||
if self.allow_nesting:
|
||||
try:
|
||||
self.env.ref_context['js:objects'].pop()
|
||||
except (KeyError, IndexError):
|
||||
self.env.ref_context['js:objects'] = []
|
||||
try:
|
||||
prefix = self.env.ref_context.get('js:objects', [])[-1]
|
||||
except IndexError:
|
||||
prefix = None
|
||||
finally:
|
||||
self.env.ref_context['js:object'] = prefix
|
||||
|
||||
|
||||
class JSCallable(JSObject):
|
||||
"""Description of a JavaScript function, method or constructor."""
|
||||
@ -146,6 +222,61 @@ class JSCallable(JSObject):
|
||||
class JSConstructor(JSCallable):
|
||||
"""Like a callable but with a different prefix."""
|
||||
display_prefix = 'class '
|
||||
allow_nesting = True
|
||||
|
||||
|
||||
class JSModule(Directive):
|
||||
"""
|
||||
Directive to mark description of a new JavaScript module.
|
||||
|
||||
This directive specifies the module name that will be used by objects that
|
||||
follow this directive.
|
||||
|
||||
Options
|
||||
-------
|
||||
|
||||
noindex
|
||||
If the ``noindex`` option is specified, no linkable elements will be
|
||||
created, and the module won't be added to the global module index. This
|
||||
is useful for splitting up the module definition across multiple
|
||||
sections or files.
|
||||
|
||||
:param mod_name: Module name. If the module name is ``nul``, or ``None``,
|
||||
the module name will be cleared for objects that follow.
|
||||
"""
|
||||
|
||||
has_content = False
|
||||
required_arguments = 1
|
||||
optional_arguments = 0
|
||||
final_argument_whitespace = False
|
||||
option_spec = {
|
||||
'noindex': directives.flag
|
||||
}
|
||||
|
||||
def run(self):
|
||||
# type: () -> List[nodes.Node]
|
||||
env = self.state.document.settings.env
|
||||
mod_name = self.arguments[0].strip()
|
||||
if mod_name in ['null', 'None']:
|
||||
env.ref_context.pop('js:module', None)
|
||||
return []
|
||||
env.ref_context['js:module'] = mod_name
|
||||
noindex = 'noindex' in self.options
|
||||
ret = []
|
||||
if not noindex:
|
||||
env.domaindata['js']['modules'][mod_name] = env.docname
|
||||
# Make a duplicate entry in 'objects' to facilitate searching for
|
||||
# the module in JavaScriptDomain.find_obj()
|
||||
env.domaindata['js']['objects'][mod_name] = (env.docname, 'module')
|
||||
targetnode = nodes.target('', '', ids=['module-' + mod_name],
|
||||
ismod=True)
|
||||
self.state.document.note_explicit_target(targetnode)
|
||||
ret.append(targetnode)
|
||||
indextext = _('%s (module)') % mod_name
|
||||
inode = addnodes.index(entries=[('single', indextext,
|
||||
'module-' + mod_name, '', None)])
|
||||
ret.append(inode)
|
||||
return ret
|
||||
|
||||
|
||||
class JSXRefRole(XRefRole):
|
||||
@ -153,6 +284,7 @@ class JSXRefRole(XRefRole):
|
||||
# type: (BuildEnvironment, nodes.Node, bool, unicode, unicode) -> Tuple[unicode, unicode] # NOQA
|
||||
# basically what sphinx.domains.python.PyXRefRole does
|
||||
refnode['js:object'] = env.ref_context.get('js:object')
|
||||
refnode['js:module'] = env.ref_context.get('js:module')
|
||||
if not has_explicit_title:
|
||||
title = title.lstrip('.')
|
||||
target = target.lstrip('~')
|
||||
@ -174,31 +306,41 @@ class JavaScriptDomain(Domain):
|
||||
# if you add a new object type make sure to edit JSObject.get_index_string
|
||||
object_types = {
|
||||
'function': ObjType(l_('function'), 'func'),
|
||||
'method': ObjType(l_('method'), 'meth'),
|
||||
'class': ObjType(l_('class'), 'class'),
|
||||
'data': ObjType(l_('data'), 'data'),
|
||||
'attribute': ObjType(l_('attribute'), 'attr'),
|
||||
'module': ObjType(l_('module'), 'mod'),
|
||||
}
|
||||
directives = {
|
||||
'function': JSCallable,
|
||||
'method': JSCallable,
|
||||
'class': JSConstructor,
|
||||
'data': JSObject,
|
||||
'attribute': JSObject,
|
||||
'module': JSModule,
|
||||
}
|
||||
roles = {
|
||||
'func': JSXRefRole(fix_parens=True),
|
||||
'meth': JSXRefRole(fix_parens=True),
|
||||
'class': JSXRefRole(fix_parens=True),
|
||||
'data': JSXRefRole(),
|
||||
'attr': JSXRefRole(),
|
||||
'mod': JSXRefRole(),
|
||||
}
|
||||
initial_data = {
|
||||
'objects': {}, # fullname -> docname, objtype
|
||||
'modules': {}, # mod_name -> docname
|
||||
} # type: Dict[unicode, Dict[unicode, Tuple[unicode, unicode]]]
|
||||
|
||||
def clear_doc(self, docname):
|
||||
# type: (unicode) -> None
|
||||
for fullname, (fn, _l) in list(self.data['objects'].items()):
|
||||
if fn == docname:
|
||||
for fullname, (pkg_docname, _l) in list(self.data['objects'].items()):
|
||||
if pkg_docname == docname:
|
||||
del self.data['objects'][fullname]
|
||||
for mod_name, pkg_docname in list(self.data['modules'].items()):
|
||||
if pkg_docname == docname:
|
||||
del self.data['modules'][mod_name]
|
||||
|
||||
def merge_domaindata(self, docnames, otherdata):
|
||||
# type: (List[unicode], Dict) -> None
|
||||
@ -206,31 +348,42 @@ class JavaScriptDomain(Domain):
|
||||
for fullname, (fn, objtype) in otherdata['objects'].items():
|
||||
if fn in docnames:
|
||||
self.data['objects'][fullname] = (fn, objtype)
|
||||
for mod_name, pkg_docname in otherdata['modules'].items():
|
||||
if pkg_docname in docnames:
|
||||
self.data['modules'][mod_name] = pkg_docname
|
||||
|
||||
def find_obj(self, env, obj, name, typ, searchorder=0):
|
||||
# type: (BuildEnvironment, unicode, unicode, unicode, int) -> Tuple[unicode, Tuple[unicode, unicode]] # NOQA
|
||||
def find_obj(self, env, mod_name, prefix, name, typ, searchorder=0):
|
||||
# type: (BuildEnvironment, unicode, unicode, unicode, unicode, int) -> Tuple[unicode, Tuple[unicode, unicode]] # NOQA
|
||||
if name[-2:] == '()':
|
||||
name = name[:-2]
|
||||
objects = self.data['objects']
|
||||
|
||||
searches = []
|
||||
if mod_name and prefix:
|
||||
searches.append('.'.join([mod_name, prefix, name]))
|
||||
if mod_name:
|
||||
searches.append('.'.join([mod_name, name]))
|
||||
if prefix:
|
||||
searches.append('.'.join([prefix, name]))
|
||||
searches.append(name)
|
||||
|
||||
if searchorder == 0:
|
||||
searches.reverse()
|
||||
|
||||
newname = None
|
||||
if searchorder == 1:
|
||||
if obj and obj + '.' + name in objects:
|
||||
newname = obj + '.' + name
|
||||
else:
|
||||
newname = name
|
||||
else:
|
||||
if name in objects:
|
||||
newname = name
|
||||
elif obj and obj + '.' + name in objects:
|
||||
newname = obj + '.' + name
|
||||
for search_name in searches:
|
||||
if search_name in objects:
|
||||
newname = search_name
|
||||
|
||||
return newname, objects.get(newname)
|
||||
|
||||
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
|
||||
contnode):
|
||||
# type: (BuildEnvironment, unicode, Builder, unicode, unicode, nodes.Node, nodes.Node) -> nodes.Node # NOQA
|
||||
objectname = node.get('js:object')
|
||||
mod_name = node.get('js:module')
|
||||
prefix = node.get('js:object')
|
||||
searchorder = node.hasattr('refspecific') and 1 or 0
|
||||
name, obj = self.find_obj(env, objectname, target, typ, searchorder)
|
||||
name, obj = self.find_obj(env, mod_name, prefix, target, typ, searchorder)
|
||||
if not obj:
|
||||
return None
|
||||
return make_refnode(builder, fromdocname, obj[0],
|
||||
@ -239,8 +392,9 @@ class JavaScriptDomain(Domain):
|
||||
def resolve_any_xref(self, env, fromdocname, builder, target, node,
|
||||
contnode):
|
||||
# type: (BuildEnvironment, unicode, Builder, unicode, nodes.Node, nodes.Node) -> List[Tuple[unicode, nodes.Node]] # NOQA
|
||||
objectname = node.get('js:object')
|
||||
name, obj = self.find_obj(env, objectname, target, None, 1)
|
||||
mod_name = node.get('js:module')
|
||||
prefix = node.get('js:object')
|
||||
name, obj = self.find_obj(env, mod_name, prefix, target, None, 1)
|
||||
if not obj:
|
||||
return []
|
||||
return [('js:' + self.role_for_objtype(obj[1]),
|
||||
|
@ -4,3 +4,4 @@ test-domain-js
|
||||
.. toctree::
|
||||
|
||||
roles
|
||||
package
|
||||
|
33
tests/roots/test-domain-js/module.rst
Normal file
33
tests/roots/test-domain-js/module.rst
Normal file
@ -0,0 +1,33 @@
|
||||
module
|
||||
=======
|
||||
|
||||
.. js:module:: module_a.submodule
|
||||
|
||||
* Link to :js:class:`ModTopLevel`
|
||||
|
||||
.. js:class:: ModTopLevel
|
||||
|
||||
* Link to :js:meth:`mod_child_1`
|
||||
* Link to :js:meth:`ModTopLevel.mod_child_1`
|
||||
|
||||
.. js:method:: ModTopLevel.mod_child_1
|
||||
|
||||
* Link to :js:meth:`mod_child_2`
|
||||
|
||||
.. js:method:: ModTopLevel.mod_child_2
|
||||
|
||||
* Link to :js:meth:`module_a.submodule.ModTopLevel.mod_child_1`
|
||||
|
||||
.. js:module:: null
|
||||
:noindex:
|
||||
|
||||
.. js:class:: ModNoModule
|
||||
|
||||
.. js:module:: module_b.submodule
|
||||
|
||||
* Link to :js:class:`ModTopLevel`
|
||||
|
||||
.. js:class:: ModTopLevel
|
||||
|
||||
* Link to :js:class:`ModNoModule`
|
||||
* Link to :js:mod:`module_a.submodule`
|
@ -20,7 +20,7 @@ def test_domain_js_xrefs(app, status, warning):
|
||||
"""Domain objects have correct prefixes when looking up xrefs"""
|
||||
app.builder.build_all()
|
||||
|
||||
def assert_refnode(node, class_name, target, reftype=None,
|
||||
def assert_refnode(node, mod_name, prefix, target, reftype=None,
|
||||
domain='js'):
|
||||
attributes = {
|
||||
'refdomain': domain,
|
||||
@ -28,60 +28,111 @@ def test_domain_js_xrefs(app, status, warning):
|
||||
}
|
||||
if reftype is not None:
|
||||
attributes['reftype'] = reftype
|
||||
if class_name is not False:
|
||||
attributes['js:class'] = class_name
|
||||
if mod_name is not False:
|
||||
attributes['js:module'] = mod_name
|
||||
if prefix is not False:
|
||||
attributes['js:object'] = prefix
|
||||
assert_node(node, **attributes)
|
||||
|
||||
doctree = app.env.get_doctree('roles')
|
||||
refnodes = list(doctree.traverse(addnodes.pending_xref))
|
||||
assert_refnode(refnodes[0], False, u'TopLevel', u'class')
|
||||
assert_refnode(refnodes[1], False, u'top_level', u'func')
|
||||
assert_refnode(refnodes[2], False, u'child_1', u'func')
|
||||
assert_refnode(refnodes[3], False, u'NestedChildA.subchild_2', u'func')
|
||||
assert_refnode(refnodes[4], False, u'child_2', u'func')
|
||||
assert_refnode(refnodes[5], False, u'any_child', domain='')
|
||||
assert_refnode(refnodes[6], False, u'NestedChildA', u'class')
|
||||
assert_refnode(refnodes[7], False, u'subchild_2', u'func')
|
||||
assert_refnode(refnodes[8], False, u'NestedParentA.child_1', u'func')
|
||||
assert_refnode(refnodes[9], False, u'NestedChildA.subchild_1', u'func')
|
||||
assert_refnode(refnodes[10], False, u'child_1', u'func')
|
||||
assert_refnode(refnodes[11], False, u'NestedParentB', u'class')
|
||||
assert_refnode(refnodes[12], False, u'NestedParentA.NestedChildA', u'class')
|
||||
assert_refnode(refnodes[0], None, None, u'TopLevel', u'class')
|
||||
assert_refnode(refnodes[1], None, None, u'top_level', u'func')
|
||||
assert_refnode(refnodes[2], None, u'NestedParentA', u'child_1', u'func')
|
||||
assert_refnode(refnodes[3], None, u'NestedParentA',
|
||||
u'NestedChildA.subchild_2', u'func')
|
||||
assert_refnode(refnodes[4], None, u'NestedParentA', u'child_2', u'func')
|
||||
assert_refnode(refnodes[5], False, u'NestedParentA', u'any_child', domain='')
|
||||
assert_refnode(refnodes[6], None, u'NestedParentA', u'NestedChildA', u'class')
|
||||
assert_refnode(refnodes[7], None, u'NestedParentA.NestedChildA',
|
||||
u'subchild_2', u'func')
|
||||
assert_refnode(refnodes[8], None, u'NestedParentA.NestedChildA',
|
||||
u'NestedParentA.child_1', u'func')
|
||||
assert_refnode(refnodes[9], None, u'NestedParentA',
|
||||
u'NestedChildA.subchild_1', u'func')
|
||||
assert_refnode(refnodes[10], None, u'NestedParentB', u'child_1', u'func')
|
||||
assert_refnode(refnodes[11], None, u'NestedParentB', u'NestedParentB',
|
||||
u'class')
|
||||
assert_refnode(refnodes[12], None, None, u'NestedParentA.NestedChildA',
|
||||
u'class')
|
||||
assert len(refnodes) == 13
|
||||
|
||||
doctree = app.env.get_doctree('module')
|
||||
refnodes = list(doctree.traverse(addnodes.pending_xref))
|
||||
assert_refnode(refnodes[0], 'module_a.submodule', None, 'ModTopLevel',
|
||||
'class')
|
||||
assert_refnode(refnodes[1], 'module_a.submodule', 'ModTopLevel',
|
||||
'mod_child_1', 'meth')
|
||||
assert_refnode(refnodes[2], 'module_a.submodule', 'ModTopLevel',
|
||||
'ModTopLevel.mod_child_1', 'meth')
|
||||
assert_refnode(refnodes[3], 'module_a.submodule', 'ModTopLevel',
|
||||
'mod_child_2', 'meth')
|
||||
assert_refnode(refnodes[4], 'module_a.submodule', 'ModTopLevel',
|
||||
'module_a.submodule.ModTopLevel.mod_child_1', 'meth')
|
||||
assert_refnode(refnodes[5], 'module_b.submodule', None, 'ModTopLevel',
|
||||
'class')
|
||||
assert_refnode(refnodes[6], 'module_b.submodule', 'ModTopLevel',
|
||||
'ModNoModule', 'class')
|
||||
assert_refnode(refnodes[7], 'module_b.submodule', 'ModTopLevel',
|
||||
'module_a.submodule', 'mod')
|
||||
assert len(refnodes) == 8
|
||||
|
||||
|
||||
@pytest.mark.sphinx('dummy', testroot='domain-js')
|
||||
def test_domain_js_objects(app, status, warning):
|
||||
app.builder.build_all()
|
||||
|
||||
modules = app.env.domains['js'].data['modules']
|
||||
objects = app.env.domains['js'].data['objects']
|
||||
|
||||
assert 'module_a.submodule' in modules
|
||||
assert 'module_a.submodule' in objects
|
||||
assert 'module_b.submodule' in modules
|
||||
assert 'module_b.submodule' in objects
|
||||
|
||||
assert objects['module_a.submodule.ModTopLevel'] == ('module', 'class')
|
||||
assert objects['module_a.submodule.ModTopLevel.mod_child_1'] == ('module', 'method')
|
||||
assert objects['module_a.submodule.ModTopLevel.mod_child_2'] == ('module', 'method')
|
||||
assert objects['ModNoModule'] == ('module', 'class')
|
||||
assert objects['module_b.submodule.ModTopLevel'] == ('module', 'class')
|
||||
|
||||
assert objects['TopLevel'] == ('roles', 'class')
|
||||
assert objects['top_level'] == ('roles', 'function')
|
||||
assert objects['NestedParentA'] == ('roles', 'class')
|
||||
assert objects['child_1'] == ('roles', 'function')
|
||||
assert objects['any_child'] == ('roles', 'function')
|
||||
assert objects['NestedChildA'] == ('roles', 'class')
|
||||
assert objects['subchild_1'] == ('roles', 'function')
|
||||
assert objects['subchild_2'] == ('roles', 'function')
|
||||
assert objects['child_2'] == ('roles', 'function')
|
||||
assert objects['NestedParentA.child_1'] == ('roles', 'function')
|
||||
assert objects['NestedParentA.any_child'] == ('roles', 'function')
|
||||
assert objects['NestedParentA.NestedChildA'] == ('roles', 'class')
|
||||
assert objects['NestedParentA.NestedChildA.subchild_1'] == ('roles', 'function')
|
||||
assert objects['NestedParentA.NestedChildA.subchild_2'] == ('roles', 'function')
|
||||
assert objects['NestedParentA.child_2'] == ('roles', 'function')
|
||||
assert objects['NestedParentB'] == ('roles', 'class')
|
||||
assert objects['NestedParentB.child_1'] == ('roles', 'function')
|
||||
|
||||
|
||||
@pytest.mark.sphinx('dummy', testroot='domain-js')
|
||||
def test_domain_js_find_obj(app, status, warning):
|
||||
|
||||
def find_obj(prefix, obj_name, obj_type, searchmode=0):
|
||||
def find_obj(mod_name, prefix, obj_name, obj_type, searchmode=0):
|
||||
return app.env.domains['js'].find_obj(
|
||||
app.env, prefix, obj_name, obj_type, searchmode)
|
||||
app.env, mod_name, prefix, obj_name, obj_type, searchmode)
|
||||
|
||||
app.builder.build_all()
|
||||
|
||||
assert (find_obj(None, u'NONEXISTANT', u'class') ==
|
||||
assert (find_obj(None, None, u'NONEXISTANT', u'class') ==
|
||||
(None, None))
|
||||
assert (find_obj(None, u'TopLevel', u'class') ==
|
||||
(u'TopLevel', (u'roles', u'class')))
|
||||
assert (find_obj(None, u'NestedParentA.NestedChildA', u'class') ==
|
||||
(None, None))
|
||||
assert (find_obj(None, u'subchild_2', u'func') ==
|
||||
(u'subchild_2', (u'roles', u'function')))
|
||||
assert (find_obj(None, None, u'NestedParentA', u'class') ==
|
||||
( u'NestedParentA', (u'roles', u'class')))
|
||||
assert (find_obj(None, None, u'NestedParentA.NestedChildA', u'class') ==
|
||||
( u'NestedParentA.NestedChildA', (u'roles', u'class')))
|
||||
assert (find_obj(None, 'NestedParentA', u'NestedChildA', u'class') ==
|
||||
( u'NestedParentA.NestedChildA', (u'roles', u'class')))
|
||||
assert (find_obj(None, None, u'NestedParentA.NestedChildA.subchild_1', u'func') ==
|
||||
( u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'function')))
|
||||
assert (find_obj(None, u'NestedParentA', u'NestedChildA.subchild_1', u'func') ==
|
||||
( u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'function')))
|
||||
assert (find_obj(None, u'NestedParentA.NestedChildA', u'subchild_1', u'func') ==
|
||||
( u'NestedParentA.NestedChildA.subchild_1', (u'roles', u'function')))
|
||||
assert (find_obj(u'module_a.submodule', u'ModTopLevel', u'mod_child_2', u'meth') ==
|
||||
( u'module_a.submodule.ModTopLevel.mod_child_2', (u'module', u'method')))
|
||||
assert (find_obj(u'module_b.submodule', u'ModTopLevel', u'module_a.submodule', u'mod') ==
|
||||
( u'module_a.submodule', (u'module', u'module')))
|
||||
|
Loading…
Reference in New Issue
Block a user