diff options
Diffstat (limited to 'main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools')
-rw-r--r-- | main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomTool.cs | 37 | ||||
-rw-r--r-- | main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs | 121 |
2 files changed, 114 insertions, 44 deletions
diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomTool.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomTool.cs index 84ef240750..e57fdd39b2 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomTool.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomTool.cs @@ -27,12 +27,45 @@ using System; using MonoDevelop.Projects; using System.CodeDom.Compiler; +using MonoDevelop.Core; namespace MonoDevelop.Ide.CustomTools { - public abstract class CustomTool + public interface ISingleFileCustomTool { - public abstract CompilerErrorCollection Generate (ProjectFile file, out string generatedFileName); + IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result); + } + + public class SingleFileCustomToolResult + { + CompilerErrorCollection errors = new CompilerErrorCollection (); + + /// <summary> + /// Errors and warnings from the generator. + /// </summary> + public CompilerErrorCollection Errors { get { return errors; } } + + /// <summary> + /// The absolute name of the generated file. Must be in same directory as source file. + /// </summary> + public FilePath GeneratedFilePath { get; set; } + + /// <summary> + /// Any unhandled exception from the generator. + /// </summary> + public Exception UnhandledException { get; set; } + + public bool Success { + get { + return UnhandledException == null && !Errors.HasErrors && !Errors.HasWarnings; + } + } + + public bool SuccessWithWarnings { + get { + return UnhandledException == null && !Errors.HasErrors; + } + } } } diff --git a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs index 83427f272c..4e29130b24 100644 --- a/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs +++ b/main/src/core/MonoDevelop.Ide/MonoDevelop.Ide.CustomTools/CustomToolService.cs @@ -34,6 +34,7 @@ using System.IO; using MonoDevelop.Ide.Tasks; using System.CodeDom.Compiler; using MonoDevelop.Ide.Gui; +using MonoDevelop.Core.ProgressMonitoring; namespace MonoDevelop.Ide.CustomTools { @@ -58,10 +59,10 @@ namespace MonoDevelop.Ide.CustomTools } }); IdeApp.Workspace.FileChangedInProject += delegate (object sender, ProjectFileEventArgs e) { - Update (e.ProjectFile); + Update (e.ProjectFile, false); }; IdeApp.Workspace.FilePropertyChangedInProject += delegate (object sender, ProjectFileEventArgs e) { - Update (e.ProjectFile); + Update (e.ProjectFile, false); }; //FIXME: handle the rename //MonoDevelop.Ide.Gui.IdeApp.Workspace.FileRenamedInProject @@ -72,7 +73,7 @@ namespace MonoDevelop.Ide.CustomTools //forces static ctor to run } - static CustomTool GetGenerator (ProjectFile file) + static ISingleFileCustomTool GetGenerator (ProjectFile file) { CustomToolExtensionNode node; if (!string.IsNullOrEmpty (file.Generator) && nodes.TryGetValue (file.Generator, out node)) @@ -80,66 +81,102 @@ namespace MonoDevelop.Ide.CustomTools return null; } - public static void Update (ProjectFile file) + public static void Update (ProjectFile file, bool force) { var tool = GetGenerator (file); if (tool == null) return; + ProjectFile genFile = null; if (!string.IsNullOrEmpty (file.LastGenOutput)) genFile = file.Project.Files.GetFile (file.FilePath.ParentDirectory.Combine (file.LastGenOutput)); - if (genFile != null && File.Exists (genFile.FilePath) && + if (!force && genFile != null && File.Exists (genFile.FilePath) && File.GetLastWriteTime (file.FilePath) < File.GetLastWriteTime (genFile.FilePath)) { return; } - CompilerErrorCollection errors = null; - bool broken = false; - FilePath genFilePath = FilePath.Null; - string genFileName = null; + string title = GettextCatalog.GetString ("Custom tool"); + var monitor = IdeApp.Workbench.ProgressMonitors.GetOutputProgressMonitor (title, null, false, true); + var result = new SingleFileCustomToolResult (); + var aggOp = new AggregatedOperationMonitor (monitor); try { - errors = tool.Generate (file, out genFileName); - genFilePath = genFileName; - if (genFilePath.IsNullOrEmpty) { - genFileName = null; - } else { - genFileName = genFilePath.ToRelative (file.FilePath.ParentDirectory).ToString (); - } + monitor.BeginTask (GettextCatalog.GetString ("Updating file {0}...", file.Name), 1); + var op = tool.Generate (monitor, file, result); + aggOp.AddOperation (op); + op.Completed += delegate { + UpdateCompleted (monitor, aggOp, file, genFile, result); + }; } catch (Exception ex) { - broken = true; - (errors ?? (errors = new CompilerErrorCollection ())) .Add ( - new CompilerError (file.Name, 0, 0, "", - string.Format ("The '{0}' code generator crashed: {1}", file.Generator, ex.Message))); - LoggingService.LogError (string.Format ("The '{0}' code generator crashed: {1}", file.Generator), ex); + result.UnhandledException = ex; + UpdateCompleted (monitor, aggOp, file, genFile, result); } - if (string.IsNullOrEmpty (genFileName) || - genFileName.IndexOfAny (new char[] { '/', '\\' }) >= 0 || - !FileService.IsValidFileName (genFileName)) - { - broken = true; - (errors ?? (errors = new CompilerErrorCollection ())).Add ( - new CompilerError (file.Name, 0, 0, "", - string.Format ("The '{0}' code generator output invalid filename '{1}'", file.Generator, genFileName))); + } + + static void UpdateCompleted (IProgressMonitor monitor, AggregatedOperationMonitor aggOp, + ProjectFile file, ProjectFile genFile, SingleFileCustomToolResult result) + { + monitor.EndTask (); + aggOp.Dispose (); + + if (monitor.IsCancelRequested) { + monitor.ReportError ("Cancelled", null); + monitor.Dispose (); + return; } - TaskService.Errors.ClearByOwner (file); - if (errors.Count > 0) { - foreach (CompilerError err in errors) - TaskService.Errors.Add (new Task (file.FilePath, err.ErrorText, err.Column, err.Line, - err.IsWarning? TaskSeverity.Warning : TaskSeverity.Error, - TaskPriority.Normal, file.Project.ParentSolution, file)); + string genFileName; + try { + + bool broken = false; + + if (result.UnhandledException != null) { + broken = true; + result.Errors.Add (new CompilerError (file.Name, 0, 0, "", + string.Format ("The '{0}' code generator crashed: {1}", file.Generator, result.UnhandledException.Message))); + monitor.ReportError (string.Format ("The '{0}' code generator crashed", file.Generator), result.UnhandledException); + } + + genFileName = result.GeneratedFilePath.IsNullOrEmpty? + null : result.GeneratedFilePath.ToRelative (file.FilePath.ParentDirectory); + + bool validName = !string.IsNullOrEmpty (genFileName) + && genFileName.IndexOfAny (new char[] { '/', '\\' }) < 0 + && FileService.IsValidFileName (genFileName); + + if (!validName) { + broken = true; + result.Errors.Add (new CompilerError (file.Name, 0, 0, "", + string.Format ("The '{0}' code generator output invalid filename '{1}'", file.Generator, result.GeneratedFilePath))); + } + + TaskService.Errors.ClearByOwner (file); + if (result.Errors.Count > 0) { + foreach (CompilerError err in result.Errors) + TaskService.Errors.Add (new Task (file.FilePath, err.ErrorText, err.Column, err.Line, + err.IsWarning? TaskSeverity.Warning : TaskSeverity.Error, + TaskPriority.Normal, file.Project.ParentSolution, file)); + } + + if (broken) + return; + + if (result.Success) + monitor.ReportSuccess ("Generated file successfully."); + else + monitor.ReportError ("Failed to generate file. See error pad for details.", null); + + } finally { + monitor.Dispose (); } - if (broken) - return; - if (!genFilePath.IsNullOrEmpty && File.Exists (genFilePath)) { + if (!result.GeneratedFilePath.IsNullOrEmpty && File.Exists (result.GeneratedFilePath)) { if (genFile == null) { - genFile = file.Project.AddFile (genFilePath); - } else if (genFilePath != genFile.FilePath) { - genFile.Name = genFilePath; + genFile = file.Project.AddFile (result.GeneratedFilePath); + } else if (result.GeneratedFilePath != genFile.FilePath) { + genFile.Name = result.GeneratedFilePath; } - file.LastGenOutput = genFileName; + file.LastGenOutput = genFileName; genFile.DependsOn = file.FilePath.FileName; } } |