Commit c918ad67 authored by Jan Tojnar's avatar Jan Tojnar
Browse files
parent 12fd0651
Loading
Loading
Loading
Loading
+0 −92
Original line number Diff line number Diff line
From 7b2d3699ad117199bc316c7007cc5984c3b09368 Mon Sep 17 00:00:00 2001
From: Maximiliano Sandoval <msandova@gnome.org>
Date: Thu, 20 Mar 2025 22:52:54 +0100
Subject: [PATCH] scanner: Prefer some getters over others

At the moment the current set of heuristics to determine a getter for a
property is good for finding *a* getter. However, if there are multiple
candidates we might declare the wrong method as a getter.

We introduce a priority system to determine which getter candidate is
the most appropriate as the getter. The weight were chosen with gaps in
between so that new and better heuristics have space to thrive.

For a property named `p`, these are the possible getter candidates:

 - A method declared via the `(getter p)` annotation
 - The method `get_p`
 - The method `is_p`
 - The method `p`

we declare the getter to be the first candidate in the list for which a
method of the same name is available.

See https://gitlab.gnome.org/GNOME/gjs/-/issues/681.
---
 giscanner/maintransformer.py | 22 +++++++++++++++-------
 1 file changed, 15 insertions(+), 7 deletions(-)

diff --git a/giscanner/maintransformer.py b/giscanner/maintransformer.py
index a81b1777..9aaf2578 100644
--- a/giscanner/maintransformer.py
+++ b/giscanner/maintransformer.py
@@ -1612,7 +1612,10 @@ method or constructor of some type."""
             if not prop.introspectable:
                 continue
             setter = None
-            getter = []
+            # They keys are method names of candidates for getters. The values
+            # are priority weights that measure how tasteful was the heuristic
+            # used to propose their candidate.
+            getter = {}
             if prop.setter is None:
                 if prop.writable and not prop.construct_only:
                     setter = 'set_' + normalized_name
@@ -1620,17 +1623,17 @@ method or constructor of some type."""
                 setter = prop.setter
             if prop.getter is None:
                 if prop.readable:
-                    getter = ['get_' + normalized_name]
+                    getter[f"get_{normalized_name}"] = 50
                     # Heuristic: boolean properties can have getters that are
                     # prefixed by is_property_name, like: gtk_window_is_maximized()
                     if prop.type.is_equiv(ast.TYPE_BOOLEAN) and not normalized_name.startswith("is_"):
-                        getter.append(f"is_{normalized_name}")
+                        getter[f"is_{normalized_name}"] = 25
                     # Heuristic: read-only properties can have getters that are
                     # just the property name, like: gtk_widget_has_focus()
                     if not prop.writable and prop.type.is_equiv(ast.TYPE_BOOLEAN):
-                        getter.append(normalized_name)
+                        getter[normalized_name] = 10
             else:
-                getter = [prop.getter]
+                getter[prop.getter] = 99
             for method in node.methods:
                 if not method.introspectable:
                     continue
@@ -1645,7 +1648,7 @@ method or constructor of some type."""
                         method.set_property = prop.name
                     prop.setter = method.name
                     continue
-                if getter is not [] and method.name in getter:
+                if getter is not {} and method.name in getter:
                     if method.get_property is None:
                         method.get_property = prop.name
                     elif method.get_property != prop.name:
@@ -1654,7 +1657,12 @@ method or constructor of some type."""
                                           "mismatched '(get-property %s)' annotation" %
                                           (method.symbol, prop.name, method.get_property))
                         method.get_property = prop.name
-                    prop.getter = method.name
+                    # Check the priority of the last matching getter
+                    current_priority = -1
+                    if current_getter := prop.getter:
+                        current_priority = getter.get(current_getter, -1)
+                    if getter[method.name] >= current_priority:
+                        prop.getter = method.name
                     continue
 
     def _pass_member_numeric_name(self, node):
-- 
2.48.1
+2 −6
Original line number Diff line number Diff line
@@ -43,7 +43,7 @@ let
in
stdenv.mkDerivation (finalAttrs: {
  pname = "gobject-introspection";
  version = "1.84.0";
  version = "1.86.0";

  # outputs TODO: share/gobject-introspection-1.0/tests is needed during build
  # by pygobject3 (and maybe others), but it's only searched in $out
@@ -57,7 +57,7 @@ stdenv.mkDerivation (finalAttrs: {

  src = fetchurl {
    url = "mirror://gnome/sources/gobject-introspection/${lib.versions.majorMinor finalAttrs.version}/gobject-introspection-${finalAttrs.version}.tar.xz";
    hash = "sha256-lFtX2n7CYuXCZrieCR0UvoAMxCQnfYKgKHK315SoR3k=";
    hash = "sha256-kg0aP87ercMqz/lcLiA7MZA53UtKCN0aLf0oPRnAua4=";
  };

  patches = [
@@ -67,10 +67,6 @@ stdenv.mkDerivation (finalAttrs: {
    (replaceVars ./absolute_shlib_path.patch {
      inherit nixStoreDir;
    })

    # Fix getter heuristics regression
    # https://gitlab.gnome.org/GNOME/gobject-introspection/-/merge_requests/529
    ./0001-scanner-Prefer-some-getters-over-others.patch
  ]
  ++ lib.optionals x11Support [
    # Hardcode the cairo shared library path in the Cairo gir shipped with this package.