1.1 --- a/deducer.py Mon Mar 13 01:46:58 2017 +0100
1.2 +++ b/deducer.py Mon Mar 13 01:49:11 2017 +0100
1.3 @@ -1623,11 +1623,19 @@
1.4 provider_instance_types = self.provider_instance_types[accessor_location]
1.5 provider_module_types = self.provider_module_types[accessor_location]
1.6
1.7 + accessor_class_types = self.accessor_class_types[accessor_location]
1.8 + accessor_instance_types = self.accessor_instance_types[accessor_location]
1.9 + accessor_module_types = self.accessor_module_types[accessor_location]
1.10 +
1.11 # Find details for any corresponding access.
1.12
1.13 - all_class_types = set()
1.14 - all_instance_types = set()
1.15 - all_module_types = set()
1.16 + new_provider_class_types = set()
1.17 + new_provider_instance_types = set()
1.18 + new_provider_module_types = set()
1.19 +
1.20 + new_accessor_class_types = set()
1.21 + new_accessor_instance_types = set()
1.22 + new_accessor_module_types = set()
1.23
1.24 for access_location in self.alias_index[accessor_location]:
1.25 location, name, attrnames, access_number = access_location
1.26 @@ -1650,10 +1658,20 @@
1.27 # Obtain references and attribute types for the access.
1.28
1.29 attrs = self.get_references_for_access(access_location)
1.30 - attrs = self.convert_invocation_providers(attrs, invocation)
1.31 +
1.32 + # Where no specific attributes are defined, do not attempt
1.33 + # to refine the alias's types.
1.34 +
1.35 + if not attrs:
1.36 + return
1.37 +
1.38 + # Invocations converting class accessors to instances do not
1.39 + # change the nature of class providers.
1.40 +
1.41 + provider_attrs = self.convert_invocation_providers(attrs, invocation)
1.42
1.43 (class_types, instance_types, module_types, function_types,
1.44 - var_types) = separate_types(attrs)
1.45 + var_types) = separate_types(provider_attrs)
1.46
1.47 # Where non-accessor types are found, do not attempt to refine
1.48 # the defined accessor types.
1.49 @@ -1661,13 +1679,30 @@
1.50 if function_types or var_types:
1.51 return
1.52
1.53 - # Invocations converting class accessors to instances do not
1.54 - # change the nature of class providers.
1.55 -
1.56 class_types = set(provider_class_types).intersection(class_types)
1.57 instance_types = set(provider_instance_types).intersection(instance_types)
1.58 module_types = set(provider_module_types).intersection(module_types)
1.59
1.60 + new_provider_class_types.update(class_types)
1.61 + new_provider_instance_types.update(instance_types)
1.62 + new_provider_module_types.update(module_types)
1.63 +
1.64 + # Accessors are updated separately, employing invocation
1.65 + # result details.
1.66 +
1.67 + accessor_attrs = self.convert_invocations(attrs, invocation)
1.68 +
1.69 + (class_types, instance_types, module_types, function_types,
1.70 + var_types) = separate_types(accessor_attrs)
1.71 +
1.72 + class_types = set(accessor_class_types).intersection(class_types)
1.73 + instance_types = set(accessor_instance_types).intersection(instance_types)
1.74 + module_types = set(accessor_module_types).intersection(module_types)
1.75 +
1.76 + new_accessor_class_types.update(class_types)
1.77 + new_accessor_instance_types.update(instance_types)
1.78 + new_accessor_module_types.update(module_types)
1.79 +
1.80 # Alias references a name, not an access.
1.81
1.82 else:
1.83 @@ -1675,10 +1710,32 @@
1.84
1.85 attr = self.get_initialised_name(access_location)
1.86 if attr:
1.87 - attrs = self.convert_invocation_providers([attr], invocation)
1.88 + attrs = [attr]
1.89 + provider_attrs = self.convert_invocation_providers(attrs, invocation)
1.90
1.91 (class_types, instance_types, module_types, function_types,
1.92 - var_types) = separate_types(attrs)
1.93 + var_types) = separate_types(provider_attrs)
1.94 +
1.95 + class_types = set(provider_class_types).intersection(class_types)
1.96 + instance_types = set(provider_instance_types).intersection(instance_types)
1.97 + module_types = set(provider_module_types).intersection(module_types)
1.98 +
1.99 + new_provider_class_types.update(class_types)
1.100 + new_provider_instance_types.update(instance_types)
1.101 + new_provider_module_types.update(module_types)
1.102 +
1.103 + accessor_attrs = self.convert_invocations(attrs, invocation)
1.104 +
1.105 + (class_types, instance_types, module_types, function_types,
1.106 + var_types) = separate_types(accessor_attrs)
1.107 +
1.108 + class_types = set(accessor_class_types).intersection(class_types)
1.109 + instance_types = set(accessor_instance_types).intersection(instance_types)
1.110 + module_types = set(accessor_module_types).intersection(module_types)
1.111 +
1.112 + new_accessor_class_types.update(class_types)
1.113 + new_accessor_instance_types.update(instance_types)
1.114 + new_accessor_module_types.update(module_types)
1.115
1.116 # Where no further information is found, do not attempt to
1.117 # refine the defined accessor types.
1.118 @@ -1686,14 +1743,11 @@
1.119 else:
1.120 return
1.121
1.122 - all_class_types.update(class_types)
1.123 - all_instance_types.update(instance_types)
1.124 - all_module_types.update(module_types)
1.125 -
1.126 # Record refined type details for the alias as an accessor.
1.127
1.128 self.init_definition_details(accessor_location)
1.129 - self.record_reference_types(accessor_location, all_class_types, all_instance_types, all_module_types, False)
1.130 + self.update_provider_types(accessor_location, new_provider_class_types, new_provider_instance_types, new_provider_module_types)
1.131 + self.update_accessor_types(accessor_location, new_accessor_class_types, new_accessor_instance_types, new_accessor_module_types)
1.132
1.133 # Without an access, attempt to identify references for the alias.
1.134 # Invocations convert classes to instances and also attempt to find
1.135 @@ -1724,9 +1778,7 @@
1.136
1.137 # Alias references an attribute access.
1.138
1.139 - attrname = attrnames and attrnames[0]
1.140 -
1.141 - if attrname:
1.142 + if attrnames:
1.143
1.144 # Obtain references and attribute types for the access.
1.145
1.146 @@ -1751,7 +1803,8 @@
1.147 instance_types = self.provider_instance_types[access_location]
1.148 module_types = self.provider_module_types[access_location]
1.149
1.150 - refs.update(combine_types(class_types, instance_types, module_types))
1.151 + types = combine_types(class_types, instance_types, module_types)
1.152 + refs.update(self.convert_invocation_providers(types, invocation))
1.153
1.154 # Record reference details for the alias separately from accessors.
1.155
1.156 @@ -1858,15 +1911,13 @@
1.157
1.158 # Update the type details for the location.
1.159
1.160 - self.provider_class_types[location].update(class_types)
1.161 - self.provider_instance_types[location].update(instance_types)
1.162 - self.provider_module_types[location].update(module_types)
1.163 + self.update_provider_types(location, class_types, instance_types, module_types)
1.164
1.165 # Class types support classes and instances as accessors.
1.166 # Instance-only and module types support only their own kinds as
1.167 # accessors.
1.168
1.169 - path, name, version, attrnames = location
1.170 + path, name, attrnames, version = location
1.171
1.172 if invocations:
1.173 class_only_types = self.filter_for_invocations(class_types, invocations)
1.174 @@ -1890,6 +1941,28 @@
1.175 if constrained:
1.176 self.accessor_constrained.add(location)
1.177
1.178 + def update_provider_types(self, location, class_types, instance_types, module_types):
1.179 +
1.180 + """
1.181 + Update provider types for the given 'location', adding 'class_types',
1.182 + 'instance_types' and 'module_types' to those already stored.
1.183 + """
1.184 +
1.185 + self.provider_class_types[location].update(class_types)
1.186 + self.provider_instance_types[location].update(instance_types)
1.187 + self.provider_module_types[location].update(module_types)
1.188 +
1.189 + def update_accessor_types(self, location, class_types, instance_types, module_types):
1.190 +
1.191 + """
1.192 + Update accessor types for the given 'location', adding 'class_types',
1.193 + 'instance_types' and 'module_types' to those already stored.
1.194 + """
1.195 +
1.196 + self.accessor_class_types[location].update(class_types)
1.197 + self.accessor_instance_types[location].update(instance_types)
1.198 + self.accessor_module_types[location].update(module_types)
1.199 +
1.200 def filter_for_invocations(self, class_types, attrnames):
1.201
1.202 """