public static void CollectRoslynAssemblies(
            string roslynBinariesDirectoryPath,
            ref IImmutableDictionary <AssemblyShortName, AssemblyDetails> mainAssemblies,
            out IImmutableDictionary <AssemblyShortName, AssemblyDetails> usedRoslynAssemblies,
            out IImmutableDictionary <AssemblyShortName, string> roslynAssemblyPaths
            )
        {
            var roslynAssemblyPathsBuilder  = ImmutableSortedDictionary.CreateBuilder <AssemblyShortName, string>();
            var usedRoslynAssembliesBuilder = ImmutableSortedDictionary.CreateBuilder <AssemblyShortName, AssemblyDetails>();

            FluentConsole.White.Line($"Scanning {roslynBinariesDirectoryPath}…");
            foreach (var assemblyPath in Directory.EnumerateFiles(roslynBinariesDirectoryPath, "*.dll", SearchOption.AllDirectories))
            {
                FluentConsole.Gray.Line($"  {Path.GetFileName(assemblyPath)}");
                var name = Path.GetFileNameWithoutExtension(assemblyPath);
                // ReSharper disable once AssignNullToNotNullAttribute
                var assemblyFromMain = mainAssemblies.GetValueOrDefault(name);
                if (assemblyFromMain != null)
                {
                    FluentConsole.Gray.Line("    [used by main]");
                    usedRoslynAssembliesBuilder.Add(name, AssemblyDetails.ReadFrom(assemblyPath, readSymbols: true));
                    mainAssemblies = mainAssemblies.Remove(name);
                }
                if (roslynAssemblyPathsBuilder.ContainsKey(name))
                {
                    continue;
                }
                roslynAssemblyPathsBuilder.Add(name, assemblyPath);
            }
            usedRoslynAssemblies = usedRoslynAssembliesBuilder.ToImmutable();
            roslynAssemblyPaths  = roslynAssemblyPathsBuilder.ToImmutable();
        }
Beispiel #2
0
        public static void CollectRoslynReferences(
            ref IImmutableDictionary <AssemblyShortName, AssemblyDetails> usedRoslynAssemblies,
            IImmutableDictionary <AssemblyShortName, string> roslynAssemblyPaths,
            ref IImmutableDictionary <AssemblyShortName, AssemblyDetails> mainAssemblies,
            IImmutableDictionary <AssemblyShortName, IImmutableSet <PackageInfo> > roslynPackageMap,
            out IImmutableDictionary <AssemblyShortName, AssemblyDetails> othersReferencedByRoslyn
            )
        {
            var othersReferencedByRoslynBuilder = ImmutableSortedDictionary.CreateBuilder <AssemblyShortName, AssemblyDetails>();

            FluentConsole.White.Line("Analyzing Roslyn references…");
            var seen  = new HashSet <AssemblyShortName>();
            var queue = new Queue <AssemblyDetails>(usedRoslynAssemblies.Values);

            while (queue.Count > 0)
            {
                var assembly = queue.Dequeue();
                FluentConsole.Gray.Line($"  {assembly.Definition.Name.Name}");
                seen.Add(assembly.Definition.Name.Name);
                foreach (var reference in assembly.Definition.MainModule.AssemblyReferences)
                {
                    if (!seen.Add(reference.Name))
                    {
                        continue;
                    }
                    FluentConsole.Gray.Line($"    {reference.FullName}");
                    mainAssemblies = mainAssemblies.Remove(reference.Name);
                    if (usedRoslynAssemblies.ContainsKey(reference.Name))
                    {
                        FluentConsole.Gray.Line("      [roslyn assembly, already used]");
                        continue;
                    }
                    var roslynAssemblyPath = roslynAssemblyPaths.GetValueOrDefault(reference.Name);
                    if (roslynAssemblyPath != null)
                    {
                        FluentConsole.Gray.Line("      [roslyn assembly, queued]");
                        var roslynAssembly = AssemblyDetails.ReadFrom(roslynAssemblyPath, readSymbols: true);
                        usedRoslynAssemblies = usedRoslynAssemblies.Add(roslynAssembly.Definition.Name.Name, roslynAssembly);
                        queue.Enqueue(roslynAssembly);
                        continue;
                    }
                    if (InGlobalAssemblyCache(reference))
                    {
                        FluentConsole.Gray.Line("      [gac]");
                        continue;
                    }

                    var referencedAssembly = GetAssemblyDetailsFromNuGetCache(reference.Name, roslynPackageMap);
                    if (referencedAssembly == null)
                    {
                        FluentConsole.Gray.Line("      [system?]");
                        continue;
                    }
                    othersReferencedByRoslynBuilder.Add(reference.Name, referencedAssembly);
                    queue.Enqueue(referencedAssembly);
                }
            }
            othersReferencedByRoslyn = othersReferencedByRoslynBuilder.ToImmutable();
        }
