1.1 --- a/common.py Sun Feb 12 23:23:28 2017 +0100
1.2 +++ b/common.py Sun Feb 19 17:31:31 2017 +0100
1.3 @@ -741,14 +741,14 @@
1.4
1.5 return isinstance(node.expr, compiler.ast.Getattr)
1.6
1.7 - def get_name_for_tracking(self, name, path=None):
1.8 + def get_name_for_tracking(self, name, ref=None):
1.9
1.10 """
1.11 Return the name to be used for attribute usage observations involving
1.12 - the given 'name' in the current namespace. If 'path' is indicated and
1.13 - the name is being used outside a function, return the path value;
1.14 - otherwise, return a path computed using the current namespace and the
1.15 - given name.
1.16 + the given 'name' in the current namespace. If 'ref' is indicated and
1.17 + the name is being used outside a function, return the origin information
1.18 + from 'ref'; otherwise, return a path computed using the current
1.19 + namespace and the given name.
1.20
1.21 The intention of this method is to provide a suitably-qualified name
1.22 that can be tracked across namespaces. Where globals are being
1.23 @@ -768,8 +768,13 @@
1.24
1.25 # For static namespaces, use the given qualified name.
1.26
1.27 - elif path:
1.28 - return path
1.29 + elif ref and ref.static():
1.30 + return ref.get_origin()
1.31 +
1.32 + # For non-static objects in static namespaces, use any alias.
1.33 +
1.34 + elif ref and ref.get_name():
1.35 + return ref.get_name()
1.36
1.37 # Otherwise, establish a name in the current namespace.
1.38
2.1 --- a/deducer.py Sun Feb 12 23:23:28 2017 +0100
2.2 +++ b/deducer.py Sun Feb 19 17:31:31 2017 +0100
2.3 @@ -917,9 +917,9 @@
2.4
2.5 # For each version of the name, obtain the access location.
2.6
2.7 - for version, (original_name, attrnames, access_number) in all_aliases.items():
2.8 + for version, (original_path, original_name, attrnames, access_number) in all_aliases.items():
2.9 accessor_location = (path, name, None, version)
2.10 - access_location = (path, original_name, attrnames, access_number)
2.11 + access_location = (original_path, original_name, attrnames, access_number)
2.12 init_item(self.alias_index, accessor_location, list)
2.13 self.alias_index[accessor_location].append(access_location)
2.14
3.1 --- a/inspector.py Sun Feb 12 23:23:28 2017 +0100
3.2 +++ b/inspector.py Sun Feb 19 17:31:31 2017 +0100
3.3 @@ -412,7 +412,7 @@
3.4 # if assigned in the namespace, or using an external name
3.5 # (presently just globals within classes).
3.6
3.7 - name = self.get_name_for_tracking(name_ref.name, name_ref.final())
3.8 + name = self.get_name_for_tracking(name_ref.name, name_ref.reference())
3.9 tracker = self.trackers[-1]
3.10
3.11 immediate_access = len(self.attrs) == 1
4.1 --- a/modules.py Sun Feb 12 23:23:28 2017 +0100
4.2 +++ b/modules.py Sun Feb 19 17:31:31 2017 +0100
4.3 @@ -495,11 +495,11 @@
4.4 f.readline() # "aliased names:"
4.5 line = f.readline().rstrip()
4.6 while line:
4.7 - name, version, original_name, attrnames, number = self._get_fields(line, 5)
4.8 + name, version, path, original_name, attrnames, number = self._get_fields(line, 5)
4.9 init_item(self.aliased_names, name, dict)
4.10 if number == "{}": number = None
4.11 else: number = int(number)
4.12 - self.aliased_names[name][int(version)] = (original_name, attrnames != "{}" and attrnames or None, number)
4.13 + self.aliased_names[name][int(version)] = (path, original_name, attrnames != "{}" and attrnames or None, number)
4.14 line = f.readline().rstrip()
4.15
4.16 def _get_function_parameters(self, f):
4.17 @@ -785,8 +785,8 @@
4.18 versions = aliases.items()
4.19 versions.sort()
4.20 for version, alias in versions:
4.21 - original_name, attrnames, number = alias
4.22 - print >>f, name, version, original_name, attrnames or "{}", number is None and "{}" or number
4.23 + path, original_name, attrnames, number = alias
4.24 + print >>f, name, version, path, original_name, attrnames or "{}", number is None and "{}" or number
4.25
4.26 print >>f
4.27 print >>f, "function parameters:"
5.1 --- a/resolving.py Sun Feb 12 23:23:28 2017 +0100
5.2 +++ b/resolving.py Sun Feb 19 17:31:31 2017 +0100
5.3 @@ -3,7 +3,7 @@
5.4 """
5.5 Name resolution.
5.6
5.7 -Copyright (C) 2016 Paul Boddie <paul@boddie.org.uk>
5.8 +Copyright (C) 2016, 2017 Paul Boddie <paul@boddie.org.uk>
5.9
5.10 This program is free software; you can redistribute it and/or modify it under
5.11 the terms of the GNU General Public License as published by the Free Software
5.12 @@ -289,7 +289,13 @@
5.13
5.14 if not ref:
5.15 if not invocation:
5.16 - aliased_names[i] = name_ref.original_name, name_ref.attrnames, name_ref.number
5.17 +
5.18 + # Record the path used for tracking purposes
5.19 + # alongside original name, attribute and access
5.20 + # number details.
5.21 +
5.22 + aliased_names[i] = path, name_ref.original_name, name_ref.attrnames, name_ref.number
5.23 +
5.24 continue
5.25
5.26 # Attempt to resolve a plain name reference.
5.27 @@ -303,7 +309,13 @@
5.28
5.29 if not origin:
5.30 if not invocation:
5.31 - aliased_names[i] = name_ref.name, None, name_ref.number
5.32 +
5.33 + # Record the path used for tracking purposes
5.34 + # alongside original name, attribute and access
5.35 + # number details.
5.36 +
5.37 + aliased_names[i] = path, name_ref.name, None, name_ref.number
5.38 +
5.39 continue
5.40
5.41 ref = self.get_resolved_object(origin)
6.1 --- a/translator.py Sun Feb 12 23:23:28 2017 +0100
6.2 +++ b/translator.py Sun Feb 19 17:31:31 2017 +0100
6.3 @@ -726,7 +726,7 @@
6.4 # the complete access.
6.5
6.6 name_ref = attr_expr and attr_expr.is_name() and attr_expr
6.7 - name = name_ref and self.get_name_for_tracking(name_ref.name, name_ref and name_ref.final()) or None
6.8 + name = name_ref and self.get_name_for_tracking(name_ref.name, name_ref and name_ref.reference()) or None
6.9
6.10 location = self.get_access_location(name, self.attrs)
6.11 refs = self.get_referenced_attributes(location)