1.1 --- a/deducer.py Fri Mar 17 00:59:21 2017 +0100
1.2 +++ b/deducer.py Sun Mar 19 00:16:10 2017 +0100
1.3 @@ -62,10 +62,18 @@
1.4
1.5 self.access_index = {}
1.6
1.7 + # Map definition locations to affected accesses.
1.8 +
1.9 + self.access_index_rev = {}
1.10 +
1.11 # Map aliases to accesses that define them.
1.12
1.13 self.alias_index = {}
1.14
1.15 + # Map accesses to aliases whose initial values are influenced by them.
1.16 +
1.17 + self.alias_index_rev = {}
1.18 +
1.19 # Map constant accesses to redefined accesses.
1.20
1.21 self.const_accesses = {}
1.22 @@ -521,9 +529,10 @@
1.23 self.accessor_all_general_types[location] = all_general_types = \
1.24 combine_types(general_class_types, general_instance_types, general_module_types)
1.25
1.26 - # Record guard information.
1.27 -
1.28 - if not constrained:
1.29 + # Record guard information but only for accessors employed by
1.30 + # accesses. There are no attribute accesses to guard, otherwise.
1.31 +
1.32 + if not constrained and self.access_index_rev.get(location):
1.33
1.34 # Record specific type guard details.
1.35
1.36 @@ -863,6 +872,13 @@
1.37 location = (path, name, None, version)
1.38 locations.append(location)
1.39
1.40 + # Map accessors to affected accesses.
1.41 +
1.42 + l = init_item(self.access_index_rev, location, set)
1.43 + l.add(access_location)
1.44 +
1.45 + # Map accesses to supplying accessors.
1.46 +
1.47 self.access_index[access_location] = locations
1.48
1.49 def get_accessors_for_access(self, access_location):
1.50 @@ -956,22 +972,21 @@
1.51
1.52 for (path, name), all_aliases in self.importer.all_aliased_names.items():
1.53
1.54 - # For each version of the name, obtain the access location.
1.55 -
1.56 - for version, (original_path, original_name, attrnames, access_number) in all_aliases.items():
1.57 - accessor_location = (path, name, None, version)
1.58 - access_location = (original_path, original_name, attrnames, access_number)
1.59 - init_item(self.alias_index, accessor_location, list)
1.60 - self.alias_index[accessor_location].append(access_location)
1.61 + # For each version of the name, obtain the access locations.
1.62 +
1.63 + for version, aliases in all_aliases.items():
1.64 + for (original_path, original_name, attrnames, access_number) in aliases:
1.65 + accessor_location = (path, name, None, version)
1.66 + access_location = (original_path, original_name, attrnames, access_number)
1.67 + init_item(self.alias_index, accessor_location, list)
1.68 + self.alias_index[accessor_location].append(access_location)
1.69
1.70 # Get aliases in terms of non-aliases and accesses.
1.71
1.72 for accessor_location, access_locations in self.alias_index.items():
1.73 self.update_aliases(accessor_location, access_locations)
1.74
1.75 - # Get accesses affected by aliases.
1.76 -
1.77 - self.alias_index_rev = {}
1.78 + # Get a mapping from accesses to affected aliases.
1.79
1.80 for accessor_location, access_locations in self.alias_index.items():
1.81 for access_location in access_locations:
1.82 @@ -997,10 +1012,16 @@
1.83 for access_location in access_locations:
1.84 (path, original_name, attrnames, access_number) = access_location
1.85
1.86 + # Locations may have been recorded for return values, but they may
1.87 + # not correspond to actual accesses.
1.88 +
1.89 + if not self.access_index.has_key(access_location):
1.90 + updated_locations.add(access_location)
1.91 +
1.92 # Where an alias refers to a name access, obtain the original name
1.93 # version details.
1.94
1.95 - if attrnames is None:
1.96 + elif attrnames is None:
1.97
1.98 # For each name version, attempt to determine any accesses that
1.99 # initialise the name.
1.100 @@ -1251,10 +1272,8 @@
1.101
1.102 # Specific name-based attribute accesses.
1.103
1.104 - alias_accesses = set()
1.105 -
1.106 for access_location, accessor_locations in self.access_index.items():
1.107 - self.record_types_for_access(access_location, accessor_locations, alias_accesses)
1.108 + self.record_types_for_access(access_location, accessor_locations)
1.109
1.110 # Anonymous references with attribute chains.
1.111
1.112 @@ -1374,6 +1393,23 @@
1.113 if self.record_types_for_alias(location):
1.114 updated_aliases.add(location)
1.115
1.116 + # Define accesses employing aliases.
1.117 +
1.118 + alias_accesses = set()
1.119 + affected_aliases = set()
1.120 +
1.121 + for alias in updated_aliases:
1.122 +
1.123 + # Access affected by the alias.
1.124 +
1.125 + if self.access_index_rev.has_key(alias):
1.126 + alias_accesses.update(self.access_index_rev[alias])
1.127 +
1.128 + # Another alias affected by the alias.
1.129 +
1.130 + elif self.alias_index_rev.has_key(alias):
1.131 + affected_aliases.update(self.alias_index_rev[alias])
1.132 +
1.133 # Update accesses employing aliases.
1.134
1.135 updated_accesses = set()
1.136 @@ -1382,9 +1418,7 @@
1.137 if self.record_types_for_access(access_location, self.access_index[access_location]):
1.138 updated_accesses.add(access_location)
1.139
1.140 - # Update aliases for updated accesses.
1.141 -
1.142 - affected_aliases = set()
1.143 + # Determine which aliases are affected by the updated accesses.
1.144
1.145 for access_location in updated_accesses:
1.146 if self.alias_index_rev.has_key(access_location):
1.147 @@ -1434,10 +1468,10 @@
1.148 # Detect any initialised name for the location.
1.149
1.150 if name:
1.151 - ref = self.get_initialised_name(location)
1.152 - if ref:
1.153 + refs = self.get_initialised_name(location)
1.154 + if refs:
1.155 (class_types, only_instance_types, module_types,
1.156 - _function_types, _var_types) = separate_types([ref])
1.157 + _function_types, _var_types) = separate_types(refs)
1.158 return class_types, only_instance_types, module_types, True, have_assignments
1.159
1.160 # Retrieve the recorded types for the usage.
1.161 @@ -1542,7 +1576,7 @@
1.162
1.163 self.referenced_attrs[location] = {}
1.164
1.165 - def record_types_for_access(self, access_location, accessor_locations, alias_accesses=None):
1.166 + def record_types_for_access(self, access_location, accessor_locations):
1.167
1.168 """
1.169 Define types for the 'access_location' associated with the given
1.170 @@ -1569,11 +1603,6 @@
1.171
1.172 for location in accessor_locations:
1.173
1.174 - # Remember accesses employing aliases.
1.175 -
1.176 - if alias_accesses is not None and self.alias_index.has_key(location):
1.177 - alias_accesses.add(access_location)
1.178 -
1.179 # Use the type information deduced for names from above.
1.180
1.181 if self.accessor_class_types.has_key(location):
1.182 @@ -1677,6 +1706,8 @@
1.183 new_accessor_instance_types = set()
1.184 new_accessor_module_types = set()
1.185
1.186 + refs = set()
1.187 +
1.188 for access_location in self.alias_index[accessor_location]:
1.189 location, name, attrnames, access_number = access_location
1.190 invocation = self.reference_invocations.get(access_location)
1.191 @@ -1743,52 +1774,67 @@
1.192 new_accessor_instance_types.update(instance_types)
1.193 new_accessor_module_types.update(module_types)
1.194
1.195 + refs.update(accessor_attrs)
1.196 +
1.197 # Alias references a name, not an access.
1.198
1.199 else:
1.200 - # Attempt to refine the types using initialised names.
1.201 -
1.202 - attr = self.get_initialised_name(access_location)
1.203 - if attr:
1.204 - attrs = [attr]
1.205 + # Attempt to refine the types using initialised names or
1.206 + # accessors.
1.207 +
1.208 + attrs = self.get_initialised_name(access_location)
1.209 +
1.210 + if attrs:
1.211 provider_attrs = self.convert_invocation_providers(attrs, invocation)
1.212 -
1.213 - (class_types, instance_types, module_types, function_types,
1.214 - var_types) = separate_types(provider_attrs)
1.215 -
1.216 - class_types = set(provider_class_types).intersection(class_types)
1.217 - instance_types = set(provider_instance_types).intersection(instance_types)
1.218 - module_types = set(provider_module_types).intersection(module_types)
1.219 -
1.220 - new_provider_class_types.update(class_types)
1.221 - new_provider_instance_types.update(instance_types)
1.222 - new_provider_module_types.update(module_types)
1.223 -
1.224 accessor_attrs = self.convert_invocations(attrs, invocation)
1.225 -
1.226 - (class_types, instance_types, module_types, function_types,
1.227 - var_types) = separate_types(accessor_attrs)
1.228 -
1.229 - class_types = set(accessor_class_types).intersection(class_types)
1.230 - instance_types = set(accessor_instance_types).intersection(instance_types)
1.231 - module_types = set(accessor_module_types).intersection(module_types)
1.232 -
1.233 - new_accessor_class_types.update(class_types)
1.234 - new_accessor_instance_types.update(instance_types)
1.235 - new_accessor_module_types.update(module_types)
1.236 + else:
1.237 + provider_attrs = self.get_provider_references(access_location)
1.238 + attrs = accessor_attrs = self.get_accessor_references(access_location)
1.239
1.240 # Where no further information is found, do not attempt to
1.241 # refine the defined accessor types.
1.242
1.243 - else:
1.244 + if not attrs:
1.245 return False
1.246
1.247 + (class_types, instance_types, module_types, function_types,
1.248 + var_types) = separate_types(provider_attrs)
1.249 +
1.250 + class_types = set(provider_class_types).intersection(class_types)
1.251 + instance_types = set(provider_instance_types).intersection(instance_types)
1.252 + module_types = set(provider_module_types).intersection(module_types)
1.253 +
1.254 + new_provider_class_types.update(class_types)
1.255 + new_provider_instance_types.update(instance_types)
1.256 + new_provider_module_types.update(module_types)
1.257 +
1.258 + (class_types, instance_types, module_types, function_types,
1.259 + var_types) = separate_types(accessor_attrs)
1.260 +
1.261 + class_types = set(accessor_class_types).intersection(class_types)
1.262 + instance_types = set(accessor_instance_types).intersection(instance_types)
1.263 + module_types = set(accessor_module_types).intersection(module_types)
1.264 +
1.265 + new_accessor_class_types.update(class_types)
1.266 + new_accessor_instance_types.update(instance_types)
1.267 + new_accessor_module_types.update(module_types)
1.268 +
1.269 + refs.update(accessor_attrs)
1.270 +
1.271 + # Update the alias relationships for invocations.
1.272 +
1.273 + self.update_alias_accesses(access_location, attrs)
1.274 +
1.275 # Record refined type details for the alias as an accessor.
1.276
1.277 self.init_definition_details(accessor_location)
1.278 self.update_provider_types(accessor_location, new_provider_class_types, new_provider_instance_types, new_provider_module_types)
1.279 self.update_accessor_types(accessor_location, new_accessor_class_types, new_accessor_instance_types, new_accessor_module_types)
1.280
1.281 + # Record reference details for the alias separately from accessors.
1.282 +
1.283 + self.referenced_objects[accessor_location] = refs
1.284 +
1.285 return new_accessor_class_types != accessor_class_types or \
1.286 new_accessor_instance_types != accessor_instance_types or \
1.287 new_accessor_module_types != accessor_module_types
1.288 @@ -1798,7 +1844,6 @@
1.289 # return value information.
1.290
1.291 else:
1.292 - old_refs = self.referenced_objects.get(accessor_location)
1.293 refs = set()
1.294
1.295 for access_location in self.alias_index[accessor_location]:
1.296 @@ -1822,8 +1867,14 @@
1.297 # Obtain references and attribute types for the access.
1.298
1.299 attrs = self.get_references_for_access(access_location)
1.300 - attrs = self.convert_invocations(attrs, invocation)
1.301 - refs.update(attrs)
1.302 +
1.303 + # Where no further information is found, do not attempt to
1.304 + # refine the defined accessor types.
1.305 +
1.306 + if not attrs:
1.307 + return False
1.308 +
1.309 + refs.update(self.convert_invocations(attrs, invocation))
1.310
1.311 # Alias references a name, not an access.
1.312
1.313 @@ -1831,15 +1882,83 @@
1.314
1.315 # Obtain initialiser information.
1.316
1.317 - attr = self.get_initialised_name(access_location)
1.318 - if attr:
1.319 - refs.update(self.convert_invocations([attr], invocation))
1.320 + attrs = self.get_initialised_name(access_location)
1.321 +
1.322 + if attrs:
1.323 + provider_attrs = self.convert_invocation_providers(attrs, invocation)
1.324 + accessor_attrs = self.convert_invocations(attrs, invocation)
1.325 + else:
1.326 + provider_attrs = self.get_provider_references(access_location)
1.327 + attrs = accessor_attrs = self.get_accessor_references(access_location)
1.328 +
1.329 + # Where no further information is found, do not attempt to
1.330 + # refine the defined accessor types.
1.331 +
1.332 + if not attrs:
1.333 + return False
1.334 +
1.335 + refs.update(self.convert_invocations(attrs, invocation))
1.336 +
1.337 + # Update the alias relationships for invocations.
1.338 +
1.339 + self.update_alias_accesses(access_location, attrs)
1.340 +
1.341 + # Record refined type details for the alias as an accessor.
1.342 +
1.343 + (class_types, instance_types, module_types, function_types,
1.344 + var_types) = separate_types(refs)
1.345 +
1.346 + # Where non-accessor types are found, do not attempt to refine
1.347 + # the defined accessor types.
1.348 +
1.349 + if not function_types and not var_types:
1.350 + self.init_definition_details(accessor_location)
1.351 + self.update_provider_types(accessor_location, class_types + instance_types, class_types + instance_types, module_types)
1.352 + self.update_accessor_types(accessor_location, class_types, instance_types, module_types)
1.353
1.354 # Record reference details for the alias separately from accessors.
1.355
1.356 self.referenced_objects[accessor_location] = refs
1.357
1.358 - return old_refs != refs
1.359 + return True
1.360 +
1.361 + def update_alias_accesses(self, access_location, refs):
1.362 +
1.363 + """
1.364 + Record 'access_location' as a location affected by the return values of
1.365 + 'refs' if an invocation is involved.
1.366 + """
1.367 +
1.368 + if not self.reference_invocations.has_key(access_location):
1.369 + return
1.370 +
1.371 + for ref in refs:
1.372 +
1.373 + # Initialising accesses originate from the return values.
1.374 +
1.375 + key = (ref.get_origin(), "$return")
1.376 + self._update_alias_accesses(access_location, key, self.importer.all_initialised_names)
1.377 + self._update_alias_accesses(access_location, key, self.importer.all_aliased_names)
1.378 +
1.379 + def _update_alias_accesses(self, access_location, key, names):
1.380 +
1.381 + """
1.382 + Make each return value provide information to the given
1.383 + 'access_location', using 'key' to reference the return value and 'names'
1.384 + as the collection of definitions.
1.385 + """
1.386 +
1.387 + versions = names.get(key)
1.388 + if not versions:
1.389 + return
1.390 +
1.391 + for version in versions.keys():
1.392 + location = key + (None, version)
1.393 + l = init_item(self.alias_index_rev, location, set)
1.394 + l.add(access_location)
1.395 +
1.396 + l = init_item(self.alias_index, access_location, set)
1.397 + l.add(location)
1.398
1.399 def get_references_for_access(self, access_location):
1.400
1.401 @@ -1863,11 +1982,20 @@
1.402 providers = set()
1.403
1.404 for ref in refs:
1.405 - for invocation_ref in self.convert_invocation_provider(ref):
1.406 - if invocation_ref.has_kind("<instance>"):
1.407 - providers.add(Reference("<class>", invocation_ref.get_origin()))
1.408 - providers.add(invocation_ref)
1.409 -
1.410 + invocation_providers = self.convert_accessors_to_providers(self.convert_invocation_provider(ref))
1.411 + providers.update(invocation_providers)
1.412 +
1.413 + return self.references_or_var(providers)
1.414 +
1.415 + def convert_accessors_to_providers(self, refs):
1.416 +
1.417 + "Convert accessor 'refs' to provider references."
1.418 +
1.419 + providers = set()
1.420 + for ref in refs:
1.421 + if ref.has_kind("<instance>"):
1.422 + providers.add(Reference("<class>", ref.get_origin()))
1.423 + providers.add(ref)
1.424 return providers
1.425
1.426 def convert_invocation_provider(self, ref):
1.427 @@ -1876,11 +2004,11 @@
1.428
1.429 if ref:
1.430 if ref.has_kind("<class>"):
1.431 - return ref
1.432 + return [ref]
1.433 elif ref.has_kind("<function>"):
1.434 return self.convert_function_invocation(ref)
1.435
1.436 - return Reference("<var>")
1.437 + return [Reference("<var>")]
1.438
1.439 def convert_invocations(self, refs, invocation):
1.440
1.441 @@ -1897,7 +2025,7 @@
1.442 for ref in refs:
1.443 invocation_refs.update(self.convert_invocation(ref))
1.444
1.445 - return invocation_refs
1.446 + return self.references_or_var(invocation_refs)
1.447
1.448 def convert_invocation(self, ref):
1.449
1.450 @@ -1915,12 +2043,23 @@
1.451
1.452 "Convert the function 'ref' to its return value reference."
1.453
1.454 - initialised_names = self.importer.all_initialised_names.get((ref.get_origin(), "$return"))
1.455 - if initialised_names:
1.456 - return set(initialised_names.values())
1.457 + initialisers = self.importer.all_initialised_names.get((ref.get_origin(), "$return"))
1.458 + aliases = self.importer.all_aliased_names.get((ref.get_origin(), "$return"))
1.459 +
1.460 + if initialisers and not aliases:
1.461 + return set(initialisers.values())
1.462
1.463 return [Reference("<var>")]
1.464
1.465 + def references_or_var(self, refs):
1.466 +
1.467 + var = Reference("<var>")
1.468 +
1.469 + if var in refs:
1.470 + return set([var])
1.471 + else:
1.472 + return refs
1.473 +
1.474 def get_initialised_name(self, access_location):
1.475
1.476 """
1.477 @@ -1932,9 +2071,39 @@
1.478
1.479 # Use initialiser information, if available.
1.480
1.481 - refs = self.importer.all_initialised_names.get((path, name))
1.482 - if refs and refs.has_key(version):
1.483 - return refs[version]
1.484 + initialisers = self.importer.all_initialised_names.get((path, name))
1.485 + if initialisers and initialisers.has_key(version):
1.486 + return [initialisers[version]]
1.487 + else:
1.488 + return None
1.489 +
1.490 + def get_accessor_references(self, access_location):
1.491 +
1.492 + """
1.493 + Return references corresponding to accessor details at the given
1.494 + 'access_location'.
1.495 + """
1.496 +
1.497 + if self.accessor_class_types.has_key(access_location):
1.498 + class_types = self.accessor_class_types[access_location]
1.499 + instance_types = self.accessor_instance_types[access_location]
1.500 + module_types = self.accessor_module_types[access_location]
1.501 + return combine_types(class_types, instance_types, module_types)
1.502 + else:
1.503 + return None
1.504 +
1.505 + def get_provider_references(self, access_location):
1.506 +
1.507 + """
1.508 + Return references corresponding to provider details at the given
1.509 + 'access_location'.
1.510 + """
1.511 +
1.512 + if self.provider_class_types.has_key(access_location):
1.513 + class_types = self.provider_class_types[access_location]
1.514 + instance_types = self.provider_instance_types[access_location]
1.515 + module_types = self.provider_module_types[access_location]
1.516 + return combine_types(class_types, instance_types, module_types)
1.517 else:
1.518 return None
1.519
4.1 --- a/modules.py Fri Mar 17 00:59:21 2017 +0100
4.2 +++ b/modules.py Sun Mar 19 00:16:10 2017 +0100
4.3 @@ -71,10 +71,6 @@
4.4
4.5 self.exception_namespaces = set()
4.6
4.7 - # Return value details.
4.8 -
4.9 - self.return_values = {}
4.10 -
4.11 # Attribute usage at module and function levels.
4.12
4.13 self.attr_usage = {}
4.14 @@ -102,6 +98,10 @@
4.15 self.initialised_names = {}
4.16 self.aliased_names = {}
4.17
4.18 + # Return values for functions in this module.
4.19 +
4.20 + self.return_values = {}
4.21 +
4.22 def __repr__(self):
4.23 return "BasicModule(%r, %r)" % (self.name, self.importer)
4.24
4.25 @@ -496,7 +496,9 @@
4.26 init_item(self.aliased_names, (path, name), dict)
4.27 if number == "{}": number = None
4.28 else: number = int(number)
4.29 - self.aliased_names[(path, name)][int(version)] = (original_path, original_name, attrnames != "{}" and attrnames or None, number)
4.30 + d = self.aliased_names[(path, name)]
4.31 + init_item(d, int(version), list)
4.32 + d[int(version)].append((original_path, original_name, attrnames != "{}" and attrnames or None, number))
4.33 line = f.readline().rstrip()
4.34
4.35 def _get_function_parameters(self, f):
4.36 @@ -763,9 +765,10 @@
4.37 for (path, name), aliases in assignments:
4.38 versions = aliases.items()
4.39 versions.sort()
4.40 - for version, alias in versions:
4.41 - original_path, original_name, attrnames, number = alias
4.42 - print >>f, path, name, version, original_path, original_name, attrnames or "{}", number is None and "{}" or number
4.43 + for version, version_aliases in versions:
4.44 + for alias in version_aliases:
4.45 + original_path, original_name, attrnames, number = alias
4.46 + print >>f, path, name, version, original_path, original_name, attrnames or "{}", number is None and "{}" or number
4.47
4.48 print >>f
4.49 print >>f, "function parameters:"
5.1 --- a/resolving.py Fri Mar 17 00:59:21 2017 +0100
5.2 +++ b/resolving.py Sun Mar 19 00:16:10 2017 +0100
5.3 @@ -244,11 +244,11 @@
5.4 aliased_names = {}
5.5
5.6 for i, name_ref in enumerate(values):
5.7 - initialised_ref, aliased_name = self.resolve_reference(path, name_ref)
5.8 + initialised_ref, _aliased_names = self.resolve_reference(path, name_ref)
5.9 if initialised_ref:
5.10 initialised_names[i] = initialised_ref
5.11 - if aliased_name:
5.12 - aliased_names[i] = aliased_name
5.13 + if _aliased_names:
5.14 + aliased_names[i] = _aliased_names
5.15
5.16 if initialised_names:
5.17 self.initialised_names[(path, name)] = initialised_names
5.18 @@ -269,11 +269,11 @@
5.19 aliased_names = {}
5.20
5.21 for i, name_ref in enumerate(values):
5.22 - initialised_ref, aliased_name = self.resolve_reference(path, name_ref)
5.23 + initialised_ref, _aliased_names = self.resolve_reference(path, name_ref)
5.24 if initialised_ref:
5.25 initialised_names[i] = initialised_ref
5.26 - if aliased_name:
5.27 - aliased_names[i] = aliased_name
5.28 + if _aliased_names:
5.29 + aliased_names[i] = _aliased_names
5.30
5.31 if initialised_names:
5.32 self.initialised_names[(path, "$return")] = initialised_names
5.33 @@ -290,7 +290,7 @@
5.34 const_accesses = self.const_accesses.get(path)
5.35
5.36 initialised_ref = None
5.37 - aliased_name = None
5.38 + aliased_names = None
5.39 no_reference = None, None
5.40
5.41 # Unwrap invocations.
5.42 @@ -336,9 +336,9 @@
5.43 # alongside original name, attribute and access
5.44 # number details.
5.45
5.46 - aliased_name = path, name_ref.original_name, name_ref.attrnames, name_ref.number
5.47 + aliased_names = [(path, name_ref.original_name, name_ref.attrnames, name_ref.number)]
5.48
5.49 - return None, aliased_name
5.50 + return None, aliased_names
5.51
5.52 # Attempt to resolve a plain name reference.
5.53
5.54 @@ -355,9 +355,9 @@
5.55 # alongside original name, attribute and access
5.56 # number details.
5.57
5.58 - aliased_name = path, name_ref.name, None, name_ref.number
5.59 + aliased_names = [(path, name_ref.name, None, name_ref.number)]
5.60
5.61 - return None, aliased_name
5.62 + return None, aliased_names
5.63
5.64 ref = self.get_resolved_object(ref.get_origin())
5.65 if not ref:
5.66 @@ -382,13 +382,32 @@
5.67
5.68 # Convert class invocations to instances.
5.69
5.70 - if ref and invocation or ref.has_kind("<invoke>"):
5.71 - ref = self.convert_invocation(ref)
5.72 + if ref and (invocation or ref.has_kind("<invoke>")):
5.73 + target_ref = ref
5.74 + ref = self.convert_invocation(target_ref)
5.75 +
5.76 + if not ref or ref.has_kind("<var>"):
5.77 + aliased_names = self.get_aliases_for_target(target_ref.get_origin())
5.78 + else:
5.79 + initialised_ref = ref
5.80
5.81 - if ref and not ref.has_kind("<var>"):
5.82 + elif ref and not ref.has_kind("<var>"):
5.83 initialised_ref = ref
5.84 +
5.85 + return initialised_ref, aliased_names
5.86
5.87 - return initialised_ref, aliased_name
5.88 + def get_aliases_for_target(self, path):
5.89 +
5.90 + "Return a list of return value locations for the given 'path'."
5.91 +
5.92 + return_values = self.importer.all_return_values.get(path)
5.93 + locations = []
5.94 +
5.95 + if return_values:
5.96 + for version in range(0, len(return_values)):
5.97 + locations.append((path, "$return", None, version))
5.98 +
5.99 + return locations
5.100
5.101 def resolve_literals(self):
5.102