public IEnumerable <ResolvedReference> GetReferencesForPackage(ITaskItem reference, string specific_version)
    {
        string package_name = reference.ItemSpec;

        log.LogMessage("Version \"{1}\" of package \"{0}\" was requested", package_name, specific_version);
        IEnumerable <LibraryPackageInfo> packages = PcCache.GetPackages();

        foreach (LibraryPackageInfo info in packages)
        {
            if (info.Assemblies != null && info.Assemblies.Count > 0 && info.Name.StartsWith(package_name))
            {
                if (!string.IsNullOrEmpty(specific_version))
                {
                    if (string.Compare(info.Version, specific_version) != 0)
                    {
                        continue;                         // try another package
                    }
                }
                foreach (PackageAssemblyInfo asm in info.Assemblies)
                {
                    AssemblyName      aname = new AssemblyName(asm.FullName);
                    ResolvedReference rr    = GetResolvedReference(reference, asm.File, aname, false, SearchPath.PkgConfig);
                    yield return(rr);
                }
                break;                 // break cycle on packages
            }
        }
    }
Example #2
0
        public static IEnumerable <MetadataReference> GetMetadataReference(this ResolvedReference reference, bool throwOnError = true)
        {
            var references = new List <MetadataReference>();
            AssemblyMetadata assemblyMetadata;

            try
            {
                using (var stream = File.OpenRead(reference.ResolvedPath))
                {
                    var moduleMetadata = ModuleMetadata.CreateFromStream(stream, PEStreamOptions.PrefetchMetadata);
                    assemblyMetadata = AssemblyMetadata.Create(moduleMetadata);
                    references.Add(assemblyMetadata.GetReference());
                }
            }
            catch (Exception ex)
                when(ex is NotSupportedException ||
                     ex is ArgumentException ||
                     ex is BadImageFormatException ||
                     ex is IOException)
                {
                    // TODO: Log this
                    if (throwOnError)
                    {
                        throw ex;
                    }
                }
            return(references);
        }
Example #3
0
        /// <remarks>
        /// Caller is responsible for freeing any allocated ArrayBuilders.
        /// </remarks>
        private static void AddModule(PEModule module, int referenceIndex, ResolvedReference[] referenceMap, ref ArrayBuilder <PEModule> modules)
        {
            if (modules == null)
            {
                modules = ArrayBuilder <PEModule> .GetInstance();
            }

            referenceMap[referenceIndex] = new ResolvedReference(modules.Count, MetadataImageKind.Module);
            modules.Add(module);
        }
Example #4
0
        /// <remarks>
        /// Caller is responsible for freeing any allocated ArrayBuilders.
        /// </remarks>
        private static void AddAssembly(AssemblyData data, int referenceIndex, ResolvedReference[] referenceMap, ref ArrayBuilder <AssemblyData> assemblies)
        {
            if (assemblies == null)
            {
                assemblies = ArrayBuilder <AssemblyData> .GetInstance();
            }

            referenceMap[referenceIndex] = new ResolvedReference(assemblies.Count, MetadataImageKind.Assembly, default(ImmutableArray <string>));
            assemblies.Add(data);
        }
Example #5
0
        private IEnumerable <string> GetOnConditions(ResolvedReference joinReference)
        {
            return(joinReference.ReferencingMembers.Select(referenceMember =>
            {
                string refName = referenceMember.Target.Name;
                string refColumn = referenceMember.ThroughMember.Name;

                return $"[{refName}].[{refColumn}] = [{joinReference.Name}].[{refColumn}]";
            }));
        }
Example #6
0
        /// <remarks>
        /// Caller is responsible for freeing any allocated ArrayBuilders.
        /// </remarks>
        private static void AddAssembly(AssemblyData data, int referenceIndex, ResolvedReference[] referenceMap, ref ArrayBuilder <AssemblyData> assemblies)
        {
            if (assemblies == null)
            {
                assemblies = ArrayBuilder <AssemblyData> .GetInstance();
            }

            // aliases will be filled in later:
            referenceMap[referenceIndex] = new ResolvedReference(assemblies.Count, MetadataImageKind.Assembly);
            assemblies.Add(data);
        }
