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 } } }
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); }
/// <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); }
/// <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); }
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}]"; })); }
/// <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); }
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); }
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); }
/// <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()); }