Пример #1
0
        private static void WriteApiList(UsageInformation apis)
        {
            var options = new JsonSerializerOptions()
            {
                WriteIndented = true
            };
            var json = JsonSerializer.Serialize(apis, options);

            Console.WriteLine(json);
        }
Пример #2
0
        private static UsageInformation?GetApisUsedByAssembly(string file)
        {
            // Skip NuGet's own assemblies
            string filename = Path.GetFileNameWithoutExtension(file);

            if (NuGetAssembly.MatchesName(filename) ||
                filename.Equals("NuGet.Core", StringComparison.OrdinalIgnoreCase))
            {
                return(null);
            }

            if (filename.StartsWith("NuGet.", StringComparison.OrdinalIgnoreCase))
            {
                Console.Error.WriteLine("Suspicious assembly name: " + file);
            }

            using var fileStream = File.OpenRead(file);
            using var peReader   = new PEReader(fileStream);

            MetadataReader metadata;

            try
            {
                metadata = peReader.GetMetadataReader();
            }
            catch (InvalidOperationException)
            {
                // Not a .NET assembly
                return(null);
            }

            if (!AssemblyAnalyser.HasReferenceToNuGetAssembly(metadata))
            {
                return(null);
            }

            UsageInformation usedNuGetApis = AssemblyAnalyser.FindUsedNuGetApis(metadata);

            return(usedNuGetApis);
        }
Пример #3
0
        internal static UsageInformation FindUsedNuGetApis(MetadataReader metadata)
        {
            var result = new UsageInformation();

            void AddMember(string assembly, string member)
            {
                if (!result.MemberReferences.TryGetValue(assembly, out HashSet <string>?apis))
                {
                    apis = new HashSet <string>();
                    result.MemberReferences[assembly] = apis;
                }

                apis.Add(member);
            }

            foreach (var memberReferenceHandle in metadata.MemberReferences)
            {
                var memberReference        = metadata.GetMemberReference(memberReferenceHandle);
                var foundAssemblyReference = TryFindAssemblyReference(memberReferenceHandle, metadata, out var assemblyReference);

                if (foundAssemblyReference && NuGetAssembly.IsNuGetAssembly(assemblyReference))
                {
                    var assemblyName = assemblyReference.GetAssemblyName();
                    var version      = assemblyName.Version?.ToString();
                    if (version != null)
                    {
                        result.Versions.Add(version);
                    }

                    var kind = memberReference.GetKind();
                    switch (kind)
                    {
                    case MemberReferenceKind.Method:
                    {
                        var(assembly, member) = TypeNameGenerator.GetFullName(memberReferenceHandle, metadata);
                        var sig             = memberReference.DecodeMethodSignature(MethodSignatureDecoder.Default, null);
                        var methodSignature = GetMethodSignature(member, sig);
                        AddMember(assembly, methodSignature);
                    }
                    break;

                    case MemberReferenceKind.Field:
                    {
                        var(assembly, member) = TypeNameGenerator.GetFullName(memberReferenceHandle, metadata);
                        AddMember(assembly, member);
                    }
                    break;

                    default:
                        throw new NotImplementedException(kind.ToString());
                    }
                }
            }

            if (result.MemberReferences.SelectMany(r => r.Value).Any())
            {
                if (TryGetTargetFramework(metadata, out string?targetFramework))
                {
                    result.TargetFrameworks.Add(targetFramework);
                }
            }

            return(result);
        }
Пример #4
0
        private static async Task <UsageInformation> GetUsageInformation(IEnumerable <string> files)
        {
            var result = new UsageInformation();

            var multipleInstancesOption = new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = Environment.ProcessorCount
            };
            var singleInstanceOption = new ExecutionDataflowBlockOptions
            {
                MaxDegreeOfParallelism = 1
            };

            var getApisBlock     = new TransformBlock <string, UsageInformation?>(GetApisUsedByAssembly, multipleInstancesOption);
            var collectApisBlock = new ActionBlock <UsageInformation?>(assemblyInfo =>
            {
                if (assemblyInfo != null)
                {
                    foreach (var targetFramework in assemblyInfo.TargetFrameworks)
                    {
                        result.TargetFrameworks.Add(targetFramework);
                    }

                    foreach (var version in assemblyInfo.Versions)
                    {
                        result.Versions.Add(version);
                    }

                    foreach (var apisByAssembly in assemblyInfo.MemberReferences)
                    {
                        if (!result.MemberReferences.TryGetValue(apisByAssembly.Key, out HashSet <string>?allApis))
                        {
                            allApis = new HashSet <string>();
                            result.MemberReferences[apisByAssembly.Key] = allApis;
                        }

                        foreach (var api in apisByAssembly.Value)
                        {
                            allApis.Add(api);
                        }
                    }
                }
            },
                                                                       singleInstanceOption);

            var linkOptions = new DataflowLinkOptions()
            {
                PropagateCompletion = true
            };

            getApisBlock.LinkTo(collectApisBlock, linkOptions);

            foreach (var file in files)
            {
                await getApisBlock.SendAsync(file);
            }

            getApisBlock.Complete();

            await Task.WhenAll(getApisBlock.Completion, collectApisBlock.Completion);

            return(result);
        }