Exemplo n.º 1
0
        /// <summary>
        /// 将语法树生成到程序集
        /// </summary>
        /// <param name="trees"></param>
        /// <returns></returns>
        public virtual Assembly ComplieToAssembly(IEnumerable <SyntaxTree> trees)
        {
#if DEBUG
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
#endif
            Assembly   assembly      = null;
            EmitResult compileResult = null;
            if (PreCompiler())
            {
                if (trees == default)
                {
                    return(null);
                }

                //Mark : 26ms
                var options = GetCompilationOptions();
                OptionAction?.Invoke(options);
                Compilation = GetCompilation(options);
#if DEBUG
                Console.WriteLine();
                stopwatch.StopAndShowCategoreInfo("[Compilation]", "获取编译单元", 2);
                stopwatch.Restart();
#endif
                //Mark : 951ms
                //Mark : 19M Memory
                Compilation = (TCompilation)Compilation.AddSyntaxTrees(trees);
                foreach (var item in _semanticAnalysistor)
                {
                    Compilation = item(Compilation);
                }
#if DEBUG
                stopwatch.StopAndShowCategoreInfo("[Semantic]", "语义解析排查", 2);
                stopwatch.Restart();
#endif
                //Mark : 264ms
                //Mark : 3M Memory
                Stream outputStream = new MemoryStream();
                if (AssemblyOutputKind == AssemblyBuildKind.File)
                {
                    outputStream = File.Create(OutputFilePath);
                    using (var pdbStream = File.Create(OutputPdbPath))
                    {
                        compileResult = Compilation.Emit(
                            outputStream,
                            pdbStream: pdbStream,
                            options: new EmitOptions(pdbFilePath: OutputPdbPath, debugInformationFormat: DebugInformationFormat.PortablePdb));
                    }
                }
                else
                {
                    compileResult = Compilation.Emit(
                        outputStream,
                        options: new EmitOptions(false, debugInformationFormat: DebugInformationFormat.PortablePdb));
                }

                if (compileResult.Success)
                {
                    outputStream.Seek(0, SeekOrigin.Begin);

                    if (CompileSucceedEvent != default)
                    {
                        MemoryStream copyStream = new MemoryStream();
                        outputStream.CopyTo(copyStream);
                        outputStream.Seek(0, SeekOrigin.Begin);
                        assembly = Domain.CompileStreamCallback(OutputFilePath, OutputPdbPath, outputStream, AssemblyName);
                        CompileSucceedEvent(OutputFilePath, OutputPdbPath, copyStream, Compilation);
                        copyStream.Dispose();
                    }
                    else
                    {
                        assembly = Domain.CompileStreamCallback(OutputFilePath, OutputPdbPath, outputStream, AssemblyName);
                    }
                }
                else
                {
                    assembly = CompileFailedEvent?.Invoke(outputStream, compileResult.Diagnostics, Compilation);
                }
                outputStream.Dispose();
#if DEBUG
                stopwatch.StopAndShowCategoreInfo("[  Emit  ]", "编译时长", 2);
#endif
            }
            return(assembly);
        }
Exemplo n.º 2
0
        /// <summary>
        /// 将语法树生成到程序集
        /// </summary>
        /// <param name="trees"></param>
        /// <returns></returns>
        public virtual Assembly ComplieToAssembly(IEnumerable <SyntaxTree> trees)
        {
            Assembly   assembly      = null;
            EmitResult compileResult = null;

            if (PreCompiler())
            {
                if (trees == default)
                {
                    return(null);
                }

                var options = GetCompilationOptions();
                OptionAction?.Invoke(options);
                Compilation = GetCompilation(options);
                Compilation = (TCompilation)Compilation.AddSyntaxTrees(trees);
                foreach (var item in _semanticAnalysistor)
                {
                    Compilation = item(Compilation);
                }


                Stream outputStream = new MemoryStream();
                if (AssemblyOutputKind == AssemblyBuildKind.File)
                {
                    outputStream = File.Create(OutputFilePath);
                    using (var pdbStream = File.Create(OutputPdbPath))
                    {
                        compileResult = Compilation.Emit(
                            outputStream,
                            pdbStream: pdbStream,
                            options: new EmitOptions(pdbFilePath: OutputPdbPath, debugInformationFormat: DebugInformationFormat.PortablePdb));
                    }
                }
                else
                {
                    compileResult = Compilation.Emit(
                        outputStream,
                        options: new EmitOptions(false, debugInformationFormat: DebugInformationFormat.PortablePdb));
                }

                if (compileResult.Success)
                {
                    outputStream.Seek(0, SeekOrigin.Begin);

                    if (CompileSucceedEvent != default)
                    {
                        MemoryStream copyStream = new MemoryStream();
                        outputStream.CopyTo(copyStream);
                        outputStream.Seek(0, SeekOrigin.Begin);
                        assembly = Domain.CompileStreamCallback(OutputFilePath, OutputPdbPath, outputStream, AssemblyName);
                        CompileSucceedEvent(OutputFilePath, OutputPdbPath, copyStream, Compilation);
                        copyStream.Dispose();
                    }
                    else
                    {
                        assembly = Domain.CompileStreamCallback(OutputFilePath, OutputPdbPath, outputStream, AssemblyName);
                    }
                }
                else
                {
                    assembly = CompileFailedEvent?.Invoke(outputStream, compileResult.Diagnostics, Compilation);
                }
                outputStream.Dispose();
            }
            return(assembly);
        }
