// // TaskStore.cs // // Author: // Lluis Sanchez Gual // // Copyright (c) 2009 Novell, Inc (http://www.novell.com) // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. //------------------------------------------------------------------------------ // // This code was generated by a tool. // Runtime Version:2.0.50727.3074 // // Changes to this file may cause incorrect behavior and will be lost if // the code is regenerated. // //------------------------------------------------------------------------------ using System; using System.Collections; using System.Collections.Generic; using MonoDevelop.Core; using MonoDevelop.Projects; using MonoDevelop.Ide.Gui; using MonoDevelop.Ide.Gui.Content; using MonoDevelop.Ide.Navigation; namespace MonoDevelop.Ide.Tasks { public class TaskStore: IEnumerable, ILocationList { int taskUpdateCount; List tasks = new List (); Dictionary taskIndex = new Dictionary (); public event TaskEventHandler TasksAdded; public event TaskEventHandler TasksRemoved; public event TaskEventHandler TasksChanged; List tasksAdded; List tasksRemoved; public TaskStore () { IdeApp.Workspace.FileRenamedInProject += ProjectFileRenamed; IdeApp.Workspace.FileRemovedFromProject += ProjectFileRemoved; MonoDevelop.Projects.Text.TextFileService.CommitCountChanges += delegate (object sender, MonoDevelop.Projects.Text.TextFileEventArgs args) { foreach (Task task in GetFileTasks (args.TextFile.Name.FullPath)) task.SavedLine = -1; }; MonoDevelop.Projects.Text.TextFileService.ResetCountChanges += delegate (object sender, MonoDevelop.Projects.Text.TextFileEventArgs args) { Task[] ctasks = GetFileTasks (args.TextFile.Name.FullPath); foreach (Task task in ctasks) { if (task.SavedLine != -1) { task.Line = task.SavedLine; task.SavedLine = -1; } } NotifyTasksChanged (ctasks); }; MonoDevelop.Projects.Text.TextFileService.LineCountChanged += delegate (object sender, MonoDevelop.Projects.Text.LineCountEventArgs args) { if (args.TextFile == null || args.TextFile.Name.IsNullOrEmpty) return; Task[] ctasks = GetFileTasks (args.TextFile.Name.FullPath); foreach (Task task in ctasks) { if (task.Line > args.LineNumber || (task.Line == args.LineNumber && task.Column >= args.Column)) { if (task.SavedLine == -1) task.SavedLine = task.Line; task.Line += args.LineCount; } } NotifyTasksChanged (ctasks); }; } public void Add (Task task) { tasks.Add (task); OnTaskAdded (task); } public void AddRange (IEnumerable newTasks) { BeginTaskUpdates (); try { foreach (Task t in newTasks) { tasks.Add (t); OnTaskAdded (t); } } finally { EndTaskUpdates (); } } public void RemoveRange (IEnumerable tasks) { BeginTaskUpdates (); try { foreach (Task t in tasks) { if (this.tasks.Remove (t)) OnTaskRemoved (t); } } finally { EndTaskUpdates (); } } public void RemoveItemTasks (IWorkspaceObject parent) { RemoveRange (new List (GetItemTasks (parent))); } public void RemoveItemTasks (IWorkspaceObject parent, bool checkHierarchy) { RemoveRange (new List (GetItemTasks (parent, checkHierarchy))); } public void RemoveFileTasks (FilePath file) { RemoveRange (new List (GetFileTasks (file))); } public void Remove (Task task) { if (tasks.Remove (task)) OnTaskRemoved (task); } public void Clear () { try { BeginTaskUpdates (); List toRemove = tasks; tasks = new List (); foreach (Task t in toRemove) OnTaskRemoved (t); } finally { EndTaskUpdates (); } } public void ClearByOwner (object owner) { try { BeginTaskUpdates (); List toRemove = new List (GetOwnerTasks (owner)); foreach (Task t in toRemove) Remove (t); } finally { EndTaskUpdates (); } } public int Count { get { return tasks.Count; } } public IEnumerator GetEnumerator () { return tasks.GetEnumerator (); } IEnumerator IEnumerable.GetEnumerator () { return ((IEnumerable)tasks).GetEnumerator (); } public IEnumerable GetOwnerTasks (object owner) { foreach (Task t in tasks) { if (t.Owner == owner) yield return t; } } public Task[] GetFileTasks (FilePath file) { Task[] ta; if (taskIndex.TryGetValue (file, out ta)) return ta; else return new Task [0]; } public IEnumerable GetItemTasks (IWorkspaceObject parent) { return GetItemTasks (parent, true); } public IEnumerable GetItemTasks (IWorkspaceObject parent, bool checkHierarchy) { foreach (Task t in tasks) { if (t.BelongsToItem (parent, checkHierarchy)) yield return t; } } public void BeginTaskUpdates () { if (taskUpdateCount++ != 0) return; tasksAdded = new List (); tasksRemoved = new List (); } public void EndTaskUpdates () { if (--taskUpdateCount != 0) return; List oldAdded = tasksAdded; List oldRemoved = tasksRemoved; tasksAdded = null; tasksRemoved = null; if (oldRemoved.Count > 0) NotifyTasksRemoved (oldRemoved); if (oldAdded.Count > 0) NotifyTasksAdded (oldAdded); } void NotifyTasksAdded (IEnumerable ts) { try { if (TasksAdded != null) TasksAdded (null, new TaskEventArgs (ts)); } catch (Exception ex) { LoggingService.LogError ("Error while notifying task changes", ex); } } void NotifyTasksChanged (IEnumerable ts) { try { if (TasksChanged != null) TasksChanged (null, new TaskEventArgs (ts)); } catch (Exception ex) { LoggingService.LogError ("Error while notifying task changes", ex); } } void NotifyTasksRemoved (IEnumerable ts) { try { if (TasksRemoved != null) TasksRemoved (null, new TaskEventArgs (ts)); } catch (Exception ex) { LoggingService.LogError ("Error while notifying task changes", ex); } } internal void OnTaskAdded (Task t) { if (t.FileName != FilePath.Null) { Task[] ta; if (taskIndex.TryGetValue (t.FileName, out ta)) { Array.Resize (ref ta, ta.Length + 1); ta [ta.Length - 1] = t; } else { ta = new Task [] { t }; } taskIndex [t.FileName] = ta; } if (tasksAdded != null) tasksAdded.Add (t); else NotifyTasksAdded (new Task [] { t }); } internal void OnTaskRemoved (Task t) { if (t.FileName != FilePath.Null) { Task[] ta; if (taskIndex.TryGetValue (t.FileName, out ta)) { if (ta.Length == 1) { if (ta [0] == t) taskIndex.Remove (t.FileName); } else { int i = Array.IndexOf (ta, t); if (i != -1) { Task[] newTa = new Task [ta.Length - 1]; Array.Copy (ta, 0, newTa, 0, i); Array.Copy (ta, i+1, newTa, i, ta.Length - i - 1); taskIndex [t.FileName] = newTa; } } } } if (tasksRemoved != null) tasksRemoved.Add (t); else NotifyTasksRemoved (new Task [] { t }); } void ProjectFileRemoved (object sender, ProjectFileEventArgs args) { BeginTaskUpdates (); try { foreach (ProjectFileEventInfo e in args) { foreach (Task curTask in new List (GetFileTasks (e.ProjectFile.FilePath))) { Remove (curTask); } } } finally { EndTaskUpdates (); } } void ProjectFileRenamed (object sender, ProjectFileRenamedEventArgs args) { BeginTaskUpdates (); try { foreach (ProjectFileRenamedEventInfo e in args) { Task[] ctasks = GetFileTasks (e.OldName); foreach (Task curTask in ctasks) curTask.FileName = e.NewName; taskIndex.Remove (e.OldName); taskIndex [e.NewName] = ctasks; tasksAdded.AddRange (ctasks); tasksRemoved.AddRange (ctasks); } } finally { EndTaskUpdates (); } } #region ILocationList implementation Task currentLocationTask; TaskSeverity iteratingSeverity; public void ResetLocationList () { currentLocationTask = null; iteratingSeverity = TaskSeverity.Error; } public event EventHandler CurrentLocationTaskChanged; public Task CurrentLocationTask { get { return currentLocationTask; } set { currentLocationTask = value; iteratingSeverity = value != null ? value.Severity : TaskSeverity.Error; } } public NavigationPoint GetNextLocation () { return GetNextLocation (false); } class TaskNavigationPoint : TextFileNavigationPoint { Task task; public TaskNavigationPoint (Task task) : base (task.FileName, task.Line, task.Column) { this.task = task; } protected override Document DoShow () { Document result = base.DoShow (); TaskService.InformJumpToTask (task); return result; } } NavigationPoint GetNextLocation (bool followSeverity) { int n; if (currentLocationTask == null) { n = 0; if (!followSeverity) iteratingSeverity = TaskSeverity.Error; } else { n = IndexOfTask (currentLocationTask); if (n != -1) n++; } // Jump over tasks with different severity or with no file name while (n != -1 && n < tasks.Count && (iteratingSeverity != tasks [n].Severity || !IsProjectTaskFile (tasks [n]))) n++; Task ct = n != -1 && n < tasks.Count ? tasks [n] : null; if (ct == null) { if (iteratingSeverity != TaskSeverity.Comment) { iteratingSeverity++; currentLocationTask = null; return GetNextLocation (true); } } currentLocationTask = ct; if (CurrentLocationTaskChanged != null) CurrentLocationTaskChanged (this, EventArgs.Empty); if (currentLocationTask != null) { TaskService.ShowStatus (currentLocationTask); return new TaskNavigationPoint (currentLocationTask); } else { IdeApp.Workbench.StatusBar.ShowMessage (GettextCatalog.GetString ("End of list")); return null; } } public static bool IsProjectTaskFile (Task t) { if (t.FileName.IsNullOrEmpty) return false; Project p = t.WorkspaceObject as Project; if (p == null) return false; return p.GetProjectFile (t.FileName) != null; } public NavigationPoint GetPreviousLocation () { return GetPreviousLocation (false); } NavigationPoint GetPreviousLocation (bool followSeverity) { int n; if (currentLocationTask == null) { n = tasks.Count - 1; if (!followSeverity) iteratingSeverity = TaskSeverity.Comment; } else { n = IndexOfTask (currentLocationTask); if (n != -1) n--; } while (n != -1 && n < tasks.Count && (iteratingSeverity != tasks [n].Severity || string.IsNullOrEmpty (tasks [n].FileName))) n--; Task ct = n != -1 && n < tasks.Count ? tasks [n] : null; if (ct == null) { if (iteratingSeverity != TaskSeverity.Error) { iteratingSeverity--; currentLocationTask = null; return GetPreviousLocation (true); } } currentLocationTask = ct; if (CurrentLocationTaskChanged != null) CurrentLocationTaskChanged (this, EventArgs.Empty); if (currentLocationTask != null) { TaskService.ShowStatus (currentLocationTask); return new TaskNavigationPoint (currentLocationTask); } else { IdeApp.Workbench.StatusBar.ShowMessage (GettextCatalog.GetString ("End of list")); return null; } } int IndexOfTask (Task t) { for (int n=0; n tasks; public TaskEventArgs (Task task) : this (new Task[] { task }) { } public TaskEventArgs (IEnumerable tasks) { this.tasks = tasks; } public IEnumerable Tasks { get { return tasks; } } } }