private static void WriteApiList(UsageInformation apis) { var options = new JsonSerializerOptions() { WriteIndented = true }; var json = JsonSerializer.Serialize(apis, options); Console.WriteLine(json); }
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); }
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); }
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); }