Commits

Anonymous committed e2b7be8

Added a vala method object type

  • Participants
  • Parent commits fc887d2

Comments (0)

Files changed (2)

File sphinx/domains/vala.py

     :copyright: Copyright 2007-2010 by the Sphinx team, see AUTHORS.
     :license: BSD, see LICENSE for details.
 """
-from sphinx.domains import Domain
+from docutils import nodes
+
+from sphinx import addnodes
+from sphinx.roles import XRefRole
+from sphinx.locale import l_
+from sphinx.domains import Domain, ObjType
+from sphinx.directives import ObjectDescription
+from sphinx.util.nodes import make_refnode
 from sphinx.util.compat import Directive
+from sphinx.util.docfields import Field, GroupedField, TypedField
+
+
+ACCESSMODIFIERS = frozenset(['public', 'private', 'protected', 'internal'])
+
+
+class ValaObject(ObjectDescription):
+    def attach_name(self, node, prefix, name):
+        if prefix:
+            node += addnodes.desc_addname(prefix, prefix + '.')
+        node += addnodes.desc_name(name, name)
+
+    def attach_type(self, node, type):
+        node += addnodes.desc_annotation(type, type)
+        node += nodes.Text(' ')
+
+
+class ValaMethod(ValaObject):
+    """
+    Description of a Vala method.
+    """
+    doc_field_types = [
+        GroupedField('parameter', label=l_('Parameters'),
+                     names=('param', 'parameter'), can_collapse=True),
+        GroupedField('errors', label=l_('Throws'), names=('throws', ),
+                     can_collapse=True),
+        Field('returnvalue', label=l_('Returns'), has_arg=False,
+              names=('returns', 'return'))
+    ]
+
+    def handle_signature(self, sig, signode):
+        definition, parameters = sig[:-1].split('(')
+        namespace = self.env.temp_data.get('vala:namespace')
+        parts = definition.split(' ')
+        if len(parts) == 2:
+            returntype, name = parts
+        else:
+            raise ValueError(parts)
+        if '.' in name:
+            prefix, name = name.rsplit('.', 1)
+        else:
+            prefix = None
+        prefix = '.'.join(filter(None, [namespace, prefix]))
+        fullname = prefix + '.' + name
+        signode['fullname'] = fullname
+        self.attach_type(signode, returntype)
+        self.attach_name(signode, prefix, name)
+        self.handle_parameters(signode, parameters)
+        return fullname
+
+    def handle_parameters(self, signode, parameters):
+        paramlist = addnodes.desc_parameterlist()
+        if parameters:
+            for param in parameters.split(','):
+                paramnode = addnodes.desc_parameter('', '', noemph=True)
+                parts = param.strip().split(' ')
+                if len(parts) == 2:
+                    type, name = parts
+                    direction = None
+                elif len(parts) == 3:
+                    direction, type, name = parts
+                    paramnode += addnodes.desc_annotation(direction, direction)
+                    paramnode += nodes.Text(' ')
+                else:
+                    raise ValueError(parts)
+                reftarget = type[:-1] if type.endswith('?') else type
+                typenode = addnodes.pending_xref('', refdomain='vala',
+                                                 reftype='type', reftarget=type)
+                typenode += nodes.Text(type)
+                paramnode += typenode
+                paramnode += nodes.Text(' ')
+                paramnode += nodes.emphasis(name, name)
+                paramlist += paramnode
+        signode += paramlist
+
+    def add_target_and_index(self, fullname, sig, signode):
+        fullname = signode['fullname']
+        objects = self.env.domaindata['vala']['objects']
+        if fullname not in self.state.document.ids:
+            signode['names'].append(fullname)
+            signode['ids'].append(fullname)
+            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]) +
+                    ', use :noindex: for one of them',
+                    self.lineno)
+            objects[fullname] = self.env.docname, self.objtype
 
 
 class ValaCurrentNamespace(Directive):
     label = 'Vala'
     # TODO: add object types for:
     #       - classes
-    #       - methods
+    #       - (methods)
     #       - interfaces
     #       - structs
     #       - enums
     #       - errordomains
     #       - members
     #       - namespace? this could be used like a python module
-    object_types = {}
+    object_types = {
+        'method': ObjType(l_('method'), 'meth'),
+    }
     directives = {
         'currentnamespace': ValaCurrentNamespace,
+        'method': ValaMethod,
     }
-    roles = {}
+    roles = {
+        'meth': XRefRole(fix_parens=True),
+    }
     initial_data = {
         'objects': {}, # fullname -> docname, objtype
     }
     def get_objects(self):
         for fullname, (docname, objtype) in self.data['objects'].iteritems():
             yield fullname, fullname, objtype, docname, fullname, 1
+
+    def resolve_xref(self, env, fromdocname, builder, type, target, node,
+                     contnode):
+        if target in self.data['objects']:
+            return make_refnode(builder, fromdocname,
+                                self.data['objects'][target][0], target,
+                                contnode, target)

File tests/root/objects.txt

 
 .. vala:currentnamespace:: foo
 
+.. vala:method:: void spam()
+
+   :parameter a: blubber
+   :throws bla: foo
+   :throws blubb: bar
+   :returns bling: very blingy
+
 .. vala:currentnamespace:: foo.bar
 
+.. vala:method:: void spam(int a, out foo? b, ref bar x)
+
+   :param a: whatever
+   :throws boom:
+   :return something: doing bla
+
 .. should reset the namespace
 .. vala:currentnamespace:: global
 
+.. vala:method:: void spam(out int a)
+
+.. with namespace
+.. vala:method int foo.bar.eggs()
+
+:vala:meth:`foo.spam`
+:vala:meth:`foo.spam()`
+
+:vala:meth:`foo.bar.spam`
+
+:vala:meth:`spam`
+
 
 References
 ==========