public StatementProcessor(MethodDescriptor m,
            PropGraphNodeDescriptor rv, PropGraphNodeDescriptor thisRef,
            IEnumerable<PropGraphNodeDescriptor> parameters,
            ProjectCodeProvider codeProvider)
        {
            // this.containerEntity = containerEntity;
            this.ReturnVariable = rv;
            this.Method = m;
            this.ParameterNodes = parameters;
            this.ThisRef = thisRef;
            this.PropagationGraph = new PropagationGraph();
            this.InstantiatedTypes = new HashSet<TypeDescriptor>();
            this.RemovedTypes = new HashSet<TypeDescriptor>();

            if (rv != null)
            {
                PropagationGraph.AddRet(rv);
            }
            if (thisRef != null)
            {
                PropagationGraph.Add(thisRef);
            }

            foreach (var parameter in this.ParameterNodes)
            {
                if (parameter != null)
                {
                    PropagationGraph.Add(parameter);
                }
            }
            //this.dispatcher = dispatcher;
        }
        public void AnalyzeEntireSolutionAsync()
        {
			foreach (var project in this.Solution.Projects)
			{
				var compilation = project.GetCompilationAsync().Result;
				var diag = compilation.GetDiagnostics();

				var theAssembly = compilation.Assembly;

				var continuations = new List<Task>();
				foreach (var tree in compilation.SyntaxTrees)
				{
					var provider = new ProjectCodeProvider(project, compilation);
                    var model = compilation.GetSemanticModel(tree);
                    var allMethodsVisitor = new AllMethodsVisitor(model, tree, this.Dispatcher);
					continuations.Add(allMethodsVisitor.Run(tree));
				}
				Task.WhenAll(continuations);
			}
            //if (this.Dispatcher is QueueingDispatcher)
            //{
            //    var qd = (QueueingDispatcher)this.Dispatcher;
            //    while (!qd.IsDoneProcessing)
            //    {
            //        Logger.Instance.Log("Waiting for the queue to empty up...");
            //        Thread.Sleep(1000);
            //    }
            //}

            /*
            if (mainMethod != null)
            {
                var methodDescriptor = new MethodDescriptor(mainMethod);
                callgraph.AddRootMethod(methodDescriptor);

                var mainMethodEntityDescriptor = new MethodEntityDescriptor<AMethod>(new AMethod(mainMethod));
                var mainEntityProcessor = this.Dispatcher.GetEntityWithProcessor(mainMethodEntityDescriptor) as MethodEntityProcessor<ANode,AType,AMethod>;
                
                // Just a test
                //mainEntityProcessor.MethodEntity.CurrentContext = new CallConext<AMethod, ANode>(mainEntityProcessor.MethodEntity.Method, null, null);
                
                var task = mainEntityProcessor.DoAnalysisAsync();
                task.Start();
                task.Wait();

                //var methodEntity = (MethodEntity<ANode, AType, AMethod>)mainEntityProcessor.Entity;
                var methodEntity = mainEntityProcessor.MethodEntity;
                Thread.Sleep(10);

                //if (this.Dispatcher is AsyncDispatcher)
                //{
                //    while (!mainEntityProcessor.HasFinishedAllProgatations())
                //    {
                //        Logger.Instance.Log("Waiting in Main for the queue to empty up... {0}",mainEntityProcessor.MethodEntity.NodesProcessing.Count());
                //        Thread.Sleep(10);
                //    }
                //}
                GenerateCallGraph();
            }*/
        }
        public void AnalyzeEntireSolution()
        {
			foreach (var project in this.Solution.Projects)
			{
				var compilation = project.GetCompilationAsync().Result;
				var diag = compilation.GetDiagnostics();

				var theAssembly = compilation.Assembly;

				foreach (var tree in compilation.SyntaxTrees)
				{
                    var model = compilation.GetSemanticModel(tree);
					var codeProvider = new ProjectCodeProvider(project, compilation);
					var allMethodsVisitor = new AllMethodsVisitor(model, tree, this.Dispatcher);
					allMethodsVisitor.Visit(tree.GetRoot());
				}
			}
            //if (this.Dispatcher is QueueingDispatcher)
            //{
            //    var qd = (QueueingDispatcher)this.Dispatcher;
            //    while (!qd.IsDoneProcessing)
            //    {
            //        Logger.Instance.Log("Waiting for the queue to empty up...");
            //        Thread.Sleep(1000);
            //    }
            //}

            /*
            if (mainMethod != null)
            {
                var methodDescriptor = new MethodDescriptor(mainMethod);
                callgraph.AddRootMethod(methodDescriptor);

				var mainMethodEntityDescriptor = new MethodEntityDescriptor<AMethod>(new AMethod(mainMethod));
				var mainEntityProcessor = this.Dispatcher.GetEntityWithProcessor(mainMethodEntityDescriptor);

				mainEntityProcessor.DoAnalysis();
				GenerateCallGraph();
            }*/
        }
        public static async Task<IProjectCodeProviderGrain> GetCodeProviderGrainAsync(MethodDescriptor methodDescriptor, Solution solution)
        {
            var cancellationSource = new CancellationTokenSource();
            var continuations = new List<Task<Compilation>>();
            foreach (var project in solution.Projects)
            {
                var compilation = await project.GetCompilationAsync(cancellationSource.Token);

                foreach (var tree in compilation.SyntaxTrees)
                {
                    var model = compilation.GetSemanticModel(tree);
                    var codeProvider = new ProjectCodeProvider(project, compilation);
                    var pair = await ProjectCodeProvider.FindMethodSyntaxAsync(model, tree, methodDescriptor);
                    if (pair != null)
                    {
                        // found it
                        cancellationSource.Cancel();
                        var codeProviderGrain = ProjectCodeProviderGrainFactory.GetGrain(project.Name);
                        return codeProviderGrain;
                    }
                }
            }
            return null;
        }
		internal static async Task<Tuple<ProjectCodeProvider, SyntaxTree>> GetProjectProviderAndSyntaxAsync(MethodDescriptor methodDescriptor, Solution solution)
		{
			Contract.Assert(solution != null);
			var cancellationSource = new CancellationTokenSource();
			var continuations = new List<Task<Compilation>>();
			foreach (var project in solution.Projects)
			{
				var compilation = await project.GetCompilationAsync(cancellationSource.Token);                
				foreach (var tree in compilation.SyntaxTrees)
				{
                    var model = compilation.GetSemanticModel(tree);
                    var codeProvider = new ProjectCodeProvider(project, compilation);
					var pair = await ProjectCodeProvider.FindMethodSyntaxAsync(model, tree, methodDescriptor);
					if (pair != null)
					{
						// found it
						cancellationSource.Cancel();
                        return new Tuple<ProjectCodeProvider, SyntaxTree>(codeProvider, tree);
					}
				}
			}
            // In some cases (e.g, default constructors or library methods, we are not going to find the code in the solution)
            // We should not throw an exception. Maybe return a dummy code Provider to let the analysis evolve
            // or an informative message in order to let the caller continue. We can declare the exception
            // throw new ArgumentException("Cannot find a provider for " + methodDescriptor);
            return null;
		}