Example #7
0
        private IEnumerable <ResolvedReference> GetCompilationAssemblies(ITaskItem[] resolvedReferences)
        {
            var compilationAssemblies = new List <ResolvedReference>();

            foreach (var item in resolvedReferences)
            {
                var resolvedPath = item.ItemSpec;
                var name         = Path.GetFileName(resolvedPath);
                var reference    = new ResolvedReference(name, resolvedPath);
                compilationAssemblies.Add(reference);
            }

            return(compilationAssemblies);
        }
    public ResolvedReference ResolvePkgConfigReference(ITaskItem reference, bool specific_version = true)
    {
        var packages = PcCache.GetPackages();
        int count    = packages.Count();

        log.LogMessage("packages count = {0}", count.ToString());

        PackageAssemblyInfo pkg = null;

        pkg = PcCache.GetAssemblyLocation(reference.ItemSpec);
        log.LogMessage("PcCache.GetAssemblyLocation(\"{0}\") returned \"{1}\"", reference.ItemSpec, pkg);
        if (pkg == null)
        {
            log.LogMessage("It's null !!!");
        }
        if (pkg == null && !specific_version)
        {
            // if not specific version, then just match simple name
            string name = reference.ItemSpec;
            if (name.IndexOf(',') > 0)
            {
                name = name.Substring(0, name.IndexOf(','));
            }
            pkg = PcCache.ResolveAssemblyName(name).FirstOrDefault();
        }

        if (pkg == null)
        {
            log.LogMessage("Considered {0}, but could not find in any pkg-config files.",
                           reference.ItemSpec);
            return(null);
        }

        AssemblyName aname;

        if (!TryGetAssemblyNameFromFullName(pkg.FullName, out aname))
        {
            return(null);
        }

        ResolvedReference rr = GetResolvedReference(reference, pkg.File, aname, false, SearchPath.PkgConfig);

        rr.FoundInSearchPathAsString = String.Format("{{PkgConfig}} provided by package named {0}",
                                                     pkg.ParentPackage.Name);

        return(rr);
    }
Example #9
0
        private static List <Reference> ResolveReferences(Queue <AtomModel> sortedReferences, HashSet <AtomModel> projectedAtoms)
        {
            // Pick the first ref to be the atomModel
            var primaryRef = new SimpleReference(sortedReferences.Dequeue());

            var references = new List <Reference>
            {
                primaryRef
            };
            var referenceMap = new Dictionary <string, Reference>
            {
                { primaryRef.Name, primaryRef }
            };

            var atomDependencyMap = projectedAtoms.ToDictionary(atom => atom.Name, atom => atom.GetDependencies());

            foreach (var atomRelation in sortedReferences)
            {
                var posibleReferences = atomDependencyMap[atomRelation.Name];

                if (!posibleReferences.Any())
                {
                    var r = new SimpleReference(atomRelation);
                    references.Add(r);
                    referenceMap.Add(r.Name, r);
                }
                else
                {
                    var referenceName = posibleReferences.First(referenceMap.ContainsKey);
                    var reference     = referenceMap[referenceName];

                    var resolvedDependencies = posibleReferences.Where(referenceMap.ContainsKey)
                                               .Select(p => referenceMap[p]);

                    var r = new ResolvedReference(atomRelation, resolvedDependencies);
                    references.Add(r);
                    referenceMap.Add(r.Name, r);
                }
            }
            return(references);
        }
    // Look for %(Identity).{dll|exe|..}
    // if specific_version==true
    //  resolve if assembly names match
    // else
    //  resolve the valid assembly
    public ResolvedReference FindInDirectory(ITaskItem reference, string directory, string [] file_extensions, bool specific_version)
    {
        string filename  = reference.ItemSpec;
        int    comma_pos = filename.IndexOf(',');

        if (comma_pos >= 0)
        {
            filename = filename.Substring(0, comma_pos);
        }

        // Try as a filename
        string       path  = Path.GetFullPath(Path.Combine(directory, filename));
        AssemblyName aname = null;

        if (specific_version && !TryGetAssemblyNameFromFullName(reference.ItemSpec, out aname))
        {
            return(null);
        }

        ResolvedReference resolved_ref = ResolveReferenceForPath(path, reference, aname, null, SearchPath.Directory, specific_version);

        if (resolved_ref != null)
        {
            return(resolved_ref);
        }

        // try path + Include + {.dll|.exe|..}
        foreach (string extn in file_extensions)
        {
            resolved_ref = ResolveReferenceForPath(path + extn, reference, aname, null, SearchPath.Directory, specific_version);
            if (resolved_ref != null)
            {
                return(resolved_ref);
            }
        }

        return(null);
    }
