Exemplo n.º 1
0
        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);
        }