Beispiel #1
0
        /// <summary>
        /// Runs all the subscribed visitors against the visitable tree
        /// parsed by the ITraverser implementation.
        /// </summary>
        /// <param name="source">The <c>RunnerSource</c> object to process.</param>
        private void RunSource(RunnerSource source)
        {
            GeneratorHost.Instance.Extender.Traverser.Initialize(GeneratorHost.Instance);

            // Build the result tree to use.
            IVisitable result =
                GeneratorHost.Instance.Extender.Traverser.Traverse(source.FileName);

            foreach (DictionaryEntry entry in GeneratorHost.Instance.Extender.Visitors)
            {
                IVisitor visitor = entry.Value as IVisitor;

                // If the element implements IHostedComponent, initialize it
                // with the GeneratorHost instance.
                if (visitor is IHostedComponent)
                {
                    ((IHostedComponent)visitor).Initialize(GeneratorHost.Instance);
                }
                // If the element implements INotifier, append the progress event handler.
                if (visitor is INotifier)
                {
                    // Remove it just in case it was already subscribed.
                    ((INotifier)visitor).Progress -= new ProgressEventHandler(OnBubbleProgress);
                    ((INotifier)visitor).Progress += new ProgressEventHandler(OnBubbleProgress);
                }

                result.Accept(visitor);
            }
        }
Beispiel #2
0
 /// <summary>
 /// Reinitialize values for the current processing state.
 /// </summary>
 /// <param name="source">The current source in use.</param>
 /// <param name="unit">The code graph to compile.</param>
 internal void Init(RunnerSource source, CodeCompileUnit unit)
 {
     _source = source;
     _unit   = unit;
 }
Beispiel #3
0
        /// <summary>
        /// Starts processing the file passed in the constructor.
        /// </summary>
        public void Start()
        {
            CodeCompileUnit unit;

            #region Initialize GeneratorHost variables
            GeneratorHost.Instance.Retriever = new ConfigurationRetriever(
                _config, ConfigurationSettings.AppPathConfig);

            ExtenderSection extender = (ExtenderSection)
                                       GeneratorHost.Instance.Retriever.GetConfig("extender");
            if (extender == null)
            {
                GeneratorHost.ThrowInvalidHostResponse("Invalid <extender> section.");
            }
            GeneratorHost.Instance.Extender = extender;

            GeneratorSection options = (GeneratorSection)
                                       GeneratorHost.Instance.Retriever.GetConfig("generator");
            if (options == null)
            {
                GeneratorHost.ThrowInvalidHostResponse("Invalid <generator> section.");
            }
            GeneratorHost.Instance.GeneratorOptions = options;
            // If the configured traverser implements INotifier, append the progress event handler.
            if (GeneratorHost.Instance.Extender.Traverser is INotifier)
            {
                ((INotifier)GeneratorHost.Instance.Extender.Traverser).Progress +=
                    new ProgressEventHandler(OnBubbleProgress);
            }

            GeneratorHost.Instance.InitSchema();
            #endregion

            RunnerSection section = (RunnerSection)
                                    GeneratorHost.Instance.Retriever.GetConfig("runner");

            if (section == null)
            {
                OnProgress("No <runner> section found to process!");
                return;
            }

            // Load the ordered list of files and run the process.
            foreach (DictionaryEntry sch in section.Sources)
            {
                //TODO: move TargetAssembly setting to each source to run.
                //TODO:	maybe check to include all sources in a single assembly?
                RunnerSource source = sch.Value as RunnerSource;
                // Reinitialize the current unit.

                #region Order the customizations in a sorted list.
                SortedList indexes = new SortedList();
                ArrayList  files   = new ArrayList();
                foreach (DictionaryEntry entry in section.Customizations)
                {
                    RunnerCustomization cust = entry.Value as RunnerCustomization;
                    files = indexes[cust.RunOrder] as ArrayList;
                    if (files == null)
                    {
                        files = new ArrayList();
                        indexes.Add(cust.RunOrder, files);
                    }
                    files.Add(cust.File);
                }

                foreach (DictionaryEntry entry in source.Customizations)
                {
                    RunnerCustomization cust = entry.Value as RunnerCustomization;
                    files = indexes[cust.RunOrder] as ArrayList;
                    if (files == null)
                    {
                        files = new ArrayList();
                        indexes.Add(cust.RunOrder, files);
                    }
                    files.Add(cust.File);
                }
                #endregion

                #region Execute the ordered entries
                foreach (DictionaryEntry entry in indexes)
                {
                    unit = new CodeCompileUnit();
                    GeneratorHost.Instance.Manager.Initialize(entry.Value as ArrayList);
                    GeneratorHost.Instance.State.Init(source, unit);
                    RunSource(source);
                    GenerateOutput(unit, source);
                }
                #endregion

                // If no customizations are defined, run the process anyway (empty structure).
                if (indexes.Count == 0)
                {
                    unit = new CodeCompileUnit();
                    GeneratorHost.Instance.Manager.Initialize(new ArrayList());
                    GeneratorHost.Instance.State.Init(source, unit);
                    RunSource(source);
                    GenerateOutput(unit, source);
                }

                OnProgress("Finished!");
            }
        }