Example #11
0
        /// <summary>
        /// Resolves given metadata references to assemblies and modules.
        /// </summary>
        /// <param name="compilation">The compilation whose references are being resolved.</param>
        /// <param name="assemblyReferencesBySimpleName">
        /// Used to filter out assemblies that have the same strong or weak identity.
        /// Maps simple name to a list of identities. The highest version of each name is the first.
        /// </param>
        /// <param name="references">List where to store resolved references. References from #r directives will follow references passed to the compilation constructor.</param>
        /// <param name="boundReferenceDirectiveMap">Maps #r values to successfully resolved metadata references. Does not contain values that failed to resolve.</param>
        /// <param name="boundReferenceDirectives">Unique metadata references resolved from #r directives.</param>
        /// <param name="assemblies">List where to store information about resolved assemblies to.</param>
        /// <param name="modules">List where to store information about resolved modules to.</param>
        /// <param name="diagnostics">Diagnostic bag where to report resolution errors.</param>
        /// <returns>
        /// Maps index to <paramref name="references"/> to an index of a resolved assembly or module in <paramref name="assemblies"/> or <paramref name="modules"/>, respectively.
        ///</returns>
        protected ImmutableArray <ResolvedReference> ResolveMetadataReferences(
            TCompilation compilation,
            [Out] Dictionary <string, List <ReferencedAssemblyIdentity> > assemblyReferencesBySimpleName,
            out ImmutableArray <MetadataReference> references,
            out IDictionary <ValueTuple <string, string>, MetadataReference> boundReferenceDirectiveMap,
            out ImmutableArray <MetadataReference> boundReferenceDirectives,
            out ImmutableArray <AssemblyData> assemblies,
            out ImmutableArray <PEModule> modules,
            DiagnosticBag diagnostics)
        {
            // Locations of all #r directives in the order they are listed in the references list.
            ImmutableArray <Location> referenceDirectiveLocations;

            GetCompilationReferences(compilation, diagnostics, out references, out boundReferenceDirectiveMap, out referenceDirectiveLocations);

            // References originating from #r directives precede references supplied as arguments of the compilation.
            int referenceCount          = references.Length;
            int referenceDirectiveCount = (referenceDirectiveLocations != null ? referenceDirectiveLocations.Length : 0);

            var referenceMap = new ResolvedReference[referenceCount];

            // Maps references that were added to the reference set (i.e. not filtered out as duplicates) to a set of names that
            // can be used to alias these references. Duplicate assemblies contribute their aliases into this set.
            Dictionary <MetadataReference, MergedAliases> lazyAliasMap = null;

            // Used to filter out duplicate references that reference the same file (resolve to the same full normalized path).
            var boundReferences = new Dictionary <MetadataReference, MetadataReference>(MetadataReferenceEqualityComparer.Instance);

            ArrayBuilder <MetadataReference> uniqueDirectiveReferences = (referenceDirectiveLocations != null) ? ArrayBuilder <MetadataReference> .GetInstance() : null;

            var assembliesBuilder = ArrayBuilder <AssemblyData> .GetInstance();

            ArrayBuilder <PEModule> lazyModulesBuilder = null;

            bool supersedeLowerVersions = compilation.Options.ReferencesSupersedeLowerVersions;

            // When duplicate references with conflicting EmbedInteropTypes flag are encountered,
            // VB uses the flag from the last one, C# reports an error. We need to enumerate in reverse order
            // so that we find the one that matters first.
            for (int referenceIndex = referenceCount - 1; referenceIndex >= 0; referenceIndex--)
            {
                var boundReference = references[referenceIndex];
                if (boundReference == null)
                {
                    continue;
                }

                // add bound reference if it doesn't exist yet, merging aliases:
                MetadataReference existingReference;
                if (boundReferences.TryGetValue(boundReference, out existingReference))
                {
                    // merge properties of compilation-based references if the underlying compilations are the same
                    if ((object)boundReference != existingReference)
                    {
                        MergeReferenceProperties(existingReference, boundReference, diagnostics, ref lazyAliasMap);
                    }

                    continue;
                }

                boundReferences.Add(boundReference, boundReference);

                Location location;
                if (referenceIndex < referenceDirectiveCount)
                {
                    location = referenceDirectiveLocations[referenceIndex];
                    uniqueDirectiveReferences.Add(boundReference);
                }
                else
                {
                    location = Location.None;
                }

                // compilation reference

                var compilationReference = boundReference as CompilationReference;
                if (compilationReference != null)
                {
                    switch (compilationReference.Properties.Kind)
                    {
                    case MetadataImageKind.Assembly:
                        existingReference = TryAddAssembly(
                            compilationReference.Compilation.Assembly.Identity,
                            boundReference,
                            -assembliesBuilder.Count - 1,
                            diagnostics,
                            location,
                            assemblyReferencesBySimpleName,
                            supersedeLowerVersions);

                        if (existingReference != null)
                        {
                            MergeReferenceProperties(existingReference, boundReference, diagnostics, ref lazyAliasMap);
                            continue;
                        }

                        // Note, if SourceAssemblySymbol hasn't been created for
                        // compilationAssembly.Compilation yet, we want this to happen
                        // right now. Conveniently, this constructor will trigger creation of the
                        // SourceAssemblySymbol.
                        var asmData = CreateAssemblyDataForCompilation(compilationReference);
                        AddAssembly(asmData, referenceIndex, referenceMap, assembliesBuilder);
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(compilationReference.Properties.Kind);
                    }

                    continue;
                }

                // PE reference

                var      peReference = (PortableExecutableReference)boundReference;
                Metadata metadata    = GetMetadata(peReference, MessageProvider, location, diagnostics);
                Debug.Assert(metadata != null || diagnostics.HasAnyErrors());

                if (metadata != null)
                {
                    Debug.Assert(metadata != null);

                    switch (peReference.Properties.Kind)
                    {
                    case MetadataImageKind.Assembly:
                        var assemblyMetadata = (AssemblyMetadata)metadata;
                        WeakList <IAssemblySymbol> cachedSymbols = assemblyMetadata.CachedSymbols;

                        if (assemblyMetadata.IsValidAssembly())
                        {
                            PEAssembly assembly = assemblyMetadata.GetAssembly();
                            existingReference = TryAddAssembly(
                                assembly.Identity,
                                peReference,
                                -assembliesBuilder.Count - 1,
                                diagnostics,
                                location,
                                assemblyReferencesBySimpleName,
                                supersedeLowerVersions);

                            if (existingReference != null)
                            {
                                MergeReferenceProperties(existingReference, boundReference, diagnostics, ref lazyAliasMap);
                                continue;
                            }

                            var asmData = CreateAssemblyDataForFile(
                                assembly,
                                cachedSymbols,
                                peReference.DocumentationProvider,
                                SimpleAssemblyName,
                                compilation.Options.MetadataImportOptions,
                                peReference.Properties.EmbedInteropTypes);

                            AddAssembly(asmData, referenceIndex, referenceMap, assembliesBuilder);
                        }
                        else
                        {
                            diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotAssembly, location, peReference.Display));
                        }

                        // asmData keeps strong ref after this point
                        GC.KeepAlive(assemblyMetadata);
                        break;

                    case MetadataImageKind.Module:
                        var moduleMetadata = (ModuleMetadata)metadata;
                        if (moduleMetadata.Module.IsLinkedModule)
                        {
                            // We don't support netmodules since some checks in the compiler need information from the full PE image
                            // (Machine, Bit32Required, PE image hash).
                            if (!moduleMetadata.Module.IsEntireImageAvailable)
                            {
                                diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_LinkedNetmoduleMetadataMustProvideFullPEImage, location, peReference.Display));
                            }

                            AddModule(moduleMetadata.Module, referenceIndex, referenceMap, ref lazyModulesBuilder);
                        }
                        else
                        {
                            diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotModule, location, peReference.Display));
                        }
                        break;

                    default:
                        throw ExceptionUtilities.UnexpectedValue(peReference.Properties.Kind);
                    }
                }
            }

            if (uniqueDirectiveReferences != null)
            {
                uniqueDirectiveReferences.ReverseContents();
                boundReferenceDirectives = uniqueDirectiveReferences.ToImmutableAndFree();
            }
            else
            {
                boundReferenceDirectives = ImmutableArray <MetadataReference> .Empty;
            }

            // We enumerated references in reverse order in the above code
            // and thus assemblies and modules in the builders are reversed.
            // Fix up all the indices and reverse the builder content now to get
            // the ordering matching the references.
            //
            // Also fills in aliases.

            for (int i = 0; i < referenceMap.Length; i++)
            {
                if (!referenceMap[i].IsSkipped)
                {
                    int count = (referenceMap[i].Kind == MetadataImageKind.Assembly) ? assembliesBuilder.Count : lazyModulesBuilder?.Count ?? 0;

                    int reversedIndex = count - 1 - referenceMap[i].Index;
                    referenceMap[i] = GetResolvedReferenceAndFreePropertyMapEntry(references[i], reversedIndex, referenceMap[i].Kind, lazyAliasMap);
                }
            }

            assembliesBuilder.ReverseContents();
            assemblies = assembliesBuilder.ToImmutableAndFree();

            if (lazyModulesBuilder == null)
            {
                modules = ImmutableArray <PEModule> .Empty;
            }
            else
            {
                lazyModulesBuilder.ReverseContents();
                modules = lazyModulesBuilder.ToImmutableAndFree();
            }

            return(ImmutableArray.CreateRange(referenceMap));
        }
 private static void AddModule(Module module, int referenceIndex, List <Module> modules, ResolvedReference[] referenceMap)
 {
     referenceMap[referenceIndex] = new ResolvedReference(modules.Count, MetadataImageKind.Module, ReadOnlyArray <string> .Null);
     modules.Add(module);
 }
 private static void AddAssembly(AssemblyData data, int referenceIndex, List <AssemblyData> assemblies, ResolvedReference[] referenceMap)
 {
     referenceMap[referenceIndex] = new ResolvedReference(assemblies.Count, MetadataImageKind.Assembly, ReadOnlyArray <string> .Null);
     assemblies.Add(data);
 }
        /// <summary>
        /// Resolves given metadata references to assemblies and modules.
        /// </summary>
        /// <param name="compilation">The compilation whose references are being resolved.</param>
        /// <param name="references">List where to store resolved references. References from #r directives will follow references passed to the compilation constructor.</param>
        /// <param name="boundReferenceDirectiveMap">Maps #r values to successuflly resolved metadata references. Does not contain values that failed to resolve.</param>
        /// <param name="boundReferenceDirectives">Unique metadata references resolved from #r directives.</param>
        /// <param name="assemblies">List where to store information about resolved assemblies to.</param>
        /// <param name="modules">List where to store information about resolved modules to.</param>
        /// <param name="diagnostics">Diagnostic bag where to report resolution errors.</param>
        /// <returns>
        /// Maps index to <paramref name="references"/> to an index of a resolved assembly or module in <paramref name="assemblies"/> or <paramref name="modules"/>, respectively.
        ///</returns>
        protected ReadOnlyArray <ResolvedReference> ResolveMetadataReferences(
            TCompilation compilation,
            List <MetadataReference> references,
            out IDictionary <string, MetadataReference> boundReferenceDirectiveMap,
            out ReadOnlyArray <MetadataReference> boundReferenceDirectives,
            List <AssemblyData> assemblies,
            List <Module> modules,
            DiagnosticBag diagnostics)
        {
            // Locations of all #r directives in the order they are listed in the references list.
            List <CommonLocation> referenceDirectiveLocations;

            GetCompilationReferences(compilation, diagnostics, references, out boundReferenceDirectiveMap, out referenceDirectiveLocations);

            int externalReferenceCount = compilation.ExternalReferences.Count;
            int referenceCount         = references.Count;

            // References originating from #r directives precede references supplied as arguments of the compilation.
            int referenceDirectiveCount = referenceCount - externalReferenceCount;

            Debug.Assert((referenceDirectiveLocations != null ? referenceDirectiveLocations.Count : 0) == referenceDirectiveCount);

            var referenceMap = new ResolvedReference[referenceCount];

            // Maps references that were added to the reference set (i.e. not filtered out as duplicates) to a set of names that
            // can be used to alias these references. Duplicate assemblies contribute their aliases into this set.
            Dictionary <MetadataReference, ArrayBuilder <string> > aliasMap = null;

            // Used to filter out duplicate references that reference the same file (resolve to the same full normalized path).
            var boundReferences = new Dictionary <MetadataReference, MetadataReference>(MetadataReferenceEqualityComparer.Instance);

            // Used to filter out assemblies that have the same strong or weak identity.
            // Maps simple name to a list of full names.
            Dictionary <string, List <ReferencedAssemblyIdentity> > assemblyReferencesBySimpleName = null;

            ArrayBuilder <MetadataReference> uniqueDirectiveReferences = (referenceDirectiveLocations != null) ? ArrayBuilder <MetadataReference> .GetInstance() : null;

            // When duplicate references with conflicting EmbedInteropTypes flag are encountered,
            // VB uses the flag from the last one, C# reports an error. We need to enumerate in reverse order
            // so that we find the one that matters first.
            for (int referenceIndex = referenceCount - 1; referenceIndex >= 0; referenceIndex--)
            {
                var boundReference = references[referenceIndex];
                if (boundReference == null)
                {
                    continue;
                }

                // add bound reference if it doesn't exist yet, merging aliases:
                MetadataReference existingReference;
                if (boundReferences.TryGetValue(boundReference, out existingReference))
                {
                    if (CheckPropertiesConsistency(boundReference, existingReference, diagnostics))
                    {
                        AddAlias(existingReference, boundReference.Properties.Alias, ref aliasMap);
                    }

                    continue;
                }

                boundReferences.Add(boundReference, boundReference);

                CommonLocation location;
                if (referenceIndex < referenceDirectiveCount)
                {
                    location = referenceDirectiveLocations[referenceIndex];
                    uniqueDirectiveReferences.Add(boundReference);
                }
                else
                {
                    location = MessageProvider.NoLocation;
                }

                // compilation reference

                var compilationReference = boundReference as CommonCompilationReference;
                if (compilationReference != null)
                {
                    switch (compilationReference.Properties.Kind)
                    {
                    case MetadataImageKind.Assembly:
                        existingReference = TryAddAssembly(compilationReference.Compilation.Assembly.Identity, boundReference, diagnostics, location, ref assemblyReferencesBySimpleName);
                        if (existingReference != null)
                        {
                            AddAlias(existingReference, boundReference.Properties.Alias, ref aliasMap);
                            continue;
                        }

                        // Note, if SourceAssemblySymbol hasn't been created for
                        // compilationAssembly.Compilation yet, we want this to happen
                        // right now. Conveniently, this constructor will trigger creation of the
                        // SourceAssemblySymbol.
                        var asmData = CreateAssemblyDataForCompilation(compilationReference);
                        AddAssembly(asmData, referenceIndex, assemblies, referenceMap);
                        break;

                    default:
                        throw Contract.Unreachable;
                    }

                    continue;
                }

                // PE reference

                var      peReference = (PortableExecutableReference)boundReference;
                Metadata metadata    = peReference.GetMetadata(MessageProvider, location, diagnostics);
                Debug.Assert(metadata != null || diagnostics.HasAnyErrors());

                if (metadata != null)
                {
                    Debug.Assert(metadata != null);

                    switch (peReference.Properties.Kind)
                    {
                    case MetadataImageKind.Assembly:
                        var assemblyMetadata = (AssemblyMetadata)metadata;
                        WeakList <IAssemblySymbol> cachedSymbols = assemblyMetadata.CachedSymbols;

                        if (assemblyMetadata.IsValidAssembly())
                        {
                            Assembly assembly = assemblyMetadata.Assembly;
                            existingReference = TryAddAssembly(assembly.Identity, peReference, diagnostics, location, ref assemblyReferencesBySimpleName);
                            if (existingReference != null)
                            {
                                AddAlias(existingReference, boundReference.Properties.Alias, ref aliasMap);
                                continue;
                            }

                            var asmData = CreateAssemblyDataForFile(
                                assembly,
                                cachedSymbols,
                                peReference.GetDocumentationProvider(),
                                SimpleAssemblyName,
                                compilation.Options.AlwaysImportInternalMembers,
                                peReference.Properties.EmbedInteropTypes);

                            AddAssembly(asmData, referenceIndex, assemblies, referenceMap);
                        }
                        else
                        {
                            diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotAssembly, location, peReference.Display));
                        }

                        // asmData keeps strong ref after this point
                        GC.KeepAlive(assemblyMetadata);
                        break;

                    case MetadataImageKind.Module:
                        var moduleMetadata = (ModuleMetadata)metadata;
                        if (moduleMetadata.IsValidModule())
                        {
                            AddModule(moduleMetadata.Module, referenceIndex, modules, referenceMap);
                        }
                        else
                        {
                            diagnostics.Add(MessageProvider.CreateDiagnostic(MessageProvider.ERR_MetadataFileNotModule, location, peReference.Display));
                        }
                        break;

                    default:
                        throw Contract.Unreachable;
                    }
                }
            }

            if (uniqueDirectiveReferences != null)
            {
                uniqueDirectiveReferences.Reverse();
                boundReferenceDirectives = uniqueDirectiveReferences.ToReadOnlyAndFree();
            }
            else
            {
                boundReferenceDirectives = ReadOnlyArray <MetadataReference> .Empty;
            }

            for (int i = 0; i < referenceMap.Length; i++)
            {
                if (!referenceMap[i].IsSkipped)
                {
                    int reversedIndex = (referenceMap[i].Kind == MetadataImageKind.Assembly ? assemblies.Count : modules.Count) - 1 - referenceMap[i].Index;
                    referenceMap[i] = new ResolvedReference(reversedIndex, referenceMap[i].Kind, GetAliases(references[i], aliasMap));
                }
            }

            assemblies.Reverse();
            modules.Reverse();
            return(referenceMap.AsReadOnlyWrap());
        }