public static Stetic.CodeGenerationResult GenerateSteticCode(IProgressMonitor monitor, DotNetProject project, ConfigurationSelector configuration) { if (generating || !GtkDesignInfo.HasDesignedObjects(project)) { return(null); } GtkDesignInfo info = GtkDesignInfo.FromProject(project); info.CheckGtkFolder(); DateTime last_gen_time = File.Exists(info.SteticGeneratedFile) ? File.GetLastWriteTime(info.SteticGeneratedFile) : DateTime.MinValue; bool ref_changed = false; foreach (ProjectReference pref in project.References) { if (!pref.IsValid) { continue; } foreach (string filename in pref.GetReferencedFileNames(configuration)) { if (File.GetLastWriteTime(filename) > last_gen_time) { ref_changed = true; break; } } if (ref_changed) { break; } } // Check if generated code is already up to date. // if (!ref_changed && last_gen_time >= File.GetLastWriteTime (info.SteticFile)) // return null; if (info.GuiBuilderProject.HasError) { monitor.ReportError(GettextCatalog.GetString("GUI code generation failed for project '{0}'. The file '{1}' could not be loaded.", project.Name, info.SteticFile), null); monitor.AsyncOperation.Cancel(); return(null); } if (info.GuiBuilderProject.IsEmpty) { return(null); } monitor.Log.WriteLine(GettextCatalog.GetString("Generating GUI code for project '{0}'...", project.Name)); // Make sure the referenced assemblies are up to date. It is necessary to do // it now since they may contain widget libraries. project.CopySupportFiles(monitor, configuration); info.GuiBuilderProject.UpdateLibraries(); ArrayList projectFolders = new ArrayList(); projectFolders.Add(info.SteticFolder.FullPath); generating = true; Stetic.CodeGenerationResult generationResult = null; Exception generatedException = null; bool canGenerateInProcess = IsolationMode != Stetic.IsolationMode.None || info.GuiBuilderProject.SteticProject.CanGenerateCode; if (!canGenerateInProcess) { // Run the generation in another thread to avoid freezing the GUI System.Threading.ThreadPool.QueueUserWorkItem(delegate { try { // Generate the code in another process if stetic is not isolated CodeGeneratorProcess cob = (CodeGeneratorProcess)Runtime.ProcessService.CreateExternalProcessObject(typeof(CodeGeneratorProcess), false); using (cob) { generationResult = cob.GenerateCode(projectFolders, info.GenerateGettext, info.GettextClass, project.UsePartialTypes, info); } } catch (Exception ex) { generatedException = ex; } finally { generating = false; } }); while (generating) { DispatchService.RunPendingEvents(); System.Threading.Thread.Sleep(100); } } else { // No need to create another process, since stetic has its own backend process // or the widget libraries have no custom wrappers try { Stetic.GenerationOptions options = new Stetic.GenerationOptions(); options.UseGettext = info.GenerateGettext; options.GettextClass = info.GettextClass; generationResult = SteticApp.GenerateProjectCode(options, info.GuiBuilderProject.SteticProject); } catch (Exception ex) { generatedException = ex; } generating = false; } if (generatedException != null) { string msg = string.Empty; if (generatedException.InnerException != null) { msg = string.Format("{0}\n{1}\nInner Exception {2}\n{3}", generatedException.Message, generatedException.StackTrace, generatedException.InnerException.Message, generatedException.InnerException.StackTrace); } else { msg = string.Format("{0}\n{1}", generatedException.Message, generatedException.StackTrace); } // LoggingService.LogError ("GUI code generation failed", generatedException); LoggingService.LogError("GUI code generation failed: " + msg); throw new UserException("GUI code generation failed: " + msg); } if (generationResult == null) { return(null); } CodeDomProvider provider = project.LanguageBinding.GetCodeDomProvider(); if (provider == null) { throw new UserException("Code generation not supported for language: " + project.LanguageName); } foreach (Stetic.SteticCompilationUnit unit in generationResult.Units) { string fname; if (unit.Name.Length == 0) { fname = info.SteticGeneratedFile; } else { fname = GetBuildCodeFileName(project, unit.Name, (unit.Namespace != null) ? unit.Namespace.Name : string.Empty); } StringWriter sw = new StringWriter(); try { foreach (CodeNamespace ns in unit.Namespaces) { ns.Comments.Add(new CodeCommentStatement("This file has been generated by the GUI designer. Do not modify.")); } provider.GenerateCodeFromCompileUnit(unit, sw, new CodeGeneratorOptions()); string content = sw.ToString(); content = FormatGeneratedFile(fname, content, provider); File.WriteAllText(fname, content); } finally { FileService.NotifyFileChanged(fname); } } // Make sure the generated files are added to the project if (info.UpdateGtkFolder()) { Gtk.Application.Invoke(delegate { IdeApp.ProjectOperations.Save(project); }); } return(generationResult); }