public DependencyGraph AnalyzeSolution(string solution, string framework = null) { var analyzerManager = new AnalyzerManager(solution, new AnalyzerManagerOptions { LoggerFactory = _loggerFactory }); var solutionNode = new SolutionReferenceNode(solution); var builder = new DependencyGraph.Builder(solutionNode); foreach (var project in analyzerManager.Projects.Where(p => p.Value.ProjectInSolution.ProjectType == SolutionProjectType.KnownToBeMSBuildFormat)) { builder = CreateBuilder(project.Value, project.Key, builder, framework); } return(builder.Build()); }
public DependencyGraph Analyze(string packageId, string version, string framework) { var package = new PackageIdentity(packageId, NuGetVersion.Parse(version)); var settings = Settings.LoadDefaultSettings(root: null, configFileName: null, machineWideSettings: null); var sourceRepositoryProvider = new SourceRepositoryProvider(settings, Repository.Provider.GetCoreV3()); var nuGetFramework = NuGetFramework.ParseFolder(framework); var nugetLogger = _logger.AsNuGetLogger(); using (var cacheContext = new SourceCacheContext()) { var repositories = sourceRepositoryProvider.GetRepositories(); var resolvedPackages = new ConcurrentDictionary <PackageIdentity, SourcePackageDependencyInfo>(PackageIdentityComparer.Default); ResolvePackage(package, nuGetFramework, cacheContext, nugetLogger, repositories, resolvedPackages).Wait(); var availablePackages = new HashSet <SourcePackageDependencyInfo>(resolvedPackages.Values); var resolverContext = new PackageResolverContext( DependencyBehavior.Lowest, new[] { packageId }, Enumerable.Empty <string>(), Enumerable.Empty <PackageReference>(), Enumerable.Empty <PackageIdentity>(), availablePackages, sourceRepositoryProvider.GetRepositories().Select(s => s.PackageSource), nugetLogger); var resolver = new PackageResolver(); var prunedPackages = resolver.Resolve(resolverContext, CancellationToken.None) .Select(x => resolvedPackages[x]); var rootNode = new PackageReferenceNode(package.Id, package.Version.ToString()); var packageNodes = new Dictionary <string, PackageReferenceNode>(StringComparer.OrdinalIgnoreCase); var builder = new DependencyGraph.Builder(rootNode); foreach (var target in prunedPackages) { var downloadResource = target.Source.GetResource <DownloadResource>(); var downloadResult = downloadResource.GetDownloadResourceResultAsync(new PackageIdentity(target.Id, target.Version), new PackageDownloadContext(cacheContext), SettingsUtility.GetGlobalPackagesFolder(settings), nugetLogger, CancellationToken.None).Result; var libItems = downloadResult.PackageReader.GetLibItems(); var reducer = new FrameworkReducer(); var nearest = reducer.GetNearest(nuGetFramework, libItems.Select(x => x.TargetFramework)); var assemblyReferences = libItems .Where(x => x.TargetFramework.Equals(nearest)) .SelectMany(x => x.Items) .Where(x => Path.GetExtension(x).Equals(".dll", StringComparison.OrdinalIgnoreCase)) .Select(x => new AssemblyReferenceNode(Path.GetFileName(x))); var frameworkItems = downloadResult.PackageReader.GetFrameworkItems(); nearest = reducer.GetNearest(nuGetFramework, frameworkItems.Select(x => x.TargetFramework)); assemblyReferences = assemblyReferences.Concat(frameworkItems .Where(x => x.TargetFramework.Equals(nearest)) .SelectMany(x => x.Items) .Select(x => new AssemblyReferenceNode(x))); var packageReferenceNode = new PackageReferenceNode(target.Id, target.Version.ToString()); builder.WithNode(packageReferenceNode); builder.WithNodes(assemblyReferences); builder.WithEdges(assemblyReferences.Select(x => new Edge(packageReferenceNode, x))); packageNodes.Add(target.Id, packageReferenceNode); } foreach (var target in prunedPackages) { var packageReferenceNode = packageNodes[target.Id]; builder.WithEdges(target.Dependencies.Select(x => new Edge(packageReferenceNode, packageNodes[x.Id], x.VersionRange.ToString()))); } return(builder.Build()); } }
public DependencyGraph Analyze(string projectPath, string framework = null) { if (string.IsNullOrWhiteSpace(projectPath)) { throw new ArgumentException(nameof(projectPath)); } if (!File.Exists(projectPath)) { throw new ArgumentException("Project path does not exist.", nameof(projectPath)); } var analyzerManager = new AnalyzerManager(new AnalyzerManagerOptions { LoggerFactory = _loggerFactory }); var projectAnalyzer = analyzerManager.GetProject(projectPath); var analyzeResults = string.IsNullOrEmpty(framework) ? projectAnalyzer.Build() : projectAnalyzer.Build(framework); var analyzerResult = string.IsNullOrEmpty(framework) ? analyzeResults.FirstOrDefault() : analyzeResults[framework]; if (analyzerResult == null) { // Todo: Something went wrong, log and return better exception. throw new InvalidOperationException("Unable to load project."); } if (!analyzerResult.IsNetSdkProject()) { // Todo: Support "legacy" projects in the future. throw new InvalidOperationException("Unable to load project."); } var projectAssetsFilePath = analyzerResult.GetProjectAssetsFilePath(); if (!File.Exists(projectAssetsFilePath)) { // Todo: Make sure this exists in future throw new InvalidOperationException($"{projectAssetsFilePath} not found. Please run 'dotnet restore'"); } var lockFile = new LockFileFormat().Read(projectAssetsFilePath); var targetFramework = analyzerResult.GetTargetFramework(); var libraries = lockFile.Targets.Single(x => x.TargetFramework == targetFramework) .Libraries.Where(x => x.IsPackage()).ToList(); var projectNode = new ProjectReferenceNode(projectPath); var builder = new DependencyGraph.Builder(projectNode); var libraryNodes = new Dictionary <string, PackageReferenceNode>(StringComparer.OrdinalIgnoreCase); foreach (var library in libraries) { var libraryNode = library.ToNode(); builder.WithNode(libraryNode); libraryNodes.Add(libraryNode.PackageId, libraryNode); if (library.FrameworkAssemblies.Count > 0) { var assemblyNodes = library.FrameworkAssemblies .Select(x => new AssemblyReferenceNode($"{x}.dll")); builder.WithNodes(assemblyNodes); builder.WithEdges(assemblyNodes .Select(x => new Edge(libraryNode, x))); } if (library.RuntimeAssemblies.Count > 0) { var assemblyNodes = library.RuntimeAssemblies .Select(x => new AssemblyReferenceNode(Path.GetFileName(x.Path))) .Where(x => x.Id != "_._"); if (assemblyNodes.Any()) { builder.WithNodes(assemblyNodes); builder.WithEdges(assemblyNodes .Select(x => new Edge(libraryNode, x))); } } //if (library.CompileTimeAssemblies.Count > 0) //{ // var assemblyNodes = library.CompileTimeAssemblies // .Select(x => new AssemblyReferenceNode(Path.GetFileName(x.Path))); // builder.WithNodes(assemblyNodes); // builder.WithEdges(assemblyNodes // .Select(x => new Edge(libraryNode, x))); //} } foreach (var library in libraries) { var libraryNode = library.ToNode(); if (library.Dependencies.Count > 0) { builder.WithEdges(library.Dependencies .Select(x => new Edge(libraryNode, libraryNodes[x.Id], x.VersionRange.ToString()))); } } builder.WithEdges(analyzerResult.GetItems("PackageReference") .Select(x => new Edge(projectNode, libraryNodes[x.ItemSpec], x.Metadata["Version"]))); var references = analyzerResult.References//GetItems("Reference") .Select(x => new AssemblyReferenceNode(Path.GetFileName(x))); builder.WithNodes(references); builder.WithEdges(references.Select(x => new Edge(projectNode, x))); return(builder.Build()); }
private DependencyGraph.Builder CreateBuilder(IProjectAnalyzer projectAnalyzer, string projectPath, DependencyGraph.Builder builder = null, string framework = null) { var analyzeResults = string.IsNullOrEmpty(framework) ? projectAnalyzer.Build() : projectAnalyzer.Build(framework); var analyzerResult = string.IsNullOrEmpty(framework) ? analyzeResults.FirstOrDefault() : analyzeResults[framework]; if (analyzerResult == null) { // Todo: Something went wrong, log and return better exception. throw new InvalidOperationException("Unable to load project."); } var projectNode = new ProjectReferenceNode(projectPath); if (builder == null) { builder = new DependencyGraph.Builder(projectNode); } else { builder.WithNode(projectNode); builder.WithEdge(new Edge(builder.Root, projectNode)); } var projectAssetsFilePath = analyzerResult.GetProjectAssetsFilePath(); if (!File.Exists(projectAssetsFilePath)) { if (analyzerResult.IsNetSdkProject()) { // a new project doesn't have an asset file throw new InvalidOperationException($"{projectAssetsFilePath} not found. Please run 'dotnet restore'"); } // Old csproj var oldStylePackageReferences = analyzerResult.GetItems("Reference").Where(x => x.ItemSpec.Contains("Version=")); foreach (var reference in oldStylePackageReferences) { var split = reference.ItemSpec.Split(','); var version = split.Single(s => s.Contains("Version="))?.Split('=')[1]; var name = reference.ItemSpec.Split(',')[0]; var node = new PackageReferenceNode(name, version); builder.WithNode(node); builder.WithEdge(new Edge(projectNode, node, version)); } } else { // New csproj var lockFile = new LockFileFormat().Read(projectAssetsFilePath); var targetFramework = analyzerResult.GetTargetFramework(); var runtimeIdentifier = analyzerResult.GetRuntimeIdentifier(); var libraries = lockFile.Targets.Single( x => x.TargetFramework == targetFramework && x.RuntimeIdentifier == runtimeIdentifier) .Libraries.Where(x => x.IsPackage()).ToList(); var libraryNodes = new Dictionary <string, PackageReferenceNode>(StringComparer.OrdinalIgnoreCase); foreach (var library in libraries) { var libraryNode = library.ToNode(); builder.WithNode(libraryNode); // Overwrite any previous additions that may have been added by the loop below. libraryNodes[libraryNode.PackageId] = libraryNode; // Not all dependencies are necessarily included in the list of libraries // for the current target framework and runtime identifier. Add these to libraryNodes // so we can still record these dependencies. foreach (var dependency in library.Dependencies) { // Add min version in version range if this dependency doesn't exist libraryNodes.TryAdd( dependency.Id, new PackageReferenceNode(dependency.Id, dependency.VersionRange.MinVersion.ToString())); } if (library.FrameworkAssemblies.Count > 0) { var assemblyNodes = library.FrameworkAssemblies .Select(x => new AssemblyReferenceNode($"{x}.dll")); builder.WithNodes(assemblyNodes); builder.WithEdges(assemblyNodes .Select(x => new Edge(libraryNode, x))); } if (library.RuntimeAssemblies.Count > 0) { var assemblyNodes = library.RuntimeAssemblies .Select(x => new AssemblyReferenceNode(Path.GetFileName(x.Path))) .Where(x => x.Id != "_._"); if (assemblyNodes.Any()) { builder.WithNodes(assemblyNodes); builder.WithEdges(assemblyNodes .Select(x => new Edge(libraryNode, x))); } } //if (library.CompileTimeAssemblies.Count > 0) //{ // var assemblyNodes = library.CompileTimeAssemblies // .Select(x => new AssemblyReferenceNode(Path.GetFileName(x.Path))); // builder.WithNodes(assemblyNodes); // builder.WithEdges(assemblyNodes // .Select(x => new Edge(libraryNode, x))); //} } foreach (var library in libraries) { var libraryNode = library.ToNode(); if (library.Dependencies.Count > 0) { builder.WithEdges(library.Dependencies .Select(x => new Edge(libraryNode, libraryNodes[x.Id], x.VersionRange.ToString()))); } } // Ignore unversioned references like implicit SDK packages builder.WithEdges(analyzerResult.GetItems("PackageReference") .Where(x => x.Metadata.ContainsKey("Version")) .Select(x => new Edge(projectNode, libraryNodes[x.ItemSpec], x.Metadata["Version"]))); } var references = analyzerResult.References.Select(x => new AssemblyReferenceNode(Path.GetFileName(x))); builder.WithNodes(references); builder.WithEdges(references.Select(x => new Edge(projectNode, x))); return(builder); }