Beispiel #1
0
 def test_variable_product_dict(self):
     u1 = self.prog.NewVariable([1, 2], [], self.current_location)
     u2 = self.prog.NewVariable([3, 4], [], self.current_location)
     product = cfg_utils.variable_product_dict({"a": u1, "b": u2})
     pairs = [{k: a.data for k, a in d.items()} for d in product]
     self.assertCountEqual(pairs, [
         {
             "a": 1,
             "b": 3
         },
         {
             "a": 1,
             "b": 4
         },
         {
             "a": 2,
             "b": 3
         },
         {
             "a": 2,
             "b": 4
         },
     ])
 def get_call_combinations(self, node):
     """Get this function's call records."""
     all_combinations = []
     signature_data = set()
     for callargs, ret, node_after_call in self._call_records:
         try:
             combinations = cfg_utils.variable_product_dict(callargs)
         except cfg_utils.TooComplexError:
             combination = {
                 name:
                 self.ctx.convert.unsolvable.to_binding(node_after_call)
                 for name in callargs
             }
             combinations = [combination]
             ret = self.ctx.new_unsolvable(node_after_call)
         for combination in combinations:
             for return_value in ret.bindings:
                 values = list(combination.values()) + [return_value]
                 data = tuple(v.data for v in values)
                 if data in signature_data:
                     # This combination yields a signature we already know is possible
                     continue
                 # Optimization: when only one combination exists, assume it's visible.
                 if (len(combinations) == 1 and len(ret.bindings) == 1
                         or node_after_call.HasCombination(values)):
                     signature_data.add(data)
                     all_combinations.append(
                         (node_after_call, combination, return_value))
     if not all_combinations:
         # Fallback: Generate signatures only from the definition of the
         # method, not the way it's being used.
         param_binding = self.ctx.convert.unsolvable.to_binding(node)
         params = collections.defaultdict(lambda: param_binding)
         ret = self.ctx.convert.unsolvable.to_binding(node)
         all_combinations.append((node, params, ret))
     return all_combinations