Ejemplo n.º 1
0
 /// <summary>
 /// 拿到异常之后进行后处理,如果处理后可以重编译,将再次编译
 /// </summary>
 /// <param name="errors"></param>
 /// <returns></returns>
 private bool CanRetryCompile(ImmutableArray <Diagnostic> errors)
 {
     if (CanRetry)
     {
         _retryCount += 1;
         if (_retryCount < RetryLimit)
         {
             return(true);
         }
     }
     Exceptions = NatashaExceptionAnalyzer.GetCompileException(Compiler.AssemblyName, errors);
     return(false);
 }
Ejemplo n.º 2
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 !);
    }