Skip to content

Commit

Permalink
Update Parser Logic (#8565)
Browse files Browse the repository at this point in the history
  • Loading branch information
chidozieononiwu authored Jul 8, 2024
1 parent 211cf7d commit 6287e62
Show file tree
Hide file tree
Showing 3 changed files with 64 additions and 50 deletions.
45 changes: 0 additions & 45 deletions src/dotnet/APIView/APIViewWeb/Languages/CSharpLanguageService.cs
Original file line number Diff line number Diff line change
Expand Up @@ -86,50 +86,5 @@ private CodeFile GetDummyReviewCodeFile(string originalName, List<DependencyInfo
Tokens = builder.Tokens.ToArray()
};
}

/// <summary>
/// Resolves the NuGet package dependencies and extracts them to a temporary folder. It is the responsibility of teh caller to clean up the folder.
/// </summary>
/// <param name="dependencyInfos">The dependency infos</param>
/// <returns>A temporary path where the dependency files were extracted.</returns>
private async Task<string> ExtractNugetDependencies(List<DependencyInfo> dependencyInfos)
{
string tempFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
SourceCacheContext cache = new SourceCacheContext();
SourceRepository repository = NuGet.Protocol.Core.Types.Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
try
{
FindPackageByIdResource resource = await repository.GetResourceAsync<FindPackageByIdResource>().ConfigureAwait(false);
foreach (var dep in dependencyInfos)
{
using (MemoryStream packageStream = new MemoryStream())
{
if (await resource.CopyNupkgToStreamAsync(
dep.Name,
new NuGetVersion(dep.Version),
packageStream,
cache,
NullLogger.Instance,
CancellationToken.None))
{
using PackageArchiveReader reader = new PackageArchiveReader(packageStream);
NuspecReader nuspec = reader.NuspecReader;
var file = reader.GetFiles().FirstOrDefault(f => f.EndsWith(dep.Name + ".dll"));
if (file != null)
{
var fileInfo = new FileInfo(file);
var path = Path.Combine(tempFolder, dep.Name, fileInfo.Name);
var tmp = reader.ExtractFile(file, path, NullLogger.Instance);
}
}
}
}
}
finally
{
cache.Dispose();
}
return tempFolder;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="NuGet.Protocol" Version="6.10.1" />
<PackageReference Include="System.CommandLine" Version="2.0.0-beta4.22272.1" />
</ItemGroup>

Expand Down
68 changes: 63 additions & 5 deletions tools/apiview/parsers/csharp-api-parser/CSharpAPIParser/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,11 @@
using System.Text.Json.Serialization;
using System.Xml.Linq;
using ApiView;
using NuGet.Common;
using NuGet.Packaging;
using NuGet.Protocol;
using NuGet.Protocol.Core.Types;
using NuGet.Versioning;

var inputOption = new Option<FileInfo>("--packageFilePath", "C# Package (.nupkg) file").ExistingOnly();
inputOption.IsRequired = true;
Expand All @@ -21,13 +26,13 @@
runAnalysis
};

rootCommand.SetHandler((FileInfo packageFilePath, DirectoryInfo outputDirectory, string outputFileName, bool runAnalysis) =>
rootCommand.SetHandler(async (FileInfo packageFilePath, DirectoryInfo outputDirectory, string outputFileName, bool runAnalysis) =>
{
try
{
using (var stream = packageFilePath.OpenRead())
{
HandlePackageFileParsing(stream, packageFilePath, outputDirectory, outputFileName, runAnalysis);
await HandlePackageFileParsing(stream, packageFilePath, outputDirectory, outputFileName, runAnalysis);
}
}
catch (Exception ex)
Expand All @@ -39,12 +44,13 @@
return rootCommand.InvokeAsync(args).Result;


static void HandlePackageFileParsing(Stream stream, FileInfo packageFilePath, DirectoryInfo OutputDirectory, string outputFileName, bool runAnalysis)
static async Task HandlePackageFileParsing(Stream stream, FileInfo packageFilePath, DirectoryInfo OutputDirectory, string outputFileName, bool runAnalysis)
{
ZipArchive? zipArchive = null;
Stream? dllStream = stream;
Stream? docStream = null;
List<DependencyInfo>? dependencies = null;
string dependencyFilesTempDir = null;

try
{
Expand Down Expand Up @@ -94,12 +100,16 @@ static void HandlePackageFileParsing(Stream stream, FileInfo packageFilePath, Di
}
}

var assemblySymbol = CompilationFactory.GetCompilation(dllStream, docStream);
dependencyFilesTempDir = await ExtractNugetDependencies(dependencies).ConfigureAwait(false);
var dependencyFilePaths = Directory.EnumerateFiles(dependencyFilesTempDir, "*.dll", SearchOption.AllDirectories);
var assemblySymbol = CompilationFactory.GetCompilation(dllStream, docStream, dependencyFilePaths);

if (assemblySymbol == null)
{
Console.Error.WriteLine($"PackageFile {packageFilePath.FullName} contains no Assembly Symbol.");
return;
}

var parsedFileName = string.IsNullOrEmpty(outputFileName) ? assemblySymbol.Name : outputFileName;
var treeTokenCodeFile = new CSharpAPIParser.TreeToken.CodeFileBuilder().Build(assemblySymbol, runAnalysis, dependencies);
var gzipJsonTokenFilePath = Path.Combine(OutputDirectory.FullName, $"{parsedFileName}.json.tgz");
Expand All @@ -126,8 +136,11 @@ static void HandlePackageFileParsing(Stream stream, FileInfo packageFilePath, Di
finally
{
zipArchive?.Dispose();
if (dependencyFilesTempDir != null && Directory.Exists(dependencyFilesTempDir))
{
Directory.Delete(dependencyFilesTempDir, true);
}
}

}

static bool IsNuget(string name)
Expand All @@ -144,3 +157,48 @@ static bool IsDll(string name)
{
return name.EndsWith(".dll", StringComparison.OrdinalIgnoreCase);
}

/// <summary>
/// Resolves the NuGet package dependencies and extracts them to a temporary folder. It is the responsibility of teh caller to clean up the folder.
/// </summary>
/// <param name="dependencyInfos">The dependency infos</param>
/// <returns>A temporary path where the dependency files were extracted.</returns>
static async Task<string> ExtractNugetDependencies(List<DependencyInfo> dependencyInfos)
{
string tempFolder = Path.Combine(Path.GetTempPath(), Guid.NewGuid().ToString());
SourceCacheContext cache = new SourceCacheContext();
SourceRepository repository = Repository.Factory.GetCoreV3("https://api.nuget.org/v3/index.json");
try
{
FindPackageByIdResource resource = await repository.GetResourceAsync<FindPackageByIdResource>().ConfigureAwait(false);
foreach (var dep in dependencyInfos)
{
using (MemoryStream packageStream = new MemoryStream())
{
if (await resource.CopyNupkgToStreamAsync(
dep.Name,
new NuGetVersion(dep.Version),
packageStream,
cache,
NullLogger.Instance,
CancellationToken.None))
{
using PackageArchiveReader reader = new PackageArchiveReader(packageStream);
NuspecReader nuspec = reader.NuspecReader;
var file = reader.GetFiles().FirstOrDefault(f => f.EndsWith(dep.Name + ".dll"));
if (file != null)
{
var fileInfo = new FileInfo(file);
var path = Path.Combine(tempFolder, dep.Name, fileInfo.Name);
var tmp = reader.ExtractFile(file, path, NullLogger.Instance);
}
}
}
}
}
finally
{
cache.Dispose();
}
return tempFolder;
}

0 comments on commit 6287e62

Please sign in to comment.