private static void UnsubscribeFromBuildEvents(IVsTaskManager taskManager) { // unsubscribe from the VS task manager clear events if (taskManager != null && clearTasksEvent != null) { try { taskManager.RemoveClearTasksEvent(clearTasksEvent); } catch { } clearTasksEvent = null; } }
/// <summary> /// This is called under the following cirumstances: /// 1. Whenever solution update happens it is called with "buildStart" in angle brackets. /// 2. Whenever a project is built, it is called with the project name /// 3. If all projects are cleared (on rebuilds) it is called with an emtpyt string /// 4. Whenever the solution build is done, it is called with "buildDone" /// /// If we are running Clousot in a separate process, then we need to kill the process WHENEVER a build starts. /// Otherwise, the build may fail due to locked files. The tasks that haven't been analyzed at that point are /// saved away in a saved task list. /// /// During the build, we get to clear certain projects from the queue (those that are rebuilt) and the saved task list. /// Some of these will be added again by the build task executing. We can start processing these again as we get notified /// only when all dependencies are ready. /// /// At the end of the build "buildDone", we can put all saved tasks that weren't cleared back into the queue. /// </summary> /// <param name="taskManager"></param> /// <param name="projectName"></param> public void ivsTaskManager_OnClearTasks(IVsTaskManager taskManager, string projectName) { try { lock (backgroundTasks) { switch (projectName) { case "": backgroundTasks.Clear(); savedTasks = null; break; case "<buildStart>": var offset = 1; // save space for possible current task savedTasks = new AnalysisTask[backgroundTasks.Count + offset]; backgroundTasks.CopyTo(savedTasks, offset); backgroundTasks.Clear(); var currentTask = KillProc(taskManager); if (currentTask != null) { currentTask.process = null; // clear old process savedTasks[0] = currentTask; } break; case "<buildCancel>": // make sure not to restart any tasks backgroundTasks.Clear(); KillProc(taskManager); // for good measure savedTasks = null; break; case "<buildFailed>": // don't restart the tasks backgroundTasks.Clear(); KillProc(taskManager); savedTasks = null; break; case "<buildDone>": // add saved tasks back on queue if (savedTasks != null) { for (int i = 0; i < savedTasks.Length; i++) { var task = savedTasks[i]; if (task == null) continue; if (task.process == null) { task.SetupProcess(); // reset the process to start again when build is done. } backgroundTasks.Enqueue(task); } savedTasks = null; } StartupBackgroundThreadIfNeeded(); break; case "<release>": KillProc(taskManager); UnsubscribeFromBuildEvents(taskManager); backgroundTasks.Clear(); savedTasks = null; break; default: ClearProject(projectName); break; } } } catch (Exception exn) { System.Diagnostics.Trace.WriteLine("Code contracts task manager exception:\n" + exn.ToString()); } }
private static AnalysisTask KillProc(IVsTaskManager taskManager) { AnalysisTask result = null; // kill current process if (currentProcess != null) { try { if (!currentProcess.HasExited) { currentProcess.Kill(); result = currentTask; } } catch (Exception exn) { System.Diagnostics.Trace.WriteLine("Code contracts: Task manager exception: kill process:\n" + exn.ToString()); } finally { currentProcess = null; currentTask = null; } } return result; }
public void Invoke(IVsTaskManager taskManager, string projectName) { task.ivsTaskManager_OnClearTasks(taskManager, projectName); }