Beispiel #3
0
        private static AssemblyDetails GetAssemblyDetailsFromNuGetCache(
            AssemblyShortName name,
            IImmutableDictionary <AssemblyShortName, IImmutableSet <PackageInfo> > roslynPackageMap
            )
        {
            var packageInfoSet = roslynPackageMap.GetValueOrDefault(name);

            if (packageInfoSet == null)
            {
                throw new Exception($"Could not identify NuGet package for assembly '{name}' (in packages referenced by Roslyn).");
            }
            if (packageInfoSet.Count > 1)
            {
                throw new Exception($"Ambiguous match for NuGet package for assembly '{name}':\r\n  {string.Join("\r\n  ", packageInfoSet)}.");
            }

            var packageInfo = packageInfoSet.Single();

            FluentConsole.Gray.Line($"      {packageInfo.PackageId}.{packageInfo.PackageVersion}");
            var packageVersionPath = Path.Combine(LocalNuGetCachePath, packageInfo.PackageId, packageInfo.PackageVersion);

            var libPath       = Path.Combine(packageVersionPath, "lib");
            var frameworkPath = new DirectoryInfo(libPath)
                                .EnumerateDirectories()
                                .Where(f => SupportedFrameworkNames.ContainsKey(f.Name))
                                .OrderBy(f => SupportedFrameworkNames[f.Name])
                                .FirstOrDefault()
                                ?.FullName;

            if (frameworkPath == null)
            {
                throw new DirectoryNotFoundException($"Could not find compatible framework for assembly '{name}' in NuGet cache, under {libPath}.");
            }
            if (File.Exists(Path.Combine(frameworkPath, "_._")))
            {
                return(null);
            }

            var assemblyPath = Path.Combine(frameworkPath, name.Name + ".dll");

            if (!File.Exists(assemblyPath))
            {
                throw new FileNotFoundException($"Could not find assembly '{name}' in NuGet cache, at {assemblyPath}.", assemblyPath);
            }
            return(AssemblyDetails.ReadFrom(assemblyPath, readSymbolsIfExist: false));
        }
Beispiel #4
0
        public static void CollectMainAssemblies(string binariesDirectoryPath, out IImmutableDictionary <AssemblyShortName, AssemblyDetails> mainAssemblies)
        {
            FluentConsole.White.Line($"Scanning {binariesDirectoryPath}…");
            var mainAssembliesBuilder = ImmutableSortedDictionary.CreateBuilder <AssemblyShortName, AssemblyDetails>();

            foreach (var assemblyPath in Directory.EnumerateFiles(binariesDirectoryPath, "*.*"))
            {
                if (!Regex.IsMatch(assemblyPath, @"(?:\.dll|\.exe)$", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant))
                {
                    continue;
                }

                FluentConsole.Gray.Line($"  {Path.GetFileName(assemblyPath)}");
                var name = Path.GetFileNameWithoutExtension(assemblyPath);
                // ReSharper disable once AssignNullToNotNullAttribute
                mainAssembliesBuilder.Add(name, AssemblyDetails.ReadFrom(assemblyPath, readSymbols: false));
            }
            mainAssemblies = mainAssembliesBuilder.ToImmutable();
        }