File: FrameworkFork\Microsoft.CodeDom\Compiler\CodeCompiler.cs
Web Access
Project: src\src\dotnet-svcutil\lib\src\dotnet-svcutil-lib.csproj (dotnet-svcutil-lib)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
 
namespace Microsoft.CodeDom.Compiler
{
    using System.Text;
    using System.Diagnostics;
    using System;
    using Microsoft.Win32;
    using Microsoft.Win32.SafeHandles;
    using System.IO;
    using System.Collections;
    using System.Security;
    using System.Reflection;
    using Microsoft.CodeDom;
    using System.Globalization;
    using System.Runtime.Versioning;
 
    /// <devdoc>
    /// <para>Provides a
    /// base
    /// class for code compilers.</para>
    /// </devdoc>
 
 
    public abstract class CodeCompiler : CodeGenerator, ICodeCompiler
    {
        /// <internalonly/>
        CompilerResults ICodeCompiler.CompileAssemblyFromDom(CompilerParameters options, CodeCompileUnit e)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
 
            try
            {
                return FromDom(options, e);
            }
            finally
            {
                options.TempFiles.SafeDelete();
            }
        }
 
        /// <internalonly/>
 
 
        CompilerResults ICodeCompiler.CompileAssemblyFromFile(CompilerParameters options, string fileName)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
 
