/// <summary> /// this gives you SymbolTreeInfo for a metadata /// </summary> public static async Task <SymbolTreeInfo> TryGetInfoForAssemblyAsync(Solution solution, IAssemblySymbol assembly, PortableExecutableReference reference, CancellationToken cancellationToken) { var metadata = assembly.GetMetadata(); if (metadata == null) { return(null); } // Find the lock associated with this piece of metadata. This way only one thread is // computing a symbol tree info for a particular piece of metadata at a time. var gate = s_metadataIdToGate.GetValue(metadata.Id, s_metadataIdToGateCallback); using (await gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { cancellationToken.ThrowIfCancellationRequested(); SymbolTreeInfo info; if (s_metadataIdToInfo.TryGetValue(metadata.Id, out info)) { return(info); } info = await LoadOrCreateAsync(solution, assembly, reference.FilePath, cancellationToken).ConfigureAwait(false); return(s_metadataIdToInfo.GetValue(metadata.Id, _ => info)); } }
/// <summary> /// this gives you SymbolTreeInfo for a metadata /// </summary> public static async Task <SymbolTreeInfo> TryGetInfoForMetadataAssemblyAsync( Solution solution, IAssemblySymbol assembly, PortableExecutableReference reference, bool loadOnly, CancellationToken cancellationToken) { var metadata = assembly.GetMetadata(); if (metadata == null) { return(null); } // Find the lock associated with this piece of metadata. This way only one thread is // computing a symbol tree info for a particular piece of metadata at a time. var gate = s_metadataIdToGate.GetValue(metadata.Id, s_metadataIdToGateCallback); using (await gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { cancellationToken.ThrowIfCancellationRequested(); SymbolTreeInfo info; if (s_metadataIdToInfo.TryGetValue(metadata.Id, out info)) { return(info); } // We don't include internals from metadata assemblies. It's less likely that // a project would have IVT to it and so it helps us save on memory. It also // means we can avoid loading lots and lots of obfuscated code in the case hte // dll was obfuscated. info = await LoadOrCreateSymbolTreeInfoAsync(solution, assembly, reference.FilePath, loadOnly, includeInternal : false, cancellationToken : cancellationToken).ConfigureAwait(false); if (info == null && loadOnly) { return(null); } return(s_metadataIdToInfo.GetValue(metadata.Id, _ => info)); } }
/// <summary> /// this gives you SymbolTreeInfo for a metadata /// </summary> public static async Task<SymbolTreeInfo> TryGetInfoForMetadataAssemblyAsync( Solution solution, IAssemblySymbol assembly, PortableExecutableReference reference, bool loadOnly, CancellationToken cancellationToken) { var metadata = assembly.GetMetadata(); if (metadata == null) { return null; } // Find the lock associated with this piece of metadata. This way only one thread is // computing a symbol tree info for a particular piece of metadata at a time. var gate = s_metadataIdToGate.GetValue(metadata.Id, s_metadataIdToGateCallback); using (await gate.DisposableWaitAsync(cancellationToken).ConfigureAwait(false)) { cancellationToken.ThrowIfCancellationRequested(); SymbolTreeInfo info; if (s_metadataIdToInfo.TryGetValue(metadata.Id, out info)) { return info; } info = await LoadOrCreateAsync(solution, assembly, reference.FilePath, loadOnly, cancellationToken).ConfigureAwait(false); if (info == null && loadOnly) { return null; } return s_metadataIdToInfo.GetValue(metadata.Id, _ => info); } }