[gi-docgen/link-type: 1/2] Support generic type fragment for linking types
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gi-docgen/link-type: 1/2] Support generic type fragment for linking types
- Date: Mon, 24 May 2021 12:07:26 +0000 (UTC)
commit a8721ad2ed98f6f5f5bd2dfa8e2c6137823a1f69
Author: Emmanuele Bassi <ebassi gnome org>
Date: Mon May 24 13:04:55 2021 +0100
Support generic type fragment for linking types
We can determine a type ourselves, just like we can determine symbols.
Of course, using a generic `type` fragment will require a type
resolution pass from any other tool parsing the documentation embedded
into the GIR data.
docs/linking.rst | 15 ++++++++++++++-
gidocgen/utils.py | 48 +++++++++++++++++++++++++++++++++++-------------
2 files changed, 49 insertions(+), 14 deletions(-)
---
diff --git a/docs/linking.rst b/docs/linking.rst
index a2e3d14..dbd27b7 100644
--- a/docs/linking.rst
+++ b/docs/linking.rst
@@ -96,7 +96,20 @@ The available qualifier fragments are:
- A virtual function in a class or interface
- ``[vfunc@Gtk.Widget.measure]``
-Additionally, the ``id`` fragment, followed by a C symbol identifier, will try to link to the function; for
instance:
+The generic ``type`` fragment, followed by a type, will look up the given type
+and generate the appropriate link for it. The type can be fully qualified or
+relative to the current namespace:
+
+::
+
+ // Equivalent to [class@Gtk.Window]
+ [type@Gtk.Window]
+
+ // Equivalent to [enum@Gtk.Orientation]
+ [type@Gtk.Orientation]
+
+Additionally, the ``id`` fragment, followed by a C symbol identifier, will try
+to link to the function; for instance:
::
diff --git a/gidocgen/utils.py b/gidocgen/utils.py
index e2c2544..e8a5b1f 100644
--- a/gidocgen/utils.py
+++ b/gidocgen/utils.py
@@ -68,7 +68,7 @@ LINK_RE = re.compile(
r'''
\[
(`)?
- (?P<fragment>alias|class|const|ctor|enum|error|flags|func|id|iface|method|property|signal|struct|vfunc)
+
(?P<fragment>alias|class|const|ctor|enum|error|flags|func|id|iface|method|property|signal|struct|type|vfunc)
@
(?P<endpoint>[\w\-_:\.]+)
(`)?
@@ -217,12 +217,13 @@ class LinkGenerator:
"property": self._parse_property,
"signal": self._parse_signal,
"struct": self._parse_type,
+ "type": self._parse_type,
"vfunc": self._parse_method,
}
parser_method = fragment_parsers.get(self._fragment)
if parser_method is not None:
- res = parser_method()
+ res = parser_method(self._fragment)
if res is not None:
self._fragment = None
log.warning(str(res))
@@ -232,7 +233,7 @@ class LinkGenerator:
self._fragment, self._endpoint,
"Unable to parse link")))
- def _parse_id(self):
+ def _parse_id(self, fragment):
t = self._namespace.find_symbol(self._endpoint)
if isinstance(t, gir.Class) or \
isinstance(t, gir.Interface) or \
@@ -254,7 +255,7 @@ class LinkGenerator:
self._fragment, self._endpoint,
f"Unable to find symbol {self._endpoint}")
- def _parse_type(self):
+ def _parse_type(self, fragment):
res = TYPE_RE.match(self._endpoint)
if res:
ns = res.group('ns')
@@ -286,6 +287,27 @@ class LinkGenerator:
return None
t = namespace.find_real_type(name)
if t is not None and t.base_ctype is not None:
+ if fragment == 'type':
+ if isinstance(t, gir.Alias):
+ self._fragment = 'alias'
+ elif isinstance(t, gir.BitField):
+ self._fragment = 'flags'
+ elif isinstance(t, gir.Class):
+ self._fragment = 'class'
+ elif isinstance(t, gir.Constant):
+ self._fragment = 'const'
+ elif isinstance(t, gir.Enumeration):
+ self._fragment = 'enum'
+ elif isinstance(t, gir.ErrorDomain):
+ self._fragment = 'error'
+ elif isinstance(t, gir.Interface):
+ self._fragment = 'iface'
+ elif isinstance(t, gir.Record) or isinstance(t, gir.Union):
+ self._fragment = 'struct'
+ else:
+ return LinkParseError(self._line, self._start, self._end,
+ self._fragment, self._endpoint,
+ f"Invalid type {t} for '{ns}.{name}'")
self._name = name
self._type = t.base_ctype
return None
@@ -294,7 +316,7 @@ class LinkGenerator:
self._fragment, self._endpoint,
f"Unable to find type '{ns}.{name}'")
- def _parse_property(self):
+ def _parse_property(self, fragment):
res = PROPERTY_RE.match(self._endpoint)
if res:
ns = res.group('ns')
@@ -342,7 +364,7 @@ class LinkGenerator:
self._fragment, self._endpoint,
f"Invalid property '{pname}' for type '{ns}.{name}'")
- def _parse_signal(self):
+ def _parse_signal(self, fragment):
res = SIGNAL_RE.match(self._endpoint)
if res:
ns = res.group('ns')
@@ -390,7 +412,7 @@ class LinkGenerator:
self._fragment, self._endpoint,
f"Invalid signal name '{sname}' for type '{ns}.{name}'")
- def _parse_method(self):
+ def _parse_method(self, fragment):
res = METHOD_RE.match(self._endpoint)
if res:
ns = res.group('ns')
@@ -429,7 +451,7 @@ class LinkGenerator:
if isinstance(t, gir.Record) and t.struct_for is not None:
self._name = t.struct_for
self._fragment = "class_method"
- elif self._fragment == "vfunc" and t.type_struct is not None:
+ elif fragment == "vfunc" and t.type_struct is not None:
self._name = name
self._type = t.type_struct
else:
@@ -438,17 +460,17 @@ class LinkGenerator:
return LinkParseError(self._line, self._start, self._end,
self._fragment, self._endpoint,
f"Unable to find type '{ns}.{name}'")
- if self._fragment == "ctor":
+ if fragment == "ctor":
methods = getattr(t, "constructors", [])
- elif self._fragment in ["method", "class_method"]:
+ elif fragment in ["method", "class_method"]:
methods = getattr(t, "methods", [])
- elif self._fragment == "vfunc":
+ elif fragment == "vfunc":
methods = getattr(t, "virtual_methods", [])
else:
methods = []
for m in methods:
if m.name == method:
- if self._fragment == "vfunc":
+ if fragment == "vfunc":
self._vfunc_name = m.name
else:
self._symbol_name = f"{m.identifier}()"
@@ -457,7 +479,7 @@ class LinkGenerator:
self._fragment, self._endpoint,
f"Unable to find method '{ns}.{name}.{method}'")
- def _parse_func(self):
+ def _parse_func(self, fragment):
tokens = self._endpoint.split('.')
# Case 1: [func@init] => gtk_init()
if len(tokens) == 1:
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]