Directory.Build.props
+1
-1
diff --git a/Directory.Build.props b/Directory.Build.props
index ca628d0..2717ecc 100644
@@ -6,6 +6,6 @@
<Nullable>enable</Nullable>
<RestorePackagesWithLockFile>true</RestorePackagesWithLockFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<IsAotCompatible>true</IsAotCompatible>
<IsTrimmable>true</IsTrimmable>
</PropertyGroup>
</Project>
Directory.Packages.props
+5
-0
diff --git a/Directory.Packages.props b/Directory.Packages.props
index c464477..29a8326 100644
@@ -9,4 +9,9 @@
<PrivateAssets>all</PrivateAssets>
</GlobalPackageReference>
</ItemGroup>
<ItemGroup>
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="5.9.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="5.9.0" />
<PackageVersion Include="System.CommandLine" Version="2.0.14" />
</ItemGroup>
</Project>
cli/src/Cfa.Cli.csproj
+17
-0
diff --git a/cli/src/Cfa.Cli.csproj b/cli/src/Cfa.Cli.csproj
new file mode 100644
index 0000000..4929328
@@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<RootNamespace>Cfa.Cli</RootNamespace>
<AssemblyName>Cfa.Cli</AssemblyName>
<OutputType>Exe</OutputType>
<PublishReadyToRun>true</PublishReadyToRun>
</PropertyGroup>
<ItemGroup>
<InternalsVisibleTo Include="Cfa.Cli.Tests" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\core\src\Cfa.csproj" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="System.CommandLine" />
</ItemGroup>
</Project>
cli/src/Program.cs
+6
-0
diff --git a/cli/src/Program.cs b/cli/src/Program.cs
new file mode 100644
index 0000000..a1ea539
@@ -0,0 +1,6 @@
using System.CommandLine;
using Cfa.Cli;
var rootCommand = new RootCommand("Code Flow Analysis");
rootCommand.Subcommands.Add(new ScanCommand());
return rootCommand.Parse(args).Invoke();
cli/src/ScanCommand.cs
+96
-0
diff --git a/cli/src/ScanCommand.cs b/cli/src/ScanCommand.cs
new file mode 100644
index 0000000..b558e8d
@@ -0,0 +1,96 @@
using System;
using System.CommandLine;
using System.CommandLine.Invocation;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
namespace Cfa.Cli;
internal sealed class ScanCommand : Command
{
private static Argument<FileInfo> PathArgument { get; } =
new("path")
{
Description =
"Path to the solution file, or the directory containing it. (Defaults to the current directory.)",
DefaultValueFactory = result =>
{
var directory = new DirectoryInfo(Directory.GetCurrentDirectory());
switch (
directory
.GetFiles("*.sln?", SearchOption.TopDirectoryOnly)
.Where(f => f.Extension is ".sln" or ".slnx")
.ToArray()
)
{
case []:
result.AddError("No solution files found in the current directory.");
return null!;
case [var file]:
return file;
default:
result.AddError("Multiple solution files found in the current directory.");
return null!;
}
},
CustomParser = result =>
{
if (result.Tokens is not [var token] || string.IsNullOrWhiteSpace(token.Value))
{
result.AddError("No path specified.");
return null;
}
if (Directory.Exists(token.Value))
{
var directory = new DirectoryInfo(token.Value);
switch (
directory
.GetFiles("*.sln?", SearchOption.TopDirectoryOnly)
.Where(f => f.Extension is ".sln" or ".slnx")
.ToArray()
)
{
case []:
result.AddError("No solution files found in the specified directory.");
return null;
case [var file]:
return file;
default:
result.AddError("Multiple solution files found in the specified directory.");
return null;
}
}
if (File.Exists(token.Value))
{
return new FileInfo(token.Value);
}
result.AddError("The specified path does not exist.");
return null;
},
};
public ScanCommand()
: base("scan", "Scan the code for analysis")
{
Action = new ScanAction();
Arguments.Add(PathArgument);
}
internal sealed class ScanAction : AsynchronousCommandLineAction
{
public override async Task<int> InvokeAsync(ParseResult parseResult, CancellationToken cancellationToken)
{
var solutionFile = parseResult.GetRequiredValue(PathArgument);
using var scanner = await Scanner.Create(solutionFile, cancellationToken);
await foreach (var method in scanner.FindMethods(cancellationToken))
{
Console.WriteLine($"Found method: {method.Name}");
}
return 0;
}
}
}
cli/src/packages.lock.json
+172
-0
diff --git a/cli/src/packages.lock.json b/cli/src/packages.lock.json
new file mode 100644
index 0000000..190150c
@@ -0,0 +1,172 @@
{
"version": 2,
"dependencies": {
"net11.0": {
"CSharpier.MsBuild": {
"type": "Direct",
"requested": "[1.3.0, )",
"resolved": "1.3.0",
"contentHash": "jzzLpmz7F6LyBh5FTZy8/4dEYVcAG9VjBPKryZ82LIoUuupcBkCSXzaeS/4oYcp/rBC8yVLcDstJ8CIv9n2IFw=="
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[11.0.0-rc.3.26522.148, )",
"resolved": "11.0.0-rc.3.26522.148",
"contentHash": "SWnTMx96mhBr9LCOySJg1ETlEFFHVsPGdVT02JnYhtqk1+Vke1J7RU3VkKwEiErBr4FJ42Uu4k7GdOtkRuvs/Q=="
},
"System.CommandLine": {
"type": "Direct",
"requested": "[2.0.14, )",
"resolved": "2.0.14",
"contentHash": "15fyVO4aG6poR6IKmhM74zf7PUzaU6FZAGm2d3SQSO9yIyGAeo44e6t9qeKjjaqyMEqYdqcb2G1B0gpLoDU2cA=="
},
"Humanizer.Core": {
"type": "Transitive",
"resolved": "2.14.1",
"contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw=="
},
"Microsoft.Build.Framework": {
"type": "Transitive",
"resolved": "17.11.48",
"contentHash": "C3WIMt2wBl4++NX3jSEpTq5KXBhvAV154R4JrYHkfy9JSBcXWiL0mkgpspk5xSdOj+fS/uz7zluIy6bMM1fkkQ=="
},
"Microsoft.CodeAnalysis.Analyzers": {
"type": "Transitive",
"resolved": "5.9.0-1.26328.17",
"contentHash": "HP9NNk8ZjOSI2hgOyXnQg+kv7/X837Vr2nAlXiGAtqtYnYKjRRa1UmQFr8KFs5ynGYKqfbb8zB9APoWjiAGdMg=="
},
"Microsoft.CodeAnalysis.Common": {
"type": "Transitive",
"resolved": "5.9.0",
"contentHash": "IYaIaUWdIx539AReKZOBEqTskFusZfCh/wFSPilDvCn5Say8MegLw2LONcSIcVy+v3Gzv53qYBspgvBGSErfbQ==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17"
}
},
"Microsoft.CodeAnalysis.CSharp": {
"type": "Transitive",
"resolved": "5.9.0",
"contentHash": "7JGDA0UT1+h7k9ZcA3rF4eFC8+QPq1xyYaXxag4p8r/zzPurEJxvdi7aM+MRL/SfP7XADXpWF/pl/eUYXOq/ww==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17",
"Microsoft.CodeAnalysis.Common": "[5.9.0]"
}
},
"Microsoft.CodeAnalysis.Workspaces.Common": {
"type": "Transitive",
"resolved": "5.9.0",
"contentHash": "1A6jz50NG4nOEW8tX5+h+MyHqjWL0mPGwrUdwu+OlTfyknLo0GfxSqj4zEks8uVUdHdo9v8Ir9dHxACf8iYNEA==",
"dependencies": {
"Humanizer.Core": "2.14.1",
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17",
"Microsoft.CodeAnalysis.Common": "[5.9.0]",
"System.Composition": "10.0.1"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "zerXV0GAR9LCSXoSIApbWn+Dq1/T+6vbXMHGduq1LoVQRHT0BXsGQEau0jeLUBUcsoF/NaUT8ADPu8b+eNcIyg=="
},
"Microsoft.Extensions.Logging": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "9ItMpMLFZFJFqCuHLLbR3LiA4ahA8dMtYuXpXl2YamSDWZhYS9BruPprkftY0tYi2bQ0slNrixdFm+4kpz1g5w==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "10.0.1"
}
},
"Microsoft.VisualStudio.SolutionPersistence": {
"type": "Transitive",
"resolved": "1.0.52",
"contentHash": "oNv2JtYXhpdJrX63nibx1JT3uCESOBQ1LAk7Dtz/sr0+laW0KRM6eKp4CZ3MHDR2siIkKsY8MmUkeP5DKkQQ5w=="
},
"System.Composition": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "DJkqaWQfho/ReTzKcZD3zJJ6K4GcS154k+T0UCPMBNIOZ2U/lNpyiiWZ6Etw0onWyTH1K+yhICsdmwA5xy2aPQ==",
"dependencies": {
"System.Composition.AttributedModel": "10.0.1",
"System.Composition.Convention": "10.0.1",
"System.Composition.Hosting": "10.0.1",
"System.Composition.Runtime": "10.0.1",
"System.Composition.TypedParts": "10.0.1"
}
},
"System.Composition.AttributedModel": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "mRxYvpCVPAeuLEk0c0kxWJVjbW1/HUoxCgYotOj9eDeQiYcTDOMdCQApsTrHYMN3pHBA8WoF00KGolG632Etaw=="
},
"System.Composition.Convention": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "dYynUByfVBzYDheNPGxS8UN8AvG/4tXf/coSs1odHOyoh4etv1kad/FrLWLMq4f8NO49NV20Xu+0/y613woTUA==",
"dependencies": {
"System.Composition.AttributedModel": "10.0.1"
}
},
"System.Composition.Hosting": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "4UGmyBdKWEN1nkqspJlji/nV7XIVm6KGlOC2So0mtM/gKvaNgLz+tUkcbY+6Zpr7dr6ohX1S5yl0RLID5otRHw==",
"dependencies": {
"System.Composition.Runtime": "10.0.1"
}
},
"System.Composition.Runtime": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "TVfys1gnUIhmXuYfFzyez0fOkDyELe9UwlxYeVlq6FmqmWmt1ouF0OQJ+6ozkHbkaop7uBUaXw7Qb+/o0m+nMg=="
},
"System.Composition.TypedParts": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "koSfjkdQZfgQr3SyiSIBboDn+GiR0vZ3x9Uek9FJbXK0w5AiATV8KrnMEP8B8OAlO+Y3zQf0CPCNzwH+VIYDKg==",
"dependencies": {
"System.Composition.AttributedModel": "10.0.1",
"System.Composition.Hosting": "10.0.1",
"System.Composition.Runtime": "10.0.1"
}
},
"cfa": {
"type": "Project",
"dependencies": {
"Microsoft.CodeAnalysis.CSharp.Workspaces": "[5.9.0, )",
"Microsoft.CodeAnalysis.Workspaces.MSBuild": "[5.9.0, )"
}
},
"Microsoft.CodeAnalysis.CSharp.Workspaces": {
"type": "CentralTransitive",
"requested": "[5.9.0, )",
"resolved": "5.9.0",
"contentHash": "D2zqK/k16fto0yMz0hcXMTkzOxEwMDJyA1mu/KXF9Befwz4zub3MpHQD8FeRxJtVSSsC3dQFYBw7zu7r/pfO7g==",
"dependencies": {
"Humanizer.Core": "2.14.1",
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17",
"Microsoft.CodeAnalysis.CSharp": "[5.9.0]",
"Microsoft.CodeAnalysis.Common": "[5.9.0]",
"Microsoft.CodeAnalysis.Workspaces.Common": "[5.9.0]",
"System.Composition": "10.0.1"
}
},
"Microsoft.CodeAnalysis.Workspaces.MSBuild": {
"type": "CentralTransitive",
"requested": "[5.9.0, )",
"resolved": "5.9.0",
"contentHash": "BBux6hhD4wXt4lYN2oaY+jV4PnIj5plyqohijgSZtxJQqsvsldPEdii2q9lGrJbNjKEALnldDHz1rmGKG0PeeA==",
"dependencies": {
"Humanizer.Core": "2.14.1",
"Microsoft.Build.Framework": "17.11.48",
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17",
"Microsoft.CodeAnalysis.Workspaces.Common": "[5.9.0]",
"Microsoft.Extensions.DependencyInjection": "10.0.1",
"Microsoft.Extensions.Logging": "10.0.1",
"Microsoft.VisualStudio.SolutionPersistence": "1.0.52",
"System.Composition": "10.0.1"
}
}
},
"net11.0/linux-x64": {}
}
}
\ No newline at end of file
code-flow-analysis.slnx
+3
-0
diff --git a/code-flow-analysis.slnx b/code-flow-analysis.slnx
index 79671dc..5e0d5f4 100644
@@ -1,4 +1,7 @@
<Solution>
<Folder Name="/cli/">
<Project Path="cli/src/Cfa.Cli.csproj" />
</Folder>
<Folder Name="/core/">
<Project Path="core/src/Cfa.csproj" />
</Folder>
core/src/Cfa.csproj
+4
-0
diff --git a/core/src/Cfa.csproj b/core/src/Cfa.csproj
index 4359b83..2b8091b 100644
@@ -6,4 +6,8 @@
<ItemGroup>
<InternalsVisibleTo Include="Cfa.Tests" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" />
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" />
</ItemGroup>
</Project>
core/src/Scanner.cs
+69
-0
diff --git a/core/src/Scanner.cs b/core/src/Scanner.cs
new file mode 100644
index 0000000..dbb9ac7
@@ -0,0 +1,69 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp.Syntax;
using Microsoft.CodeAnalysis.MSBuild;
namespace Cfa;
public sealed class Scanner : IDisposable
{
public static async Task<Scanner> Create(FileInfo solutionFile, CancellationToken cancellationToken = default)
{
var workspace = MSBuildWorkspace.Create();
var solution = await workspace.OpenSolutionAsync(solutionFile.FullName, cancellationToken: cancellationToken);
return new Scanner(workspace, solution);
}
private readonly Workspace workspace;
private readonly Solution solution;
private Scanner(Workspace workspace, Solution solution)
{
this.workspace = workspace;
this.solution = solution;
}
public async IAsyncEnumerable<IMethodSymbol> FindMethods(
[EnumeratorCancellation] CancellationToken cancellationToken = default
)
{
foreach (var project in solution.Projects)
{
var compilation = await project.GetCompilationAsync(cancellationToken);
if (compilation == null)
{
continue;
}
foreach (var syntaxTree in compilation.SyntaxTrees)
{
var semanticModel = compilation.GetSemanticModel(syntaxTree);
var methodDeclarations = syntaxTree
.GetRoot(cancellationToken)
.DescendantNodes()
.OfType<MethodDeclarationSyntax>();
foreach (var methodDeclaration in methodDeclarations)
{
if (
semanticModel.GetDeclaredSymbol(methodDeclaration, cancellationToken: cancellationToken)
is IMethodSymbol methodSymbol
)
{
yield return methodSymbol;
}
}
}
}
}
public void Dispose()
{
workspace.Dispose();
}
}
core/src/packages.lock.json
+139
-0
diff --git a/core/src/packages.lock.json b/core/src/packages.lock.json
index 6b6f557..68fbb9d 100644
@@ -8,11 +8,150 @@
"resolved": "1.3.0",
"contentHash": "jzzLpmz7F6LyBh5FTZy8/4dEYVcAG9VjBPKryZ82LIoUuupcBkCSXzaeS/4oYcp/rBC8yVLcDstJ8CIv9n2IFw=="
},
"Microsoft.CodeAnalysis.CSharp.Workspaces": {
"type": "Direct",
"requested": "[5.9.0, )",
"resolved": "5.9.0",
"contentHash": "D2zqK/k16fto0yMz0hcXMTkzOxEwMDJyA1mu/KXF9Befwz4zub3MpHQD8FeRxJtVSSsC3dQFYBw7zu7r/pfO7g==",
"dependencies": {
"Humanizer.Core": "2.14.1",
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17",
"Microsoft.CodeAnalysis.CSharp": "[5.9.0]",
"Microsoft.CodeAnalysis.Common": "[5.9.0]",
"Microsoft.CodeAnalysis.Workspaces.Common": "[5.9.0]",
"System.Composition": "10.0.1"
}
},
"Microsoft.CodeAnalysis.Workspaces.MSBuild": {
"type": "Direct",
"requested": "[5.9.0, )",
"resolved": "5.9.0",
"contentHash": "BBux6hhD4wXt4lYN2oaY+jV4PnIj5plyqohijgSZtxJQqsvsldPEdii2q9lGrJbNjKEALnldDHz1rmGKG0PeeA==",
"dependencies": {
"Humanizer.Core": "2.14.1",
"Microsoft.Build.Framework": "17.11.48",
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17",
"Microsoft.CodeAnalysis.Workspaces.Common": "[5.9.0]",
"Microsoft.Extensions.DependencyInjection": "10.0.1",
"Microsoft.Extensions.Logging": "10.0.1",
"Microsoft.VisualStudio.SolutionPersistence": "1.0.52",
"System.Composition": "10.0.1"
}
},
"Microsoft.NET.ILLink.Tasks": {
"type": "Direct",
"requested": "[11.0.0-rc.3.26522.148, )",
"resolved": "11.0.0-rc.3.26522.148",
"contentHash": "SWnTMx96mhBr9LCOySJg1ETlEFFHVsPGdVT02JnYhtqk1+Vke1J7RU3VkKwEiErBr4FJ42Uu4k7GdOtkRuvs/Q=="
},
"Humanizer.Core": {
"type": "Transitive",
"resolved": "2.14.1",
"contentHash": "lQKvtaTDOXnoVJ20ibTuSIOf2i0uO0MPbDhd1jm238I+U/2ZnRENj0cktKZhtchBMtCUSRQ5v4xBCUbKNmyVMw=="
},
"Microsoft.Build.Framework": {
"type": "Transitive",
"resolved": "17.11.48",
"contentHash": "C3WIMt2wBl4++NX3jSEpTq5KXBhvAV154R4JrYHkfy9JSBcXWiL0mkgpspk5xSdOj+fS/uz7zluIy6bMM1fkkQ=="
},
"Microsoft.CodeAnalysis.Analyzers": {
"type": "Transitive",
"resolved": "5.9.0-1.26328.17",
"contentHash": "HP9NNk8ZjOSI2hgOyXnQg+kv7/X837Vr2nAlXiGAtqtYnYKjRRa1UmQFr8KFs5ynGYKqfbb8zB9APoWjiAGdMg=="
},
"Microsoft.CodeAnalysis.Common": {
"type": "Transitive",
"resolved": "5.9.0",
"contentHash": "IYaIaUWdIx539AReKZOBEqTskFusZfCh/wFSPilDvCn5Say8MegLw2LONcSIcVy+v3Gzv53qYBspgvBGSErfbQ==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17"
}
},
"Microsoft.CodeAnalysis.CSharp": {
"type": "Transitive",
"resolved": "5.9.0",
"contentHash": "7JGDA0UT1+h7k9ZcA3rF4eFC8+QPq1xyYaXxag4p8r/zzPurEJxvdi7aM+MRL/SfP7XADXpWF/pl/eUYXOq/ww==",
"dependencies": {
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17",
"Microsoft.CodeAnalysis.Common": "[5.9.0]"
}
},
"Microsoft.CodeAnalysis.Workspaces.Common": {
"type": "Transitive",
"resolved": "5.9.0",
"contentHash": "1A6jz50NG4nOEW8tX5+h+MyHqjWL0mPGwrUdwu+OlTfyknLo0GfxSqj4zEks8uVUdHdo9v8Ir9dHxACf8iYNEA==",
"dependencies": {
"Humanizer.Core": "2.14.1",
"Microsoft.CodeAnalysis.Analyzers": "5.9.0-1.26328.17",
"Microsoft.CodeAnalysis.Common": "[5.9.0]",
"System.Composition": "10.0.1"
}
},
"Microsoft.Extensions.DependencyInjection": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "zerXV0GAR9LCSXoSIApbWn+Dq1/T+6vbXMHGduq1LoVQRHT0BXsGQEau0jeLUBUcsoF/NaUT8ADPu8b+eNcIyg=="
},
"Microsoft.Extensions.Logging": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "9ItMpMLFZFJFqCuHLLbR3LiA4ahA8dMtYuXpXl2YamSDWZhYS9BruPprkftY0tYi2bQ0slNrixdFm+4kpz1g5w==",
"dependencies": {
"Microsoft.Extensions.DependencyInjection": "10.0.1"
}
},
"Microsoft.VisualStudio.SolutionPersistence": {
"type": "Transitive",
"resolved": "1.0.52",
"contentHash": "oNv2JtYXhpdJrX63nibx1JT3uCESOBQ1LAk7Dtz/sr0+laW0KRM6eKp4CZ3MHDR2siIkKsY8MmUkeP5DKkQQ5w=="
},
"System.Composition": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "DJkqaWQfho/ReTzKcZD3zJJ6K4GcS154k+T0UCPMBNIOZ2U/lNpyiiWZ6Etw0onWyTH1K+yhICsdmwA5xy2aPQ==",
"dependencies": {
"System.Composition.AttributedModel": "10.0.1",
"System.Composition.Convention": "10.0.1",
"System.Composition.Hosting": "10.0.1",
"System.Composition.Runtime": "10.0.1",
"System.Composition.TypedParts": "10.0.1"
}
},
"System.Composition.AttributedModel": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "mRxYvpCVPAeuLEk0c0kxWJVjbW1/HUoxCgYotOj9eDeQiYcTDOMdCQApsTrHYMN3pHBA8WoF00KGolG632Etaw=="
},
"System.Composition.Convention": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "dYynUByfVBzYDheNPGxS8UN8AvG/4tXf/coSs1odHOyoh4etv1kad/FrLWLMq4f8NO49NV20Xu+0/y613woTUA==",
"dependencies": {
"System.Composition.AttributedModel": "10.0.1"
}
},
"System.Composition.Hosting": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "4UGmyBdKWEN1nkqspJlji/nV7XIVm6KGlOC2So0mtM/gKvaNgLz+tUkcbY+6Zpr7dr6ohX1S5yl0RLID5otRHw==",
"dependencies": {
"System.Composition.Runtime": "10.0.1"
}
},
"System.Composition.Runtime": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "TVfys1gnUIhmXuYfFzyez0fOkDyELe9UwlxYeVlq6FmqmWmt1ouF0OQJ+6ozkHbkaop7uBUaXw7Qb+/o0m+nMg=="
},
"System.Composition.TypedParts": {
"type": "Transitive",
"resolved": "10.0.1",
"contentHash": "koSfjkdQZfgQr3SyiSIBboDn+GiR0vZ3x9Uek9FJbXK0w5AiATV8KrnMEP8B8OAlO+Y3zQf0CPCNzwH+VIYDKg==",
"dependencies": {
"System.Composition.AttributedModel": "10.0.1",
"System.Composition.Hosting": "10.0.1",
"System.Composition.Runtime": "10.0.1"
}
}
}
}