Beispiel #4
0
        /// <summary>
        /// Compiles the generated code in the output assembly.
        /// </summary>
        /// <param name="unit">The code graph to compile.</param>
        /// <param name="source">The current source in use.</param>
        private void GenerateOutput(CodeCompileUnit unit, RunnerSource source)
        {
            if (GeneratorHost.Instance.GeneratorOptions.OutputSource)
            {
                OnProgress("Generating source code output ... ");
                ICodeGenerator gen =
                    GeneratorHost.Instance.GeneratorOptions.Provider.CreateGenerator();
                CodeGeneratorOptions opt = new CodeGeneratorOptions();
                opt.BracingStyle = "C";

                string ns   = GeneratorHost.Instance.GeneratorOptions.TargetNamespace;
                string path = "";

                // If a namespace isn't defined and the source file is an XmlSchema,
                // we use the targetnamespace of the schema as the namespace for the classes.
                if (ns == String.Empty)
                {
                    XmlSchema sch = null;
                    try
                    {
                        using (FileStream fs = new FileStream(source.FileName, FileMode.Open))
                            sch = XmlSchema.Read(fs, null);
                    }
                    catch { }

                    if (sch != null)
                    {
                        ns = sch.TargetNamespace;
                    }
                }

                // Review folder organization.
                if (GeneratorHost.Instance.GeneratorOptions.CreateNamespaceFolders)
                {
                    // Replace target namespace dots with slashes
                    path = GeneratorHost.Instance.GeneratorOptions.TargetFolder +
                           Path.DirectorySeparatorChar + ns.Replace('.',
                                                                    Path.DirectorySeparatorChar);
                }
                else if (GeneratorHost.Instance.GeneratorOptions.TargetFolder != String.Empty)
                {
                    path = GeneratorHost.Instance.GeneratorOptions.TargetFolder;
                }
                else
                {
                    path = Path.GetDirectoryName(source.FileName);
                }

                if (!Directory.Exists(path))
                {
                    Directory.CreateDirectory(path);
                }

                path += Path.DirectorySeparatorChar + Path.GetFileNameWithoutExtension(source.FileName);

                if (GeneratorHost.Instance.GeneratorOptions.Provider is Microsoft.CSharp.CSharpCodeProvider)
                {
                    path += ".cs";
                }
                else if (GeneratorHost.Instance.GeneratorOptions.Provider is Microsoft.VisualBasic.VBCodeProvider)
                {
                    path += ".vb";
                }
                else
                {
                    // Dummy extension for other unknown languages.
                    path += ".code";
                }

                // Write source code to the output file.
                using (FileStream fs = new FileStream(path, FileMode.Create))
                {
                    OnProgress("Writing " + path + " source file ... ");
                    StreamWriter w = new StreamWriter(fs);
                    gen.GenerateCodeFromCompileUnit(unit, w, opt);
                    w.Flush();
                }

                OnFileFinished(path);
            }

            if (GeneratorHost.Instance.GeneratorOptions.OutputCompiled)
            {
                OnProgress("Generating compiled output ... ");
                ICodeCompiler      comp  = GeneratorHost.Instance.GeneratorOptions.Provider.CreateCompiler();
                CompilerParameters param = new CompilerParameters();
                param.TreatWarningsAsErrors = false;

                param.OutputAssembly =
                    GeneratorHost.Instance.GeneratorOptions.TargetFolder +
                    Path.DirectorySeparatorChar +
                    GeneratorHost.Instance.GeneratorOptions.TargetAssembly;

                // Add referenced assemblies.
                string[] assemblies = new string[GeneratorHost.Instance.GeneratorOptions.AssemblyReferences.Count];
                GeneratorHost.Instance.GeneratorOptions.AssemblyReferences.CopyTo(assemblies);
                param.ReferencedAssemblies.AddRange(assemblies);

                CompilerResults results = comp.CompileAssemblyFromDom(param, unit);

                StringWriter w = new StringWriter();
                foreach (string msg in results.Output)
                {
                    Console.WriteLine(msg);
                }

                if (results.Errors.Count != 0)
                {
                    foreach (CompilerError error in results.Errors)
                    {
                        w.WriteLine(error);
                    }
                    throw new InvalidOperationException(w.ToString());
                }
            }
        }