internal async Task<ISet<TypeDescriptor>> GetPotentialTypesAsync(PropGraphNodeDescriptor n, PropagationGraph propGraph, ICodeProvider codeProvider)
 {
     var result = new HashSet<TypeDescriptor>();
     foreach (var typeDescriptor in propGraph.GetTypes(n))
     {
         // TO-DO fix by adding a where T: AnalysisType
         if (typeDescriptor.IsConcreteType)
         {
             result.Add(typeDescriptor);
         }
         else
         {
             Contract.Assert(this.InstatiatedTypes != null);
             foreach(var candidateType in this.InstatiatedTypes)
             {
                 var isSubtype = await codeProvider.IsSubtypeAsync(candidateType, typeDescriptor);
                 if(isSubtype)
                 {
                     result.Add(candidateType);
                 }
             }
         }
     }
     return result;
 }
		internal ISet<TypeDescriptor> GetPotentialTypes(PropGraphNodeDescriptor n, PropagationGraph propGraph, ICodeProvider codeProvider)
		{
			var result = new HashSet<TypeDescriptor>();
			foreach (var typeDescriptor in propGraph.GetTypes(n))
			{
				// TO-DO fix by adding a where T: AnalysisType
				if (typeDescriptor.IsConcreteType)
				{
					result.Add(typeDescriptor);
				}
				else
				{
                    // If it is a declaredTyped it means we were not able to compute a concrete type
                    // Therefore, we instantiate all compatible types for the set of instantiated types
					//result.UnionWith(this.InstatiatedTypes.Where(iType => iType.IsSubtype(typeDescriptor)));
                    Contract.Assert(this.InstatiatedTypes != null);
                    // Diego: This requires a Code Provider. Now it will simply fail.
                    result.UnionWith(this.InstatiatedTypes.Where(candidateTypeDescriptor
                                            => codeProvider.IsSubtype(candidateTypeDescriptor, typeDescriptor)));
				}
			}
			return result;
		}
		internal abstract ISet<MethodDescriptor> ComputeCalleesForNode(PropagationGraph propGraph, ICodeProvider codeProvider);
 internal virtual Task<ISet<MethodDescriptor>> ComputeCalleesForNodeAsync(PropagationGraph propGraph, ICodeProvider codeProvider)
 {
     throw new NotImplementedException();
 }
        private async Task<ISet<MethodDescriptor>> GetDelegateCalleesAsync(VariableNode delegateNode, PropagationGraph propGraph, ICodeProvider codeProvider)
        {
            var callees = new HashSet<MethodDescriptor>();
            var typeDescriptors = propGraph.GetTypes(delegateNode);
            foreach (var delegateInstance in propGraph.GetDelegates(delegateNode))
            {
                if (typeDescriptors.Count() > 0)
                {
                    foreach (var typeDescriptor in typeDescriptors)
                    {
                        // TO-DO!!!
                        // Ugly: I'll fix it
                        //var aMethod = delegateInstance.FindMethodImplementation(type);
                        var aMethod = await codeProvider.FindMethodImplementationAsync(delegateInstance, typeDescriptor);
                        callees.Add(aMethod);
                    }
                }
                else
                {
                    // if Count is 0, it is a delegate that do not came form an instance variable
                    callees.Add(delegateInstance);
                }
            }

            return callees;
        }
 internal override async Task<ISet<MethodDescriptor>> ComputeCalleesForNodeAsync(PropagationGraph propGraph, ICodeProvider codeProvider)
 {
     return await GetDelegateCalleesAsync(this.CalleeDelegate, propGraph, codeProvider);
 }
		internal override ISet<MethodDescriptor> ComputeCalleesForNode(PropagationGraph propGraph, ICodeProvider codeProvider)
		{
			return GetDelegateCallees(this.CalleeDelegate, propGraph, codeProvider);
		}
 internal async override Task<ISet<MethodDescriptor>> ComputeCalleesForNodeAsync(PropagationGraph propGraph, ICodeProvider codeProvider)
 {
     var calleesForNode = new HashSet<MethodDescriptor>();
     if (this.Receiver != null)
     {
         // I replaced the invocation for a local call to mark that functionality is missing
         //var callees = GetPotentialTypes(this.Receiver, propGraph)
         //    .Select(t => this.Callee.FindMethodImplementation(t));
         foreach(var type in GetPotentialTypes(this.Receiver, propGraph, codeProvider))
         {
             var realCallee = await codeProvider.FindMethodImplementationAsync(this.Callee, type);
             calleesForNode.Add(realCallee);
         }
     }
     else
     {
         calleesForNode.Add(this.Callee);
     }
     return calleesForNode;
 }
		internal override ISet<MethodDescriptor> ComputeCalleesForNode(PropagationGraph propGraph, ICodeProvider codeProvider)
		{
			var calleesForNode = new HashSet<MethodDescriptor>();
			if (this.Receiver != null)
			{
                // I replaced the invocation for a local call to mark that functionality is missing
                //var callees = GetPotentialTypes(this.Receiver, propGraph)
                //    .Select(t => this.Callee.FindMethodImplementation(t));
                var callees = GetPotentialTypes(this.Receiver, propGraph, codeProvider)
                        .Select(t => codeProvider.FindMethodImplementation(this.Callee,t));
				calleesForNode.UnionWith(callees);
			}
			else
			{
				calleesForNode.Add(this.Callee);
			}
			return calleesForNode;
		}