using System; using System.Collections.Generic; using System.IO; using System.Linq; using Semmle.Util.Logging; namespace Semmle.Extraction.CSharp.DependencyFetching { /// /// Used to represent a path to an assembly or a directory containing assemblies /// and a selector function to determine which files to include, when indexing the assemblies. /// internal sealed class AssemblyLookupLocation(string path, Func includeFileName, bool indexSubdirectories = true) { public string Path => path; public AssemblyLookupLocation(string path) : this(path, _ => true) { } public static implicit operator AssemblyLookupLocation(string path) => new(path); /// /// Finds all assemblies nested within the directory `path` /// and adds them to the a list of assembly names to index. /// Indexing is performed at a later stage. This only collects the names. /// /// List of dlls to index. /// Logger. private void AddReferenceDirectory(List dllsToIndex, ILogger logger) { try { var dlls = new DirectoryInfo(path).EnumerateFiles("*.dll", new EnumerationOptions { RecurseSubdirectories = indexSubdirectories, MatchCasing = MatchCasing.CaseInsensitive, AttributesToSkip = FileAttributes.None }); if (!dlls.Any()) { logger.LogWarning($"AssemblyLookupLocation: No DLLs found in the path '{path}'."); return; } foreach (var dll in dlls) { if (includeFileName(dll.Name)) { dllsToIndex.Add(dll.FullName); } else { logger.LogDebug($"AssemblyLookupLocation: Skipping {dll.FullName}."); } } } catch (Exception e) { logger.LogError($"AssemblyLookupLocation: Error while searching for DLLs in '{path}': {e.Message}"); } } /// /// Returns a list of paths to all assemblies in `path` that should be indexed. /// /// Logger public List GetDlls(ILogger logger) { var dllsToIndex = new List(); if (File.Exists(path)) { if (includeFileName(System.IO.Path.GetFileName(path))) { dllsToIndex.Add(path); } else { logger.LogDebug($"AssemblyLookupLocation: Skipping {path}."); } return dllsToIndex; } if (Directory.Exists(path)) { logger.LogDebug($"AssemblyLookupLocation: Finding reference DLLs in {path}..."); AddReferenceDirectory(dllsToIndex, logger); } else { logger.LogDebug($"AssemblyLookupLocation: Path not found: {path}"); } return dllsToIndex; } public override bool Equals(object? obj) => obj is AssemblyLookupLocation ap && path.Equals(ap.Path); public override int GetHashCode() => path.GetHashCode(); public override string ToString() => path; } }