JavaScript domain supports now references, also :class:JSObjects are now indexed.

This commit is contained in:
Daniel Neuhäuser 2010-03-31 02:17:24 +00:00
parent 00cb284182
commit f03f8356d1

View File

@ -16,17 +16,20 @@ from sphinx.locale import l_, _
from sphinx.directives import ObjectDescription
from sphinx.domains.python import py_paramlist_re as js_paramlist_re
from sphinx.roles import XRefRole
from sphinx.util.nodes import make_refnode
js_sig_re = re.compile(
r'''([^ .]+\.)? # object name
([^ .]+\s*) # name
\((.*)\)$ # arguments
\((.*)\)$ # arguments
''', re.VERBOSE)
class JSObject(ObjectDescription):
"""
Description of a JavaScript object.
"""
#: If set to ``True`` this object is callable and a `desc_parameterlist` is
#: added
has_arguments = False
def handle_signature(self, sig, signode):
@ -36,14 +39,14 @@ class JSObject(ObjectDescription):
nameprefix, name, arglist = match.groups()
objectname = self.env.temp_data.get('js:object')
if objectname and nameprefix:
# someone documenting the method of an attribute of the current
# object? shouldn't happen but who knows...
fullname = objectname + '.' + nameprefix + name
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
elif nameprefix:
fullname = nameprefix + '.' + name
else:
# just a function or constructor
objectname = ''
@ -52,6 +55,7 @@ class JSObject(ObjectDescription):
signode['object'] = objectname
signode['fullname'] = fullname
signode += addnodes.desc_addname(nameprefix, nameprefix)
signode += addnodes.desc_name(name, name)
if self.has_arguments:
signode += addnodes.desc_parameterlist()
@ -78,6 +82,42 @@ class JSObject(ObjectDescription):
raise ValueError()
return fullname, nameprefix
def add_target_and_index(self, name_obj, sig, signode):
objectname = self.options.get(
'object', self.env.temp_data.get('js:object'))
fullname = name_obj[0]
if fullname not in self.state.document.ids:
signode['names'].append(fullname)
signode['ids'].append(fullname)
signode['first'] = not self.names
self.state.document.note_explicit_target(signode)
objects = self.env.domaindata['js']['objects']
if fullname in objects:
self.env.warn(
self.env.docname,
'duplicate object description of %s, ' % fullname +
'other instance in ' +
self.env.doc2path(objects[fullname][0]),
self.lineno)
objects[fullname] = self.env.docname, self.objtype
indextext = self.get_index_text(objectname, name_obj)
if indextext:
self.indexnode['entries'].append(('single', indextext,
fullname, fullname))
def get_index_text(self, objectname, name_obj):
name, obj = name_obj
if self.objtype == 'function':
if not obj:
return _('%s() (built-in function)') % name
return _('%s() (%s method)') % (name, obj)
elif self.objtype == 'data':
return _('%s (global variable or constant)') % name
elif self.objtype == 'attribute':
return _('%s (%s attribute)') % (name, obj)
return ''
class JSCallable(JSObject):
"""Description of a JavaScript function, method or constructor."""
has_arguments = True
@ -116,5 +156,43 @@ class JavaScriptDomain(Domain):
roles = {
'func': JSXRefRole(fix_parens=True),
'data': JSXRefRole(),
'attr': JSXRefRole()
'attr': JSXRefRole(),
}
initial_data = {
'objects': {}, # fullname -> docname, objtype
}
def clear_doc(self, docname):
for fullname, (fn, _) in self.data['objects'].items():
if fn == docname:
del self.data['objects'][fullname]
def find_obj(self, env, obj, name, typ, searchorder=0):
if name[-2:] == '()':
name = name[:-2]
objects = self.data['objects']
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
return newname, objects.get(newname)
def resolve_xref(self, env, fromdocname, builder, typ, target, node,
contnode):
objectname = node.get('js:object')
searchorder = node.hasattr('refspecific') and 1 or 0
name, obj = self.find_obj(env, objectname, target, typ, searchorder)
if not obj:
return None
return make_refnode(builder, fromdocname, obj[0], name, contnode, name)
def get_objects(self):
for refname, (docname, type) in self.data['objects'].iteritems():
yield refname, type, docname, refname, 1