            try
            {
                return FromFile(options, fileName);
            }
            finally
            {
                options.TempFiles.SafeDelete();
            }
        }
 
        /// <internalonly/>
        CompilerResults ICodeCompiler.CompileAssemblyFromSource(CompilerParameters options, string source)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
 
            try
            {
                return FromSource(options, source);
            }
            finally
            {
                options.TempFiles.SafeDelete();
            }
        }
 
        /// <internalonly/>
        CompilerResults ICodeCompiler.CompileAssemblyFromSourceBatch(CompilerParameters options, string[] sources)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
 
            try
            {
                return FromSourceBatch(options, sources);
            }
            finally
            {
                options.TempFiles.SafeDelete();
            }
        }
 
        /// <internalonly/>
 
 
        CompilerResults ICodeCompiler.CompileAssemblyFromFileBatch(CompilerParameters options, string[] fileNames)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            if (fileNames == null)
                throw new ArgumentNullException("fileNames");
 
            try
            {
                // Try opening the files to make sure they exists.  This will throw an exception
                // if it doesn't
                foreach (string fileName in fileNames)
                {
                    using (Stream str = File.OpenRead(fileName)) { }
                }
 
                return FromFileBatch(options, fileNames);
            }
            finally
            {
                options.TempFiles.SafeDelete();
            }
        }
 
        /// <internalonly/>
        CompilerResults ICodeCompiler.CompileAssemblyFromDomBatch(CompilerParameters options, CodeCompileUnit[] ea)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
 
            try
            {
                return FromDomBatch(options, ea);
            }
            finally
            {
                options.TempFiles.SafeDelete();
            }
        }
 
        /// <devdoc>
        /// <para>
        /// Gets
        /// or sets the file extension to use for source files.
        /// </para>
        /// </devdoc>
        protected abstract string FileExtension
        {
            get;
        }
 
        /// <devdoc>
        /// <para>Gets or
        /// sets the name of the compiler executable.</para>
        /// </devdoc>
        protected abstract string CompilerName
        {
            get;
        }
 
 
 
 
        internal void Compile(CompilerParameters options, string compilerDirectory, string compilerExe, string arguments, ref string outputFile, ref int nativeReturnValue, string trueArgs)
        {
            throw new NotImplementedException();
        }
 
        /// <devdoc>
        /// <para>
        /// Compiles the specified compile unit and options, and returns the results
        /// from the compilation.
        /// </para>
        /// </devdoc>
        protected virtual CompilerResults FromDom(CompilerParameters options, CodeCompileUnit e)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
 
            CodeCompileUnit[] units = new CodeCompileUnit[1];
            units[0] = e;
            return FromDomBatch(options, units);
        }
 
        /// <devdoc>
        /// <para>
        /// Compiles the specified file using the specified options, and returns the
        /// results from the compilation.
        /// </para>
        /// </devdoc>
 
 
        protected virtual CompilerResults FromFile(CompilerParameters options, string fileName)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            if (fileName == null)
                throw new ArgumentNullException("fileName");
 
            // Try opening the file to make sure it exists.  This will throw an exception
            // if it doesn't
            using (Stream str = File.OpenRead(fileName)) { }
 
            string[] filenames = new string[1];
            filenames[0] = fileName;
            return FromFileBatch(options, filenames);
        }
 
        /// <devdoc>
        /// <para>
        /// Compiles the specified source code using the specified options, and
        /// returns the results from the compilation.
        /// </para>
        /// </devdoc>
        protected virtual CompilerResults FromSource(CompilerParameters options, string source)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
 
            string[] sources = new string[1];
            sources[0] = source;
 
            return FromSourceBatch(options, sources);
        }
 
        /// <devdoc>
        /// <para>
        /// Compiles the specified compile units and
        /// options, and returns the results from the compilation.
        /// </para>
        /// </devdoc>
 
 
        protected virtual CompilerResults FromDomBatch(CompilerParameters options, CodeCompileUnit[] ea)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            if (ea == null)
                throw new ArgumentNullException("ea");
 
            string[] filenames = new string[ea.Length];
 
            CompilerResults results = null;
 
            for (int i = 0; i < ea.Length; i++)
            {
                if (ea[i] == null)
                    continue;       // the other two batch methods just work if one element is null, so we'll match that. 
 
                ResolveReferencedAssemblies(options, ea[i]);
                filenames[i] = options.TempFiles.AddExtension(i + FileExtension);
                Stream temp = new FileStream(filenames[i], FileMode.Create, FileAccess.Write, FileShare.Read);
                try
                {
                    using (StreamWriter sw = new StreamWriter(temp, Encoding.UTF8))
                    {
                        ((ICodeGenerator)this).GenerateCodeFromCompileUnit(ea[i], sw, Options);
                        sw.Flush();
                    }
                }
                finally
                {
                    temp.Dispose();
                }
            }
 
            results = FromFileBatch(options, filenames);
            return results;
        }
 
        /// <devdoc>
        ///    <para>
        ///       Because CodeCompileUnit and CompilerParameters both have a referenced assemblies 
        ///       property, they must be reconciled. However, because you can compile multiple
        ///       compile units with one set of options, it will simply merge them.
        ///    </para>
        /// </devdoc>
        private void ResolveReferencedAssemblies(CompilerParameters options, CodeCompileUnit e)
        {
            if (e.ReferencedAssemblies.Count > 0)
            {
                foreach (string assemblyName in e.ReferencedAssemblies)
                {
                    if (!options.ReferencedAssemblies.Contains(assemblyName))
                    {
                        options.ReferencedAssemblies.Add(assemblyName);
                    }
                }
            }
        }
 
        /// <devdoc>
        /// <para>
        /// Compiles the specified files using the specified options, and returns the
        /// results from the compilation.
        /// </para>
        /// </devdoc>
        protected virtual CompilerResults FromFileBatch(CompilerParameters options, string[] fileNames)
        {
            throw new NotImplementedException();
        }
 
        /// <devdoc>
        /// <para>Processes the specified line from the specified <see cref='Microsoft.CodeDom.Compiler.CompilerResults'/> .</para>
        /// </devdoc>
        protected abstract void ProcessCompilerOutputLine(CompilerResults results, string line);
 
        /// <devdoc>
        /// <para>
        /// Gets the command arguments from the specified <see cref='Microsoft.CodeDom.Compiler.CompilerParameters'/>.
        /// </para>
        /// </devdoc>
        protected abstract string CmdArgsFromParameters(CompilerParameters options);
 
        /// <devdoc>
        /// <para>[To be supplied.]</para>
        /// </devdoc>
 
 
        protected virtual string GetResponseFileCmdArgs(CompilerParameters options, string cmdArgs)
        {
            string responseFileName = options.TempFiles.AddExtension("cmdline");
 
            Stream temp = new FileStream(responseFileName, FileMode.Create, FileAccess.Write, FileShare.Read);
            try
            {
                using (StreamWriter sw = new StreamWriter(temp, Encoding.UTF8))
                {
                    sw.Write(cmdArgs);
                    sw.Flush();
                }
            }
            finally
            {
                temp.Dispose();
            }
 
            return "@\"" + responseFileName + "\"";
        }
 
        /// <devdoc>
        /// <para>
        /// Compiles the specified source code strings using the specified options, and
        /// returns the results from the compilation.
        /// </para>
        /// </devdoc>
 
 
        protected virtual CompilerResults FromSourceBatch(CompilerParameters options, string[] sources)
        {
            if (options == null)
            {
                throw new ArgumentNullException("options");
            }
            if (sources == null)
                throw new ArgumentNullException("sources");
 
            string[] filenames = new string[sources.Length];
 
            CompilerResults results = null;
            for (int i = 0; i < sources.Length; i++)
            {
                string name = options.TempFiles.AddExtension(i + FileExtension);
                Stream temp = new FileStream(name, FileMode.Create, FileAccess.Write, FileShare.Read);
                try
                {
                    using (StreamWriter sw = new StreamWriter(temp, Encoding.UTF8))
                    {
                        sw.Write(sources[i]);
                        sw.Flush();
                    }
                }
                finally
                {
                    temp.Dispose();
                }
                filenames[i] = name;
            }
            results = FromFileBatch(options, filenames);
 
            return results;
        }
 
        /// <devdoc>
        /// <para>Joins the specified string arrays.</para>
        /// </devdoc>
        protected static string JoinStringArray(string[] sa, string separator)
        {
            if (sa == null || sa.Length == 0)
                return String.Empty;
 
            if (sa.Length == 1)
            {
                return "\"" + sa[0] + "\"";
            }
 
            StringBuilder sb = new StringBuilder();
            for (int i = 0; i < sa.Length - 1; i++)
            {
                sb.Append("\"");
                sb.Append(sa[i]);
                sb.Append("\"");
                sb.Append(separator);
            }
            sb.Append("\"");
            sb.Append(sa[sa.Length - 1]);
            sb.Append("\"");
 
            return sb.ToString();
        }
    }
}