summaryrefslogtreecommitdiffstats
path: root/docs/sphinxgobject/domain.py
blob: 5cc4c4cd33008fd9a53e8a0d2d2c58a4ea21116b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
from docutils import nodes
from docutils.parsers.rst import Directive
from sphinx import addnodes
from sphinx.domains import Domain, ObjType
from sphinx.directives import ObjectDescription
from sphinx.locale import l_
from sphinx.roles import XRefRole
from sphinx.util.docfields import Field
from sphinx.util.nodes import make_refnode


class GObjectObj(ObjectDescription):

    def add_target_and_index(self, fqn, sig, signode):
        current = self.env.temp_data['current-class']

        if fqn not in self.state.document.ids:
            name = '{0}-{1}'.format(current, fqn.split(':')[0])
            signode['names'].append(name)
            signode['ids'].append(name)
            # FIXME: this fails for some names like "minimum", "maximum", etc.
            # self.state.document.note_explicit_target(signode)

            objects = self.env.domaindata['gobj']['objects']
            objects[name] = (self.env.docname, self.objtype)


class GObjectClass(GObjectObj):

    def handle_signature(self, sig, signode):
        self.env.temp_data['current-class'] = sig
        signode += addnodes.desc_annotation('class', ' class ')
        signode += addnodes.desc_name(sig, sig)
        return sig


class GObjectProperty(GObjectObj):

    def handle_signature(self, sig, signode):
        ptype = None
        split = sig.split(':')
        name = split[0]

        if len(split) > 1:
            ptype = split[1]

        quoted = '"{0}"'.format(name)
        signode += addnodes.desc_name(quoted, quoted)

        if ptype:
            signode += nodes.inline(':', ': ')
            signode += addnodes.desc_type(ptype, ptype)

        return sig


class GObjectXRefRole(XRefRole):
    def process_link(self, env, refnode, has_explicit_title, title, target):
        title = has_explicit_title if has_explicit_title else title

        if 'current-class' in env.temp_data:
            current = env.temp_data['current-class']
            target = '{0}-{1}'.format(current, target)

        return title, target


class GObjectDomain(Domain):

    label = 'GObject'
    name = 'gobj'

    object_types = {
        'class': ObjType(l_('class'), 'class'),
        'prop': ObjType(l_('prop'), 'prop'),
    }

    directives = {
        'class':    GObjectClass,
        'prop':     GObjectProperty,
    }

    initial_data = {
        # 'modules': {},
        'objects': {},
    }

    roles = {
        'class': GObjectXRefRole(),
        'prop': GObjectXRefRole(),
    }

    def get_objects(self):
        for fqn, (docname, objtype) in self.data['objects'].items():
            yield (fqn, fqn, objtype, docname, fqn, 1)

    def resolve_xref(self, env, fromdocname, builder, type, target, node, contnode):
        if target[0] == '~':
            target = target[1:]

        rtarget = '{}-{}'.format(target, target)
        doc, _ = self.data['objects'].get(rtarget, (None, None))

        if doc:
            return make_refnode(builder, fromdocname, doc, rtarget, contnode, target)