public static void CompileMethodBodies( CSharpCompilation compilation, PEModuleBuilder moduleBeingBuilt, bool generateDebugInfo, bool hasDeclarationErrors, Predicate <Symbol> filter, SyntaxTree filterTree, TextSpan?filterSpanWithinTree, DiagnosticBag diagnostics, CancellationToken cancellationToken) { using (Logger.LogBlock(FunctionId.CSharp_Compiler_CompileMethodBodies, message: compilation.AssemblyName, cancellationToken: cancellationToken)) { Debug.Assert(filter == null || filterTree == null, "Cannot provide both a filter predicate and a filter tree."); if (filter == null && filterTree != null) { filter = s => s.IsDefinedInSourceTree(filterTree, filterSpanWithinTree); } if (compilation.PreviousSubmission != null) { // In case there is a previous submission, we should ensure // it has already created anonymous type/delegates templates // NOTE: if there are any errors, we will pick up what was created anyway compilation.PreviousSubmission.EnsureAnonymousTypeTemplates(cancellationToken); // TODO: revise to use a loop instead of a recursion } MethodBodyCompiler.CompileMethodBodies(compilation, moduleBeingBuilt, generateDebugInfo, hasDeclarationErrors, diagnostics, filter, cancellationToken); MethodSymbol entryPoint = GetEntryPoint(compilation, moduleBeingBuilt, hasDeclarationErrors, diagnostics, cancellationToken); if (moduleBeingBuilt != null) { moduleBeingBuilt.SetEntryPoint(entryPoint); } } }
public static void CompileMethodBodies( CSharpCompilation compilation, PEModuleBuilder moduleBeingBuilt, bool generateDebugInfo, bool hasDeclarationErrors, DiagnosticBag diagnostics, Predicate <Symbol> filter, CancellationToken cancellationToken) { MethodBodyCompiler methodBodyCompiler = new MethodBodyCompiler( compilation, moduleBeingBuilt, generateDebugInfo, hasDeclarationErrors, diagnostics, filter, cancellationToken); if (compilation.Options.ConcurrentBuild) { methodBodyCompiler.compilerTasks = new ConcurrentStack <Task>(); } // directly traverse global namespace (no point to defer this to async) methodBodyCompiler.CompileNamespace(compilation.SourceModule.GlobalNamespace); methodBodyCompiler.WaitForWorkers(); // compile additional and anonymous types if any if (moduleBeingBuilt != null) { var additionalTypes = moduleBeingBuilt.GetAdditionalTopLevelTypes(); if (!additionalTypes.IsEmpty) { methodBodyCompiler.CompileGeneratedMethods(additionalTypes, diagnostics); } // By this time we have processed all types reachable from module's global namespace compilation.AnonymousTypeManager.AssignTemplatesNamesAndCompile(methodBodyCompiler, moduleBeingBuilt, diagnostics); methodBodyCompiler.WaitForWorkers(); var privateImplClass = moduleBeingBuilt.PrivateImplClass; if (privateImplClass != null) { // all threads that were adding methods must be finished now, we can freeze the class: privateImplClass.Freeze(); methodBodyCompiler.CompileGeneratedMethods(privateImplClass, diagnostics); } } // If we are trying to emit and there's an error without a corresponding diagnostic (e.g. because // we depend on an invalid type or constant from another module), then explicitly add a diagnostic. // This diagnostic is not very helpful to the user, but it will prevent us from emitting an invalid // module or crashing. if (moduleBeingBuilt != null && methodBodyCompiler.GlobalHasErrors && !diagnostics.HasAnyErrors() && !hasDeclarationErrors) { diagnostics.Add(ErrorCode.ERR_ModuleEmitFailure, NoLocation.Singleton, ((Microsoft.Cci.INamedEntity)moduleBeingBuilt).Name); } diagnostics.AddRange(compilation.AdditionalCodegenWarnings); // we can get unused field warnings only if compiling whole compilation. if (filter == null) { WarnUnusedFields(compilation, diagnostics, cancellationToken); } }