void GenerateInternal (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { var dnp = file.Project as DotNetProject; if (dnp == null || dnp.LanguageName != "C#") { var msg = "Razor templates are only supported in C# projects"; result.Errors.Add (new CompilerError (file.Name, -1, -1, null, msg)); monitor.Log.WriteLine (msg); return; } var host = PreprocessedRazorHost.Create (file.FilePath); var defaultOutputName = file.FilePath.ChangeExtension (".cs"); var ns = GetNamespaceHint (file, defaultOutputName); host.DefaultNamespace = ns; CompilerErrorCollection errors; var code = host.GenerateCode (out errors); result.Errors.AddRange (errors); var writer = new MonoDevelop.DesignerSupport.CodeBehindWriter (); writer.WriteFile (defaultOutputName, code); writer.WriteOpenFiles (); result.GeneratedFilePath = defaultOutputName; foreach (var err in result.Errors) { monitor.Log.WriteLine (err.ToString ()); } }
static void GenerateInternal (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { if (file.Project.SupportedLanguages.All (l => l != "C#")) { const string msg = "Razor templates are only supported in C# projects"; result.Errors.Add (new CompilerError (file.Name, -1, -1, null, msg)); monitor.Log.WriteLine (msg); return; } var host = new PreprocessedRazorHost (file.FilePath); var defaultOutputName = file.FilePath.ChangeExtension (".cs"); var ns = CustomToolService.GetFileNamespace (file, defaultOutputName); host.DefaultNamespace = ns; CompilerErrorCollection errors; var code = host.GenerateCode (out errors); result.Errors.AddRange (errors); var writer = new MonoDevelop.DesignerSupport.CodeBehindWriter (); writer.WriteFile (defaultOutputName, code); writer.WriteOpenFiles (); result.GeneratedFilePath = defaultOutputName; foreach (var err in result.Errors) { monitor.Log.WriteLine (err); } }
public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation (delegate { var dnp = file.Project as DotNetProject; if (dnp == null) { var err = "ResXFileCodeGenerator can only be used with .NET projects"; result.Errors.Add (new CompilerError (null, 0, 0, null, err)); return; } var provider = dnp.LanguageBinding.GetCodeDomProvider (); if (provider == null) { var err = "ResXFileCodeGenerator can only be used with languages that support CodeDOM"; result.Errors.Add (new CompilerError (null, 0, 0, null, err)); return; } var outputfile = file.FilePath.ChangeExtension (".Designer." + provider.FileExtension); var ns = CustomToolService.GetFileNamespace (file, outputfile); var cn = provider.CreateValidIdentifier (file.FilePath.FileNameWithoutExtension); string[] unmatchable; var ccu = StronglyTypedResourceBuilder.Create (file.FilePath, cn, ns, provider, true, out unmatchable); foreach (var p in unmatchable) { var msg = string.Format ("Could not generate property for resource ID '{0}'", p); result.Errors.Add (new CompilerError (file.FilePath, 0, 0, null, msg)); } using (var w = new StreamWriter (outputfile, false, Encoding.UTF8)) provider.GenerateCodeFromCompileUnit (ccu, w, new CodeGeneratorOptions ()); result.GeneratedFilePath = outputfile; }, result); }
static void Update(IProgressMonitor monitor, IEnumerator <ProjectFile> fileEnumerator, bool force, int succeeded, int warnings, int errors) { ProjectFile file = fileEnumerator.Current; ISingleFileCustomTool tool; ProjectFile genFile; bool shouldRun; while (!(shouldRun = ShouldRunGenerator(file, force, out tool, out genFile)) && fileEnumerator.MoveNext()) { continue; } //no files which can be generated in remaining elements of the collection, nothing to do if (!shouldRun) { WriteSummaryResults(monitor, succeeded, warnings, errors); return; } TaskService.Errors.ClearByOwner(file); var result = new SingleFileCustomToolResult(); monitor.BeginTask(GettextCatalog.GetString("Running generator '{0}' on file '{1}'...", file.Generator, file.Name), 1); try { IAsyncOperation op = tool.Generate(monitor, file, result); op.Completed += delegate { if (result.Success) { monitor.Log.WriteLine(GettextCatalog.GetString("File '{0}' was generated successfully.", result.GeneratedFilePath)); succeeded++; } else if (result.SuccessWithWarnings) { monitor.Log.WriteLine(GettextCatalog.GetString("File '{0}' was generated with warnings.", result.GeneratedFilePath)); warnings++; } else { monitor.Log.WriteLine(GettextCatalog.GetString("Errors in file '{0}' generation.", result.GeneratedFilePath)); errors++; } //check that we can process further. If UpdateCompleted returns `true` this means no errors or non-fatal errors occured if (UpdateCompleted(monitor, null, file, genFile, result, true) && fileEnumerator.MoveNext()) { Update(monitor, fileEnumerator, force, succeeded, warnings, errors); } else { WriteSummaryResults(monitor, succeeded, warnings, errors); } }; } catch (Exception ex) { result.UnhandledException = ex; UpdateCompleted(monitor, null, file, genFile, result, true); } }
private void HandleException(Exception ex, ProjectFile file, SingleFileCustomToolResult result) { if (ex is SpecFlowParserException) { SpecFlowParserException sfpex = (SpecFlowParserException) ex; if (sfpex.ErrorDetails == null || sfpex.ErrorDetails.Count == 0) { result.UnhandledException = ex; } else { var compilerErrors = new CompilerErrorCollection(); foreach (var errorDetail in sfpex.ErrorDetails) { var compilerError = new CompilerError(file.Name, errorDetail.ForcedLine, errorDetail.ForcedColumn, "0", errorDetail.Message); compilerErrors.Add(compilerError); } result.Errors.AddRange(compilerErrors); } } else { result.UnhandledException = ex; } }
public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation (delegate { try { GenerateInternal (monitor, file, result); } catch (Exception ex) { result.UnhandledException = ex; } }, result); }
public async Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { var buildResult = await file.Project.PerformGeneratorAsync (monitor, IdeApp.Workspace.ActiveConfiguration, this.targetName); foreach (var err in buildResult.BuildResult.Errors) { result.Errors.Add (new CompilerError (err.FileName, err.Line, err.Column, err.ErrorNumber, err.ErrorText) { IsWarning = err.IsWarning }); } }
public ThreadAsyncOperation (Action task, SingleFileCustomToolResult result) { if (result == null) throw new ArgumentNullException ("result"); this.task = task; this.result = result; thread = new Thread (Run); thread.Start (); }
public Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return Task.Run (delegate { try { GenerateInternal (monitor, file, result); } catch (Exception ex) { result.UnhandledException = ex; } }); }
public static void Update(ProjectFile file, bool force) { ISingleFileCustomTool tool; ProjectFile genFile; if (!ShouldRunGenerator(file, force, out tool, out genFile)) { return; } TaskService.Errors.ClearByOwner(file); //if this file is already being run, cancel it lock (runningTasks) { IAsyncOperation runningTask; if (runningTasks.TryGetValue(file.FilePath, out runningTask)) { runningTask.Cancel(); runningTasks.Remove(file.FilePath); } } var monitor = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor(false); var result = new SingleFileCustomToolResult(); var aggOp = new AggregatedOperationMonitor(monitor); try { monitor.BeginTask(GettextCatalog.GetString("Running generator '{0}' on file '{1}'...", file.Generator, file.Name), 1); IAsyncOperation op = tool.Generate(monitor, file, result); runningTasks.Add(file.FilePath, op); aggOp.AddOperation(op); op.Completed += delegate { lock (runningTasks) { IAsyncOperation runningTask; if (runningTasks.TryGetValue(file.FilePath, out runningTask) && runningTask == op) { runningTasks.Remove(file.FilePath); UpdateCompleted(monitor, aggOp, file, genFile, result, false); } else { //it was cancelled because another was run for the same file, so just clean up aggOp.Dispose(); monitor.EndTask(); monitor.ReportWarning(GettextCatalog.GetString("Cancelled because generator ran again for the same file")); monitor.Dispose(); } } }; } catch (Exception ex) { result.UnhandledException = ex; UpdateCompleted(monitor, aggOp, file, genFile, result, false); } }
public IAsyncOperation Generate(IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation (() => { var buildResult = file.Project.RunTarget (monitor, targetName, IdeApp.Workspace.ActiveConfiguration); foreach (var err in buildResult.Errors) { result.Errors.Add (new CompilerError (err.FileName, err.Line, err.Column, err.ErrorNumber, err.ErrorText) { IsWarning = err.IsWarning }); } }, result); }
public IAsyncOperation Generate(IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation (delegate { var outputfile = file.FilePath.ChangeExtension(".Designer.cs"); var ns = GetNamespaceHint (file, outputfile); var cn = file.FilePath.FileNameWithoutExtension; GenerateDesignerFile(file.FilePath.FullPath, ns, cn, outputfile); result.GeneratedFilePath = outputfile; }, result); }
public static Action GenerateFile(ProjectFile file, SingleFileCustomToolResult result, bool internalClass) { return(delegate { var dnp = file.Project as DotNetProject; if (dnp == null) { var err = "ResXFileCodeGenerator can only be used with .NET projects"; result.Errors.Add(new CompilerError(null, 0, 0, null, err)); return; } var provider = dnp.LanguageBinding.GetCodeDomProvider(); if (provider == null) { var err = "ResXFileCodeGenerator can only be used with languages that support CodeDOM"; result.Errors.Add(new CompilerError(null, 0, 0, null, err)); return; } var outputfile = file.FilePath.ChangeExtension(".Designer." + provider.FileExtension); var ns = CustomToolService.GetFileNamespace(file, outputfile); var cn = provider.CreateValidIdentifier(file.FilePath.FileNameWithoutExtension); var rd = new Dictionary <object, object> (); using (var r = new ResXResourceReader(file.FilePath)) { r.UseResXDataNodes = true; r.BasePath = file.FilePath.ParentDirectory; foreach (DictionaryEntry e in r) { rd.Add(e.Key, e.Value); } } string[] unmatchable; var ccu = StronglyTypedResourceBuilder.Create(rd, cn, ns, provider, internalClass, out unmatchable); if (TargetsPcl2Framework(dnp)) { FixupPclTypeInfo(ccu); } foreach (var p in unmatchable) { var msg = string.Format("Could not generate property for resource ID '{0}'", p); result.Errors.Add(new CompilerError(file.FilePath, 0, 0, null, msg)); } using (var w = new StreamWriter(outputfile, false, Encoding.UTF8)) provider.GenerateCodeFromCompileUnit(ccu, w, new CodeGeneratorOptions()); result.GeneratedFilePath = outputfile; }); }
public ThreadAsyncOperation(Action task, SingleFileCustomToolResult result) { if (result == null) { throw new ArgumentNullException("result"); } this.task = task; this.result = result; thread = new Thread(Run); thread.Start(); }
public async Task Generate(ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { var buildResult = await file.Project.PerformGeneratorAsync(monitor, IdeApp.Workspace.ActiveConfiguration, this.targetName); foreach (var err in buildResult.BuildResult.Errors) { result.Errors.Add(new CompilerError(err.FileName, err.Line, err.Column, err.ErrorNumber, err.ErrorText) { IsWarning = err.IsWarning }); } }
public IAsyncOperation Generate(IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return(new ThreadAsyncOperation(() => { var buildResult = file.Project.RunTarget(monitor, targetName, IdeApp.Workspace.ActiveConfiguration); foreach (var err in buildResult.Errors) { result.Errors.Add(new CompilerError(err.FileName, err.Line, err.Column, err.ErrorNumber, err.ErrorText) { IsWarning = err.IsWarning }); } }, result)); }
public static Action GenerateFile (ProjectFile file, SingleFileCustomToolResult result, bool internalClass) { return delegate { var dnp = file.Project as DotNetProject; if (dnp == null) { var err = "ResXFileCodeGenerator can only be used with .NET projects"; result.Errors.Add (new CompilerError (null, 0, 0, null, err)); return; } var provider = dnp.LanguageBinding.GetCodeDomProvider (); if (provider == null) { var err = "ResXFileCodeGenerator can only be used with languages that support CodeDOM"; result.Errors.Add (new CompilerError (null, 0, 0, null, err)); return; } var outputfile = file.FilePath.ChangeExtension (".Designer." + provider.FileExtension); var ns = CustomToolService.GetFileNamespace (file, outputfile); var cn = provider.CreateValidIdentifier (file.FilePath.FileNameWithoutExtension); var rd = new Dictionary<object, object> (); using (var r = new ResXResourceReader (file.FilePath)) { r.UseResXDataNodes = true; r.BasePath = file.FilePath.ParentDirectory; foreach (DictionaryEntry e in r) { rd.Add (e.Key, e.Value); } } string[] unmatchable; var ccu = StronglyTypedResourceBuilder.Create (rd, cn, ns, provider, internalClass, out unmatchable); if (TargetsPcl2Framework (dnp)) { FixupPclTypeInfo (ccu); } foreach (var p in unmatchable) { var msg = string.Format ("Could not generate property for resource ID '{0}'", p); result.Errors.Add (new CompilerError (file.FilePath, 0, 0, null, msg)); } using (var w = new StreamWriter (outputfile, false, Encoding.UTF8)) provider.GenerateCodeFromCompileUnit (ccu, w, new CodeGeneratorOptions ()); result.GeneratedFilePath = outputfile; }; }
public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation (delegate { using (var h = TextTemplatingService.GetTemplatingDomain ()) { var host = (MonoDevelopTemplatingHost) h.Domain.CreateInstanceAndUnwrap ( typeof (MonoDevelopTemplatingHost).Assembly.FullName, typeof (MonoDevelopTemplatingHost).FullName); var defaultOutputName = file.FilePath.ChangeExtension (".cs"); //cs extension for VS compat host.ProcessTemplate (file.FilePath, defaultOutputName); result.GeneratedFilePath = host.OutputFile; result.Errors.AddRange (host.Errors); foreach (var err in host.Errors) monitor.Log.WriteLine (err.ToString ()); } }, result); }
public Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return Task.Run (delegate { using (var host = new ProjectFileTemplatingHost (file, IdeApp.Workspace.ActiveConfiguration)) { string outputFile; Generate (host, file, out outputFile); result.GeneratedFilePath = outputFile; result.Errors.AddRange (host.Errors); foreach (var err in host.Errors) monitor.Log.WriteLine (err); } }); }
public Task Generate (ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return Task.Run (delegate { using (var host = new ProjectFileTemplatingHost (file, IdeApp.Workspace.ActiveConfiguration)) { host.AddMonoDevelopHostImport (); var defaultOutputName = file.FilePath.ChangeExtension (".cs"); //cs extension for VS compat string ns = CustomToolService.GetFileNamespace (file, defaultOutputName); LogicalSetData ("NamespaceHint", ns); host.ProcessTemplate (file.FilePath, defaultOutputName); result.GeneratedFilePath = host.OutputFile; result.Errors.AddRange (host.Errors); foreach (var err in host.Errors) monitor.Log.WriteLine (err); } }); }
public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation (delegate { using (var host = new ProjectFileTemplatingHost (file)) { var defaultOutputName = file.FilePath.ChangeExtension (".cs"); //cs extension for VS compat string ns = TextTemplatingFilePreprocessor.GetNamespaceHint (file, defaultOutputName); TextTemplatingFilePreprocessor.LogicalSetData ("NamespaceHint", ns, result.Errors); host.ProcessTemplate (file.FilePath, defaultOutputName); result.GeneratedFilePath = host.OutputFile; result.Errors.AddRange (host.Errors); foreach (var err in host.Errors) monitor.Log.WriteLine (err); } }, result); }
public IAsyncOperation Generate(IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation(() => { FilePath codeFilePath = file.FilePath.ChangeExtension(".feature.cs"); try { codeFilePath = GenerateFeatureCodeFileFor(file); } catch (Exception ex) { HandleException(ex, file, result); } result.GeneratedFilePath = codeFilePath; }, result); }
internal static void Generate(IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result, bool internalClass) { var outputFile = file.FilePath.ChangeExtension (".Designer.cs"); DotNetProject dnProject = file.Project as DotNetProject; if (dnProject == null) return; //don't do anything if file not in project CodeDomProvider provider = dnProject.LanguageBinding.GetCodeDomProvider (); if (provider == null) return; //don't do anything if no provider available // this returns the namespace in accordance with DotNetNamingPolicy in use string resourcesNamespace = dnProject.GetDefaultNamespace (outputFile.ToString ()); string baseName = file.FilePath.FileNameWithoutExtension; string genCodeNamespace = String.IsNullOrWhiteSpace (file.CustomToolNamespace) ? resourcesNamespace : file.CustomToolNamespace; string [] unmatchables; CodeCompileUnit ccu; ccu = StronglyTypedResourceBuilder.Create (file.FilePath.ToString (), baseName, genCodeNamespace, resourcesNamespace, provider, internalClass, out unmatchables); // generate code overwriting existing file using (var writer = new StreamWriter (outputFile, false)) { provider.GenerateCodeFromCompileUnit (ccu, writer, new CodeGeneratorOptions()); } result.GeneratedFilePath = outputFile; foreach (var u in unmatchables) //should report these better? monitor.Log.WriteLine ("Unable to create property for resource named: {0}", u); }
public IAsyncOperation Generate(IProgressMonitor monitor, ProjectFile featureFile, SingleFileCustomToolResult result) { return new ThreadAsyncOperation(() => { var ideSingleFileGenerator = new IdeSingleFileGenerator(); ideSingleFileGenerator.GenerationError += delegate(TestGenerationError error) { result.Errors.Add(new CompilerError(featureFile.Name, error.Line + 1, error.LinePosition + 1, "0", error.Message)); }; ideSingleFileGenerator.OtherError += delegate(Exception exception) { result.UnhandledException = exception; }; string outputFilePath = ideSingleFileGenerator.GenerateFile(featureFile.FilePath, null, () => new MonoDevelopGeneratorServices(featureFile.Project)); result.GeneratedFilePath = outputFilePath; }, result); }
public static Action GenerateFile(ProjectFile file, SingleFileCustomToolResult result, bool internalClass) { return(delegate { var dnp = file.Project as DotNetProject; if (dnp == null) { var err = "ResXFileCodeGenerator can only be used with .NET projects"; result.Errors.Add(new CompilerError(null, 0, 0, null, err)); return; } var provider = dnp.LanguageBinding.GetCodeDomProvider(); if (provider == null) { var err = "ResXFileCodeGenerator can only be used with languages that support CodeDOM"; result.Errors.Add(new CompilerError(null, 0, 0, null, err)); return; } var outputfile = file.FilePath.ChangeExtension(".Designer." + provider.FileExtension); var ns = CustomToolService.GetFileNamespace(file, outputfile); var cn = provider.CreateValidIdentifier(file.FilePath.FileNameWithoutExtension); string[] unmatchable; var ccu = StronglyTypedResourceBuilder.Create(file.FilePath, cn, ns, provider, internalClass, out unmatchable); foreach (var p in unmatchable) { var msg = string.Format("Could not generate property for resource ID '{0}'", p); result.Errors.Add(new CompilerError(file.FilePath, 0, 0, null, msg)); } using (var w = new StreamWriter(outputfile, false, Encoding.UTF8)) provider.GenerateCodeFromCompileUnit(ccu, w, new CodeGeneratorOptions()); result.GeneratedFilePath = outputfile; }); }
public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation (delegate { var host = new ProjectFileTemplatingHost (file); var dnp = file.Project as DotNetProject; if (dnp == null) { var msg = "Precompiled T4 templates are only supported in .NET projects"; result.Errors.Add (new CompilerError (file.Name, -1, -1, null, msg)); monitor.Log.WriteLine (msg); return; } var provider = dnp.LanguageBinding.GetCodeDomProvider (); if (provider == null) { var msg = "Precompiled T4 templates are only supported for .NET languages with CodeDOM providers"; result.Errors.Add (new CompilerError (file.Name, -1, -1, null, msg)); monitor.Log.WriteLine (msg); return; }; var outputFile = file.FilePath.ChangeExtension (provider.FileExtension); var encoding = System.Text.Encoding.UTF8; string langauge; string[] references; string className = provider.CreateValidIdentifier (file.FilePath.FileNameWithoutExtension); string classNamespace = CustomToolService.GetFileNamespace (file, outputFile); LogicalSetData ("NamespaceHint", classNamespace, result.Errors); host.PreprocessTemplate (file.FilePath, className, classNamespace, outputFile, encoding, out langauge, out references); result.GeneratedFilePath = outputFile; result.Errors.AddRange (host.Errors); foreach (var err in host.Errors) monitor.Log.WriteLine (err.ToString ()); }, result); }
public async Task Generate(ProgressMonitor monitor, ProjectFile featureFile, SingleFileCustomToolResult result) { await Task.Run(() => { // This is the project directory containing the .imfl file string dir = System.IO.Path.GetDirectoryName(featureFile.FilePath); monitor.Log.WriteLine("Creating images for " + featureFile.FilePath); var processor = new ImageProcessor(monitor, result); var lines = System.IO.File.ReadLines(featureFile.FilePath); int lineNumber = 0; var outputSpecifiers = new List<OutputSpecifier>(); foreach (var line in lines) { lineNumber++; if (String.IsNullOrWhiteSpace(line)) continue; if (line.StartsWith("#")) continue; //monitor.Log.WriteLine("Interpreting " + line); try { // Slight hack ... if (line.Contains("type:")) { var ts = JsonConvert.DeserializeObject<OutputSpecifier>(line); if (ts != null) { string testPath = processor.GetFullOutputPath(dir, ts, "test.svg"); var directory = Path.GetDirectoryName(testPath); if (!Directory.Exists(directory)) { string shortDirectory = Path.GetDirectoryName(string.Format(ts.path, "x.png")); result.Errors.Add(new CompilerError(featureFile.FilePath, lineNumber, 1, "Err17", "Directory not found " + shortDirectory)); } else { outputSpecifiers.Add(ts); monitor.Log.WriteLine("Added output specifier " + line); } } else { result.Errors.Add(new CompilerError(featureFile.FilePath, lineNumber, 1, "Err2", "Could not parse output specifier")); } } else if (line.Contains("process:")) { var ps = JsonConvert.DeserializeObject<ProcessSpecifier>(line); if (ps != null) { // Process output var subdir = Path.GetDirectoryName(ps.process); var searchPattern = Path.GetFileName(ps.process); var inputDirectory = Path.Combine(dir, subdir); if (Directory.Exists(inputDirectory)) { var outputters = outputSpecifiers.Where(s => [email protected](s.type)); processor.Process(dir, Directory.GetFiles(inputDirectory, searchPattern), outputters, lineNumber); } else { result.Errors.Add(new CompilerError(featureFile.FilePath, lineNumber, 1, "Err17", "Directory not found " + subdir)); } } else { result.Errors.Add(new CompilerError(featureFile.FilePath, lineNumber, 1, "Err2", "Could not parse process specifier")); } } else { result.Errors.Add(new CompilerError(featureFile.FilePath, lineNumber, 1, "Err2", "Could not parse this line")); } } catch (Exception ex) { result.Errors.Add(new CompilerError(featureFile.FilePath, lineNumber, 1, "Err1", ex.ToString())); } } result.GeneratedFilePath = ""; }); }
public override Task Generate(ProgressMonitor monitor, Project project, ProjectFile file, SingleFileCustomToolResult result) { return(this.customTool.Generate(monitor, file, result)); }
public ImageProcessor(IProgressMonitor monitor, SingleFileCustomToolResult result) { this.monitor = monitor; this.result = result; }
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 (!force && genFile != null && File.Exists(genFile.FilePath) && File.GetLastWriteTime(file.FilePath) < File.GetLastWriteTime(genFile.FilePath)) { return; } TaskService.Errors.ClearByOwner(file); //if this file is already being run, cancel it lock (runningTasks) { IAsyncOperation runningTask; if (runningTasks.TryGetValue(file.FilePath, out runningTask)) { runningTask.Cancel(); runningTasks.Remove(file.FilePath); } } var monitor = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor(false); var result = new SingleFileCustomToolResult(); var aggOp = new AggregatedOperationMonitor(monitor); try { monitor.BeginTask(GettextCatalog.GetString("Running generator '{0}' on file '{1}'...", file.Generator, file.Name), 1); var op = tool.Generate(monitor, file, result); runningTasks.Add(file.FilePath, op); aggOp.AddOperation(op); op.Completed += delegate { lock (runningTasks) { IAsyncOperation runningTask; if (runningTasks.TryGetValue(file.FilePath, out runningTask) && runningTask == op) { runningTasks.Remove(file.FilePath); UpdateCompleted(monitor, aggOp, file, genFile, result); } else { //it was cancelled because another was run for the same file, so just clean up aggOp.Dispose(); monitor.EndTask(); monitor.ReportWarning(GettextCatalog.GetString("Cancelled because generator ran again for the same file")); monitor.Dispose(); } } }; } catch (Exception ex) { result.UnhandledException = ex; UpdateCompleted(monitor, aggOp, file, genFile, result); } }
public async static Task GenerateFile(ProjectFile file, SingleFileCustomToolResult result, bool internalClass) { var dnp = file.Project as DotNetProject; if (dnp == null) { var err = "ResXFileCodeGenerator can only be used with .NET projects"; result.Errors.Add(new CompilerError(null, 0, 0, null, err)); return; } var provider = dnp.LanguageBinding.GetCodeDomProvider(); if (provider == null) { const string err = "ResXFileCodeGenerator can only be used with languages that support CodeDOM"; result.Errors.Add(new CompilerError(null, 0, 0, null, err)); return; } var outputfile = file.FilePath.ChangeExtension(".Designer." + provider.FileExtension); //use the Visual Studio naming polict, so it matches code generated by VS var codeNamespace = CustomToolService.GetFileNamespace(file, outputfile, true); //no need to escape/cleanup, StronglyTypedResourceBuilder does that var name = file.FilePath.FileNameWithoutExtension; //NOTE: we fix it up later with the real resource ID, this is just a fallback in case that fails var resourcesNamespace = dnp.GetDefaultNamespace(outputfile, true); var rd = new Dictionary <object, object> (); var filePath = file.FilePath; var targetsPcl2Framework = TargetsPcl2Framework(dnp); //Compute the *real* ID of the embedded resource. It can be affected by LogicalName so might not match the //class name, but StronglyTypedResourceBuilder only accepts a single name for both. //Fix this by patching it into the CodeDOM later. var id = file.ResourceId; const string suffix = ".resources"; if (id.Length > suffix.Length && id.EndsWith(suffix, StringComparison.OrdinalIgnoreCase)) { id = id.Substring(0, id.Length - suffix.Length); } await Task.Run(() => { using (var r = new ResXResourceReader(filePath)) { r.BasePath = filePath.ParentDirectory; foreach (DictionaryEntry e in r) { rd.Add(e.Key, e.Value); } } string[] unmatchable; var ccu = StronglyTypedResourceBuilder.Create(rd, name, codeNamespace, resourcesNamespace, provider, internalClass, out unmatchable); if (targetsPcl2Framework) { FixupPclTypeInfo(ccu); } FixupEmbeddedResourceID(ccu, id); foreach (var p in unmatchable) { var msg = string.Format("Could not generate property for resource ID '{0}'", p); result.Errors.Add(new CompilerError(filePath, 0, 0, null, msg)); } lock (file) { // Avoid race if ResXFileCodeGenerator is called more than once for the same file using (var w = new StreamWriter(outputfile, false, Encoding.UTF8)) provider.GenerateCodeFromCompileUnit(ccu, w, new CodeGeneratorOptions()); } result.GeneratedFilePath = outputfile; }); }
public IAsyncOperation Generate(IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return(new ThreadAsyncOperation(GenerateFile(file, result, true), result)); }
public async static Task GenerateFile (ProjectFile file, SingleFileCustomToolResult result, bool internalClass) { var dnp = file.Project as DotNetProject; if (dnp == null) { var err = "ResXFileCodeGenerator can only be used with .NET projects"; result.Errors.Add (new CompilerError (null, 0, 0, null, err)); return; } var provider = dnp.LanguageBinding.GetCodeDomProvider (); if (provider == null) { const string err = "ResXFileCodeGenerator can only be used with languages that support CodeDOM"; result.Errors.Add (new CompilerError (null, 0, 0, null, err)); return; } var outputfile = file.FilePath.ChangeExtension (".Designer." + provider.FileExtension); //use the Visual Studio naming polict, so it matches code generated by VS var codeNamespace = CustomToolService.GetFileNamespace (file, outputfile, true); //no need to escape/cleanup, StronglyTypedResourceBuilder does that var name = file.FilePath.FileNameWithoutExtension; //NOTE: we fix it up later with the real resource ID, this is just a fallback in case that fails var resourcesNamespace = dnp.GetDefaultNamespace (outputfile, true); var rd = new Dictionary<object, object> (); var filePath = file.FilePath; var targetsPcl2Framework = TargetsPcl2Framework (dnp); //Compute the *real* ID of the embedded resource. It can be affected by LogicalName so might not match the //class name, but StronglyTypedResourceBuilder only accepts a single name for both. //Fix this by patching it into the CodeDOM later. var id = file.ResourceId; const string suffix = ".resources"; if (id.Length > suffix.Length && id.EndsWith (suffix, StringComparison.OrdinalIgnoreCase)) { id = id.Substring (0, id.Length - suffix.Length); } await Task.Run (() => { using (var r = new ResXResourceReader (filePath)) { r.BasePath = filePath.ParentDirectory; foreach (DictionaryEntry e in r) { rd.Add (e.Key, e.Value); } } string[] unmatchable; var ccu = StronglyTypedResourceBuilder.Create (rd, name, codeNamespace, resourcesNamespace, provider, internalClass, out unmatchable); if (targetsPcl2Framework) { FixupPclTypeInfo (ccu); } FixupEmbeddedResourceID (ccu, id); foreach (var p in unmatchable) { var msg = string.Format ("Could not generate property for resource ID '{0}'", p); result.Errors.Add (new CompilerError (filePath, 0, 0, null, msg)); } lock (file) { // Avoid race if ResXFileCodeGenerator is called more than once for the same file using (var w = new StreamWriter (outputfile, false, Encoding.UTF8)) provider.GenerateCodeFromCompileUnit (ccu, w, new CodeGeneratorOptions ()); } result.GeneratedFilePath = outputfile; }); }
static void Update (IProgressMonitor monitor, IEnumerator<ProjectFile> fileEnumerator, bool force, int succeeded, int warnings, int errors) { ProjectFile file = fileEnumerator.Current; ISingleFileCustomTool tool; ProjectFile genFile; bool shouldRun; while (!(shouldRun = ShouldRunGenerator (file, force, out tool, out genFile)) && fileEnumerator.MoveNext ()) continue; //no files which can be generated in remaining elements of the collection, nothing to do if (!shouldRun) { WriteSummaryResults (monitor, succeeded, warnings, errors); return; } TaskService.Errors.ClearByOwner (file); var result = new SingleFileCustomToolResult (); monitor.BeginTask (GettextCatalog.GetString ("Running generator '{0}' on file '{1}'...", file.Generator, file.Name), 1); try { IAsyncOperation op = tool.Generate (monitor, file, result); op.Completed += delegate { if (result.Success) { monitor.Log.WriteLine (GettextCatalog.GetString ("File '{0}' was generated successfully.", result.GeneratedFilePath)); succeeded++; } else if (result.SuccessWithWarnings) { monitor.Log.WriteLine (GettextCatalog.GetString ("File '{0}' was generated with warnings.", result.GeneratedFilePath)); warnings++; } else { monitor.Log.WriteLine (GettextCatalog.GetString ("Errors in file '{0}' generation.", result.GeneratedFilePath)); errors++; } //check that we can process further. If UpdateCompleted returns `true` this means no errors or non-fatal errors occured if (UpdateCompleted (monitor, null, file, genFile, result, true) && fileEnumerator.MoveNext ()) Update (monitor, fileEnumerator, force, succeeded, warnings, errors); else WriteSummaryResults (monitor, succeeded, warnings, errors); }; } catch (Exception ex) { result.UnhandledException = ex; UpdateCompleted (monitor, null, file, genFile, result, true); } }
public static async void Update (ProjectFile file, bool force) { ISingleFileCustomTool tool; ProjectFile genFile; if (!ShouldRunGenerator (file, force, out tool, out genFile)) { return; } TaskService.Errors.ClearByOwner (file); TaskInfo runningTask; TaskCompletionSource<bool> newTask = new TaskCompletionSource<bool> (); var result = new SingleFileCustomToolResult (); Task existingTask = null; CancellationTokenSource cs = new CancellationTokenSource (); // if this file is already being run, cancel it lock (runningTasks) { if (runningTasks.TryGetValue (file.FilePath, out runningTask)) { runningTask.CancellationTokenSource.Cancel (); runningTasks.Remove (file.FilePath); existingTask = runningTask.Task; } runningTask = new TaskInfo { Task = newTask.Task, CancellationTokenSource = cs, Result = result }; runningTasks.Add (file.FilePath, runningTask); } // If a task was already running, wait for it to finish. Running the same task in parallel may lead // to file sharing violation errors if (existingTask != null) { try { await existingTask; } catch { // Ignore exceptions, they are handled elsewhere } } // Maybe I was cancelled while I was waiting. In that case, the task has already been removed from // the runningTasks collection if (cs.IsCancellationRequested) return; // Execute the generator Exception error = null; var monitor = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor (false).WithCancellationSource (cs); try { monitor.BeginTask (GettextCatalog.GetString ("Running generator '{0}' on file '{1}'...", file.Generator, file.Name), 1); try { await tool.Generate (monitor, file, result); } catch (Exception ex) { error = ex; result.UnhandledException = ex; } // Generation has finished. Remove the task from the runningTasks collection lock (runningTasks) { TaskInfo registeredTask; if (runningTasks.TryGetValue (file.FilePath, out registeredTask) && registeredTask == runningTask) { runningTasks.Remove (file.FilePath); UpdateCompleted (monitor, file, genFile, result, false); } else { // it was cancelled because another was run for the same file, so just clean up monitor.EndTask (); monitor.ReportWarning (GettextCatalog.GetString ("Cancelled because generator ran again for the same file")); monitor.Dispose (); } } } catch (Exception ex) { result.UnhandledException = ex; UpdateCompleted (monitor, file, genFile, result, false); } finally { if (error == null) newTask.SetResult (true); else { newTask.SetException (error); } } }
static void UpdateCompleted (IProgressMonitor monitor, AggregatedOperationMonitor aggOp, ProjectFile file, ProjectFile genFile, SingleFileCustomToolResult result) { monitor.EndTask (); aggOp.Dispose (); if (monitor.IsCancelRequested) { monitor.ReportError (GettextCatalog.GetString ("Cancelled"), null); monitor.Dispose (); return; } string genFileName; try { bool broken = false; if (result.UnhandledException != null) { broken = true; string msg = GettextCatalog.GetString ("The '{0}' code generator crashed", file.Generator); result.Errors.Add (new CompilerError (file.Name, 0, 0, "", msg + ": " + result.UnhandledException.Message)); monitor.ReportError (msg, result.UnhandledException); LoggingService.LogError (msg, 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 (!broken && !validName) { broken = true; string msg = GettextCatalog.GetString ("The '{0}' code generator output invalid filename '{1}'", file.Generator, result.GeneratedFilePath); result.Errors.Add (new CompilerError (file.Name, 0, 0, "", msg)); monitor.ReportError (msg, null); } 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 (!result.GeneratedFilePath.IsNullOrEmpty && File.Exists (result.GeneratedFilePath)) { Gtk.Application.Invoke (delegate { if (genFile == null) { genFile = file.Project.AddFile (result.GeneratedFilePath); } else if (result.GeneratedFilePath != genFile.FilePath) { genFile.Name = result.GeneratedFilePath; } file.LastGenOutput = genFileName; genFile.DependsOn = file.FilePath.FileName; IdeApp.ProjectOperations.Save (file.Project); }); } }
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 (!force && genFile != null && File.Exists (genFile.FilePath) && File.GetLastWriteTime (file.FilePath) < File.GetLastWriteTime (genFile.FilePath)) { return; } TaskService.Errors.ClearByOwner (file); //if this file is already being run, cancel it lock (runningTasks) { IAsyncOperation runningTask; if (runningTasks.TryGetValue (file.FilePath, out runningTask)) { runningTask.Cancel (); runningTasks.Remove (file.FilePath); } } var monitor = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor (false); var result = new SingleFileCustomToolResult (); var aggOp = new AggregatedOperationMonitor (monitor); try { monitor.BeginTask (GettextCatalog.GetString ("Running generator '{0}' on file '{1}'...", file.Generator, file.Name), 1); var op = tool.Generate (monitor, file, result); runningTasks.Add (file.FilePath, op); aggOp.AddOperation (op); op.Completed += delegate { lock (runningTasks) { IAsyncOperation runningTask; if (runningTasks.TryGetValue (file.FilePath, out runningTask) && runningTask == op) { runningTasks.Remove (file.FilePath); UpdateCompleted (monitor, aggOp, file, genFile, result); } else { //it was cancelled because another was run for the same file, so just clean up aggOp.Dispose (); monitor.EndTask (); monitor.ReportWarning (GettextCatalog.GetString ("Cancelled because generator ran again for the same file")); monitor.Dispose (); } } }; } catch (Exception ex) { result.UnhandledException = ex; UpdateCompleted (monitor, aggOp, file, genFile, result); } }
public IAsyncOperation Generate (IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation (GenerateFile (file, result, true), result); }
static void UpdateCompleted(IProgressMonitor monitor, AggregatedOperationMonitor aggOp, ProjectFile file, ProjectFile genFile, SingleFileCustomToolResult result) { monitor.EndTask(); aggOp.Dispose(); if (monitor.IsCancelRequested) { monitor.ReportError(GettextCatalog.GetString("Cancelled"), null); monitor.Dispose(); return; } string genFileName; try { bool broken = false; if (result.UnhandledException != null) { broken = true; string msg = GettextCatalog.GetString("The '{0}' code generator crashed", file.Generator); result.Errors.Add(new CompilerError(file.Name, 0, 0, "", msg + ": " + result.UnhandledException.Message)); monitor.ReportError(msg, result.UnhandledException); LoggingService.LogError(msg, 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 (!broken && !validName) { broken = true; string msg = GettextCatalog.GetString("The '{0}' code generator output invalid filename '{1}'", file.Generator, result.GeneratedFilePath); result.Errors.Add(new CompilerError(file.Name, 0, 0, "", msg)); monitor.ReportError(msg, null); } 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 (!result.GeneratedFilePath.IsNullOrEmpty && File.Exists(result.GeneratedFilePath)) { Gtk.Application.Invoke(delegate { if (genFile == null) { genFile = file.Project.AddFile(result.GeneratedFilePath); } else if (result.GeneratedFilePath != genFile.FilePath) { genFile.Name = result.GeneratedFilePath; } file.LastGenOutput = genFileName; genFile.DependsOn = file.FilePath.FileName; IdeApp.ProjectOperations.Save(file.Project); }); } }
public IAsyncOperation Generate(IProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return new ThreadAsyncOperation (delegate { ResXCodeFileGenerator.Generate (monitor, file, result, false); }, result); }
public abstract Task Generate(ProgressMonitor monitor, Project project, ProjectFile file, SingleFileCustomToolResult result);
public Task Generate(ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return(ResXFileCodeGenerator.GenerateFile(file, result, false)); }
public static void Update (ProjectFile file, bool force) { ISingleFileCustomTool tool; ProjectFile genFile; if (!ShouldRunGenerator (file, force, out tool, out genFile)) { return; } TaskService.Errors.ClearByOwner (file); //if this file is already being run, cancel it lock (runningTasks) { IAsyncOperation runningTask; if (runningTasks.TryGetValue (file.FilePath, out runningTask)) { runningTask.Cancel (); runningTasks.Remove (file.FilePath); } } var monitor = IdeApp.Workbench.ProgressMonitors.GetToolOutputProgressMonitor (false); var result = new SingleFileCustomToolResult (); var aggOp = new AggregatedOperationMonitor (monitor); try { monitor.BeginTask (GettextCatalog.GetString ("Running generator '{0}' on file '{1}'...", file.Generator, file.Name), 1); IAsyncOperation op = tool.Generate (monitor, file, result); runningTasks.Add (file.FilePath, op); aggOp.AddOperation (op); op.Completed += delegate { lock (runningTasks) { IAsyncOperation runningTask; if (runningTasks.TryGetValue (file.FilePath, out runningTask) && runningTask == op) { runningTasks.Remove (file.FilePath); UpdateCompleted (monitor, aggOp, file, genFile, result, false); } else { //it was cancelled because another was run for the same file, so just clean up aggOp.Dispose (); monitor.EndTask (); monitor.ReportWarning (GettextCatalog.GetString ("Cancelled because generator ran again for the same file")); monitor.Dispose (); } } }; } catch (Exception ex) { result.UnhandledException = ex; UpdateCompleted (monitor, aggOp, file, genFile, result, false); } }
static bool UpdateCompleted(IProgressMonitor monitor, AggregatedOperationMonitor aggOp, ProjectFile file, ProjectFile genFile, SingleFileCustomToolResult result, bool runMultipleFiles) { monitor.EndTask(); if (aggOp != null) { aggOp.Dispose(); } if (monitor.IsCancelRequested) { monitor.ReportError(GettextCatalog.GetString("Cancelled"), null); monitor.Dispose(); return(false); } string genFileName; try { bool broken = false; if (result.UnhandledException != null) { broken = true; string msg = GettextCatalog.GetString("The '{0}' code generator crashed", file.Generator); result.Errors.Add(new CompilerError(file.Name, 0, 0, "", msg + ": " + result.UnhandledException.Message)); monitor.ReportError(msg, result.UnhandledException); LoggingService.LogError(msg, result.UnhandledException); } genFileName = result.GeneratedFilePath.IsNullOrEmpty? null : result.GeneratedFilePath.ToRelative(file.FilePath.ParentDirectory); if (!string.IsNullOrEmpty(genFileName)) { bool validName = genFileName.IndexOfAny(new [] { '/', '\\' }) < 0 && FileService.IsValidFileName(genFileName); if (!broken && !validName) { broken = true; string msg = GettextCatalog.GetString("The '{0}' code generator output invalid filename '{1}'", file.Generator, result.GeneratedFilePath); result.Errors.Add(new CompilerError(file.Name, 0, 0, "", msg)); monitor.ReportError(msg, null); } } if (result.Errors.Count > 0) { DispatchService.GuiDispatch(delegate { 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(true); } if (!runMultipleFiles) { if (result.Success) { monitor.ReportSuccess("Generated file successfully."); } else if (result.SuccessWithWarnings) { monitor.ReportSuccess("Warnings in file generation."); } else { monitor.ReportError("Errors in file generation.", null); } } } finally { if (!runMultipleFiles) { monitor.Dispose(); } } if (result.GeneratedFilePath.IsNullOrEmpty || !File.Exists(result.GeneratedFilePath)) { return(true); } // broadcast a change event so text editors etc reload the file FileService.NotifyFileChanged(result.GeneratedFilePath); // add file to project, update file properties, etc Gtk.Application.Invoke(delegate { bool projectChanged = false; if (genFile == null) { genFile = file.Project.AddFile(result.GeneratedFilePath, result.OverrideBuildAction); projectChanged = true; } else if (result.GeneratedFilePath != genFile.FilePath) { genFile.Name = result.GeneratedFilePath; projectChanged = true; } if (file.LastGenOutput != genFileName) { file.LastGenOutput = genFileName; projectChanged = true; } if (genFile.DependsOn != file.FilePath.FileName) { genFile.DependsOn = file.FilePath.FileName; projectChanged = true; } if (projectChanged) { IdeApp.ProjectOperations.Save(file.Project); } }); return(true); }
static bool UpdateCompleted (IProgressMonitor monitor, AggregatedOperationMonitor aggOp, ProjectFile file, ProjectFile genFile, SingleFileCustomToolResult result, bool runMultipleFiles) { monitor.EndTask (); if (aggOp != null) aggOp.Dispose (); if (monitor.IsCancelRequested) { monitor.ReportError (GettextCatalog.GetString ("Cancelled"), null); monitor.Dispose (); return false; } string genFileName; try { bool broken = false; if (result.UnhandledException != null) { broken = true; string msg = GettextCatalog.GetString ("The '{0}' code generator crashed", file.Generator); result.Errors.Add (new CompilerError (file.Name, 0, 0, "", msg + ": " + result.UnhandledException.Message)); monitor.ReportError (msg, result.UnhandledException); LoggingService.LogError (msg, result.UnhandledException); } genFileName = result.GeneratedFilePath.IsNullOrEmpty? null : result.GeneratedFilePath.ToRelative (file.FilePath.ParentDirectory); if (!string.IsNullOrEmpty (genFileName)) { bool validName = genFileName.IndexOfAny (new [] { '/', '\\' }) < 0 && FileService.IsValidFileName (genFileName); if (!broken && !validName) { broken = true; string msg = GettextCatalog.GetString ("The '{0}' code generator output invalid filename '{1}'", file.Generator, result.GeneratedFilePath); result.Errors.Add (new CompilerError (file.Name, 0, 0, "", msg)); monitor.ReportError (msg, null); } } if (result.Errors.Count > 0) { DispatchService.GuiDispatch (delegate { 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 true; if (!runMultipleFiles) { if (result.Success) monitor.ReportSuccess ("Generated file successfully."); else if (result.SuccessWithWarnings) monitor.ReportSuccess ("Warnings in file generation."); else monitor.ReportError ("Errors in file generation.", null); } } finally { if (!runMultipleFiles) monitor.Dispose (); } if (result.GeneratedFilePath.IsNullOrEmpty || !File.Exists (result.GeneratedFilePath)) return true; // broadcast a change event so text editors etc reload the file FileService.NotifyFileChanged (result.GeneratedFilePath); // add file to project, update file properties, etc Gtk.Application.Invoke (delegate { bool projectChanged = false; if (genFile == null) { genFile = file.Project.AddFile (result.GeneratedFilePath, result.OverrideBuildAction); projectChanged = true; } else if (result.GeneratedFilePath != genFile.FilePath) { genFile.Name = result.GeneratedFilePath; projectChanged = true; } if (file.LastGenOutput != genFileName) { file.LastGenOutput = genFileName; projectChanged = true; } if (genFile.DependsOn != file.FilePath.FileName) { genFile.DependsOn = file.FilePath.FileName; projectChanged = true; } if (projectChanged) IdeApp.ProjectOperations.Save (file.Project); }); return true; }
public static async void Update(ProjectFile file, Project project, bool force) { SingleProjectFileCustomTool tool; ProjectFile genFile; if (!ShouldRunGenerator(file, project, force, out tool, out genFile)) { return; } TaskService.Errors.ClearByOwner(file); TaskInfo runningTask; TaskCompletionSource <bool> newTask = new TaskCompletionSource <bool> (); var result = new SingleFileCustomToolResult(); Task existingTask = null; CancellationTokenSource cs = new CancellationTokenSource(); // if this file is already being run, cancel it lock (runningTasks) { if (runningTasks.TryGetValue(file.FilePath, out runningTask)) { runningTask.CancellationTokenSource.Cancel(); runningTasks.Remove(file.FilePath); existingTask = runningTask.Task; } runningTask = new TaskInfo { Task = newTask.Task, CancellationTokenSource = cs, Result = result }; runningTasks.Add(file.FilePath, runningTask); } // If a task was already running, wait for it to finish. Running the same task in parallel may lead // to file sharing violation errors if (existingTask != null) { try { await existingTask; } catch { // Ignore exceptions, they are handled elsewhere } } // Maybe I was cancelled while I was waiting. In that case, the task has already been removed from // the runningTasks collection if (cs.IsCancellationRequested) { newTask.TrySetResult(true); return; } // Execute the generator Exception error = null; // Share the one pad for all Tool output. Pad pad = null; if (monitorPad != null) { monitorPad.TryGetTarget(out pad); } if (pad == null) { pad = IdeApp.Workbench.ProgressMonitors.CreateMonitorPad("MonoDevelop.Ide.ToolOutput", GettextCatalog.GetString("Tool Output"), Stock.PadExecute, false, true, true); pad.Visible = true; ((DefaultMonitorPad)pad.Content).ClearOnBeginProgress = false; monitorPad = new WeakReference <Pad> (pad); } var monitor = ((DefaultMonitorPad)pad.Content).BeginProgress(GettextCatalog.GetString("Tool Output")); monitor.WithCancellationSource(cs); try { monitor.BeginTask(GettextCatalog.GetString("Running generator '{0}' on file '{1}'...", file.Generator, file.Name), 1); try { await tool.Generate(monitor, project, file, result); } catch (Exception ex) { error = ex; result.UnhandledException = ex; } // Generation has finished. Remove the task from the runningTasks collection lock (runningTasks) { TaskInfo registeredTask; if (runningTasks.TryGetValue(file.FilePath, out registeredTask) && registeredTask == runningTask) { runningTasks.Remove(file.FilePath); UpdateCompleted(monitor, file, genFile, result, false); } else { // it was cancelled because another was run for the same file, so just clean up monitor.EndTask(); monitor.ReportWarning(GettextCatalog.GetString("Cancelled because generator ran again for the same file")); monitor.Dispose(); } } } catch (Exception ex) { result.UnhandledException = ex; UpdateCompleted(monitor, file, genFile, result, false); } finally { if (error == null) { newTask.SetResult(true); } else { newTask.SetException(error); } } }
public Task Generate(ProgressMonitor monitor, ProjectFile file, SingleFileCustomToolResult result) { return(GenerateFile(file, result, true)); }