/// <exception cref="BadImageFormatException">An exception from metadata reader.</exception> internal static ImmutableArray <AssemblyIdentity> GetReferencedAssembliesOrThrow(this MetadataReader reader) { ArrayBuilder <AssemblyIdentity> result = ArrayBuilder <AssemblyIdentity> .GetInstance(reader.AssemblyReferences.Count); try { foreach (AssemblyReferenceHandle assemblyRef in reader.AssemblyReferences) { AssemblyReference reference = reader.GetAssemblyReference(assemblyRef); result.Add(reader.CreateAssemblyIdentityOrThrow( reference.Version, reference.Flags, reference.PublicKeyOrToken, reference.Name, reference.Culture, isReference: true)); } return(result.ToImmutable()); } finally { result.Free(); } }
/// <summary> /// Returns an array of distinct elements, preserving the order in the original array. /// If the array has no duplicates, the original array is returned. The original array must not be null. /// </summary> public static ImmutableArray <T> Distinct <T>(this ImmutableArray <T> array, IEqualityComparer <T> comparer = null) { Debug.Assert(!array.IsDefault); if (array.Length < 2) { return(array); } HashSet <T> set = new HashSet <T>(comparer); ArrayBuilder <T> builder = ArrayBuilder <T> .GetInstance(); foreach (T a in array) { if (set.Add(a)) { builder.Add(a); } } ImmutableArray <T> result = (builder.Count == array.Length) ? array : builder.ToImmutable(); builder.Free(); return(result); }
/// <summary> /// Get the import strings for a given method, following forward pointers as necessary. /// </summary> /// <returns> /// For each namespace enclosing the method, a list of import strings, innermost to outermost. /// There should always be at least one entry, for the global namespace. /// </returns> public static ImmutableArray <ImmutableArray <string> > GetCSharpGroupedImportStrings(this ISymUnmanagedReader reader, int methodToken, int methodVersion, out ImmutableArray <string> externAliasStrings) { externAliasStrings = default(ImmutableArray <string>); ImmutableArray <short> groupSizes = default(ImmutableArray <short>); bool seenForward = false; RETRY: byte[] bytes = reader.GetCustomDebugInfoBytes(methodToken, methodVersion); if (bytes == null) { return(default(ImmutableArray <ImmutableArray <string> >)); } foreach (var record in GetCustomDebugInfoRecords(bytes)) { switch (record.Kind) { case CustomDebugInfoKind.UsingInfo: if (!groupSizes.IsDefault) { throw new InvalidOperationException(string.Format("Expected at most one Using record for method {0}", FormatMethodToken(methodToken))); } groupSizes = DecodeUsingRecord(record.Data); break; case CustomDebugInfoKind.ForwardInfo: if (!externAliasStrings.IsDefault) { throw new InvalidOperationException(string.Format("Did not expect both Forward and ForwardToModule records for method {0}", FormatMethodToken(methodToken))); } methodToken = DecodeForwardRecord(record.Data); // Follow at most one forward link (as in FUNCBRECEE::ensureNamespaces). // NOTE: Dev11 may produce chains of forward links (e.g. for System.Collections.Immutable). if (!seenForward) { seenForward = true; goto RETRY; } break; case CustomDebugInfoKind.ForwardToModuleInfo: if (!externAliasStrings.IsDefault) { throw new InvalidOperationException(string.Format("Expected at most one ForwardToModule record for method {0}", FormatMethodToken(methodToken))); } int moduleInfoMethodToken = DecodeForwardToModuleRecord(record.Data); ImmutableArray <string> allModuleInfoImportStrings = reader.GetMethodByVersion(moduleInfoMethodToken, methodVersion).GetImportStrings(); ArrayBuilder <string> externAliasBuilder = ArrayBuilder <string> .GetInstance(); foreach (string importString in allModuleInfoImportStrings) { if (IsCSharpExternAliasInfo(importString)) { externAliasBuilder.Add(importString); } } externAliasStrings = externAliasBuilder.ToImmutableAndFree(); break; } } if (groupSizes.IsDefault) { // This can happen in malformed PDBs (e.g. chains of forwards). return(default(ImmutableArray <ImmutableArray <string> >)); } var method = reader.GetMethodByVersion(methodToken, methodVersion); if (method == null) { return(default(ImmutableArray <ImmutableArray <string> >)); } ImmutableArray <string> importStrings = method.GetImportStrings(); int numImportStrings = importStrings.Length; ArrayBuilder <ImmutableArray <string> > resultBuilder = ArrayBuilder <ImmutableArray <string> > .GetInstance(groupSizes.Length); ArrayBuilder <string> groupBuilder = ArrayBuilder <string> .GetInstance(); int pos = 0; foreach (short groupSize in groupSizes) { for (int i = 0; i < groupSize; i++, pos++) { if (pos >= numImportStrings) { throw new InvalidOperationException(string.Format("Group size indicates more imports than there are import strings (method {0}).", FormatMethodToken(methodToken))); } string importString = importStrings[pos]; if (IsCSharpExternAliasInfo(importString)) { throw new InvalidOperationException(string.Format("Encountered extern alias info before all import strings were consumed (method {0}).", FormatMethodToken(methodToken))); } groupBuilder.Add(importString); } resultBuilder.Add(groupBuilder.ToImmutable()); groupBuilder.Clear(); } if (externAliasStrings.IsDefault) { Debug.Assert(groupBuilder.Count == 0); // Extern alias detail strings (prefix "Z") are not included in the group counts. for (; pos < numImportStrings; pos++) { string importString = importStrings[pos]; if (!IsCSharpExternAliasInfo(importString)) { throw new InvalidOperationException(string.Format("Expected only extern alias info strings after consuming the indicated number of imports (method {0}).", FormatMethodToken(methodToken))); } groupBuilder.Add(importString); } externAliasStrings = groupBuilder.ToImmutableAndFree(); } else { groupBuilder.Free(); if (pos < numImportStrings) { throw new InvalidOperationException(string.Format("Group size indicates fewer imports than there are import strings (method {0}).", FormatMethodToken(methodToken))); } } return(resultBuilder.ToImmutableAndFree()); }
protected void GetCompilationReferences( TCompilation compilation, DiagnosticBag diagnostics, out ImmutableArray <MetadataReference> references, out IDictionary <ValueTuple <string, string>, MetadataReference> boundReferenceDirectives, out ImmutableArray <Location> referenceDirectiveLocations) { boundReferenceDirectives = null; ArrayBuilder <MetadataReference> referencesBuilder = ArrayBuilder <MetadataReference> .GetInstance(); ArrayBuilder <Location> referenceDirectiveLocationsBuilder = null; try { foreach (var referenceDirective in compilation.ReferenceDirectives) { if (compilation.Options.MetadataReferenceResolver == null) { diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataReferencesNotSupported, referenceDirective.Location)); break; } // we already successfully bound #r with the same value: if (boundReferenceDirectives != null && boundReferenceDirectives.ContainsKey(ValueTuple.Create(referenceDirective.Location.SourceTree.FilePath, referenceDirective.File))) { continue; } MetadataReference boundReference = ResolveReferenceDirective(referenceDirective.File, referenceDirective.Location, compilation); if (boundReference == null) { diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotFound, referenceDirective.Location, referenceDirective.File)); continue; } if (boundReferenceDirectives == null) { boundReferenceDirectives = new Dictionary <ValueTuple <string, string>, MetadataReference>(); referenceDirectiveLocationsBuilder = ArrayBuilder <Location> .GetInstance(); } referencesBuilder.Add(boundReference); referenceDirectiveLocationsBuilder.Add(referenceDirective.Location); boundReferenceDirectives.Add(ValueTuple.Create(referenceDirective.Location.SourceTree.FilePath, referenceDirective.File), boundReference); } // add external reference at the end, so that they are processed first: referencesBuilder.AddRange(compilation.ExternalReferences); // Add all explicit references of the previous script compilation. var previousScriptCompilation = compilation.ScriptCompilationInfo?.PreviousScriptCompilation; if (previousScriptCompilation != null) { referencesBuilder.AddRange(previousScriptCompilation.GetBoundReferenceManager().ExplicitReferences); } if (boundReferenceDirectives == null) { // no directive references resolved successfully: boundReferenceDirectives = SpecializedCollections.EmptyDictionary <ValueTuple <string, string>, MetadataReference>(); } references = referencesBuilder.ToImmutable(); referenceDirectiveLocations = referenceDirectiveLocationsBuilder?.ToImmutableAndFree() ?? ImmutableArray <Location> .Empty; } finally { // Put this in a finally because we have tests that (intentionally) cause ResolveReferenceDirective to throw and // we don't want to clutter the test output with leak reports. referencesBuilder.Free(); } }
protected void GetCompilationReferences( TCompilation compilation, DiagnosticBag diagnostics, out ImmutableArray <MetadataReference> references, out IDictionary <string, MetadataReference> boundReferenceDirectives, out ImmutableArray <Location> referenceDirectiveLocations) { boundReferenceDirectives = null; ArrayBuilder <MetadataReference> referencesBuilder = ArrayBuilder <MetadataReference> .GetInstance(); ArrayBuilder <Location> referenceDirectiveLocationsBuilder = null; try { foreach (var referenceDirective in compilation.ReferenceDirectives) { if (compilation.Options.MetadataReferenceResolver == null || compilation.Options.MetadataReferenceProvider == null) { diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataReferencesNotSupported, referenceDirective.Location)); break; } // we already successfully bound #r with the same value: if (boundReferenceDirectives != null && boundReferenceDirectives.ContainsKey(referenceDirective.File)) { continue; } MetadataReference boundReference = ResolveReferenceDirective(referenceDirective.File, referenceDirective.Location, compilation); if (boundReference == null) { diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotFound, referenceDirective.Location, referenceDirective.File)); continue; } if (boundReferenceDirectives == null) { boundReferenceDirectives = new Dictionary <string, MetadataReference>(); referenceDirectiveLocationsBuilder = ArrayBuilder <Location> .GetInstance(); } referencesBuilder.Add(boundReference); referenceDirectiveLocationsBuilder.Add(referenceDirective.Location); boundReferenceDirectives.Add(referenceDirective.File, boundReference); } // Workaround for bug #797360: include facades if we reference a Portable Library: referencesBuilder.AddRange(ResolveFacadeReferences(compilation)); // add external reference at the end, so that they are processed first: referencesBuilder.AddRange(compilation.ExternalReferences); if (boundReferenceDirectives == null) { // no directive references resolved successfully: boundReferenceDirectives = SpecializedCollections.EmptyDictionary <string, MetadataReference>(); } references = referencesBuilder.ToImmutable(); referenceDirectiveLocations = referenceDirectiveLocationsBuilder == null ? ImmutableArray <Location> .Empty : referenceDirectiveLocationsBuilder.ToImmutableAndFree(); } finally { // Put this in a finally because we have tests that (intentionally) cause ResolveReferenceDirective to throw and // we don't want to clutter the test output with leak reports. referencesBuilder.Free(); } }
internal ImmutableArray <GeneratedSourceText> ToImmutable() => _sourcesAdded.ToImmutable();
private AssemblyMetadata CreateAssemblyMetadata(ShadowCopy manifestModuleCopy) { // We don't need to use the global metadata cache here since the shadow copy // won't change and is private to us - only users of the same shadow copy provider see it. ArrayBuilder <ModuleMetadata> moduleBuilder = null; bool fault = true; ModuleMetadata manifestModule = null; try { manifestModule = CreateModuleMetadata(manifestModuleCopy); string originalDirectory = null, shadowCopyDirectory = null; foreach (string moduleName in manifestModule.GetModuleNames()) { if (moduleBuilder == null) { moduleBuilder = ArrayBuilder <ModuleMetadata> .GetInstance(); moduleBuilder.Add(manifestModule); originalDirectory = Path.GetDirectoryName(manifestModuleCopy.OriginalPath); shadowCopyDirectory = Path.GetDirectoryName(manifestModuleCopy.FullPath); } string originalPath = Path.Combine(originalDirectory, moduleName); string shadowCopyPath = Path.Combine(shadowCopyDirectory, moduleName); var moduleCopy = CopyFile(originalPath, shadowCopyPath); moduleBuilder.Add(CreateModuleMetadata(moduleCopy)); } var modules = (moduleBuilder != null) ? moduleBuilder.ToImmutable() : ImmutableArray.Create(manifestModule); fault = false; return(new AssemblyMetadata(modules)); } finally { if (fault) { if (manifestModule != null) { manifestModule.Dispose(); } if (moduleBuilder != null) { for (int i = 1; i < moduleBuilder.Count; i++) { moduleBuilder[i].Dispose(); } } } if (moduleBuilder != null) { moduleBuilder.Free(); } } }