diff options
author | Simon Lindgren <simon.n.lindgren@gmail.com> | 2013-08-07 15:50:10 +0400 |
---|---|---|
committer | Simon Lindgren <simon.n.lindgren@gmail.com> | 2013-08-20 17:15:37 +0400 |
commit | 9e427418b5792652ea11792ba5fb8f0a750cddea (patch) | |
tree | b6c0ca86efbfb0facfe17cf2d92dae5e2a31436a /main/src/addins | |
parent | 2b703b332ce67be2a94b9515a2216229f1f61982 (diff) |
[Refactoring] Handle exceptions better and add more specific error handling in CodeAnalysisBatchRunner.
Diffstat (limited to 'main/src/addins')
-rw-r--r-- | main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalysisState.cs | 3 | ||||
-rw-r--r-- | main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeAnalysisBatchRunner.cs | 143 |
2 files changed, 87 insertions, 59 deletions
diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalysisState.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalysisState.cs index 0a6af25dbc..221e11d819 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalysisState.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/AnalysisState.cs @@ -30,7 +30,8 @@ namespace MonoDevelop.CodeIssues NeverStarted, Running, Completed, - Cancelled + Cancelled, + Error } } diff --git a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeAnalysisBatchRunner.cs b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeAnalysisBatchRunner.cs index 39bad501a3..bf0ea189e9 100644 --- a/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeAnalysisBatchRunner.cs +++ b/main/src/addins/MonoDevelop.Refactoring/MonoDevelop.CodeIssues/CodeAnalysisBatchRunner.cs @@ -41,6 +41,7 @@ using MonoDevelop.Core; using System.Collections.Concurrent; using ICSharpCode.NRefactory.Semantics; using ICSharpCode.NRefactory.TypeSystem; +using Mono.TextEditor; namespace MonoDevelop.CodeIssues { @@ -49,6 +50,8 @@ namespace MonoDevelop.CodeIssues object _lock = new object (); CancellationTokenSource tokenSource; IIssueSummarySink destinationGroup; + + ConcurrentDictionary<string, object> processedFiles; public IIssueSummarySink IssueSink { get { @@ -115,77 +118,101 @@ namespace MonoDevelop.CodeIssues { lock (_lock) { tokenSource = new CancellationTokenSource (); + processedFiles = new ConcurrentDictionary<string, object> (); ThreadPool.QueueUserWorkItem (delegate { State = AnalysisState.Running; using (var monitor = IdeApp.Workbench.ProgressMonitors.GetStatusProgressMonitor ("Analyzing solution", null, false)) { - int work = 0; - foreach (var project in solution.GetAllProjects ()) { - work += project.Files.Count (f => f.BuildAction == BuildAction.Compile); - } - monitor.BeginTask ("Analyzing solution", work); - var processedFiles = new ConcurrentDictionary<string, object> (); - foreach (var project in solution.GetAllProjects ()) { - if (tokenSource.IsCancellationRequested) - break; - var content = TypeSystemService.GetProjectContext (project); - Parallel.ForEach (project.Files, file => { - var me = new object(); - var owner = processedFiles.AddOrUpdate(file.Name, me, (key, old) => old); - if (me != owner) - return; - if (file.BuildAction != BuildAction.Compile || tokenSource.IsCancellationRequested) - return; - - var editor = TextFileProvider.Instance.GetReadOnlyTextEditorData (file.FilePath); - var document = TypeSystemService.ParseFile (project, editor); - if (document == null) - return; - - var compilation = content.AddOrUpdateFiles (document.ParsedFile).CreateCompilation (); - var resolver = new CSharpAstResolver (compilation, document.GetAst<SyntaxTree> (), document.ParsedFile as ICSharpCode.NRefactory.CSharp.TypeSystem.CSharpUnresolvedFile); - var context = document.CreateRefactoringContextWithEditor (editor, resolver, tokenSource.Token); - - CodeIssueProvider[] codeIssueProvider = RefactoringService.GetInspectors (editor.MimeType).ToArray (); - Parallel.ForEach (codeIssueProvider, (provider) => { - var severity = provider.GetSeverity (); - if (severity == Severity.None || tokenSource.IsCancellationRequested) - return; - try { - foreach (var issue in provider.GetIssues (context, tokenSource.Token)) { - AddIssue (file, provider, issue); - } - } catch (OperationCanceledException) { - // The operation was cancelled, no-op as the user-visible parts are - // handled elsewhere - } catch (Exception ex) { - LoggingService.LogError ("Error while running code issue on:" + editor.FileName, ex); - } - }); - //lastMime = editor.MimeType; - monitor.Step (1); - }); - } - // Cleanup AnalysisState oldState; AnalysisState newState; - lock (_lock) { - oldState = state; - if (tokenSource.IsCancellationRequested) { - newState = AnalysisState.Cancelled; - } else { - newState = AnalysisState.Completed; + try { + int work = 0; + foreach (var project in solution.GetAllProjects ()) { + work += project.Files.Count (f => f.BuildAction == BuildAction.Compile); + } + monitor.BeginTask ("Analyzing solution", work); + foreach (var project in solution.GetAllProjects ()) { + if (tokenSource.IsCancellationRequested) + break; + var content = TypeSystemService.GetProjectContext (project); + Parallel.ForEach (project.Files, file => { + AnalyzeFile (file, content); + monitor.Step (1); + }); } - state = newState; - tokenSource = null; + // Cleanup + lock (_lock) { + oldState = state; + if (tokenSource.IsCancellationRequested) { + newState = AnalysisState.Cancelled; + } else { + newState = AnalysisState.Completed; + } + state = newState; + tokenSource = null; + } + OnAnalysisStateChanged (new AnalysisStateChangeEventArgs (oldState, newState)); + } catch (Exception e) { + lock (_lock) { + oldState = state; + state = AnalysisState.Error; + newState = state; + tokenSource = null; + } + OnAnalysisStateChanged (new AnalysisStateChangeEventArgs (oldState, newState)); + // Do not rethrow in a thread pool + MessageService.ShowException (e); } - OnAnalysisStateChanged(new AnalysisStateChangeEventArgs(oldState, newState)); - monitor.EndTask (); } }); } } + void AnalyzeFile (ProjectFile file, IProjectContent content) + { + var me = new object (); + var owner = processedFiles.AddOrUpdate (file.Name, me, (key, old) => old); + if (me != owner) + return; + + if (file.BuildAction != BuildAction.Compile || tokenSource.IsCancellationRequested) + return; + + TextEditorData editor; + try { + editor = TextFileProvider.Instance.GetReadOnlyTextEditorData (file.FilePath); + } catch (FileNotFoundException) { + // Swallow exception and ignore this file + return; + } + var document = TypeSystemService.ParseFile (file.Project, editor); + if (document == null) + return; + + var compilation = content.AddOrUpdateFiles (document.ParsedFile).CreateCompilation (); + var resolver = new CSharpAstResolver (compilation, document.GetAst<SyntaxTree> (), document.ParsedFile as ICSharpCode.NRefactory.CSharp.TypeSystem.CSharpUnresolvedFile); + var context = document.CreateRefactoringContextWithEditor (editor, resolver, tokenSource.Token); + + CodeIssueProvider[] codeIssueProvider = RefactoringService.GetInspectors (editor.MimeType).ToArray (); + Parallel.ForEach (codeIssueProvider, provider => { + var severity = provider.GetSeverity (); + if (severity == Severity.None || tokenSource.IsCancellationRequested) + return; + try { + foreach (var issue in provider.GetIssues (context, tokenSource.Token)) { + AddIssue (file, provider, issue); + } + } + catch (OperationCanceledException) { + // The operation was cancelled, no-op as the user-visible parts are + // handled elsewhere + } + catch (Exception ex) { + LoggingService.LogError ("Error while running code issue on:" + editor.FileName, ex); + } + }); + } + void AddIssue (ProjectFile file, CodeIssueProvider provider, CodeIssue r) { var issue = new IssueSummary { |