[gi-docgen/link-fixes: 3/3] generate: Generate proper cross-reference links
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [gi-docgen/link-fixes: 3/3] generate: Generate proper cross-reference links
- Date: Sat, 25 Sep 2021 15:41:39 +0000 (UTC)
commit 6c61743452a8add6475dd747b4d6ab0031b8a377
Author: Emmanuele Bassi <ebassi gnome org>
Date: Sat Sep 25 16:28:27 2021 +0100
generate: Generate proper cross-reference links
When finding a type for a cross-link, we need to pass all components,
including the namespace; otherwise, the type lookup will just find the
first type matching the name in the various dependencies, generating
collisions or weird results.
Fixes: #107
gidocgen/gdgenerate.py | 90 ++++++++++++++++++++++++++++++++++----------------
gidocgen/gir/ast.py | 35 +++++++++++++++-----
2 files changed, 88 insertions(+), 37 deletions(-)
---
diff --git a/gidocgen/gdgenerate.py b/gidocgen/gdgenerate.py
index b80d22b..7720517 100644
--- a/gidocgen/gdgenerate.py
+++ b/gidocgen/gdgenerate.py
@@ -178,8 +178,10 @@ def gen_index_signal(signal, namespace, md=None):
def gen_index_ancestor(ancestor_type, namespace, config, md=None):
ancestor_name = ancestor_type.name
if '.' in ancestor_name:
- _, ancestor_name = ancestor_name.split('.')
- res = namespace.repository.find_class(ancestor_name)
+ ns, ancestor_name = ancestor_name.split('.')
+ else:
+ ns = ancestor_type.namespace or namespace.name
+ res = namespace.repository.find_class(ancestor_name, ns)
if res is not None:
ancestor_ns = res[0].name
ancestor_ctype = res[1].base_ctype
@@ -228,13 +230,20 @@ def gen_index_ancestor(ancestor_type, namespace, config, md=None):
def gen_index_implements(iface_type, namespace, config, md=None):
- if '.' in iface_type.name:
- iface_ns, iface_name = iface_type.name.split('.')
+ iface_name = iface_type.name
+ if '.' in iface_name:
+ ns, iface_name = iface_name.split('.')
+ else:
+ ns = iface_type.namespace or namespace.name
+ res = namespace.repository.find_interface(iface_name, ns)
+ if res is not None:
+ iface_ns = res[0].name
+ iface_ctype = res[1].base_ctype
+ iface = res[1]
else:
iface_ns = iface_type.namespace or namespace.name
- iface_name = iface_type.name
- iface_ctype = iface_type.base_ctype
- iface = namespace.find_interface(iface_name)
+ iface_ctype = iface_type.base_ctype
+ iface = None
n_methods = 0
methods = []
n_properties = 0
@@ -273,11 +282,14 @@ def gen_index_implements(iface_type, namespace, config, md=None):
def gen_type_link(repository, namespace, name):
- res = repository.find_type(name)
+ res = repository.find_type(name, ns=namespace)
if res is None:
- return f"<code>{namespace.identifier_prefix[0]}{name}</code>"
+ return f"<code>{name}</code>"
ns, t = res
+ if t.is_fundamental:
+ return f"<code>{name}</code>"
+
if isinstance(t, gir.Alias):
link = f"alias.{name}.html"
elif isinstance(t, gir.BitField):
@@ -299,7 +311,7 @@ def gen_type_link(repository, namespace, name):
else:
return f"<code>{t.ctype}</code>"
- if ns.name == namespace.name:
+ if ns.name == repository.namespace.name:
href = f'href="{link}"'
text = f"<code>{t.ctype}</code>"
css_class = ""
@@ -361,7 +373,10 @@ class TemplateProperty:
self.type_name = prop.target.name
self.type_cname = prop.target.ctype
if self.type_cname is None:
- self.type_cname = type_name_to_cname(prop.target.name, True)
+ if prop.target.is_fundamental:
+ self.type_cname = prop.target.name
+ else:
+ self.type_cname = type_name_to_cname(prop.target.name, True)
self.readable = prop.readable
self.writable = prop.writable
self.construct = prop.construct
@@ -446,8 +461,10 @@ class TemplateProperty:
if self.type_name is not None:
name = self.type_name
if '.' in name:
- _, name = name.split('.')
- self.link = gen_type_link(namespace.repository, namespace, name)
+ ns, name = name.split('.')
+ else:
+ ns = namespace.name
+ self.link = gen_type_link(namespace.repository, ns, name)
@property
def c_decl(self):
@@ -479,6 +496,8 @@ class TemplateArgument:
self.is_map = isinstance(argument.target, gir.MapType)
self.is_varargs = isinstance(argument.target, gir.VarArgs)
self.is_macro = isinstance(call, gir.FunctionMacro)
+ self.is_list_model = self.type_name in ['Gio.ListModel', 'GListModel']
+ self.is_fundamental = argument.target.is_fundamental
self.transfer = argument.transfer or 'none'
if isinstance(call, gir.Method):
self.transfer_note = METHOD_ARG_TRANSFER_MODES[argument.transfer or 'none']
@@ -505,6 +524,8 @@ class TemplateArgument:
if self.is_list:
self.value_type = argument.target.value_type.name
self.value_type_cname = argument.target.value_type.ctype
+ if self.is_list_model:
+ self.value_type = argument.attributes.get('element-type', 'GObject')
if argument.doc is not None:
self.summary = utils.preprocess_docs(argument.doc.content, namespace, summary=True)
self.description = utils.preprocess_docs(argument.doc.content, namespace)
@@ -519,14 +540,20 @@ class TemplateArgument:
else:
name = None
if name is not None:
- if '.' in name:
- _, name = name.split('.')
- self.link = gen_type_link(namespace.repository, namespace, name)
+ if self.is_fundamental:
+ self.link = f"<code>{self.type_cname}</code>"
+ elif self.is_array:
+ self.link = f"<code>{self.value_type_cname}</code>"
+ elif self.is_list:
+ self.link = f"<code>{self.value_type_cname}</code>"
+ elif self.is_list_model:
+ self.link = f"<code>{self.value_type}</code>"
else:
- if self.is_array:
- self.link = f"<code>{self.value_type_cname}</code>"
- elif self.is_list:
- self.link = f"<code>{self.value_type_cname}</code>"
+ if '.' in name:
+ ns, name = name.split('.')
+ else:
+ ns = namespace.name
+ self.link = gen_type_link(namespace.repository, ns, name)
@property
def is_pointer(self):
@@ -547,6 +574,7 @@ class TemplateReturnValue:
self.name = retval.name
self.type_name = retval.target.name
self.type_cname = retval.target.ctype
+ self.is_fundamental = retval.target.is_fundamental
if self.type_cname is None:
self.type_cname = type_name_to_cname(retval.target.name, True)
self.is_array = isinstance(retval.target, gir.ArrayType)
@@ -588,16 +616,20 @@ class TemplateReturnValue:
else:
name = None
if name is not None:
- if '.' in name:
- _, name = name.split('.')
- self.link = gen_type_link(namespace.repository, namespace, name)
+ if self.is_fundamental:
+ self.link = f"<code>{self.type_name}</code>"
+ elif self.is_array:
+ self.link = f"<code>{self.value_type_cname}</code>"
+ elif self.is_list:
+ self.link = f"<code>{self.value_type_cname}</code>"
+ elif self.is_list_model:
+ self.link = f"<code>{self.value_type}</code>"
else:
- if self.is_array:
- self.link = f"<code>{self.value_type_cname}</code>"
- elif self.is_list:
- self.link = f"<code>{self.value_type_cname}</code>"
- elif self.is_list_model:
- self.link = f"<code>{self.value_type}</code>"
+ if '.' in name:
+ ns, name = name.split('.')
+ else:
+ ns = namespace.name
+ self.link = gen_type_link(namespace.repository, ns, name)
@property
def is_pointer(self):
diff --git a/gidocgen/gir/ast.py b/gidocgen/gir/ast.py
index 53a93ed..1973f40 100644
--- a/gidocgen/gir/ast.py
+++ b/gidocgen/gir/ast.py
@@ -1178,11 +1178,14 @@ class Repository:
def namespace(self) -> T.Optional[Namespace]:
return self._namespaces[0]
- def find_type(self, name: str) -> T.Optional[T.Tuple[Namespace, Type]]:
- res = self.namespace.find_real_type(name)
- if res is not None:
- return (self.namespace, res)
+ def find_type(self, name: str, ns: T.Optional[str] = None) -> T.Optional[T.Tuple[Namespace, Type]]:
+ if ns is None or self.namespace.name == ns:
+ res = self.namespace.find_real_type(name)
+ if res is not None:
+ return (self.namespace, res)
for repo in self.includes.values():
+ if ns is not None and ns != repo.namespace.name:
+ continue
res = repo.namespace.find_real_type(name)
if res is not None:
return (repo.namespace, res)
@@ -1200,12 +1203,28 @@ class Repository:
return (repo.namespace, res)
return None
- def find_class(self, name: str) -> T.Optional[T.Tuple[Namespace, Type]]:
- res = self.namespace.find_class(name)
- if res is not None:
- return (self.namespace, res)
+ def find_class(self, name: str, ns: T.Optional[str] = None) -> T.Optional[T.Tuple[Namespace, Type]]:
+ if ns is None or self.namespace.name == ns:
+ res = self.namespace.find_class(name)
+ if res is not None:
+ return (self.namespace, res)
for repo in self.includes.values():
+ if ns is not None and ns != repo.namespace.name:
+ continue
res = repo.namespace.find_class(name)
if res is not None:
return (repo.namespace, res)
return None
+
+ def find_interface(self, name: str, ns: T.Optional[str] = None) -> T.Optional[T.Tuple[Namespace, Type]]:
+ if ns is None or self.namespace.name == ns:
+ res = self.namespace.find_interface(name)
+ if res is not None:
+ return (self.namespace, res)
+ for repo in self.includes.values():
+ if ns is not None and ns != repo.namespace.name:
+ continue
+ res = repo.namespace.find_interface(name)
+ if res is not None:
+ return (repo.namespace, res)
+ return None
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]