internal static TResult CompileWithRetry <TResult>( ImmutableArray <MetadataBlock> metadataBlocks, DiagnosticFormatter formatter, CreateContextDelegate createContext, CompileDelegate <TResult> compile, DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr, out string errorMessage) { TResult compileResult; PooledHashSet <AssemblyIdentity> assembliesLoadedInRetryLoop = null; bool tryAgain; do { errorMessage = null; var context = createContext(metadataBlocks, useReferencedModulesOnly: false); var diagnostics = DiagnosticBag.GetInstance(); compileResult = compile(context, diagnostics); tryAgain = false; if (diagnostics.HasAnyErrors()) { bool useReferencedModulesOnly; ImmutableArray <AssemblyIdentity> missingAssemblyIdentities; errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities( diagnostics, formatter, preferredUICulture: null, useReferencedModulesOnly: out useReferencedModulesOnly, missingAssemblyIdentities: out missingAssemblyIdentities); if (useReferencedModulesOnly) { Debug.Assert(missingAssemblyIdentities.IsEmpty); var otherContext = createContext(metadataBlocks, useReferencedModulesOnly: true); var otherDiagnostics = DiagnosticBag.GetInstance(); var otherResult = compile(otherContext, otherDiagnostics); if (!otherDiagnostics.HasAnyErrors()) { errorMessage = null; compileResult = otherResult; } otherDiagnostics.Free(); } else { if (!missingAssemblyIdentities.IsEmpty) { if (assembliesLoadedInRetryLoop == null) { assembliesLoadedInRetryLoop = PooledHashSet <AssemblyIdentity> .GetInstance(); } // If any identities failed to add (they were already in the list), then don't retry. if (assembliesLoadedInRetryLoop.AddAll(missingAssemblyIdentities)) { tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks); } } } } diagnostics.Free(); } while (tryAgain); assembliesLoadedInRetryLoop?.Free(); return(compileResult); }
internal static TResult CompileWithRetry <TResult>( ImmutableArray <MetadataBlock> metadataBlocks, DiagnosticFormatter formatter, CreateContextDelegate createContext, CompileDelegate <TResult> compile, DkmUtilities.GetMetadataBytesPtrFunction getMetaDataBytesPtr, out string errorMessage) { TResult compileResult; PooledHashSet <AssemblyIdentity> assembliesLoadedInRetryLoop = null; bool tryAgain; var linqLibrary = EvaluationContextBase.SystemLinqIdentity; do { errorMessage = null; var context = createContext(metadataBlocks, useReferencedModulesOnly: false); var diagnostics = DiagnosticBag.GetInstance(); compileResult = compile(context, diagnostics); tryAgain = false; if (diagnostics.HasAnyErrors()) { bool useReferencedModulesOnly; ImmutableArray <AssemblyIdentity> missingAssemblyIdentities; errorMessage = context.GetErrorMessageAndMissingAssemblyIdentities( diagnostics, formatter, preferredUICulture: null, linqLibrary: linqLibrary, useReferencedModulesOnly: out useReferencedModulesOnly, missingAssemblyIdentities: out missingAssemblyIdentities); // If there were LINQ-related errors, we'll initially add System.Linq (set above). // If that doesn't work, we'll fall back to System.Core for subsequent retries. linqLibrary = EvaluationContextBase.SystemCoreIdentity; // Can we remove the `useReferencedModulesOnly` attempt if we're only using // modules reachable from the current module? In short, can we avoid retrying? if (useReferencedModulesOnly) { Debug.Assert(missingAssemblyIdentities.IsEmpty); var otherContext = createContext(metadataBlocks, useReferencedModulesOnly: true); var otherDiagnostics = DiagnosticBag.GetInstance(); var otherResult = compile(otherContext, otherDiagnostics); if (!otherDiagnostics.HasAnyErrors()) { errorMessage = null; compileResult = otherResult; } otherDiagnostics.Free(); } else { if (!missingAssemblyIdentities.IsEmpty) { if (assembliesLoadedInRetryLoop == null) { assembliesLoadedInRetryLoop = PooledHashSet <AssemblyIdentity> .GetInstance(); } // If any identities failed to add (they were already in the list), then don't retry. if (assembliesLoadedInRetryLoop.AddAll(missingAssemblyIdentities)) { tryAgain = ShouldTryAgainWithMoreMetadataBlocks(getMetaDataBytesPtr, missingAssemblyIdentities, ref metadataBlocks); } } } } diagnostics.Free(); } while (tryAgain); assembliesLoadedInRetryLoop?.Free(); return(compileResult); }