From 7b2d3699ad117199bc316c7007cc5984c3b09368 Mon Sep 17 00:00:00 2001 From: Maximiliano Sandoval 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