Exemplo n.º 3
0
    /// <summary>
    /// 将 SyntaxTrees 中的语法树编译到程序集.如果不成功会抛出 NatashaException.
    /// </summary>
    /// <remarks>
    /// <example>
    /// <code>
    ///
    ///     //程序集的域加载行为, 该行为决定了编译后的程序集随着依赖加载到域中的处理结果.
    ///     //和加载插件原理相同.
    ///     builder.CompileWithAssemblyLoadBehavior(enum);
    ///
    ///     //编译单元的引用加载行为, 遇到同名不同版本的引用该如何处理.
    ///     builder.CompileWithReferenceLoadBehavior(enum);
    ///     builder.CompileWithReferencesFilter(func);
    ///
    /// </code>
    /// </example>
    /// </remarks>
    public Assembly GetAssembly()
    {
#if DEBUG
        Stopwatch stopwatch = new();
        stopwatch.Start();
#endif

        //Mark : 26ms
        if (_compileReferenceBehavior == LoadBehaviorEnum.None)
        {
            _compilerOptions.SetSupersedeLowerVersions(true);
        }

        var options     = _compilerOptions.GetCompilationOptions();
        var references  = Domain.GetReferences(_compileReferenceBehavior, _referencePickFunc);
        var compilation = CSharpCompilation.Create(AssemblyName, SyntaxTrees, references, options);

#if DEBUG
        stopwatch.RestartAndShowCategoreInfo("[Compiler]", "获取编译单元", 2);
#endif


        if (EnableSemanticHandler)
        {
            foreach (var item in _semanticAnalysistor)
            {
                compilation = item(this, compilation);
            }
            lock (SyntaxTrees)
            {
                SyntaxTrees.Clear();
                SyntaxTrees.AddRange(compilation.SyntaxTrees);
            }
        }

#if DEBUG
        stopwatch.RestartAndShowCategoreInfo("[Semantic]", "语义处理", 2);
#endif

        Stream dllStream;
        Stream pdbStream;
        Stream?xmlStream = null;
        if (DllFilePath != string.Empty)
        {
            dllStream = File.Create(DllFilePath);
        }
        else
        {
            dllStream = new MemoryStream();
        }

        if (PdbFilePath != string.Empty)
        {
            pdbStream = File.Create(PdbFilePath);
        }
        else
        {
            pdbStream = new MemoryStream();
        }

        if (XmlFilePath != string.Empty)
        {
            xmlStream = File.Create(XmlFilePath);
        }

        var compileResult = compilation.Emit(
            dllStream,
            pdbStream: pdbStream,
            xmlDocumentationStream: xmlStream,
            options: new EmitOptions(pdbFilePath: PdbFilePath == string.Empty ? null : PdbFilePath, debugInformationFormat: DebugInformationFormat.PortablePdb));


        LogCompilationEvent?.Invoke(compilation.GetNatashaLog());

        Assembly?assembly = null;
        if (compileResult.Success)
        {
            dllStream.Seek(0, SeekOrigin.Begin);
            pdbStream?.Seek(0, SeekOrigin.Begin);
            Domain.SetAssemblyLoadBehavior(_compileAssemblyBehavior);
            assembly = Domain.LoadAssemblyFromStream(dllStream, pdbStream);
            CompileSucceedEvent?.Invoke(compilation, assembly !);
        }
        dllStream.Dispose();
        pdbStream?.Dispose();
        xmlStream?.Dispose();

#if DEBUG
        stopwatch.StopAndShowCategoreInfo("[  Emit  ]", "编译时长", 2);
#endif

        if (!compileResult.Success)
        {
            CompileFailedEvent?.Invoke(compilation, compileResult.Diagnostics);
            throw NatashaExceptionAnalyzer.GetCompileException(compilation, compileResult.Diagnostics);
        }

        return(assembly !);
    }