diff options
Diffstat (limited to 'main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner')
9 files changed, 901 insertions, 0 deletions
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/AnalysisJobQueue.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/AnalysisJobQueue.cs new file mode 100644 index 0000000000..cdb3182fbb --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/AnalysisJobQueue.cs @@ -0,0 +1,121 @@ +// +// AnalysisJobQueue.cs +// +// Author: +// Simon Lindgren <simon.n.lindgren@gmail.com> +// +// Copyright (c) 2013 Simon Lindgren +// +// 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. +using System.Collections.Generic; +using System.Linq; + +namespace MonoDevelop.CodeIssues +{ + public class AnalysisJobQueue + { + readonly object _lock = new object(); + + /// <summary> + /// The list of items in the queue. + /// </summary> + readonly List<JobSlice> slices = new List<JobSlice>(); + + /// <summary> + /// Indicates whether queueItems is sorted. + /// </summary> + bool sorted; + + /// <summary> + /// Adds the specified job to the queue. + /// </summary> + /// <param name="job">The job.</param> + public void Add (IAnalysisJob job) + { + lock (_lock) { + var jobStatus = new JobStatus (job); + foreach (var file in job.GetFiles()) { + JobSlice slice = slices.FirstOrDefault (j => j.File == file); + if (slice == null) { + slice = new JobSlice (file); + slices.Add (slice); + } + jobStatus.AddSlice (slice); + slice.AddJob (job, jobStatus); + } + InvalidateSort (); + } + } + + /// <summary> + /// Remove the specified job from the queue. + /// </summary> + /// <param name="job">The job to remove.</param> + public void Remove (IAnalysisJob job) + { + lock (_lock) { + foreach (var file in job.GetFiles()) { + JobSlice queueItem = slices.FirstOrDefault (j => j.File == file); + if (queueItem == null) + // The file might have been processed already, carry on + continue; + queueItem.RemoveJob (job); + if (!queueItem.GetJobs ().Any ()) + slices.Remove (queueItem); + } + InvalidateSort (); + } + } + + /// <summary> + /// Dequeues a number of elements less than or equal to <paramref name="maxNumber"/>. + /// </summary> + /// <param name="maxNumber">The index.</param> + public IEnumerable<JobSlice> Dequeue (int maxNumber) + { + lock (_lock) { + EnsureSorted (); + var taken = slices.Take (maxNumber).ToList (); + foreach (var item in taken) + slices.Remove (item); + return taken; + } + } + + /// <summary> + /// Notifies the rest of the class that <see cref="slices"/> is no longer sorted. + /// </summary> + void InvalidateSort () + { + sorted = false; + } + + /// <summary> + /// Ensures that <see cref="slices"/> is sorted. + /// </summary> + void EnsureSorted () + { + if (!sorted) { + slices.Sort (); + sorted = true; + } + } + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/CodeIssueEventArgs.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/CodeIssueEventArgs.cs new file mode 100644 index 0000000000..53e3a29f8b --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/CodeIssueEventArgs.cs @@ -0,0 +1,70 @@ +// +// CodeIssueEventArgs.cs +// +// Author: +// Simon Lindgren <simon.n.lindgren@gmail.com> +// +// Copyright (c) 2013 Simon Lindgren +// +// 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. +using System; +using MonoDevelop.CodeIssues; +using System.Collections.Generic; +using System.Linq; +using MonoDevelop.Projects; + +namespace MonoDevelop.CodeIssues +{ + /// <summary> + /// Code issue event arguments. + /// </summary> + public class CodeIssueEventArgs : EventArgs + { + + /// <summary> + /// Initializes a new instance of the <see cref="CodeIssueEventArgs"/> class. + /// </summary> + /// <param name="codeIssues">The code issues.</param> + public CodeIssueEventArgs (ProjectFile file, BaseCodeIssueProvider provider, IEnumerable<CodeIssue> codeIssues) + { + File = file; + Provider = provider; + CodeIssues = codeIssues as IList<CodeIssue> ?? codeIssues.ToList (); + } + + /// <summary> + /// Gets the analyzed file. + /// </summary> + /// <value>The analyzed file.</value> + public ProjectFile File { get; private set; } + + /// <summary> + /// Gets the provider. + /// </summary> + /// <value>The code issue provider that provided the issues.</value> + public BaseCodeIssueProvider Provider { get; private set; } + + /// <summary> + /// Gets the code issues. + /// </summary> + /// <value>The new code issues.</value> + public IList<CodeIssue> CodeIssues { get; private set; } + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IAnalysisJob.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IAnalysisJob.cs new file mode 100644 index 0000000000..0ab2553b4f --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IAnalysisJob.cs @@ -0,0 +1,93 @@ +// +// IAnalysisJob.cs +// +// Author: +// Simon Lindgren <simon.n.lindgren@gmail.com> +// +// Copyright (c) 2013 Simon Lindgren +// +// 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. +using System.Collections.Generic; +using MonoDevelop.Projects; +using System; + +namespace MonoDevelop.CodeIssues +{ + /// <summary> + /// Represents an analysis job. Implementations must be thread safe. + /// </summary> + public interface IAnalysisJob + { + /// <summary> + /// Gets the file names affected by this job. + /// </summary> + /// <remarks> + /// The return value of this method may not change after the initial invocation. + /// </remarks> + /// <returns>The file names.</returns> + IEnumerable<ProjectFile> GetFiles (); + + /// <summary> + /// Gets the issue providers for the file specified in <paramref name="file"/>. + /// </summary> + /// <returns>The issue providers to run on the specified file.</returns> + /// <param name="file">The file.</param> + IEnumerable<BaseCodeIssueProvider> GetIssueProviders (ProjectFile file); + + /// <summary> + /// Adds the results to this job. + /// </summary> + /// <param name="file">The file that the results apply to.</param> + /// <param name="provider">The provider that provided the issues.</param> + /// <param name="issues">The issues detected in the specified file.</param> + void AddResult (ProjectFile file, BaseCodeIssueProvider provider, IEnumerable<CodeIssue> issues); + + /// <summary> + /// Notifies the job that there was an error running the specified provider on the specified file. + /// </summary> + /// <param name="file">The file.</param> + /// <param name="provider">The provider.</param> + void AddError (ProjectFile file, BaseCodeIssueProvider provider); + + /// <summary> + /// Occurs when new code issues are added. + /// </summary> + event EventHandler<CodeIssueEventArgs> CodeIssueAdded; + + /// <summary> + /// Called when this job is cancelled to notify the instance about that change. + /// </summary> + /// <remarks> + /// The caller does NOT have to ensure that this is the last method called. + /// Specifically, <see cref="AddResult"/> can be called after this method has been invoked. + /// </remarks> + void NotifyCancelled (); + + /// <summary> + /// Notifies the job that all files have been processed. + /// </summary> + void SetCompleted (); + + /// <summary> + /// Occurs when the job is completed. + /// </summary> + event EventHandler<EventArgs> Completed; + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IJobContext.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IJobContext.cs new file mode 100644 index 0000000000..4027081b81 --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/IJobContext.cs @@ -0,0 +1,35 @@ +// +// IJobContext.cs +// +// Author: +// Simon Lindgren <simon.n.lindgren@gmail.com> +// +// Copyright (c) 2013 Simon Lindgren +// +// 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. + +namespace MonoDevelop.CodeIssues +{ + public interface IJobContext + { + IAnalysisJob Job { get; } + void CancelJob (); + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobContext.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobContext.cs new file mode 100644 index 0000000000..e15c83c88e --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobContext.cs @@ -0,0 +1,66 @@ +// +// JobContext.cs +// +// Author: +// Simon Lindgren <simon.n.lindgren@gmail.com> +// +// Copyright (c) 2013 Simon Lindgren +// +// 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. +using System; + +namespace MonoDevelop.CodeIssues +{ + public class JobContext : IJobContext + { + readonly IAnalysisJob job; + + readonly AnalysisJobQueue queue; + + readonly CodeAnalysisBatchRunner runner; + + public JobContext(IAnalysisJob job, AnalysisJobQueue queue, CodeAnalysisBatchRunner runner) + { + if (job == null) + throw new ArgumentNullException ("job"); + if (queue == null) + throw new ArgumentNullException ("queue"); + if (runner == null) + throw new ArgumentNullException ("runner"); + this.job = job; + this.queue = queue; + this.runner = runner; + } + + #region IJobContext implementation + public void CancelJob () + { + job.NotifyCancelled (); + queue.Remove (job); + } + + public IAnalysisJob Job { + get { + return job; + } + } + #endregion + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobSlice.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobSlice.cs new file mode 100644 index 0000000000..7802e21ada --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobSlice.cs @@ -0,0 +1,162 @@ +// +// QueueItem.cs +// +// Author: +// Simon Lindgren <simon.n.lindgren@gmail.com> +// +// Copyright (c) 2013 Simon Lindgren +// +// 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. +using System; +using System.Collections.Generic; +using MonoDevelop.Projects; +using System.Threading; +using System.Linq; + +namespace MonoDevelop.CodeIssues +{ + /// <summary> + /// Represents a unit of analysis at the time of analysis. Essentially this + /// maps a file to the jobs that wants to run analysis on it so the runner + /// can parse the file once and then make progress on all the jobs. + /// This class is not thread safe. + /// </summary> + public class JobSlice : IComparable<JobSlice>, IDisposable + { + bool disposed; + readonly CancellationTokenSource tokenSource = new CancellationTokenSource(); + + /// <summary> + /// The jobs to run on the file specified in <see cref="FileName"/>. + /// </summary> + readonly IList<IAnalysisJob> jobs = new List<IAnalysisJob>(); + + /// <summary> + /// The status to report to when this slice is complete. + /// </summary> + readonly IList<JobStatus> statuses = new List<JobStatus>(); + + /// <summary> + /// The name of a file to be analyzed. + /// </summary> + /// <value>The name of the file.</value> + public ProjectFile File { get; private set; } + + /// <summary> + /// Gets the cancellation token for this work unit. + /// </summary> + /// <value>A cancellation token.</value> + public CancellationToken CancellationToken { + get { + return tokenSource.Token; + } + } + + /// <summary> + /// Initializes a new instance of the <see cref="MonoDevelop.CodeIssues.JobSlice"/> class. + /// </summary> + /// <param name="file">The file.</param> + public JobSlice (ProjectFile file) + { + File = file; + } + + ~JobSlice () + { + Dispose (false); + } + + /// <summary> + /// Adds a job to be run on this file. + /// </summary> + /// <param name="job">The job.</param> + /// <param name = "status">The status of the job.</param> + public void AddJob (IAnalysisJob job, JobStatus status) + { + if (disposed) + throw new ObjectDisposedException (GetType ().FullName); + + statuses.Add (status); + jobs.Add (job); + } + + /// <summary> + /// Gets the current jobs. + /// </summary> + /// <returns>The jobs.</returns> + public IEnumerable<IAnalysisJob> GetJobs () + { + if (disposed) + throw new ObjectDisposedException (GetType ().FullName); + + return new List<IAnalysisJob> (jobs); + } + + /// <summary> + /// Removes the specified job. + /// If the job is the last job in this instance it requests cancellation of it's CancellationToken. + /// </summary> + /// <param name="job">The job to remove.</param> + public void RemoveJob(IAnalysisJob job) + { + if (disposed) + throw new ObjectDisposedException (GetType ().FullName); + + jobs.Remove (job); + if (!jobs.Any ()) + tokenSource.Cancel (); + } + + void MarkAsComplete () + { + foreach (var status in statuses) { + status.MarkAsComplete (this); + } + } + + #region IComparable implementation + + public int CompareTo (JobSlice other) + { + return jobs.Count.CompareTo (other.jobs.Count); + } + + #endregion + + #region IDisposable implementation + + public void Dispose () + { + Dispose (true); + } + + protected virtual void Dispose (bool disposing) + { + if (disposed) + return; + + MarkAsComplete (); + + disposed = true; + } + + #endregion + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobStatus.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobStatus.cs new file mode 100644 index 0000000000..02ca3eb1fd --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/JobStatus.cs @@ -0,0 +1,86 @@ +// +// JobStatus.cs +// +// Author: +// Simon Lindgren <simon.n.lindgren@gmail.com> +// +// Copyright (c) 2013 Simon Lindgren +// +// 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. +using System; +using System.Collections.Generic; + +namespace MonoDevelop.CodeIssues +{ + /// <summary> + /// Keeps track of the status of a possibly partially executed job. + /// </summary> + public class JobStatus + { + readonly object _lock = new object(); + + /// <summary> + /// The job. + /// </summary> + readonly IAnalysisJob job; + + /// <summary> + /// The slices that the job has been split into. + /// </summary> + readonly ISet<JobSlice> slices = new HashSet<JobSlice> (); + + /// <summary> + /// Initializes a new instance of the <see cref="MonoDevelop.CodeIssues.JobStatus"/> class. + /// </summary> + /// <param name="job">The job.</param> + public JobStatus (IAnalysisJob job) + { + if (job == null) + throw new ArgumentNullException ("job"); + + this.job = job; + } + + /// <summary> + /// Adds another slice. This method should not be called after <see cref="MarkAsComplete"/> has been called. + /// </summary> + /// <param name="slice">Slice.</param> + public void AddSlice (JobSlice slice) + { + lock (_lock) { + slices.Add (slice); + } + } + + /// <summary> + /// Marks a slice of the job as complete and marks the job as completed if all slices have been completed. + /// </summary> + /// <param name="slice">The completed slice.</param> + public void MarkAsComplete(JobSlice slice) + { + lock (_lock) { + slices.Remove (slice); + if (slices.Count == 0) { + job.SetCompleted (); + } + } + } + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/ProgressMonitorWrapperJob.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/ProgressMonitorWrapperJob.cs new file mode 100644 index 0000000000..b1eea307cf --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/ProgressMonitorWrapperJob.cs @@ -0,0 +1,126 @@ +// +// ProgressReportingWrapperJob.cs +// +// Author: +// Simon Lindgren <simon.n.lindgren@gmail.com> +// +// Copyright (c) 2013 Simon Lindgren +// +// 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. +using System.Linq; +using MonoDevelop.Ide; +using MonoDevelop.Core; +using MonoDevelop.Projects; +using System.Collections.Generic; +using System; + +namespace MonoDevelop.CodeIssues +{ + public class ProgressMonitorWrapperJob : IAnalysisJob + { + readonly IAnalysisJob wrappedJob; + + ProgressMonitor monitor;
+
+ int reportingThinningFactor = 100;
+
+ int completedWork;
+
+ public ProgressMonitorWrapperJob (IAnalysisJob wrappedJob, string message) + { + this.wrappedJob = wrappedJob; + monitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor (message, null, false); + var work = wrappedJob.GetFiles ().Sum (f => wrappedJob.GetIssueProviders (f).Count ()); + + monitor.BeginTask (message, work); + } + + #region IAnalysisJob implementation + + public event EventHandler<CodeIssueEventArgs> CodeIssueAdded { + add { + wrappedJob.CodeIssueAdded += value; + } + remove { + wrappedJob.CodeIssueAdded -= value; + } + } + + public IEnumerable<ProjectFile> GetFiles () + { + return wrappedJob.GetFiles (); + } + + public IEnumerable<BaseCodeIssueProvider> GetIssueProviders (ProjectFile file) + { + return wrappedJob.GetIssueProviders (file); + } + + public void AddResult (ProjectFile file, BaseCodeIssueProvider provider, IEnumerable<CodeIssue> issues) + { + Step (); + wrappedJob.AddResult (file, provider, issues); + } + + public void AddError (ProjectFile file, BaseCodeIssueProvider provider) + { + Step (); + wrappedJob.AddError (file, provider); + } + + public event EventHandler<EventArgs> Completed { + add { + wrappedJob.Completed += value; + } + remove { + wrappedJob.Completed -= value; + } + } + + public void SetCompleted () + { + StopReporting (); + wrappedJob.SetCompleted (); + } + + void Step ()
+ {
+ completedWork++; + if (monitor != null && completedWork % reportingThinningFactor == 0) { + monitor.Step (reportingThinningFactor); + } + } + + void StopReporting () + { + if (monitor != null) { + monitor.Dispose (); + monitor = null; + } + } + + public void NotifyCancelled () + { + StopReporting (); + } + + #endregion + } +} + diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/SimpleAnalysisJob.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/SimpleAnalysisJob.cs new file mode 100644 index 0000000000..15878be01b --- /dev/null +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/Pad/Runner/SimpleAnalysisJob.cs @@ -0,0 +1,142 @@ +// +// AbstractAnalysisJob.cs +// +// Author: +// Simon Lindgren <simon.n.lindgren@gmail.com> +// +// Copyright (c) 2013 Simon Lindgren +// +// 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. +using System; +using System.Collections.Generic; +using MonoDevelop.Projects; +using MonoDevelop.Refactoring; +using MonoDevelop.Ide; +using System.Linq; +using ICSharpCode.NRefactory.Refactoring; + +namespace MonoDevelop.CodeIssues +{ + /// <summary> + /// A simple analysis job. + /// </summary> + public class SimpleAnalysisJob : IAnalysisJob
+ {
+ object _lock = new object (); + + readonly IList<ProjectFile> files; + + /// <summary> + /// Initializes a new instance of the <see cref="MonoDevelop.CodeIssues.SimpleAnalysisJob"/> class. + /// </summary> + /// <param name="files">The files to analyze.</param> + public SimpleAnalysisJob (IList<ProjectFile> files) + { + if (files == null) + throw new ArgumentNullException ("files"); + this.files = files; + } + + public bool IsCompleted { + get; + private set; + } + + bool IsCancelled { + get; + set; + } + + #region IAnalysisJob implementation + + public event EventHandler<CodeIssueEventArgs> CodeIssueAdded; + + protected virtual void OnCodeIssueAdded (CodeIssueEventArgs args) + { + var handler = CodeIssueAdded; + if (handler != null) + handler(this, args); + } + + public IEnumerable<ProjectFile> GetFiles () + { + return files; + } + + public IEnumerable<BaseCodeIssueProvider> GetIssueProviders (ProjectFile file) + { + return RefactoringService.GetInspectors (DesktopService.GetMimeTypeForUri (file.Name)) + .Where (provider => { + var severity = provider.GetSeverity (); + if (severity == Severity.None || !provider.GetIsEnabled ()) + return false; + return true; + }); + } + + public void AddResult (ProjectFile file, BaseCodeIssueProvider provider, IEnumerable<CodeIssue> issues) + { + OnCodeIssueAdded (new CodeIssueEventArgs(file, provider, issues)); + } + + public void AddError (ProjectFile file, BaseCodeIssueProvider provider) + { + } + + public void NotifyCancelled () + {
+ lock (_lock) {
+ IsCancelled = true;
+ }
+ } + + event EventHandler<EventArgs> completed; + public event EventHandler<EventArgs> Completed { + add { + completed += value; + if (IsCompleted && !IsCancelled) + OnCompleted (new EventArgs()); + } + remove { + completed += value; + } + } + + protected virtual void OnCompleted (EventArgs e) + { + var handler = completed; + if (handler != null) + handler (this, e); + } + + public void SetCompleted ()
+ {
+ bool runEventHandler; + lock (_lock) {
+ IsCompleted = true;
+ runEventHandler = !IsCancelled && !IsCompleted;
+ } + if (runEventHandler) + OnCompleted (new EventArgs()); + } + + #endregion + } +} + |