Example #1
0
        /// <summary>
        /// Generate code based on inputs and print to output files.
        /// </summary>
        /// <param name="inputDefs">Paths for source files.</param>
        /// <param name="outputPath">Location to store output files.</param>
        /// <param name="outputFileBasename">The basename used for all the output files.</param>
        public static void GenerateCode(string[] inputDefs, string outputPath, string outputFileBasename)
        {
            CodeGenCSharpCompiler compiler       = new CodeGenCSharpCompiler();
            CompilerOutput        compilerOutput = compiler.CompileFromFiles(inputDefs, outputPath);

            CodeCommentsReader codeComments        = compilerOutput.CodeComments;
            Compilation        compilation         = compilerOutput.Compilation;
            Assembly           sourceTypesAssembly = compilerOutput.Assembly;

            // Store C# compiler, used later to compute codegen type hash.
            //
            TypeMetadataMapper.Compilation = compilerOutput.Compilation;

            MultiCodeWriter codeWriter = GetMainCodeWriter(sourceTypesAssembly);

            var codeGenErrors = new List <CodegenError>();

            bool result = GenerateTypes(codeWriter, compilation, codeComments, codeGenErrors, sourceTypesAssembly);

            if (!result || codeGenErrors.Any())
            {
                PrintCodeGenErrorsAndExit(codeGenErrors);
            }

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

            WriteOutputToFile(codeWriter, outputFileBasename, outputPath);
        }
Example #2
0
 /// <summary>
 /// Initializes a new instance of the <see cref="CompilerOutput"/> struct.
 /// </summary>
 /// <param name="assembly"></param>
 /// <param name="emitResult"></param>
 /// <param name="codeComments"></param>
 /// <param name="compilation"></param>
 public CompilerOutput(Assembly assembly, EmitResult emitResult, CodeCommentsReader codeComments, CSharpCompilation compilation)
 {
     Assembly     = assembly;
     EmitResult   = emitResult;
     CodeComments = codeComments;
     Compilation  = compilation;
 }
Example #3
0
        private static bool GenerateTypes(CodeWriter codeWriter, Compilation compilation, CodeCommentsReader codeComments, List <CodegenError> codeGenErrors, Assembly sourceTypesAssembly)
        {
            bool result = true;

            codeWriter.WriteBeginFile();

            var typeCodeGenerator = new TypeCodeGenerator
            {
                CodeWriter         = codeWriter,
                SourceCompilation  = compilation,
                SourceCodeComments = codeComments,
                CodeGenErrors      = codeGenErrors,
            };

            // CodeGen all the Mlos types.
            //
            foreach (Type sourceType in sourceTypesAssembly.GetTypes().Where(type => type.IsCodegenType()))
            {
                result &= typeCodeGenerator.GenerateType(sourceType);
            }

            codeWriter.WriteEndFile();

            return(result);
        }
Example #4
0
        /// <summary>
        /// Compiles multiple CSharp files into assembly.
        /// </summary>
        /// <param name="inputFiles"></param>
        /// <param name="outputPath"></param>
        /// <remarks>
        /// The method also returns a documentation created from the source code.
        /// </remarks>
        /// <returns></returns>
        internal CompilerOutput CompileFromFiles(string[] inputFiles, string outputPath)
        {
            string resultAssemblyDocFullPath = Path.Combine(outputPath, "SettingsRegistry.xml");

            Directory.CreateDirectory(Path.GetDirectoryName(resultAssemblyDocFullPath));
            string assemblyName = Path.GetFileNameWithoutExtension(outputPath);

            var syntaxTrees = inputFiles.Select(inputFile =>
            {
                string sourceContent = File.ReadAllText(inputFile);
                return(CSharpSyntaxTree.ParseText(text: sourceContent, path: inputFile, encoding: System.Text.Encoding.ASCII));
            });

            var refPaths = new[]
            {
                typeof(object).GetTypeInfo().Assembly.Location,
                Assembly.GetAssembly(typeof(Attributes.BaseCodegenAttribute)).Location,
                Assembly.GetExecutingAssembly().Location,
                Path.Combine(Path.GetDirectoryName(typeof(System.Runtime.GCSettings).GetTypeInfo().Assembly.Location), "System.Runtime.dll"),
            };

            MetadataReference[] references = refPaths.Select(r => MetadataReference.CreateFromFile(r)).ToArray();

            // Compile as dynamic library and disable all warnings.
            //
            var compilationOptions = new CSharpCompilationOptions(
                OutputKind.DynamicallyLinkedLibrary,
                warningLevel: 0,
                optimizationLevel: OptimizationLevel.Debug,
                allowUnsafe: true);

            CSharpCompilation compilation = CSharpCompilation.Create(
                assemblyName: assemblyName,
                syntaxTrees: syntaxTrees,
                references: references,
                options: compilationOptions);

            Assembly outputAssembly;

            using (var peStream = new MemoryStream())
                using (var pdbStream = new MemoryStream())
                    using (var xmlDocStream = new MemoryStream())
                    {
                        var emitOptions = new EmitOptions(
                            debugInformationFormat: DebugInformationFormat.PortablePdb,
                            includePrivateMembers: true);

                        EmitResult emitResults = compilation.Emit(
                            peStream: peStream,
                            pdbStream: pdbStream,
                            xmlDocumentationStream: xmlDocStream,
                            options: emitOptions);

                        // Rewind streams.
                        //
                        peStream.Seek(0, SeekOrigin.Begin);
                        pdbStream.Seek(0, SeekOrigin.Begin);
                        xmlDocStream.Seek(0, SeekOrigin.Begin);

                        if (!emitResults.Success)
                        {
                            emitResults.Diagnostics.ToList().ForEach(
                                error =>
                            {
                                Console.Error.WriteLine($"Location:{error.Location}");
                                Console.Error.WriteLine($"  Error: {error}");
                            });

                            Environment.Exit(1);
                        }

                        outputAssembly = AssemblyLoadContext.Default.LoadFromStream(peStream, pdbStream);

                        var codeComments = new CodeCommentsReader();
                        codeComments.LoadFromAssembly(xmlDocStream);

                        return(new CompilerOutput(outputAssembly, emitResults, codeComments, compilation));
                    }
        }